webext-messenger 0.35.0 → 0.36.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.
@@ -1,11 +1,9 @@
1
- import { isExtensionContext } from "webext-detect";
1
+ import { isBackground, isExtensionContext } from "webext-detect";
2
2
  import { deserializeError } from "serialize-error";
3
3
  import { isObject, MessengerError, ExtensionNotFoundError, __webextMessenger, } from "./shared.js";
4
4
  import { log } from "./logging.js";
5
5
  import { handlers } from "./handlers.js";
6
6
  import { events } from "./events.js";
7
- import { compareTargets } from "./targetLogic.js";
8
- import { thisTarget } from "./thisTarget.js";
9
7
  const _errorNonExistingTarget = "Could not establish connection. Receiving end does not exist.";
10
8
  const _errorTargetClosedEarly = "A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received";
11
9
  export const errorTargetClosedEarly = "The target was closed before receiving a response";
@@ -186,17 +184,16 @@ function messenger(type, options, target, ...args) {
186
184
  };
187
185
  return manageConnection(type, options, target, sendMessage);
188
186
  }
189
- // Use local methods if the target matches the current context
190
- if (compareTargets(target, thisTarget)) {
191
- const handler = handlers.get(type);
192
- if (handler) {
193
- log.warn(type, seq, "is being handled locally");
194
- return handler.apply({ trace: [] }, args);
195
- }
196
- throw new MessengerError("No handler registered locally for " + type);
197
- }
198
187
  // Message goes to extension page
199
188
  if ("page" in target) {
189
+ if (target.page === "background" && isBackground()) {
190
+ const handler = handlers.get(type);
191
+ if (handler) {
192
+ log.warn(type, seq, "is being handled locally");
193
+ return handler.apply({ trace: [] }, args);
194
+ }
195
+ throw new MessengerError("No handler registered locally for " + type);
196
+ }
200
197
  const sendMessage = async (attemptCount) => {
201
198
  log.debug(type, seq, "↗️ sending message to runtime", attemptLog(attemptCount));
202
199
  return chrome.runtime.sendMessage(makeMessage(type, args, target, options));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webext-messenger",
3
- "version": "0.35.0",
3
+ "version": "0.36.0",
4
4
  "description": "Browser Extension component messaging framework",
5
5
  "keywords": [],
6
6
  "repository": "pixiebrix/webext-messenger",
@@ -27,18 +27,18 @@
27
27
  "watch": "tsc --watch"
28
28
  },
29
29
  "dependencies": {
30
- "one-event": "^4.3.0",
31
- "serialize-error": "^12.0.0",
32
- "type-fest": "^5.0.1",
30
+ "one-event": "^4.4.0",
31
+ "serialize-error": "^13.0.1",
32
+ "type-fest": "^5.7.0",
33
33
  "webext-detect": "^5.3.2"
34
34
  },
35
35
  "@parcel/resolver-default": {
36
36
  "packageExports": true
37
37
  },
38
38
  "devDependencies": {
39
- "@parcel/config-webextension": "^2.16.0",
40
- "@sindresorhus/tsconfig": "^8.0.1",
41
- "@types/chrome": "^0.1.22",
39
+ "@parcel/config-webextension": "^2.16.3",
40
+ "@sindresorhus/tsconfig": "^8.1.0",
41
+ "@types/chrome": "^0.2.1",
42
42
  "@types/tape": "^5.8.1",
43
43
  "buffer": "^6.0.3",
44
44
  "eslint": "^8.57.0",
@@ -49,9 +49,9 @@
49
49
  "path-browserify": "^1.0.1",
50
50
  "process": "^0.11.10",
51
51
  "stream-browserify": "^3.0.0",
52
- "tape": "^5.9.0",
52
+ "tape": "^5.10.2",
53
53
  "typescript": "^5.9.3",
54
- "vitest": "^3.2.4"
54
+ "vitest": "^4.1.9"
55
55
  },
56
56
  "targets": {
57
57
  "main": false,
@@ -1,6 +0,0 @@
1
- declare global {
2
- interface MessengerMethods {
3
- testMethod: () => Promise<string>;
4
- }
5
- }
6
- export {};
@@ -1,160 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-argument, @typescript-eslint/naming-convention */
2
- import { describe, test, expect, vi, beforeEach } from "vitest";
3
- import { handlers } from "./handlers.js";
4
- import * as thisTargetModule from "./thisTarget.js";
5
- // Mock dependencies
6
- vi.mock("webext-detect", () => ({
7
- isBackground: vi.fn(() => false),
8
- isExtensionContext: vi.fn(() => true),
9
- isOffscreenDocument: vi.fn(() => false),
10
- isContentScript: vi.fn(() => true),
11
- }));
12
- vi.mock("./logging.js", () => ({
13
- log: {
14
- debug: vi.fn(),
15
- warn: vi.fn(),
16
- },
17
- }));
18
- vi.mock("./events.js", () => ({
19
- events: {
20
- dispatchEvent: vi.fn(),
21
- },
22
- }));
23
- // Mock chrome APIs - simulate content script environment (no chrome.tabs)
24
- globalThis.chrome = {
25
- runtime: {
26
- id: "test-extension-id",
27
- sendMessage: vi.fn(),
28
- },
29
- // Note: chrome.tabs is undefined in content scripts
30
- };
31
- describe("messenger with tab targets and local methods", () => {
32
- beforeEach(() => {
33
- vi.clearAllMocks();
34
- handlers.clear();
35
- });
36
- test("should use local method when targeting same tab and frame", async () => {
37
- // Setup: Set thisTarget to have tabId: 1, frameId: 0
38
- const mockThisTarget = {
39
- tabId: 1,
40
- frameId: 0,
41
- page: "test",
42
- };
43
- vi.spyOn(thisTargetModule, "thisTarget", "get").mockReturnValue(mockThisTarget);
44
- // Register a local handler
45
- const mockHandler = vi.fn(async () => "local result");
46
- handlers.set("testMethod", mockHandler);
47
- // Import messenger after mocks are set up
48
- const { messenger } = await import("./sender.js");
49
- // Test: Send message to same tab and frame
50
- const result = await messenger("testMethod", {}, { tabId: 1, frameId: 0 });
51
- // Verify: Handler was called locally
52
- expect(mockHandler).toHaveBeenCalledOnce();
53
- expect(mockHandler).toHaveBeenCalledWith();
54
- expect(result).toBe("local result");
55
- // Verify: No message was sent via chrome.runtime.sendMessage
56
- expect(chrome.runtime.sendMessage).not.toHaveBeenCalled();
57
- });
58
- test("should send message when targeting different tab", async () => {
59
- // Setup: Set thisTarget to have tabId: 1, frameId: 0
60
- const mockThisTarget = {
61
- tabId: 1,
62
- frameId: 0,
63
- page: "test",
64
- };
65
- vi.spyOn(thisTargetModule, "thisTarget", "get").mockReturnValue(mockThisTarget);
66
- // Register a local handler (should not be used)
67
- const mockHandler = vi.fn(async () => "local result");
68
- handlers.set("testMethod", mockHandler);
69
- // Mock chrome.runtime.sendMessage to return a messenger response
70
- vi.mocked(chrome.runtime.sendMessage).mockResolvedValue({
71
- __webextMessenger: true,
72
- value: "remote result",
73
- });
74
- // Import messenger after mocks are set up
75
- const { messenger } = await import("./sender.js");
76
- // Test: Send message to different tab
77
- const result = await messenger("testMethod", {}, { tabId: 2, frameId: 0 });
78
- // Verify: Message was sent via chrome.runtime.sendMessage
79
- expect(chrome.runtime.sendMessage).toHaveBeenCalledOnce();
80
- expect(result).toBe("remote result");
81
- // Verify: Local handler was not called
82
- expect(mockHandler).not.toHaveBeenCalled();
83
- });
84
- test("should send message when targeting different frame in same tab", async () => {
85
- // Setup: Set thisTarget to have tabId: 1, frameId: 0
86
- const mockThisTarget = {
87
- tabId: 1,
88
- frameId: 0,
89
- page: "test",
90
- };
91
- vi.spyOn(thisTargetModule, "thisTarget", "get").mockReturnValue(mockThisTarget);
92
- // Register a local handler (should not be used)
93
- const mockHandler = vi.fn(async () => "local result");
94
- handlers.set("testMethod", mockHandler);
95
- // Mock chrome.runtime.sendMessage to return a messenger response
96
- vi.mocked(chrome.runtime.sendMessage).mockResolvedValue({
97
- __webextMessenger: true,
98
- value: "remote result",
99
- });
100
- // Import messenger after mocks are set up
101
- const { messenger } = await import("./sender.js");
102
- // Test: Send message to different frame in same tab
103
- const result = await messenger("testMethod", {}, { tabId: 1, frameId: 1 });
104
- // Verify: Message was sent via chrome.runtime.sendMessage
105
- expect(chrome.runtime.sendMessage).toHaveBeenCalledOnce();
106
- expect(result).toBe("remote result");
107
- // Verify: Local handler was not called
108
- expect(mockHandler).not.toHaveBeenCalled();
109
- });
110
- test("should send message when targeting allFrames", async () => {
111
- // Setup: Set thisTarget to have tabId: 1, frameId: 0
112
- const mockThisTarget = {
113
- tabId: 1,
114
- frameId: 0,
115
- page: "test",
116
- };
117
- vi.spyOn(thisTargetModule, "thisTarget", "get").mockReturnValue(mockThisTarget);
118
- // Register a local handler (should not be used for allFrames)
119
- const mockHandler = vi.fn(async () => "local result");
120
- handlers.set("testMethod", mockHandler);
121
- // Mock chrome.runtime.sendMessage to return a messenger response
122
- vi.mocked(chrome.runtime.sendMessage).mockResolvedValue({
123
- __webextMessenger: true,
124
- value: "remote result",
125
- });
126
- // Import messenger after mocks are set up
127
- const { messenger } = await import("./sender.js");
128
- // Test: Send message to allFrames in same tab
129
- const result = await messenger("testMethod", {}, { tabId: 1, frameId: "allFrames" });
130
- // Verify: Message was sent via chrome.runtime.sendMessage
131
- expect(chrome.runtime.sendMessage).toHaveBeenCalledOnce();
132
- expect(result).toBe("remote result");
133
- // Verify: Local handler was not called
134
- expect(mockHandler).not.toHaveBeenCalled();
135
- });
136
- test("should throw error when no local handler registered for same tab/frame", async () => {
137
- // Setup: Set thisTarget to have tabId: 1, frameId: 0
138
- const mockThisTarget = {
139
- tabId: 1,
140
- frameId: 0,
141
- page: "test",
142
- };
143
- vi.spyOn(thisTargetModule, "thisTarget", "get").mockReturnValue(mockThisTarget);
144
- // No handler registered
145
- // Import messenger and MessengerError after mocks are set up
146
- const { messenger } = await import("./sender.js");
147
- const { MessengerError } = await import("./shared.js");
148
- // Test: Send message to same tab and frame without handler
149
- try {
150
- await messenger("testMethod", {}, { tabId: 1, frameId: 0 });
151
- expect.fail("Should have thrown an error");
152
- }
153
- catch (error) {
154
- expect(error).toBeInstanceOf(MessengerError);
155
- expect(error.message).toBe("No handler registered locally for testMethod");
156
- }
157
- // Verify: No message was sent via chrome.runtime.sendMessage
158
- expect(chrome.runtime.sendMessage).not.toHaveBeenCalled();
159
- });
160
- });