fix: Reject with real Error instances like Firefox does (#293)

Co-authored-by: Federico Brigante <me@fregante.com>
This commit is contained in:
Luca Greco 2021-03-18 18:07:16 +01:00 committed by GitHub
parent fa4b26f406
commit 5ab825b83f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 7 deletions

View File

@ -95,7 +95,7 @@ if (typeof browser === "undefined" || Object.getPrototypeOf(browser) !== Object.
const makeCallback = (promise, metadata) => { const makeCallback = (promise, metadata) => {
return (...callbackArgs) => { return (...callbackArgs) => {
if (extensionAPIs.runtime.lastError) { if (extensionAPIs.runtime.lastError) {
promise.reject(extensionAPIs.runtime.lastError); promise.reject(new Error(extensionAPIs.runtime.lastError.message));
} else if (metadata.singleCallbackArg || } else if (metadata.singleCallbackArg ||
(callbackArgs.length <= 1 && metadata.singleCallbackArg !== false)) { (callbackArgs.length <= 1 && metadata.singleCallbackArg !== false)) {
promise.resolve(callbackArgs[0]); promise.resolve(callbackArgs[0]);
@ -484,7 +484,7 @@ if (typeof browser === "undefined" || Object.getPrototypeOf(browser) !== Object.
if (extensionAPIs.runtime.lastError.message === CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE) { if (extensionAPIs.runtime.lastError.message === CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE) {
resolve(); resolve();
} else { } else {
reject(extensionAPIs.runtime.lastError); reject(new Error(extensionAPIs.runtime.lastError.message));
} }
} else if (reply && reply.__mozWebExtensionPolyfillReject__) { } else if (reply && reply.__mozWebExtensionPolyfillReject__) {
// Convert back the JSON representation of the error into // Convert back the JSON representation of the error into

View File

@ -33,3 +33,22 @@ test("browser api object in background page", async (t) => {
t.ok(!reply.windowBrowserIsUnchanged, "window.browser API object should have been defined by the polyfill"); t.ok(!reply.windowBrowserIsUnchanged, "window.browser API object should have been defined by the polyfill");
} }
}); });
test("error types", async (t) => {
if (navigator.userAgent.includes("Firefox/")) {
try {
await browser.storage.sync.set({a: 'a'});
t.fail('It should throw when attempting to call storage.sync with a temporary addon ID');
} catch (error) {
t.equal(error.message, 'The storage API will not work with a temporary addon ID. Please add an explicit addon ID to your manifest. For more information see https://mzl.la/3lPk1aE.');
t.ok(error instanceof Error);
}
} else {
await new Promise(resolve => {
chrome.storage.local.set({a: 'a'.repeat(10000000)}, resolve);
});
t.ok(chrome.runtime.lastError, 'It should throw when attempting to set an object over quota');
t.equal(chrome.runtime.lastError.message, 'QUOTA_BYTES quota exceeded');
t.notOk(chrome.runtime.lastError instanceof Error);
}
});

View File

@ -19,5 +19,7 @@
] ]
} }
], ],
"permissions": [] "permissions": [
"storage"
]
} }

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
const {deepEqual, equal, fail, ok, throws} = require("chai").assert; const {deepEqual, equal, fail, ok, throws, instanceOf} = require("chai").assert;
const sinon = require("sinon"); const sinon = require("sinon");
const {setupTestDOMWindow} = require("./setup"); const {setupTestDOMWindow} = require("./setup");
@ -56,7 +56,7 @@ describe("browser-polyfill", () => {
it("rejects the returned promise if chrome.runtime.lastError is not null", () => { it("rejects the returned promise if chrome.runtime.lastError is not null", () => {
const fakeChrome = { const fakeChrome = {
runtime: { runtime: {
lastError: new Error("fake lastError"), lastError: {message: "fake lastError"},
}, },
tabs: { tabs: {
query: sinon.stub(), query: sinon.stub(),
@ -70,8 +70,11 @@ describe("browser-polyfill", () => {
return window.browser.tabs.query({active: true}).then( return window.browser.tabs.query({active: true}).then(
() => fail("Expected a rejected promise"), () => fail("Expected a rejected promise"),
(err) => equal(err, fakeChrome.runtime.lastError, (err) => {
"Got the expected error in the rejected promise") instanceOf(err, window.Error, "Expected the error to be an instance of Error");
equal(err.message, fakeChrome.runtime.lastError.message,
"Got the expected error in the rejected promise");
}
); );
}); });
}); });