New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

webext-messenger

Package Overview
Dependencies
Maintainers
3
Versions
82
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

webext-messenger - npm Package Compare versions

Comparing version 0.26.0 to 0.27.0

distribution/targetLogic.d.ts

14

distribution/receiver.js

@@ -6,4 +6,5 @@ import { serializeError } from "serialize-error";

import { log } from "./logging.js";
import { getActionForMessage } from "./thisTarget.js";
import { getActionForMessage } from "./targetLogic.js";
import { didUserRegisterMethods, handlers } from "./handlers.js";
import { getTabDataStatus, thisTarget } from "./thisTarget.js";
export function isMessengerMessage(message) {

@@ -22,4 +23,9 @@ return (isObject(message) &&

// Target check must be synchronous (`await` means we're handling the message)
const action = getActionForMessage(sender, message);
const action = getActionForMessage(sender, message.target, thisTarget);
if (action === "ignore") {
log.debug(message.type, "🤫 ignored due to target mismatch", {
requestedTarget: message.target,
thisTarget,
tabDataStatus: getTabDataStatus(),
});
return;

@@ -79,4 +85,2 @@ }

/** Ensure/document that the current function was called via Messenger */
export function assertMessengerCall(_this
// eslint-disable-next-line @typescript-eslint/no-empty-function -- TypeScript already does this, it's a documentation-only call
) { }
export function assertMessengerCall(_this) { }

@@ -138,3 +138,3 @@ import pRetry from "p-retry";

// Tab 2 sends: 12000, 12001, 12002
let globalSeq = (Date.now() % 100) * 10000;
let globalSeq = (Date.now() % 100) * 10_000;
function messenger(type, options, target, ...args) {

@@ -141,0 +141,0 @@ options.seq = globalSeq++;

@@ -1,3 +0,25 @@

import { type AnyTarget, type TopLevelFrame, type Message, type MessengerMeta, type Sender, type FrameTarget } from "./types.js";
export declare function getActionForMessage(from: Sender, message: Message): "respond" | "forward" | "ignore";
import { type AnyTarget, type KnownTarget, type TopLevelFrame, type MessengerMeta, type FrameTarget } from "./types.js";
/**
* @file This file exists because `runtime.sendMessage` acts as a broadcast to
* all open extension pages, so the receiver needs a way to figure out if the
* message was intended for them.
*
* If the requested target only includes a `page` (URL), then it can be determined
* immediately. If the target also specifies a tab, like `{tabId: 1, page: '/sidebar.html'}`,
* then the receiving target needs to fetch the tab information via `__getTabData`.
*
* `__getTabData` is called automatically when `webext-messenger` is imported in
* a context that requires this logic (most extension:// pages).
*
* If a broadcast message with `tabId` target is received before `__getTabData` is "received",
* the message will be ignored and it can be retried. If `__getTabData` somehow fails,
* the target will forever ignore any messages that require the `tabId`. In that case,
* an error would be thrown once and will be visible in the console, uncaught.
*
* Content scripts do not use this logic at all at the moment because they're
* always targeted via `tabId/frameId` combo and `tabs.sendMessage`.
*/
export declare const thisTarget: KnownTarget;
declare let tabDataStatus: "needed" | "pending" | "received" | "not-needed" | "error";
export declare function getTabDataStatus(): typeof tabDataStatus;
export declare function __getTabData(this: MessengerMeta): AnyTarget;

@@ -7,1 +29,2 @@ export declare function getThisFrame(): Promise<FrameTarget>;

export declare function initPrivateApi(): void;
export {};

@@ -1,6 +0,5 @@

import { getContextName, isBackground, isContentScript, isExtensionContext, } from "webext-detect-page";
import { getContextName, isBackground, isExtensionContext, } from "webext-detect-page";
import { messenger } from "./sender.js";
import { registerMethods } from "./receiver.js";
import { MessengerError, once } from "./shared.js";
import { log } from "./logging.js";
/**

@@ -29,3 +28,3 @@ * @file This file exists because `runtime.sendMessage` acts as a broadcast to

// If a message is received before this is ready, it will just have to be ignored.
const thisTarget = isBackground()
export const thisTarget = isBackground()
? { page: "background" }

@@ -45,54 +44,5 @@ : {

isBackground() ? "not-needed" : "needed";
function compareTargets(to, thisTarget) {
for (const [key, value] of Object.entries(to)) {
if (thisTarget[key] === value) {
continue;
}
if (key !== "page") {
return false;
}
const toUrl = new URL(to.page, location.origin);
const thisUrl = new URL(thisTarget.page, location.origin);
if (toUrl.pathname !== thisUrl.pathname) {
return false;
}
for (const [parameterKey, parameterValue] of toUrl.searchParams) {
if (thisUrl.searchParams.get(parameterKey) !== parameterValue) {
return false;
}
}
}
return true;
export function getTabDataStatus() {
return tabDataStatus;
}
// TODO: Test this in Jest, outside the browser
export function getActionForMessage(from, message) {
// Clone object because we're editing it
const to = { ...message.target };
if (to.page === "any") {
return "respond";
}
// Content scripts only receive messages that are meant for them. In the future
// they'll also forward them, but that still means they need to be handled here.
if (isContentScript()) {
return "respond";
}
// We're in an extension page, but the target is not one.
if (!to.page) {
return "forward";
}
// Set "this" tab to the current tabId
if (to.tabId === "this" && thisTarget.tabId === from.tab?.id) {
to.tabId = thisTarget.tabId;
}
// Every `target` key must match `thisTarget`
const isThisTarget = compareTargets(to, thisTarget);
if (!isThisTarget) {
log.debug(message.type, "🤫 ignored due to target mismatch", {
requestedTarget: to,
thisTarget,
tabDataStatus,
});
}
return isThisTarget ? "respond" : "ignore";
}
const storeTabData = once(async () => {

@@ -104,5 +54,3 @@ if (tabDataStatus !== "needed") {

tabDataStatus = "pending";
Object.assign(thisTarget, {
...(await messenger("__getTabData", {}, { page: "any" })),
});
Object.assign(thisTarget, await messenger("__getTabData", {}, { page: "any" }));
tabDataStatus = "received";

@@ -125,3 +73,4 @@ }

try {
moreInfo = `(context: ${getContextName()}, url: ${globalThis.location?.href})`;
moreInfo = `(context: ${getContextName()}, url: ${globalThis.location
?.href})`;
}

@@ -128,0 +77,0 @@ catch { }

{
"name": "webext-messenger",
"version": "0.26.0",
"version": "0.27.0",
"description": "Browser Extension component messaging framework",

@@ -12,3 +12,3 @@ "keywords": [],

".": {
"types": "./distribution/index.js",
"types": "./distribution/index.d.ts",
"default": "./distribution/index.js"

@@ -23,3 +23,4 @@ },

"prepack": "tsc --sourceMap false",
"test": "eslint . && tsc --noEmit",
"test": "run-p test:unit lint build demo:build",
"test:unit": "vitest run",
"lint": "eslint .",

@@ -31,5 +32,5 @@ "fix": "eslint . --fix",

"p-retry": "^6.2.0",
"serialize-error": "^11.0.2",
"type-fest": "^4.10.2",
"webext-detect-page": "^5.0.0"
"serialize-error": "^11.0.3",
"type-fest": "^4.13.0",
"webext-detect-page": "^5.0.1"
},

@@ -42,8 +43,8 @@ "@parcel/resolver-default": {

"@sindresorhus/tsconfig": "^5.0.0",
"@types/chrome": "^0.0.259",
"@types/chrome": "^0.0.263",
"@types/tape": "^5.6.4",
"@types/webextension-polyfill": "^0.10.7",
"buffer": "^6.0.3",
"eslint": "^8.56.0",
"eslint-config-pixiebrix": "^0.34.1",
"eslint": "^8.57.0",
"eslint-config-pixiebrix": "^0.37.2",
"events": "^3.3.0",

@@ -55,4 +56,5 @@ "npm-run-all": "^4.1.5",

"stream-browserify": "^3.0.0",
"tape": "^5.7.4",
"typescript": "^5.3.3",
"tape": "^5.7.5",
"typescript": "^5.4.2",
"vitest": "^1.4.0",
"webext-content-scripts": "^2.6.1",

@@ -59,0 +61,0 @@ "webextension-polyfill": "^0.10.0"

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc