webext-messenger 0.19.0 → 0.20.1
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/handlers.d.ts +10 -0
- package/distribution/handlers.js +6 -0
- package/distribution/index.js +1 -5
- package/distribution/receiver.js +8 -2
- package/distribution/sender.js +6 -2
- package/distribution/shared.d.ts +0 -2
- package/distribution/shared.js +1 -2
- package/distribution/thisTarget.d.ts +1 -7
- package/distribution/thisTarget.js +9 -10
- package/distribution/types.d.ts +3 -1
- package/package.json +20 -102
@@ -0,0 +1,10 @@
|
|
1
|
+
import { __getTabData } from "./thisTarget.js";
|
2
|
+
import { Method } from "./types.js";
|
3
|
+
declare global {
|
4
|
+
interface MessengerMethods {
|
5
|
+
__getTabData: typeof __getTabData;
|
6
|
+
}
|
7
|
+
}
|
8
|
+
export declare const privateMethods: (typeof __getTabData)[];
|
9
|
+
export declare const handlers: Map<string, Method>;
|
10
|
+
export declare function didUserRegisterMethods(): boolean;
|
package/distribution/index.js
CHANGED
@@ -1,8 +1,4 @@
|
|
1
|
-
// Imports must use the .js extension because
|
2
|
-
// This works in TS even if the .js doesn't exist, but it breaks Parcel (the tests builder)
|
3
|
-
// For this reason, there's an `alias` field in package.json to redirect these imports.
|
4
|
-
// If you see "@parcel/resolver-default: Cannot load file './yourNewFile.js'" you need to add it to the `alias` list
|
5
|
-
// 🥲
|
1
|
+
// Imports must use the .js extension because ESM requires it and TS refuses to rewrite .ts to .js
|
6
2
|
export * from "./receiver.js";
|
7
3
|
export * from "./sender.js";
|
8
4
|
export * from "./types.js";
|
package/distribution/receiver.js
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
import { serializeError } from "serialize-error";
|
2
|
-
import { messenger } from "./sender.js";
|
3
|
-
import { handlers, isObject, MessengerError, debug, __webextMessenger, } from "./shared.js";
|
4
2
|
import { getContextName, isBackground } from "webext-detect-page";
|
3
|
+
import { messenger } from "./sender.js";
|
4
|
+
import { isObject, MessengerError, debug, __webextMessenger, } from "./shared.js";
|
5
5
|
import { getActionForMessage, nameThisTarget } from "./thisTarget.js";
|
6
|
+
import { didUserRegisterMethods, handlers } from "./handlers.js";
|
6
7
|
export function isMessengerMessage(message) {
|
7
8
|
return (isObject(message) &&
|
8
9
|
typeof message["type"] === "string" &&
|
@@ -44,6 +45,11 @@ action) {
|
|
44
45
|
});
|
45
46
|
const localHandler = handlers.get(type);
|
46
47
|
if (!localHandler) {
|
48
|
+
if (!didUserRegisterMethods()) {
|
49
|
+
// TODO: Test the handling of __getTabData in contexts that have no registered methods
|
50
|
+
// https://github.com/pixiebrix/webext-messenger/pull/82
|
51
|
+
throw new MessengerError(`No handlers registered in ${getContextName()}`);
|
52
|
+
}
|
47
53
|
throw new MessengerError(`No handler registered for ${type} in ${getContextName()}`);
|
48
54
|
}
|
49
55
|
handleMessage = async () => localHandler.apply(meta, args);
|
package/distribution/sender.js
CHANGED
@@ -2,7 +2,8 @@ import pRetry from "p-retry";
|
|
2
2
|
import { isBackground } from "webext-detect-page";
|
3
3
|
import { doesTabExist } from "webext-tools";
|
4
4
|
import { deserializeError } from "serialize-error";
|
5
|
-
import { isObject, MessengerError, __webextMessenger,
|
5
|
+
import { isObject, MessengerError, __webextMessenger, debug, warn, } from "./shared.js";
|
6
|
+
import { handlers } from "./handlers.js";
|
6
7
|
const _errorNonExistingTarget = "Could not establish connection. Receiving end does not exist.";
|
7
8
|
// https://github.com/mozilla/webextension-polyfill/issues/384
|
8
9
|
const _errorTargetClosedEarly = "A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received";
|
@@ -47,7 +48,10 @@ async function manageMessage(type, target, sendMessage) {
|
|
47
48
|
if (
|
48
49
|
// Don't retry sending to the background page unless it really hasn't loaded yet
|
49
50
|
(target.page !== "background" && error instanceof MessengerError) ||
|
50
|
-
|
51
|
+
// Page or its content script not yet loaded
|
52
|
+
String(error.message).startsWith(_errorNonExistingTarget) ||
|
53
|
+
// `registerMethods` not yet loaded
|
54
|
+
String(error.message).startsWith("No handlers registered in ")) {
|
51
55
|
if (browser.tabs &&
|
52
56
|
typeof target.tabId === "number" &&
|
53
57
|
!(await doesTabExist(target.tabId))) {
|
package/distribution/shared.d.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
import { JsonObject } from "type-fest";
|
2
|
-
import { Method } from "./types.js";
|
3
2
|
declare type ErrorObject = {
|
4
3
|
name?: string;
|
5
4
|
stack?: string;
|
@@ -11,7 +10,6 @@ export declare function isObject(value: unknown): value is Record<string, unknow
|
|
11
10
|
export declare class MessengerError extends Error {
|
12
11
|
name: string;
|
13
12
|
}
|
14
|
-
export declare const handlers: Map<string, Method>;
|
15
13
|
export declare const debug: (...args: any[]) => void;
|
16
14
|
export declare const warn: (...args: any[]) => void;
|
17
15
|
export declare function isErrorObject(error: unknown): error is ErrorObject;
|
package/distribution/shared.js
CHANGED
@@ -25,13 +25,12 @@ export class MessengerError extends Error {
|
|
25
25
|
});
|
26
26
|
}
|
27
27
|
}
|
28
|
-
export const handlers = new Map();
|
29
28
|
// .bind preserves the call location in the console
|
30
29
|
export const debug = logging ? console.debug.bind(console, "Messenger:") : noop;
|
31
30
|
export const warn = logging ? console.warn.bind(console, "Messenger:") : noop;
|
32
31
|
export function isErrorObject(error) {
|
33
32
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a type guard function and it uses ?.
|
34
|
-
return typeof
|
33
|
+
return typeof error?.message === "string";
|
35
34
|
}
|
36
35
|
export async function delay(milliseconds) {
|
37
36
|
return new Promise((resolve) => {
|
@@ -1,11 +1,5 @@
|
|
1
1
|
import { AnyTarget, MessengerMeta, Sender } from "./types.js";
|
2
2
|
export declare function getActionForMessage(from: Sender, { ...to }: AnyTarget): "respond" | "forward" | "ignore";
|
3
3
|
export declare function nameThisTarget(): Promise<void>;
|
4
|
-
declare function __getTabData(this: MessengerMeta): AnyTarget;
|
5
|
-
declare global {
|
6
|
-
interface MessengerMethods {
|
7
|
-
__getTabData: typeof __getTabData;
|
8
|
-
}
|
9
|
-
}
|
4
|
+
export declare function __getTabData(this: MessengerMeta): AnyTarget;
|
10
5
|
export declare function initPrivateApi(): void;
|
11
|
-
export {};
|
@@ -5,7 +5,9 @@ import { debug } from "./shared.js";
|
|
5
5
|
// Soft warning: Race conditions are possible.
|
6
6
|
// This CANNOT be awaited because waiting for it means "I will handle the message."
|
7
7
|
// If a message is received before this is ready, it will just have to be ignored.
|
8
|
-
let thisTarget
|
8
|
+
let thisTarget = isBackground()
|
9
|
+
? { page: "background" }
|
10
|
+
: undefined;
|
9
11
|
function compareTargets(to, thisTarget) {
|
10
12
|
for (const [key, value] of Object.entries(to)) {
|
11
13
|
if (thisTarget[key] === value) {
|
@@ -29,7 +31,6 @@ function compareTargets(to, thisTarget) {
|
|
29
31
|
}
|
30
32
|
export function getActionForMessage(from, { ...to } // Clone object because we're editing it
|
31
33
|
) {
|
32
|
-
var _a;
|
33
34
|
if (to.page === "any") {
|
34
35
|
return "respond";
|
35
36
|
}
|
@@ -48,7 +49,7 @@ export function getActionForMessage(from, { ...to } // Clone object because we'r
|
|
48
49
|
return "ignore";
|
49
50
|
}
|
50
51
|
// Set "this" tab to the current tabId
|
51
|
-
if (to.tabId === "this" && thisTarget.tabId ===
|
52
|
+
if (to.tabId === "this" && thisTarget.tabId === from.tab?.id) {
|
52
53
|
to.tabId = thisTarget.tabId;
|
53
54
|
}
|
54
55
|
// Every `target` key must match `thisTarget`
|
@@ -67,16 +68,14 @@ export async function nameThisTarget() {
|
|
67
68
|
thisTarget.page = location.pathname + location.search;
|
68
69
|
}
|
69
70
|
}
|
70
|
-
function __getTabData() {
|
71
|
-
|
72
|
-
return { tabId: (_b = (_a = this.trace[0]) === null || _a === void 0 ? void 0 : _a.tab) === null || _b === void 0 ? void 0 : _b.id, frameId: (_c = this.trace[0]) === null || _c === void 0 ? void 0 : _c.frameId };
|
71
|
+
export function __getTabData() {
|
72
|
+
return { tabId: this.trace[0]?.tab?.id, frameId: this.trace[0]?.frameId };
|
73
73
|
}
|
74
74
|
export function initPrivateApi() {
|
75
|
-
if (isBackground()) {
|
76
|
-
thisTarget = { page: "background" };
|
77
|
-
}
|
78
75
|
if (isExtensionContext()) {
|
79
|
-
//
|
76
|
+
// Only `runtime` pages can handle this message but I can't remove it because its listener
|
77
|
+
// also serves the purpose of throwing a specific error when no methods have been registered.
|
78
|
+
// https://github.com/pixiebrix/webext-messenger/pull/80
|
80
79
|
registerMethods({ __getTabData });
|
81
80
|
}
|
82
81
|
}
|
package/distribution/types.d.ts
CHANGED
@@ -40,7 +40,9 @@ export declare type Message<LocalArguments extends Arguments = Arguments> = {
|
|
40
40
|
/** If the message is being sent to an intermediary receiver, also set the options */
|
41
41
|
options?: Options;
|
42
42
|
};
|
43
|
-
export declare type Sender = Runtime.MessageSender
|
43
|
+
export declare type Sender = Runtime.MessageSender & {
|
44
|
+
origin?: string;
|
45
|
+
};
|
44
46
|
export declare type MessengerMessage = Message & {
|
45
47
|
/** Guarantees that a message is meant to be handled by this library */
|
46
48
|
__webextMessenger: true;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "webext-messenger",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.20.1",
|
4
4
|
"description": "Browser Extension component messaging framework",
|
5
5
|
"keywords": [],
|
6
6
|
"repository": "pixiebrix/webext-messenger",
|
@@ -18,124 +18,42 @@
|
|
18
18
|
"fix": "eslint . --fix",
|
19
19
|
"watch": "tsc --watch"
|
20
20
|
},
|
21
|
-
"eslintConfig": {
|
22
|
-
"env": {
|
23
|
-
"browser": true
|
24
|
-
},
|
25
|
-
"parserOptions": {
|
26
|
-
"project": "tsconfig.json"
|
27
|
-
},
|
28
|
-
"plugins": [
|
29
|
-
"import"
|
30
|
-
],
|
31
|
-
"extends": [
|
32
|
-
"plugin:@typescript-eslint/recommended",
|
33
|
-
"xo",
|
34
|
-
"xo-typescript",
|
35
|
-
"prettier",
|
36
|
-
"plugin:import/recommended",
|
37
|
-
"plugin:import/typescript",
|
38
|
-
"plugin:unicorn/recommended"
|
39
|
-
],
|
40
|
-
"rules": {
|
41
|
-
"no-restricted-imports": [
|
42
|
-
"error",
|
43
|
-
{
|
44
|
-
"paths": [
|
45
|
-
{
|
46
|
-
"name": "./index",
|
47
|
-
"message": "The index file is only used to re-export internal files. Use direct imports instead."
|
48
|
-
}
|
49
|
-
]
|
50
|
-
}
|
51
|
-
],
|
52
|
-
"import/extensions": [
|
53
|
-
"error",
|
54
|
-
"always"
|
55
|
-
],
|
56
|
-
"import/no-unresolved": "off",
|
57
|
-
"unicorn/filename-case": [
|
58
|
-
"error",
|
59
|
-
{
|
60
|
-
"case": "camelCase"
|
61
|
-
}
|
62
|
-
],
|
63
|
-
"unicorn/no-useless-undefined": [
|
64
|
-
"error",
|
65
|
-
{
|
66
|
-
"checkArguments": false
|
67
|
-
}
|
68
|
-
],
|
69
|
-
"unicorn/prevent-abbreviations": [
|
70
|
-
"error",
|
71
|
-
{
|
72
|
-
"allowList": {
|
73
|
-
"args": true
|
74
|
-
}
|
75
|
-
}
|
76
|
-
]
|
77
|
-
},
|
78
|
-
"overrides": [
|
79
|
-
{
|
80
|
-
"files": [
|
81
|
-
"*.test.ts"
|
82
|
-
],
|
83
|
-
"rules": {
|
84
|
-
"@typescript-eslint/no-explicit-any": "off",
|
85
|
-
"@typescript-eslint/no-non-null-assertion": "off",
|
86
|
-
"@typescript-eslint/no-unsafe-member-access": "off"
|
87
|
-
}
|
88
|
-
},
|
89
|
-
{
|
90
|
-
"files": [
|
91
|
-
"source/test/**/*"
|
92
|
-
],
|
93
|
-
"rules": {
|
94
|
-
"import/extensions": "off"
|
95
|
-
}
|
96
|
-
}
|
97
|
-
]
|
98
|
-
},
|
99
21
|
"dependencies": {
|
100
|
-
"p-retry": "^5.1.
|
22
|
+
"p-retry": "^5.1.1",
|
101
23
|
"serialize-error": "^11.0.0",
|
102
|
-
"type-fest": "^2.
|
24
|
+
"type-fest": "^2.13.0",
|
103
25
|
"webext-detect-page": "^4.0.1",
|
104
26
|
"webext-tools": "^1.1.0"
|
105
27
|
},
|
106
28
|
"devDependencies": {
|
107
|
-
"@parcel/config-webextension": "^2.
|
108
|
-
"@sindresorhus/tsconfig": "^
|
109
|
-
"@types/chrome": "^0.0.
|
29
|
+
"@parcel/config-webextension": "^2.6.0",
|
30
|
+
"@sindresorhus/tsconfig": "^3.0.1",
|
31
|
+
"@types/chrome": "^0.0.188",
|
110
32
|
"@types/tape": "^4.13.2",
|
111
|
-
"@types/webextension-polyfill": "^0.
|
112
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
113
|
-
"@typescript-eslint/parser": "^5.
|
33
|
+
"@types/webextension-polyfill": "^0.9.0",
|
34
|
+
"@typescript-eslint/eslint-plugin": "^5.27.0",
|
35
|
+
"@typescript-eslint/parser": "^5.27.0",
|
114
36
|
"buffer": "^6.0.3",
|
115
|
-
"eslint": "^8.
|
37
|
+
"eslint": "^8.17.0",
|
116
38
|
"eslint-config-prettier": "^8.5.0",
|
117
|
-
"eslint-config-xo": "^0.
|
118
|
-
"eslint-config-xo-typescript": "^0.
|
119
|
-
"eslint-plugin-import": "^2.
|
120
|
-
"eslint-plugin-unicorn": "^
|
39
|
+
"eslint-config-xo": "^0.41.0",
|
40
|
+
"eslint-config-xo-typescript": "^0.51.1",
|
41
|
+
"eslint-plugin-import": "^2.26.0",
|
42
|
+
"eslint-plugin-unicorn": "^42.0.0",
|
121
43
|
"events": "^3.3.0",
|
122
44
|
"npm-run-all": "^4.1.5",
|
123
|
-
"parcel": "^2.
|
45
|
+
"parcel": "^2.6.0",
|
124
46
|
"path-browserify": "^1.0.1",
|
125
47
|
"process": "^0.11.10",
|
126
48
|
"stream-browserify": "^3.0.0",
|
127
|
-
"tape": "^5.5.
|
128
|
-
"typescript": "^4.
|
129
|
-
"webext-content-scripts": "^1.0.
|
49
|
+
"tape": "^5.5.3",
|
50
|
+
"typescript": "^4.7.3",
|
51
|
+
"webext-content-scripts": "^1.0.2",
|
130
52
|
"webextension-polyfill": "^0.9.0"
|
131
53
|
},
|
132
54
|
"alias": {
|
133
|
-
"./this-stuff-is-just-for-local-parcel-tests": "
|
134
|
-
"./source
|
135
|
-
"./source/receiver.js": "./source/receiver.ts",
|
136
|
-
"./source/types.js": "./source/types.ts",
|
137
|
-
"./source/shared.js": "./source/shared.ts",
|
138
|
-
"./source/thisTarget.js": "./source/thisTarget.ts"
|
55
|
+
"./this-stuff-is-just-for-local-parcel-tests": "https://github.com/parcel-bundler/parcel/issues/4936",
|
56
|
+
"./source/**/*.js": "./source/$1/$2.ts"
|
139
57
|
},
|
140
58
|
"targets": {
|
141
59
|
"main": false,
|