webext-messenger 0.18.2 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- package/distribution/handlers.d.ts +10 -0
- package/distribution/handlers.js +6 -0
- package/distribution/receiver.js +6 -2
- package/distribution/sender.d.ts +2 -1
- package/distribution/sender.js +21 -4
- package/distribution/shared.d.ts +0 -2
- package/distribution/shared.js +1 -2
- package/distribution/thisTarget.d.ts +1 -7
- package/distribution/thisTarget.js +3 -5
- package/package.json +22 -103
- package/readme.md +4 -0
@@ -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/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" &&
|
@@ -42,6 +43,9 @@ action) {
|
|
42
43
|
args,
|
43
44
|
wasForwarded: trace.length > 1,
|
44
45
|
});
|
46
|
+
if (!didUserRegisterMethods()) {
|
47
|
+
throw new MessengerError(`No handlers registered in ${getContextName()}`);
|
48
|
+
}
|
45
49
|
const localHandler = handlers.get(type);
|
46
50
|
if (!localHandler) {
|
47
51
|
throw new MessengerError(`No handler registered for ${type} in ${getContextName()}`);
|
package/distribution/sender.d.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import { PublicMethod, PublicMethodWithTarget, Options, Target, PageTarget } from "./types.js";
|
2
2
|
import { SetReturnType } from "type-fest";
|
3
|
-
export declare const
|
3
|
+
export declare const errorTargetClosedEarly = "The target was closed before receiving a response";
|
4
|
+
export declare const errorTabDoesntExist = "The tab doesn't exist";
|
4
5
|
declare function messenger<Type extends keyof MessengerMethods, Method extends MessengerMethods[Type]>(type: Type, options: {
|
5
6
|
isNotification: true;
|
6
7
|
}, target: Target | PageTarget, ...args: Parameters<Method>): void;
|
package/distribution/sender.js
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
import pRetry from "p-retry";
|
2
2
|
import { isBackground } from "webext-detect-page";
|
3
|
+
import { doesTabExist } from "webext-tools";
|
3
4
|
import { deserializeError } from "serialize-error";
|
4
|
-
import { isObject, MessengerError, __webextMessenger,
|
5
|
-
|
5
|
+
import { isObject, MessengerError, __webextMessenger, debug, warn, } from "./shared.js";
|
6
|
+
import { handlers } from "./handlers.js";
|
7
|
+
const _errorNonExistingTarget = "Could not establish connection. Receiving end does not exist.";
|
8
|
+
// https://github.com/mozilla/webextension-polyfill/issues/384
|
9
|
+
const _errorTargetClosedEarly = "A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received";
|
10
|
+
export const errorTargetClosedEarly = "The target was closed before receiving a response";
|
11
|
+
export const errorTabDoesntExist = "The tab doesn't exist";
|
6
12
|
function isMessengerResponse(response) {
|
7
13
|
return isObject(response) && response["__webextMessenger"] === true;
|
8
14
|
}
|
@@ -35,11 +41,22 @@ async function manageMessage(type, target, sendMessage) {
|
|
35
41
|
minTimeout: 100,
|
36
42
|
factor: 1.3,
|
37
43
|
maxRetryTime: 4000,
|
38
|
-
onFailedAttempt(error) {
|
44
|
+
async onFailedAttempt(error) {
|
45
|
+
if (error.message === _errorTargetClosedEarly) {
|
46
|
+
throw new Error(errorTargetClosedEarly);
|
47
|
+
}
|
39
48
|
if (
|
40
49
|
// Don't retry sending to the background page unless it really hasn't loaded yet
|
41
50
|
(target.page !== "background" && error instanceof MessengerError) ||
|
42
|
-
|
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 ")) {
|
55
|
+
if (browser.tabs &&
|
56
|
+
typeof target.tabId === "number" &&
|
57
|
+
!(await doesTabExist(target.tabId))) {
|
58
|
+
throw new Error(errorTabDoesntExist);
|
59
|
+
}
|
43
60
|
debug(type, "will retry. Attempt", error.attemptNumber);
|
44
61
|
}
|
45
62
|
else {
|
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 {};
|
@@ -29,7 +29,6 @@ function compareTargets(to, thisTarget) {
|
|
29
29
|
}
|
30
30
|
export function getActionForMessage(from, { ...to } // Clone object because we're editing it
|
31
31
|
) {
|
32
|
-
var _a;
|
33
32
|
if (to.page === "any") {
|
34
33
|
return "respond";
|
35
34
|
}
|
@@ -48,7 +47,7 @@ export function getActionForMessage(from, { ...to } // Clone object because we'r
|
|
48
47
|
return "ignore";
|
49
48
|
}
|
50
49
|
// Set "this" tab to the current tabId
|
51
|
-
if (to.tabId === "this" && thisTarget.tabId ===
|
50
|
+
if (to.tabId === "this" && thisTarget.tabId === from.tab?.id) {
|
52
51
|
to.tabId = thisTarget.tabId;
|
53
52
|
}
|
54
53
|
// Every `target` key must match `thisTarget`
|
@@ -67,9 +66,8 @@ export async function nameThisTarget() {
|
|
67
66
|
thisTarget.page = location.pathname + location.search;
|
68
67
|
}
|
69
68
|
}
|
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 };
|
69
|
+
export function __getTabData() {
|
70
|
+
return { tabId: this.trace[0]?.tab?.id, frameId: this.trace[0]?.frameId };
|
73
71
|
}
|
74
72
|
export function initPrivateApi() {
|
75
73
|
if (isBackground()) {
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "webext-messenger",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.20.0",
|
4
4
|
"description": "Browser Extension component messaging framework",
|
5
5
|
"keywords": [],
|
6
6
|
"repository": "pixiebrix/webext-messenger",
|
@@ -18,123 +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.
|
103
|
-
"webext-detect-page": "^4.0.1"
|
24
|
+
"type-fest": "^2.13.0",
|
25
|
+
"webext-detect-page": "^4.0.1",
|
26
|
+
"webext-tools": "^1.1.0"
|
104
27
|
},
|
105
28
|
"devDependencies": {
|
106
|
-
"@parcel/config-webextension": "^2.
|
107
|
-
"@sindresorhus/tsconfig": "^
|
108
|
-
"@types/chrome": "^0.0.
|
29
|
+
"@parcel/config-webextension": "^2.6.0",
|
30
|
+
"@sindresorhus/tsconfig": "^3.0.1",
|
31
|
+
"@types/chrome": "^0.0.188",
|
109
32
|
"@types/tape": "^4.13.2",
|
110
|
-
"@types/webextension-polyfill": "^0.
|
111
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
112
|
-
"@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",
|
113
36
|
"buffer": "^6.0.3",
|
114
|
-
"eslint": "^8.
|
37
|
+
"eslint": "^8.17.0",
|
115
38
|
"eslint-config-prettier": "^8.5.0",
|
116
|
-
"eslint-config-xo": "^0.
|
117
|
-
"eslint-config-xo-typescript": "^0.
|
118
|
-
"eslint-plugin-import": "^2.
|
119
|
-
"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",
|
120
43
|
"events": "^3.3.0",
|
121
44
|
"npm-run-all": "^4.1.5",
|
122
|
-
"parcel": "^2.
|
45
|
+
"parcel": "^2.6.0",
|
123
46
|
"path-browserify": "^1.0.1",
|
124
47
|
"process": "^0.11.10",
|
125
48
|
"stream-browserify": "^3.0.0",
|
126
|
-
"tape": "^5.5.
|
127
|
-
"typescript": "^4.
|
128
|
-
"webext-content-scripts": "^1.0.
|
49
|
+
"tape": "^5.5.3",
|
50
|
+
"typescript": "^4.7.3",
|
51
|
+
"webext-content-scripts": "^1.0.2",
|
129
52
|
"webextension-polyfill": "^0.9.0"
|
130
53
|
},
|
131
54
|
"alias": {
|
132
|
-
"./this-stuff-is-just-for-local-parcel-tests": "
|
133
|
-
"./source
|
134
|
-
"./source/receiver.js": "./source/receiver.ts",
|
135
|
-
"./source/types.js": "./source/types.ts",
|
136
|
-
"./source/shared.js": "./source/shared.ts",
|
137
|
-
"./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"
|
138
57
|
},
|
139
58
|
"targets": {
|
140
59
|
"main": false,
|