-
Notifications
You must be signed in to change notification settings - Fork 152
Expand file tree
/
Copy pathfunction.ts
More file actions
74 lines (67 loc) · 2.65 KB
/
Copy pathfunction.ts
File metadata and controls
74 lines (67 loc) · 2.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import { TransferrableKeys } from '../transfer/TransferrableKeys.js';
import { Document } from './dom/Document.js';
import { MessageToWorker, MessageType, FunctionCallToWorker, ResolveOrReject } from '../transfer/Messages.js';
import { transfer } from './MutationTransfer.js';
import { TransferrableMutationType } from '../transfer/TransferrableMutation.js';
import { store } from './strings.js';
import { DocumentStub } from './dom/DocumentStub.js';
const exportedFunctions: { [fnIdent: string]: Function } = {};
export function callFunctionMessageHandler(event: MessageEvent, document: Document | DocumentStub) {
const msg = event.data as MessageToWorker;
if (msg[TransferrableKeys.type] !== MessageType.FUNCTION) {
return;
}
const functionMessage = msg as FunctionCallToWorker;
const fnIdentifier = functionMessage[TransferrableKeys.functionIdentifier];
const fnArguments = JSON.parse(functionMessage[TransferrableKeys.functionArguments]);
const index = functionMessage[TransferrableKeys.index];
const fn = exportedFunctions[fnIdentifier];
if (!fn) {
transfer(document, [
TransferrableMutationType.FUNCTION_CALL,
ResolveOrReject.REJECT,
index,
store(JSON.stringify({
stack: '',
message: `[worker-dom]: Exported function "${fnIdentifier}" could not be found.`
})),
]);
return;
}
Promise.resolve(fn) // Forcing promise flows allows us to skip a try/catch block.
.then((f) => f.apply(null, fnArguments))
.then(
(value) => {
transfer(document, [TransferrableMutationType.FUNCTION_CALL, ResolveOrReject.RESOLVE, index, store(JSON.stringify(value))]);
},
(err: Error) => {
const errorMessage = JSON.stringify(err.message || err);
transfer(document, [
TransferrableMutationType.FUNCTION_CALL,
ResolveOrReject.REJECT,
index,
store(JSON.stringify({
stack: err.stack || '',
message: `[worker-dom]: Function "${fnIdentifier}" threw: "${errorMessage}"`
}))
]);
},
);
}
export function exportFunction(name: string, fn: Function) {
if (!name || name === '') {
throw new Error(`[worker-dom]: Attempt to export function was missing an identifier.`);
}
if (typeof fn !== 'function') {
throw new Error(`[worker-dom]: Attempt to export non-function failed: ("${name}", ${typeof fn}).`);
}
if (name in exportedFunctions) {
throw new Error(`[worker-dom]: Attempt to re-export function failed: "${name}".`);
}
exportedFunctions[name] = fn;
}
export function resetForTesting() {
for (const key of Object.keys(exportedFunctions)) {
delete exportedFunctions[key];
}
}