diff --git a/manifest.json b/manifest.json index 592097a..fd584c9 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "name": "Three.js Developer Tools", - "version": "0.4.0", + "version": "0.4.1", "description": "Developer tools for 3D library three.js.", "devtools_page": "src/extension/devtools.html", "background": { @@ -37,4 +37,4 @@ "id": "three-devtools@jsantell.com" } } -} +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 57871c5..8513b3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,341 @@ { "name": "three-devtools", "version": "0.4.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "three-devtools", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@egjs/agent": "2.1.5", + "lit-element": "2.2.1", + "lit-html": "1.1.2", + "three": "0.137.0", + "webextension-polyfill": "^0.9.0" + }, + "devDependencies": { + "http-server": "^0.12.0", + "json": "10.0.0" + } + }, + "node_modules/@egjs/agent": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@egjs/agent/-/agent-2.1.5.tgz", + "integrity": "sha512-PfdMXd+4WiZN9Xcc1MU31w/RSi6GK6hgufuADRKNY60nXvT34dnXaIyEQlTBkviDfYSOZ8kYW66udyiEMcpqVA==" + }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/basic-auth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", + "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/ecstatic": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", + "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", + "deprecated": "This package is unmaintained and deprecated. See the GH Issue 259.", + "dev": true, + "dependencies": { + "he": "^1.1.1", + "mime": "^1.6.0", + "minimist": "^1.1.0", + "url-join": "^2.0.5" + }, + "bin": { + "ecstatic": "lib/ecstatic.js" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", + "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.14.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-server": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.0.tgz", + "integrity": "sha512-imGLDSTT1BZ0QG1rBFnaZ6weK5jeisUnCxZQI1cpYTdz0luPUM5e3s+WU5zRWEkiI6DQxL2p54oeKrDlzO6bRw==", + "dev": true, + "dependencies": { + "basic-auth": "^1.0.3", + "colors": "^1.3.3", + "corser": "^2.0.1", + "ecstatic": "^3.3.2", + "http-proxy": "^1.17.0", + "opener": "^1.5.1", + "optimist": "~0.6.1", + "portfinder": "^1.0.20", + "secure-compare": "3.0.1", + "union": "~0.5.0" + }, + "bin": { + "hs": "bin/http-server", + "http-server": "bin/http-server" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/json/-/json-10.0.0.tgz", + "integrity": "sha512-iK7tAZtpoghibjdB1ncCWykeBMmke3JThUe+rnkD4qkZaglOIQ70Pw7r5UJ4lyUT+7gnw7ehmmLUHDuhqzQD+g==", + "dev": true, + "bin": { + "json": "lib/json.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lit-element": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-2.2.1.tgz", + "integrity": "sha512-ipDcgQ1EpW6Va2Z6dWm79jYdimVepO5GL0eYkZrFvdr0OD/1N260Q9DH+K5HXHFrRoC7dOg+ZpED2XE0TgGdXw==", + "dependencies": { + "lit-html": "^1.0.0" + } + }, + "node_modules/lit-html": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-1.1.2.tgz", + "integrity": "sha512-FFlUMKHKi+qG1x1iHNZ1hrtc/zHmfYTyrSvs3/wBTvaNtpZjOZGWzU7efGYVpgp6KvWeKF6ql9/KsCq6Z/mEDA==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp/node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/opener": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", + "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==", + "dev": true, + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "dependencies": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "node_modules/optimist/node_modules/minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "node_modules/portfinder": { + "version": "1.0.25", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz", + "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==", + "dev": true, + "dependencies": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.1" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/qs": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.1.tgz", + "integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==", + "dev": true, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "node_modules/secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=", + "dev": true + }, + "node_modules/three": { + "version": "0.137.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.137.0.tgz", + "integrity": "sha512-rzSDhia6cU35UCy6y+zEEws6vSgytfHqFMSaBvUcySgzwvDO6vETyswtSNi/+aVqJw8WLMwyT1mlQQ1T/dxxOA==" + }, + "node_modules/union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "dev": true, + "dependencies": { + "qs": "^6.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/url-join": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", + "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", + "dev": true + }, + "node_modules/webextension-polyfill": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.9.0.tgz", + "integrity": "sha512-LTtHb0yR49xa9irkstDxba4GATDAcDw3ncnFH9RImoFwDlW47U95ME5sn5IiQX2ghfaECaf6xyXM8yvClIBkkw==" + }, + "node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + } + }, "dependencies": { "@egjs/agent": { "version": "2.1.5", @@ -238,9 +571,9 @@ "dev": true }, "webextension-polyfill": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.4.0.tgz", - "integrity": "sha512-oreMp+EoAo1pzRMigx4jB5jInIpx6NTCySPSjGyLLee/dCIPiRqowCEfbFP8o20wz9SOtNwSsfkaJ9D/tRgpag==" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.9.0.tgz", + "integrity": "sha512-LTtHb0yR49xa9irkstDxba4GATDAcDw3ncnFH9RImoFwDlW47U95ME5sn5IiQX2ghfaECaf6xyXM8yvClIBkkw==" }, "wordwrap": { "version": "0.0.3", diff --git a/package.json b/package.json index c4b45ea..dd391d9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "three-devtools", "private": true, - "version": "0.4.0", + "version": "0.4.1", "description": "three.js developer tools web extension", "scripts": { "build:source": "./scripts/build-source.sh", @@ -27,7 +27,7 @@ "lit-element": "2.2.1", "lit-html": "1.1.2", "three": "0.137.0", - "webextension-polyfill": "0.4.0" + "webextension-polyfill": "^0.9.0" }, "devDependencies": { "http-server": "^0.12.0", diff --git a/src/app/index.html b/src/app/index.html index ce032f4..25f1e62 100644 --- a/src/app/index.html +++ b/src/app/index.html @@ -8,8 +8,10 @@ - - - + + + + + diff --git a/src/app/index.js b/src/app/index.js index 7207d6f..49fd85a 100644 --- a/src/app/index.js +++ b/src/app/index.js @@ -1,4 +1,3 @@ -import browser from '../../web_modules/webextension-polyfill/dist/browser-polyfill.js'; import getAgent from '../../web_modules/@egjs/agent.js'; import AppElement from './elements/AppElement.js'; @@ -26,7 +25,6 @@ import DevtoolsIconButtonElement from './common-elements/DevtoolsIconButtonEleme import IconElement from './common-elements/IconElement.js'; ////// -globalThis.browser = browser; window.customElements.define('three-devtools-app', AppElement); diff --git a/src/app/injection.js b/src/app/injection.js index a68056b..45b8289 100644 --- a/src/app/injection.js +++ b/src/app/injection.js @@ -1,20 +1,18 @@ -import browser from '../../web_modules/webextension-polyfill/dist/browser-polyfill.js'; -import utils from '../content/utils.js'; -import TransformControls from '../content/TransformControls.js'; -import EntityCache from '../content/EntityCache.js'; -import ThreeDevTools from '../content/ThreeDevTools.js'; -import DevToolsScene from '../content/DevToolsScene.js'; -import InstrumentedToJSON from '../content/toJSON.js'; -import THREE from '../content/three.js'; +import utils from "../content/utils.js"; +import TransformControls from "../content/TransformControls.js"; +import EntityCache from "../content/EntityCache.js"; +import ThreeDevTools from "../content/ThreeDevTools.js"; +import DevToolsScene from "../content/DevToolsScene.js"; +import InstrumentedToJSON from "../content/toJSON.js"; +import THREE from "../content/three.js"; -const version = browser.runtime.getManifest().version; -const red = 'rgb(255, 137, 137)'; -const green = 'rgb(190, 251, 125)' -const blue = 'rgb(120, 250, 228)'; +const red = "rgb(255, 137, 137)"; +const green = "rgb(190, 251, 125)"; +const blue = "rgb(120, 250, 228)"; export default ` -console.log('%c▲%cthree-devtools%cv${version}', +console.log('%c▲%cthree-devtools%c', 'font-size:150%; color:${green}; text-shadow: -10px 0px ${red}, 10px 0px ${blue}; padding: 0 15px 0 10px;', 'font-size: 110%; background-color: #666; color:white; padding: 0 5px;', 'font-size: 110%; background-color: ${blue}; color:#666; padding: 0 5px;'); diff --git a/src/extension/background.html b/src/extension/background.html index 2d0fb68..be625d1 100644 --- a/src/extension/background.html +++ b/src/extension/background.html @@ -1 +1,2 @@ + diff --git a/src/extension/background.js b/src/extension/background.js index 00ee949..ab75871 100644 --- a/src/extension/background.js +++ b/src/extension/background.js @@ -1,6 +1,3 @@ -import browser from '../../web_modules/webextension-polyfill/dist/browser-polyfill.js'; -globalThis.browser = browser; - const connections = new Map(); /** @@ -15,7 +12,7 @@ browser.runtime.onConnect.addListener(port => { if (message.name === 'connect') { connections.set(tabId, port); } - } + }; port.onMessage.addListener(onMessage); @@ -43,12 +40,12 @@ browser.runtime.onMessage.addListener((request, sender) => { * When a page has reloaded; if three-devtools are open, notify * the devtools panel so it can inject the content-side of the tools. */ -browser.webNavigation.onCommitted.addListener(({tabId, frameId}) => { +browser.webNavigation.onDOMContentLoaded.addListener(({ tabId, frameId }) => { // Only support top-level frame for now if (frameId !== 0) { return; } - console.log('onCommitted', tabId, connections.has(tabId)); + console.log('onDOMContentLoaded', tabId, connections.has(tabId)); if (connections.has(tabId)) { connections.get(tabId).postMessage({ type: 'committed', diff --git a/src/extension/devtools.html b/src/extension/devtools.html index 87c7f2e..39cc9b5 100644 --- a/src/extension/devtools.html +++ b/src/extension/devtools.html @@ -1 +1,2 @@ + diff --git a/src/extension/devtools.js b/src/extension/devtools.js index 08541ba..65eeb3e 100644 --- a/src/extension/devtools.js +++ b/src/extension/devtools.js @@ -1,6 +1,3 @@ -import browser from '../../web_modules/webextension-polyfill/dist/browser-polyfill.js'; -globalThis.browser = browser; - if (browser.devtools.inspectedWindow.tabId) { // As of now, only inspect content windows, not when // debugging a devtools panel for example. diff --git a/web_modules/webextension-polyfill/dist/browser-polyfill.js b/web_modules/webextension-polyfill/dist/browser-polyfill.js index f5e44da..237dcfd 100644 --- a/web_modules/webextension-polyfill/dist/browser-polyfill.js +++ b/web_modules/webextension-polyfill/dist/browser-polyfill.js @@ -1,25 +1,39 @@ -var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - -function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; -} - -var browserPolyfill = createCommonjsModule(function (module, exports) { (function (global, factory) { - { + if (typeof define === "function" && define.amd) { + define("webextension-polyfill", ["module"], factory); + } else if (typeof exports !== "undefined") { factory(module); + } else { + var mod = { + exports: {} + }; + factory(mod); + global.browser = mod.exports; } -})(commonjsGlobal, function (module) { +})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (module) { + /* webextension-polyfill - v0.9.0 - Fri Mar 25 2022 17:00:23 */ - if (typeof browser === "undefined" || Object.getPrototypeOf(browser) !== Object.prototype) { - const CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE = "The message port closed before a response was received."; - const SEND_RESPONSE_DEPRECATION_WARNING = "Returning a Promise is the preferred way to send a reply from an onMessage/onMessageExternal listener, as the sendResponse will be removed from the specs (See https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage)"; + /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ + + /* vim: set sts=2 sw=2 et tw=80: */ + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; - // Wrapping the bulk of this polyfill in a one-time-use function is a minor + if (typeof globalThis != "object" || typeof chrome != "object" || !chrome || !chrome.runtime || !chrome.runtime.id) { + throw new Error("This script should only be loaded in a browser extension."); + } + + if (typeof globalThis.browser === "undefined" || Object.getPrototypeOf(globalThis.browser) !== Object.prototype) { + const CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE = "The message port closed before a response was received."; + const SEND_RESPONSE_DEPRECATION_WARNING = "Returning a Promise is the preferred way to send a reply from an onMessage/onMessageExternal listener, as the sendResponse will be removed from the specs (See https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage)"; // Wrapping the bulk of this polyfill in a one-time-use function is a minor // optimization for Firefox. Since Spidermonkey does not fully parse the // contents of a function until the first time it's called, and since it will // never actually need to be called, this allows the polyfill to be included // in Firefox nearly for free. + const wrapAPIs = extensionAPIs => { // NOTE: apiMetadata is associated to the content of the api-metadata.json file // at build time by replacing the following "include" with the content of the @@ -242,6 +256,12 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { "minArgs": 3, "maxArgs": 3, "singleCallbackArg": true + }, + "elements": { + "createSidebarPane": { + "minArgs": 1, + "maxArgs": 1 + } } } }, @@ -448,10 +468,6 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { "minArgs": 0, "maxArgs": 0 }, - "getBrowserInfo": { - "minArgs": 0, - "maxArgs": 0 - }, "getPlatformInfo": { "minArgs": 0, "maxArgs": 0 @@ -588,6 +604,14 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { "minArgs": 0, "maxArgs": 1 }, + "goBack": { + "minArgs": 0, + "maxArgs": 1 + }, + "goForward": { + "minArgs": 0, + "maxArgs": 1 + }, "highlight": { "minArgs": 1, "maxArgs": 1 @@ -690,7 +714,6 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { if (Object.keys(apiMetadata).length === 0) { throw new Error("api-metadata.json has not been included in browser-polyfill"); } - /** * A WeakMap subclass which creates and stores a value for any key which does * not exist when accessed, but behaves exactly as an ordinary WeakMap @@ -701,6 +724,8 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { * key which does not exist, the first time it is accessed. The * function receives, as its only argument, the key being created. */ + + class DefaultWeakMap extends WeakMap { constructor(createItem, items = undefined) { super(items); @@ -714,8 +739,8 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { return super.get(key); } - } + } /** * Returns true if the given object is an object with a `then` method, and can * therefore be assumed to behave as a Promise. @@ -723,10 +748,11 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { * @param {*} value The value to test. * @returns {boolean} True if the value is thenable. */ + + const isThenable = value => { return value && typeof value === "object" && typeof value.then === "function"; }; - /** * Creates and returns a function which, when called, will resolve or reject * the given promise based on how it is called: @@ -743,21 +769,27 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { * promise. * @param {function} promise.resolve * The promise's resolution function. - * @param {function} promise.rejection + * @param {function} promise.reject * The promise's rejection function. * @param {object} metadata * Metadata about the wrapped method which has created the callback. - * @param {integer} metadata.maxResolvedArgs - * The maximum number of arguments which may be passed to the - * callback created by the wrapped async function. + * @param {boolean} metadata.singleCallbackArg + * Whether or not the promise is resolved with only the first + * argument of the callback, alternatively an array of all the + * callback arguments is resolved. By default, if the callback + * function is invoked with only a single argument, that will be + * resolved to the promise, while all arguments will be resolved as + * an array if multiple are given. * * @returns {function} * The generated callback function. */ + + const makeCallback = (promise, metadata) => { return (...callbackArgs) => { if (extensionAPIs.runtime.lastError) { - promise.reject(extensionAPIs.runtime.lastError); + promise.reject(new Error(extensionAPIs.runtime.lastError.message)); } else if (metadata.singleCallbackArg || callbackArgs.length <= 1 && metadata.singleCallbackArg !== false) { promise.resolve(callbackArgs[0]); } else { @@ -767,7 +799,6 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { }; const pluralizeArguments = numArgs => numArgs == 1 ? "argument" : "arguments"; - /** * Creates a wrapper function for a method with the given name and metadata. * @@ -783,13 +814,19 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { * The maximum number of arguments which may be passed to the * function. If called with more than this number of arguments, the * wrapper will raise an exception. - * @param {integer} metadata.maxResolvedArgs - * The maximum number of arguments which may be passed to the - * callback created by the wrapped async function. + * @param {boolean} metadata.singleCallbackArg + * Whether or not the promise is resolved with only the first + * argument of the callback, alternatively an array of all the + * callback arguments is resolved. By default, if the callback + * function is invoked with only a single argument, that will be + * resolved to the promise, while all arguments will be resolved as + * an array if multiple are given. * * @returns {function(object, ...*)} * The generated wrapper function. */ + + const wrapAsyncFunction = (name, metadata) => { return function asyncFunctionWrapper(target, ...args) { if (args.length < metadata.minArgs) { @@ -806,29 +843,31 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { // and so the polyfill will try to call it with a callback first, and it will fallback // to not passing the callback if the first call fails. try { - target[name](...args, makeCallback({ resolve, reject }, metadata)); + target[name](...args, makeCallback({ + resolve, + reject + }, metadata)); } catch (cbError) { console.warn(`${name} API method doesn't seem to support the callback parameter, ` + "falling back to call it without a callback: ", cbError); - - target[name](...args); - - // Update the API method metadata, so that the next API calls will not try to + target[name](...args); // Update the API method metadata, so that the next API calls will not try to // use the unsupported callback anymore. + metadata.fallbackToNoCallback = false; metadata.noCallback = true; - resolve(); } } else if (metadata.noCallback) { target[name](...args); resolve(); } else { - target[name](...args, makeCallback({ resolve, reject }, metadata)); + target[name](...args, makeCallback({ + resolve, + reject + }, metadata)); } }); }; }; - /** * Wraps an existing method of the target object, so that calls to it are * intercepted by the given wrapper function. The wrapper function receives, @@ -848,16 +887,18 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { * A Proxy object for the given method, which invokes the given wrapper * method in its place. */ + + const wrapMethod = (target, method, wrapper) => { return new Proxy(method, { apply(targetMethod, thisObj, args) { return wrapper.call(thisObj, target, ...args); } + }); }; let hasOwnProperty = Function.call.bind(Object.prototype.hasOwnProperty); - /** * Wraps an object in a Proxy which intercepts and wraps certain methods * based on the given `wrappers` and `metadata` objects. @@ -881,6 +922,7 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { * * @returns {Proxy} */ + const wrapObject = (target, wrappers = {}, metadata = {}) => { let cache = Object.create(null); let handlers = { @@ -902,7 +944,6 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { if (typeof value === "function") { // This is a method on the underlying object. Check if we need to do // any wrapping. - if (typeof wrappers[prop] === "function") { // We have a special-case wrapper for this method. value = wrapMethod(target, target[prop], wrappers[prop]); @@ -921,20 +962,25 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { // of. Create a sub-object wrapper for it with the appropriate child // metadata. value = wrapObject(value, wrappers[prop], metadata[prop]); + } else if (hasOwnProperty(metadata, "*")) { + // Wrap all properties in * namespace. + value = wrapObject(value, wrappers[prop], metadata["*"]); } else { // We don't need to do any wrapping for this property, // so just forward all access to the underlying object. Object.defineProperty(cache, prop, { configurable: true, enumerable: true, + get() { return target[prop]; }, + set(value) { target[prop] = value; } - }); + }); return value; } @@ -948,6 +994,7 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { } else { target[prop] = value; } + return true; }, @@ -958,9 +1005,8 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { deleteProperty(proxyTarget, prop) { return Reflect.deleteProperty(cache, prop); } - }; - // Per contract of the Proxy API, the "get" proxy handler must return the + }; // Per contract of the Proxy API, the "get" proxy handler must return the // original value of the target if that value is declared read-only and // non-configurable. For this reason, we create an object with the // prototype set to `target` instead of using `target` directly. @@ -970,10 +1016,10 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { // The proxy handlers themselves will still use the original `target` // instead of the `proxyTarget`, so that the methods and properties are // dereferenced via the original targets. + let proxyTarget = Object.create(target); return new Proxy(proxyTarget, handlers); }; - /** * Creates a set of wrapper functions for an event object, which handles * wrapping of listener functions that those messages are passed. @@ -990,6 +1036,8 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { * * @returns {object} */ + + const wrapEvent = wrapperMap => ({ addListener(target, listener, ...args) { target.addListener(wrapperMap.get(listener), ...args); @@ -1002,16 +1050,41 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { removeListener(target, listener) { target.removeListener(wrapperMap.get(listener)); } + }); - // Keep track if the deprecation warning has been logged at least once. - let loggedSendResponseDeprecationWarning = false; + const onRequestFinishedWrappers = new DefaultWeakMap(listener => { + if (typeof listener !== "function") { + return listener; + } + /** + * Wraps an onRequestFinished listener function so that it will return a + * `getContent()` property which returns a `Promise` rather than using a + * callback API. + * + * @param {object} req + * The HAR entry object representing the network request. + */ + + return function onRequestFinished(req) { + const wrappedReq = wrapObject(req, {} + /* wrappers */ + , { + getContent: { + minArgs: 0, + maxArgs: 0 + } + }); + listener(wrappedReq); + }; + }); // Keep track if the deprecation warning has been logged at least once. + + let loggedSendResponseDeprecationWarning = false; const onMessageWrappers = new DefaultWeakMap(listener => { if (typeof listener !== "function") { return listener; } - /** * Wraps a message listener function so that it may send responses based on * its return value, rather than by returning a sentinel value and calling a @@ -1029,9 +1102,10 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { * True if the wrapped listener returned a Promise, which will later * yield a response. False otherwise. */ + + return function onMessage(message, sender, sendResponse) { let didCallSendResponse = false; - let wrappedSendResponse; let sendResponsePromise = new Promise(resolve => { wrappedSendResponse = function (response) { @@ -1039,31 +1113,31 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { console.warn(SEND_RESPONSE_DEPRECATION_WARNING, new Error().stack); loggedSendResponseDeprecationWarning = true; } + didCallSendResponse = true; resolve(response); }; }); - let result; + try { result = listener(message, sender, wrappedSendResponse); } catch (err) { result = Promise.reject(err); } - const isResultThenable = result !== true && isThenable(result); - - // If the listener didn't returned true or a Promise, or called + const isResultThenable = result !== true && isThenable(result); // If the listener didn't returned true or a Promise, or called // wrappedSendResponse synchronously, we can exit earlier // because there will be no response sent from this listener. + if (result !== true && !isResultThenable && !didCallSendResponse) { return false; - } - - // A small helper to send the message if the promise resolves + } // A small helper to send the message if the promise resolves // and an error if the promise rejects (a wrapped sendMessage has // to translate the message into a resolved promise or a rejected // promise). + + const sendPromisedResult = promise => { promise.then(msg => { // send the message value. @@ -1072,6 +1146,7 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { // Send a JSON representation of the error if the rejected value // is an instance of error, or the object itself otherwise. let message; + if (error && (error instanceof Error || typeof error.message === "string")) { message = error.message; } else { @@ -1086,23 +1161,26 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { // Print an error on the console if unable to send the response. console.error("Failed to send onMessage rejected reply", err); }); - }; - - // If the listener returned a Promise, send the resolved value as a + }; // If the listener returned a Promise, send the resolved value as a // result, otherwise wait the promise related to the wrappedSendResponse // callback to resolve and send it as a response. + + if (isResultThenable) { sendPromisedResult(result); } else { sendPromisedResult(sendResponsePromise); - } + } // Let Chrome know that the listener is replying. + - // Let Chrome know that the listener is replying. return true; }; }); - const wrappedSendMessageCallback = ({ reject, resolve }, reply) => { + const wrappedSendMessageCallback = ({ + reject, + resolve + }, reply) => { if (extensionAPIs.runtime.lastError) { // Detect when none of the listeners replied to the sendMessage call and resolve // the promise to undefined as in Firefox. @@ -1110,7 +1188,7 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { if (extensionAPIs.runtime.lastError.message === CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE) { resolve(); } else { - reject(extensionAPIs.runtime.lastError); + reject(new Error(extensionAPIs.runtime.lastError.message)); } } else if (reply && reply.__mozWebExtensionPolyfillReject__) { // Convert back the JSON representation of the error into @@ -1131,52 +1209,69 @@ var browserPolyfill = createCommonjsModule(function (module, exports) { } return new Promise((resolve, reject) => { - const wrappedCb = wrappedSendMessageCallback.bind(null, { resolve, reject }); + const wrappedCb = wrappedSendMessageCallback.bind(null, { + resolve, + reject + }); args.push(wrappedCb); apiNamespaceObj.sendMessage(...args); }); }; const staticWrappers = { + devtools: { + network: { + onRequestFinished: wrapEvent(onRequestFinishedWrappers) + } + }, runtime: { onMessage: wrapEvent(onMessageWrappers), onMessageExternal: wrapEvent(onMessageWrappers), - sendMessage: wrappedSendMessage.bind(null, "sendMessage", { minArgs: 1, maxArgs: 3 }) + sendMessage: wrappedSendMessage.bind(null, "sendMessage", { + minArgs: 1, + maxArgs: 3 + }) }, tabs: { - sendMessage: wrappedSendMessage.bind(null, "sendMessage", { minArgs: 2, maxArgs: 3 }) + sendMessage: wrappedSendMessage.bind(null, "sendMessage", { + minArgs: 2, + maxArgs: 3 + }) } }; const settingMetadata = { - clear: { minArgs: 1, maxArgs: 1 }, - get: { minArgs: 1, maxArgs: 1 }, - set: { minArgs: 1, maxArgs: 1 } + clear: { + minArgs: 1, + maxArgs: 1 + }, + get: { + minArgs: 1, + maxArgs: 1 + }, + set: { + minArgs: 1, + maxArgs: 1 + } }; apiMetadata.privacy = { network: { - networkPredictionEnabled: settingMetadata, - webRTCIPHandlingPolicy: settingMetadata + "*": settingMetadata }, services: { - passwordSavingEnabled: settingMetadata + "*": settingMetadata }, websites: { - hyperlinkAuditingEnabled: settingMetadata, - referrersEnabled: settingMetadata + "*": settingMetadata } }; - return wrapObject(extensionAPIs, staticWrappers, apiMetadata); - }; - - // The build process adds a UMD wrapper around this file, which makes the + }; // The build process adds a UMD wrapper around this file, which makes the // `module` variable available. + + module.exports = wrapAPIs(chrome); } else { - module.exports = browser; + module.exports = globalThis.browser; } }); - -}); - -export default browserPolyfill; +//# sourceMappingURL=browser-polyfill.js.map