Skip to content

Commit

Permalink
Merge pull request #52 from alesgenova/set-methods
Browse files Browse the repository at this point in the history
Add ability to set the exposed methods after a successful handshake
  • Loading branch information
alesgenova authored Feb 3, 2021
2 parents e128132 + 4030661 commit ca7e3f5
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 1 deletion.
27 changes: 27 additions & 0 deletions src/handles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ export interface RemoteHandle<
*
* - Emit custom events to the other end
*
* - Set the methods that are exposed to the other end
*
* @typeParam M - The methods exposed by this context
* @typeParam E - The events exposed by this context
*
Expand All @@ -117,6 +119,23 @@ export interface LocalHandle<
options?: EmitOptions
): void;

/**
* Set the methods that will be exposed to the other end of the connection.
*
* @param methods - An object mapping method names to functions
*
*/
setMethods(methods: M): void;

/**
* Set a specific method that will be exposed to the other end of the connection.
*
* @param methodName - The name of the method
* @param method - The function that will be exposed
*
*/
setMethod<K extends keyof M>(methodName: K, method: M[K]): void;

/**
* Specify which parts of the return value of a given method call should be transferred
* into the other context instead of cloned.
Expand Down Expand Up @@ -302,6 +321,14 @@ export class ConcreteLocalHandle<
this._dispatcher.emitToRemote(eventName as string, payload, transfer);
}

setMethods(methods: M) {
this._methods = methods;
}

setMethod<K extends keyof M>(methodName: K, method: M[K]) {
this._methods[methodName] = method;
}

setReturnTransfer<K extends keyof M>(
methodName: K,
transfer: (result: InnerType<ReturnType<M[K]>>) => Transferable[]
Expand Down
63 changes: 62 additions & 1 deletion tests/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { JSDOM } from 'jsdom';

import MessageEventJSDOM from 'jsdom/lib/jsdom/living/generated/MessageEvent';
import { fireAnEvent } from 'jsdom/lib/jsdom/living/helpers/events';
import { RemoteHandle } from '../src/handles';
import { LocalHandle, RemoteHandle } from '../src/handles';

type ChildMethods = {
foo: (x: number) => number;
Expand Down Expand Up @@ -830,3 +830,64 @@ test('callback', () => {
});
});
});

test('set methods', async () => {
const parentOrigin = 'https://parent.example.com';
const childOrigin = 'https://child.example.com';
const [parentWindow, childWindow] = makeWindows(parentOrigin, childOrigin);

const parentMessenger = new WindowMessenger({
localWindow: parentWindow,
remoteWindow: childWindow,
remoteOrigin: childWindow.origin,
});

const childMessenger = new WindowMessenger({
localWindow: childWindow,
remoteWindow: parentWindow,
remoteOrigin: parentWindow.origin,
});

const initialChildMethods = {
foo() {
return 1;
},
bar() {
return 1;
},
};

const [parentConnection, childConnection] = await Promise.all([
ParentHandshake(parentMessenger),
ChildHandshake(childMessenger, initialChildMethods),
] as const);

// Child code
{
const localHandle: LocalHandle<
typeof initialChildMethods
> = childConnection.localHandle();

const newChildMethods = {
foo() {
return 2;
},
bar() {
return 2;
},
};

localHandle.setMethods(newChildMethods);
localHandle.setMethod('bar', () => 3);
}

// Parent code
{
const remoteHandle: RemoteHandle<
typeof initialChildMethods
> = parentConnection.remoteHandle();

expect(await remoteHandle.call('foo')).toEqual(2);
expect(await remoteHandle.call('bar')).toEqual(3);
}
});

0 comments on commit ca7e3f5

Please sign in to comment.