fix: sendMessage promise should resolve to undefined when no listeners reply
This commit is contained in:
parent
7ff6e8a1dc
commit
4e1e98add2
|
@ -7,6 +7,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
if (typeof browser === "undefined") {
|
if (typeof browser === "undefined") {
|
||||||
|
const CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE = "The message port closed before a response was received.";
|
||||||
const SEND_RESPONSE_DEPRECATION_WARNING = `
|
const SEND_RESPONSE_DEPRECATION_WARNING = `
|
||||||
Returning a Promise is the preferred way to send a reply from an
|
Returning a Promise is the preferred way to send a reply from an
|
||||||
onMessage/onMessageExternal listener, as the sendResponse will be
|
onMessage/onMessageExternal listener, as the sendResponse will be
|
||||||
|
@ -446,7 +447,14 @@ if (typeof browser === "undefined") {
|
||||||
|
|
||||||
const wrappedSendMessageCallback = ({reject, resolve}, reply) => {
|
const wrappedSendMessageCallback = ({reject, resolve}, reply) => {
|
||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
reject(chrome.runtime.lastError);
|
// Detect when none of the listers replied to the sendMessage call and resolve
|
||||||
|
// the promise to undefined as in Firefox.
|
||||||
|
// See https://github.com/mozilla/webextension-polyfill/issues/130
|
||||||
|
if (chrome.runtime.lastError.message === CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE) {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject(chrome.runtime.lastError);
|
||||||
|
}
|
||||||
} 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
|
||||||
// an Error instance.
|
// an Error instance.
|
||||||
|
|
|
@ -45,6 +45,9 @@ browser.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||||
case "test - sendMessage with listener callback throws":
|
case "test - sendMessage with listener callback throws":
|
||||||
throw new Error("listener throws");
|
throw new Error("listener throws");
|
||||||
|
|
||||||
|
case "test - sendMessage and no listener answers":
|
||||||
|
return undefined;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return Promise.resolve(
|
return Promise.resolve(
|
||||||
`Unxpected message received by the background page: ${JSON.stringify(msg)}\n`);
|
`Unxpected message received by the background page: ${JSON.stringify(msg)}\n`);
|
||||||
|
@ -52,6 +55,10 @@ browser.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
browser.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
browser.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||||
|
if (msg === "test - sendMessage and no listener answers") {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
sendResponse("second listener reply");
|
sendResponse("second listener reply");
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
|
@ -75,3 +75,8 @@ test("sendMessage with listener callback throws", async (t) => {
|
||||||
t.equal(err.message, "listener throws", "Got an error with the expected message");
|
t.equal(err.message, "listener throws", "Got an error with the expected message");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("sendMessage and no listener answers", async (t) => {
|
||||||
|
const reply = await browser.runtime.sendMessage("test - sendMessage and no listener answers");
|
||||||
|
t.equal(reply, undefined, "Got undefined reply as expected");
|
||||||
|
});
|
||||||
|
|
|
@ -238,5 +238,30 @@ describe("browser-polyfill", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("resolves to undefined when no listeners reply", () => {
|
||||||
|
const fakeChrome = {
|
||||||
|
runtime: {
|
||||||
|
// This error message is defined as CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE
|
||||||
|
// in the polyfill sources and it is used to recognize when Chrome has detected that
|
||||||
|
// none of the listeners replied.
|
||||||
|
lastError: {
|
||||||
|
message: "The message port closed before a response was received.",
|
||||||
|
},
|
||||||
|
sendMessage: sinon.stub(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
fakeChrome.runtime.sendMessage.onFirstCall().callsArgWith(1, [undefined]);
|
||||||
|
|
||||||
|
return setupTestDOMWindow(fakeChrome).then(window => {
|
||||||
|
const promise = window.browser.runtime.sendMessage("some_message");
|
||||||
|
ok(fakeChrome.runtime.sendMessage.calledOnce, "sendMessage has been called once");
|
||||||
|
|
||||||
|
return promise.then(reply => {
|
||||||
|
deepEqual(reply, undefined, "sendMessage promise should be resolved to undefined");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue