Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 9 commits into from
Mar 18, 2021
4 changes: 2 additions & 2 deletions src/browser-polyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ if (typeof browser === "undefined" || Object.getPrototypeOf(browser) !== Object.
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]);
Expand Down Expand Up @@ -484,7 +484,7 @@ if (typeof browser === "undefined" || Object.getPrototypeOf(browser) !== Object.
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
Expand Down
19 changes: 19 additions & 0 deletions test/fixtures/detect-existing-browser-api-object/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
});

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 set an object over quota');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, the assertion message doesn't match the actual error scenario now, we could change it to t.fail('storage.sync should throw when called from an extension with a temporary id') or something like that.

(@fregante I can make the change and update this branch if you don't get to it first, in the end it is just a small nit related to an assertion message and so I don't mind if you prefer that I make the change and then land this on master).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor tweak to one of the assertion messages applied in edaa539.

} 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);
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,7 @@
]
}
],
"permissions": []
"permissions": [
"storage"
]
}
11 changes: 7 additions & 4 deletions test/test-async-functions.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"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 {setupTestDOMWindow} = require("./setup");
Expand Down Expand Up @@ -56,7 +56,7 @@ describe("browser-polyfill", () => {
it("rejects the returned promise if chrome.runtime.lastError is not null", () => {
const fakeChrome = {
runtime: {
lastError: new Error("fake lastError"),
lastError: {message: "fake lastError"},
},
tabs: {
query: sinon.stub(),
Expand All @@ -70,8 +70,11 @@ describe("browser-polyfill", () => {

return window.browser.tabs.query({active: true}).then(
() => fail("Expected a rejected promise"),
(err) => equal(err, fakeChrome.runtime.lastError,
"Got the expected error in the rejected promise")
(err) => {
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");
}
);
});
});
Expand Down