diff --git a/magic/contact/algebra.js b/magic/contact/algebra.js new file mode 100644 index 0000000..4077c7c --- /dev/null +++ b/magic/contact/algebra.js @@ -0,0 +1,1129 @@ +if (!self.__uv) { + __uvHook(self, self.__uv$config, self.__uv$config.bare); +}; + +async function __uvHook(window, config = {}, bare = '/outerspace/') { + if ('__uv' in window && window.__uv instanceof Ultraviolet) return false; + + if (window.document && !!window.window) { + window.document.querySelectorAll("script[__uv-script]").forEach(node => node.remove()) + }; + + const worker = !window.window; + const master = '__uv'; + const methodPrefix = '__uv$'; + const __uv = new Ultraviolet({ + ...config, + window, + }); + + if (typeof config.construct === 'function') { + config.construct(__uv, worker ? 'worker' : 'window'); + }; + + const { client } = __uv; + const { + HTMLMediaElement, + HTMLScriptElement, + HTMLAudioElement, + HTMLVideoElement, + HTMLInputElement, + HTMLEmbedElement, + HTMLTrackElement, + HTMLAnchorElement, + HTMLIFrameElement, + HTMLAreaElement, + HTMLLinkElement, + HTMLBaseElement, + HTMLFormElement, + HTMLImageElement, + HTMLSourceElement, + } = window; + + client.nativeMethods.defineProperty(window, '__uv', { + value: __uv, + enumerable: false, + }); + + + __uv.meta.origin = location.origin; + __uv.location = client.location.emulate( + (href) => { + if (href === 'about:srcdoc') return new URL(href); + if (href.startsWith('blob:')) href = href.slice('blob:'.length); + return new URL(__uv.sourceUrl(href)); + }, + (href) => { + return __uv.rewriteUrl(href); + }, + ); + + __uv.cookieStr = window.__uv$cookies || ''; + __uv.meta.url = __uv.location; + __uv.domain = __uv.meta.url.host; + __uv.blobUrls = new window.Map(); + __uv.referrer = ''; + __uv.cookies = []; + __uv.localStorageObj = {}; + __uv.sessionStorageObj = {}; + + try { + __uv.bare = new URL(bare, window.location.href); + } catch(e) { + __uv.bare = window.parent.__uv.bare; + }; + + if (__uv.location.href === 'about:srcdoc') { + __uv.meta = window.parent.__uv.meta; + }; + + if (window.EventTarget) { + __uv.addEventListener = window.EventTarget.prototype.addEventListener; + __uv.removeListener = window.EventTarget.prototype.removeListener; + __uv.dispatchEvent = window.EventTarget.prototype.dispatchEvent; + }; + + // Storage wrappers + client.nativeMethods.defineProperty(client.storage.storeProto, '__uv$storageObj', { + get() { + if (this === client.storage.sessionStorage) return __uv.sessionStorageObj; + if (this === client.storage.localStorage) return __uv.localStorageObj; + }, + enumerable: false, + }); + + if (window.localStorage) { + for (const key in window.localStorage) { + if (key.startsWith(methodPrefix + __uv.location.origin + '@')) { + __uv.localStorageObj[key.slice((methodPrefix + __uv.location.origin + '@').length)] = window.localStorage.getItem(key); + }; + }; + + __uv.lsWrap = client.storage.emulate(client.storage.localStorage, __uv.localStorageObj); + }; + + if (window.sessionStorage) { + for (const key in window.sessionStorage) { + if (key.startsWith(methodPrefix + __uv.location.origin + '@')) { + __uv.sessionStorageObj[key.slice((methodPrefix + __uv.location.origin + '@').length)] = window.sessionStorage.getItem(key); + }; + }; + + __uv.ssWrap = client.storage.emulate(client.storage.sessionStorage, __uv.sessionStorageObj); + }; + + + + let rawBase = window.document ? client.node.baseURI.get.call(window.document) : window.location.href; + let base = __uv.sourceUrl(rawBase); + + client.nativeMethods.defineProperty(__uv.meta, 'base', { + get() { + if (!window.document) return __uv.meta.url.href; + + if (client.node.baseURI.get.call(window.document) !== rawBase) { + rawBase = client.node.baseURI.get.call(window.document); + base = __uv.sourceUrl(rawBase); + }; + + return base; + }, + }); + + + __uv.methods = { + setSource: methodPrefix + 'setSource', + source: methodPrefix + 'source', + location: methodPrefix + 'location', + function: methodPrefix + 'function', + string: methodPrefix + 'string', + eval: methodPrefix + 'eval', + parent: methodPrefix + 'parent', + top: methodPrefix + 'top', + }; + + __uv.filterKeys = [ + master, + __uv.methods.setSource, + __uv.methods.source, + __uv.methods.location, + __uv.methods.function, + __uv.methods.string, + __uv.methods.eval, + __uv.methods.parent, + __uv.methods.top, + methodPrefix + 'protocol', + methodPrefix + 'storageObj', + methodPrefix + 'url', + methodPrefix + 'modifiedStyle', + methodPrefix + 'config', + methodPrefix + 'dispatched', + 'Ultraviolet', + '__uvHook', + ]; + + + client.on('wrap', (target, wrapped) => { + client.nativeMethods.defineProperty(wrapped, 'name', client.nativeMethods.getOwnPropertyDescriptor(target, 'name')); + client.nativeMethods.defineProperty(wrapped, 'length', client.nativeMethods.getOwnPropertyDescriptor(target, 'length')); + + client.nativeMethods.defineProperty(wrapped, __uv.methods.string, { + enumerable: false, + value: client.nativeMethods.fnToString.call(target), + }); + + client.nativeMethods.defineProperty(wrapped, __uv.methods.function, { + enumerable: false, + value: target, + }); + }); + + client.fetch.on('request', event => { + event.data.input = __uv.rewriteUrl(event.data.input); + }); + + client.fetch.on('requestUrl', event => { + event.data.value = __uv.sourceUrl(event.data.value); + }); + + client.fetch.on('responseUrl', event => { + event.data.value = __uv.sourceUrl(event.data.value); + }); + + // XMLHttpRequest + client.xhr.on('open', event => { + event.data.input = __uv.rewriteUrl(event.data.input); + }); + + client.xhr.on('responseUrl', event => { + event.data.value = __uv.sourceUrl(event.data.value); + }); + + + // Workers + client.workers.on('worker', event => { + event.data.url = __uv.rewriteUrl(event.data.url); + }); + + client.workers.on('addModule', event => { + event.data.url = __uv.rewriteUrl(event.data.url); + }); + + client.workers.on('importScripts', event => { + for (const i in event.data.scripts) { + event.data.scripts[i] = __uv.rewriteUrl(event.data.scripts[i]); + }; + }); + + client.workers.on('postMessage', event => { + let to = event.data.origin; + + event.data.origin = '*'; + event.data.message = { + __data: event.data.message, + __origin: __uv.meta.url.origin, + __to: to, + }; + }); + + // Navigator + client.navigator.on('sendBeacon', event => { + event.data.url = __uv.rewriteUrl(event.data.url); + }); + + // Cookies + client.document.on('getCookie', event => { + event.data.value = __uv.cookieStr; + }); + + client.document.on('setCookie', event => { + Promise.resolve(__uv.cookie.setCookies(event.data.value, __uv.db, __uv.meta)).then(() => { + __uv.cookie.db().then(db => { + __uv.cookie.getCookies(db).then(cookies => { + __uv.cookieStr = __uv.cookie.serialize(cookies, __uv.meta, true); + }); + }); + }); + const cookie = __uv.cookie.setCookie(event.data.value)[0]; + + if (!cookie.path) cookie.path = '/'; + if (!cookie.domain) cookie.domain = __uv.meta.url.hostname; + + if (__uv.cookie.validateCookie(cookie, __uv.meta, true)) { + if (__uv.cookieStr.length) __uv.cookieStr += '; '; + __uv.cookieStr += `${cookie.name}=${cookie.value}`; + }; + + event.respondWith(event.data.value); + }); + + // HTML + client.element.on('setInnerHTML', event => { + switch (event.that.tagName) { + case 'SCRIPT': + event.data.value = __uv.js.rewrite(event.data.value); + break; + case 'STYLE': + event.data.value = __uv.rewriteCSS(event.data.value); + break; + default: + event.data.value = __uv.rewriteHtml(event.data.value); + }; + }); + + client.element.on('getInnerHTML', event => { + switch (event.that.tagName) { + case 'SCRIPT': + event.data.value = __uv.js.source(event.data.value); + break; + default: + event.data.value = __uv.sourceHtml(event.data.value); + }; + }); + + client.element.on('setOuterHTML', event => { + event.data.value = __uv.rewriteHtml(event.data.value, { document: event.that.tagName === 'HTML' }); + }); + + client.element.on('getOuterHTML', event => { + switch (event.that.tagName) { + case 'HEAD': + event.data.value = __uv.sourceHtml( + event.data.value.replace(/(.*)<\/head>/s, '$2') + ).replace(/(.*)<\/op-head>/s, '$2'); + break; + case 'BODY': + event.data.value = __uv.sourceHtml( + event.data.value.replace(/(.*)<\/body>/s, '$2') + ).replace(/(.*)<\/op-body>/s, '$2'); + break; + default: + event.data.value = __uv.sourceHtml(event.data.value, { document: event.that.tagName === 'HTML' }); + break; + }; + + //event.data.value = __uv.sourceHtml(event.data.value, { document: event.that.tagName === 'HTML' }); + }); + + client.document.on('write', event => { + if (!event.data.html.length) return false; + event.data.html = [__uv.rewriteHtml(event.data.html.join(''))]; + }); + + client.document.on('writeln', event => { + if (!event.data.html.length) return false; + event.data.html = [__uv.rewriteHtml(event.data.html.join(''))]; + }); + + client.element.on('insertAdjacentHTML', event => { + event.data.html = __uv.rewriteHtml(event.data.html); + }); + + // EventSource + + client.eventSource.on('construct', event => { + event.data.url = __uv.rewriteUrl(event.data.url); + }); + + + client.eventSource.on('url', event => { + event.data.url = __uv.rewriteUrl(event.data.url); + }); + + // History + client.history.on('replaceState', event => { + if (event.data.url) event.data.url = __uv.rewriteUrl(event.data.url, '__uv' in event.that ? event.that.__uv.meta : __uv.meta); + }); + client.history.on('pushState', event => { + if (event.data.url) event.data.url = __uv.rewriteUrl(event.data.url, '__uv' in event.that ? event.that.__uv.meta : __uv.meta); + }); + + // Element get set attribute methods + client.element.on('getAttribute', event => { + if (client.element.hasAttribute.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name)) { + event.respondWith( + event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name) + ); + }; + }); + + // Message + client.message.on('postMessage', event => { + let to = event.data.origin; + let call = __uv.call; + + + if (event.that) { + call = event.that.__uv$source.call; + }; + + event.data.origin = '*'; + event.data.message = { + __data: event.data.message, + __origin: (event.that || event.target).__uv$source.location.origin, + __to: to, + }; + + event.respondWith( + worker ? + call(event.target, [event.data.message, event.data.transfer], event.that) : + call(event.target, [event.data.message, event.data.origin, event.data.transfer], event.that) + ); + + }); + + client.message.on('data', event => { + const { value: data } = event.data; + if (typeof data === 'object' && '__data' in data && '__origin' in data) { + event.respondWith(data.__data); + }; + }); + + client.message.on('origin', event => { + const data = client.message.messageData.get.call(event.that); + if (typeof data === 'object' && data.__data && data.__origin) { + event.respondWith(data.__origin); + }; + }); + + client.overrideDescriptor(window, 'origin', { + get: (target, that) => { + return __uv.location.origin; + }, + }); + + client.node.on('baseURI', event => { + if (event.data.value.startsWith(window.location.origin)) event.data.value = __uv.sourceUrl(event.data.value); + }); + + client.element.on('setAttribute', event => { + if (event.that instanceof HTMLMediaElement && event.data.name === 'src' && event.data.value.startsWith('blob:')) { + event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value); + event.data.value = __uv.blobUrls.get(event.data.value); + return; + }; + + if (__uv.attrs.isUrl(event.data.name)) { + event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value); + event.data.value = __uv.rewriteUrl(event.data.value); + }; + + if (__uv.attrs.isStyle(event.data.name)) { + event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value); + event.data.value = __uv.rewriteCSS(event.data.value, { context: 'declarationList' }); + }; + + if (__uv.attrs.isHtml(event.data.name)) { + event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value); + event.data.value = __uv.rewriteHtml(event.data.value, {...__uv.meta, document: true, injectHead:__uv.createHtmlInject(__uv.handlerScript, __uv.bundleScript, __uv.configScript, __uv.cookieStr, window.location.href) }); + }; + + if (__uv.attrs.isSrcset(event.data.name)) { + event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value); + event.data.value = __uv.html.wrapSrcset(event.data.value); + }; + + if (__uv.attrs.isForbidden(event.data.name)) { + event.data.name = __uv.attributePrefix + '-attr-' + event.data.name; + }; + }); + + client.element.on('audio', event => { + event.data.url = __uv.rewriteUrl(event.data.url); + }); + + // Element Property Attributes + client.element.hookProperty([HTMLAnchorElement, HTMLAreaElement, HTMLLinkElement, HTMLBaseElement], 'href', { + get: (target, that) => { + return __uv.sourceUrl( + target.call(that) + ); + }, + set: (target, that, [val]) => { + client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-href', val) + target.call(that, __uv.rewriteUrl(val)); + }, + }); + + client.element.hookProperty([HTMLScriptElement, HTMLAudioElement, HTMLVideoElement, HTMLMediaElement, HTMLImageElement, HTMLInputElement, HTMLEmbedElement, HTMLIFrameElement, HTMLTrackElement, HTMLSourceElement], 'src', { + get: (target, that) => { + return __uv.sourceUrl( + target.call(that) + ); + }, + set: (target, that, [val]) => { + if (new String(val).toString().trim().startsWith('blob:') && that instanceof HTMLMediaElement) { + client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-src', val) + return target.call(that, __uv.blobUrls.get(val) || val); + }; + + client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-src', val) + target.call(that, __uv.rewriteUrl(val)); + }, + }); + + client.element.hookProperty([HTMLFormElement], 'action', { + get: (target, that) => { + return __uv.sourceUrl( + target.call(that) + ); + }, + set: (target, that, [val]) => { + client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-action', val) + target.call(that, __uv.rewriteUrl(val)); + }, + }); + + client.element.hookProperty([HTMLImageElement], 'srcset', { + get: (target, that) => { + return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-srcset') || target.call(that); + }, + set: (target, that, [val]) => { + client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-srcset', val) + target.call(that, __uv.html.wrapSrcset(val)); + }, + }); + + client.element.hookProperty(HTMLScriptElement, 'integrity', { + get: (target, that) => { + return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-integrity'); + }, + set: (target, that, [val]) => { + client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-integrity', val); + }, + }); + + client.element.hookProperty(HTMLIFrameElement, 'sandbox', { + get: (target, that) => { + return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-sandbox') || target.call(that); + }, + set: (target, that, [val]) => { + client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-sandbox', val); + }, + }); + + client.element.hookProperty(HTMLIFrameElement, 'contentWindow', { + get: (target, that) => { + const win = target.call(that); + try { + if (!win.__uv) __uvHook(win, config, bare); + return win; + } catch (e) { + return win; + }; + }, + }); + + client.element.hookProperty(HTMLIFrameElement, 'contentDocument', { + get: (target, that) => { + const doc = target.call(that); + try { + const win = doc.defaultView + if (!win.__uv) __uvHook(win, config, bare); + return doc; + } catch (e) { + return win; + }; + }, + }); + + client.element.hookProperty(HTMLIFrameElement, 'srcdoc', { + get: (target, that) => { + return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-srcdoc') || target.call(that); + }, + set: (target, that, [val]) => { + target.call(that, __uv.rewriteHtml(val, { + document: true, + injectHead: __uv.createHtmlInject(__uv.handlerScript, __uv.bundleScript, __uv.configScript, __uv.cookieStr, window.location.href) + })) + }, + }); + + client.node.on('getTextContent', event => { + if (event.that.tagName === 'SCRIPT') { + event.data.value = __uv.js.source(event.data.value); + }; + }); + + client.node.on('setTextContent', event => { + if (event.that.tagName === 'SCRIPT') { + event.data.value = __uv.js.rewrite(event.data.value); + }; + }); + + // Until proper rewriting is implemented for service workers. + // Not sure atm how to implement it with the already built in service worker + if ('serviceWorker' in window.navigator) { + delete window.Navigator.prototype.serviceWorker; + }; + + // Document + client.document.on('getDomain', event => { + event.data.value = __uv.domain; + }); + client.document.on('setDomain', event => { + if (!event.data.value.toString().endsWith(__uv.meta.url.hostname.split('.').slice(-2).join('.'))) return event.respondWith(''); + event.respondWith(__uv.domain = event.data.value); + }) + + client.document.on('url', event => { + event.data.value = __uv.location.href; + }); + + client.document.on('documentURI', event => { + event.data.value = __uv.location.href; + }); + + client.document.on('referrer', event => { + event.data.value = __uv.referrer || __uv.sourceUrl(event.data.value); + }); + + client.document.on('parseFromString', event => { + if (event.data.type !== 'text/html') return false; + event.data.string = __uv.rewriteHtml(event.data.string, {...__uv.meta, document: true, }); + }); + + // Attribute (node.attributes) + client.attribute.on('getValue', event => { + if (client.element.hasAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name)) { + event.data.value = client.element.getAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name); + }; + }); + + client.attribute.on('setValue', event => { + if (__uv.attrs.isUrl(event.data.name)) { + client.element.setAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value); + event.data.value = __uv.rewriteUrl(event.data.value); + }; + + if (__uv.attrs.isStyle(event.data.name)) { + client.element.setAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value); + event.data.value = __uv.rewriteCSS(event.data.value, { context: 'declarationList' }); + }; + + if (__uv.attrs.isHtml(event.data.name)) { + client.element.setAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value); + event.data.value = __uv.rewriteHtml(event.data.value, {...__uv.meta, document: true, injectHead:__uv.createHtmlInject(__uv.handlerScript, __uv.bundleScript, __uv.configScript, __uv.cookieStr, window.location.href) }); + }; + + if (__uv.attrs.isSrcset(event.data.name)) { + client.element.setAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value); + event.data.value = __uv.html.wrapSrcset(event.data.value); + }; + + }); + + // URL + client.url.on('createObjectURL', event => { + let url = event.target.call(event.that, event.data.object); + if (url.startsWith('blob:' + location.origin)) { + let newUrl = 'blob:' + (__uv.meta.url.href !== 'about:blank' ? __uv.meta.url.origin : window.parent.__uv.meta.url.origin) + url.slice('blob:'.length + location.origin.length); + __uv.blobUrls.set(newUrl, url); + event.respondWith(newUrl); + } else { + event.respondWith(url); + }; + }); + + client.url.on('revokeObjectURL', event => { + if (__uv.blobUrls.has(event.data.url)) { + const old = event.data.url; + event.data.url = __uv.blobUrls.get(event.data.url); + __uv.blobUrls.delete(old); + }; + }); + + client.storage.on('get', event => { + event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name; + }); + + client.storage.on('set', event => { + if (event.that.__uv$storageObj) { + event.that.__uv$storageObj[event.data.name] = event.data.value; + }; + event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name; + }); + + client.storage.on('delete', event => { + if (event.that.__uv$storageObj) { + delete event.that.__uv$storageObj[event.data.name]; + }; + event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name; + }); + + client.storage.on('getItem', event => { + event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name; + }); + + client.storage.on('setItem', event => { + if (event.that.__uv$storageObj) { + event.that.__uv$storageObj[event.data.name] = event.data.value; + }; + event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name; + }); + + client.storage.on('removeItem', event => { + if (event.that.__uv$storageObj) { + delete event.that.__uv$storageObj[event.data.name]; + }; + event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name; + }); + + client.storage.on('clear', event => { + if (event.that.__uv$storageObj) { + for (const key of client.nativeMethods.keys.call(null, event.that.__uv$storageObj)) { + delete event.that.__uv$storageObj[key]; + client.storage.removeItem.call(event.that, methodPrefix + __uv.meta.url.origin + '@' + key); + event.respondWith(); + }; + }; + }); + + client.storage.on('length', event => { + if (event.that.__uv$storageObj) { + event.respondWith(client.nativeMethods.keys.call(null, event.that.__uv$storageObj).length); + }; + }); + + client.storage.on('key', event => { + if (event.that.__uv$storageObj) { + event.respondWith( + (client.nativeMethods.keys.call(null, event.that.__uv$storageObj)[event.data.index] || null) + ); + }; + }); + + client.websocket.on('websocket', async event => { + let url; + try { + url = new URL(event.data.url); + } catch(e) { + return; + }; + + const headers = { + Host: url.host, + Origin: __uv.meta.url.origin, + Pragma: 'no-cache', + 'Cache-Control': 'no-cache', + Upgrade: 'websocket', + 'User-Agent': window.navigator.userAgent, + 'Connection': 'Upgrade', + }; + + const cookies = __uv.cookie.serialize(__uv.cookies, { url }, false); + + if (cookies) headers.Cookie = cookies; + const protocols = [...event.data.protocols]; + + const remote = { + protocol: url.protocol, + host: url.hostname, + port: url.port || (url.protocol === 'wss:' ? '443' : '80'), + path: url.pathname + url.search, + }; + + if (protocols.length) headers['Sec-WebSocket-Protocol'] = protocols.join(', '); + + event.data.url = (__uv.bare.protocol === 'https:' ? 'wss://' : 'ws://') + __uv.bare.host + __uv.bare.pathname + 'v1/'; + event.data.protocols = [ + 'bare', + __uv.encodeProtocol(JSON.stringify({ + remote, + headers, + forward_headers: [ + 'accept', + 'accept-encoding', + 'accept-language', + 'sec-websocket-extensions', + 'sec-websocket-key', + 'sec-websocket-version', + ], + })), + ]; + + const ws = new event.target(event.data.url, event.data.protocols); + + client.nativeMethods.defineProperty(ws, methodPrefix + 'url', { + enumerable: false, + value: url.href, + }); + + event.respondWith( + ws + ); + }); + + client.websocket.on('url', event => { + if ('__uv$url' in event.that) { + event.data.value = event.that.__uv$url; + }; + }); + + client.websocket.on('protocol', event => { + if ('__uv$protocol' in event.that) { + event.data.value = event.that.__uv$protocol; + }; + }); + + client.function.on('function', event => { + event.data.script = __uv.rewriteJS(event.data.script); + }); + + client.function.on('toString', event => { + if (__uv.methods.string in event.that) event.respondWith(event.that[__uv.methods.string]); + }); + + client.object.on('getOwnPropertyNames', event => { + event.data.names = event.data.names.filter(element => !(__uv.filterKeys.includes(element))); + }); + + client.object.on('getOwnPropertyDescriptors', event => { + for (const forbidden of __uv.filterKeys) { + delete event.data.descriptors[forbidden]; + }; + + }); + + client.style.on('setProperty', event => { + if (client.style.dashedUrlProps.includes(event.data.property)) { + event.data.value = __uv.rewriteCSS(event.data.value, { + context: 'value', + ...__uv.meta + }) + }; + }); + + client.style.on('getPropertyValue', event => { + if (client.style.dashedUrlProps.includes(event.data.property)) { + event.respondWith( + __uv.sourceCSS( + event.target.call(event.that, event.data.property), + { + context: 'value', + ...__uv.meta + } + ) + ); + }; + }); + + if ('CSS2Properties' in window) { + for (const key of client.style.urlProps) { + client.overrideDescriptor(window.CSS2Properties.prototype, key, { + get: (target, that) => { + return __uv.sourceCSS( + target.call(that), + { + context: 'value', + ...__uv.meta + } + ) + }, + set: (target, that, val) => { + target.call( + that, + __uv.rewriteCSS(val, { + context: 'value', + ...__uv.meta + }) + ); + } + }); + }; + } else if ('HTMLElement' in window) { + + client.overrideDescriptor( + window.HTMLElement.prototype, + 'style', + { + get: (target, that) => { + const value = target.call(that); + if (!value[methodPrefix + 'modifiedStyle']) { + + for (const key of client.style.urlProps) { + client.nativeMethods.defineProperty(value, key, { + enumerable: true, + configurable: true, + get() { + const value = client.style.getPropertyValue.call(this, key) || ''; + return __uv.sourceCSS( + value, + { + context: 'value', + ...__uv.meta + } + ) + }, + set(val) { + client.style.setProperty.call(this, + (client.style.propToDashed[key] || key), + __uv.rewriteCSS(val, { + context: 'value', + ...__uv.meta + }) + ) + } + }); + client.nativeMethods.defineProperty(value, methodPrefix + 'modifiedStyle', { + enumerable: false, + value: true + }); + }; + }; + return value; + } + } + ); + }; + + client.style.on('setCssText', event => { + event.data.value = __uv.rewriteCSS(event.data.value, { + context: 'declarationList', + ...__uv.meta + }); + }); + + client.style.on('getCssText', event => { + event.data.value = __uv.sourceCSS(event.data.value, { + context: 'declarationList', + ...__uv.meta + }); + }); + + // Proper hash emulation. + if (!!window.window) { + __uv.addEventListener.call(window, 'hashchange', event => { + if (event.__uv$dispatched) return false; + event.stopImmediatePropagation(); + const hash = window.location.hash; + client.history.replaceState.call(window.history, '', '', event.oldURL); + __uv.location.hash = hash; + }); + }; + + client.location.on('hashchange', (oldUrl, newUrl, ctx) => { + if (ctx.HashChangeEvent && client.history.replaceState) { + client.history.replaceState.call(window.history, '', '', __uv.rewriteUrl(newUrl)); + + const event = new ctx.HashChangeEvent('hashchange', { newURL: newUrl, oldURL: oldUrl }); + + client.nativeMethods.defineProperty(event, methodPrefix + 'dispatched', { + value: true, + enumerable: false, + }); + + __uv.dispatchEvent.call(window, event); + }; + }); + + // Hooking functions & descriptors + client.fetch.overrideRequest(); + client.fetch.overrideUrl(); + client.xhr.overrideOpen(); + client.xhr.overrideResponseUrl(); + client.element.overrideHtml(); + client.element.overrideAttribute(); + client.element.overrideInsertAdjacentHTML(); + client.element.overrideAudio(); + // client.element.overrideQuerySelector(); + client.node.overrideBaseURI(); + client.node.overrideTextContent(); + client.attribute.overrideNameValue(); + client.document.overrideDomain(); + client.document.overrideURL(); + client.document.overrideDocumentURI(); + client.document.overrideWrite(); + client.document.overrideReferrer(); + client.document.overrideParseFromString(); + client.storage.overrideMethods(); + client.storage.overrideLength(); + //client.document.overrideQuerySelector(); + client.object.overrideGetPropertyNames(); + client.object.overrideGetOwnPropertyDescriptors(); + client.history.overridePushState(); + client.history.overrideReplaceState(); + client.eventSource.overrideConstruct(); + client.eventSource.overrideUrl(); + client.websocket.overrideWebSocket(); + client.websocket.overrideProtocol(); + client.websocket.overrideUrl(); + client.url.overrideObjectURL(); + client.document.overrideCookie(); + client.message.overridePostMessage(); + client.message.overrideMessageOrigin(); + client.message.overrideMessageData(); + client.workers.overrideWorker(); + client.workers.overrideAddModule(); + client.workers.overrideImportScripts(); + client.workers.overridePostMessage(); + client.style.overrideSetGetProperty(); + client.style.overrideCssText(); + client.navigator.overrideSendBeacon(); + client.function.overrideFunction(); + client.function.overrideToString(); + client.location.overrideWorkerLocation( + (href) => { + return new URL(__uv.sourceUrl(href)); + } + ); + + client.overrideDescriptor(window, 'localStorage', { + get: (target, that) => { + return (that || window).__uv.lsWrap; + }, + }); + client.overrideDescriptor(window, 'sessionStorage', { + get: (target, that) => { + return (that || window).__uv.ssWrap; + }, + }); + + + client.override(window, 'open', (target, that, args) => { + if (!args.length) return target.apply(that, args); + let [url] = args; + + url = __uv.rewriteUrl(url); + + return target.call(that, url); + }); + + __uv.$wrap = function(name) { + if (name === 'location') return __uv.methods.location; + if (name === 'eval') return __uv.methods.eval; + return name; + }; + + + __uv.$get = function(that) { + if (that === window.location) return __uv.location; + if (that === window.eval) return __uv.eval; + if (that === window.parent) { + return window.__uv$parent; + }; + if (that === window.top) { + return window.__uv$top; + }; + return that; + }; + + __uv.eval = client.wrap(window, 'eval', (target, that, args) => { + if (!args.length || typeof args[0] !== 'string') return target.apply(that, args); + let [script] = args; + + script = __uv.rewriteJS(script); + return target.call(that, script); + }); + + __uv.call = function(target, args, that) { + return that ? target.apply(that, args) : target(...args); + }; + + __uv.call$ = function(obj, prop, args = []) { + return obj[prop].apply(obj, args); + }; + + client.nativeMethods.defineProperty(window.Object.prototype, master, { + get: () => { + return __uv; + }, + enumerable: false + }); + + client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.setSource, { + value: function(source) { + if (!client.nativeMethods.isExtensible(this)) return this; + + client.nativeMethods.defineProperty(this, __uv.methods.source, { + value: source, + writable: true, + enumerable: false + }); + + return this; + }, + enumerable: false, + }); + + client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.source, { + value: __uv, + writable: true, + enumerable: false + }); + + client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.location, { + configurable: true, + get() { + return (this === window.document || this === window) ? __uv.location : this.location; + }, + set(val) { + if (this === window.document || this === window) { + __uv.location.href = val; + } else { + this.location = val; + }; + }, + }); + + client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.parent, { + configurable: true, + get() { + const val = this.parent; + + if (this === window) { + try { + return '__uv' in val ? val : this; + } catch (e) { + return this; + }; + }; + return val; + }, + set(val) { + this.parent = val; + }, + }); + + client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.top, { + configurable: true, + get() { + const val = this.top; + + if (this === window) { + if (val === this.parent) return this[__uv.methods.parent]; + try { + if (!('__uv' in val)) { + let current = this; + + while (current.parent !== val) { + current = current.parent + }; + + return '__uv' in current ? current : this; + + } else { + return val; + }; + } catch (e) { + return this; + }; + }; + return val; + }, + set(val) { + this.top = val; + }, + }); + + + client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.eval, { + configurable: true, + get() { + return this === window ? __uv.eval : this.eval; + }, + set(val) { + this.eval = val; + }, + }); +}; \ No newline at end of file diff --git a/magic/contact/english.js b/magic/contact/english.js new file mode 100644 index 0000000..a2fe322 --- /dev/null +++ b/magic/contact/english.js @@ -0,0 +1,790 @@ +importScripts('/contact/mathematics.js'); +importScripts('/contact/geography.js'); + +class UVServiceWorker extends EventEmitter { + constructor(config = __uv$config) { + super(); + if (!config.bare) config.bare = '/outerspace/'; + this.addresses = typeof config.bare === 'string' ? [ new URL(config.bare, location) ] : config.bare.map(str => new URL(str, location)); + this.headers = { + csp: [ + 'cross-origin-embedder-policy', + 'cross-origin-opener-policy', + 'cross-origin-resource-policy', + 'content-security-policy', + 'content-security-policy-report-only', + 'expect-ct', + 'feature-policy', + 'origin-isolation', + 'strict-transport-security', + 'upgrade-insecure-requests', + 'x-content-type-options', + 'x-download-options', + 'x-frame-options', + 'x-permitted-cross-domain-policies', + 'x-powered-by', + 'x-xss-protection', + ], + forward: [ + 'accept-encoding', + 'connection', + 'content-length', + ], + }; + this.method = { + empty: [ + 'GET', + 'HEAD' + ] + }; + this.statusCode = { + empty: [ + 204, + 304, + ], + }; + this.config = config; + this.browser = Ultraviolet.Bowser.getParser(self.navigator.userAgent).getBrowserName(); + + if (this.browser === 'Firefox') { + this.headers.forward.push('user-agent'); + this.headers.forward.push('content-type'); + }; + }; + async fetch({ request }) { + if (!request.url.startsWith(location.origin + (this.config.prefix || '/reviews/'))) { + return fetch(request); + }; + try { + + const ultraviolet = new Ultraviolet(this.config); + + if (typeof this.config.construct === 'function') { + this.config.construct(ultraviolet, 'service'); + }; + + const db = await ultraviolet.cookie.db(); + + ultraviolet.meta.origin = location.origin; + ultraviolet.meta.base = ultraviolet.meta.url = new URL(ultraviolet.sourceUrl(request.url)); + + const requestCtx = new RequestContext( + request, + this, + ultraviolet, + !this.method.empty.includes(request.method.toUpperCase()) ? await request.blob() : null + ); + + if (ultraviolet.meta.url.protocol === 'blob:') { + requestCtx.blob = true; + requestCtx.base = requestCtx.url = new URL(requestCtx.url.pathname); + }; + + if (request.referrer && request.referrer.startsWith(location.origin)) { + const referer = new URL(ultraviolet.sourceUrl(request.referrer)); + + if (requestCtx.headers.origin || ultraviolet.meta.url.origin !== referer.origin && request.mode === 'cors') { + requestCtx.headers.origin = referer.origin; + }; + + requestCtx.headers.referer = referer.href; + }; + + const cookies = await ultraviolet.cookie.getCookies(db) || []; + const cookieStr = ultraviolet.cookie.serialize(cookies, ultraviolet.meta, false); + + if (this.browser === 'Firefox' && !(request.destination === 'iframe' || request.destination === 'document')) { + requestCtx.forward.shift(); + }; + + if (cookieStr) requestCtx.headers.cookie = cookieStr; + requestCtx.headers.Host = requestCtx.url.host; + + + const reqEvent = new HookEvent(requestCtx, null, null); + this.emit('request', reqEvent); + + if (reqEvent.intercepted) return reqEvent.returnValue; + + const response = await fetch(requestCtx.send); + + if (response.status === 500) { + return Promise.reject(''); + }; + + const responseCtx = new ResponseContext(requestCtx, response, this); + const resEvent = new HookEvent(responseCtx, null, null); + + this.emit('beforemod', resEvent); + if (resEvent.intercepted) return resEvent.returnValue; + + for (const name of this.headers.csp) { + if (responseCtx.headers[name]) delete responseCtx.headers[name]; + }; + + if (responseCtx.headers.location) { + responseCtx.headers.location = ultraviolet.rewriteUrl(responseCtx.headers.location); + }; + + if (responseCtx.headers['set-cookie']) { + Promise.resolve(ultraviolet.cookie.setCookies(responseCtx.headers['set-cookie'], db, ultraviolet.meta)).then(() => { + self.clients.matchAll().then(function (clients){ + clients.forEach(function(client){ + client.postMessage({ + msg: 'updateCookies', + url: ultraviolet.meta.url.href, + }); + }); + }); + }); + delete responseCtx.headers['set-cookie']; + }; + + if (responseCtx.body) { + switch(request.destination) { + case 'script': + case 'worker': + responseCtx.body = `if (!self.__uv && self.importScripts) importScripts('${__uv$config.bundle}', '${__uv$config.config}', '${__uv$config.handler}');\n`; + responseCtx.body += ultraviolet.js.rewrite( + await response.text() + ); + break; + case 'style': + responseCtx.body = ultraviolet.rewriteCSS( + await response.text() + ); + break; + case 'iframe': + case 'document': + if (isHtml(ultraviolet.meta.url, (responseCtx.headers['content-type'] || ''))) { + responseCtx.body = ultraviolet.rewriteHtml( + await response.text(), + { + document: true , + injectHead: ultraviolet.createHtmlInject( + this.config.handler, + this.config.bundle, + this.config.config, + ultraviolet.cookie.serialize(cookies, ultraviolet.meta, true), + request.referrer + ) + } + ); + }; + }; + }; + + if (requestCtx.headers.accept === 'text/event-stream') { + responseCtx.headers['content-type'] = 'text/event-stream'; + }; + + this.emit('response', resEvent); + if (resEvent.intercepted) return resEvent.returnValue; + + return new Response(responseCtx.body, { + headers: responseCtx.headers, + status: responseCtx.status, + statusText: responseCtx.statusText, + }); + + } catch(err) { + return new Response(err.toString(), { + status: 500, + }); + }; + }; + getBarerResponse(response) { + const headers = {}; + const raw = JSON.parse(response.headers.get('x-bare-headers')); + + for (const key in raw) { + headers[key.toLowerCase()] = raw[key]; + }; + + return { + headers, + status: +response.headers.get('x-bare-status'), + statusText: response.headers.get('x-bare-status-text'), + body: !this.statusCode.empty.includes(+response.headers.get('x-bare-status')) ? response.body : null, + }; + }; + get address() { + return this.addresses[Math.floor(Math.random() * this.addresses.length)]; + }; + static Ultraviolet = Ultraviolet; +}; + +self.UVServiceWorker = UVServiceWorker; + + +class ResponseContext { + constructor(request, response, worker) { + const { headers, status, statusText, body } = !request.blob ? worker.getBarerResponse(response) : { + status: response.status, + statusText: response.statusText, + headers: Object.fromEntries([...response.headers.entries()]), + body: response.body, + }; + this.request = request; + this.raw = response; + this.ultraviolet = request.ultraviolet; + this.headers = headers; + this.status = status; + this.statusText = statusText; + this.body = body; + }; + get url() { + return this.request.url; + } + get base() { + return this.request.base; + }; + set base(val) { + this.request.base = val; + }; +}; + +class RequestContext { + constructor(request, worker, ultraviolet, body = null) { + this.ultraviolet = ultraviolet; + this.request = request; + this.headers = Object.fromEntries([...request.headers.entries()]); + this.method = request.method; + this.forward = [...worker.headers.forward]; + this.address = worker.address; + this.body = body || null; + this.redirect = request.redirect; + this.credentials = 'omit'; + this.mode = request.mode === 'cors' ? request.mode : 'same-origin'; + this.blob = false; + }; + get send() { + return new Request((!this.blob ? this.address.href + 'v1/' : 'blob:' + location.origin + this.url.pathname), { + method: this.method, + headers: { + 'x-bare-protocol': this.url.protocol, + 'x-bare-host': this.url.hostname, + 'x-bare-path': this.url.pathname + this.url.search, + 'x-bare-port': this.url.port || (this.url.protocol === 'https:' ? '443' : '80'), + 'x-bare-headers': JSON.stringify(this.headers), + 'x-bare-forward-headers': JSON.stringify(this.forward), + 'userKey': userKey, + }, + redirect: this.redirect, + credentials: this.credentials, + mode: location.origin !== this.address.origin ? 'cors' : this.mode, + body: this.body + }); + }; + get url() { + return this.ultraviolet.meta.url; + }; + set url(val) { + this.ultraviolet.meta.url = val; + }; + get base() { + return this.ultraviolet.meta.base; + }; + set base(val) { + this.ultraviolet.meta.base = val; + }; +} + +function isHtml(url, contentType = '') { + return (Ultraviolet.mime.contentType((contentType || url.pathname)) || 'text/html').split(';')[0] === 'text/html'; +}; + +class HookEvent { + #intercepted; + #returnValue; + constructor(data = {}, target = null, that = null) { + this.#intercepted = false; + this.#returnValue = null; + this.data = data; + this.target = target; + this.that = that; + }; + get intercepted() { + return this.#intercepted; + }; + get returnValue() { + return this.#returnValue; + }; + respondWith(input) { + this.#returnValue = input; + this.#intercepted = true; + }; +}; + +var R = typeof Reflect === 'object' ? Reflect : null +var ReflectApply = R && typeof R.apply === 'function' + ? R.apply + : function ReflectApply(target, receiver, args) { + return Function.prototype.apply.call(target, receiver, args); + } + +var ReflectOwnKeys +if (R && typeof R.ownKeys === 'function') { + ReflectOwnKeys = R.ownKeys +} else if (Object.getOwnPropertySymbols) { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target) + .concat(Object.getOwnPropertySymbols(target)); + }; +} else { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target); + }; +} + +function ProcessEmitWarning(warning) { + if (console && console.warn) console.warn(warning); +} + +var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) { + return value !== value; +} + +function EventEmitter() { + EventEmitter.init.call(this); +} + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._eventsCount = 0; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +var defaultMaxListeners = 10; + +function checkListener(listener) { + if (typeof listener !== 'function') { + throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); + } +} + +Object.defineProperty(EventEmitter, 'defaultMaxListeners', { + enumerable: true, + get: function() { + return defaultMaxListeners; + }, + set: function(arg) { + if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) { + throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.'); + } + defaultMaxListeners = arg; + } +}); + +EventEmitter.init = function() { + + if (this._events === undefined || + this._events === Object.getPrototypeOf(this)._events) { + this._events = Object.create(null); + this._eventsCount = 0; + } + + this._maxListeners = this._maxListeners || undefined; +}; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { + if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) { + throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.'); + } + this._maxListeners = n; + return this; +}; + +function _getMaxListeners(that) { + if (that._maxListeners === undefined) + return EventEmitter.defaultMaxListeners; + return that._maxListeners; +} + +EventEmitter.prototype.getMaxListeners = function getMaxListeners() { + return _getMaxListeners(this); +}; + +EventEmitter.prototype.emit = function emit(type) { + var args = []; + for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); + var doError = (type === 'error'); + + var events = this._events; + if (events !== undefined) + doError = (doError && events.error === undefined); + else if (!doError) + return false; + + // If there is no 'error' event listener then throw. + if (doError) { + var er; + if (args.length > 0) + er = args[0]; + if (er instanceof Error) { + // Note: The comments on the `throw` lines are intentional, they show + // up in Node's output if this results in an unhandled exception. + throw er; // Unhandled 'error' event + } + // At least give some kind of context to the user + var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); + err.context = er; + throw err; // Unhandled 'error' event + } + + var handler = events[type]; + + if (handler === undefined) + return false; + + if (typeof handler === 'function') { + ReflectApply(handler, this, args); + } else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + ReflectApply(listeners[i], this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + checkListener(listener); + + events = target._events; + if (events === undefined) { + events = target._events = Object.create(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener !== undefined) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (existing === undefined) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + // If we've already got an array, just append. + } else if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + + // Check for listener leak + m = _getMaxListeners(target); + if (m > 0 && existing.length > m && !existing.warned) { + existing.warned = true; + // No error code for this since it is a Warning + // eslint-disable-next-line no-restricted-syntax + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' ' + String(type) + ' listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + ProcessEmitWarning(w); + } + } + + return target; +} + +EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + +function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + if (arguments.length === 0) + return this.listener.call(this.target); + return this.listener.apply(this.target, arguments); + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = onceWrapper.bind(state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + checkListener(listener); + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + checkListener(listener); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + +// Emits a 'removeListener' event if and only if the listener was removed. +EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + checkListener(listener); + + events = this._events; + if (events === undefined) + return this; + + list = events[type]; + if (list === undefined) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = Object.create(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else { + spliceOne(list, position); + } + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener !== undefined) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.off = EventEmitter.prototype.removeListener; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (events === undefined) + return this; + + // not listening for removeListener, no need to emit + if (events.removeListener === undefined) { + if (arguments.length === 0) { + this._events = Object.create(null); + this._eventsCount = 0; + } else if (events[type] !== undefined) { + if (--this._eventsCount === 0) + this._events = Object.create(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = Object.keys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = Object.create(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners !== undefined) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + +function _listeners(target, type, unwrap) { + var events = target._events; + + if (events === undefined) + return []; + + var evlistener = events[type]; + if (evlistener === undefined) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? + unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); +} + +EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); +}; + +EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); +}; + +EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } +}; + +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { + var events = this._events; + + if (events !== undefined) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener !== undefined) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; +}; + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +function spliceOne(list, index) { + for (; index + 1 < list.length; index++) + list[index] = list[index + 1]; + list.pop(); +} + +function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; +} + +function once(emitter, name) { + return new Promise(function (resolve, reject) { + function errorListener(err) { + emitter.removeListener(name, resolver); + reject(err); + } + + function resolver() { + if (typeof emitter.removeListener === 'function') { + emitter.removeListener('error', errorListener); + } + resolve([].slice.call(arguments)); + }; + + eventTargetAgnosticAddListener(emitter, name, resolver, { once: true }); + if (name !== 'error') { + addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true }); + } + }); +} + +function addErrorHandlerIfEventEmitter(emitter, handler, flags) { + if (typeof emitter.on === 'function') { + eventTargetAgnosticAddListener(emitter, 'error', handler, flags); + } +} + +function eventTargetAgnosticAddListener(emitter, name, listener, flags) { + if (typeof emitter.on === 'function') { + if (flags.once) { + emitter.once(name, listener); + } else { + emitter.on(name, listener); + } + } else if (typeof emitter.addEventListener === 'function') { + // EventTarget does not have `error` event semantics like Node + // EventEmitters, we do not listen for `error` events here. + emitter.addEventListener(name, function wrapListener(arg) { + // IE does not have builtin `{ once: true }` support so we + // have to do it manually. + if (flags.once) { + emitter.removeEventListener(name, wrapListener); + } + listener(arg); + }); + } else { + throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter); + } +} \ No newline at end of file diff --git a/magic/contact/geography.js b/magic/contact/geography.js new file mode 100644 index 0000000..d62766d --- /dev/null +++ b/magic/contact/geography.js @@ -0,0 +1,10 @@ +self.__uv$config = { + prefix: '/reviews/', + bare: '/outerspace/', + encodeUrl: Ultraviolet.codec.xor.encode, + decodeUrl: Ultraviolet.codec.xor.decode, + handler: '/contact/algebra.js', + bundle: '/contact/mathematics.js', + config: '/contact/geography.js', + sw: '/contact/english.js', +}; diff --git a/magic/contact/mathematics.js b/magic/contact/mathematics.js new file mode 100644 index 0000000..da92521 --- /dev/null +++ b/magic/contact/mathematics.js @@ -0,0 +1,39304 @@ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ([ +/* 0 */, +/* 1 */ +/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { + + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) + /* harmony export */ }); + /* harmony import */ var _events_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); + /* harmony import */ var parse5__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3); + + + + class HTML extends _events_js__WEBPACK_IMPORTED_MODULE_0__["default"] { + constructor(ctx) { + super(); + this.ctx = ctx; + this.rewriteUrl = ctx.rewriteUrl; + this.sourceUrl = ctx.sourceUrl; + }; + rewrite(str, options = {}) { + if (!str) return str; + return this.recast(str, node => { + if (node.tagName) this.emit('element', node, 'rewrite'); + if (node.attr) this.emit('attr', node, 'rewrite'); + if (node.nodeName === '#text') this.emit('text', node, 'rewrite'); + }, options) + }; + source(str, options = {}) { + if (!str) return str; + return this.recast(str, node => { + if (node.tagName) this.emit('element', node, 'source'); + if (node.attr) this.emit('attr', node, 'source'); + if (node.nodeName === '#text') this.emit('text', node, 'source'); + }, options) + }; + recast(str, fn, options = {}) { + try { + const ast = (options.document ? parse5__WEBPACK_IMPORTED_MODULE_1__.parse : parse5__WEBPACK_IMPORTED_MODULE_1__.parseFragment)(new String(str).toString()); + this.iterate(ast, fn, options); + return (0,parse5__WEBPACK_IMPORTED_MODULE_1__.serialize)(ast); + } catch(e) { + return str; + }; + }; + iterate(ast, fn, fnOptions) { + if (!ast) return ast; + + if (ast.tagName) { + const element = new P5Element(ast, false, fnOptions); + fn(element); + if (ast.attrs) { + for (const attr of ast.attrs) { + if (!attr.skip) fn(new AttributeEvent(element, attr, fnOptions)); + }; + }; + }; + + if (ast.childNodes) { + for (const child of ast.childNodes) { + if (!child.skip) this.iterate(child, fn, fnOptions); + }; + }; + + if (ast.nodeName === '#text') { + fn(new TextEvent(ast, new P5Element(ast.parentNode), false, fnOptions)); + }; + + return ast; + }; + wrapSrcset(str, meta = this.ctx.meta) { + return str.split(',').map(src => { + const parts = src.trimStart().split(' '); + if (parts[0]) parts[0] = this.ctx.rewriteUrl(parts[0], meta); + return parts.join(' '); + }).join(', '); + }; + unwrapSrcset(str, meta = this.ctx.meta) { + return str.split(',').map(src => { + const parts = src.trimStart().split(' '); + if (parts[0]) parts[0] = this.ctx.sourceUrl(parts[0], meta); + return parts.join(' '); + }).join(', '); + }; + static parse = parse5__WEBPACK_IMPORTED_MODULE_1__.parse; + static parseFragment = parse5__WEBPACK_IMPORTED_MODULE_1__.parseFragment; + static serialize = parse5__WEBPACK_IMPORTED_MODULE_1__.serialize; + }; + + class P5Element extends _events_js__WEBPACK_IMPORTED_MODULE_0__["default"] { + constructor(node, stream = false, options = {}) { + super(); + this.stream = stream; + this.node = node; + this.options = options; + }; + setAttribute(name, value) { + for (const attr of this.attrs) { + if (attr.name === name) { + attr.value = value; + return true; + }; + }; + + this.attrs.push( + { + name, + value, + } + ); + }; + getAttribute(name) { + const attr = this.attrs.find(attr => attr.name === name) || {}; + return attr.value; + }; + hasAttribute(name) { + return !!this.attrs.find(attr => attr.name === name); + }; + removeAttribute(name) { + const i = this.attrs.findIndex(attr => attr.name === name); + if (typeof i !== 'undefined') this.attrs.splice(i, 1); + }; + get tagName() { + return this.node.tagName; + }; + set tagName(val) { + this.node.tagName = val; + }; + get childNodes() { + return !this.stream ? this.node.childNodes : null; + }; + get innerHTML() { + return !this.stream ? (0,parse5__WEBPACK_IMPORTED_MODULE_1__.serialize)( + { + nodeName: '#document-fragment', + childNodes: this.childNodes, + } + ) : null; + }; + set innerHTML(val) { + if (!this.stream) this.node.childNodes = (0,parse5__WEBPACK_IMPORTED_MODULE_1__.parseFragment)(val).childNodes; + }; + get outerHTML() { + return !this.stream ? (0,parse5__WEBPACK_IMPORTED_MODULE_1__.serialize)( + { + nodeName: '#document-fragment', + childNodes: [ this ], + } + ) : null; + }; + set outerHTML(val) { + if (!this.stream) this.parentNode.childNodes.splice(this.parentNode.childNodes.findIndex(node => node === this.node), 1, ...(0,parse5__WEBPACK_IMPORTED_MODULE_1__.parseFragment)(val).childNodes); + }; + get textContent() { + if (this.stream) return null; + + let str = ''; + iterate(this.node, node => { + if (node.nodeName === '#text') str += node.value; + }); + + return str; + }; + set textContent(val) { + if (!this.stream) this.node.childNodes = [ + { + nodeName: '#text', + value: val, + parentNode: this.node + } + ]; + }; + get nodeName() { + return this.node.nodeName; + } + get parentNode() { + return this.node.parentNode ? new P5Element(this.node.parentNode) : null; + }; + get attrs() { + return this.node.attrs; + } + get namespaceURI() { + return this.node.namespaceURI; + } + }; + + class AttributeEvent { + constructor(node, attr, options = {}) { + this.attr = attr; + this.attrs = node.attrs; + this.node = node; + this.options = options; + }; + delete() { + const i = this.attrs.findIndex(attr => attr === this.attr); + + this.attrs.splice(i, 1); + + Object.defineProperty(this, 'deleted', { + get: () => true, + }); + + return true; + }; + get name() { + return this.attr.name; + }; + + set name(val) { + this.attr.name = val; + }; + get value() { + return this.attr.value; + }; + + set value(val) { + this.attr.value = val; + }; + get deleted() { + return false; + }; + }; + + class TextEvent { + constructor(node, element, stream = false, options = {}) { + this.stream = stream; + this.node = node; + this.element = element; + this.options = options; + }; + get nodeName() { + return this.node.nodeName; + } + get parentNode() { + return this.element; + }; + get value() { + return this.stream ? this.node.text : this.node.value; + }; + set value(val) { + + if (this.stream) this.node.text = val; + else this.node.value = val; + }; + }; + + /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HTML); + + /***/ }), + /* 2 */ + /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { + + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) + /* harmony export */ }); + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + + + var R = typeof Reflect === 'object' ? Reflect : null + var ReflectApply = R && typeof R.apply === 'function' + ? R.apply + : function ReflectApply(target, receiver, args) { + return Function.prototype.apply.call(target, receiver, args); + } + + var ReflectOwnKeys + if (R && typeof R.ownKeys === 'function') { + ReflectOwnKeys = R.ownKeys + } else if (Object.getOwnPropertySymbols) { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target) + .concat(Object.getOwnPropertySymbols(target)); + }; + } else { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target); + }; + } + + function ProcessEmitWarning(warning) { + if (console && console.warn) console.warn(warning); + } + + var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) { + return value !== value; + } + + function EventEmitter() { + EventEmitter.init.call(this); + } + + /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (EventEmitter); + + // Backwards-compat with node 0.10.x + EventEmitter.EventEmitter = EventEmitter; + + EventEmitter.prototype._events = undefined; + EventEmitter.prototype._eventsCount = 0; + EventEmitter.prototype._maxListeners = undefined; + + // By default EventEmitters will print a warning if more than 10 listeners are + // added to it. This is a useful default which helps finding memory leaks. + var defaultMaxListeners = 10; + + function checkListener(listener) { + if (typeof listener !== 'function') { + throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); + } + } + + Object.defineProperty(EventEmitter, 'defaultMaxListeners', { + enumerable: true, + get: function() { + return defaultMaxListeners; + }, + set: function(arg) { + if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) { + throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.'); + } + defaultMaxListeners = arg; + } + }); + + EventEmitter.init = function() { + + if (this._events === undefined || + this._events === Object.getPrototypeOf(this)._events) { + this._events = Object.create(null); + this._eventsCount = 0; + } + + this._maxListeners = this._maxListeners || undefined; + }; + + // Obviously not all Emitters should be limited to 10. This function allows + // that to be increased. Set to zero for unlimited. + EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { + if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) { + throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.'); + } + this._maxListeners = n; + return this; + }; + + function _getMaxListeners(that) { + if (that._maxListeners === undefined) + return EventEmitter.defaultMaxListeners; + return that._maxListeners; + } + + EventEmitter.prototype.getMaxListeners = function getMaxListeners() { + return _getMaxListeners(this); + }; + + EventEmitter.prototype.emit = function emit(type) { + var args = []; + for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); + var doError = (type === 'error'); + + var events = this._events; + if (events !== undefined) + doError = (doError && events.error === undefined); + else if (!doError) + return false; + + // If there is no 'error' event listener then throw. + if (doError) { + var er; + if (args.length > 0) + er = args[0]; + if (er instanceof Error) { + // Note: The comments on the `throw` lines are intentional, they show + // up in Node's output if this results in an unhandled exception. + throw er; // Unhandled 'error' event + } + // At least give some kind of context to the user + var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); + err.context = er; + throw err; // Unhandled 'error' event + } + + var handler = events[type]; + + if (handler === undefined) + return false; + + if (typeof handler === 'function') { + ReflectApply(handler, this, args); + } else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + ReflectApply(listeners[i], this, args); + } + + return true; + }; + + function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + checkListener(listener); + + events = target._events; + if (events === undefined) { + events = target._events = Object.create(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener !== undefined) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (existing === undefined) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + // If we've already got an array, just append. + } else if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + + // Check for listener leak + m = _getMaxListeners(target); + if (m > 0 && existing.length > m && !existing.warned) { + existing.warned = true; + // No error code for this since it is a Warning + // eslint-disable-next-line no-restricted-syntax + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' ' + String(type) + ' listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + ProcessEmitWarning(w); + } + } + + return target; + } + + EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); + }; + + EventEmitter.prototype.on = EventEmitter.prototype.addListener; + + EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + + function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + if (arguments.length === 0) + return this.listener.call(this.target); + return this.listener.apply(this.target, arguments); + } + } + + function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = onceWrapper.bind(state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; + } + + EventEmitter.prototype.once = function once(type, listener) { + checkListener(listener); + this.on(type, _onceWrap(this, type, listener)); + return this; + }; + + EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + checkListener(listener); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + + // Emits a 'removeListener' event if and only if the listener was removed. + EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + checkListener(listener); + + events = this._events; + if (events === undefined) + return this; + + list = events[type]; + if (list === undefined) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = Object.create(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else { + spliceOne(list, position); + } + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener !== undefined) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + + EventEmitter.prototype.off = EventEmitter.prototype.removeListener; + + EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (events === undefined) + return this; + + // not listening for removeListener, no need to emit + if (events.removeListener === undefined) { + if (arguments.length === 0) { + this._events = Object.create(null); + this._eventsCount = 0; + } else if (events[type] !== undefined) { + if (--this._eventsCount === 0) + this._events = Object.create(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = Object.keys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = Object.create(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners !== undefined) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + + function _listeners(target, type, unwrap) { + var events = target._events; + + if (events === undefined) + return []; + + var evlistener = events[type]; + if (evlistener === undefined) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? + unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); + } + + EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); + }; + + EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); + }; + + EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } + }; + + EventEmitter.prototype.listenerCount = listenerCount; + function listenerCount(type) { + var events = this._events; + + if (events !== undefined) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener !== undefined) { + return evlistener.length; + } + } + + return 0; + } + + EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; + }; + + function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; + } + + function spliceOne(list, index) { + for (; index + 1 < list.length; index++) + list[index] = list[index + 1]; + list.pop(); + } + + function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; + } + + function once(emitter, name) { + return new Promise(function (resolve, reject) { + function errorListener(err) { + emitter.removeListener(name, resolver); + reject(err); + } + + function resolver() { + if (typeof emitter.removeListener === 'function') { + emitter.removeListener('error', errorListener); + } + resolve([].slice.call(arguments)); + }; + + eventTargetAgnosticAddListener(emitter, name, resolver, { once: true }); + if (name !== 'error') { + addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true }); + } + }); + } + + function addErrorHandlerIfEventEmitter(emitter, handler, flags) { + if (typeof emitter.on === 'function') { + eventTargetAgnosticAddListener(emitter, 'error', handler, flags); + } + } + + function eventTargetAgnosticAddListener(emitter, name, listener, flags) { + if (typeof emitter.on === 'function') { + if (flags.once) { + emitter.once(name, listener); + } else { + emitter.on(name, listener); + } + } else if (typeof emitter.addEventListener === 'function') { + // EventTarget does not have `error` event semantics like Node + // EventEmitters, we do not listen for `error` events here. + emitter.addEventListener(name, function wrapListener(arg) { + // IE does not have builtin `{ once: true }` support so we + // have to do it manually. + if (flags.once) { + emitter.removeEventListener(name, wrapListener); + } + listener(arg); + }); + } else { + throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter); + } + } + + /***/ }), + /* 3 */ + /***/ ((__unused_webpack_module, exports, __webpack_require__) => { + + "use strict"; + + + const Parser = __webpack_require__(4); + const Serializer = __webpack_require__(26); + + // Shorthands + exports.parse = function parse(html, options) { + const parser = new Parser(options); + + return parser.parse(html); + }; + + exports.parseFragment = function parseFragment(fragmentContext, html, options) { + if (typeof fragmentContext === 'string') { + options = html; + html = fragmentContext; + fragmentContext = null; + } + + const parser = new Parser(options); + + return parser.parseFragment(html, fragmentContext); + }; + + exports.serialize = function(node, options) { + const serializer = new Serializer(node, options); + + return serializer.serialize(); + }; + + + /***/ }), + /* 4 */ + /***/ ((module, __unused_webpack_exports, __webpack_require__) => { + + "use strict"; + + + const Tokenizer = __webpack_require__(5); + const OpenElementStack = __webpack_require__(10); + const FormattingElementList = __webpack_require__(12); + const LocationInfoParserMixin = __webpack_require__(13); + const ErrorReportingParserMixin = __webpack_require__(18); + const Mixin = __webpack_require__(14); + const defaultTreeAdapter = __webpack_require__(22); + const mergeOptions = __webpack_require__(23); + const doctype = __webpack_require__(24); + const foreignContent = __webpack_require__(25); + const ERR = __webpack_require__(8); + const unicode = __webpack_require__(7); + const HTML = __webpack_require__(11); + + //Aliases + const $ = HTML.TAG_NAMES; + const NS = HTML.NAMESPACES; + const ATTRS = HTML.ATTRS; + + const DEFAULT_OPTIONS = { + scriptingEnabled: true, + sourceCodeLocationInfo: false, + onParseError: null, + treeAdapter: defaultTreeAdapter + }; + + //Misc constants + const HIDDEN_INPUT_TYPE = 'hidden'; + + //Adoption agency loops iteration count + const AA_OUTER_LOOP_ITER = 8; + const AA_INNER_LOOP_ITER = 3; + + //Insertion modes + const INITIAL_MODE = 'INITIAL_MODE'; + const BEFORE_HTML_MODE = 'BEFORE_HTML_MODE'; + const BEFORE_HEAD_MODE = 'BEFORE_HEAD_MODE'; + const IN_HEAD_MODE = 'IN_HEAD_MODE'; + const IN_HEAD_NO_SCRIPT_MODE = 'IN_HEAD_NO_SCRIPT_MODE'; + const AFTER_HEAD_MODE = 'AFTER_HEAD_MODE'; + const IN_BODY_MODE = 'IN_BODY_MODE'; + const TEXT_MODE = 'TEXT_MODE'; + const IN_TABLE_MODE = 'IN_TABLE_MODE'; + const IN_TABLE_TEXT_MODE = 'IN_TABLE_TEXT_MODE'; + const IN_CAPTION_MODE = 'IN_CAPTION_MODE'; + const IN_COLUMN_GROUP_MODE = 'IN_COLUMN_GROUP_MODE'; + const IN_TABLE_BODY_MODE = 'IN_TABLE_BODY_MODE'; + const IN_ROW_MODE = 'IN_ROW_MODE'; + const IN_CELL_MODE = 'IN_CELL_MODE'; + const IN_SELECT_MODE = 'IN_SELECT_MODE'; + const IN_SELECT_IN_TABLE_MODE = 'IN_SELECT_IN_TABLE_MODE'; + const IN_TEMPLATE_MODE = 'IN_TEMPLATE_MODE'; + const AFTER_BODY_MODE = 'AFTER_BODY_MODE'; + const IN_FRAMESET_MODE = 'IN_FRAMESET_MODE'; + const AFTER_FRAMESET_MODE = 'AFTER_FRAMESET_MODE'; + const AFTER_AFTER_BODY_MODE = 'AFTER_AFTER_BODY_MODE'; + const AFTER_AFTER_FRAMESET_MODE = 'AFTER_AFTER_FRAMESET_MODE'; + + //Insertion mode reset map + const INSERTION_MODE_RESET_MAP = { + [$.TR]: IN_ROW_MODE, + [$.TBODY]: IN_TABLE_BODY_MODE, + [$.THEAD]: IN_TABLE_BODY_MODE, + [$.TFOOT]: IN_TABLE_BODY_MODE, + [$.CAPTION]: IN_CAPTION_MODE, + [$.COLGROUP]: IN_COLUMN_GROUP_MODE, + [$.TABLE]: IN_TABLE_MODE, + [$.BODY]: IN_BODY_MODE, + [$.FRAMESET]: IN_FRAMESET_MODE + }; + + //Template insertion mode switch map + const TEMPLATE_INSERTION_MODE_SWITCH_MAP = { + [$.CAPTION]: IN_TABLE_MODE, + [$.COLGROUP]: IN_TABLE_MODE, + [$.TBODY]: IN_TABLE_MODE, + [$.TFOOT]: IN_TABLE_MODE, + [$.THEAD]: IN_TABLE_MODE, + [$.COL]: IN_COLUMN_GROUP_MODE, + [$.TR]: IN_TABLE_BODY_MODE, + [$.TD]: IN_ROW_MODE, + [$.TH]: IN_ROW_MODE + }; + + //Token handlers map for insertion modes + const TOKEN_HANDLERS = { + [INITIAL_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: tokenInInitialMode, + [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInInitialMode, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: doctypeInInitialMode, + [Tokenizer.START_TAG_TOKEN]: tokenInInitialMode, + [Tokenizer.END_TAG_TOKEN]: tokenInInitialMode, + [Tokenizer.EOF_TOKEN]: tokenInInitialMode + }, + [BEFORE_HTML_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: tokenBeforeHtml, + [Tokenizer.NULL_CHARACTER_TOKEN]: tokenBeforeHtml, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagBeforeHtml, + [Tokenizer.END_TAG_TOKEN]: endTagBeforeHtml, + [Tokenizer.EOF_TOKEN]: tokenBeforeHtml + }, + [BEFORE_HEAD_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: tokenBeforeHead, + [Tokenizer.NULL_CHARACTER_TOKEN]: tokenBeforeHead, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype, + [Tokenizer.START_TAG_TOKEN]: startTagBeforeHead, + [Tokenizer.END_TAG_TOKEN]: endTagBeforeHead, + [Tokenizer.EOF_TOKEN]: tokenBeforeHead + }, + [IN_HEAD_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: tokenInHead, + [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInHead, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype, + [Tokenizer.START_TAG_TOKEN]: startTagInHead, + [Tokenizer.END_TAG_TOKEN]: endTagInHead, + [Tokenizer.EOF_TOKEN]: tokenInHead + }, + [IN_HEAD_NO_SCRIPT_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: tokenInHeadNoScript, + [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInHeadNoScript, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype, + [Tokenizer.START_TAG_TOKEN]: startTagInHeadNoScript, + [Tokenizer.END_TAG_TOKEN]: endTagInHeadNoScript, + [Tokenizer.EOF_TOKEN]: tokenInHeadNoScript + }, + [AFTER_HEAD_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: tokenAfterHead, + [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterHead, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype, + [Tokenizer.START_TAG_TOKEN]: startTagAfterHead, + [Tokenizer.END_TAG_TOKEN]: endTagAfterHead, + [Tokenizer.EOF_TOKEN]: tokenAfterHead + }, + [IN_BODY_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: characterInBody, + [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagInBody, + [Tokenizer.END_TAG_TOKEN]: endTagInBody, + [Tokenizer.EOF_TOKEN]: eofInBody + }, + [TEXT_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: insertCharacters, + [Tokenizer.NULL_CHARACTER_TOKEN]: insertCharacters, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, + [Tokenizer.COMMENT_TOKEN]: ignoreToken, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: ignoreToken, + [Tokenizer.END_TAG_TOKEN]: endTagInText, + [Tokenizer.EOF_TOKEN]: eofInText + }, + [IN_TABLE_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: characterInTable, + [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagInTable, + [Tokenizer.END_TAG_TOKEN]: endTagInTable, + [Tokenizer.EOF_TOKEN]: eofInBody + }, + [IN_TABLE_TEXT_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: characterInTableText, + [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInTableText, + [Tokenizer.COMMENT_TOKEN]: tokenInTableText, + [Tokenizer.DOCTYPE_TOKEN]: tokenInTableText, + [Tokenizer.START_TAG_TOKEN]: tokenInTableText, + [Tokenizer.END_TAG_TOKEN]: tokenInTableText, + [Tokenizer.EOF_TOKEN]: tokenInTableText + }, + [IN_CAPTION_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: characterInBody, + [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagInCaption, + [Tokenizer.END_TAG_TOKEN]: endTagInCaption, + [Tokenizer.EOF_TOKEN]: eofInBody + }, + [IN_COLUMN_GROUP_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: tokenInColumnGroup, + [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInColumnGroup, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagInColumnGroup, + [Tokenizer.END_TAG_TOKEN]: endTagInColumnGroup, + [Tokenizer.EOF_TOKEN]: eofInBody + }, + [IN_TABLE_BODY_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: characterInTable, + [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagInTableBody, + [Tokenizer.END_TAG_TOKEN]: endTagInTableBody, + [Tokenizer.EOF_TOKEN]: eofInBody + }, + [IN_ROW_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: characterInTable, + [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagInRow, + [Tokenizer.END_TAG_TOKEN]: endTagInRow, + [Tokenizer.EOF_TOKEN]: eofInBody + }, + [IN_CELL_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: characterInBody, + [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagInCell, + [Tokenizer.END_TAG_TOKEN]: endTagInCell, + [Tokenizer.EOF_TOKEN]: eofInBody + }, + [IN_SELECT_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: insertCharacters, + [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagInSelect, + [Tokenizer.END_TAG_TOKEN]: endTagInSelect, + [Tokenizer.EOF_TOKEN]: eofInBody + }, + [IN_SELECT_IN_TABLE_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: insertCharacters, + [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagInSelectInTable, + [Tokenizer.END_TAG_TOKEN]: endTagInSelectInTable, + [Tokenizer.EOF_TOKEN]: eofInBody + }, + [IN_TEMPLATE_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: characterInBody, + [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagInTemplate, + [Tokenizer.END_TAG_TOKEN]: endTagInTemplate, + [Tokenizer.EOF_TOKEN]: eofInTemplate + }, + [AFTER_BODY_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: tokenAfterBody, + [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterBody, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, + [Tokenizer.COMMENT_TOKEN]: appendCommentToRootHtmlElement, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagAfterBody, + [Tokenizer.END_TAG_TOKEN]: endTagAfterBody, + [Tokenizer.EOF_TOKEN]: stopParsing + }, + [IN_FRAMESET_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagInFrameset, + [Tokenizer.END_TAG_TOKEN]: endTagInFrameset, + [Tokenizer.EOF_TOKEN]: stopParsing + }, + [AFTER_FRAMESET_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, + [Tokenizer.COMMENT_TOKEN]: appendComment, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagAfterFrameset, + [Tokenizer.END_TAG_TOKEN]: endTagAfterFrameset, + [Tokenizer.EOF_TOKEN]: stopParsing + }, + [AFTER_AFTER_BODY_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: tokenAfterAfterBody, + [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterAfterBody, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, + [Tokenizer.COMMENT_TOKEN]: appendCommentToDocument, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagAfterAfterBody, + [Tokenizer.END_TAG_TOKEN]: tokenAfterAfterBody, + [Tokenizer.EOF_TOKEN]: stopParsing + }, + [AFTER_AFTER_FRAMESET_MODE]: { + [Tokenizer.CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, + [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, + [Tokenizer.COMMENT_TOKEN]: appendCommentToDocument, + [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, + [Tokenizer.START_TAG_TOKEN]: startTagAfterAfterFrameset, + [Tokenizer.END_TAG_TOKEN]: ignoreToken, + [Tokenizer.EOF_TOKEN]: stopParsing + } + }; + + //Parser + class Parser { + constructor(options) { + this.options = mergeOptions(DEFAULT_OPTIONS, options); + + this.treeAdapter = this.options.treeAdapter; + this.pendingScript = null; + + if (this.options.sourceCodeLocationInfo) { + Mixin.install(this, LocationInfoParserMixin); + } + + if (this.options.onParseError) { + Mixin.install(this, ErrorReportingParserMixin, { onParseError: this.options.onParseError }); + } + } + + // API + parse(html) { + const document = this.treeAdapter.createDocument(); + + this._bootstrap(document, null); + this.tokenizer.write(html, true); + this._runParsingLoop(null); + + return document; + } + + parseFragment(html, fragmentContext) { + //NOTE: use