webext-messenger 0.23.0 → 0.24.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,4 +2,4 @@ export * from "./receiver.js";
2
2
  export * from "./sender.js";
3
3
  export * from "./types.js";
4
4
  export { getThisFrame, getTopLevelFrame } from "./thisTarget.js";
5
- export { toggleLogging } from "./shared.js";
5
+ export { toggleLogging } from "./logging.js";
@@ -3,6 +3,6 @@ export * from "./receiver.js";
3
3
  export * from "./sender.js";
4
4
  export * from "./types.js";
5
5
  export { getThisFrame, getTopLevelFrame } from "./thisTarget.js";
6
- export { toggleLogging } from "./shared.js";
6
+ export { toggleLogging } from "./logging.js";
7
7
  import { initPrivateApi } from "./thisTarget.js";
8
8
  initPrivateApi();
@@ -0,0 +1,5 @@
1
+ export declare const log: {
2
+ debug: (...args: unknown[]) => void;
3
+ warn: (...args: unknown[]) => void;
4
+ };
5
+ export declare function toggleLogging(enabled: boolean): void;
@@ -0,0 +1,13 @@
1
+ /* Warning: Do not use import browser-polyfill directly or indirectly */
2
+ // .bind preserves the call location in the console
3
+ const debug = console.debug.bind(console, "Messenger:");
4
+ const warn = console.warn.bind(console, "Messenger:");
5
+ const noop = () => {
6
+ /* */
7
+ };
8
+ // Default to "no logs"
9
+ export const log = { debug: noop, warn: noop };
10
+ export function toggleLogging(enabled) {
11
+ log.debug = enabled ? debug : noop;
12
+ log.warn = enabled ? warn : noop;
13
+ }
@@ -1,7 +1,8 @@
1
1
  import { serializeError } from "serialize-error";
2
2
  import { getContextName } from "webext-detect-page";
3
3
  import { messenger } from "./sender.js";
4
- import { isObject, MessengerError, log, __webextMessenger } from "./shared.js";
4
+ import { isObject, MessengerError, __webextMessenger } from "./shared.js";
5
+ import { log } from "./logging.js";
5
6
  import { getActionForMessage } from "./thisTarget.js";
6
7
  import { didUserRegisterMethods, handlers } from "./handlers.js";
7
8
  export function isMessengerMessage(message) {
@@ -2,6 +2,7 @@ import { type PublicMethod, type PublicMethodWithTarget, type Options, type Targ
2
2
  import { type SetReturnType } from "type-fest";
3
3
  export declare const errorTargetClosedEarly = "The target was closed before receiving a response";
4
4
  export declare const errorTabDoesntExist = "The tab doesn't exist";
5
+ export declare const errorTabWasDiscarded = "The tab was discarded";
5
6
  declare function messenger<Type extends keyof MessengerMethods, Method extends MessengerMethods[Type]>(type: Type, options: {
6
7
  isNotification: true;
7
8
  }, target: Target | PageTarget, ...args: Parameters<Method>): void;
@@ -1,14 +1,15 @@
1
1
  import pRetry from "p-retry";
2
2
  import { isBackground } from "webext-detect-page";
3
- import { doesTabExist } from "webext-tools";
4
3
  import { deserializeError } from "serialize-error";
5
- import { isObject, MessengerError, __webextMessenger, log } from "./shared.js";
4
+ import { isObject, MessengerError, __webextMessenger } from "./shared.js";
5
+ import { log } from "./logging.js";
6
6
  import { handlers } from "./handlers.js";
7
7
  const _errorNonExistingTarget = "Could not establish connection. Receiving end does not exist.";
8
8
  // https://github.com/mozilla/webextension-polyfill/issues/384
9
9
  const _errorTargetClosedEarly = "A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received";
10
10
  export const errorTargetClosedEarly = "The target was closed before receiving a response";
11
11
  export const errorTabDoesntExist = "The tab doesn't exist";
12
+ export const errorTabWasDiscarded = "The tab was discarded";
12
13
  function isMessengerResponse(response) {
13
14
  return isObject(response) && response["__webextMessenger"] === true;
14
15
  }
@@ -65,23 +66,29 @@ async function manageMessage(type, target, seq, sendMessage) {
65
66
  if (error.message === _errorTargetClosedEarly) {
66
67
  throw new Error(errorTargetClosedEarly);
67
68
  }
68
- if (
69
+ if (!(
70
+ // If NONE of these conditions is true, stop retrying
69
71
  // Don't retry sending to the background page unless it really hasn't loaded yet
70
- (target.page !== "background" && error instanceof MessengerError) ||
72
+ ((target.page !== "background" &&
73
+ error instanceof MessengerError) ||
71
74
  // Page or its content script not yet loaded
72
75
  error.message === _errorNonExistingTarget ||
73
76
  // `registerMethods` not yet loaded
74
- String(error.message).startsWith("No handlers registered in ")) {
75
- if (browser.tabs &&
76
- typeof target.tabId === "number" &&
77
- !(await doesTabExist(target.tabId))) {
77
+ String(error.message).startsWith("No handlers registered in ")))) {
78
+ throw error;
79
+ }
80
+ if (browser.tabs && typeof target.tabId === "number") {
81
+ try {
82
+ const tabInfo = await browser.tabs.get(target.tabId);
83
+ if (tabInfo.discarded) {
84
+ throw new Error(errorTabWasDiscarded);
85
+ }
86
+ }
87
+ catch {
78
88
  throw new Error(errorTabDoesntExist);
79
89
  }
80
- log.debug(type, seq, "will retry. Attempt", error.attemptNumber);
81
- }
82
- else {
83
- throw error;
84
90
  }
91
+ log.debug(type, seq, "will retry. Attempt", error.attemptNumber);
85
92
  },
86
93
  }).catch((error) => {
87
94
  if (error?.message === _errorNonExistingTarget) {
@@ -10,11 +10,6 @@ export declare function isObject(value: unknown): value is Record<string, unknow
10
10
  export declare class MessengerError extends Error {
11
11
  name: string;
12
12
  }
13
- export declare const log: {
14
- debug: (...args: any[]) => void;
15
- warn: (...args: any[]) => void;
16
- };
17
- export declare function toggleLogging(enabled: boolean): void;
18
13
  export declare function isErrorObject(error: unknown): error is ErrorObject;
19
14
  export declare function delay(milliseconds: number): Promise<void>;
20
15
  export declare function once<Callback extends (...arguments_: unknown[]) => unknown>(function_: Callback): Callback;
@@ -3,9 +3,6 @@ export const __webextMessenger = true;
3
3
  export function isObject(value) {
4
4
  return typeof value === "object" && value !== null;
5
5
  }
6
- function noop() {
7
- /* */
8
- }
9
6
  export class MessengerError extends Error {
10
7
  constructor() {
11
8
  super(...arguments);
@@ -19,16 +16,6 @@ export class MessengerError extends Error {
19
16
  }
20
17
  // @ts-expect-error Wrong `errorConstructors` types
21
18
  errorConstructors.set("MessengerError", MessengerError);
22
- // .bind preserves the call location in the console
23
- const debug = console.debug.bind(console, "Messenger:");
24
- const warn = console.warn.bind(console, "Messenger:");
25
- export const log = { debug, warn };
26
- export function toggleLogging(enabled) {
27
- log.debug = enabled ? debug : noop;
28
- log.warn = enabled ? warn : noop;
29
- }
30
- // Default to "no logs"
31
- toggleLogging(false);
32
19
  export function isErrorObject(error) {
33
20
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a type guard function and it uses ?.
34
21
  return typeof error?.message === "string";
@@ -1,7 +1,8 @@
1
1
  import { isBackground, isContentScript, isExtensionContext, } from "webext-detect-page";
2
2
  import { messenger } from "./sender.js";
3
3
  import { registerMethods } from "./receiver.js";
4
- import { log, MessengerError, once } from "./shared.js";
4
+ import { MessengerError, once } from "./shared.js";
5
+ import { log } from "./logging.js";
5
6
  /**
6
7
  * @file This file exists because `runtime.sendMessage` acts as a broadcast to
7
8
  * all open extension pages, so the receiver needs a way to figure out if the
@@ -114,7 +115,7 @@ export function __getTabData() {
114
115
  return { tabId: this.trace[0]?.tab?.id, frameId: this.trace[0]?.frameId };
115
116
  }
116
117
  export async function getThisFrame() {
117
- await storeTabData(); // It should already have been called by we still need to await it
118
+ await storeTabData(); // It should already have been called but we still need to await it
118
119
  const { tabId, frameId } = thisTarget;
119
120
  if (typeof tabId !== "number" || typeof frameId !== "number") {
120
121
  throw new TypeError("This target is not in a frame");
package/package.json CHANGED
@@ -1,13 +1,19 @@
1
1
  {
2
2
  "name": "webext-messenger",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
4
4
  "description": "Browser Extension component messaging framework",
5
5
  "keywords": [],
6
6
  "repository": "pixiebrix/webext-messenger",
7
7
  "license": "MIT",
8
8
  "author": "Federico Brigante for PixieBrix <federico@pixiebrix.com> (https://www.pixiebrix.com)",
9
9
  "type": "module",
10
- "main": "distribution/index.js",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./distribution/index.js",
13
+ "default": "./distribution/index.js"
14
+ },
15
+ "./*": "./distribution/*"
16
+ },
11
17
  "scripts": {
12
18
  "build": "tsc",
13
19
  "demo:watch": "parcel watch --no-cache --no-hmr",
@@ -22,8 +28,7 @@
22
28
  "p-retry": "^6.0.0",
23
29
  "serialize-error": "^11.0.2",
24
30
  "type-fest": "^4.3.1",
25
- "webext-detect-page": "^4.1.1",
26
- "webext-tools": "^1.1.3"
31
+ "webext-detect-page": "^4.1.1"
27
32
  },
28
33
  "devDependencies": {
29
34
  "@parcel/config-webextension": "^2.6.2",
@@ -32,7 +37,7 @@
32
37
  "@types/tape": "^5.6.1",
33
38
  "@types/webextension-polyfill": "^0.10.2",
34
39
  "buffer": "^6.0.3",
35
- "eslint": "^8.29.0",
40
+ "eslint": "^8.50.0",
36
41
  "eslint-config-pixiebrix": "^0.27.2",
37
42
  "events": "^3.3.0",
38
43
  "npm-run-all": "^4.1.5",
@@ -40,7 +45,7 @@
40
45
  "path-browserify": "^1.0.1",
41
46
  "process": "^0.11.10",
42
47
  "stream-browserify": "^3.0.0",
43
- "tape": "^5.6.6",
48
+ "tape": "^5.7.0",
44
49
  "typescript": "^5.2.2",
45
50
  "webext-content-scripts": "^2.5.5",
46
51
  "webextension-polyfill": "^0.10.0"