From a01bd3cd618f2cc125fc0f4ee279434d7f4cd476 Mon Sep 17 00:00:00 2001 From: tophf Date: Wed, 7 Oct 2020 23:27:38 +0300 Subject: [PATCH] update polyfill for Chrome>=55 --- background/background-worker.js | 2 - edit/editor-worker.js | 1 - js/polyfill.js | 122 ++++++++------------------------ 3 files changed, 28 insertions(+), 97 deletions(-) diff --git a/background/background-worker.js b/background/background-worker.js index f44013e5..ddb33d53 100644 --- a/background/background-worker.js +++ b/background/background-worker.js @@ -12,7 +12,6 @@ createAPI({ compileUsercss, parseUsercssMeta(text, indexOffset = 0) { loadScript( - '/js/polyfill.js', '/vendor/usercss-meta/usercss-meta.min.js', '/vendor-overwrites/colorpicker/colorconverter.js', '/js/meta-parser.js' @@ -21,7 +20,6 @@ createAPI({ }, nullifyInvalidVars(vars) { loadScript( - '/js/polyfill.js', '/vendor/usercss-meta/usercss-meta.min.js', '/vendor-overwrites/colorpicker/colorconverter.js', '/js/meta-parser.js' diff --git a/edit/editor-worker.js b/edit/editor-worker.js index 6ef51eef..62ef380c 100644 --- a/edit/editor-worker.js +++ b/edit/editor-worker.js @@ -16,7 +16,6 @@ createAPI({ }, metalint: code => { loadScript( - '/js/polyfill.js', '/vendor/usercss-meta/usercss-meta.min.js', '/vendor-overwrites/colorpicker/colorconverter.js', '/js/meta-parser.js' diff --git a/js/polyfill.js b/js/polyfill.js index 3b22c96d..859de6e2 100644 --- a/js/polyfill.js +++ b/js/polyfill.js @@ -3,27 +3,33 @@ // eslint-disable-next-line no-unused-expressions self.INJECTED !== 1 && (() => { - // this part runs in workers, content scripts, our extension pages + //#region for content scripts and our extension pages - if (!Object.entries) { - Object.entries = obj => Object.keys(obj).map(k => [k, obj[k]]); + if (!window.browser || !browser.runtime) { + const createTrap = (base, parent) => { + const target = typeof base === 'function' ? () => {} : {}; + target.isTrap = true; + return new Proxy(target, { + get: (target, prop) => { + if (target[prop]) return target[prop]; + if (base[prop] && (typeof base[prop] === 'object' || typeof base[prop] === 'function')) { + target[prop] = createTrap(base[prop], base); + return target[prop]; + } + return base[prop]; + }, + apply: (target, thisArg, args) => base.apply(parent, args) + }); + }; + window.browser = createTrap(chrome, null); } - if (!Object.values) { - Object.values = obj => Object.keys(obj).map(k => obj[k]); - } - - // don't use self.chrome. It is undefined in Firefox - if (typeof chrome !== 'object') return; - // the rest is for content scripts and our extension pages - - self.browser = polyfillBrowser(); /* Promisifies the specified `chrome` methods into `browser`. The definitions is an object like this: { 'storage.sync': ['get', 'set'], // if deeper than one level, combine the path via `.` windows: ['create', 'update'], // items and sub-objects will only be created if present in `chrome` } */ - self.promisifyChrome = definitions => { + window.promisifyChrome = definitions => { for (const [scopeName, methods] of Object.entries(definitions)) { const path = scopeName.split('.'); const src = path.reduce((obj, p) => obj && obj[p], chrome); @@ -43,90 +49,18 @@ self.INJECTED !== 1 && (() => { }; if (!chrome.tabs) return; - // the rest is for our extension pages - if (typeof document === 'object') { - const ELEMENT_METH = { - append: { - base: [Element, Document, DocumentFragment], - fn: (node, frag) => { - node.appendChild(frag); - } - }, - prepend: { - base: [Element, Document, DocumentFragment], - fn: (node, frag) => { - node.insertBefore(frag, node.firstChild); - } - }, - before: { - base: [Element, CharacterData, DocumentType], - fn: (node, frag) => { - node.parentNode.insertBefore(frag, node); - } - }, - after: { - base: [Element, CharacterData, DocumentType], - fn: (node, frag) => { - node.parentNode.insertBefore(frag, node.nextSibling); - } - } - }; + //#endregion + //#region for our extension pages - for (const [key, {base, fn}] of Object.entries(ELEMENT_METH)) { - for (const cls of base) { - if (cls.prototype[key]) { - continue; - } - cls.prototype[key] = function (...nodes) { - const frag = document.createDocumentFragment(); - for (const node of nodes) { - frag.appendChild(typeof node === 'string' ? document.createTextNode(node) : node); - } - fn(this, frag); - }; - } + for (const storage of ['localStorage', 'sessionStorage']) { + try { + window[storage]._access_check = 1; + delete window[storage]._access_check; + } catch (err) { + Object.defineProperty(window, storage, {value: {}}); } } - try { - if (!localStorage) { - throw new Error('localStorage is null'); - } - localStorage._access_check = 1; - delete localStorage._access_check; - } catch (err) { - Object.defineProperty(self, 'localStorage', {value: {}}); - } - try { - if (!sessionStorage) { - throw new Error('sessionStorage is null'); - } - sessionStorage._access_check = 1; - delete sessionStorage._access_check; - } catch (err) { - Object.defineProperty(self, 'sessionStorage', {value: {}}); - } - function polyfillBrowser() { - if (typeof browser === 'object' && browser.runtime) { - return browser; - } - return createTrap(chrome, null); - - function createTrap(base, parent) { - const target = typeof base === 'function' ? () => {} : {}; - target.isTrap = true; - return new Proxy(target, { - get: (target, prop) => { - if (target[prop]) return target[prop]; - if (base[prop] && (typeof base[prop] === 'object' || typeof base[prop] === 'function')) { - target[prop] = createTrap(base[prop], base); - return target[prop]; - } - return base[prop]; - }, - apply: (target, thisArg, args) => base.apply(parent, args) - }); - } - } + //#endregion })();