-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathworker.ts
132 lines (111 loc) · 3.81 KB
/
worker.ts
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import {Deferred, guid, IDeferred, IProxyAnswer, IProxyArg, IProxyRequest, isPlainObject, isPrimitive} from './proxy';
const requests = new Map<string, IDeferred>();
const objects = new Map<string, any>();
const callbacks = new Map<string, any>();
const dedicatedWorkerGlobalScope: any = self;
const onmessage = dedicatedWorkerGlobalScope.onmessage;
dedicatedWorkerGlobalScope.onmessage = (...args) => {
if (onmessage) {
onmessage.apply(null, args);
}
onMessage.apply(null, args);
};
function onMessage({data}) {
const message: IProxyAnswer = data;
if (!(message.type && message.requestId)) {
return;
}
if (message.type === 'plain') {
const request = requests.get(message.requestId);
if (request) {
requests.delete(message.requestId);
request.resolve(message.result);
}
} else if (message.type === 'proxy') {
const request = requests.get(message.requestId);
if (request) {
requests.delete(message.requestId);
request.resolve(objects.get(message.requestId));
}
} else if (message.type === 'function') {
const callback = callbacks.get(message.requestId);
if (callback) {
const args = message.result.map((arg) => convertfromProxy(arg));
callback.apply(null, args);
}
}
}
function postMessage(objectId: string, action: string, args: any[]): any {
const requestId = guid();
const request: IProxyRequest = { type: 'proxy', objectId, requestId, action, args };
dedicatedWorkerGlobalScope.postMessage(request);
const deferred = new Deferred();
requests.set(requestId, deferred);
return WorkerProxyObject(requestId);
}
function getAction(target, name, receiver) {
let result;
if (name === 'then') {
const request = requests.get(target.parentId);
if (request) {
result = (resolve, reject) => {
return request.promise.then(resolve, reject);
};
}
} else {
result = postMessage(target.parentId, 'getAction', [name]);
}
return result;
}
function setAction(target, name, value) {
const valueProxy = convertToProxy(value);
postMessage(target.parentId, 'setAction', [name, valueProxy]);
return true;
}
function applyAction(target, thisValue, args = []) {
const argsProxy = args.map(convertToProxy);
return postMessage(target.parentId, 'applyAction', [argsProxy]);
}
export function WorkerProxyObject(parentId: string) {
let proxyObject = objects.get(parentId);
if (!proxyObject) {
const target: any = () => { /* */ };
target.parentId = parentId;
proxyObject = new Proxy(target, {
get: getAction,
set: setAction,
apply: applyAction,
});
objects.set(parentId, proxyObject);
}
return proxyObject;
}
function convertToProxy(obj: any): IProxyArg {
if (isPrimitive(obj) || isPlainObject(obj)) {
return {type: 'plain', value: obj};
} else if (typeof obj === 'function') {
const callbackId = guid();
callbacks.set(callbackId, obj);
return {type: 'function', value: callbackId};
} else {
return {type: 'proxy', value: obj};
}
}
function convertfromProxy(value: IProxyArg): any {
if (value.type === 'plain') {
return value.value;
} else if (value.type === 'function') {
throw new Error('Not Implemented');
} else if (value.type === 'proxy') {
const parentId = value.value;
const target: any = () => { /* */ };
target.parentId = parentId;
const proxyObject = new Proxy(target, {
get: getAction,
set: setAction,
apply: applyAction,
});
objects.set(parentId, proxyObject);
return proxyObject;
}
}