Skip to content

Commit

Permalink
Support Promise<Target> in methods with static targets (#194)
Browse files Browse the repository at this point in the history
  • Loading branch information
fregante authored Jan 19, 2024
1 parent c919a54 commit f1508d9
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 12 deletions.
24 changes: 13 additions & 11 deletions source/sender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from "./types.js";
import { isObject, MessengerError, __webextMessenger } from "./shared.js";
import { log } from "./logging.js";
import { type SetReturnType } from "type-fest";
import { type Promisable, type SetReturnType } from "type-fest";
import { handlers } from "./handlers.js";
import { events } from "./events.js";

Expand Down Expand Up @@ -302,7 +302,7 @@ function getMethod<
Type extends keyof MessengerMethods,
Method extends MessengerMethods[Type],
PublicMethodType extends PublicMethod<Method>
>(type: Type, target: Target | PageTarget): PublicMethodType;
>(type: Type, target: Promisable<Target | PageTarget>): PublicMethodType;
function getMethod<
Type extends keyof MessengerMethods,
Method extends MessengerMethods[Type],
Expand All @@ -315,21 +315,21 @@ function getMethod<
PublicMethodWithDynamicTarget extends PublicMethodWithTarget<Method>
>(
type: Type,
target?: Target | PageTarget
target?: Promisable<Target | PageTarget>
): PublicMethodType | PublicMethodWithDynamicTarget {
if (arguments.length === 1) {
if (!target) {
return messenger.bind(undefined, type, {}) as PublicMethodWithDynamicTarget;
}

// @ts-expect-error `bind` types are junk
return messenger.bind(undefined, type, {}, target) as PublicMethodType;
return (async (...args: Parameters<Method>) =>
messenger(type, {}, await target, ...args)) as PublicMethodType;
}

function getNotifier<
Type extends keyof MessengerMethods,
Method extends MessengerMethods[Type],
PublicMethodType extends SetReturnType<PublicMethod<Method>, void>
>(type: Type, target: Target | PageTarget): PublicMethodType;
>(type: Type, target: Promisable<Target | PageTarget>): PublicMethodType;
function getNotifier<
Type extends keyof MessengerMethods,
Method extends MessengerMethods[Type],
Expand All @@ -348,10 +348,10 @@ function getNotifier<
>
>(
type: Type,
target?: Target | PageTarget
target?: Promisable<Target | PageTarget>
): PublicMethodType | PublicMethodWithDynamicTarget {
const options = { isNotification: true };
if (arguments.length === 1) {
if (!target) {
// @ts-expect-error `bind` types are junk
return messenger.bind(
undefined,
Expand All @@ -360,8 +360,10 @@ function getNotifier<
) as PublicMethodWithDynamicTarget;
}

// @ts-expect-error `bind` types are junk
return messenger.bind(undefined, type, options, target) as PublicMethodType;
return ((...args: Parameters<Method>) => {
// Async wrapper needed to use `await` while preserving a non-Promise return type
(async () => messenger(type, options, await target, ...args))();
}) as PublicMethodType;
}

export { messenger, getMethod, getNotifier };
Expand Down
18 changes: 17 additions & 1 deletion source/test/contentscript/api.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import test from "tape";
import { isBackground, isContentScript, isWebPage } from "webext-detect-page";
import { type PageTarget, type Sender, type Target } from "../../index.js";
import { errorTabDoesntExist, errorTargetClosedEarly } from "../../sender.js";
import {
errorTabDoesntExist,
errorTargetClosedEarly,
getMethod,
} from "../../sender.js";
import {
expectRejection,
sleep,
Expand Down Expand Up @@ -393,6 +397,18 @@ function additionalTests() {
getPageTitleNotification({ tabId });
await closeTab(tabId);
});

test("should support target promises in methods with static targets", async (t) => {
const tabIdPromise = openTab(
"https://fregante.github.io/pixiebrix-testing-ground/Will-receive-CS-calls/Promised-target"
);
const targetPromise = tabIdPromise.then((tabId) => ({ tabId }));

const request = getMethod("getPageTitle", targetPromise);
t.equal(await request(), "Promised target");

await closeTab(await tabIdPromise);
});
}

void testEveryTarget();
Expand Down

0 comments on commit f1508d9

Please sign in to comment.