UNPKG

shadow-function

Version:

ioing lib - shadow Function, worker Function

1,250 lines (1,237 loc) 55.1 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var windowOwnPropertyNames = [ 'Object', 'Function', 'Array', 'Number', 'parseFloat', 'parseInt', 'Infinity', 'NaN', 'undefined', 'Boolean', 'String', 'Symbol', 'Date', 'Promise', 'RegExp', 'Error', 'EvalError', 'RangeError', 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError', 'JSON', 'Math', 'console', 'Intl', 'ArrayBuffer', 'Uint8Array', 'Int8Array', 'Uint16Array', 'Int16Array', 'Uint32Array', 'Int32Array', 'Float32Array', 'Float64Array', 'Uint8ClampedArray', 'BigUint64Array', 'BigInt64Array', 'DataView', 'Map', 'BigInt', 'Set', 'WeakMap', 'WeakSet', 'Proxy', 'Reflect', 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape', 'unescape', 'eval', 'isFinite', 'isNaN', 'TreeWalker', 'SVGAElement', 'Range', 'NodeList', 'NodeIterator', 'NodeFilter', 'Node', 'Element', 'HTMLElement', 'document', 'innerheight', 'innerwidth', 'outerheight', 'outerwidth', 'pageXOffset', 'pageYOffset', 'addEventListener', 'removeEventListener', 'dispatchEvent', 'Screen', 'alert', 'clearInterval', 'clearTimeout', 'valueOf', 'confirm', 'scrollTo', 'setInterval', 'setTimeout', 'toString', 'Float32Array', 'Proxy', 'EventTarget', 'hasOwnProperty', 'isPrototypeOf', 'toLocaleString', 'propertyIsEnumerable', '__proto__', '__defineGetter__', '__lookupGetter__', '__defineSetter__', '__lookupSetter__' ]; var Sandbox = /** @class */ (function () { function Sandbox(white, properties, setting) { if (white === void 0) { white = false; } if (properties === void 0) { properties = ['*']; } if (setting === void 0) { setting = 'allow-scripts allow-same-origin'; } this.windowOwnPropertyNames = windowOwnPropertyNames; var sandbox = this.sandbox = document.createElement('iframe'); sandbox.src = 'about:blank'; sandbox.style.display = 'none'; this.windowOwnPropertyNames = this.windowOwnPropertyNames.concat(properties); this.white = white; this.set(setting); this.enter(); this.shadow(); if (!white) this.exit(); return this; } Sandbox.getWindowOwnPropertyNames = function () { return windowOwnPropertyNames; }; Sandbox.debugger = function (isee, model) { if (model === void 0) { model = { 'safe-context': 'safe' }; } var msg = 'I know the danger!'; if (isee === msg) { this.prototype['open debugger'] = true; if (model['safe-context'] === 'unsafe') { this.prototype['unsafe-context'] = true; } else { console.warn("%c Sandbox: Opening the 'debugger' will result in a risk of losing security!", 'font-size: 32px; color: red'); } } else { console.log("Sandbox: Opening 'debugger' input '" + msg + "'"); } }; Sandbox.prototype.shadow = function () { var contentWindow = this.sandbox.contentWindow; var contentDocument = this.sandbox.contentDocument; this.window = contentWindow; this.content = this.document = contentDocument; if (this.white) return this; var globalProperty = this.getProtoProperty(this.window); var ShadowObject = this.window.Object; var allowAllProperty = ~this.windowOwnPropertyNames.indexOf('*'); this.shadowWindow = new contentWindow.Object(); var _loop_1 = function (k) { if (this_1.window[k] + '' !== '[object Window]' && (allowAllProperty || ~this_1.windowOwnPropertyNames.indexOf(k))) { this_1.shadowWindow[k] = this_1.window[k]; } else { try { ShadowObject.defineProperty(this_1.shadowWindow, k, { configurable: true, enumerable: true, writable: true, get: function () { console.error("Sandbox Error: Unauthorized use of window['" + k + "']."); return null; } }); this_1.delProtoProperty(this_1.window, k); } catch (e) { // } } }; var this_1 = this; for (var _i = 0, globalProperty_1 = globalProperty; _i < globalProperty_1.length; _i++) { var k = globalProperty_1[_i]; _loop_1(k); } this.shadowWindow.shadowWindow = this.shadowWindow; this.shadowWindow.window = this.shadowWindow; return this; }; Sandbox.prototype.getProtoProperty = function (object) { var propertyNames = Object.getOwnPropertyNames(object); if (object['__proto__']) return propertyNames.concat(this.getProtoProperty(object['__proto__'])); return propertyNames; }; Sandbox.prototype.delProtoProperty = function (object, name) { if (!object) return false; if (object['__proto__']) { if (object['__proto__'].hasOwnProperty(name)) { return delete object['__proto__'][name]; } else { return this.delProtoProperty(object['__proto__'], name); } } else { return delete object[name]; } }; Sandbox.prototype.set = function (allow) { this.sandbox.setAttribute('sandbox', allow); }; Sandbox.prototype.reset = function (allow) { this.exit(); this.set(allow); this.enter(); this.shadow(); return this; }; Sandbox.prototype.open = function () { this.content.open(); return this; }; Sandbox.prototype.write = function (context) { if (context === void 0) { context = '<head><meta charset="utf-8"></head>'; } this.content.write(context); return this; }; Sandbox.prototype.close = function () { this.content.close(); return this; }; Sandbox.prototype.enter = function () { var documentElement = document.documentElement; documentElement.appendChild(this.sandbox); }; Sandbox.prototype.exit = function () { if (this['open debugger']) return; var parentNode = this.sandbox.parentNode; parentNode && parentNode.removeChild(this.sandbox); }; return Sandbox; }()); var getObjectType = function (object) { var objectStr = Object.prototype.toString.call(object); var objectType = (/\s*\[(\w+) (\w+)\]\s*/.exec(objectStr) || []); switch (objectType[1]) { case 'object': return objectType[2]; case 'native': return 'native'; } return 'unknow'; }; var allowProtoProperties = { Node: [ 'nodeName', 'nodeType', 'textContent' ], Element: [ 'style', 'onblur', 'onfocus', 'onscroll', 'offsetWidth', 'offsetHeight', 'clientWidth', 'clientHeight', 'innerText', 'setAttribute', 'removeAttribute', 'createTextNode', 'addEventListener', 'getElementsByTagName' ], HTMLElement: [], HTMLBodyElement: [], HTMLDivElement: [], HTMLUListElement: [], HTMLLIElement: [], HTMLVideoElement: [], HTMLAudioElement: [], HTMLSelectElement: [], HTMLOptionElement: [], HTMLInputElement: [], HTMLSpanElement: [], HTMLDListElement: [], HTMLFontElement: [], HTMLHeadingElement: [], HTMLParagraphElement: [], HTMLDocument: [ 'documentElement', 'body' ], Navigator: [ 'appCodeName', 'appName', 'appVersion', 'language', 'languages', 'maxTouchPoints', 'onLine', 'platform', 'product', 'productSub', 'userAgent', 'vendor', 'vendorSub' ], UserActivation: [ 'hasBeenActive', 'isActive' ], Promise: [ 'then', 'catch', 'resolve' ], Touch: [ 'clientX', 'clientY', 'force', 'identifier', 'pageX', 'pageY', 'radiusX', 'radiusY', 'rotationAngle', 'screenX', 'screenY', 'target' ], TouchEvent: [ 'altKey', 'bubbles', 'cancelBubble', 'cancelable', 'changedTouches', 'composed', 'ctrlKey', 'currentTarget', 'defaultPrevented', 'detail', 'eventPhase', 'metaKey', 'returnValue', 'shiftKey', 'sourceCapabilities', 'targetTouches', 'timeStamp', 'touches', 'type', 'which' ], MouseEvent: [ 'altKey', 'bubbles', 'button', 'buttons', 'cancelBubble', 'cancelable', 'clientX', 'clientY', 'composed', 'ctrlKey', 'defaultPrevented', 'detail', 'eventPhase', 'fromElement', 'getModifierState', 'initMouseEvent', 'layerX', 'layerY', 'metaKey', 'movementX', 'movementY', 'offsetX', 'offsetY', 'pageX', 'pageY', 'relatedTarget', 'returnValue', 'screenX', 'screenY', 'shiftKey', 'sourceCapabilities', 'timeStamp', 'type', 'which', 'x', 'y' ] }; // ShadowFunction var ShadowFunction = /** @class */ (function () { function ShadowFunction() { var _this = this; this.sandbox = new Sandbox(false, this['allow properties'] || ['*']); this.shadowWindow = this.sandbox.shadowWindow; this.ShadowFunction = this.shadowWindow.Function; this.shadowHasOwnProperty = this.shadowWindow.Object.hasOwnProperty; this.ShadowObject = this.shadowWindow.Object; this.ShadowProxy = this.shadowWindow.Proxy; this.allowProtoProperties = allowProtoProperties; this.run = function () { return null; }; this.tracker = function (e) { if (typeof (e.name) === 'symbol' || !isNaN(Number(e.name))) return 'no'; switch (e.name) { case 'length': case '__proto__': break; default: return _this.log(e); } return 'no'; }; this.freezeShadowProto(this.shadowWindow); } ShadowFunction.prototype.log = function (e) { return console.log('Event Log:', e); }; ShadowFunction.debugger = function (isee, model) { if (model === void 0) { model = { 'no-Proxy': false }; } var msg = 'I know the danger!'; if (isee === msg) { this.prototype['open debugger'] = true; if (model['no-Proxy']) { this.prototype['open debugger: no-Proxy'] = true; } if (Sandbox.prototype['unsafe-context'] !== true) { console.warn("%c ShadowFunction: Opening the 'debugger' will result in a risk of losing security!", 'font-size: 32px; color: red'); } } else { console.log("ShadowFunction: Opening 'debugger' input '" + msg + "'"); } }; ShadowFunction.assignContextProperties = function (names) { if (names === void 0) { names = ['*']; } this.prototype['allow properties'] = names; }; ShadowFunction.prototype.setAllowProtoProperties = function (allowProperties) { Object.assign(this.allowProtoProperties, allowProperties); return this.preShadowFunction.bind(this); }; ShadowFunction.prototype.freezeShadowProto = function (object) { var Object = this.ShadowObject; var propNames = Object.getOwnPropertyNames(object); // Freeze properties before freezing self for (var _i = 0, propNames_1 = propNames; _i < propNames_1.length; _i++) { var name_1 = propNames_1[_i]; var value = object[name_1]; if (!value) break; if (!(Object.getOwnPropertyDescriptor(object, name_1) || {}).writable) break; typeof value === 'object' && this.freezeShadowProto(value); } if (!Object.isFrozen(object['prototype'])) Object.freeze(object['prototype']); }; ShadowFunction.prototype.getAllowProperties = function (object) { return this.getAllowProtoProperties(object).concat(Object.getOwnPropertyNames(object)); }; ShadowFunction.prototype.getAllowProtoProperties = function (object) { var propertyNames = this.allowProtoProperties[getObjectType(object)] || []; if (object['__proto__']) return propertyNames.concat(this.getAllowProtoProperties(object['__proto__'])); return propertyNames; }; ShadowFunction.prototype.isElementObject = function (value) { if (/HTML(\w+)?Element/.exec(getObjectType(value))) return true; return false; }; ShadowFunction.prototype.isFixedObject = function (value) { if (this.isElementObject(value)) return false; return typeof value === 'object'; }; ShadowFunction.prototype.safeGetter = function (origin, target, name) { if (this['open debugger'] && name === '...') { console.warn("ShadowFunction: Unsafe return in debug mode\uFF01"); return origin; } if (this.getAllowProperties(origin).indexOf(name) === -1) { this.tracker({ origin: origin, name: name, action: 'read' }); return target[name]; } if (origin[name] && !this.isFixedObject(origin[name]) && origin[name].hasOwnProperty === this.shadowHasOwnProperty) { return origin[name]; } return this.proxy(origin[name], origin); }; ShadowFunction.prototype.safeSetter = function (origin, target, name, value) { target[name] = this.proxy(value, target); if (this.tracker({ origin: origin, name: name, action: 'write', value: value }) === "allow set " + name) origin[name] = target[name]; return true; }; ShadowFunction.prototype.puppet = function (origin) { var _this = this; var Proxy = this.ShadowProxy; var propNames = Object.getOwnPropertyNames(origin); var puppet = new this.ShadowObject(); propNames.map(function (name) { if ((Object.getOwnPropertyDescriptor(puppet, name) || { writable: true }).writable) puppet[name] = '...'; }); return new Proxy(puppet, { get: function (target, name) { return _this.safeGetter(origin, target, name); }, set: function (target, name, value) { return _this.safeSetter(origin, target, name, value); } }); }; ShadowFunction.prototype.proxy = function (target, self) { if (self === void 0) { self = null; } if (this['open debugger: no-Proxy'] || !target) return target; switch (typeof (target)) { case 'string': case 'number': case 'boolean': case 'undefined': return target; case 'function': return this.safeReturnFunction(target, self); case 'object': return this.puppet(target); } return; }; ShadowFunction.prototype.safeReturnFunction = function (fn, origin) { var shadowFunction = new this.ShadowFunction('fn', 'origin', 'proxy', "\n return (function () {\n return function () {\n return proxy(fn.apply(origin, proxy(arguments)))\n }\n })()\n ")(fn, origin, this.proxy.bind(this)); var propNames = Object.getOwnPropertyNames(fn); for (var _i = 0, propNames_2 = propNames; _i < propNames_2.length; _i++) { var name_2 = propNames_2[_i]; if ((Object.getOwnPropertyDescriptor(fn, name_2) || { writable: true }).writable) { if (name_2 === 'prototype') continue; shadowFunction[name_2] = this.proxy({ 0: fn[name_2] })[0]; } } return shadowFunction; }; ShadowFunction.prototype.preShadowFunction = function (scriptStr) { this.shadowFunction = new this.ShadowFunction("\n (function () {\n with (arguments[0].window || {}) {\n with (arguments[0].context || {}) {\n (function () {" + scriptStr + "}).bind(Object.assign(arguments[0].window || {}, arguments[0].context || {}))()\n }\n }\n })(this)"); return this.runShadowFunction.bind(this); }; ShadowFunction.prototype.runShadowFunction = function (origin) { var target = this.proxy(origin); var shadowFunction = this.shadowFunction; shadowFunction.apply(this.ShadowObject.assign(new this.ShadowObject(), { window: this.shadowWindow, context: target })); return { run: this.preShadowFunction.bind(this), proxy: this.proxy.bind(this), sandbox: this.sandbox }; }; return ShadowFunction; }()); var shadowFunction = function (code, setting, log) { var sfnc = new ShadowFunction(); if (log) sfnc.log = log; if (setting) { sfnc.run = sfnc.setAllowProtoProperties(setting)(code); } else { switch (typeof (code)) { case 'object': sfnc.run = sfnc.setAllowProtoProperties(code); break; case 'string': sfnc.run = sfnc.preShadowFunction(code); break; default: throw new Error('ShadowFunction: Uncaught SyntaxError: Unexpected identifier.'); } } return sfnc.run; }; shadowFunction.debugger = ShadowFunction.debugger.bind(ShadowFunction); var DOCUMENT = document; var constructorId = 0; // ShadowDocument var ShadowDocument = /** @class */ (function () { function ShadowDocument(root, template, setting, log) { if (setting === void 0) { setting = [{}, {}]; } var _this = this; this.run = function () { return null; }; this.constructorId = 0; this.o = 0; this.allowTagName = { 'DIV': true, 'B': true, 'P': true, 'H1': true, 'H2': true, 'H3': true, 'H4': true, 'H5': true, 'DL': true, 'DT': true, 'DD': true, 'EM': true, 'HR': true, 'UL': true, 'LI': true, 'OL': true, 'TD': true, 'TH': true, 'TR': true, 'TT': true, 'NAV': true, 'SUP': true, 'SUB': true, 'SPAN': true, 'FONT': true, 'BR': true, 'STYLE': true, 'SMALL': true, 'LABEL': true, 'TABLE': true, 'TBODY': true, 'THEAD': true, 'TFOOT': true, 'BUTTON': true, 'FOOTER': true, 'HEADER': true, 'STRONG': true }; this.tracker = function (e) { if (typeof (_this.log) === 'function') { _this.log(e); } else { console.log('Event Log:', e); } }; this.getRealElement = function (element) { return _this.TREE[element['uuid']] || new Error("ShadowFunction: Cannot synchronously read compiled style. Async read after the rendering ends / or use '<HTMLElement>.oncomputed = () => { element.offsetTop }'\uFF01"); }; this.TREE = { 0: root.attachShadow ? root.attachShadow({ mode: 'open' }) : root }; this.SHADOWTREE = {}; Object.assign(this.allowTagName, setting[0] || setting); this.log = log; this.constructorId = constructorId++; this.shadowFunction = new shadowFunction(setting[1] || {}, undefined, log); this.shadowFunction = this.shadowFunction(this.injection())(this.empowerment()); this.sandbox = this.shadowFunction.sandbox; this.shadowWindow = this.sandbox.shadowWindow; this.shadowDocumentBody = this.shadowWindow.document.body; this.ShadowObject = this.shadowWindow.Object; this.ShadowNode = this.shadowWindow.Node; this.ShadowElement = this.shadowWindow.Element; this.shadowGetAttribute = this.ShadowElement['prototype'].getAttribute; this.setShadowObserver(); this.write(template); this.run = this.shadowFunction.run.bind(this); } ShadowDocument.prototype.empowerment = function () { var _this = this; return { getShadowElement: function (element) { return _this.getRealElement(element); }, getShadowElementProps: function (element, propsName) { return _this.getRealElement(element)[propsName]; }, getComputedStyle: function (element, pseudoElt) { if (pseudoElt === void 0) { pseudoElt = null; } return getComputedStyle(_this.getRealElement(element), pseudoElt); }, setShadowEventListener: function (listener, type, callback, opt) { var target = null; var eventName = 'on-shadow-' + type + '-' + _this.constructorId; switch (listener) { case '[object Window]': target = window; break; case '[object HTMLDocument]': target = document; break; case '[object HTMLBodyElement]': target = document.body; break; case '[object HTMLHtmlElement]': target = document.documentElement; break; } if (!target) return; if (!callback) return target.removeEventListener(type, target[eventName]); Object.defineProperty(target, eventName, { enumerable: false, configurable: true, writable: false, value: function (e) { callback.apply(callback, [_this.createShadowEventObject(e)]); } }); target.addEventListener(type, target[eventName], opt); } }; }; ShadowDocument.prototype.isElementObject = function (value) { if (/HTML(\w+)?Element/.exec(getObjectType(value))) return true; return false; }; ShadowDocument.prototype.createShadowEventObject = function (originEvent) { var target = {}; for (var key in originEvent) { var value = originEvent[key]; switch (typeof value) { case 'string': case 'number': case 'boolean': case 'undefined': target[key] = value; break; case 'function': target[key] = value.bind(originEvent); break; case 'object': switch (key) { case 'changedTouches': case 'sourceCapabilities': case 'targetTouches': case 'touches': target[key] = this.createShadowEventObject(value); break; case 'srcElement': case 'target': case 'toElement': if (this.isElementObject(value)) target[key] = this.SHADOWTREE[value.uuid]; break; default: if (!isNaN(Number(key))) { target[key] = this.createShadowEventObject(value); } else { target[key] = value; } break; } break; } } return target; }; ShadowDocument.prototype.injection = function () { return "\n window.addEventListener = EventTarget.prototype.addEventListener = function (type, callback, options) {\n var target = this\n var targetTypeName = Object.prototype.toString.call(target)\n if (!target['onShadowEventNames']) {\n Object.defineProperty(target, 'onShadowEventNames', {\n enumerable: false,\n configurable: true,\n writable: true,\n value: [type]\n })\n } else {\n target['onShadowEventNames'].push(type)\n }\n if (!target['onshadow' + type]) {\n Object.defineProperty(target, 'onshadow' + type, {\n enumerable: false,\n configurable: true,\n writable: true,\n value: {\n type: type,\n options: options,\n callback: [callback]\n }\n })\n setShadowEventListener(targetTypeName, type, function () {\n var args = arguments\n target['onshadow' + type].callback.map(function (fn) {\n fn.apply(target, args)\n })\n }, options)\n } else {\n target['onshadow' + type].callback.push(callback)\n }\n }\n window.removeEventListener = EventTarget.prototype.removeEventListener = function (type, callback, options) {\n var target = this\n var targetTypeName = Object.prototype.toString.call(target)\n var callbackIndex = this['onshadow' + type].callback.indexOf(callback)\n var eventNameIndex = this['onShadowEventNames'].indexOf(type)\n if (eventNameIndex !== -1) {\n this['onShadowEventNames'].splice(eventNameIndex, 1)\n }\n if (callbackIndex !== -1) {\n this['onshadow' + type].callback.splice(callbackIndex, 1)\n }\n if (this['onshadow' + type].callback.length === 0) {\n setShadowEventListener(targetTypeName, type)\n }\n }\n shadowWindow.Object.defineProperties(shadowWindow.HTMLElement.prototype, {\n 'offsetHeight': {\n get () {\n return getShadowElementProps(this, 'offsetHeight')\n }\n },\n 'offsetWidth': {\n get () {\n return getShadowElementProps(this, 'offsetWidth')\n }\n },\n 'offsetTop': {\n get () {\n return getShadowElementProps(this, 'offsetTop')\n }\n },\n 'offsetLeft': {\n get () {\n return getShadowElementProps(this, 'offsetLeft')\n }\n },\n 'offsetParent': {\n get () {\n return getShadowElementProps(this, 'offsetParent')\n }\n },\n 'ref': {\n get () {\n return getShadowElement(this)\n }\n }\n })\n "; }; ShadowDocument.prototype.setShadowObserver = function () { var _this = this; new MutationObserver(function (records) { var _loop_1 = function (record) { var target = record.target; switch (record.type) { case 'attributes': _this.setAttribute(record.attributeName, target); break; case 'characterData': _this.setCharacterData(target); break; case 'childList': Array.prototype.forEach.call(record.removedNodes, function (node) { _this.walker(_this.iterator(node), target, true); }); Array.prototype.forEach.call(record.addedNodes, function (node) { _this.walker(_this.iterator(node), target); }); break; } }; for (var _i = 0, records_1 = records; _i < records_1.length; _i++) { var record = records_1[_i]; _loop_1(record); } }).observe(this.shadowDocumentBody, { subtree: true, attributes: true, childList: true, characterData: true, attributeOldValue: true, characterDataOldValue: true }); }; ShadowDocument.prototype.write = function (template) { this.shadowDocumentBody.innerHTML = "<div>" + template + "</div>"; }; ShadowDocument.prototype.uuid = function (node, uuid) { uuid = parseInt(node.parentNode ? node.parentNode.uuid || 0 : 0, 10); uuid++; this.o++; uuid = uuid + '.' + this.o; if (!node.uuid) { this.ShadowObject.defineProperty(node, 'uuid', { configurable: false, enumerable: false, value: uuid }); this.SHADOWTREE[uuid] = node; } return uuid; }; ShadowDocument.prototype.iterator = function (nodes) { if (nodes.nextNode) return nodes; return DOCUMENT.createNodeIterator(nodes, NodeFilter.SHOW_ALL, null); }; ShadowDocument.prototype.walker = function (nodes, target, del) { if (del === void 0) { del = false; } var node = nodes.nextNode(); while (node) { this.uuid(node); switch (node.nodeType) { case Node.ELEMENT_NODE: if (del) { this.removeElement(node, target); } else { this.createElement(node, target); } break; case Node.TEXT_NODE: if (del) { this.removeTextNode(node, target); } else { this.createTextNode(node, target); } break; } node = nodes.nextNode(); if (!node) break; } }; ShadowDocument.prototype.getParentId = function (node, target) { return (node.parentNode ? node.parentNode['uuid'] : target['uuid']) || 0; }; ShadowDocument.prototype.createElement = function (node, target) { var uuid = node['uuid']; var name = this.ShadowNode['prototype'].cloneNode.call(node).nodeName; var puuid = this.getParentId(node, target); if (this.TREE[uuid]) return; switch (name) { case this.allowTagName[name] ? name : null: this.TREE[uuid] = DOCUMENT.createElement(name); this.TREE[uuid].uuid = uuid; break; default: this.tracker({ tagName: name, action: 'createElement' }); throw new Error("ShadowFunction: The tag name provided ('" + name + "') is not a valid name of whitelist."); } for (var i = 0; i < node.attributes.length; i++) { this.setAttribute(node.attributes[i].name, node); } node['completedState'] = 'complete'; this.TREE[puuid].appendChild(this.TREE[uuid]); this.createEvent(node); this.shadowFunction.run("\n typeof computed === 'function' && computed(el)\n ")({ el: this.TREE[uuid], computed: node['oncomputed'] }); }; ShadowDocument.prototype.removeElement = function (node, target) { var uuid = node['uuid']; var puuid = this.getParentId(node, target); if (this.TREE[puuid] && this.TREE[uuid]) { this.TREE[puuid].removeChild(this.TREE[uuid]); } delete this.TREE[uuid]; }; ShadowDocument.prototype.createTextNode = function (node, target) { var uuid = node['uuid']; var puuid = this.getParentId(node, target); var text = node.textContent || ''; if (this.TREE[uuid]) return; this.TREE[uuid] = DOCUMENT.createTextNode(text); this.TREE[uuid].uuid = uuid; if (this.TREE[puuid]) { this.TREE[puuid].appendChild(this.TREE[uuid]); } }; ShadowDocument.prototype.removeTextNode = function (node, target) { var uuid = node['uuid']; var puuid = this.getParentId(node, target); if (this.TREE[puuid] && this.TREE[uuid]) { this.TREE[puuid].removeChild(this.TREE[uuid]); } delete this.TREE[uuid]; }; ShadowDocument.prototype.createEvent = function (node) { var _this = this; var onEvent = node['onShadowEventNames']; if (!onEvent) return; onEvent.map(function (type) { var shadowEvent = node['onshadow' + type]; if (shadowEvent) { _this.TREE[node['uuid']].addEventListener(shadowEvent.type, function (event) { event = _this.createShadowEventObject(event); _this.shadowFunction.run("\n for (let i = 0; i < events.length; i++) {\n typeof(events[i]) === 'function' && events[i].apply(node, args)\n }\n ")({ events: shadowEvent.callback.map(function (fn) { return fn.bind(node); }), node: node, args: [event] }); }, shadowEvent.options); } }); }; ShadowDocument.prototype.setAttribute = function (name, node) { var whiteNode = this.TREE[node['uuid']]; var shadowNode = this.ShadowNode['prototype'].cloneNode.call(node); var tagName = shadowNode.tagName; var allow = this.allowTagName[tagName]; var value = this.shadowGetAttribute.call(shadowNode, name); var safeAttr = false; if (!whiteNode) return; switch (name) { case 'id': case 'name': case 'style': case 'class': case 'width': case 'height': safeAttr = true; break; default: if (typeof (allow) === 'function' && allow(name, value)) { safeAttr = true; } else { this.tracker({ tagName: tagName, attributeName: name, action: 'setAttribute', value: value }); throw new Error("ShadowFunction: The attribute name provided ('" + name + " in <" + tagName.toLocaleLowerCase() + " />') is not a valid name of whitelist."); } break; } if (whiteNode && safeAttr) whiteNode.setAttribute(name, value); }; ShadowDocument.prototype.setCharacterData = function (node) { var char = this.TREE[node.uuid]; if (char) char.textContent = node.textContent; }; return ShadowDocument; }()); var shadowDocument = function (root, template, setting, log) { if (setting === void 0) { setting = [{}, {}]; } return new ShadowDocument(root, template, setting, log).run; }; var BlackDocument = /** @class */ (function () { function BlackDocument(template, root, csp, type) { if (root === void 0) { root = document.body; } if (csp === void 0) { csp = "default-src 'self';"; } this.root = root; this.create(template, csp, type); // @ts-ignore return this.run.bind(this); } BlackDocument.prototype.hashSource = function () { return (new Array(8 + Math.round(Math.random() * 8))).join(',').split(',').map(function () { return String.fromCharCode(97 + Math.round(Math.random() * 25)); }).join(''); }; BlackDocument.prototype.injectRequestParentAction = function (csp) { var _this = this; var hash = this.hashSource(); window.addEventListener('message', function (data) { var result = data.data || {}; var method = result.method; var params = result.params; var postToSandbox = function (data) { if (_this.sandbox.contentWindow) { _this.sandbox.contentWindow.postMessage({ data: data, key: method + ':' + JSON.stringify(params) }, '*'); } }; if (result.hash === hash) { var func = _this.methods[method]; var promise = void 0; if (typeof func === 'function') { promise = func(params); } else { promise = func; } if (promise instanceof Promise) { promise.then(postToSandbox); } else { postToSandbox(promise); } } }, false); return "\n <meta http-equiv=\"Content-Security-Policy\" content=\"" + csp + "\">\n <script>\n window.requestParentAction = function (method, params) {\n parent.postMessage({ method: method, params: params, hash: '" + hash + "' }, '" + location.origin + "')\n return new Promise(function (reslove, reject) {\n function callback (data) {\n if (data && data.data && data.data.data) {\n if (method + ':' + JSON.stringify(params) === data.data.key) {\n window.removeEventListener('message', callback)\n reslove(data.data.data)\n }\n } else {\n reject()\n }\n }\n window.addEventListener('message', callback)\n })\n }\n </script>\n "; }; BlackDocument.prototype.create = function (template, csp, type) { if (type === void 0) { type = 'fullscreen'; } var iframe = document.createElement('iframe'); iframe.csp = csp; iframe.src = URL.createObjectURL(new Blob([this.injectRequestParentAction(csp) + " ;\n " + template], { type: 'text/html' })); iframe.setAttribute('sandbox', 'allow-scripts'); if (type === 'fullscreen') iframe.setAttribute('style', "position: fixed; top: 0; right: 0; bottom: 0; left: 0; width: 100%; height: 100%"); this.sandbox = iframe; }; BlackDocument.prototype.run = function (methods) { this.methods = methods; this.root.appendChild(this.sandbox); }; return BlackDocument; }()); function freeze(object, deep, exclude) { if (deep === void 0) { deep = false; } if (exclude === void 0) { exclude = {}; } if (!object) return; exclude = getObjectType(exclude) === 'Object' ? exclude : {}; if (deep) { var propNames = Object.getOwnPropertyNames(object); // Freeze properties before freezing self for (var _i = 0, propNames_1 = propNames; _i < propNames_1.length; _i++) { var name_1 = propNames_1[_i]; var value = object[name_1]; var ignore = exclude[name_1]; if (!value) break; if (isFrozen(value)) break; if (ignore) break; freeze(value.prototype, true, exclude); freeze(value.__proto__, true, exclude); var descriptor = Object.getOwnPropertyDescriptor(object, name_1) || {}; if (!descriptor.writable) break; object[name_1] = value && typeof value === 'object' ? freeze(value, true) : value; } } return Object.freeze(object); } function isFrozen(obj) { return Object.isFrozen(obj); } var sandbox = new Sandbox(); var randPassword = function () { var shadowString = sandbox.shadowWindow.String; var shadowMath = sandbox.shadowWindow.Math; var shadowArray = sandbox.shadowWindow.Array; return (new shadowArray(8 + shadowMath.round(shadowMath.random() * 8))).join(',').split(',').map(function () { return shadowString['fromCharCode'](33 + shadowMath.round(shadowMath.random() * 89)); }).join(''); }; var Strongbox = /** @class */ (function () { function Strongbox(insurance, log) { var _this = this; this.password = randPassword(); this.tracker = function (e) { if (typeof (_this.log) === 'function') { _this.log(e); } else { console.log('Event Log:', e); } }; var that = this; var secretKey = this.password; // tracker log this.log = log; var _loop_1 = function (insured) { var object = insured[0]; var props = insured[1]; var value = object[props]; Object.defineProperty(object, props, { get: function () { that.password = secretKey = randPassword(); return function (password, setValue) { if (password === secretKey) { if (setValue) { value = setValue; } else { return value; } } else { var log_1 = { object: object, name: props, action: 'read' }; if (setValue) { log_1.value = setValue; log_1.action = 'write'; } that.tracker(log_1); return; } }; }, set: function () { return; }, enumerable: true, configurable: false }); freeze(object, true); }; for (var _i = 0, insurance_1 = insurance; _i < insurance_1.length; _i++) { var insured = insurance_1[_i]; _loop_1(insured); } return this; } Strongbox.prototype.lock = function () { windowOwnPropertyNames.forEach(function (key) { var type = typeof (window[key]); if (type === 'object' || type === 'function') { try { switch (key) { case 'window': break; default: freeze(window[key], true); break; } } catch (_e) { // } } }); }; return Strongbox; }()); var WorkerFunction = /** @class */ (function () { function WorkerFunction(code) { code = typeof (code) === 'string' ? code : typeof (code) === 'function' ? Object.toString.call(code) : ''; // code = `self.addEventListener('message', function (event) { ` + code + ` }, false)` return new Worker(URL.createObjectURL(new Blob([code], { type: 'text/javascript' }))); } return WorkerFunction; }()); var TryAgain = /** @class */ (function () { function TryAgain(task, options) { this.task = task; this.polls = options.polls || 2; this.timeout = options.timeout || 3000; this.timeoutId = null; } TryAgain.prototype.try = function () { var _this = this; if (this.polls <= 0) return false; this.timeoutId = setTimeout(function () { if (_this.polls-- > 0) _this.task() && _this.try(); }, this.timeout); }; TryAgain.prototype.stop = function () { clearTimeout(this.timeoutId); }; TryAgain.prototype.wait = function (time) { this.timeout = time; }; TryAgain.prototype.over = function () { this.stop(); this.polls = 0; }; return TryAgain; }()); var documentElement = document.documentElement; var clearUnsafe = "\n function clearUnsafe (proto) {\n var props = Object.getOwnPropertyNames(proto)\n props.map(function (key) {\n try {\n proto[key] = null\n delete proto[key]\n } catch (e) {}\n })\n }\n clearUnsafe(Document.prototype)\n clearUnsafe(Function.prototype)\n clearUnsafe(Object.prototype)\n clearUnsafe(HTMLElement.prototype)\n clearUnsafe(Element.prototype)\n clearUnsafe(Node.prototype)\n clearUnsafe(String.prototype)\n clearUnsafe(window)\n"; var getShadowModule = function (url, options) { if (options === void 0) { options = { receiver: '', timeout: 30000, dataType: 'module' }; } return new Promise(function (resolve, reject) { var dataType = options.dataType, receiver = options.receiver, timeout = options.timeout; var iframe; var tryObj; var timeoutId; timeout = timeout || 30000; // 异常尝试 tryObj = new TryAgain(send, { timeout: 3000, polls: 2 }); // abort function abort() { clearTimeout(timeoutId); window.removeEventListener('online', send, false); iframe.parentElement && documentElement.removeChild(iframe); } // over function over(type) { abort(); tryObj.try(); if (tryObj.polls === 0) { reject(type); } } function hashSource() { return (new Array(8 + Math.round(Math.random() * 8))).join(',').split(',').map(function () { return String.fromCharCode(97 + Math.round(Math.random() * 25)); }).join(''); } function send() { var hash = hashSource(); var script = document.createElement('script'); script.src = url; url = script.src; iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.csp = "script-src 'unsafe-inline' " + url.split(/\?|\#/)[0] + " 'nonce-" + hash + "'; " + (options.reportUrl ? 'report-uri ' + options.reportUrl : ''); iframe.src = URL.createObjectURL(new Blob(["\n <html>\n <head>\n <meta http-equiv=\"Content-Security-Policy\" content=\"" + iframe.csp + "\">\n <script id=" + hash + " nonce=" + hash + " src=\"" + url + "\" async></script>\n <script nonce=" + hash + ">\n (function () {\n var parent = window.parent\n var script = document.getElementById('" + hash + "')\n window['" + receiver + "'] = window['moduleExportsReceiver'] = function (data) {\n window['moduleExportsReceiver'] = function () {}\n parent['on" + hash + "'] ? parent['on" + hash + "']({ data: { response: data, src: '" + url + "', hash: '" + hash + "' } }) : parent.postMessage({ response: JSON.parse(JSON.stringify(data)), src: '" + url + "', hash: '" + hash + "' }, '" + location.origin + "')\n }\n script.o