@scrypted/server 0.0.108 → 0.0.112
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.
Potentially problematic release.
This version of @scrypted/server might be problematic. Click here for more details.
- package/dist/event-registry.js +2 -2
- package/dist/event-registry.js.map +1 -1
- package/dist/plugin/plugin-api.js +2 -2
- package/dist/plugin/plugin-api.js.map +1 -1
- package/dist/plugin/plugin-device.js +1 -0
- package/dist/plugin/plugin-device.js.map +1 -1
- package/dist/plugin/plugin-host-api.js +10 -8
- package/dist/plugin/plugin-host-api.js.map +1 -1
- package/dist/plugin/plugin-npm-dependencies.js +16 -16
- package/dist/plugin/plugin-npm-dependencies.js.map +1 -1
- package/dist/plugin/system.js +11 -3
- package/dist/plugin/system.js.map +1 -1
- package/dist/rpc.js +57 -27
- package/dist/rpc.js.map +1 -1
- package/dist/state.js.map +1 -1
- package/package.json +1 -1
- package/python/plugin-remote.py +4 -4
- package/python/rpc.py +68 -26
- package/src/event-registry.ts +5 -5
- package/src/plugin/plugin-api.ts +4 -4
- package/src/plugin/plugin-device.ts +2 -1
- package/src/plugin/plugin-host-api.ts +11 -9
- package/src/plugin/plugin-npm-dependencies.ts +19 -18
- package/src/plugin/system.ts +15 -6
- package/src/rpc.ts +66 -26
- package/src/state.ts +2 -2
package/src/rpc.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import vm from 'vm';
|
|
2
2
|
|
|
3
|
+
const finalizerIdSymbol = Symbol('rpcFinalizerId');
|
|
4
|
+
|
|
3
5
|
function getDefaultTransportSafeArgumentTypes() {
|
|
4
6
|
const jsonSerializable = new Set<string>();
|
|
5
7
|
jsonSerializable.add(Number.name);
|
|
@@ -40,6 +42,7 @@ interface RpcOob extends RpcMessage {
|
|
|
40
42
|
|
|
41
43
|
interface RpcRemoteProxyValue {
|
|
42
44
|
__remote_proxy_id: string;
|
|
45
|
+
__remote_proxy_finalizer_id: string;
|
|
43
46
|
__remote_constructor_name: string;
|
|
44
47
|
__remote_proxy_props: any;
|
|
45
48
|
__remote_proxy_oneway_methods: string[];
|
|
@@ -52,6 +55,7 @@ interface RpcLocalProxyValue {
|
|
|
52
55
|
|
|
53
56
|
interface RpcFinalize extends RpcMessage {
|
|
54
57
|
__local_proxy_id: string;
|
|
58
|
+
__local_proxy_finalizer_id: string;
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
interface Deferred {
|
|
@@ -78,20 +82,17 @@ export const PROPERTY_PROXY_PROPERTIES = '__proxy_props';
|
|
|
78
82
|
export const PROPERTY_JSON_COPY_SERIALIZE_CHILDREN = '__json_copy_serialize_children';
|
|
79
83
|
|
|
80
84
|
class RpcProxy implements ProxyHandler<any> {
|
|
85
|
+
|
|
81
86
|
constructor(public peer: RpcPeer,
|
|
82
|
-
public
|
|
87
|
+
public entry: LocalProxiedEntry,
|
|
83
88
|
public constructorName: string,
|
|
84
89
|
public proxyProps: any,
|
|
85
90
|
public proxyOneWayMethods: string[]) {
|
|
86
|
-
this.peer = peer;
|
|
87
|
-
this.id = id;
|
|
88
|
-
this.constructorName = constructorName;
|
|
89
|
-
this.proxyProps = proxyProps;
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
get(target: any, p: PropertyKey, receiver: any): any {
|
|
93
94
|
if (p === '__proxy_id')
|
|
94
|
-
return this.id;
|
|
95
|
+
return this.entry.id;
|
|
95
96
|
if (p === '__proxy_constructor')
|
|
96
97
|
return this.constructorName;
|
|
97
98
|
if (p === '__proxy_peer')
|
|
@@ -114,8 +115,17 @@ class RpcProxy implements ProxyHandler<any> {
|
|
|
114
115
|
return new Proxy(() => p, this);
|
|
115
116
|
}
|
|
116
117
|
|
|
118
|
+
set(target: any, p: string | symbol, value: any, receiver: any): boolean {
|
|
119
|
+
if (p === finalizerIdSymbol)
|
|
120
|
+
this.entry.finalizerId = value;
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
|
|
117
124
|
apply(target: any, thisArg: any, argArray?: any): any {
|
|
118
|
-
|
|
125
|
+
// rpc objects can be functions. if the function is a oneway method,
|
|
126
|
+
// it will have a null in the oneway method list. this is because
|
|
127
|
+
// undefined is not JSON serializable.
|
|
128
|
+
const method = target() || null;
|
|
119
129
|
const args: any[] = [];
|
|
120
130
|
for (const arg of (argArray || [])) {
|
|
121
131
|
args.push(this.peer.serialize(arg));
|
|
@@ -124,7 +134,7 @@ class RpcProxy implements ProxyHandler<any> {
|
|
|
124
134
|
const rpcApply: RpcApply = {
|
|
125
135
|
type: "apply",
|
|
126
136
|
id: undefined,
|
|
127
|
-
proxyId: this.id,
|
|
137
|
+
proxyId: this.entry.id,
|
|
128
138
|
args,
|
|
129
139
|
method,
|
|
130
140
|
};
|
|
@@ -187,16 +197,21 @@ export interface RpcSerializer {
|
|
|
187
197
|
deserialize(serialized: any): any;
|
|
188
198
|
}
|
|
189
199
|
|
|
200
|
+
interface LocalProxiedEntry {
|
|
201
|
+
id: string;
|
|
202
|
+
finalizerId: string;
|
|
203
|
+
}
|
|
204
|
+
|
|
190
205
|
export class RpcPeer {
|
|
191
206
|
idCounter = 1;
|
|
192
207
|
onOob: (oob: any) => void;
|
|
193
208
|
params: { [name: string]: any } = {};
|
|
194
209
|
pendingResults: { [id: string]: Deferred } = {};
|
|
195
210
|
proxyCounter = 1;
|
|
196
|
-
localProxied = new Map<any,
|
|
211
|
+
localProxied = new Map<any, LocalProxiedEntry>();
|
|
197
212
|
localProxyMap: { [id: string]: any } = {};
|
|
198
213
|
remoteWeakProxies: { [id: string]: WeakRef<any> } = {};
|
|
199
|
-
finalizers = new FinalizationRegistry(
|
|
214
|
+
finalizers = new FinalizationRegistry(entry => this.finalize(entry as LocalProxiedEntry));
|
|
200
215
|
nameDeserializerMap = new Map<string, RpcSerializer>();
|
|
201
216
|
constructorSerializerMap = new Map<string, string>();
|
|
202
217
|
transportSafeArgumentTypes = getDefaultTransportSafeArgumentTypes();
|
|
@@ -238,10 +253,11 @@ export class RpcPeer {
|
|
|
238
253
|
this.constructorSerializerMap.set(ctr, name);
|
|
239
254
|
}
|
|
240
255
|
|
|
241
|
-
finalize(
|
|
242
|
-
delete this.remoteWeakProxies[id];
|
|
256
|
+
finalize(entry: LocalProxiedEntry) {
|
|
257
|
+
delete this.remoteWeakProxies[entry.id];
|
|
243
258
|
const rpcFinalize: RpcFinalize = {
|
|
244
|
-
__local_proxy_id: id,
|
|
259
|
+
__local_proxy_id: entry.id,
|
|
260
|
+
__local_proxy_finalizer_id: entry.finalizerId,
|
|
245
261
|
type: 'finalize',
|
|
246
262
|
}
|
|
247
263
|
this.send(rpcFinalize);
|
|
@@ -294,9 +310,12 @@ export class RpcPeer {
|
|
|
294
310
|
return ret;
|
|
295
311
|
}
|
|
296
312
|
|
|
297
|
-
const { __remote_proxy_id, __local_proxy_id, __remote_constructor_name, __serialized_value, __remote_proxy_props, __remote_proxy_oneway_methods } = value;
|
|
313
|
+
const { __remote_proxy_id, __remote_proxy_finalizer_id, __local_proxy_id, __remote_constructor_name, __serialized_value, __remote_proxy_props, __remote_proxy_oneway_methods } = value;
|
|
298
314
|
if (__remote_proxy_id) {
|
|
299
|
-
|
|
315
|
+
let proxy = this.remoteWeakProxies[__remote_proxy_id]?.deref();
|
|
316
|
+
if (!proxy)
|
|
317
|
+
proxy = this.newProxy(__remote_proxy_id, __remote_constructor_name, __remote_proxy_props, __remote_proxy_oneway_methods);
|
|
318
|
+
proxy[finalizerIdSymbol] = __remote_proxy_finalizer_id;
|
|
300
319
|
return proxy;
|
|
301
320
|
}
|
|
302
321
|
|
|
@@ -329,10 +348,13 @@ export class RpcPeer {
|
|
|
329
348
|
|
|
330
349
|
let __remote_constructor_name = value.__proxy_constructor || value.constructor?.name?.toString();
|
|
331
350
|
|
|
332
|
-
let
|
|
333
|
-
if (
|
|
351
|
+
let proxiedEntry = this.localProxied.get(value);
|
|
352
|
+
if (proxiedEntry) {
|
|
353
|
+
const __remote_proxy_finalizer_id = (this.proxyCounter++).toString();
|
|
354
|
+
proxiedEntry.finalizerId = __remote_proxy_finalizer_id;
|
|
334
355
|
const ret: RpcRemoteProxyValue = {
|
|
335
|
-
__remote_proxy_id:
|
|
356
|
+
__remote_proxy_id: proxiedEntry.id,
|
|
357
|
+
__remote_proxy_finalizer_id,
|
|
336
358
|
__remote_constructor_name,
|
|
337
359
|
__remote_proxy_props: value?.[PROPERTY_PROXY_PROPERTIES],
|
|
338
360
|
__remote_proxy_oneway_methods: value?.[PROPERTY_PROXY_ONEWAY_METHODS],
|
|
@@ -355,6 +377,7 @@ export class RpcPeer {
|
|
|
355
377
|
const serialized = serializer.serialize(value);
|
|
356
378
|
const ret: RpcRemoteProxyValue = {
|
|
357
379
|
__remote_proxy_id: undefined,
|
|
380
|
+
__remote_proxy_finalizer_id: undefined,
|
|
358
381
|
__remote_constructor_name,
|
|
359
382
|
__remote_proxy_props: value?.[PROPERTY_PROXY_PROPERTIES],
|
|
360
383
|
__remote_proxy_oneway_methods: value?.[PROPERTY_PROXY_ONEWAY_METHODS],
|
|
@@ -363,12 +386,17 @@ export class RpcPeer {
|
|
|
363
386
|
return ret;
|
|
364
387
|
}
|
|
365
388
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
389
|
+
const __remote_proxy_id = (this.proxyCounter++).toString();
|
|
390
|
+
proxiedEntry = {
|
|
391
|
+
id: __remote_proxy_id,
|
|
392
|
+
finalizerId: __remote_proxy_id,
|
|
393
|
+
};
|
|
394
|
+
this.localProxied.set(value, proxiedEntry);
|
|
395
|
+
this.localProxyMap[__remote_proxy_id] = value;
|
|
369
396
|
|
|
370
397
|
const ret: RpcRemoteProxyValue = {
|
|
371
|
-
__remote_proxy_id
|
|
398
|
+
__remote_proxy_id,
|
|
399
|
+
__remote_proxy_finalizer_id: __remote_proxy_id,
|
|
372
400
|
__remote_constructor_name,
|
|
373
401
|
__remote_proxy_props: value?.[PROPERTY_PROXY_PROPERTIES],
|
|
374
402
|
__remote_proxy_oneway_methods: value?.[PROPERTY_PROXY_ONEWAY_METHODS],
|
|
@@ -378,12 +406,16 @@ export class RpcPeer {
|
|
|
378
406
|
}
|
|
379
407
|
|
|
380
408
|
newProxy(proxyId: string, proxyConstructorName: string, proxyProps: any, proxyOneWayMethods: string[]) {
|
|
381
|
-
const
|
|
409
|
+
const localProxiedEntry: LocalProxiedEntry = {
|
|
410
|
+
id: proxyId,
|
|
411
|
+
finalizerId: undefined,
|
|
412
|
+
}
|
|
413
|
+
const rpc = new RpcProxy(this, localProxiedEntry, proxyConstructorName, proxyProps, proxyOneWayMethods);
|
|
382
414
|
const target = proxyConstructorName === 'Function' || proxyConstructorName === 'AsyncFunction' ? function () { } : rpc;
|
|
383
415
|
const proxy = new Proxy(target, rpc);
|
|
384
416
|
const weakref = new WeakRef(proxy);
|
|
385
417
|
this.remoteWeakProxies[proxyId] = weakref;
|
|
386
|
-
this.finalizers.register(rpc,
|
|
418
|
+
this.finalizers.register(rpc, localProxiedEntry);
|
|
387
419
|
global.gc?.();
|
|
388
420
|
return proxy;
|
|
389
421
|
}
|
|
@@ -460,8 +492,16 @@ export class RpcPeer {
|
|
|
460
492
|
case 'finalize': {
|
|
461
493
|
const rpcFinalize = message as RpcFinalize;
|
|
462
494
|
const local = this.localProxyMap[rpcFinalize.__local_proxy_id];
|
|
463
|
-
|
|
464
|
-
|
|
495
|
+
if (local) {
|
|
496
|
+
const localProxiedEntry = this.localProxied.get(local);
|
|
497
|
+
// if a finalizer id is specified, it must match.
|
|
498
|
+
if (rpcFinalize.__local_proxy_finalizer_id && rpcFinalize.__local_proxy_finalizer_id !== localProxiedEntry?.finalizerId) {
|
|
499
|
+
console.error(this.selfName, this.peerName, 'finalizer mismatch')
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
delete this.localProxyMap[rpcFinalize.__local_proxy_id];
|
|
503
|
+
this.localProxied.delete(local);
|
|
504
|
+
}
|
|
465
505
|
break;
|
|
466
506
|
}
|
|
467
507
|
case 'oob': {
|
package/src/state.ts
CHANGED
|
@@ -99,7 +99,7 @@ export class ScryptedStateManager extends EventRegistry {
|
|
|
99
99
|
return systemState;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
listenDevice(id: string, options: string | EventListenerOptions, callback: (eventDetails: EventDetails, eventData:
|
|
102
|
+
listenDevice(id: string, options: string | EventListenerOptions, callback: (eventDetails: EventDetails, eventData: any) => void): EventListenerRegister {
|
|
103
103
|
let { denoise, event, watch } = (options || {}) as EventListenerOptions;
|
|
104
104
|
if (!event && typeof options === 'string')
|
|
105
105
|
event = options as string;
|
|
@@ -124,7 +124,7 @@ export class ScryptedStateManager extends EventRegistry {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
let lastData: any = undefined;
|
|
127
|
-
let cb = (eventDetails: EventDetails, eventData:
|
|
127
|
+
let cb = (eventDetails: EventDetails, eventData: any) => {
|
|
128
128
|
if (denoise && lastData === eventData)
|
|
129
129
|
return;
|
|
130
130
|
callback(eventDetails, eventData);
|