@jsii/kernel 1.61.0 → 1.62.0
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/jest.config.mjs +3 -0
- package/lib/kernel.d.ts +4 -6
- package/lib/kernel.js +105 -114
- package/lib/objects.d.ts +2 -2
- package/lib/objects.js +15 -11
- package/lib/recording.js +1 -1
- package/lib/serialization.d.ts +9 -1
- package/lib/serialization.js +170 -90
- package/package.json +5 -5
package/jest.config.mjs
ADDED
package/lib/kernel.d.ts
CHANGED
|
@@ -5,11 +5,11 @@ export declare class Kernel {
|
|
|
5
5
|
* Set to true for verbose debugging.
|
|
6
6
|
*/
|
|
7
7
|
traceEnabled: boolean;
|
|
8
|
-
private assemblies;
|
|
8
|
+
private readonly assemblies;
|
|
9
9
|
private readonly objects;
|
|
10
|
-
private cbs;
|
|
11
|
-
private waiting;
|
|
12
|
-
private promises;
|
|
10
|
+
private readonly cbs;
|
|
11
|
+
private readonly waiting;
|
|
12
|
+
private readonly promises;
|
|
13
13
|
private nextid;
|
|
14
14
|
private syncInProgress?;
|
|
15
15
|
private installDir?;
|
|
@@ -79,8 +79,6 @@ export declare class Kernel {
|
|
|
79
79
|
* Executes arbitrary code in a VM sandbox.
|
|
80
80
|
*
|
|
81
81
|
* @param code JavaScript code to be executed in the VM
|
|
82
|
-
* @param sandbox a VM context to use for running the code
|
|
83
|
-
* @param sourceMaps source maps to be used in case an exception is thrown
|
|
84
82
|
* @param filename the file name to use for the executed code
|
|
85
83
|
*
|
|
86
84
|
* @returns the result of evaluating the code
|
package/lib/kernel.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Kernel = void 0;
|
|
4
4
|
const spec = require("@jsii/spec");
|
|
5
|
+
const spec_1 = require("@jsii/spec");
|
|
5
6
|
const cp = require("child_process");
|
|
6
7
|
const fs = require("fs-extra");
|
|
7
8
|
const os = require("os");
|
|
@@ -29,11 +30,11 @@ class Kernel {
|
|
|
29
30
|
* Set to true for verbose debugging.
|
|
30
31
|
*/
|
|
31
32
|
this.traceEnabled = false;
|
|
32
|
-
this.assemblies =
|
|
33
|
+
this.assemblies = new Map();
|
|
33
34
|
this.objects = new objects_1.ObjectTable(this._typeInfoForFqn.bind(this));
|
|
34
|
-
this.cbs =
|
|
35
|
-
this.waiting =
|
|
36
|
-
this.promises =
|
|
35
|
+
this.cbs = new Map();
|
|
36
|
+
this.waiting = new Map();
|
|
37
|
+
this.promises = new Map();
|
|
37
38
|
this.nextid = 20000; // incrementing counter for objid, cbid, promiseid
|
|
38
39
|
// `Buffer` is required when using simple-resource-bundler.
|
|
39
40
|
// HACK: when we webpack @jsii/runtime, all "require" statements get transpiled,
|
|
@@ -51,6 +52,7 @@ class Kernel {
|
|
|
51
52
|
});
|
|
52
53
|
}
|
|
53
54
|
load(req) {
|
|
55
|
+
var _a, _b;
|
|
54
56
|
this._debug('load', req);
|
|
55
57
|
if ('assembly' in req) {
|
|
56
58
|
throw new Error('`assembly` field is deprecated for "load", use `name`, `version` and `tarball` instead');
|
|
@@ -69,10 +71,10 @@ class Kernel {
|
|
|
69
71
|
}
|
|
70
72
|
// same version, no-op
|
|
71
73
|
this._debug('look up already-loaded assembly', pkgname);
|
|
72
|
-
const assm = this.assemblies
|
|
74
|
+
const assm = this.assemblies.get(pkgname);
|
|
73
75
|
return {
|
|
74
76
|
assembly: assm.metadata.name,
|
|
75
|
-
types: Object.keys(assm.metadata.types
|
|
77
|
+
types: Object.keys((_a = assm.metadata.types) !== null && _a !== void 0 ? _a : {}).length,
|
|
76
78
|
};
|
|
77
79
|
}
|
|
78
80
|
// Create the install directory (there may be several path components for @scoped/packages)
|
|
@@ -95,21 +97,24 @@ class Kernel {
|
|
|
95
97
|
process.umask(originalUmask);
|
|
96
98
|
}
|
|
97
99
|
// read .jsii metadata from the root of the package
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
let assmSpec;
|
|
101
|
+
try {
|
|
102
|
+
assmSpec = (0, spec_1.loadAssemblyFromPath)(packageDir);
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
throw new Error(`Error for package tarball ${req.tarball}: ${e.message}`);
|
|
101
106
|
}
|
|
102
|
-
const assmSpec = fs.readJsonSync(jsiiMetadataFile);
|
|
103
107
|
// load the module and capture it's closure
|
|
104
108
|
const closure = this._execute(`require(String.raw\`${packageDir}\`)`, packageDir);
|
|
105
109
|
const assm = new Assembly(assmSpec, closure);
|
|
106
110
|
this._addAssembly(assm);
|
|
107
111
|
return {
|
|
108
112
|
assembly: assmSpec.name,
|
|
109
|
-
types: Object.keys(assmSpec.types
|
|
113
|
+
types: Object.keys((_b = assmSpec.types) !== null && _b !== void 0 ? _b : {}).length,
|
|
110
114
|
};
|
|
111
115
|
}
|
|
112
116
|
invokeBinScript(req) {
|
|
117
|
+
var _a;
|
|
113
118
|
const packageDir = this._getPackageDir(req.assembly);
|
|
114
119
|
if (fs.pathExistsSync(packageDir)) {
|
|
115
120
|
// module exists, verify version
|
|
@@ -121,7 +126,7 @@ class Kernel {
|
|
|
121
126
|
if (!epkg.bin) {
|
|
122
127
|
throw new Error(`Script with name ${req.script} was not defined.`);
|
|
123
128
|
}
|
|
124
|
-
const result = cp.spawnSync(path.join(packageDir, scriptPath), req.args
|
|
129
|
+
const result = cp.spawnSync(path.join(packageDir, scriptPath), (_a = req.args) !== null && _a !== void 0 ? _a : [], {
|
|
125
130
|
encoding: 'utf-8',
|
|
126
131
|
env: {
|
|
127
132
|
...process.env,
|
|
@@ -161,7 +166,7 @@ class Kernel {
|
|
|
161
166
|
const prototype = this._findSymbol(fqn);
|
|
162
167
|
const value = this._ensureSync(`property ${property}`, () => this._wrapSandboxCode(() => prototype[property]));
|
|
163
168
|
this._debug('value:', value);
|
|
164
|
-
const ret = this._fromSandbox(value, ti);
|
|
169
|
+
const ret = this._fromSandbox(value, ti, `of static property ${symbol}`);
|
|
165
170
|
this._debug('ret', ret);
|
|
166
171
|
return { value: ret };
|
|
167
172
|
}
|
|
@@ -177,7 +182,7 @@ class Kernel {
|
|
|
177
182
|
throw new Error(`static property ${symbol} is readonly`);
|
|
178
183
|
}
|
|
179
184
|
const prototype = this._findSymbol(fqn);
|
|
180
|
-
this._ensureSync(`property ${property}`, () => this._wrapSandboxCode(() => (prototype[property] = this._toSandbox(value, ti))));
|
|
185
|
+
this._ensureSync(`property ${property}`, () => this._wrapSandboxCode(() => (prototype[property] = this._toSandbox(value, ti, `assigned to static property ${symbol}`))));
|
|
181
186
|
return {};
|
|
182
187
|
}
|
|
183
188
|
get(req) {
|
|
@@ -195,7 +200,7 @@ class Kernel {
|
|
|
195
200
|
// by jsii overrides.
|
|
196
201
|
const value = this._ensureSync(`property '${objref[api_1.TOKEN_REF]}.${propertyToGet}'`, () => this._wrapSandboxCode(() => instance[propertyToGet]));
|
|
197
202
|
this._debug('value:', value);
|
|
198
|
-
const ret = this._fromSandbox(value, ti);
|
|
203
|
+
const ret = this._fromSandbox(value, ti, `of property ${fqn}.${property}`);
|
|
199
204
|
this._debug('ret:', ret);
|
|
200
205
|
return { value: ret };
|
|
201
206
|
}
|
|
@@ -208,28 +213,31 @@ class Kernel {
|
|
|
208
213
|
throw new Error(`Cannot set value of immutable property ${req.property} to ${req.value}`);
|
|
209
214
|
}
|
|
210
215
|
const propertyToSet = this._findPropertyTarget(instance, property);
|
|
211
|
-
this._ensureSync(`property '${objref[api_1.TOKEN_REF]}.${propertyToSet}'`, () => this._wrapSandboxCode(() => (instance[propertyToSet] = this._toSandbox(value, propInfo))));
|
|
216
|
+
this._ensureSync(`property '${objref[api_1.TOKEN_REF]}.${propertyToSet}'`, () => this._wrapSandboxCode(() => (instance[propertyToSet] = this._toSandbox(value, propInfo, `assigned to property ${fqn}.${property}`))));
|
|
212
217
|
return {};
|
|
213
218
|
}
|
|
214
219
|
invoke(req) {
|
|
220
|
+
var _a, _b;
|
|
215
221
|
const { objref, method } = req;
|
|
216
|
-
const args = req.args
|
|
222
|
+
const args = (_a = req.args) !== null && _a !== void 0 ? _a : [];
|
|
217
223
|
this._debug('invoke', objref, method, args);
|
|
218
224
|
const { ti, obj, fn } = this._findInvokeTarget(objref, method, args);
|
|
219
225
|
// verify this is not an async method
|
|
220
226
|
if (ti.async) {
|
|
221
227
|
throw new Error(`${method} is an async method, use "begin" instead`);
|
|
222
228
|
}
|
|
229
|
+
const fqn = (0, objects_1.jsiiTypeFqn)(obj);
|
|
223
230
|
const ret = this._ensureSync(`method '${objref[api_1.TOKEN_REF]}.${method}'`, () => {
|
|
224
|
-
return this._wrapSandboxCode(() => fn.apply(obj, this._toSandboxValues(args, ti.parameters)));
|
|
231
|
+
return this._wrapSandboxCode(() => fn.apply(obj, this._toSandboxValues(args, `method ${fqn ? `${fqn}#` : ''}${method}`, ti.parameters)));
|
|
225
232
|
});
|
|
226
|
-
const result = this._fromSandbox(ret, ti.returns
|
|
233
|
+
const result = this._fromSandbox(ret, (_b = ti.returns) !== null && _b !== void 0 ? _b : 'void', `returned by method ${fqn ? `${fqn}#` : ''}${method}`);
|
|
227
234
|
this._debug('invoke result', result);
|
|
228
235
|
return { result };
|
|
229
236
|
}
|
|
230
237
|
sinvoke(req) {
|
|
238
|
+
var _a, _b;
|
|
231
239
|
const { fqn, method } = req;
|
|
232
|
-
const args = req.args
|
|
240
|
+
const args = (_a = req.args) !== null && _a !== void 0 ? _a : [];
|
|
233
241
|
this._debug('sinvoke', fqn, method, args);
|
|
234
242
|
const ti = this._typeInfoForMethod(method, fqn);
|
|
235
243
|
if (!ti.static) {
|
|
@@ -242,14 +250,17 @@ class Kernel {
|
|
|
242
250
|
const prototype = this._findSymbol(fqn);
|
|
243
251
|
const fn = prototype[method];
|
|
244
252
|
const ret = this._ensureSync(`method '${fqn}.${method}'`, () => {
|
|
245
|
-
return this._wrapSandboxCode(() => fn.apply(prototype, this._toSandboxValues(args, ti.parameters)));
|
|
253
|
+
return this._wrapSandboxCode(() => fn.apply(prototype, this._toSandboxValues(args, `static method ${fqn}.${method}`, ti.parameters)));
|
|
246
254
|
});
|
|
247
255
|
this._debug('method returned:', ret);
|
|
248
|
-
return {
|
|
256
|
+
return {
|
|
257
|
+
result: this._fromSandbox(ret, (_b = ti.returns) !== null && _b !== void 0 ? _b : 'void', `returned by static method ${fqn}.${method}`),
|
|
258
|
+
};
|
|
249
259
|
}
|
|
250
260
|
begin(req) {
|
|
261
|
+
var _a;
|
|
251
262
|
const { objref, method } = req;
|
|
252
|
-
const args = req.args
|
|
263
|
+
const args = (_a = req.args) !== null && _a !== void 0 ? _a : [];
|
|
253
264
|
this._debug('begin', objref, method, args);
|
|
254
265
|
if (this.syncInProgress) {
|
|
255
266
|
throw new Error(`Cannot invoke async method '${req.objref[api_1.TOKEN_REF]}.${req.method}' while sync ${this.syncInProgress} is being processed`);
|
|
@@ -259,25 +270,28 @@ class Kernel {
|
|
|
259
270
|
if (!ti.async) {
|
|
260
271
|
throw new Error(`Method ${method} is expected to be an async method`);
|
|
261
272
|
}
|
|
262
|
-
const
|
|
273
|
+
const fqn = (0, objects_1.jsiiTypeFqn)(obj);
|
|
274
|
+
const promise = this._wrapSandboxCode(() => fn.apply(obj, this._toSandboxValues(args, `async method ${fqn ? `${fqn}#` : ''}${method}`, ti.parameters)));
|
|
263
275
|
// since we are planning to resolve this promise in a different scope
|
|
264
276
|
// we need to handle rejections here [1]
|
|
265
277
|
// [1]: https://stackoverflow.com/questions/40920179/should-i-refrain-from-handling-promise-rejection-asynchronously/40921505
|
|
266
278
|
promise.catch((_) => undefined);
|
|
267
279
|
const prid = this._makeprid();
|
|
268
|
-
this.promises
|
|
280
|
+
this.promises.set(prid, {
|
|
269
281
|
promise,
|
|
270
282
|
method: ti,
|
|
271
|
-
};
|
|
283
|
+
});
|
|
272
284
|
return { promiseid: prid };
|
|
273
285
|
}
|
|
274
286
|
async end(req) {
|
|
287
|
+
var _a;
|
|
275
288
|
const { promiseid } = req;
|
|
276
289
|
this._debug('end', promiseid);
|
|
277
|
-
const
|
|
278
|
-
if (
|
|
290
|
+
const storedPromise = this.promises.get(promiseid);
|
|
291
|
+
if (storedPromise == null) {
|
|
279
292
|
throw new Error(`Cannot find promise with ID: ${promiseid}`);
|
|
280
293
|
}
|
|
294
|
+
const { promise, method } = storedPromise;
|
|
281
295
|
let result;
|
|
282
296
|
try {
|
|
283
297
|
result = await promise;
|
|
@@ -287,13 +301,15 @@ class Kernel {
|
|
|
287
301
|
this._debug('promise error:', e);
|
|
288
302
|
throw e;
|
|
289
303
|
}
|
|
290
|
-
return {
|
|
304
|
+
return {
|
|
305
|
+
result: this._fromSandbox(result, (_a = method.returns) !== null && _a !== void 0 ? _a : 'void', `returned by async method ${method.name}`),
|
|
306
|
+
};
|
|
291
307
|
}
|
|
292
308
|
callbacks(_req) {
|
|
293
309
|
this._debug('callbacks');
|
|
294
|
-
const ret =
|
|
295
|
-
|
|
296
|
-
this.
|
|
310
|
+
const ret = Array.from(this.cbs.entries()).map(([cbid, cb]) => {
|
|
311
|
+
this.waiting.set(cbid, cb); // move to waiting
|
|
312
|
+
this.cbs.delete(cbid); // remove from created
|
|
297
313
|
const callback = {
|
|
298
314
|
cbid,
|
|
299
315
|
cookie: cb.override.cookie,
|
|
@@ -305,27 +321,26 @@ class Kernel {
|
|
|
305
321
|
};
|
|
306
322
|
return callback;
|
|
307
323
|
});
|
|
308
|
-
// move all callbacks to the wait queue and clean the callback queue.
|
|
309
|
-
this.cbs = {};
|
|
310
324
|
return { callbacks: ret };
|
|
311
325
|
}
|
|
312
326
|
complete(req) {
|
|
327
|
+
var _a;
|
|
313
328
|
const { cbid, err, result } = req;
|
|
314
329
|
this._debug('complete', cbid, err, result);
|
|
315
|
-
|
|
330
|
+
const cb = this.waiting.get(cbid);
|
|
331
|
+
if (!cb) {
|
|
316
332
|
throw new Error(`Callback ${cbid} not found`);
|
|
317
333
|
}
|
|
318
|
-
const cb = this.waiting[cbid];
|
|
319
334
|
if (err) {
|
|
320
335
|
this._debug('completed with error:', err);
|
|
321
336
|
cb.fail(new Error(err));
|
|
322
337
|
}
|
|
323
338
|
else {
|
|
324
|
-
const sandoxResult = this._toSandbox(result, cb.expectedReturnType
|
|
339
|
+
const sandoxResult = this._toSandbox(result, (_a = cb.expectedReturnType) !== null && _a !== void 0 ? _a : 'void', `returned by callback ${cb.toString()}`);
|
|
325
340
|
this._debug('completed with result:', sandoxResult);
|
|
326
341
|
cb.succeed(sandoxResult);
|
|
327
342
|
}
|
|
328
|
-
|
|
343
|
+
this.waiting.delete(cbid);
|
|
329
344
|
return { cbid };
|
|
330
345
|
}
|
|
331
346
|
/**
|
|
@@ -348,10 +363,11 @@ class Kernel {
|
|
|
348
363
|
};
|
|
349
364
|
}
|
|
350
365
|
_addAssembly(assm) {
|
|
351
|
-
|
|
366
|
+
var _a;
|
|
367
|
+
this.assemblies.set(assm.metadata.name, assm);
|
|
352
368
|
// add the __jsii__.fqn property on every constructor. this allows
|
|
353
369
|
// traversing between the javascript and jsii worlds given any object.
|
|
354
|
-
for (const fqn of Object.keys(assm.metadata.types
|
|
370
|
+
for (const fqn of Object.keys((_a = assm.metadata.types) !== null && _a !== void 0 ? _a : {})) {
|
|
355
371
|
const typedef = assm.metadata.types[fqn];
|
|
356
372
|
switch (typedef.kind) {
|
|
357
373
|
case spec.TypeKind.Interface:
|
|
@@ -395,13 +411,14 @@ class Kernel {
|
|
|
395
411
|
// prefixed with _ to allow calling this method internally without
|
|
396
412
|
// getting it recorded for testing.
|
|
397
413
|
_create(req) {
|
|
414
|
+
var _a, _b;
|
|
398
415
|
this._debug('create', req);
|
|
399
416
|
const { fqn, interfaces, overrides } = req;
|
|
400
|
-
const requestArgs = req.args
|
|
417
|
+
const requestArgs = (_a = req.args) !== null && _a !== void 0 ? _a : [];
|
|
401
418
|
const ctorResult = this._findCtor(fqn, requestArgs);
|
|
402
419
|
const ctor = ctorResult.ctor;
|
|
403
|
-
const obj = this._wrapSandboxCode(() => new ctor(...this._toSandboxValues(requestArgs, ctorResult.parameters)));
|
|
404
|
-
const objref = this.objects.registerObject(obj, fqn, req.interfaces
|
|
420
|
+
const obj = this._wrapSandboxCode(() => new ctor(...this._toSandboxValues(requestArgs, `new ${fqn}`, ctorResult.parameters)));
|
|
421
|
+
const objref = this.objects.registerObject(obj, fqn, (_b = req.interfaces) !== null && _b !== void 0 ? _b : []);
|
|
405
422
|
// overrides: for each one of the override method names, installs a
|
|
406
423
|
// method on the newly created object which represents the remote "reverse proxy".
|
|
407
424
|
if (overrides) {
|
|
@@ -466,11 +483,12 @@ class Kernel {
|
|
|
466
483
|
this._defineOverridenProperty(obj, objref, override, propInfo);
|
|
467
484
|
}
|
|
468
485
|
_defineOverridenProperty(obj, objref, override, propInfo) {
|
|
486
|
+
var _a;
|
|
469
487
|
const propertyName = override.property;
|
|
470
488
|
this._debug('apply override', propertyName);
|
|
471
489
|
// save the old property under $jsii$super$<prop>$ so that property overrides
|
|
472
490
|
// can still access it via `super.<prop>`.
|
|
473
|
-
const prev = getPropertyDescriptor(obj, propertyName)
|
|
491
|
+
const prev = (_a = getPropertyDescriptor(obj, propertyName)) !== null && _a !== void 0 ? _a : {
|
|
474
492
|
value: obj[propertyName],
|
|
475
493
|
writable: true,
|
|
476
494
|
enumerable: true,
|
|
@@ -495,7 +513,7 @@ class Kernel {
|
|
|
495
513
|
get: { objref, property: propertyName },
|
|
496
514
|
});
|
|
497
515
|
this._debug('callback returned', result);
|
|
498
|
-
return this._toSandbox(result, propInfo);
|
|
516
|
+
return this._toSandbox(result, propInfo, `returned by callback property ${propertyName}`);
|
|
499
517
|
},
|
|
500
518
|
set: (value) => {
|
|
501
519
|
this._debug('virtual set', objref, propertyName, {
|
|
@@ -507,7 +525,7 @@ class Kernel {
|
|
|
507
525
|
set: {
|
|
508
526
|
objref,
|
|
509
527
|
property: propertyName,
|
|
510
|
-
value: this._fromSandbox(value, propInfo),
|
|
528
|
+
value: this._fromSandbox(value, propInfo, `assigned to callback property ${propertyName}`),
|
|
511
529
|
},
|
|
512
530
|
});
|
|
513
531
|
},
|
|
@@ -558,6 +576,8 @@ class Kernel {
|
|
|
558
576
|
}
|
|
559
577
|
_defineOverridenMethod(obj, objref, override, methodInfo) {
|
|
560
578
|
const methodName = override.method;
|
|
579
|
+
const fqn = (0, objects_1.jsiiTypeFqn)(obj);
|
|
580
|
+
const methodContext = `${methodInfo.async ? 'async ' : ''}method${fqn ? `${fqn}#` : methodName}`;
|
|
561
581
|
if (methodInfo.async) {
|
|
562
582
|
// async method override
|
|
563
583
|
Object.defineProperty(obj, methodName, {
|
|
@@ -566,18 +586,19 @@ class Kernel {
|
|
|
566
586
|
writable: false,
|
|
567
587
|
value: (...methodArgs) => {
|
|
568
588
|
this._debug('invoke async method override', override);
|
|
569
|
-
const args = this._toSandboxValues(methodArgs, methodInfo.parameters);
|
|
589
|
+
const args = this._toSandboxValues(methodArgs, methodContext, methodInfo.parameters);
|
|
570
590
|
return new Promise((succeed, fail) => {
|
|
591
|
+
var _a;
|
|
571
592
|
const cbid = this._makecbid();
|
|
572
593
|
this._debug('adding callback to queue', cbid);
|
|
573
|
-
this.cbs
|
|
594
|
+
this.cbs.set(cbid, {
|
|
574
595
|
objref,
|
|
575
596
|
override,
|
|
576
597
|
args,
|
|
577
|
-
expectedReturnType: methodInfo.returns
|
|
598
|
+
expectedReturnType: (_a = methodInfo.returns) !== null && _a !== void 0 ? _a : 'void',
|
|
578
599
|
succeed,
|
|
579
600
|
fail,
|
|
580
|
-
};
|
|
601
|
+
});
|
|
581
602
|
});
|
|
582
603
|
},
|
|
583
604
|
});
|
|
@@ -589,6 +610,7 @@ class Kernel {
|
|
|
589
610
|
configurable: false,
|
|
590
611
|
writable: false,
|
|
591
612
|
value: (...methodArgs) => {
|
|
613
|
+
var _a;
|
|
592
614
|
this._debug('invoke sync method override', override, 'args', methodArgs);
|
|
593
615
|
// We should be validating the actual arguments according to the
|
|
594
616
|
// declared parameters here, but let's just assume the JSII runtime on the
|
|
@@ -599,11 +621,11 @@ class Kernel {
|
|
|
599
621
|
invoke: {
|
|
600
622
|
objref,
|
|
601
623
|
method: methodName,
|
|
602
|
-
args: this._fromSandboxValues(methodArgs, methodInfo.parameters),
|
|
624
|
+
args: this._fromSandboxValues(methodArgs, methodContext, methodInfo.parameters),
|
|
603
625
|
},
|
|
604
626
|
});
|
|
605
627
|
this._debug('Result', result);
|
|
606
|
-
return this._toSandbox(result, methodInfo.returns
|
|
628
|
+
return this._toSandbox(result, (_a = methodInfo.returns) !== null && _a !== void 0 ? _a : 'void', `returned by callback method ${methodName}`);
|
|
607
629
|
},
|
|
608
630
|
});
|
|
609
631
|
}
|
|
@@ -629,7 +651,8 @@ class Kernel {
|
|
|
629
651
|
return { ti, obj: instance, fn };
|
|
630
652
|
}
|
|
631
653
|
_validateMethodArguments(method, args) {
|
|
632
|
-
|
|
654
|
+
var _a;
|
|
655
|
+
const params = (_a = method === null || method === void 0 ? void 0 : method.parameters) !== null && _a !== void 0 ? _a : [];
|
|
633
656
|
// error if args > params
|
|
634
657
|
if (args.length > params.length && !(method && method.variadic)) {
|
|
635
658
|
throw new Error(`Too many arguments (method accepts ${params.length} parameters, got ${args.length} arguments)`);
|
|
@@ -653,7 +676,7 @@ class Kernel {
|
|
|
653
676
|
}
|
|
654
677
|
}
|
|
655
678
|
_assemblyFor(assemblyName) {
|
|
656
|
-
const assembly = this.assemblies
|
|
679
|
+
const assembly = this.assemblies.get(assemblyName);
|
|
657
680
|
if (!assembly) {
|
|
658
681
|
throw new Error(`Could not find assembly: ${assemblyName}`);
|
|
659
682
|
}
|
|
@@ -676,13 +699,14 @@ class Kernel {
|
|
|
676
699
|
return curr;
|
|
677
700
|
}
|
|
678
701
|
_typeInfoForFqn(fqn) {
|
|
702
|
+
var _a;
|
|
679
703
|
const components = fqn.split('.');
|
|
680
704
|
const moduleName = components[0];
|
|
681
|
-
const assembly = this.assemblies
|
|
705
|
+
const assembly = this.assemblies.get(moduleName);
|
|
682
706
|
if (!assembly) {
|
|
683
707
|
throw new Error(`Module '${moduleName}' not found`);
|
|
684
708
|
}
|
|
685
|
-
const types = assembly.metadata.types
|
|
709
|
+
const types = (_a = assembly.metadata.types) !== null && _a !== void 0 ? _a : {};
|
|
686
710
|
const fqnInfo = types[fqn];
|
|
687
711
|
if (!fqnInfo) {
|
|
688
712
|
throw new Error(`Type '${fqn}' not found`);
|
|
@@ -700,12 +724,13 @@ class Kernel {
|
|
|
700
724
|
return ti;
|
|
701
725
|
}
|
|
702
726
|
_tryTypeInfoForMethod(methodName, classFqn, interfaces = []) {
|
|
727
|
+
var _a, _b;
|
|
703
728
|
for (const fqn of [classFqn, ...interfaces]) {
|
|
704
729
|
if (fqn === wire.EMPTY_OBJECT_FQN) {
|
|
705
730
|
continue;
|
|
706
731
|
}
|
|
707
732
|
const typeinfo = this._typeInfoForFqn(fqn);
|
|
708
|
-
const methods = typeinfo.methods
|
|
733
|
+
const methods = (_a = typeinfo.methods) !== null && _a !== void 0 ? _a : [];
|
|
709
734
|
for (const m of methods) {
|
|
710
735
|
if (m.name === methodName) {
|
|
711
736
|
return m;
|
|
@@ -714,7 +739,7 @@ class Kernel {
|
|
|
714
739
|
// recursion to parent type (if exists)
|
|
715
740
|
const bases = [
|
|
716
741
|
typeinfo.base,
|
|
717
|
-
...(typeinfo.interfaces
|
|
742
|
+
...((_b = typeinfo.interfaces) !== null && _b !== void 0 ? _b : []),
|
|
718
743
|
];
|
|
719
744
|
for (const base of bases) {
|
|
720
745
|
if (!base) {
|
|
@@ -729,6 +754,7 @@ class Kernel {
|
|
|
729
754
|
return undefined;
|
|
730
755
|
}
|
|
731
756
|
_tryTypeInfoForProperty(property, classFqn, interfaces = []) {
|
|
757
|
+
var _a;
|
|
732
758
|
for (const fqn of [classFqn, ...interfaces]) {
|
|
733
759
|
if (fqn === wire.EMPTY_OBJECT_FQN) {
|
|
734
760
|
continue;
|
|
@@ -744,12 +770,12 @@ class Kernel {
|
|
|
744
770
|
else if (spec.isInterfaceType(typeInfo)) {
|
|
745
771
|
const interfaceTypeInfo = typeInfo;
|
|
746
772
|
properties = interfaceTypeInfo.properties;
|
|
747
|
-
bases = interfaceTypeInfo.interfaces
|
|
773
|
+
bases = (_a = interfaceTypeInfo.interfaces) !== null && _a !== void 0 ? _a : [];
|
|
748
774
|
}
|
|
749
775
|
else {
|
|
750
776
|
throw new Error(`Type of kind ${typeInfo.kind} does not have properties`);
|
|
751
777
|
}
|
|
752
|
-
for (const p of properties
|
|
778
|
+
for (const p of properties !== null && properties !== void 0 ? properties : []) {
|
|
753
779
|
if (p.name === property) {
|
|
754
780
|
return p;
|
|
755
781
|
}
|
|
@@ -774,73 +800,40 @@ class Kernel {
|
|
|
774
800
|
}
|
|
775
801
|
return typeInfo;
|
|
776
802
|
}
|
|
777
|
-
_toSandbox(v, expectedType) {
|
|
778
|
-
|
|
779
|
-
this._debug('toSandbox', v, JSON.stringify(serTypes));
|
|
780
|
-
const host = {
|
|
803
|
+
_toSandbox(v, expectedType, context) {
|
|
804
|
+
return wire.process({
|
|
781
805
|
objects: this.objects,
|
|
782
806
|
debug: this._debug.bind(this),
|
|
783
807
|
findSymbol: this._findSymbol.bind(this),
|
|
784
808
|
lookupType: this._typeInfoForFqn.bind(this),
|
|
785
|
-
|
|
786
|
-
};
|
|
787
|
-
const errors = new Array();
|
|
788
|
-
for (const { serializationClass, typeRef } of serTypes) {
|
|
789
|
-
try {
|
|
790
|
-
return wire.SERIALIZERS[serializationClass].deserialize(v, typeRef, host);
|
|
791
|
-
}
|
|
792
|
-
catch (e) {
|
|
793
|
-
// If no union (99% case), rethrow immediately to preserve stack trace
|
|
794
|
-
if (serTypes.length === 1) {
|
|
795
|
-
throw e;
|
|
796
|
-
}
|
|
797
|
-
errors.push(e.message);
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
throw new Error(`Value did not match any type in union: ${errors.join(', ')}`);
|
|
809
|
+
}, 'deserialize', v, expectedType, context);
|
|
801
810
|
}
|
|
802
|
-
_fromSandbox(v, targetType) {
|
|
803
|
-
|
|
804
|
-
this._debug('fromSandbox', v, JSON.stringify(serTypes));
|
|
805
|
-
const host = {
|
|
811
|
+
_fromSandbox(v, targetType, context) {
|
|
812
|
+
return wire.process({
|
|
806
813
|
objects: this.objects,
|
|
807
814
|
debug: this._debug.bind(this),
|
|
808
815
|
findSymbol: this._findSymbol.bind(this),
|
|
809
816
|
lookupType: this._typeInfoForFqn.bind(this),
|
|
810
|
-
|
|
811
|
-
};
|
|
812
|
-
const errors = new Array();
|
|
813
|
-
for (const { serializationClass, typeRef } of serTypes) {
|
|
814
|
-
try {
|
|
815
|
-
return wire.SERIALIZERS[serializationClass].serialize(v, typeRef, host);
|
|
816
|
-
}
|
|
817
|
-
catch (e) {
|
|
818
|
-
// If no union (99% case), rethrow immediately to preserve stack trace
|
|
819
|
-
if (serTypes.length === 1) {
|
|
820
|
-
throw e;
|
|
821
|
-
}
|
|
822
|
-
errors.push(e.message);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
throw new Error(`Value did not match any type in union: ${errors.join(', ')}`);
|
|
817
|
+
}, 'serialize', v, targetType, context);
|
|
826
818
|
}
|
|
827
|
-
_toSandboxValues(xs, parameters) {
|
|
828
|
-
return this._boxUnboxParameters(xs, parameters, this._toSandbox.bind(this));
|
|
819
|
+
_toSandboxValues(xs, methodContext, parameters) {
|
|
820
|
+
return this._boxUnboxParameters(xs, methodContext, parameters, this._toSandbox.bind(this));
|
|
829
821
|
}
|
|
830
|
-
_fromSandboxValues(xs, parameters) {
|
|
831
|
-
return this._boxUnboxParameters(xs, parameters, this._fromSandbox.bind(this));
|
|
822
|
+
_fromSandboxValues(xs, methodContext, parameters) {
|
|
823
|
+
return this._boxUnboxParameters(xs, methodContext, parameters, this._fromSandbox.bind(this));
|
|
832
824
|
}
|
|
833
|
-
_boxUnboxParameters(xs, parameters, boxUnbox) {
|
|
834
|
-
|
|
835
|
-
const variadic =
|
|
825
|
+
_boxUnboxParameters(xs, methodContext, parameters = [], boxUnbox) {
|
|
826
|
+
const parametersCopy = [...parameters];
|
|
827
|
+
const variadic = parametersCopy.length > 0 &&
|
|
828
|
+
!!parametersCopy[parametersCopy.length - 1].variadic;
|
|
836
829
|
// Repeat the last (variadic) type to match the number of actual arguments
|
|
837
|
-
while (variadic &&
|
|
838
|
-
|
|
830
|
+
while (variadic && parametersCopy.length < xs.length) {
|
|
831
|
+
parametersCopy.push(parametersCopy[parametersCopy.length - 1]);
|
|
839
832
|
}
|
|
840
|
-
if (xs.length >
|
|
841
|
-
throw new Error(`Argument list (${JSON.stringify(xs)}) not same size as expected argument list (length ${
|
|
833
|
+
if (xs.length > parametersCopy.length) {
|
|
834
|
+
throw new Error(`Argument list (${JSON.stringify(xs)}) not same size as expected argument list (length ${parametersCopy.length})`);
|
|
842
835
|
}
|
|
843
|
-
return xs.map((x, i) => boxUnbox(x,
|
|
836
|
+
return xs.map((x, i) => boxUnbox(x, parametersCopy[i], `passed to parameter ${parametersCopy[i].name} of ${methodContext}`));
|
|
844
837
|
}
|
|
845
838
|
_debug(...args) {
|
|
846
839
|
if (this.traceEnabled) {
|
|
@@ -883,8 +876,6 @@ class Kernel {
|
|
|
883
876
|
* Executes arbitrary code in a VM sandbox.
|
|
884
877
|
*
|
|
885
878
|
* @param code JavaScript code to be executed in the VM
|
|
886
|
-
* @param sandbox a VM context to use for running the code
|
|
887
|
-
* @param sourceMaps source maps to be used in case an exception is thrown
|
|
888
879
|
* @param filename the file name to use for the executed code
|
|
889
880
|
*
|
|
890
881
|
* @returns the result of evaluating the code
|
package/lib/objects.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export declare function tagJsiiConstructor(constructor: any, fqn: string): void;
|
|
|
26
26
|
*/
|
|
27
27
|
export declare class ObjectTable {
|
|
28
28
|
private readonly resolveType;
|
|
29
|
-
private objects;
|
|
29
|
+
private readonly objects;
|
|
30
30
|
private nextid;
|
|
31
31
|
constructor(resolveType: (fqn: string) => spec.Type);
|
|
32
32
|
/**
|
|
@@ -42,7 +42,7 @@ export declare class ObjectTable {
|
|
|
42
42
|
/**
|
|
43
43
|
* Delete the registration with the given objref
|
|
44
44
|
*/
|
|
45
|
-
deleteObject(
|
|
45
|
+
deleteObject({ [api.TOKEN_REF]: objid }: api.ObjRef): void;
|
|
46
46
|
get count(): number;
|
|
47
47
|
private makeId;
|
|
48
48
|
private removeRedundant;
|