@farcaster/frame-host 0.0.21 → 0.0.23
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.
- package/dist/comlink/comlink.d.ts +1 -1
- package/dist/comlink/comlink.js +43 -42
- package/dist/comlink/index.d.ts +1 -1
- package/dist/comlink/index.js +1 -1
- package/dist/comlink/node-adapter.d.ts +1 -1
- package/dist/comlink/node-adapter.js +4 -4
- package/dist/comlink/protocol.d.ts +2 -2
- package/dist/comlink/protocol.js +16 -1
- package/dist/helpers/endpoint.d.ts +5 -5
- package/dist/helpers/endpoint.js +4 -4
- package/dist/helpers/provider.d.ts +2 -2
- package/dist/helpers/provider.js +31 -31
- package/dist/helpers/sdk.d.ts +1 -1
- package/dist/helpers/sdk.js +27 -4
- package/dist/iframe.d.ts +4 -4
- package/dist/iframe.js +6 -6
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +2 -2
- package/package.json +9 -5
- package/src/comlink/comlink.ts +184 -187
- package/src/comlink/index.ts +1 -1
- package/src/comlink/node-adapter.ts +18 -18
- package/src/comlink/protocol.ts +46 -46
- package/src/helpers/endpoint.ts +29 -29
- package/src/helpers/provider.ts +49 -49
- package/src/helpers/sdk.ts +32 -8
- package/src/iframe.ts +25 -25
- package/src/index.ts +4 -4
- package/src/types.ts +5 -5
package/src/comlink/comlink.ts
CHANGED
|
@@ -5,29 +5,29 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
-
Endpoint,
|
|
9
|
-
EventSource,
|
|
10
|
-
Message,
|
|
8
|
+
type Endpoint,
|
|
9
|
+
type EventSource,
|
|
10
|
+
type Message,
|
|
11
11
|
MessageType,
|
|
12
|
-
PostMessageWithOrigin,
|
|
13
|
-
WireValue,
|
|
12
|
+
type PostMessageWithOrigin,
|
|
13
|
+
type WireValue,
|
|
14
14
|
WireValueType,
|
|
15
|
-
} from
|
|
16
|
-
export type { Endpoint }
|
|
15
|
+
} from './protocol'
|
|
16
|
+
export type { Endpoint }
|
|
17
17
|
|
|
18
|
-
export const proxyMarker = Symbol(
|
|
19
|
-
export const createEndpoint = Symbol(
|
|
20
|
-
export const releaseProxy = Symbol(
|
|
21
|
-
export const finalizer = Symbol(
|
|
18
|
+
export const proxyMarker = Symbol('Comlink.proxy')
|
|
19
|
+
export const createEndpoint = Symbol('Comlink.endpoint')
|
|
20
|
+
export const releaseProxy = Symbol('Comlink.releaseProxy')
|
|
21
|
+
export const finalizer = Symbol('Comlink.finalizer')
|
|
22
22
|
|
|
23
|
-
const throwMarker = Symbol(
|
|
23
|
+
const throwMarker = Symbol('Comlink.thrown')
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Interface of values that were marked to be proxied with `comlink.proxy()`.
|
|
27
27
|
* Can also be implemented by classes.
|
|
28
28
|
*/
|
|
29
29
|
export interface ProxyMarked {
|
|
30
|
-
[proxyMarker]: true
|
|
30
|
+
[proxyMarker]: true
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
@@ -36,14 +36,14 @@ export interface ProxyMarked {
|
|
|
36
36
|
*
|
|
37
37
|
* This is the inverse of `Unpromisify<T>`.
|
|
38
38
|
*/
|
|
39
|
-
type Promisify<T> = T extends Promise<unknown> ? T : Promise<T
|
|
39
|
+
type Promisify<T> = T extends Promise<unknown> ? T : Promise<T>
|
|
40
40
|
/**
|
|
41
41
|
* Takes a type that may be Promise and unwraps the Promise type.
|
|
42
42
|
* If `P` is not a Promise, it returns `P`.
|
|
43
43
|
*
|
|
44
44
|
* This is the inverse of `Promisify<T>`.
|
|
45
45
|
*/
|
|
46
|
-
type Unpromisify<P> = P extends Promise<infer T> ? T : P
|
|
46
|
+
type Unpromisify<P> = P extends Promise<infer T> ? T : P
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* Takes the raw type of a remote property and returns the type that is visible to the local thread on the proxy.
|
|
@@ -55,7 +55,7 @@ type RemoteProperty<T> =
|
|
|
55
55
|
// If the value is a method, comlink will proxy it automatically.
|
|
56
56
|
// Objects are only proxied if they are marked to be proxied.
|
|
57
57
|
// Otherwise, the property is converted to a Promise that resolves the cloned value.
|
|
58
|
-
T extends Function | ProxyMarked ? Remote<T> : Promisify<T
|
|
58
|
+
T extends Function | ProxyMarked ? Remote<T> : Promisify<T>
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
61
|
* Takes the raw type of a property as a remote thread would see it through a proxy (e.g. when passed in as a function
|
|
@@ -68,17 +68,18 @@ type RemoteProperty<T> =
|
|
|
68
68
|
*/
|
|
69
69
|
type LocalProperty<T> = T extends Function | ProxyMarked
|
|
70
70
|
? Local<T>
|
|
71
|
-
: Unpromisify<T
|
|
71
|
+
: Unpromisify<T>
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
74
|
* Proxies `T` if it is a `ProxyMarked`, clones it otherwise (as handled by structured cloning and transfer handlers).
|
|
75
75
|
*/
|
|
76
|
-
export type ProxyOrClone<T> = T extends ProxyMarked ? Remote<T> : T
|
|
76
|
+
export type ProxyOrClone<T> = T extends ProxyMarked ? Remote<T> : T
|
|
77
77
|
/**
|
|
78
78
|
* Inverse of `ProxyOrClone<T>`.
|
|
79
79
|
*/
|
|
80
|
-
export type UnproxyOrClone<T> =
|
|
81
|
-
|
|
80
|
+
export type UnproxyOrClone<T> = T extends RemoteObject<ProxyMarked>
|
|
81
|
+
? Local<T>
|
|
82
|
+
: T
|
|
82
83
|
|
|
83
84
|
/**
|
|
84
85
|
* Takes the raw type of a remote object in the other thread and returns the type as it is visible to the local thread
|
|
@@ -88,7 +89,7 @@ export type UnproxyOrClone<T> =
|
|
|
88
89
|
*
|
|
89
90
|
* @template T The raw type of a remote object as seen in the other thread.
|
|
90
91
|
*/
|
|
91
|
-
export type RemoteObject<T> = { [P in keyof T]: RemoteProperty<T[P]> }
|
|
92
|
+
export type RemoteObject<T> = { [P in keyof T]: RemoteProperty<T[P]> }
|
|
92
93
|
/**
|
|
93
94
|
* Takes the type of an object as a remote thread would see it through a proxy (e.g. when passed in as a function
|
|
94
95
|
* argument) and returns the type that the local thread has to supply.
|
|
@@ -99,14 +100,14 @@ export type RemoteObject<T> = { [P in keyof T]: RemoteProperty<T[P]> };
|
|
|
99
100
|
*
|
|
100
101
|
* @template T The type of a proxied object.
|
|
101
102
|
*/
|
|
102
|
-
export type LocalObject<T> = { [P in keyof T]: LocalProperty<T[P]> }
|
|
103
|
+
export type LocalObject<T> = { [P in keyof T]: LocalProperty<T[P]> }
|
|
103
104
|
|
|
104
105
|
/**
|
|
105
106
|
* Additional special comlink methods available on each proxy returned by `Comlink.wrap()`.
|
|
106
107
|
*/
|
|
107
108
|
export interface ProxyMethods {
|
|
108
|
-
[createEndpoint]: () => Promise<MessagePort
|
|
109
|
-
[releaseProxy]: () => void
|
|
109
|
+
[createEndpoint]: () => Promise<MessagePort>
|
|
110
|
+
[releaseProxy]: () => void
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
/**
|
|
@@ -128,18 +129,18 @@ export type Remote<T> =
|
|
|
128
129
|
? {
|
|
129
130
|
new (
|
|
130
131
|
...args: {
|
|
131
|
-
[I in keyof TArguments]: UnproxyOrClone<TArguments[I]
|
|
132
|
+
[I in keyof TArguments]: UnproxyOrClone<TArguments[I]>
|
|
132
133
|
}
|
|
133
|
-
): Promisify<Remote<TInstance
|
|
134
|
+
): Promisify<Remote<TInstance>>
|
|
134
135
|
}
|
|
135
136
|
: unknown) &
|
|
136
137
|
// Include additional special comlink methods available on the proxy.
|
|
137
|
-
ProxyMethods
|
|
138
|
+
ProxyMethods
|
|
138
139
|
|
|
139
140
|
/**
|
|
140
141
|
* Expresses that a type can be either a sync or async.
|
|
141
142
|
*/
|
|
142
|
-
type MaybePromise<T> = Promise<T> | T
|
|
143
|
+
type MaybePromise<T> = Promise<T> | T
|
|
143
144
|
|
|
144
145
|
/**
|
|
145
146
|
* Takes the raw type of a remote object, function or class as a remote thread would see it through a proxy (e.g. when
|
|
@@ -154,8 +155,7 @@ export type Local<T> =
|
|
|
154
155
|
(T extends (...args: infer TArguments) => infer TReturn
|
|
155
156
|
? (
|
|
156
157
|
...args: { [I in keyof TArguments]: ProxyOrClone<TArguments[I]> }
|
|
157
|
-
) => // The raw function could either be sync or async, but is always proxied automatically
|
|
158
|
-
MaybePromise<UnproxyOrClone<Unpromisify<TReturn>>>
|
|
158
|
+
) => MaybePromise<UnproxyOrClone<Unpromisify<TReturn>>> // The raw function could either be sync or async, but is always proxied automatically
|
|
159
159
|
: unknown) &
|
|
160
160
|
// Handle construct signature (if present)
|
|
161
161
|
// The return of construct signatures is always proxied (whether marked or not)
|
|
@@ -163,15 +163,15 @@ export type Local<T> =
|
|
|
163
163
|
? {
|
|
164
164
|
new (
|
|
165
165
|
...args: {
|
|
166
|
-
[I in keyof TArguments]: ProxyOrClone<TArguments[I]
|
|
166
|
+
[I in keyof TArguments]: ProxyOrClone<TArguments[I]>
|
|
167
167
|
}
|
|
168
168
|
): // The raw constructor could either be sync or async, but is always proxied automatically
|
|
169
|
-
MaybePromise<Local<Unpromisify<TInstance
|
|
169
|
+
MaybePromise<Local<Unpromisify<TInstance>>>
|
|
170
170
|
}
|
|
171
|
-
: unknown)
|
|
171
|
+
: unknown)
|
|
172
172
|
|
|
173
173
|
const isObject = (val: unknown): val is object =>
|
|
174
|
-
(typeof val ===
|
|
174
|
+
(typeof val === 'object' && val !== null) || typeof val === 'function'
|
|
175
175
|
|
|
176
176
|
/**
|
|
177
177
|
* Customizes the serialization of certain values as determined by `canHandle()`.
|
|
@@ -185,21 +185,21 @@ export interface TransferHandler<T, S> {
|
|
|
185
185
|
* should serialize the value, which includes checking that it is of the right
|
|
186
186
|
* type (but can perform checks beyond that as well).
|
|
187
187
|
*/
|
|
188
|
-
canHandle(value: unknown): value is T
|
|
188
|
+
canHandle(value: unknown): value is T
|
|
189
189
|
|
|
190
190
|
/**
|
|
191
191
|
* Gets called with the value if `canHandle()` returned `true` to produce a
|
|
192
192
|
* value that can be sent in a message, consisting of structured-cloneable
|
|
193
193
|
* values and/or transferrable objects.
|
|
194
194
|
*/
|
|
195
|
-
serialize(value: T): [S, Transferable[]]
|
|
195
|
+
serialize(value: T): [S, Transferable[]]
|
|
196
196
|
|
|
197
197
|
/**
|
|
198
198
|
* Gets called to deserialize an incoming value that was serialized in the
|
|
199
199
|
* other thread with this transfer handler (known through the name it was
|
|
200
200
|
* registered under).
|
|
201
201
|
*/
|
|
202
|
-
deserialize(value: S): T
|
|
202
|
+
deserialize(value: S): T
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
/**
|
|
@@ -209,27 +209,27 @@ const proxyTransferHandler: TransferHandler<object, MessagePort> = {
|
|
|
209
209
|
canHandle: (val): val is ProxyMarked =>
|
|
210
210
|
isObject(val) && (val as ProxyMarked)[proxyMarker],
|
|
211
211
|
serialize(obj) {
|
|
212
|
-
const { port1, port2 } = new MessageChannel()
|
|
213
|
-
expose(obj, port1)
|
|
214
|
-
return [port2, [port2]]
|
|
212
|
+
const { port1, port2 } = new MessageChannel()
|
|
213
|
+
expose(obj, port1)
|
|
214
|
+
return [port2, [port2]]
|
|
215
215
|
},
|
|
216
216
|
deserialize(port) {
|
|
217
|
-
port.start()
|
|
218
|
-
return wrap(port)
|
|
217
|
+
port.start()
|
|
218
|
+
return wrap(port)
|
|
219
219
|
},
|
|
220
|
-
}
|
|
220
|
+
}
|
|
221
221
|
|
|
222
222
|
interface ThrownValue {
|
|
223
|
-
[throwMarker]: unknown
|
|
224
|
-
value: unknown
|
|
223
|
+
[throwMarker]: unknown // just needs to be present
|
|
224
|
+
value: unknown
|
|
225
225
|
}
|
|
226
226
|
type SerializedThrownValue =
|
|
227
227
|
| { isError: true; value: Error }
|
|
228
|
-
| { isError: false; value: unknown }
|
|
228
|
+
| { isError: false; value: unknown }
|
|
229
229
|
type PendingListenersMap = Map<
|
|
230
230
|
string,
|
|
231
231
|
(value: WireValue | PromiseLike<WireValue>) => void
|
|
232
|
-
|
|
232
|
+
>
|
|
233
233
|
|
|
234
234
|
/**
|
|
235
235
|
* Internal transfer handler to handle thrown exceptions.
|
|
@@ -241,7 +241,7 @@ const throwTransferHandler: TransferHandler<
|
|
|
241
241
|
canHandle: (value): value is ThrownValue =>
|
|
242
242
|
isObject(value) && throwMarker in value,
|
|
243
243
|
serialize({ value }) {
|
|
244
|
-
let serialized: SerializedThrownValue
|
|
244
|
+
let serialized: SerializedThrownValue
|
|
245
245
|
if (value instanceof Error) {
|
|
246
246
|
serialized = {
|
|
247
247
|
isError: true,
|
|
@@ -250,22 +250,19 @@ const throwTransferHandler: TransferHandler<
|
|
|
250
250
|
name: value.name,
|
|
251
251
|
stack: value.stack,
|
|
252
252
|
},
|
|
253
|
-
}
|
|
253
|
+
}
|
|
254
254
|
} else {
|
|
255
|
-
serialized = { isError: false, value }
|
|
255
|
+
serialized = { isError: false, value }
|
|
256
256
|
}
|
|
257
|
-
return [serialized, []]
|
|
257
|
+
return [serialized, []]
|
|
258
258
|
},
|
|
259
259
|
deserialize(serialized) {
|
|
260
260
|
if (serialized.isError) {
|
|
261
|
-
throw Object.assign(
|
|
262
|
-
new Error(serialized.value.message),
|
|
263
|
-
serialized.value,
|
|
264
|
-
);
|
|
261
|
+
throw Object.assign(new Error(serialized.value.message), serialized.value)
|
|
265
262
|
}
|
|
266
|
-
throw serialized.value
|
|
263
|
+
throw serialized.value
|
|
267
264
|
},
|
|
268
|
-
}
|
|
265
|
+
}
|
|
269
266
|
|
|
270
267
|
/**
|
|
271
268
|
* Allows customizing the serialization of certain values.
|
|
@@ -274,162 +271,162 @@ export const transferHandlers = new Map<
|
|
|
274
271
|
string,
|
|
275
272
|
TransferHandler<unknown, unknown>
|
|
276
273
|
>([
|
|
277
|
-
[
|
|
278
|
-
[
|
|
279
|
-
])
|
|
274
|
+
['proxy', proxyTransferHandler],
|
|
275
|
+
['throw', throwTransferHandler],
|
|
276
|
+
])
|
|
280
277
|
|
|
281
278
|
function isAllowedOrigin(
|
|
282
279
|
allowedOrigins: (string | RegExp)[],
|
|
283
280
|
origin: string,
|
|
284
281
|
): boolean {
|
|
285
282
|
for (const allowedOrigin of allowedOrigins) {
|
|
286
|
-
if (origin === allowedOrigin || allowedOrigin ===
|
|
287
|
-
return true
|
|
283
|
+
if (origin === allowedOrigin || allowedOrigin === '*') {
|
|
284
|
+
return true
|
|
288
285
|
}
|
|
289
286
|
if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) {
|
|
290
|
-
return true
|
|
287
|
+
return true
|
|
291
288
|
}
|
|
292
289
|
}
|
|
293
|
-
return false
|
|
290
|
+
return false
|
|
294
291
|
}
|
|
295
292
|
|
|
296
293
|
export function expose(
|
|
297
294
|
obj: any,
|
|
298
295
|
ep: Endpoint = globalThis as any,
|
|
299
|
-
allowedOrigins: (string | RegExp)[] = [
|
|
296
|
+
allowedOrigins: (string | RegExp)[] = ['*'],
|
|
300
297
|
) {
|
|
301
298
|
function callback(ev: MessageEvent) {
|
|
302
299
|
if (!ev || !ev.data) {
|
|
303
|
-
return
|
|
300
|
+
return
|
|
304
301
|
}
|
|
305
302
|
if (!isAllowedOrigin(allowedOrigins, ev.origin)) {
|
|
306
|
-
console.warn(`Invalid origin '${ev.origin}' for comlink proxy`)
|
|
307
|
-
return
|
|
303
|
+
console.warn(`Invalid origin '${ev.origin}' for comlink proxy`)
|
|
304
|
+
return
|
|
308
305
|
}
|
|
309
306
|
const { id, type, path } = {
|
|
310
307
|
path: [] as string[],
|
|
311
308
|
...(ev.data as Message),
|
|
312
|
-
}
|
|
313
|
-
const argumentList = (ev.data.argumentList || []).map(fromWireValue)
|
|
314
|
-
let returnValue
|
|
309
|
+
}
|
|
310
|
+
const argumentList = (ev.data.argumentList || []).map(fromWireValue)
|
|
311
|
+
let returnValue
|
|
315
312
|
try {
|
|
316
|
-
const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj)
|
|
317
|
-
const rawValue = path.reduce((obj, prop) => obj[prop], obj)
|
|
313
|
+
const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj)
|
|
314
|
+
const rawValue = path.reduce((obj, prop) => obj[prop], obj)
|
|
318
315
|
switch (type) {
|
|
319
316
|
case MessageType.GET:
|
|
320
317
|
{
|
|
321
|
-
returnValue = rawValue
|
|
318
|
+
returnValue = rawValue
|
|
322
319
|
}
|
|
323
|
-
break
|
|
320
|
+
break
|
|
324
321
|
case MessageType.SET:
|
|
325
322
|
{
|
|
326
|
-
parent[path.slice(-1)[0]] = fromWireValue(ev.data.value)
|
|
327
|
-
returnValue = true
|
|
323
|
+
parent[path.slice(-1)[0]] = fromWireValue(ev.data.value)
|
|
324
|
+
returnValue = true
|
|
328
325
|
}
|
|
329
|
-
break
|
|
326
|
+
break
|
|
330
327
|
case MessageType.APPLY:
|
|
331
328
|
{
|
|
332
|
-
returnValue = rawValue.apply(parent, argumentList)
|
|
329
|
+
returnValue = rawValue.apply(parent, argumentList)
|
|
333
330
|
}
|
|
334
|
-
break
|
|
331
|
+
break
|
|
335
332
|
case MessageType.CONSTRUCT:
|
|
336
333
|
{
|
|
337
|
-
const value = new rawValue(...argumentList)
|
|
338
|
-
returnValue = proxy(value)
|
|
334
|
+
const value = new rawValue(...argumentList)
|
|
335
|
+
returnValue = proxy(value)
|
|
339
336
|
}
|
|
340
|
-
break
|
|
337
|
+
break
|
|
341
338
|
case MessageType.ENDPOINT:
|
|
342
339
|
{
|
|
343
|
-
const { port1, port2 } = new MessageChannel()
|
|
344
|
-
expose(obj, port2)
|
|
345
|
-
returnValue = transfer(port1, [port1])
|
|
340
|
+
const { port1, port2 } = new MessageChannel()
|
|
341
|
+
expose(obj, port2)
|
|
342
|
+
returnValue = transfer(port1, [port1])
|
|
346
343
|
}
|
|
347
|
-
break
|
|
344
|
+
break
|
|
348
345
|
case MessageType.RELEASE:
|
|
349
346
|
{
|
|
350
|
-
returnValue = undefined
|
|
347
|
+
returnValue = undefined
|
|
351
348
|
}
|
|
352
|
-
break
|
|
349
|
+
break
|
|
353
350
|
default:
|
|
354
|
-
return
|
|
351
|
+
return
|
|
355
352
|
}
|
|
356
353
|
} catch (value) {
|
|
357
|
-
returnValue = { value, [throwMarker]: 0 }
|
|
354
|
+
returnValue = { value, [throwMarker]: 0 }
|
|
358
355
|
}
|
|
359
356
|
Promise.resolve(returnValue)
|
|
360
357
|
.catch((value) => {
|
|
361
|
-
return { value, [throwMarker]: 0 }
|
|
358
|
+
return { value, [throwMarker]: 0 }
|
|
362
359
|
})
|
|
363
360
|
.then((returnValue) => {
|
|
364
|
-
const [wireValue, transferables] = toWireValue(returnValue)
|
|
365
|
-
ep.postMessage({ ...wireValue, id }, transferables)
|
|
361
|
+
const [wireValue, transferables] = toWireValue(returnValue)
|
|
362
|
+
ep.postMessage({ ...wireValue, id }, transferables)
|
|
366
363
|
if (type === MessageType.RELEASE) {
|
|
367
364
|
// detach and deactive after sending release response above.
|
|
368
|
-
ep.removeEventListener(
|
|
369
|
-
closeEndPoint(ep)
|
|
370
|
-
if (finalizer in obj && typeof obj[finalizer] ===
|
|
371
|
-
obj[finalizer]()
|
|
365
|
+
ep.removeEventListener('message', callback as any)
|
|
366
|
+
closeEndPoint(ep)
|
|
367
|
+
if (finalizer in obj && typeof obj[finalizer] === 'function') {
|
|
368
|
+
obj[finalizer]()
|
|
372
369
|
}
|
|
373
370
|
}
|
|
374
371
|
})
|
|
375
372
|
.catch((error) => {
|
|
376
373
|
// Send Serialization Error To Caller
|
|
377
374
|
const [wireValue, transferables] = toWireValue({
|
|
378
|
-
value: new TypeError(
|
|
375
|
+
value: new TypeError('Unserializable return value'),
|
|
379
376
|
[throwMarker]: 0,
|
|
380
|
-
})
|
|
381
|
-
ep.postMessage({ ...wireValue, id }, transferables)
|
|
382
|
-
})
|
|
377
|
+
})
|
|
378
|
+
ep.postMessage({ ...wireValue, id }, transferables)
|
|
379
|
+
})
|
|
383
380
|
}
|
|
384
381
|
|
|
385
|
-
ep.addEventListener(
|
|
382
|
+
ep.addEventListener('message', callback as any)
|
|
386
383
|
if (ep.start) {
|
|
387
|
-
ep.start()
|
|
384
|
+
ep.start()
|
|
388
385
|
}
|
|
389
386
|
|
|
390
387
|
return () => {
|
|
391
|
-
ep.removeEventListener(
|
|
392
|
-
closeEndPoint(ep)
|
|
393
|
-
if (finalizer in obj && typeof obj[finalizer] ===
|
|
394
|
-
obj[finalizer]()
|
|
388
|
+
ep.removeEventListener('message', callback as any)
|
|
389
|
+
closeEndPoint(ep)
|
|
390
|
+
if (finalizer in obj && typeof obj[finalizer] === 'function') {
|
|
391
|
+
obj[finalizer]()
|
|
395
392
|
}
|
|
396
|
-
}
|
|
393
|
+
}
|
|
397
394
|
}
|
|
398
395
|
|
|
399
396
|
function isMessagePort(endpoint: Endpoint): endpoint is MessagePort {
|
|
400
|
-
return endpoint.constructor.name ===
|
|
397
|
+
return endpoint.constructor.name === 'MessagePort'
|
|
401
398
|
}
|
|
402
399
|
|
|
403
400
|
function closeEndPoint(endpoint: Endpoint) {
|
|
404
|
-
if (isMessagePort(endpoint)) endpoint.close()
|
|
401
|
+
if (isMessagePort(endpoint)) endpoint.close()
|
|
405
402
|
}
|
|
406
403
|
|
|
407
404
|
export function wrap<T>(ep: Endpoint, target?: any): Remote<T> {
|
|
408
|
-
const pendingListeners: PendingListenersMap = new Map()
|
|
405
|
+
const pendingListeners: PendingListenersMap = new Map()
|
|
409
406
|
|
|
410
|
-
ep.addEventListener(
|
|
411
|
-
const { data } = ev as MessageEvent
|
|
407
|
+
ep.addEventListener('message', function handleMessage(ev: Event) {
|
|
408
|
+
const { data } = ev as MessageEvent
|
|
412
409
|
if (!data || !data.id) {
|
|
413
|
-
return
|
|
410
|
+
return
|
|
414
411
|
}
|
|
415
|
-
const resolver = pendingListeners.get(data.id)
|
|
412
|
+
const resolver = pendingListeners.get(data.id)
|
|
416
413
|
if (!resolver) {
|
|
417
|
-
return
|
|
414
|
+
return
|
|
418
415
|
}
|
|
419
416
|
|
|
420
417
|
try {
|
|
421
|
-
resolver(data)
|
|
418
|
+
resolver(data)
|
|
422
419
|
} finally {
|
|
423
|
-
pendingListeners.delete(data.id)
|
|
420
|
+
pendingListeners.delete(data.id)
|
|
424
421
|
}
|
|
425
|
-
})
|
|
422
|
+
})
|
|
426
423
|
|
|
427
|
-
return createProxy<T>(ep, pendingListeners, [], target) as any
|
|
424
|
+
return createProxy<T>(ep, pendingListeners, [], target) as any
|
|
428
425
|
}
|
|
429
426
|
|
|
430
427
|
function throwIfProxyReleased(isReleased: boolean) {
|
|
431
428
|
if (isReleased) {
|
|
432
|
-
throw new Error(
|
|
429
|
+
throw new Error('Proxy has been released and is not useable')
|
|
433
430
|
}
|
|
434
431
|
}
|
|
435
432
|
|
|
@@ -437,43 +434,43 @@ function releaseEndpoint(ep: Endpoint) {
|
|
|
437
434
|
return requestResponseMessage(ep, new Map(), {
|
|
438
435
|
type: MessageType.RELEASE,
|
|
439
436
|
}).then(() => {
|
|
440
|
-
closeEndPoint(ep)
|
|
441
|
-
})
|
|
437
|
+
closeEndPoint(ep)
|
|
438
|
+
})
|
|
442
439
|
}
|
|
443
440
|
|
|
444
441
|
interface FinalizationRegistry<T> {
|
|
445
|
-
new (cb: (heldValue: T) => void): FinalizationRegistry<T
|
|
442
|
+
new (cb: (heldValue: T) => void): FinalizationRegistry<T>
|
|
446
443
|
register(
|
|
447
444
|
weakItem: object,
|
|
448
445
|
heldValue: T,
|
|
449
446
|
unregisterToken?: object | undefined,
|
|
450
|
-
): void
|
|
451
|
-
unregister(unregisterToken: object): void
|
|
447
|
+
): void
|
|
448
|
+
unregister(unregisterToken: object): void
|
|
452
449
|
}
|
|
453
|
-
declare
|
|
450
|
+
declare let FinalizationRegistry: FinalizationRegistry<Endpoint>
|
|
454
451
|
|
|
455
|
-
const proxyCounter = new WeakMap<Endpoint, number>()
|
|
452
|
+
const proxyCounter = new WeakMap<Endpoint, number>()
|
|
456
453
|
const proxyFinalizers =
|
|
457
|
-
|
|
454
|
+
'FinalizationRegistry' in globalThis &&
|
|
458
455
|
new FinalizationRegistry((ep: Endpoint) => {
|
|
459
|
-
const newCount = (proxyCounter.get(ep) || 0) - 1
|
|
460
|
-
proxyCounter.set(ep, newCount)
|
|
456
|
+
const newCount = (proxyCounter.get(ep) || 0) - 1
|
|
457
|
+
proxyCounter.set(ep, newCount)
|
|
461
458
|
if (newCount === 0) {
|
|
462
|
-
releaseEndpoint(ep)
|
|
459
|
+
releaseEndpoint(ep)
|
|
463
460
|
}
|
|
464
|
-
})
|
|
461
|
+
})
|
|
465
462
|
|
|
466
463
|
function registerProxy(proxy: object, ep: Endpoint) {
|
|
467
|
-
const newCount = (proxyCounter.get(ep) || 0) + 1
|
|
468
|
-
proxyCounter.set(ep, newCount)
|
|
464
|
+
const newCount = (proxyCounter.get(ep) || 0) + 1
|
|
465
|
+
proxyCounter.set(ep, newCount)
|
|
469
466
|
if (proxyFinalizers) {
|
|
470
|
-
proxyFinalizers.register(proxy, ep, proxy)
|
|
467
|
+
proxyFinalizers.register(proxy, ep, proxy)
|
|
471
468
|
}
|
|
472
469
|
}
|
|
473
470
|
|
|
474
471
|
function unregisterProxy(proxy: object) {
|
|
475
472
|
if (proxyFinalizers) {
|
|
476
|
-
proxyFinalizers.unregister(proxy)
|
|
473
|
+
proxyFinalizers.unregister(proxy)
|
|
477
474
|
}
|
|
478
475
|
}
|
|
479
476
|
|
|
@@ -481,37 +478,37 @@ function createProxy<T>(
|
|
|
481
478
|
ep: Endpoint,
|
|
482
479
|
pendingListeners: PendingListenersMap,
|
|
483
480
|
path: (string | number | symbol)[] = [],
|
|
484
|
-
target: object =
|
|
481
|
+
target: object = () => {},
|
|
485
482
|
): Remote<T> {
|
|
486
|
-
let isProxyReleased = false
|
|
483
|
+
let isProxyReleased = false
|
|
487
484
|
const proxy = new Proxy(target, {
|
|
488
485
|
get(_target, prop) {
|
|
489
|
-
throwIfProxyReleased(isProxyReleased)
|
|
486
|
+
throwIfProxyReleased(isProxyReleased)
|
|
490
487
|
if (prop === releaseProxy) {
|
|
491
488
|
return () => {
|
|
492
|
-
unregisterProxy(proxy)
|
|
493
|
-
releaseEndpoint(ep)
|
|
494
|
-
pendingListeners.clear()
|
|
495
|
-
isProxyReleased = true
|
|
496
|
-
}
|
|
489
|
+
unregisterProxy(proxy)
|
|
490
|
+
releaseEndpoint(ep)
|
|
491
|
+
pendingListeners.clear()
|
|
492
|
+
isProxyReleased = true
|
|
493
|
+
}
|
|
497
494
|
}
|
|
498
|
-
if (prop ===
|
|
495
|
+
if (prop === 'then') {
|
|
499
496
|
if (path.length === 0) {
|
|
500
|
-
return { then: () => proxy }
|
|
497
|
+
return { then: () => proxy }
|
|
501
498
|
}
|
|
502
499
|
const r = requestResponseMessage(ep, pendingListeners, {
|
|
503
500
|
type: MessageType.GET,
|
|
504
501
|
path: path.map((p) => p.toString()),
|
|
505
|
-
}).then(fromWireValue)
|
|
506
|
-
return r.then.bind(r)
|
|
502
|
+
}).then(fromWireValue)
|
|
503
|
+
return r.then.bind(r)
|
|
507
504
|
}
|
|
508
|
-
return createProxy(ep, pendingListeners, [...path, prop])
|
|
505
|
+
return createProxy(ep, pendingListeners, [...path, prop])
|
|
509
506
|
},
|
|
510
507
|
set(_target, prop, rawValue) {
|
|
511
|
-
throwIfProxyReleased(isProxyReleased)
|
|
508
|
+
throwIfProxyReleased(isProxyReleased)
|
|
512
509
|
// FIXME: ES6 Proxy Handler `set` methods are supposed to return a
|
|
513
510
|
// boolean. To show good will, we return true asynchronously ¯\_(ツ)_/¯
|
|
514
|
-
const [value, transferables] = toWireValue(rawValue)
|
|
511
|
+
const [value, transferables] = toWireValue(rawValue)
|
|
515
512
|
return requestResponseMessage(
|
|
516
513
|
ep,
|
|
517
514
|
pendingListeners,
|
|
@@ -521,21 +518,21 @@ function createProxy<T>(
|
|
|
521
518
|
value,
|
|
522
519
|
},
|
|
523
520
|
transferables,
|
|
524
|
-
).then(fromWireValue) as any
|
|
521
|
+
).then(fromWireValue) as any
|
|
525
522
|
},
|
|
526
523
|
apply(_target, _thisArg, rawArgumentList) {
|
|
527
|
-
throwIfProxyReleased(isProxyReleased)
|
|
528
|
-
const last = path[path.length - 1]
|
|
524
|
+
throwIfProxyReleased(isProxyReleased)
|
|
525
|
+
const last = path[path.length - 1]
|
|
529
526
|
if ((last as any) === createEndpoint) {
|
|
530
527
|
return requestResponseMessage(ep, pendingListeners, {
|
|
531
528
|
type: MessageType.ENDPOINT,
|
|
532
|
-
}).then(fromWireValue)
|
|
529
|
+
}).then(fromWireValue)
|
|
533
530
|
}
|
|
534
531
|
// We just pretend that `bind()` didn’t happen.
|
|
535
|
-
if (last ===
|
|
536
|
-
return createProxy(ep, pendingListeners, path.slice(0, -1))
|
|
532
|
+
if (last === 'bind') {
|
|
533
|
+
return createProxy(ep, pendingListeners, path.slice(0, -1))
|
|
537
534
|
}
|
|
538
|
-
const [argumentList, transferables] = processArguments(rawArgumentList)
|
|
535
|
+
const [argumentList, transferables] = processArguments(rawArgumentList)
|
|
539
536
|
return requestResponseMessage(
|
|
540
537
|
ep,
|
|
541
538
|
pendingListeners,
|
|
@@ -545,11 +542,11 @@ function createProxy<T>(
|
|
|
545
542
|
argumentList,
|
|
546
543
|
},
|
|
547
544
|
transferables,
|
|
548
|
-
).then(fromWireValue)
|
|
545
|
+
).then(fromWireValue)
|
|
549
546
|
},
|
|
550
547
|
construct(_target, rawArgumentList) {
|
|
551
|
-
throwIfProxyReleased(isProxyReleased)
|
|
552
|
-
const [argumentList, transferables] = processArguments(rawArgumentList)
|
|
548
|
+
throwIfProxyReleased(isProxyReleased)
|
|
549
|
+
const [argumentList, transferables] = processArguments(rawArgumentList)
|
|
553
550
|
return requestResponseMessage(
|
|
554
551
|
ep,
|
|
555
552
|
pendingListeners,
|
|
@@ -559,49 +556,49 @@ function createProxy<T>(
|
|
|
559
556
|
argumentList,
|
|
560
557
|
},
|
|
561
558
|
transferables,
|
|
562
|
-
).then(fromWireValue)
|
|
559
|
+
).then(fromWireValue)
|
|
563
560
|
},
|
|
564
|
-
})
|
|
565
|
-
registerProxy(proxy, ep)
|
|
566
|
-
return proxy as any
|
|
561
|
+
})
|
|
562
|
+
registerProxy(proxy, ep)
|
|
563
|
+
return proxy as any
|
|
567
564
|
}
|
|
568
565
|
|
|
569
566
|
function myFlat<T>(arr: (T | T[])[]): T[] {
|
|
570
|
-
return Array.prototype.concat.apply([], arr)
|
|
567
|
+
return Array.prototype.concat.apply([], arr)
|
|
571
568
|
}
|
|
572
569
|
|
|
573
570
|
function processArguments(argumentList: any[]): [WireValue[], Transferable[]] {
|
|
574
|
-
const processed = argumentList.map(toWireValue)
|
|
575
|
-
return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))]
|
|
571
|
+
const processed = argumentList.map(toWireValue)
|
|
572
|
+
return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))]
|
|
576
573
|
}
|
|
577
574
|
|
|
578
|
-
const transferCache = new WeakMap<any, Transferable[]>()
|
|
575
|
+
const transferCache = new WeakMap<any, Transferable[]>()
|
|
579
576
|
export function transfer<T>(obj: T, transfers: Transferable[]): T {
|
|
580
|
-
transferCache.set(obj, transfers)
|
|
581
|
-
return obj
|
|
577
|
+
transferCache.set(obj, transfers)
|
|
578
|
+
return obj
|
|
582
579
|
}
|
|
583
580
|
|
|
584
581
|
export function proxy<T extends {}>(obj: T): T & ProxyMarked {
|
|
585
|
-
return Object.assign(obj, { [proxyMarker]: true }) as any
|
|
582
|
+
return Object.assign(obj, { [proxyMarker]: true }) as any
|
|
586
583
|
}
|
|
587
584
|
|
|
588
585
|
export function windowEndpoint(
|
|
589
586
|
w: PostMessageWithOrigin,
|
|
590
587
|
context: EventSource = globalThis,
|
|
591
|
-
targetOrigin =
|
|
588
|
+
targetOrigin = '*',
|
|
592
589
|
): Endpoint {
|
|
593
590
|
return {
|
|
594
591
|
postMessage: (msg: any, transferables: Transferable[]) =>
|
|
595
592
|
w.postMessage(msg, targetOrigin, transferables),
|
|
596
593
|
addEventListener: context.addEventListener.bind(context),
|
|
597
594
|
removeEventListener: context.removeEventListener.bind(context),
|
|
598
|
-
}
|
|
595
|
+
}
|
|
599
596
|
}
|
|
600
597
|
|
|
601
598
|
function toWireValue(value: any): [WireValue, Transferable[]] {
|
|
602
599
|
for (const [name, handler] of transferHandlers) {
|
|
603
600
|
if (handler.canHandle(value)) {
|
|
604
|
-
const [serializedValue, transferables] = handler.serialize(value)
|
|
601
|
+
const [serializedValue, transferables] = handler.serialize(value)
|
|
605
602
|
return [
|
|
606
603
|
{
|
|
607
604
|
type: WireValueType.HANDLER,
|
|
@@ -609,7 +606,7 @@ function toWireValue(value: any): [WireValue, Transferable[]] {
|
|
|
609
606
|
value: serializedValue,
|
|
610
607
|
},
|
|
611
608
|
transferables,
|
|
612
|
-
]
|
|
609
|
+
]
|
|
613
610
|
}
|
|
614
611
|
}
|
|
615
612
|
return [
|
|
@@ -618,15 +615,15 @@ function toWireValue(value: any): [WireValue, Transferable[]] {
|
|
|
618
615
|
value,
|
|
619
616
|
},
|
|
620
617
|
transferCache.get(value) || [],
|
|
621
|
-
]
|
|
618
|
+
]
|
|
622
619
|
}
|
|
623
620
|
|
|
624
621
|
function fromWireValue(value: WireValue): any {
|
|
625
622
|
switch (value.type) {
|
|
626
623
|
case WireValueType.HANDLER:
|
|
627
|
-
return transferHandlers.get(value.name)!.deserialize(value.value)
|
|
624
|
+
return transferHandlers.get(value.name)!.deserialize(value.value)
|
|
628
625
|
case WireValueType.RAW:
|
|
629
|
-
return value.value
|
|
626
|
+
return value.value
|
|
630
627
|
}
|
|
631
628
|
}
|
|
632
629
|
|
|
@@ -637,18 +634,18 @@ function requestResponseMessage(
|
|
|
637
634
|
transfers?: Transferable[],
|
|
638
635
|
): Promise<WireValue> {
|
|
639
636
|
return new Promise((resolve) => {
|
|
640
|
-
const id = generateUUID()
|
|
641
|
-
pendingListeners.set(id, resolve)
|
|
637
|
+
const id = generateUUID()
|
|
638
|
+
pendingListeners.set(id, resolve)
|
|
642
639
|
if (ep.start) {
|
|
643
|
-
ep.start()
|
|
640
|
+
ep.start()
|
|
644
641
|
}
|
|
645
|
-
ep.postMessage({ id, ...msg }, transfers)
|
|
646
|
-
})
|
|
642
|
+
ep.postMessage({ id, ...msg }, transfers)
|
|
643
|
+
})
|
|
647
644
|
}
|
|
648
645
|
|
|
649
646
|
function generateUUID(): string {
|
|
650
647
|
return new Array(4)
|
|
651
648
|
.fill(0)
|
|
652
649
|
.map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))
|
|
653
|
-
.join(
|
|
650
|
+
.join('-')
|
|
654
651
|
}
|