update polyfill for Chrome>=55

This commit is contained in:
tophf 2020-10-07 23:27:38 +03:00
parent 7c205880d2
commit a01bd3cd61
3 changed files with 28 additions and 97 deletions

View File

@ -12,7 +12,6 @@ createAPI({
compileUsercss, compileUsercss,
parseUsercssMeta(text, indexOffset = 0) { parseUsercssMeta(text, indexOffset = 0) {
loadScript( loadScript(
'/js/polyfill.js',
'/vendor/usercss-meta/usercss-meta.min.js', '/vendor/usercss-meta/usercss-meta.min.js',
'/vendor-overwrites/colorpicker/colorconverter.js', '/vendor-overwrites/colorpicker/colorconverter.js',
'/js/meta-parser.js' '/js/meta-parser.js'
@ -21,7 +20,6 @@ createAPI({
}, },
nullifyInvalidVars(vars) { nullifyInvalidVars(vars) {
loadScript( loadScript(
'/js/polyfill.js',
'/vendor/usercss-meta/usercss-meta.min.js', '/vendor/usercss-meta/usercss-meta.min.js',
'/vendor-overwrites/colorpicker/colorconverter.js', '/vendor-overwrites/colorpicker/colorconverter.js',
'/js/meta-parser.js' '/js/meta-parser.js'

View File

@ -16,7 +16,6 @@ createAPI({
}, },
metalint: code => { metalint: code => {
loadScript( loadScript(
'/js/polyfill.js',
'/vendor/usercss-meta/usercss-meta.min.js', '/vendor/usercss-meta/usercss-meta.min.js',
'/vendor-overwrites/colorpicker/colorconverter.js', '/vendor-overwrites/colorpicker/colorconverter.js',
'/js/meta-parser.js' '/js/meta-parser.js'

View File

@ -3,27 +3,33 @@
// eslint-disable-next-line no-unused-expressions // eslint-disable-next-line no-unused-expressions
self.INJECTED !== 1 && (() => { self.INJECTED !== 1 && (() => {
// this part runs in workers, content scripts, our extension pages //#region for content scripts and our extension pages
if (!Object.entries) { if (!window.browser || !browser.runtime) {
Object.entries = obj => Object.keys(obj).map(k => [k, obj[k]]); 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`. /* Promisifies the specified `chrome` methods into `browser`.
The definitions is an object like this: { The definitions is an object like this: {
'storage.sync': ['get', 'set'], // if deeper than one level, combine the path via `.` '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` 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)) { for (const [scopeName, methods] of Object.entries(definitions)) {
const path = scopeName.split('.'); const path = scopeName.split('.');
const src = path.reduce((obj, p) => obj && obj[p], chrome); const src = path.reduce((obj, p) => obj && obj[p], chrome);
@ -43,90 +49,18 @@ self.INJECTED !== 1 && (() => {
}; };
if (!chrome.tabs) return; if (!chrome.tabs) return;
// the rest is for our extension pages
if (typeof document === 'object') { //#endregion
const ELEMENT_METH = { //#region for our extension pages
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);
}
}
};
for (const [key, {base, fn}] of Object.entries(ELEMENT_METH)) { for (const storage of ['localStorage', 'sessionStorage']) {
for (const cls of base) { try {
if (cls.prototype[key]) { window[storage]._access_check = 1;
continue; delete window[storage]._access_check;
} } catch (err) {
cls.prototype[key] = function (...nodes) { Object.defineProperty(window, storage, {value: {}});
const frag = document.createDocumentFragment();
for (const node of nodes) {
frag.appendChild(typeof node === 'string' ? document.createTextNode(node) : node);
}
fn(this, frag);
};
}
} }
} }
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() { //#endregion
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)
});
}
}
})(); })();