webext-messenger 0.19.1 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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;
@@ -0,0 +1,6 @@
1
+ import { __getTabData } from "./thisTarget.js";
2
+ export const privateMethods = [__getTabData];
3
+ export const handlers = new Map();
4
+ export function didUserRegisterMethods() {
5
+ return handlers.size > privateMethods.length;
6
+ }
@@ -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()}`);
@@ -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, handlers, debug, warn, } from "./shared.js";
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
- String(error.message).startsWith(_errorNonExistingTarget)) {
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))) {
@@ -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;
@@ -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 (error === null || error === void 0 ? void 0 : error.message) === "string";
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 === ((_a = from.tab) === null || _a === void 0 ? void 0 : _a.id)) {
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
- var _a, _b, _c;
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.19.1",
3
+ "version": "0.20.0",
4
4
  "description": "Browser Extension component messaging framework",
5
5
  "keywords": [],
6
6
  "repository": "pixiebrix/webext-messenger",
@@ -18,85 +18,6 @@
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
- "testingApi.ts"
83
- ],
84
- "rules": {
85
- "@typescript-eslint/no-explicit-any": "off",
86
- "@typescript-eslint/no-non-null-assertion": "off",
87
- "@typescript-eslint/no-unsafe-member-access": "off"
88
- }
89
- },
90
- {
91
- "files": [
92
- "source/test/**/*"
93
- ],
94
- "rules": {
95
- "import/extensions": "off"
96
- }
97
- }
98
- ]
99
- },
100
21
  "dependencies": {
101
22
  "p-retry": "^5.1.1",
102
23
  "serialize-error": "^11.0.0",
@@ -131,12 +52,8 @@
131
52
  "webextension-polyfill": "^0.9.0"
132
53
  },
133
54
  "alias": {
134
- "./this-stuff-is-just-for-local-parcel-tests": "./package.json",
135
- "./source/sender.js": "./source/sender.ts",
136
- "./source/receiver.js": "./source/receiver.ts",
137
- "./source/types.js": "./source/types.ts",
138
- "./source/shared.js": "./source/shared.ts",
139
- "./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"
140
57
  },
141
58
  "targets": {
142
59
  "main": false,