webext-messenger 0.30.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/distribution/logging.js
CHANGED
package/distribution/receiver.js
CHANGED
@@ -12,8 +12,14 @@ export function isMessengerMessage(message) {
|
|
12
12
|
message["__webextMessenger"] === true &&
|
13
13
|
Array.isArray(message["args"]));
|
14
14
|
}
|
15
|
-
|
16
|
-
|
15
|
+
/**
|
16
|
+
* Decides what to do with a message and sends a response (value or error) back to the sender.
|
17
|
+
*
|
18
|
+
* @warn This function cannot return a Promise.
|
19
|
+
* @warn Limit the amount of logic here because errors won't make it to `sendResponse`
|
20
|
+
*/
|
21
|
+
//
|
22
|
+
function onMessageListener(message, sender, sendResponse) {
|
17
23
|
if (!isMessengerMessage(message)) {
|
18
24
|
// TODO: Add test for this eventuality: ignore unrelated messages
|
19
25
|
return;
|
@@ -28,21 +34,10 @@ function onMessageListener(message, sender) {
|
|
28
34
|
});
|
29
35
|
return;
|
30
36
|
}
|
31
|
-
return handleMessage(message, sender, action);
|
32
|
-
}
|
33
|
-
// This function can only be called when the message *will* be handled locally.
|
34
|
-
// Returning "undefined" or throwing an error will still handle it.
|
35
|
-
async function handleMessage(message, sender,
|
36
|
-
// Once messages reach this function they cannot be "ignored", they're already being handled
|
37
|
-
action) {
|
38
37
|
const { type, target, args, options = {} } = message;
|
39
38
|
const { trace = [], seq } = options;
|
40
|
-
trace.push(sender);
|
41
|
-
const meta = { trace };
|
42
|
-
let handleMessage;
|
43
39
|
if (action === "forward") {
|
44
40
|
log.debug(type, seq, "🔀 forwarded", { sender, target });
|
45
|
-
handleMessage = async () => messenger(type, meta, target, ...args);
|
46
41
|
}
|
47
42
|
else {
|
48
43
|
log.debug(type, seq, "↘️ received in", getContextName(), {
|
@@ -50,24 +45,40 @@ action) {
|
|
50
45
|
args,
|
51
46
|
wasForwarded: trace.length > 1,
|
52
47
|
});
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
}
|
60
|
-
|
48
|
+
}
|
49
|
+
// Prepare the response asynchronously because the listener must return `true` synchronously
|
50
|
+
(async () => {
|
51
|
+
try {
|
52
|
+
trace.push(sender);
|
53
|
+
const value = await prepareResponse(message, action, { trace });
|
54
|
+
log.debug(type, seq, "↗️ responding", { value });
|
55
|
+
sendResponse({ __webextMessenger, value });
|
61
56
|
}
|
62
|
-
|
57
|
+
catch (error) {
|
58
|
+
log.debug(type, seq, "↗️ responding", { error });
|
59
|
+
sendResponse({ __webextMessenger, error: serializeError(error) });
|
60
|
+
}
|
61
|
+
})();
|
62
|
+
// This indicates that the message is being handled and a response will be sent asynchronously
|
63
|
+
// TODO: Just return a promise if this is ever implemented https://issues.chromium.org/issues/40753031
|
64
|
+
return true;
|
65
|
+
}
|
66
|
+
/** Generates the value or error to return to the sender; does not include further messaging logic */
|
67
|
+
async function prepareResponse(message, action, meta) {
|
68
|
+
const { type, target, args } = message;
|
69
|
+
if (action === "forward") {
|
70
|
+
return messenger(type, meta, target, ...args);
|
71
|
+
}
|
72
|
+
const localHandler = handlers.get(type);
|
73
|
+
if (localHandler) {
|
74
|
+
return localHandler.apply(meta, args);
|
75
|
+
}
|
76
|
+
if (didUserRegisterMethods()) {
|
77
|
+
throw new MessengerError(`No handler registered for ${type} in ${getContextName()}`);
|
63
78
|
}
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
error: serializeError(error),
|
68
|
-
}));
|
69
|
-
log.debug(type, seq, "↗️ responding", response);
|
70
|
-
return { ...response, __webextMessenger };
|
79
|
+
// TODO: Test the handling of __getTabData in contexts that have no registered methods
|
80
|
+
// https://github.com/pixiebrix/webext-messenger/pull/82
|
81
|
+
throw new MessengerError(`No handlers registered in ${getContextName()}`);
|
71
82
|
}
|
72
83
|
export function registerMethods(methods) {
|
73
84
|
for (const [type, method] of Object.entries(methods)) {
|
@@ -77,7 +88,7 @@ export function registerMethods(methods) {
|
|
77
88
|
log.debug("Registered", type);
|
78
89
|
handlers.set(type, method);
|
79
90
|
}
|
80
|
-
|
91
|
+
chrome.runtime.onMessage.addListener(onMessageListener);
|
81
92
|
}
|
82
93
|
/** Ensure/document that the current function was called via Messenger */
|
83
94
|
export function assertMessengerCall(_this) { }
|
package/distribution/sender.js
CHANGED
@@ -6,7 +6,6 @@ import { log } from "./logging.js";
|
|
6
6
|
import { handlers } from "./handlers.js";
|
7
7
|
import { events } from "./events.js";
|
8
8
|
const _errorNonExistingTarget = "Could not establish connection. Receiving end does not exist.";
|
9
|
-
// https://github.com/mozilla/webextension-polyfill/issues/384
|
10
9
|
const _errorTargetClosedEarly = "A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received";
|
11
10
|
export const errorTargetClosedEarly = "The target was closed before receiving a response";
|
12
11
|
export const errorTabDoesntExist = "The tab doesn't exist";
|
@@ -99,9 +98,9 @@ async function manageMessage(type, target, seq, retry, sendMessage) {
|
|
99
98
|
String(error.message).startsWith("No handlers registered in ")))) {
|
100
99
|
throw error;
|
101
100
|
}
|
102
|
-
if (
|
101
|
+
if (chrome.tabs && typeof target.tabId === "number") {
|
103
102
|
try {
|
104
|
-
const tabInfo = await
|
103
|
+
const tabInfo = await chrome.tabs.get(target.tabId);
|
105
104
|
if (tabInfo.discarded) {
|
106
105
|
throw new Error(errorTabWasDiscarded);
|
107
106
|
}
|
@@ -154,15 +153,15 @@ function messenger(type, options, target, ...args) {
|
|
154
153
|
}
|
155
154
|
const sendMessage = async (attemptCount) => {
|
156
155
|
log.debug(type, seq, "↗️ sending message to runtime", attemptLog(attemptCount));
|
157
|
-
return
|
156
|
+
return chrome.runtime.sendMessage(makeMessage(type, args, target, options));
|
158
157
|
};
|
159
158
|
return manageConnection(type, options, target, sendMessage);
|
160
159
|
}
|
161
160
|
// Contexts without direct Tab access must go through background
|
162
|
-
if (!
|
161
|
+
if (!chrome.tabs) {
|
163
162
|
return manageConnection(type, options, target, async (attemptCount) => {
|
164
163
|
log.debug(type, seq, "↗️ sending message to runtime", attemptLog(attemptCount));
|
165
|
-
return
|
164
|
+
return chrome.runtime.sendMessage(makeMessage(type, args, target, options));
|
166
165
|
});
|
167
166
|
}
|
168
167
|
// `frameId` must be specified. If missing, the message is sent to every frame
|
@@ -170,7 +169,7 @@ function messenger(type, options, target, ...args) {
|
|
170
169
|
// Message tab directly
|
171
170
|
return manageConnection(type, options, target, async (attemptCount) => {
|
172
171
|
log.debug(type, seq, "↗️ sending message to tab", tabId, "frame", frameId, attemptLog(attemptCount));
|
173
|
-
return
|
172
|
+
return chrome.tabs.sendMessage(tabId, makeMessage(type, args, target, options), frameId === "allFrames"
|
174
173
|
? {}
|
175
174
|
: {
|
176
175
|
frameId,
|
package/distribution/types.d.ts
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
import { type Runtime } from "webextension-polyfill";
|
2
1
|
import { type Asyncify, type ValueOf } from "type-fest";
|
3
2
|
import { type ErrorObject } from "serialize-error";
|
4
3
|
/**
|
@@ -48,9 +47,7 @@ export type Message<LocalArguments extends Arguments = Arguments> = {
|
|
48
47
|
/** If the message is being sent to an intermediary receiver, also set the options */
|
49
48
|
options?: Options;
|
50
49
|
};
|
51
|
-
export type Sender =
|
52
|
-
origin?: string;
|
53
|
-
};
|
50
|
+
export type Sender = chrome.runtime.MessageSender;
|
54
51
|
export type MessengerMessage = Message & {
|
55
52
|
/** Guarantees that a message is meant to be handled by this library */
|
56
53
|
__webextMessenger: true;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "webext-messenger",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.32.0",
|
4
4
|
"description": "Browser Extension component messaging framework",
|
5
5
|
"keywords": [],
|
6
6
|
"repository": "pixiebrix/webext-messenger",
|
@@ -29,9 +29,8 @@
|
|
29
29
|
"p-event": "^6.0.1",
|
30
30
|
"p-retry": "^6.2.1",
|
31
31
|
"serialize-error": "^12.0.0",
|
32
|
-
"type-fest": "^4.
|
33
|
-
"webext-detect": "^5.3.2"
|
34
|
-
"webext-events": "^3.1.1"
|
32
|
+
"type-fest": "^4.36.0",
|
33
|
+
"webext-detect": "^5.3.2"
|
35
34
|
},
|
36
35
|
"@parcel/resolver-default": {
|
37
36
|
"packageExports": true
|
@@ -39,9 +38,8 @@
|
|
39
38
|
"devDependencies": {
|
40
39
|
"@parcel/config-webextension": "^2.11.0",
|
41
40
|
"@sindresorhus/tsconfig": "^7.0.0",
|
42
|
-
"@types/chrome": "^0.0.
|
43
|
-
"@types/tape": "^5.8.
|
44
|
-
"@types/webextension-polyfill": "^0.12.1",
|
41
|
+
"@types/chrome": "^0.0.307",
|
42
|
+
"@types/tape": "^5.8.1",
|
45
43
|
"buffer": "^6.0.3",
|
46
44
|
"eslint": "^8.57.0",
|
47
45
|
"eslint-config-pixiebrix": "^0.41.1",
|
@@ -52,10 +50,8 @@
|
|
52
50
|
"process": "^0.11.10",
|
53
51
|
"stream-browserify": "^3.0.0",
|
54
52
|
"tape": "^5.9.0",
|
55
|
-
"typescript": "^5.
|
56
|
-
"vitest": "^
|
57
|
-
"webext-content-scripts": "^2.7.0",
|
58
|
-
"webextension-polyfill": "^0.12.0"
|
53
|
+
"typescript": "^5.8.2",
|
54
|
+
"vitest": "^3.0.7"
|
59
55
|
},
|
60
56
|
"targets": {
|
61
57
|
"main": false,
|