@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/lib/serialization.js
CHANGED
|
@@ -27,11 +27,14 @@
|
|
|
27
27
|
* - /R(t) recurse with declared type t
|
|
28
28
|
*/
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
-
exports.serializationType = exports.SERIALIZERS = exports.SYMBOL_WIRE_TYPE = exports.EMPTY_OBJECT_FQN = void 0;
|
|
30
|
+
exports.SerializationError = exports.process = exports.serializationType = exports.SERIALIZERS = exports.SYMBOL_WIRE_TYPE = exports.EMPTY_OBJECT_FQN = void 0;
|
|
31
31
|
const spec = require("@jsii/spec");
|
|
32
|
+
const assert = require("assert");
|
|
33
|
+
const util_1 = require("util");
|
|
32
34
|
const api_1 = require("./api");
|
|
33
35
|
const objects_1 = require("./objects");
|
|
34
36
|
const _1 = require(".");
|
|
37
|
+
const VOID = 'void';
|
|
35
38
|
/**
|
|
36
39
|
* A special FQN that can be used to create empty javascript objects.
|
|
37
40
|
*/
|
|
@@ -59,11 +62,9 @@ exports.SERIALIZERS = {
|
|
|
59
62
|
if (nullAndOk(value, optionalValue)) {
|
|
60
63
|
return undefined;
|
|
61
64
|
}
|
|
62
|
-
|
|
63
|
-
throw new Error('Encountered unexpected `void` type');
|
|
64
|
-
}
|
|
65
|
+
assert(optionalValue !== VOID, 'Encountered unexpected void type!');
|
|
65
66
|
if (!isDate(value)) {
|
|
66
|
-
throw new
|
|
67
|
+
throw new SerializationError(`Value is not an instance of Date`, value);
|
|
67
68
|
}
|
|
68
69
|
return serializeDate(value);
|
|
69
70
|
},
|
|
@@ -72,7 +73,7 @@ exports.SERIALIZERS = {
|
|
|
72
73
|
return undefined;
|
|
73
74
|
}
|
|
74
75
|
if (!(0, api_1.isWireDate)(value)) {
|
|
75
|
-
throw new
|
|
76
|
+
throw new SerializationError(`Value does not have the "${api_1.TOKEN_DATE}" key`, value);
|
|
76
77
|
}
|
|
77
78
|
return deserializeDate(value);
|
|
78
79
|
},
|
|
@@ -83,15 +84,13 @@ exports.SERIALIZERS = {
|
|
|
83
84
|
if (nullAndOk(value, optionalValue)) {
|
|
84
85
|
return undefined;
|
|
85
86
|
}
|
|
86
|
-
|
|
87
|
-
throw new Error('Encountered unexpected `void` type');
|
|
88
|
-
}
|
|
87
|
+
assert(optionalValue !== VOID, 'Encountered unexpected void type!');
|
|
89
88
|
const primitiveType = optionalValue.type;
|
|
90
89
|
if (!isScalar(value)) {
|
|
91
|
-
throw new
|
|
90
|
+
throw new SerializationError(`Value is not a ${spec.describeTypeReference(optionalValue.type)}`, value);
|
|
92
91
|
}
|
|
93
92
|
if (typeof value !== primitiveType.primitive) {
|
|
94
|
-
throw new
|
|
93
|
+
throw new SerializationError(`Value is not a ${spec.describeTypeReference(optionalValue.type)}`, value);
|
|
95
94
|
}
|
|
96
95
|
return value;
|
|
97
96
|
},
|
|
@@ -99,22 +98,24 @@ exports.SERIALIZERS = {
|
|
|
99
98
|
if (nullAndOk(value, optionalValue)) {
|
|
100
99
|
return undefined;
|
|
101
100
|
}
|
|
102
|
-
|
|
103
|
-
throw new Error('Encountered unexpected `void` type');
|
|
104
|
-
}
|
|
101
|
+
assert(optionalValue !== VOID, 'Encountered unexpected void type!');
|
|
105
102
|
const primitiveType = optionalValue.type;
|
|
106
103
|
if (!isScalar(value)) {
|
|
107
|
-
throw new
|
|
104
|
+
throw new SerializationError(`Value is not a ${spec.describeTypeReference(optionalValue.type)}`, value);
|
|
108
105
|
}
|
|
109
106
|
if (typeof value !== primitiveType.primitive) {
|
|
110
|
-
throw new
|
|
107
|
+
throw new SerializationError(`Value is not a ${spec.describeTypeReference(optionalValue.type)}`, value);
|
|
111
108
|
}
|
|
112
109
|
return value;
|
|
113
110
|
},
|
|
114
111
|
},
|
|
115
112
|
// ----------------------------------------------------------------------
|
|
116
113
|
["Json" /* SerializationClass.Json */]: {
|
|
117
|
-
serialize(value) {
|
|
114
|
+
serialize(value, optionalValue) {
|
|
115
|
+
// /!\ Top-level "null" will turn to undefined, but any null nested in the value is valid JSON, so it'll stay!
|
|
116
|
+
if (nullAndOk(value, optionalValue)) {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
118
119
|
// Just whatever. Dates will automatically serialize themselves to strings.
|
|
119
120
|
return value;
|
|
120
121
|
},
|
|
@@ -145,13 +146,13 @@ exports.SERIALIZERS = {
|
|
|
145
146
|
return value.map(mapJsonValue);
|
|
146
147
|
}
|
|
147
148
|
return mapValues(value, mapJsonValue);
|
|
148
|
-
function mapJsonValue(toMap) {
|
|
149
|
+
function mapJsonValue(toMap, key) {
|
|
149
150
|
if (toMap == null) {
|
|
150
151
|
return toMap;
|
|
151
152
|
}
|
|
152
|
-
return host
|
|
153
|
+
return process(host, 'deserialize', toMap, {
|
|
153
154
|
type: { primitive: spec.PrimitiveType.Json },
|
|
154
|
-
});
|
|
155
|
+
}, typeof key === 'string' ? `key ${(0, util_1.inspect)(key)}` : `index ${key}`);
|
|
155
156
|
}
|
|
156
157
|
},
|
|
157
158
|
},
|
|
@@ -161,18 +162,16 @@ exports.SERIALIZERS = {
|
|
|
161
162
|
if (nullAndOk(value, optionalValue)) {
|
|
162
163
|
return undefined;
|
|
163
164
|
}
|
|
164
|
-
|
|
165
|
-
throw new Error('Encountered unexpected `void` type');
|
|
166
|
-
}
|
|
165
|
+
assert(optionalValue !== VOID, 'Encountered unexpected void type!');
|
|
167
166
|
if (typeof value !== 'string' && typeof value !== 'number') {
|
|
168
|
-
throw new
|
|
167
|
+
throw new SerializationError(`Value is not a string or number`, value);
|
|
169
168
|
}
|
|
170
169
|
host.debug('Serializing enum');
|
|
171
170
|
const enumType = optionalValue.type;
|
|
172
171
|
const enumMap = host.findSymbol(enumType.fqn);
|
|
173
172
|
const enumEntry = Object.entries(enumMap).find(([, v]) => v === value);
|
|
174
173
|
if (!enumEntry) {
|
|
175
|
-
throw new
|
|
174
|
+
throw new SerializationError(`Value is not present in enum ${spec.describeTypeReference(enumType)}`, value);
|
|
176
175
|
}
|
|
177
176
|
return { [api_1.TOKEN_ENUM]: `${enumType.fqn}/${enumEntry[0]}` };
|
|
178
177
|
},
|
|
@@ -181,7 +180,7 @@ exports.SERIALIZERS = {
|
|
|
181
180
|
return undefined;
|
|
182
181
|
}
|
|
183
182
|
if (!(0, api_1.isWireEnum)(value)) {
|
|
184
|
-
throw new
|
|
183
|
+
throw new SerializationError(`Value does not have the "${api_1.TOKEN_ENUM}" key`, value);
|
|
185
184
|
}
|
|
186
185
|
return deserializeEnum(value, host.findSymbol);
|
|
187
186
|
},
|
|
@@ -192,27 +191,23 @@ exports.SERIALIZERS = {
|
|
|
192
191
|
if (nullAndOk(value, optionalValue)) {
|
|
193
192
|
return undefined;
|
|
194
193
|
}
|
|
195
|
-
|
|
196
|
-
throw new Error('Encountered unexpected `void` type');
|
|
197
|
-
}
|
|
194
|
+
assert(optionalValue !== VOID, 'Encountered unexpected void type!');
|
|
198
195
|
if (!Array.isArray(value)) {
|
|
199
|
-
throw new
|
|
196
|
+
throw new SerializationError(`Value is not an array`, value);
|
|
200
197
|
}
|
|
201
198
|
const arrayType = optionalValue.type;
|
|
202
|
-
return value.map((x) => host
|
|
199
|
+
return value.map((x, idx) => process(host, 'serialize', x, { type: arrayType.collection.elementtype }, `index ${(0, util_1.inspect)(idx)}`));
|
|
203
200
|
},
|
|
204
201
|
deserialize(value, optionalValue, host) {
|
|
205
202
|
if (nullAndOk(value, optionalValue)) {
|
|
206
203
|
return undefined;
|
|
207
204
|
}
|
|
208
|
-
|
|
209
|
-
throw new Error('Encountered unexpected `void` type');
|
|
210
|
-
}
|
|
205
|
+
assert(optionalValue !== VOID, 'Encountered unexpected void type!');
|
|
211
206
|
if (!Array.isArray(value)) {
|
|
212
|
-
throw new
|
|
207
|
+
throw new SerializationError(`Value is not an array`, value);
|
|
213
208
|
}
|
|
214
209
|
const arrayType = optionalValue.type;
|
|
215
|
-
return value.map((x) => host
|
|
210
|
+
return value.map((x, idx) => process(host, 'deserialize', x, { type: arrayType.collection.elementtype }, `index ${(0, util_1.inspect)(idx)}`));
|
|
216
211
|
},
|
|
217
212
|
},
|
|
218
213
|
// ----------------------------------------------------------------------
|
|
@@ -221,27 +216,23 @@ exports.SERIALIZERS = {
|
|
|
221
216
|
if (nullAndOk(value, optionalValue)) {
|
|
222
217
|
return undefined;
|
|
223
218
|
}
|
|
224
|
-
|
|
225
|
-
throw new Error('Encountered unexpected `void` type');
|
|
226
|
-
}
|
|
219
|
+
assert(optionalValue !== VOID, 'Encountered unexpected void type!');
|
|
227
220
|
const mapType = optionalValue.type;
|
|
228
221
|
return {
|
|
229
|
-
[api_1.TOKEN_MAP]: mapValues(value, (v) => host
|
|
222
|
+
[api_1.TOKEN_MAP]: mapValues(value, (v, key) => process(host, 'serialize', v, { type: mapType.collection.elementtype }, `key ${(0, util_1.inspect)(key)}`)),
|
|
230
223
|
};
|
|
231
224
|
},
|
|
232
225
|
deserialize(value, optionalValue, host) {
|
|
233
226
|
if (nullAndOk(value, optionalValue)) {
|
|
234
227
|
return undefined;
|
|
235
228
|
}
|
|
236
|
-
|
|
237
|
-
throw new Error('Encountered unexpected `void` type');
|
|
238
|
-
}
|
|
229
|
+
assert(optionalValue !== VOID, 'Encountered unexpected void type!');
|
|
239
230
|
const mapType = optionalValue.type;
|
|
240
231
|
if (!(0, api_1.isWireMap)(value)) {
|
|
241
232
|
// Compatibility mode with older versions that didn't wrap in [TOKEN_MAP]
|
|
242
|
-
return mapValues(value, (v) => host
|
|
233
|
+
return mapValues(value, (v, key) => process(host, 'deserialize', v, { type: mapType.collection.elementtype }, `key ${(0, util_1.inspect)(key)}`));
|
|
243
234
|
}
|
|
244
|
-
const result = mapValues(value[api_1.TOKEN_MAP], (v) => host
|
|
235
|
+
const result = mapValues(value[api_1.TOKEN_MAP], (v, key) => process(host, 'deserialize', v, { type: mapType.collection.elementtype }, `key ${(0, util_1.inspect)(key)}`));
|
|
245
236
|
Object.defineProperty(result, exports.SYMBOL_WIRE_TYPE, {
|
|
246
237
|
configurable: false,
|
|
247
238
|
enumerable: false,
|
|
@@ -257,11 +248,12 @@ exports.SERIALIZERS = {
|
|
|
257
248
|
if (nullAndOk(value, optionalValue)) {
|
|
258
249
|
return undefined;
|
|
259
250
|
}
|
|
260
|
-
|
|
261
|
-
|
|
251
|
+
assert(optionalValue !== VOID, 'Encountered unexpected void type!');
|
|
252
|
+
if (typeof value !== 'object' || value == null || value instanceof Date) {
|
|
253
|
+
throw new SerializationError(`Value is not an object`, value);
|
|
262
254
|
}
|
|
263
|
-
if (
|
|
264
|
-
throw new
|
|
255
|
+
if (Array.isArray(value)) {
|
|
256
|
+
throw new SerializationError(`Value is an array`, value);
|
|
265
257
|
}
|
|
266
258
|
/*
|
|
267
259
|
This is what we'd like to do, but we can't because at least the Java client
|
|
@@ -283,23 +275,21 @@ exports.SERIALIZERS = {
|
|
|
283
275
|
]);
|
|
284
276
|
},
|
|
285
277
|
deserialize(value, optionalValue, host) {
|
|
286
|
-
if (typeof value === 'object' && Object.keys(value
|
|
278
|
+
if (typeof value === 'object' && Object.keys(value !== null && value !== void 0 ? value : {}).length === 0) {
|
|
287
279
|
// Treat empty structs as `undefined` (see https://github.com/aws/jsii/issues/411)
|
|
288
280
|
value = undefined;
|
|
289
281
|
}
|
|
290
282
|
if (nullAndOk(value, optionalValue)) {
|
|
291
283
|
return undefined;
|
|
292
284
|
}
|
|
293
|
-
|
|
294
|
-
throw new Error('Encountered unexpected `void` type');
|
|
295
|
-
}
|
|
285
|
+
assert(optionalValue !== VOID, 'Encountered unexpected void type!');
|
|
296
286
|
if (typeof value !== 'object' || value == null) {
|
|
297
|
-
throw new
|
|
287
|
+
throw new SerializationError(`Value is not an object`, value);
|
|
298
288
|
}
|
|
299
289
|
const namedType = host.lookupType(optionalValue.type.fqn);
|
|
300
290
|
const props = propertiesOf(namedType, host.lookupType);
|
|
301
291
|
if (Array.isArray(value)) {
|
|
302
|
-
throw new
|
|
292
|
+
throw new SerializationError('Value is an array (varargs may have been incorrectly supplied)', value);
|
|
303
293
|
}
|
|
304
294
|
// Similarly to serialization, we might be getting a reference type where we're
|
|
305
295
|
// expecting a value type. Accept this for now (but also validate that object
|
|
@@ -312,7 +302,7 @@ exports.SERIALIZERS = {
|
|
|
312
302
|
if (_1.api.isWireStruct(value)) {
|
|
313
303
|
const { fqn, data } = value[_1.api.TOKEN_STRUCT];
|
|
314
304
|
if (!isAssignable(fqn, namedType, host.lookupType)) {
|
|
315
|
-
throw new
|
|
305
|
+
throw new SerializationError(`Wired struct has type '${fqn}', which does not match expected type`, value);
|
|
316
306
|
}
|
|
317
307
|
value = data;
|
|
318
308
|
}
|
|
@@ -326,41 +316,40 @@ exports.SERIALIZERS = {
|
|
|
326
316
|
if (!props[key]) {
|
|
327
317
|
return undefined;
|
|
328
318
|
} // Don't map if unknown property
|
|
329
|
-
return host
|
|
319
|
+
return process(host, 'deserialize', v, props[key], `key ${(0, util_1.inspect)(key)}`);
|
|
330
320
|
});
|
|
331
321
|
},
|
|
332
322
|
},
|
|
333
323
|
// ----------------------------------------------------------------------
|
|
334
324
|
["RefType" /* SerializationClass.ReferenceType */]: {
|
|
335
325
|
serialize(value, optionalValue, host) {
|
|
326
|
+
var _a;
|
|
336
327
|
if (nullAndOk(value, optionalValue)) {
|
|
337
328
|
return undefined;
|
|
338
329
|
}
|
|
339
|
-
|
|
340
|
-
|
|
330
|
+
assert(optionalValue !== VOID, 'Encountered unexpected void type!');
|
|
331
|
+
if (typeof value !== 'object' || value == null || Array.isArray(value)) {
|
|
332
|
+
throw new SerializationError(`Value is not an object`, value);
|
|
341
333
|
}
|
|
342
|
-
if (
|
|
343
|
-
throw new
|
|
334
|
+
if (value instanceof Date) {
|
|
335
|
+
throw new SerializationError(`Value is a Date`, value);
|
|
344
336
|
}
|
|
345
337
|
const expectedType = host.lookupType(optionalValue.type.fqn);
|
|
346
338
|
const interfaces = spec.isInterfaceType(expectedType)
|
|
347
339
|
? [expectedType.fqn]
|
|
348
340
|
: undefined;
|
|
349
|
-
const jsiiType = (0, objects_1.jsiiTypeFqn)(value)
|
|
350
|
-
(spec.isClassType(expectedType) ? expectedType.fqn : exports.EMPTY_OBJECT_FQN);
|
|
341
|
+
const jsiiType = (_a = (0, objects_1.jsiiTypeFqn)(value)) !== null && _a !== void 0 ? _a : (spec.isClassType(expectedType) ? expectedType.fqn : exports.EMPTY_OBJECT_FQN);
|
|
351
342
|
return host.objects.registerObject(value, jsiiType, interfaces);
|
|
352
343
|
},
|
|
353
344
|
deserialize(value, optionalValue, host) {
|
|
354
345
|
if (nullAndOk(value, optionalValue)) {
|
|
355
346
|
return undefined;
|
|
356
347
|
}
|
|
357
|
-
|
|
358
|
-
throw new Error('Encountered unexpected `void` type');
|
|
359
|
-
}
|
|
348
|
+
assert(optionalValue !== VOID, 'Encountered unexpected void type!');
|
|
360
349
|
// The only way to pass a by-ref object is to have created it
|
|
361
350
|
// previously inside JSII kernel, so it must have an objref already.
|
|
362
351
|
if (!(0, api_1.isObjRef)(value)) {
|
|
363
|
-
throw new
|
|
352
|
+
throw new SerializationError(`Value does not have the "${api_1.TOKEN_REF}" key`, value);
|
|
364
353
|
}
|
|
365
354
|
const { instance, fqn } = host.objects.findObject(value);
|
|
366
355
|
const namedTypeRef = optionalValue.type;
|
|
@@ -373,7 +362,7 @@ exports.SERIALIZERS = {
|
|
|
373
362
|
const declaredType = optionalValue.type;
|
|
374
363
|
if (spec.isClassType(namedType) &&
|
|
375
364
|
!isAssignable(fqn, declaredType, host.lookupType)) {
|
|
376
|
-
throw new
|
|
365
|
+
throw new SerializationError(`Object of type '${fqn}' is not convertible to ${spec.describeTypeReference(declaredType)}`, value);
|
|
377
366
|
}
|
|
378
367
|
}
|
|
379
368
|
return instance;
|
|
@@ -382,6 +371,7 @@ exports.SERIALIZERS = {
|
|
|
382
371
|
// ----------------------------------------------------------------------
|
|
383
372
|
["Any" /* SerializationClass.Any */]: {
|
|
384
373
|
serialize(value, _type, host) {
|
|
374
|
+
var _a;
|
|
385
375
|
if (value == null) {
|
|
386
376
|
return undefined;
|
|
387
377
|
}
|
|
@@ -392,15 +382,15 @@ exports.SERIALIZERS = {
|
|
|
392
382
|
return value;
|
|
393
383
|
}
|
|
394
384
|
if (Array.isArray(value)) {
|
|
395
|
-
return value.map((e) => host
|
|
385
|
+
return value.map((e, idx) => process(host, 'serialize', e, { type: spec.CANONICAL_ANY }, `index ${(0, util_1.inspect)(idx)}`));
|
|
396
386
|
}
|
|
397
387
|
// Note: no case for "ENUM" here, without type declaration we can't tell the difference
|
|
398
388
|
// between an enum member and a scalar.
|
|
399
389
|
if (typeof value === 'function') {
|
|
400
|
-
throw new
|
|
390
|
+
throw new SerializationError('Functions cannot be passed across language boundaries', value);
|
|
401
391
|
}
|
|
402
392
|
if (typeof value !== 'object' || value == null) {
|
|
403
|
-
throw new
|
|
393
|
+
throw new SerializationError(`A jsii kernel assumption was violated: value is not an object`, value);
|
|
404
394
|
}
|
|
405
395
|
if (exports.SYMBOL_WIRE_TYPE in value &&
|
|
406
396
|
value[exports.SYMBOL_WIRE_TYPE] === api_1.TOKEN_MAP) {
|
|
@@ -417,7 +407,7 @@ exports.SERIALIZERS = {
|
|
|
417
407
|
// those and throw a descriptive error message. We can't detect these cases any other
|
|
418
408
|
// way, and the by-value serialized object will be quite useless.
|
|
419
409
|
if (value instanceof Set || value instanceof Map) {
|
|
420
|
-
throw new
|
|
410
|
+
throw new SerializationError('Set and Map instances cannot be sent across the language boundary', value);
|
|
421
411
|
}
|
|
422
412
|
// Use a previous reference to maintain object identity. NOTE: this may cause us to return
|
|
423
413
|
// a different type than requested! This is just how it is right now.
|
|
@@ -428,8 +418,7 @@ exports.SERIALIZERS = {
|
|
|
428
418
|
}
|
|
429
419
|
// If this is or should be a reference type, pass or make the reference
|
|
430
420
|
// (Like regular reftype serialization, but without the type derivation to an interface)
|
|
431
|
-
const jsiiType = (0, objects_1.jsiiTypeFqn)(value)
|
|
432
|
-
(isByReferenceOnly(value) ? exports.EMPTY_OBJECT_FQN : undefined);
|
|
421
|
+
const jsiiType = (_a = (0, objects_1.jsiiTypeFqn)(value)) !== null && _a !== void 0 ? _a : (isByReferenceOnly(value) ? exports.EMPTY_OBJECT_FQN : undefined);
|
|
433
422
|
if (jsiiType) {
|
|
434
423
|
return host.objects.registerObject(value, jsiiType);
|
|
435
424
|
}
|
|
@@ -438,7 +427,7 @@ exports.SERIALIZERS = {
|
|
|
438
427
|
// We will serialize by-value, but recurse for serialization so that if
|
|
439
428
|
// the object contains reference objects, they will be serialized appropriately.
|
|
440
429
|
// (Basically, serialize anything else as a map of 'any').
|
|
441
|
-
return mapValues(value, (v) => host
|
|
430
|
+
return mapValues(value, (v, key) => process(host, 'serialize', v, { type: spec.CANONICAL_ANY }, `key ${(0, util_1.inspect)(key)}`));
|
|
442
431
|
},
|
|
443
432
|
deserialize(value, _type, host) {
|
|
444
433
|
if (value == null) {
|
|
@@ -454,7 +443,7 @@ exports.SERIALIZERS = {
|
|
|
454
443
|
}
|
|
455
444
|
if (Array.isArray(value)) {
|
|
456
445
|
host.debug('ANY is an Array');
|
|
457
|
-
return value.map((e) => host
|
|
446
|
+
return value.map((e, idx) => process(host, 'deserialize', e, { type: spec.CANONICAL_ANY }, `index ${(0, util_1.inspect)(idx)}`));
|
|
458
447
|
}
|
|
459
448
|
if ((0, api_1.isWireEnum)(value)) {
|
|
460
449
|
host.debug('ANY is an Enum');
|
|
@@ -484,7 +473,7 @@ exports.SERIALIZERS = {
|
|
|
484
473
|
}
|
|
485
474
|
// At this point again, deserialize by-value.
|
|
486
475
|
host.debug('ANY is a Map');
|
|
487
|
-
return mapValues(value, (v) => host
|
|
476
|
+
return mapValues(value, (v, key) => process(host, 'deserialize', v, { type: spec.CANONICAL_ANY }, `key ${(0, util_1.inspect)(key)}`));
|
|
488
477
|
},
|
|
489
478
|
},
|
|
490
479
|
};
|
|
@@ -498,13 +487,13 @@ function deserializeEnum(value, lookup) {
|
|
|
498
487
|
const enumLocator = value[api_1.TOKEN_ENUM];
|
|
499
488
|
const sep = enumLocator.lastIndexOf('/');
|
|
500
489
|
if (sep === -1) {
|
|
501
|
-
throw new
|
|
490
|
+
throw new SerializationError(`Invalid enum token value ${(0, util_1.inspect)(enumLocator)}`, value);
|
|
502
491
|
}
|
|
503
492
|
const typeName = enumLocator.slice(0, sep);
|
|
504
493
|
const valueName = enumLocator.slice(sep + 1);
|
|
505
494
|
const enumValue = lookup(typeName)[valueName];
|
|
506
495
|
if (enumValue === undefined) {
|
|
507
|
-
throw new
|
|
496
|
+
throw new SerializationError(`No such enum member: ${(0, util_1.inspect)(valueName)}`, value);
|
|
508
497
|
}
|
|
509
498
|
return enumValue;
|
|
510
499
|
}
|
|
@@ -514,9 +503,7 @@ function deserializeEnum(value, lookup) {
|
|
|
514
503
|
* There can be multiple, because the type can be a type union.
|
|
515
504
|
*/
|
|
516
505
|
function serializationType(typeRef, lookup) {
|
|
517
|
-
|
|
518
|
-
throw new Error("Kernel error: expected type information, got 'undefined'");
|
|
519
|
-
}
|
|
506
|
+
assert(typeRef != null, `Kernel error: expected type information, got ${(0, util_1.inspect)(typeRef)}`);
|
|
520
507
|
if (typeRef === 'void') {
|
|
521
508
|
return [{ serializationClass: "Void" /* SerializationClass.Void */, typeRef }];
|
|
522
509
|
}
|
|
@@ -533,7 +520,7 @@ function serializationType(typeRef, lookup) {
|
|
|
533
520
|
case spec.PrimitiveType.String:
|
|
534
521
|
return [{ serializationClass: "Scalar" /* SerializationClass.Scalar */, typeRef }];
|
|
535
522
|
}
|
|
536
|
-
|
|
523
|
+
assert(false, `Unknown primitive type: ${(0, util_1.inspect)(typeRef.type)}`);
|
|
537
524
|
}
|
|
538
525
|
if (spec.isCollectionTypeReference(typeRef.type)) {
|
|
539
526
|
return [
|
|
@@ -571,7 +558,7 @@ function nullAndOk(x, type) {
|
|
|
571
558
|
return false;
|
|
572
559
|
}
|
|
573
560
|
if (type !== 'void' && !type.optional) {
|
|
574
|
-
throw new
|
|
561
|
+
throw new SerializationError(`A value is required (type is non-optional)`, x);
|
|
575
562
|
}
|
|
576
563
|
return true;
|
|
577
564
|
}
|
|
@@ -594,7 +581,10 @@ function flatMap(xs, fn) {
|
|
|
594
581
|
*/
|
|
595
582
|
function mapValues(value, fn) {
|
|
596
583
|
if (typeof value !== 'object' || value == null) {
|
|
597
|
-
throw new
|
|
584
|
+
throw new SerializationError(`Value is not an object`, value);
|
|
585
|
+
}
|
|
586
|
+
if (Array.isArray(value)) {
|
|
587
|
+
throw new SerializationError(`Value is an array`, value);
|
|
598
588
|
}
|
|
599
589
|
const out = {};
|
|
600
590
|
for (const [k, v] of Object.entries(value)) {
|
|
@@ -607,6 +597,7 @@ function mapValues(value, fn) {
|
|
|
607
597
|
return out;
|
|
608
598
|
}
|
|
609
599
|
function propertiesOf(t, lookup) {
|
|
600
|
+
var _a;
|
|
610
601
|
if (!spec.isClassOrInterfaceType(t)) {
|
|
611
602
|
return {};
|
|
612
603
|
}
|
|
@@ -619,7 +610,7 @@ function propertiesOf(t, lookup) {
|
|
|
619
610
|
if (spec.isClassType(t) && t.base) {
|
|
620
611
|
ret = { ...ret, ...propertiesOf(lookup(t.base), lookup) };
|
|
621
612
|
}
|
|
622
|
-
for (const prop of t.properties
|
|
613
|
+
for (const prop of (_a = t.properties) !== null && _a !== void 0 ? _a : []) {
|
|
623
614
|
ret[prop.name] = prop;
|
|
624
615
|
}
|
|
625
616
|
return ret;
|
|
@@ -659,7 +650,9 @@ function validateRequiredProps(actualProps, typeName, specProps) {
|
|
|
659
650
|
.filter((name) => !specProps[name].optional)
|
|
660
651
|
.filter((name) => !(name in actualProps));
|
|
661
652
|
if (missingRequiredProps.length > 0) {
|
|
662
|
-
throw new
|
|
653
|
+
throw new SerializationError(`Missing required properties for ${typeName}: ${missingRequiredProps
|
|
654
|
+
.map((p) => (0, util_1.inspect)(p))
|
|
655
|
+
.join(', ')}`, actualProps);
|
|
663
656
|
}
|
|
664
657
|
return actualProps;
|
|
665
658
|
}
|
|
@@ -697,9 +690,9 @@ function isByReferenceOnly(obj) {
|
|
|
697
690
|
do {
|
|
698
691
|
for (const prop of Object.getOwnPropertyNames(curr)) {
|
|
699
692
|
const descr = Object.getOwnPropertyDescriptor(curr, prop);
|
|
700
|
-
if (descr
|
|
701
|
-
descr
|
|
702
|
-
typeof descr
|
|
693
|
+
if ((descr === null || descr === void 0 ? void 0 : descr.get) != null ||
|
|
694
|
+
(descr === null || descr === void 0 ? void 0 : descr.set) != null ||
|
|
695
|
+
typeof (descr === null || descr === void 0 ? void 0 : descr.value) === 'function') {
|
|
703
696
|
// Property has a dynamic getter, setter or is a constructor/method, so by-ref required!
|
|
704
697
|
return true;
|
|
705
698
|
}
|
|
@@ -708,4 +701,91 @@ function isByReferenceOnly(obj) {
|
|
|
708
701
|
} while (Object.getPrototypeOf((curr = Object.getPrototypeOf(curr))) != null);
|
|
709
702
|
return false;
|
|
710
703
|
}
|
|
704
|
+
function process(host, serde, value, type, context) {
|
|
705
|
+
const wireTypes = serializationType(type, host.lookupType);
|
|
706
|
+
host.debug(serde, value, wireTypes);
|
|
707
|
+
const errors = new Array();
|
|
708
|
+
for (const { serializationClass, typeRef } of wireTypes) {
|
|
709
|
+
try {
|
|
710
|
+
return exports.SERIALIZERS[serializationClass][serde](value, typeRef, host);
|
|
711
|
+
}
|
|
712
|
+
catch (error) {
|
|
713
|
+
error.context = `as ${typeRef === VOID ? VOID : spec.describeTypeReference(typeRef.type)}`;
|
|
714
|
+
errors.push(error);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
const typeDescr = type === VOID ? type : spec.describeTypeReference(type.type);
|
|
718
|
+
const optionalTypeDescr = type !== VOID && type.optional ? `${typeDescr} | undefined` : typeDescr;
|
|
719
|
+
throw new SerializationError(`${titleize(context)}: Unable to ${serde} value as ${optionalTypeDescr}`, value, errors, { renderValue: true });
|
|
720
|
+
function titleize(text) {
|
|
721
|
+
text = text.trim();
|
|
722
|
+
if (text === '') {
|
|
723
|
+
return text;
|
|
724
|
+
}
|
|
725
|
+
const [first, ...rest] = text;
|
|
726
|
+
return [first.toUpperCase(), ...rest].join('');
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
exports.process = process;
|
|
730
|
+
class SerializationError extends Error {
|
|
731
|
+
constructor(message, value, causes = [], { renderValue = false } = {}) {
|
|
732
|
+
super([
|
|
733
|
+
message,
|
|
734
|
+
...(renderValue
|
|
735
|
+
? [
|
|
736
|
+
`${causes.length > 0 ? '\u{251C}' : '\u{2570}'}\u{2500}\u{2500} \u{1F6D1} Failing value is ${describeTypeOf(value)}`,
|
|
737
|
+
...(value == null
|
|
738
|
+
? []
|
|
739
|
+
: (0, util_1.inspect)(value, false, 0)
|
|
740
|
+
.split('\n')
|
|
741
|
+
.map((l) => `${causes.length > 0 ? '\u{2502}' : ' '} ${l}`)),
|
|
742
|
+
]
|
|
743
|
+
: []),
|
|
744
|
+
...(causes.length > 0
|
|
745
|
+
? [
|
|
746
|
+
'\u{2570}\u{2500}\u{2500} \u{1F50D} Failure reason(s):',
|
|
747
|
+
...causes.map((cause, idx) => {
|
|
748
|
+
var _a;
|
|
749
|
+
return ` ${idx < causes.length - 1 ? '\u{251C}' : '\u{2570}'}\u{2500}${causes.length > 1
|
|
750
|
+
? ` [${(_a = cause.context) !== null && _a !== void 0 ? _a : (0, util_1.inspect)(idx)}]`
|
|
751
|
+
: ''} ${cause.message.split('\n').join('\n ')}`;
|
|
752
|
+
}),
|
|
753
|
+
]
|
|
754
|
+
: []),
|
|
755
|
+
].join('\n'));
|
|
756
|
+
this.value = value;
|
|
757
|
+
this.causes = causes;
|
|
758
|
+
this.name = '@jsii/kernel.SerializationError';
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
exports.SerializationError = SerializationError;
|
|
762
|
+
function describeTypeOf(value) {
|
|
763
|
+
const type = typeof value;
|
|
764
|
+
switch (type) {
|
|
765
|
+
case 'object':
|
|
766
|
+
if (value == null) {
|
|
767
|
+
return JSON.stringify(value);
|
|
768
|
+
}
|
|
769
|
+
if (Array.isArray(value)) {
|
|
770
|
+
return 'an array';
|
|
771
|
+
}
|
|
772
|
+
const fqn = (0, objects_1.jsiiTypeFqn)(value);
|
|
773
|
+
if (fqn != null && fqn !== exports.EMPTY_OBJECT_FQN) {
|
|
774
|
+
return `an instance of ${fqn}`;
|
|
775
|
+
}
|
|
776
|
+
const ctorName = value.constructor.name;
|
|
777
|
+
if (ctorName != null && ctorName !== Object.name) {
|
|
778
|
+
return `an instance of ${ctorName}`;
|
|
779
|
+
}
|
|
780
|
+
return `an object`;
|
|
781
|
+
case 'undefined':
|
|
782
|
+
return type;
|
|
783
|
+
case 'boolean':
|
|
784
|
+
case 'function':
|
|
785
|
+
case 'number':
|
|
786
|
+
case 'string':
|
|
787
|
+
default:
|
|
788
|
+
return `a ${type}`;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
711
791
|
//# sourceMappingURL=serialization.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsii/kernel",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.62.0",
|
|
4
4
|
"description": "kernel for jsii execution environment",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": {
|
|
@@ -31,17 +31,17 @@
|
|
|
31
31
|
"package": "package-js"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@jsii/spec": "^1.
|
|
34
|
+
"@jsii/spec": "^1.62.0",
|
|
35
35
|
"fs-extra": "^10.1.0",
|
|
36
36
|
"tar": "^6.1.11"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@scope/jsii-calc-base": "^1.
|
|
40
|
-
"@scope/jsii-calc-lib": "^1.
|
|
39
|
+
"@scope/jsii-calc-base": "^1.62.0",
|
|
40
|
+
"@scope/jsii-calc-lib": "^1.62.0",
|
|
41
41
|
"@types/fs-extra": "^9.0.13",
|
|
42
42
|
"@types/tar": "^6.1.1",
|
|
43
43
|
"jest-expect-message": "^1.0.2",
|
|
44
|
-
"jsii-build-tools": "^1.
|
|
44
|
+
"jsii-build-tools": "^1.62.0",
|
|
45
45
|
"jsii-calc": "^3.20.120"
|
|
46
46
|
}
|
|
47
47
|
}
|