UNPKG

cross-domain-safe-weakmap

Version:
240 lines (192 loc) 4.77 kB
import { isWindow, isWindowClosed } from 'cross-domain-utils/src'; import { hasNativeWeakMap } from './native'; import { noop, safeIndexOf } from './util'; export var CrossDomainSafeWeakMap = /*#__PURE__*/function () { // eslint-disable-next-line flowtype/no-mutable-array // eslint-disable-next-line flowtype/no-mutable-array function CrossDomainSafeWeakMap() { this.name = void 0; this.weakmap = void 0; this.keys = void 0; this.values = void 0; // eslint-disable-next-line no-bitwise this.name = "__weakmap_" + (Math.random() * 1e9 >>> 0) + "__"; if (hasNativeWeakMap()) { try { this.weakmap = new WeakMap(); } catch (err) {// pass } } this.keys = []; this.values = []; } var _proto = CrossDomainSafeWeakMap.prototype; _proto._cleanupClosedWindows = function _cleanupClosedWindows() { var weakmap = this.weakmap; var keys = this.keys; for (var i = 0; i < keys.length; i++) { var value = keys[i]; if (isWindow(value) && isWindowClosed(value)) { if (weakmap) { try { weakmap.delete(value); } catch (err) {// pass } } keys.splice(i, 1); this.values.splice(i, 1); i -= 1; } } }; _proto.isSafeToReadWrite = function isSafeToReadWrite(key) { if (isWindow(key)) { return false; } try { noop(key && key.self); noop(key && key[this.name]); } catch (err) { return false; } return true; }; _proto.set = function set(key, value) { if (!key) { throw new Error("WeakMap expected key"); } var weakmap = this.weakmap; if (weakmap) { try { weakmap.set(key, value); } catch (err) { delete this.weakmap; } } if (this.isSafeToReadWrite(key)) { try { var name = this.name; var entry = key[name]; if (entry && entry[0] === key) { entry[1] = value; } else { Object.defineProperty(key, name, { value: [key, value], writable: true }); } return; } catch (err) {// pass } } this._cleanupClosedWindows(); var keys = this.keys; var values = this.values; var index = safeIndexOf(keys, key); if (index === -1) { keys.push(key); values.push(value); } else { values[index] = value; } }; _proto.get = function get(key) { if (!key) { throw new Error("WeakMap expected key"); } var weakmap = this.weakmap; if (weakmap) { try { if (weakmap.has(key)) { return weakmap.get(key); } } catch (err) { delete this.weakmap; } } if (this.isSafeToReadWrite(key)) { try { var entry = key[this.name]; if (entry && entry[0] === key) { return entry[1]; } return; } catch (err) {// pass } } this._cleanupClosedWindows(); var keys = this.keys; var index = safeIndexOf(keys, key); if (index === -1) { return; } return this.values[index]; }; _proto.delete = function _delete(key) { if (!key) { throw new Error("WeakMap expected key"); } var weakmap = this.weakmap; if (weakmap) { try { weakmap.delete(key); } catch (err) { delete this.weakmap; } } if (this.isSafeToReadWrite(key)) { try { var entry = key[this.name]; if (entry && entry[0] === key) { entry[0] = entry[1] = undefined; } } catch (err) {// pass } } this._cleanupClosedWindows(); var keys = this.keys; var index = safeIndexOf(keys, key); if (index !== -1) { keys.splice(index, 1); this.values.splice(index, 1); } }; _proto.has = function has(key) { if (!key) { throw new Error("WeakMap expected key"); } var weakmap = this.weakmap; if (weakmap) { try { if (weakmap.has(key)) { return true; } } catch (err) { delete this.weakmap; } } if (this.isSafeToReadWrite(key)) { try { var entry = key[this.name]; if (entry && entry[0] === key) { return true; } return false; } catch (err) {// pass } } this._cleanupClosedWindows(); var index = safeIndexOf(this.keys, key); return index !== -1; }; _proto.getOrSet = function getOrSet(key, getter) { if (this.has(key)) { // $FlowFixMe return this.get(key); } var value = getter(); this.set(key, value); return value; }; return CrossDomainSafeWeakMap; }();