@depup/webpack 5.109.0-depup.0 → 5.109.2-depup.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/README.md +4 -4
- package/bin/webpack.js +12 -0
- package/changes.json +4 -4
- package/lib/ChunkGraph.js +17 -15
- package/lib/CleanPlugin.js +11 -9
- package/lib/CompatibilityPlugin.js +31 -0
- package/lib/Compilation.js +21 -5
- package/lib/Compiler.js +16 -4
- package/lib/DefinePlugin.js +47 -20
- package/lib/ExportsInfo.js +22 -5
- package/lib/ExternalModule.js +10 -7
- package/lib/FileSystemInfo.js +126 -26
- package/lib/FlagDependencyUsagePlugin.js +33 -12
- package/lib/InitFragment.js +20 -32
- package/lib/ModuleFilenameHelpers.js +13 -2
- package/lib/NormalModule.js +80 -71
- package/lib/NormalModuleFactory.js +8 -2
- package/lib/RuntimePlugin.js +40 -113
- package/lib/Template.js +23 -3
- package/lib/cache/PackFileCacheStrategy.js +259 -5
- package/lib/config/defaults.js +21 -2
- package/lib/container/HoistContainerReferencesPlugin.js +47 -55
- package/lib/container/ModuleFederationPlugin.js +15 -9
- package/lib/css/CssGenerator.js +8 -2
- package/lib/css/CssLoadingRuntimeModule.js +25 -12
- package/lib/css/CssModulesPlugin.js +29 -18
- package/lib/css/CssParser.js +135 -50
- package/lib/css/syntax.js +862 -765
- package/lib/dependencies/CommonJsExportRequireDependency.js +19 -0
- package/lib/dependencies/CommonJsFullRequireDependency.js +33 -4
- package/lib/dependencies/CommonJsImportsParserPlugin.js +2 -0
- package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +2 -1
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +17 -9
- package/lib/dependencies/HarmonyImportDependency.js +1 -1
- package/lib/dependencies/HarmonyImportGuard.js +2 -1
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +10 -7
- package/lib/esm/ModuleChunkLoadingRuntimeModule.js +15 -9
- package/lib/hmr/lazyCompilationBackend.js +19 -4
- package/lib/html/HtmlGenerator.js +23 -3
- package/lib/html/HtmlModulesPlugin.js +30 -12
- package/lib/html/syntax.js +2485 -2399
- package/lib/ids/IdHelpers.js +24 -10
- package/lib/javascript/JavascriptModulesPlugin.js +83 -49
- package/lib/javascript/JavascriptParser.js +49 -13
- package/lib/javascript/syntax.js +700 -43
- package/lib/node/ReadFileCompileAsyncWasmPlugin.js +10 -2
- package/lib/node/ReadFileCompileWasmPlugin.js +10 -2
- package/lib/optimize/AggressiveMergingPlugin.js +19 -15
- package/lib/optimize/ConcatenatedModule.js +19 -15
- package/lib/optimize/ModuleConcatenationPlugin.js +73 -24
- package/lib/optimize/RealContentHashPlugin.js +10 -7
- package/lib/optimize/SplitChunksPlugin.js +146 -44
- package/lib/prefetch/ResourceHintPlugin.js +96 -72
- package/lib/serialization/BinaryMiddleware.js +270 -938
- package/lib/serialization/FileMiddleware.js +299 -60
- package/lib/stats/DefaultStatsFactoryPlugin.js +204 -198
- package/lib/stats/DefaultStatsPrinterPlugin.js +24 -166
- package/lib/stats/StatsFactory.js +31 -9
- package/lib/util/identifier.js +21 -1
- package/package.json +10 -10
- package/schemas/WebpackOptions.json +110 -55
- package/types.d.ts +832 -247
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
"use strict";
|
|
6
6
|
|
|
7
|
+
const { deserialize: v8Deserialize, serialize: v8Serialize } = require("v8");
|
|
7
8
|
const memoize = require("../util/memoize");
|
|
8
9
|
const SerializerMiddleware = require("./SerializerMiddleware");
|
|
9
10
|
|
|
@@ -15,99 +16,33 @@ Format:
|
|
|
15
16
|
|
|
16
17
|
File -> Section*
|
|
17
18
|
|
|
18
|
-
Section ->
|
|
19
|
-
BooleansSection |
|
|
20
|
-
F64NumbersSection |
|
|
21
|
-
I32NumbersSection |
|
|
22
|
-
I8NumbersSection |
|
|
23
|
-
ShortStringSection |
|
|
24
|
-
BigIntSection |
|
|
25
|
-
I32BigIntSection |
|
|
26
|
-
I8BigIntSection
|
|
27
|
-
StringSection |
|
|
28
|
-
BufferSection |
|
|
29
|
-
NopSection
|
|
19
|
+
Section -> ValuesSection | LazySection
|
|
30
20
|
|
|
21
|
+
ValuesSection ->
|
|
22
|
+
ValuesHeaderByte u32:payloadSize u32:bufferCount (u32:valueIndex u32:bufferSize)*
|
|
23
|
+
payload buffer*
|
|
24
|
+
LazySection ->
|
|
25
|
+
LazyHeaderByte u32:count u32:size*
|
|
31
26
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
NullHeaderByte | Null2HeaderByte | Null3HeaderByte |
|
|
35
|
-
Nulls8HeaderByte 0xnn (n:count - 4) |
|
|
36
|
-
Nulls32HeaderByte n:ui32 (n:count - 260) |
|
|
37
|
-
BooleansSection -> TrueHeaderByte | FalseHeaderByte | BooleansSectionHeaderByte BooleansCountAndBitsByte
|
|
38
|
-
F64NumbersSection -> F64NumbersSectionHeaderByte f64*
|
|
39
|
-
I32NumbersSection -> I32NumbersSectionHeaderByte i32*
|
|
40
|
-
I8NumbersSection -> I8NumbersSectionHeaderByte i8*
|
|
41
|
-
ShortStringSection -> ShortStringSectionHeaderByte ascii-byte*
|
|
42
|
-
StringSection -> StringSectionHeaderByte i32:length utf8-byte*
|
|
43
|
-
BufferSection -> BufferSectionHeaderByte i32:length byte*
|
|
44
|
-
NopSection --> NopSectionHeaderByte
|
|
45
|
-
BigIntSection -> BigIntSectionHeaderByte i32:length ascii-byte*
|
|
46
|
-
I32BigIntSection -> I32BigIntSectionHeaderByte i32
|
|
47
|
-
I8BigIntSection -> I8BigIntSectionHeaderByte i8
|
|
48
|
-
|
|
49
|
-
ShortStringSectionHeaderByte -> 0b1nnn_nnnn (n:length)
|
|
50
|
-
|
|
51
|
-
F64NumbersSectionHeaderByte -> 0b001n_nnnn (n:count - 1)
|
|
52
|
-
I32NumbersSectionHeaderByte -> 0b010n_nnnn (n:count - 1)
|
|
53
|
-
I8NumbersSectionHeaderByte -> 0b011n_nnnn (n:count - 1)
|
|
54
|
-
|
|
55
|
-
NullsSectionHeaderByte -> 0b0001_nnnn (n:count - 1)
|
|
56
|
-
BooleansCountAndBitsByte ->
|
|
57
|
-
0b0000_1xxx (count = 3) |
|
|
58
|
-
0b0001_xxxx (count = 4) |
|
|
59
|
-
0b001x_xxxx (count = 5) |
|
|
60
|
-
0b01xx_xxxx (count = 6) |
|
|
61
|
-
0b1nnn_nnnn (n:count - 7, 7 <= count <= 133)
|
|
62
|
-
0xff n:ui32 (n:count, 134 <= count < 2^32)
|
|
63
|
-
|
|
64
|
-
StringSectionHeaderByte -> 0b0000_1110
|
|
65
|
-
BufferSectionHeaderByte -> 0b0000_1111
|
|
66
|
-
NopSectionHeaderByte -> 0b0000_1011
|
|
67
|
-
BigIntSectionHeaderByte -> 0b0001_1010
|
|
68
|
-
I32BigIntSectionHeaderByte -> 0b0001_1100
|
|
69
|
-
I8BigIntSectionHeaderByte -> 0b0001_1011
|
|
70
|
-
FalseHeaderByte -> 0b0000_1100
|
|
71
|
-
TrueHeaderByte -> 0b0000_1101
|
|
72
|
-
|
|
73
|
-
RawNumber -> n (n <= 10)
|
|
74
|
-
|
|
27
|
+
ValuesHeaderByte -> 0xf1
|
|
28
|
+
LazyHeaderByte -> 0xf2
|
|
75
29
|
*/
|
|
76
30
|
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
const FALSE_HEADER = 0x0d;
|
|
80
|
-
const BOOLEANS_HEADER = 0x0e;
|
|
81
|
-
const NULL_HEADER = 0x10;
|
|
82
|
-
const NULL2_HEADER = 0x11;
|
|
83
|
-
const NULL3_HEADER = 0x12;
|
|
84
|
-
const NULLS8_HEADER = 0x13;
|
|
85
|
-
const NULLS32_HEADER = 0x14;
|
|
86
|
-
const NULL_AND_I8_HEADER = 0x15;
|
|
87
|
-
const NULL_AND_I16_HEADER = 0x19;
|
|
88
|
-
const NULL_AND_I32_HEADER = 0x16;
|
|
89
|
-
const NULL_AND_TRUE_HEADER = 0x17;
|
|
90
|
-
const NULL_AND_FALSE_HEADER = 0x18;
|
|
91
|
-
const BIGINT_HEADER = 0x1a;
|
|
92
|
-
const BIGINT_I8_HEADER = 0x1b;
|
|
93
|
-
const BIGINT_I32_HEADER = 0x1c;
|
|
94
|
-
const STRING_HEADER = 0x1e;
|
|
95
|
-
const BUFFER_HEADER = 0x1f;
|
|
96
|
-
const I8_HEADER = 0x60;
|
|
97
|
-
const I32_HEADER = 0x40;
|
|
98
|
-
const F64_HEADER = 0x20;
|
|
99
|
-
const SHORT_STRING_HEADER = 0x80;
|
|
100
|
-
|
|
101
|
-
/** Uplift high-order bits */
|
|
102
|
-
const NUMBERS_HEADER_MASK = 0xe0; // 0b1010_0000
|
|
103
|
-
const NUMBERS_COUNT_MASK = 0x1f; // 0b0001_1111
|
|
104
|
-
const SHORT_STRING_LENGTH_MASK = 0x7f; // 0b0111_1111
|
|
31
|
+
const VALUES_HEADER = 0xf1;
|
|
32
|
+
const LAZY_HEADER = 0xf2;
|
|
105
33
|
|
|
106
34
|
const HEADER_SIZE = 1;
|
|
107
|
-
const I8_SIZE = 1;
|
|
108
|
-
const I16_SIZE = 2;
|
|
109
35
|
const I32_SIZE = 4;
|
|
110
|
-
|
|
36
|
+
|
|
37
|
+
/** A values section is closed once its payload is estimated to reach this size. */
|
|
38
|
+
const MAX_SECTION_SIZE = 16 * 1024 * 1024;
|
|
39
|
+
/** Assumed encoded size of a value that isn't a string, for that estimate. */
|
|
40
|
+
const ESTIMATED_VALUE_SIZE = 4;
|
|
41
|
+
|
|
42
|
+
const EMPTY_BUFFER = Buffer.alloc(0);
|
|
43
|
+
|
|
44
|
+
/** Highest V8 value serialization format version this Node.js can read. */
|
|
45
|
+
const V8_FORMAT_VERSION = v8Serialize(null)[1];
|
|
111
46
|
|
|
112
47
|
const MEASURE_START_OPERATION = Symbol("MEASURE_START_OPERATION");
|
|
113
48
|
const MEASURE_END_OPERATION = Symbol("MEASURE_END_OPERATION");
|
|
@@ -115,30 +50,6 @@ const MEASURE_END_OPERATION = Symbol("MEASURE_END_OPERATION");
|
|
|
115
50
|
/** @typedef {typeof MEASURE_START_OPERATION} MEASURE_START_OPERATION_TYPE */
|
|
116
51
|
/** @typedef {typeof MEASURE_END_OPERATION} MEASURE_END_OPERATION_TYPE */
|
|
117
52
|
|
|
118
|
-
/**
|
|
119
|
-
* Returns type of number for serialization.
|
|
120
|
-
* @param {number} n number
|
|
121
|
-
* @returns {0 | 1 | 2} type of number for serialization
|
|
122
|
-
*/
|
|
123
|
-
const identifyNumber = (n) => {
|
|
124
|
-
if (n === (n | 0)) {
|
|
125
|
-
if (n <= 127 && n >= -128) return 0;
|
|
126
|
-
if (n <= 2147483647 && n >= -2147483648) return 1;
|
|
127
|
-
}
|
|
128
|
-
return 2;
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Returns type of bigint for serialization.
|
|
133
|
-
* @param {bigint} n bigint
|
|
134
|
-
* @returns {0 | 1 | 2} type of bigint for serialization
|
|
135
|
-
*/
|
|
136
|
-
const identifyBigInt = (n) => {
|
|
137
|
-
if (n <= BigInt(127) && n >= BigInt(-128)) return 0;
|
|
138
|
-
if (n <= BigInt(2147483647) && n >= BigInt(-2147483648)) return 1;
|
|
139
|
-
return 2;
|
|
140
|
-
};
|
|
141
|
-
|
|
142
53
|
/** @typedef {PrimitiveSerializableType[]} DeserializedType */
|
|
143
54
|
/** @typedef {BufferSerializableType[]} SerializedType} */
|
|
144
55
|
/** @typedef {{ retainedBuffer?: (x: Buffer) => Buffer }} Context} */
|
|
@@ -150,34 +61,24 @@ const identifyBigInt = (n) => {
|
|
|
150
61
|
* @typedef {import("./SerializerMiddleware").LazyFunction<LazyInputValue, LazyOutputValue, BinaryMiddleware, undefined>} LazyFunction
|
|
151
62
|
*/
|
|
152
63
|
|
|
153
|
-
/**
|
|
154
|
-
* Mutable read state of one `_deserialize` run; the module-level dispatch
|
|
155
|
-
* table operates on this instead of per-call closures.
|
|
156
|
-
*/
|
|
64
|
+
/** Mutable read state of one `_deserialize` run. */
|
|
157
65
|
class ReadState {
|
|
158
66
|
/**
|
|
159
67
|
* @param {SerializedType} data data
|
|
160
68
|
* @param {Context} context context object
|
|
161
|
-
* @param {BinaryMiddleware} middleware binary middleware
|
|
162
69
|
*/
|
|
163
|
-
constructor(data, context
|
|
70
|
+
constructor(data, context) {
|
|
164
71
|
/** @type {SerializedType} */
|
|
165
72
|
this.data = data;
|
|
166
|
-
/** @type {Context} */
|
|
167
|
-
this.context = context;
|
|
168
|
-
/** @type {BinaryMiddleware} */
|
|
169
|
-
this.middleware = middleware;
|
|
170
73
|
this.retainedBuffer = context.retainedBuffer || ((x) => x);
|
|
171
74
|
/** @type {number} */
|
|
172
75
|
this.currentDataItem = 0;
|
|
173
76
|
/** @type {BufferSerializableType | null} */
|
|
174
|
-
this.currentBuffer = data[0];
|
|
77
|
+
this.currentBuffer = data.length > 0 ? data[0] : null;
|
|
175
78
|
/** @type {boolean} */
|
|
176
79
|
this.currentIsBuffer = Buffer.isBuffer(this.currentBuffer);
|
|
177
80
|
/** @type {number} */
|
|
178
81
|
this.currentPosition = 0;
|
|
179
|
-
/** @type {DeserializedType} */
|
|
180
|
-
this.result = [];
|
|
181
82
|
}
|
|
182
83
|
|
|
183
84
|
/** Advances to the next data item (does not reset the position). */
|
|
@@ -228,6 +129,7 @@ class ReadState {
|
|
|
228
129
|
* @returns {Buffer} buffer with bytes
|
|
229
130
|
*/
|
|
230
131
|
read(n) {
|
|
132
|
+
if (n === 0) return EMPTY_BUFFER;
|
|
231
133
|
this.ensureBuffer();
|
|
232
134
|
const rem =
|
|
233
135
|
/** @type {Buffer} */ (this.currentBuffer).length - this.currentPosition;
|
|
@@ -284,7 +186,7 @@ class ReadState {
|
|
|
284
186
|
const byte =
|
|
285
187
|
/** @type {Buffer} */
|
|
286
188
|
(this.currentBuffer).readUInt8(this.currentPosition);
|
|
287
|
-
this.currentPosition +=
|
|
189
|
+
this.currentPosition += HEADER_SIZE;
|
|
288
190
|
this.checkOverflow();
|
|
289
191
|
return byte;
|
|
290
192
|
}
|
|
@@ -305,365 +207,64 @@ class ReadState {
|
|
|
305
207
|
}
|
|
306
208
|
return this.read(I32_SIZE).readUInt32LE(0);
|
|
307
209
|
}
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* Pushes the lowest n bits of data as booleans.
|
|
311
|
-
* @param {number} data data
|
|
312
|
-
* @param {number} n n
|
|
313
|
-
*/
|
|
314
|
-
readBits(data, n) {
|
|
315
|
-
let mask = 1;
|
|
316
|
-
while (n !== 0) {
|
|
317
|
-
this.result.push((data & mask) !== 0);
|
|
318
|
-
mask <<= 1;
|
|
319
|
-
n--;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
210
|
}
|
|
323
211
|
|
|
324
212
|
/**
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
* @
|
|
213
|
+
* Reads a section of values written by V8's value serializer.
|
|
214
|
+
* @param {ReadState} state read state
|
|
215
|
+
* @returns {DeserializedType} values of the section
|
|
328
216
|
*/
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
content.push(s.retainedBuffer(buf));
|
|
351
|
-
} while (l > 0);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
s.result.push(s.middleware._createLazyDeserialized(content, s.context));
|
|
355
|
-
};
|
|
356
|
-
case BUFFER_HEADER:
|
|
357
|
-
return (s) => {
|
|
358
|
-
const len = s.readU32();
|
|
359
|
-
s.result.push(s.retainedBuffer(s.read(len)));
|
|
360
|
-
};
|
|
361
|
-
case TRUE_HEADER:
|
|
362
|
-
return (s) => s.result.push(true);
|
|
363
|
-
case FALSE_HEADER:
|
|
364
|
-
return (s) => s.result.push(false);
|
|
365
|
-
case NULL3_HEADER:
|
|
366
|
-
return (s) => s.result.push(null, null, null);
|
|
367
|
-
case NULL2_HEADER:
|
|
368
|
-
return (s) => s.result.push(null, null);
|
|
369
|
-
case NULL_HEADER:
|
|
370
|
-
return (s) => s.result.push(null);
|
|
371
|
-
case NULL_AND_TRUE_HEADER:
|
|
372
|
-
return (s) => s.result.push(null, true);
|
|
373
|
-
case NULL_AND_FALSE_HEADER:
|
|
374
|
-
return (s) => s.result.push(null, false);
|
|
375
|
-
case NULL_AND_I8_HEADER:
|
|
376
|
-
return (s) => {
|
|
377
|
-
if (s.currentIsBuffer) {
|
|
378
|
-
s.result.push(
|
|
379
|
-
null,
|
|
380
|
-
/** @type {Buffer} */ (s.currentBuffer).readInt8(s.currentPosition)
|
|
381
|
-
);
|
|
382
|
-
s.currentPosition += I8_SIZE;
|
|
383
|
-
s.checkOverflow();
|
|
384
|
-
} else {
|
|
385
|
-
s.result.push(null, s.read(I8_SIZE).readInt8(0));
|
|
386
|
-
}
|
|
387
|
-
};
|
|
388
|
-
case NULL_AND_I16_HEADER:
|
|
389
|
-
return (s) => {
|
|
390
|
-
s.result.push(null);
|
|
391
|
-
if (s.isInCurrentBuffer(I16_SIZE)) {
|
|
392
|
-
s.result.push(
|
|
393
|
-
/** @type {Buffer} */ (s.currentBuffer).readInt16LE(
|
|
394
|
-
s.currentPosition
|
|
395
|
-
)
|
|
396
|
-
);
|
|
397
|
-
s.currentPosition += I16_SIZE;
|
|
398
|
-
s.checkOverflow();
|
|
399
|
-
} else {
|
|
400
|
-
s.result.push(s.read(I16_SIZE).readInt16LE(0));
|
|
401
|
-
}
|
|
402
|
-
};
|
|
403
|
-
case NULL_AND_I32_HEADER:
|
|
404
|
-
return (s) => {
|
|
405
|
-
s.result.push(null);
|
|
406
|
-
if (s.isInCurrentBuffer(I32_SIZE)) {
|
|
407
|
-
s.result.push(
|
|
408
|
-
/** @type {Buffer} */ (s.currentBuffer).readInt32LE(
|
|
409
|
-
s.currentPosition
|
|
410
|
-
)
|
|
411
|
-
);
|
|
412
|
-
s.currentPosition += I32_SIZE;
|
|
413
|
-
s.checkOverflow();
|
|
414
|
-
} else {
|
|
415
|
-
s.result.push(s.read(I32_SIZE).readInt32LE(0));
|
|
416
|
-
}
|
|
417
|
-
};
|
|
418
|
-
case NULLS8_HEADER:
|
|
419
|
-
return (s) => {
|
|
420
|
-
const len = s.readU8() + 4;
|
|
421
|
-
for (let i = 0; i < len; i++) {
|
|
422
|
-
s.result.push(null);
|
|
423
|
-
}
|
|
424
|
-
};
|
|
425
|
-
case NULLS32_HEADER:
|
|
426
|
-
return (s) => {
|
|
427
|
-
const len = s.readU32() + 260;
|
|
428
|
-
for (let i = 0; i < len; i++) {
|
|
429
|
-
s.result.push(null);
|
|
430
|
-
}
|
|
431
|
-
};
|
|
432
|
-
case BOOLEANS_HEADER:
|
|
433
|
-
return (s) => {
|
|
434
|
-
const innerHeader = s.readU8();
|
|
435
|
-
if ((innerHeader & 0xf0) === 0) {
|
|
436
|
-
s.readBits(innerHeader, 3);
|
|
437
|
-
} else if ((innerHeader & 0xe0) === 0) {
|
|
438
|
-
s.readBits(innerHeader, 4);
|
|
439
|
-
} else if ((innerHeader & 0xc0) === 0) {
|
|
440
|
-
s.readBits(innerHeader, 5);
|
|
441
|
-
} else if ((innerHeader & 0x80) === 0) {
|
|
442
|
-
s.readBits(innerHeader, 6);
|
|
443
|
-
} else if (innerHeader !== 0xff) {
|
|
444
|
-
let count = (innerHeader & 0x7f) + 7;
|
|
445
|
-
while (count > 8) {
|
|
446
|
-
s.readBits(s.readU8(), 8);
|
|
447
|
-
count -= 8;
|
|
448
|
-
}
|
|
449
|
-
s.readBits(s.readU8(), count);
|
|
450
|
-
} else {
|
|
451
|
-
let count = s.readU32();
|
|
452
|
-
while (count > 8) {
|
|
453
|
-
s.readBits(s.readU8(), 8);
|
|
454
|
-
count -= 8;
|
|
455
|
-
}
|
|
456
|
-
s.readBits(s.readU8(), count);
|
|
457
|
-
}
|
|
458
|
-
};
|
|
459
|
-
case STRING_HEADER:
|
|
460
|
-
return (s) => {
|
|
461
|
-
const len = s.readU32();
|
|
462
|
-
if (s.isInCurrentBuffer(len) && s.currentPosition + len < 0x7fffffff) {
|
|
463
|
-
s.result.push(
|
|
464
|
-
/** @type {Buffer} */
|
|
465
|
-
(s.currentBuffer).toString(
|
|
466
|
-
undefined,
|
|
467
|
-
s.currentPosition,
|
|
468
|
-
s.currentPosition + len
|
|
469
|
-
)
|
|
470
|
-
);
|
|
471
|
-
s.currentPosition += len;
|
|
472
|
-
s.checkOverflow();
|
|
473
|
-
} else {
|
|
474
|
-
s.result.push(s.read(len).toString());
|
|
475
|
-
}
|
|
476
|
-
};
|
|
477
|
-
case SHORT_STRING_HEADER:
|
|
478
|
-
return (s) => s.result.push("");
|
|
479
|
-
case SHORT_STRING_HEADER | 1:
|
|
480
|
-
return (s) => {
|
|
481
|
-
if (s.currentIsBuffer && s.currentPosition < 0x7ffffffe) {
|
|
482
|
-
s.result.push(
|
|
483
|
-
/** @type {Buffer} */
|
|
484
|
-
(s.currentBuffer).toString(
|
|
485
|
-
"latin1",
|
|
486
|
-
s.currentPosition,
|
|
487
|
-
s.currentPosition + 1
|
|
488
|
-
)
|
|
489
|
-
);
|
|
490
|
-
s.currentPosition++;
|
|
491
|
-
s.checkOverflow();
|
|
492
|
-
} else {
|
|
493
|
-
s.result.push(s.read(1).toString("latin1"));
|
|
494
|
-
}
|
|
495
|
-
};
|
|
496
|
-
case I8_HEADER:
|
|
497
|
-
return (s) => {
|
|
498
|
-
if (s.currentIsBuffer) {
|
|
499
|
-
s.result.push(
|
|
500
|
-
/** @type {Buffer} */ (s.currentBuffer).readInt8(s.currentPosition)
|
|
501
|
-
);
|
|
502
|
-
s.currentPosition++;
|
|
503
|
-
s.checkOverflow();
|
|
504
|
-
} else {
|
|
505
|
-
s.result.push(s.read(1).readInt8(0));
|
|
506
|
-
}
|
|
507
|
-
};
|
|
508
|
-
case BIGINT_I8_HEADER: {
|
|
509
|
-
const len = 1;
|
|
510
|
-
return (s) => {
|
|
511
|
-
const need = I8_SIZE * len;
|
|
512
|
-
|
|
513
|
-
if (s.isInCurrentBuffer(need)) {
|
|
514
|
-
for (let i = 0; i < len; i++) {
|
|
515
|
-
const value =
|
|
516
|
-
/** @type {Buffer} */
|
|
517
|
-
(s.currentBuffer).readInt8(s.currentPosition);
|
|
518
|
-
s.result.push(BigInt(value));
|
|
519
|
-
s.currentPosition += I8_SIZE;
|
|
520
|
-
}
|
|
521
|
-
s.checkOverflow();
|
|
522
|
-
} else {
|
|
523
|
-
const buf = s.read(need);
|
|
524
|
-
for (let i = 0; i < len; i++) {
|
|
525
|
-
const value = buf.readInt8(i * I8_SIZE);
|
|
526
|
-
s.result.push(BigInt(value));
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
case BIGINT_I32_HEADER: {
|
|
532
|
-
const len = 1;
|
|
533
|
-
return (s) => {
|
|
534
|
-
const need = I32_SIZE * len;
|
|
535
|
-
if (s.isInCurrentBuffer(need)) {
|
|
536
|
-
for (let i = 0; i < len; i++) {
|
|
537
|
-
const value = /** @type {Buffer} */ (s.currentBuffer).readInt32LE(
|
|
538
|
-
s.currentPosition
|
|
539
|
-
);
|
|
540
|
-
s.result.push(BigInt(value));
|
|
541
|
-
s.currentPosition += I32_SIZE;
|
|
542
|
-
}
|
|
543
|
-
s.checkOverflow();
|
|
544
|
-
} else {
|
|
545
|
-
const buf = s.read(need);
|
|
546
|
-
for (let i = 0; i < len; i++) {
|
|
547
|
-
const value = buf.readInt32LE(i * I32_SIZE);
|
|
548
|
-
s.result.push(BigInt(value));
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
};
|
|
552
|
-
}
|
|
553
|
-
case BIGINT_HEADER: {
|
|
554
|
-
return (s) => {
|
|
555
|
-
const len = s.readU32();
|
|
556
|
-
if (s.isInCurrentBuffer(len) && s.currentPosition + len < 0x7fffffff) {
|
|
557
|
-
const value =
|
|
558
|
-
/** @type {Buffer} */
|
|
559
|
-
(s.currentBuffer).toString(
|
|
560
|
-
undefined,
|
|
561
|
-
s.currentPosition,
|
|
562
|
-
s.currentPosition + len
|
|
563
|
-
);
|
|
217
|
+
const readValuesSection = (state) => {
|
|
218
|
+
const payloadSize = state.readU32();
|
|
219
|
+
const bufferCount = state.readU32();
|
|
220
|
+
/** @type {number[]} */
|
|
221
|
+
const bufferInfo = [];
|
|
222
|
+
for (let i = 0; i < bufferCount * 2; i++) bufferInfo.push(state.readU32());
|
|
223
|
+
const payload = state.read(payloadSize);
|
|
224
|
+
// a V8 payload opens with 0xff and its format version, which only ever grows
|
|
225
|
+
if (payload[0] === 0xff && payload[1] > V8_FORMAT_VERSION) {
|
|
226
|
+
throw new Error(
|
|
227
|
+
`Data was written with V8 serialization format version ${payload[1]}, but this Node.js (${process.version}) only reads up to version ${V8_FORMAT_VERSION}`
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
const values = /** @type {DeserializedType} */ (v8Deserialize(payload));
|
|
231
|
+
for (let i = 0; i < bufferCount; i++) {
|
|
232
|
+
values[bufferInfo[i * 2]] = state.retainedBuffer(
|
|
233
|
+
state.read(bufferInfo[i * 2 + 1])
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
return values;
|
|
237
|
+
};
|
|
564
238
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
s.isInCurrentBuffer(len) &&
|
|
582
|
-
s.currentPosition + len < 0x7fffffff
|
|
583
|
-
) {
|
|
584
|
-
s.result.push(
|
|
585
|
-
/** @type {Buffer} */
|
|
586
|
-
(s.currentBuffer).toString(
|
|
587
|
-
"latin1",
|
|
588
|
-
s.currentPosition,
|
|
589
|
-
s.currentPosition + len
|
|
590
|
-
)
|
|
591
|
-
);
|
|
592
|
-
s.currentPosition += len;
|
|
593
|
-
s.checkOverflow();
|
|
594
|
-
} else {
|
|
595
|
-
s.result.push(s.read(len).toString("latin1"));
|
|
596
|
-
}
|
|
597
|
-
};
|
|
598
|
-
} else if ((header & NUMBERS_HEADER_MASK) === F64_HEADER) {
|
|
599
|
-
const len = (header & NUMBERS_COUNT_MASK) + 1;
|
|
600
|
-
return (s) => {
|
|
601
|
-
const need = F64_SIZE * len;
|
|
602
|
-
if (s.isInCurrentBuffer(need)) {
|
|
603
|
-
for (let i = 0; i < len; i++) {
|
|
604
|
-
s.result.push(
|
|
605
|
-
/** @type {Buffer} */ (s.currentBuffer).readDoubleLE(
|
|
606
|
-
s.currentPosition
|
|
607
|
-
)
|
|
608
|
-
);
|
|
609
|
-
s.currentPosition += F64_SIZE;
|
|
610
|
-
}
|
|
611
|
-
s.checkOverflow();
|
|
612
|
-
} else {
|
|
613
|
-
const buf = s.read(need);
|
|
614
|
-
for (let i = 0; i < len; i++) {
|
|
615
|
-
s.result.push(buf.readDoubleLE(i * F64_SIZE));
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
};
|
|
619
|
-
} else if ((header & NUMBERS_HEADER_MASK) === I32_HEADER) {
|
|
620
|
-
const len = (header & NUMBERS_COUNT_MASK) + 1;
|
|
621
|
-
return (s) => {
|
|
622
|
-
const need = I32_SIZE * len;
|
|
623
|
-
if (s.isInCurrentBuffer(need)) {
|
|
624
|
-
for (let i = 0; i < len; i++) {
|
|
625
|
-
s.result.push(
|
|
626
|
-
/** @type {Buffer} */ (s.currentBuffer).readInt32LE(
|
|
627
|
-
s.currentPosition
|
|
628
|
-
)
|
|
629
|
-
);
|
|
630
|
-
s.currentPosition += I32_SIZE;
|
|
631
|
-
}
|
|
632
|
-
s.checkOverflow();
|
|
633
|
-
} else {
|
|
634
|
-
const buf = s.read(need);
|
|
635
|
-
for (let i = 0; i < len; i++) {
|
|
636
|
-
s.result.push(buf.readInt32LE(i * I32_SIZE));
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
};
|
|
640
|
-
} else if ((header & NUMBERS_HEADER_MASK) === I8_HEADER) {
|
|
641
|
-
const len = (header & NUMBERS_COUNT_MASK) + 1;
|
|
642
|
-
return (s) => {
|
|
643
|
-
const need = I8_SIZE * len;
|
|
644
|
-
if (s.isInCurrentBuffer(need)) {
|
|
645
|
-
for (let i = 0; i < len; i++) {
|
|
646
|
-
s.result.push(
|
|
647
|
-
/** @type {Buffer} */ (s.currentBuffer).readInt8(
|
|
648
|
-
s.currentPosition
|
|
649
|
-
)
|
|
650
|
-
);
|
|
651
|
-
s.currentPosition += I8_SIZE;
|
|
652
|
-
}
|
|
653
|
-
s.checkOverflow();
|
|
654
|
-
} else {
|
|
655
|
-
const buf = s.read(need);
|
|
656
|
-
for (let i = 0; i < len; i++) {
|
|
657
|
-
s.result.push(buf.readInt8(i * I8_SIZE));
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
};
|
|
239
|
+
/**
|
|
240
|
+
* Reads the content items of a lazy section.
|
|
241
|
+
* @param {ReadState} state read state
|
|
242
|
+
* @returns {SerializedType} content of the lazy value
|
|
243
|
+
*/
|
|
244
|
+
const readLazySection = (state) => {
|
|
245
|
+
const count = state.readU32();
|
|
246
|
+
/** @type {number[]} */
|
|
247
|
+
const sizes = [];
|
|
248
|
+
for (let i = 0; i < count; i++) sizes.push(state.readU32());
|
|
249
|
+
/** @type {SerializedType} */
|
|
250
|
+
const content = [];
|
|
251
|
+
for (let size of sizes) {
|
|
252
|
+
if (size === 0) {
|
|
253
|
+
if (typeof state.currentBuffer !== "function") {
|
|
254
|
+
throw new Error("Unexpected non-lazy element in stream");
|
|
661
255
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
256
|
+
content.push(state.currentBuffer);
|
|
257
|
+
state.nextDataItem();
|
|
258
|
+
} else {
|
|
259
|
+
do {
|
|
260
|
+
const buf = state.readUpTo(size);
|
|
261
|
+
size -= buf.length;
|
|
262
|
+
content.push(state.retainedBuffer(buf));
|
|
263
|
+
} while (size > 0);
|
|
264
|
+
}
|
|
665
265
|
}
|
|
666
|
-
|
|
266
|
+
return content;
|
|
267
|
+
};
|
|
667
268
|
|
|
668
269
|
/**
|
|
669
270
|
* Represents BinaryMiddleware.
|
|
@@ -696,497 +297,209 @@ class BinaryMiddleware extends SerializerMiddleware {
|
|
|
696
297
|
* Returns serialized data.
|
|
697
298
|
* @param {DeserializedType} data data
|
|
698
299
|
* @param {Context} context context object
|
|
699
|
-
* @param {{ leftOverBuffer: Buffer | null, allocationSize: number, increaseCounter: number }} allocationScope allocation scope
|
|
700
300
|
* @returns {SerializedType} serialized data
|
|
701
301
|
*/
|
|
702
|
-
_serialize(
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
let leftOverBuffer = null;
|
|
713
|
-
/** @type {BufferSerializableType[]} */
|
|
714
|
-
let buffers = [];
|
|
715
|
-
/** @type {Buffer | null} */
|
|
716
|
-
let currentBuffer = allocationScope ? allocationScope.leftOverBuffer : null;
|
|
717
|
-
allocationScope.leftOverBuffer = null;
|
|
718
|
-
let currentPosition = 0;
|
|
719
|
-
if (currentBuffer === null) {
|
|
720
|
-
currentBuffer = Buffer.allocUnsafe(allocationScope.allocationSize);
|
|
721
|
-
}
|
|
302
|
+
_serialize(data, context) {
|
|
303
|
+
/** @type {SerializedType} */
|
|
304
|
+
const result = [];
|
|
305
|
+
/** @type {number[]} */
|
|
306
|
+
const measureStack = [];
|
|
307
|
+
let writtenBytes = 0;
|
|
308
|
+
/** Index of the first value of the open section. */
|
|
309
|
+
let sectionStart = 0;
|
|
310
|
+
/** Estimated payload size of the open section. */
|
|
311
|
+
let sectionSize = 0;
|
|
722
312
|
/**
|
|
723
|
-
*
|
|
724
|
-
* @
|
|
313
|
+
* Positions of the buffers of the open section, relative to `data`.
|
|
314
|
+
* @type {number[]}
|
|
725
315
|
*/
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
flush();
|
|
730
|
-
}
|
|
731
|
-
if (leftOverBuffer && leftOverBuffer.length >= bytesNeeded) {
|
|
732
|
-
currentBuffer = leftOverBuffer;
|
|
733
|
-
leftOverBuffer = null;
|
|
734
|
-
} else {
|
|
735
|
-
currentBuffer = Buffer.allocUnsafe(
|
|
736
|
-
Math.max(bytesNeeded, allocationScope.allocationSize)
|
|
737
|
-
);
|
|
738
|
-
if (
|
|
739
|
-
!(allocationScope.increaseCounter =
|
|
740
|
-
(allocationScope.increaseCounter + 1) % 4) &&
|
|
741
|
-
allocationScope.allocationSize < 16777216
|
|
742
|
-
) {
|
|
743
|
-
allocationScope.allocationSize <<= 1;
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
};
|
|
747
|
-
const flush = () => {
|
|
748
|
-
if (currentBuffer !== null) {
|
|
749
|
-
if (currentPosition > 0) {
|
|
750
|
-
buffers.push(
|
|
751
|
-
Buffer.from(
|
|
752
|
-
currentBuffer.buffer,
|
|
753
|
-
currentBuffer.byteOffset,
|
|
754
|
-
currentPosition
|
|
755
|
-
)
|
|
756
|
-
);
|
|
757
|
-
}
|
|
758
|
-
if (
|
|
759
|
-
!leftOverBuffer ||
|
|
760
|
-
leftOverBuffer.length < currentBuffer.length - currentPosition
|
|
761
|
-
) {
|
|
762
|
-
leftOverBuffer = Buffer.from(
|
|
763
|
-
currentBuffer.buffer,
|
|
764
|
-
currentBuffer.byteOffset + currentPosition,
|
|
765
|
-
currentBuffer.byteLength - currentPosition
|
|
766
|
-
);
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
currentBuffer = null;
|
|
770
|
-
currentPosition = 0;
|
|
771
|
-
}
|
|
772
|
-
};
|
|
316
|
+
let bufferIndices = [];
|
|
317
|
+
/** @type {Buffer[]} */
|
|
318
|
+
let buffers = [];
|
|
773
319
|
/**
|
|
774
|
-
*
|
|
775
|
-
* @param {
|
|
320
|
+
* Appends a buffer to the output.
|
|
321
|
+
* @param {Buffer} buffer buffer
|
|
776
322
|
*/
|
|
777
|
-
const
|
|
778
|
-
|
|
779
|
-
|
|
323
|
+
const write = (buffer) => {
|
|
324
|
+
writtenBytes += buffer.length;
|
|
325
|
+
result.push(buffer);
|
|
780
326
|
};
|
|
781
327
|
/**
|
|
782
|
-
*
|
|
783
|
-
* @param {
|
|
328
|
+
* Writes a values section for the given values.
|
|
329
|
+
* @param {DeserializedType} values values without their buffers
|
|
330
|
+
* @param {number[]} indices position of each buffer within `values`
|
|
331
|
+
* @param {Buffer[]} bufferList buffers in the order of `indices`
|
|
784
332
|
*/
|
|
785
|
-
const
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
333
|
+
const writeValuesSection = (values, indices, bufferList) => {
|
|
334
|
+
const payload = v8Serialize(values);
|
|
335
|
+
const header = Buffer.allocUnsafe(
|
|
336
|
+
HEADER_SIZE + I32_SIZE * (2 + indices.length * 2)
|
|
337
|
+
);
|
|
338
|
+
header[0] = VALUES_HEADER;
|
|
339
|
+
header.writeUInt32LE(payload.length, HEADER_SIZE);
|
|
340
|
+
header.writeUInt32LE(indices.length, HEADER_SIZE + I32_SIZE);
|
|
341
|
+
let offset = HEADER_SIZE + I32_SIZE * 2;
|
|
342
|
+
for (let i = 0; i < indices.length; i++) {
|
|
343
|
+
header.writeUInt32LE(indices[i], offset);
|
|
344
|
+
header.writeUInt32LE(bufferList[i].length, offset + I32_SIZE);
|
|
345
|
+
offset += I32_SIZE * 2;
|
|
346
|
+
}
|
|
347
|
+
write(header);
|
|
348
|
+
write(payload);
|
|
349
|
+
for (const buffer of bufferList) {
|
|
350
|
+
if (buffer.length > 0) write(buffer);
|
|
351
|
+
}
|
|
794
352
|
};
|
|
795
353
|
/**
|
|
796
|
-
*
|
|
797
|
-
* @
|
|
354
|
+
* Closes the open values section before the value at `end`.
|
|
355
|
+
* @param {number} end index of the first value not in the section
|
|
798
356
|
*/
|
|
799
|
-
const
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
if (!SerializerMiddleware.isLazy(thing)) {
|
|
813
|
-
throw new Error(`Unexpected function ${thing}`);
|
|
814
|
-
}
|
|
815
|
-
/** @type {SerializedType | LazyFunction<SerializedType, DeserializedType> | undefined} */
|
|
816
|
-
let serializedData =
|
|
817
|
-
SerializerMiddleware.getLazySerializedValue(thing);
|
|
818
|
-
if (serializedData === undefined) {
|
|
819
|
-
if (SerializerMiddleware.isLazy(thing, this)) {
|
|
820
|
-
flush();
|
|
821
|
-
allocationScope.leftOverBuffer = leftOverBuffer;
|
|
822
|
-
const result =
|
|
823
|
-
/** @type {PrimitiveSerializableType[]} */
|
|
824
|
-
(thing());
|
|
825
|
-
const data = this._serialize(result, context, allocationScope);
|
|
826
|
-
leftOverBuffer = allocationScope.leftOverBuffer;
|
|
827
|
-
allocationScope.leftOverBuffer = null;
|
|
828
|
-
SerializerMiddleware.setLazySerializedValue(thing, data);
|
|
829
|
-
serializedData = data;
|
|
830
|
-
} else {
|
|
831
|
-
serializedData = this._serializeLazy(thing, context);
|
|
832
|
-
flush();
|
|
833
|
-
buffers.push(serializedData);
|
|
834
|
-
break;
|
|
357
|
+
const flush = (end) => {
|
|
358
|
+
if (end > sectionStart) {
|
|
359
|
+
if (
|
|
360
|
+
sectionStart === 0 &&
|
|
361
|
+
end === data.length &&
|
|
362
|
+
// a frozen input can't take the placeholders, so it needs the copy
|
|
363
|
+
(bufferIndices.length === 0 || !Object.isFrozen(data))
|
|
364
|
+
) {
|
|
365
|
+
// the section covers all values: swap the buffers out and back in
|
|
366
|
+
// instead of copying the whole array to place the placeholders
|
|
367
|
+
try {
|
|
368
|
+
for (let i = 0; i < bufferIndices.length; i++) {
|
|
369
|
+
data[bufferIndices[i]] = null;
|
|
835
370
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
}
|
|
841
|
-
/** @type {number[]} */
|
|
842
|
-
const lengths = [];
|
|
843
|
-
for (const item of serializedData) {
|
|
844
|
-
/** @type {undefined | number} */
|
|
845
|
-
let last;
|
|
846
|
-
if (typeof item === "function") {
|
|
847
|
-
lengths.push(0);
|
|
848
|
-
} else if (item.length === 0) {
|
|
849
|
-
// ignore
|
|
850
|
-
} else if (
|
|
851
|
-
lengths.length > 0 &&
|
|
852
|
-
(last = lengths[lengths.length - 1]) !== 0
|
|
853
|
-
) {
|
|
854
|
-
const remaining = 0xffffffff - last;
|
|
855
|
-
if (remaining >= item.length) {
|
|
856
|
-
lengths[lengths.length - 1] += item.length;
|
|
857
|
-
} else {
|
|
858
|
-
lengths.push(item.length - remaining);
|
|
859
|
-
lengths[lengths.length - 2] = 0xffffffff;
|
|
860
|
-
}
|
|
861
|
-
} else {
|
|
862
|
-
lengths.push(item.length);
|
|
371
|
+
writeValuesSection(data, bufferIndices, buffers);
|
|
372
|
+
} finally {
|
|
373
|
+
for (let i = 0; i < bufferIndices.length; i++) {
|
|
374
|
+
data[bufferIndices[i]] = buffers[i];
|
|
863
375
|
}
|
|
864
376
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
flush();
|
|
872
|
-
for (const item of serializedData) {
|
|
873
|
-
buffers.push(item);
|
|
377
|
+
} else {
|
|
378
|
+
const values = data.slice(sectionStart, end);
|
|
379
|
+
for (let i = 0; i < bufferIndices.length; i++) {
|
|
380
|
+
const index = bufferIndices[i] - sectionStart;
|
|
381
|
+
bufferIndices[i] = index;
|
|
382
|
+
values[index] = null;
|
|
874
383
|
}
|
|
875
|
-
|
|
384
|
+
writeValuesSection(values, bufferIndices, buffers);
|
|
876
385
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
allocate(len + HEADER_SIZE + I32_SIZE);
|
|
881
|
-
writeU8(STRING_HEADER);
|
|
882
|
-
writeU32(len);
|
|
883
|
-
currentBuffer.write(thing, currentPosition);
|
|
884
|
-
currentPosition += len;
|
|
885
|
-
} else if (len >= 70) {
|
|
886
|
-
allocate(len + HEADER_SIZE);
|
|
887
|
-
writeU8(SHORT_STRING_HEADER | len);
|
|
888
|
-
|
|
889
|
-
currentBuffer.write(thing, currentPosition, "latin1");
|
|
890
|
-
currentPosition += len;
|
|
891
|
-
} else {
|
|
892
|
-
allocate(len + HEADER_SIZE);
|
|
893
|
-
writeU8(SHORT_STRING_HEADER | len);
|
|
894
|
-
|
|
895
|
-
for (let i = 0; i < len; i++) {
|
|
896
|
-
currentBuffer[currentPosition++] = thing.charCodeAt(i);
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
break;
|
|
386
|
+
if (bufferIndices.length > 0) {
|
|
387
|
+
bufferIndices = [];
|
|
388
|
+
buffers = [];
|
|
900
389
|
}
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
writeU8(BIGINT_I8_HEADER | (n - 1));
|
|
916
|
-
while (n > 0) {
|
|
917
|
-
currentBuffer.writeInt8(
|
|
918
|
-
Number(/** @type {bigint} */ (data[i])),
|
|
919
|
-
currentPosition
|
|
920
|
-
);
|
|
921
|
-
currentPosition += I8_SIZE;
|
|
922
|
-
n--;
|
|
923
|
-
i++;
|
|
924
|
-
}
|
|
925
|
-
i--;
|
|
926
|
-
break;
|
|
927
|
-
}
|
|
928
|
-
case 1: {
|
|
929
|
-
let n = 1;
|
|
930
|
-
allocate(HEADER_SIZE + I32_SIZE * n);
|
|
931
|
-
writeU8(BIGINT_I32_HEADER | (n - 1));
|
|
932
|
-
while (n > 0) {
|
|
933
|
-
currentBuffer.writeInt32LE(
|
|
934
|
-
Number(/** @type {bigint} */ (data[i])),
|
|
935
|
-
currentPosition
|
|
936
|
-
);
|
|
937
|
-
currentPosition += I32_SIZE;
|
|
938
|
-
n--;
|
|
939
|
-
i++;
|
|
940
|
-
}
|
|
941
|
-
i--;
|
|
942
|
-
break;
|
|
943
|
-
}
|
|
944
|
-
default: {
|
|
945
|
-
const value = thing.toString();
|
|
946
|
-
const len = Buffer.byteLength(value);
|
|
947
|
-
allocate(len + HEADER_SIZE + I32_SIZE);
|
|
948
|
-
writeU8(BIGINT_HEADER);
|
|
949
|
-
writeU32(len);
|
|
950
|
-
currentBuffer.write(value, currentPosition);
|
|
951
|
-
currentPosition += len;
|
|
952
|
-
break;
|
|
953
|
-
}
|
|
390
|
+
}
|
|
391
|
+
sectionStart = end;
|
|
392
|
+
sectionSize = 0;
|
|
393
|
+
};
|
|
394
|
+
for (let i = 0; i < data.length; i++) {
|
|
395
|
+
const thing = data[i];
|
|
396
|
+
const type = typeof thing;
|
|
397
|
+
if (type === "string") {
|
|
398
|
+
sectionSize += /** @type {string} */ (thing).length;
|
|
399
|
+
} else if (type === "object") {
|
|
400
|
+
// buffers are appended to the section instead of entering the payload
|
|
401
|
+
if (thing !== null) {
|
|
402
|
+
if (!Buffer.isBuffer(thing)) {
|
|
403
|
+
throw new Error(`Unexpected object ${thing} in binary middleware`);
|
|
954
404
|
}
|
|
955
|
-
|
|
405
|
+
bufferIndices.push(i);
|
|
406
|
+
buffers.push(thing);
|
|
407
|
+
// count placeholder + bytes so buffer-heavy runs still split
|
|
408
|
+
sectionSize += ESTIMATED_VALUE_SIZE + thing.length;
|
|
409
|
+
} else {
|
|
410
|
+
sectionSize += ESTIMATED_VALUE_SIZE;
|
|
956
411
|
}
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
writeU8(thing);
|
|
963
|
-
break;
|
|
964
|
-
}
|
|
965
|
-
/**
|
|
966
|
-
* amount of numbers to write
|
|
967
|
-
* @type {number}
|
|
968
|
-
*/
|
|
969
|
-
let n = 1;
|
|
970
|
-
for (; n < 32 && i + n < data.length; n++) {
|
|
971
|
-
const item = data[i + n];
|
|
972
|
-
if (typeof item !== "number") break;
|
|
973
|
-
if (identifyNumber(item) !== type) break;
|
|
974
|
-
}
|
|
975
|
-
switch (type) {
|
|
976
|
-
case 0:
|
|
977
|
-
allocate(HEADER_SIZE + I8_SIZE * n);
|
|
978
|
-
writeU8(I8_HEADER | (n - 1));
|
|
979
|
-
while (n > 0) {
|
|
980
|
-
currentBuffer.writeInt8(
|
|
981
|
-
/** @type {number} */ (data[i]),
|
|
982
|
-
currentPosition
|
|
983
|
-
);
|
|
984
|
-
currentPosition += I8_SIZE;
|
|
985
|
-
n--;
|
|
986
|
-
i++;
|
|
987
|
-
}
|
|
988
|
-
break;
|
|
989
|
-
case 1:
|
|
990
|
-
allocate(HEADER_SIZE + I32_SIZE * n);
|
|
991
|
-
writeU8(I32_HEADER | (n - 1));
|
|
992
|
-
while (n > 0) {
|
|
993
|
-
currentBuffer.writeInt32LE(
|
|
994
|
-
/** @type {number} */ (data[i]),
|
|
995
|
-
currentPosition
|
|
996
|
-
);
|
|
997
|
-
currentPosition += I32_SIZE;
|
|
998
|
-
n--;
|
|
999
|
-
i++;
|
|
1000
|
-
}
|
|
1001
|
-
break;
|
|
1002
|
-
case 2:
|
|
1003
|
-
allocate(HEADER_SIZE + F64_SIZE * n);
|
|
1004
|
-
writeU8(F64_HEADER | (n - 1));
|
|
1005
|
-
while (n > 0) {
|
|
1006
|
-
currentBuffer.writeDoubleLE(
|
|
1007
|
-
/** @type {number} */ (data[i]),
|
|
1008
|
-
currentPosition
|
|
1009
|
-
);
|
|
1010
|
-
currentPosition += F64_SIZE;
|
|
1011
|
-
n--;
|
|
1012
|
-
i++;
|
|
1013
|
-
}
|
|
1014
|
-
break;
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
i--;
|
|
1018
|
-
break;
|
|
412
|
+
} else if (type === "function") {
|
|
413
|
+
flush(i);
|
|
414
|
+
sectionStart = i + 1;
|
|
415
|
+
if (!SerializerMiddleware.isLazy(thing)) {
|
|
416
|
+
throw new Error(`Unexpected function ${thing}`);
|
|
1019
417
|
}
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
if (typeof item !== "boolean") break;
|
|
1030
|
-
const pos = count & 0x7;
|
|
1031
|
-
if (pos === 0) {
|
|
1032
|
-
bytes.push(lastByte);
|
|
1033
|
-
lastByte = item === true ? 1 : 0;
|
|
1034
|
-
} else if (item === true) {
|
|
1035
|
-
lastByte |= 1 << pos;
|
|
1036
|
-
}
|
|
1037
|
-
count++;
|
|
1038
|
-
}
|
|
1039
|
-
i += count - 1;
|
|
1040
|
-
if (count === 1) {
|
|
1041
|
-
allocate(HEADER_SIZE);
|
|
1042
|
-
writeU8(lastByte === 1 ? TRUE_HEADER : FALSE_HEADER);
|
|
1043
|
-
} else if (count === 2) {
|
|
1044
|
-
allocate(HEADER_SIZE * 2);
|
|
1045
|
-
writeU8(lastByte & 1 ? TRUE_HEADER : FALSE_HEADER);
|
|
1046
|
-
writeU8(lastByte & 2 ? TRUE_HEADER : FALSE_HEADER);
|
|
1047
|
-
} else if (count <= 6) {
|
|
1048
|
-
allocate(HEADER_SIZE + I8_SIZE);
|
|
1049
|
-
writeU8(BOOLEANS_HEADER);
|
|
1050
|
-
writeU8((1 << count) | lastByte);
|
|
1051
|
-
} else if (count <= 133) {
|
|
1052
|
-
allocate(HEADER_SIZE + I8_SIZE + I8_SIZE * bytes.length + I8_SIZE);
|
|
1053
|
-
writeU8(BOOLEANS_HEADER);
|
|
1054
|
-
writeU8(0x80 | (count - 7));
|
|
1055
|
-
for (const byte of bytes) writeU8(byte);
|
|
1056
|
-
writeU8(lastByte);
|
|
418
|
+
/** @type {SerializedType | LazyFunction<SerializedType, DeserializedType> | undefined} */
|
|
419
|
+
let serializedData = SerializerMiddleware.getLazySerializedValue(thing);
|
|
420
|
+
if (serializedData === undefined) {
|
|
421
|
+
if (SerializerMiddleware.isLazy(thing, this)) {
|
|
422
|
+
serializedData = this._serialize(
|
|
423
|
+
/** @type {DeserializedType} */ (thing()),
|
|
424
|
+
context
|
|
425
|
+
);
|
|
426
|
+
SerializerMiddleware.setLazySerializedValue(thing, serializedData);
|
|
1057
427
|
} else {
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
428
|
+
result.push(
|
|
429
|
+
this._serializeLazy(
|
|
430
|
+
/** @type {LazyFunction<DeserializedType, SerializedType>} */
|
|
431
|
+
(thing),
|
|
432
|
+
context
|
|
433
|
+
)
|
|
1064
434
|
);
|
|
1065
|
-
|
|
1066
|
-
writeU8(0xff);
|
|
1067
|
-
writeU32(count);
|
|
1068
|
-
for (const byte of bytes) writeU8(byte);
|
|
1069
|
-
writeU8(lastByte);
|
|
435
|
+
continue;
|
|
1070
436
|
}
|
|
1071
|
-
|
|
437
|
+
} else if (typeof serializedData === "function") {
|
|
438
|
+
result.push(serializedData);
|
|
439
|
+
continue;
|
|
1072
440
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
} else if (next === false) {
|
|
1090
|
-
allocate(HEADER_SIZE);
|
|
1091
|
-
writeU8(NULL_AND_FALSE_HEADER);
|
|
1092
|
-
i++;
|
|
1093
|
-
} else if (typeof next === "number") {
|
|
1094
|
-
const type = identifyNumber(next);
|
|
1095
|
-
if (type === 0) {
|
|
1096
|
-
allocate(HEADER_SIZE + I8_SIZE);
|
|
1097
|
-
writeU8(NULL_AND_I8_HEADER);
|
|
1098
|
-
currentBuffer.writeInt8(next, currentPosition);
|
|
1099
|
-
currentPosition += I8_SIZE;
|
|
1100
|
-
i++;
|
|
1101
|
-
} else if (type === 1) {
|
|
1102
|
-
// `null` + i32 is 5 bytes; if the value also fits an
|
|
1103
|
-
// i16, fuse it as 3 bytes instead (helps back-references)
|
|
1104
|
-
if (next >= -32768 && next <= 32767) {
|
|
1105
|
-
allocate(HEADER_SIZE + I16_SIZE);
|
|
1106
|
-
writeU8(NULL_AND_I16_HEADER);
|
|
1107
|
-
currentBuffer.writeInt16LE(next, currentPosition);
|
|
1108
|
-
currentPosition += I16_SIZE;
|
|
1109
|
-
} else {
|
|
1110
|
-
allocate(HEADER_SIZE + I32_SIZE);
|
|
1111
|
-
writeU8(NULL_AND_I32_HEADER);
|
|
1112
|
-
currentBuffer.writeInt32LE(next, currentPosition);
|
|
1113
|
-
currentPosition += I32_SIZE;
|
|
1114
|
-
}
|
|
1115
|
-
i++;
|
|
1116
|
-
} else {
|
|
1117
|
-
allocate(HEADER_SIZE);
|
|
1118
|
-
writeU8(NULL_HEADER);
|
|
1119
|
-
}
|
|
1120
|
-
} else {
|
|
1121
|
-
allocate(HEADER_SIZE);
|
|
1122
|
-
writeU8(NULL_HEADER);
|
|
1123
|
-
}
|
|
1124
|
-
} else {
|
|
1125
|
-
allocate(HEADER_SIZE);
|
|
1126
|
-
writeU8(NULL_HEADER);
|
|
1127
|
-
}
|
|
1128
|
-
} else if (n === 2) {
|
|
1129
|
-
allocate(HEADER_SIZE);
|
|
1130
|
-
writeU8(NULL2_HEADER);
|
|
1131
|
-
} else if (n === 3) {
|
|
1132
|
-
allocate(HEADER_SIZE);
|
|
1133
|
-
writeU8(NULL3_HEADER);
|
|
1134
|
-
} else if (n < 260) {
|
|
1135
|
-
allocate(HEADER_SIZE + I8_SIZE);
|
|
1136
|
-
writeU8(NULLS8_HEADER);
|
|
1137
|
-
writeU8(n - 4);
|
|
1138
|
-
} else {
|
|
1139
|
-
allocate(HEADER_SIZE + I32_SIZE);
|
|
1140
|
-
writeU8(NULLS32_HEADER);
|
|
1141
|
-
writeU32(n - 260);
|
|
1142
|
-
}
|
|
1143
|
-
} else if (Buffer.isBuffer(thing)) {
|
|
1144
|
-
if (thing.length < 8192) {
|
|
1145
|
-
allocate(HEADER_SIZE + I32_SIZE + thing.length);
|
|
1146
|
-
writeU8(BUFFER_HEADER);
|
|
1147
|
-
writeU32(thing.length);
|
|
1148
|
-
thing.copy(currentBuffer, currentPosition);
|
|
1149
|
-
currentPosition += thing.length;
|
|
441
|
+
/** @type {number[]} */
|
|
442
|
+
const sizes = [];
|
|
443
|
+
for (const item of serializedData) {
|
|
444
|
+
/** @type {undefined | number} */
|
|
445
|
+
let last;
|
|
446
|
+
if (typeof item === "function") {
|
|
447
|
+
sizes.push(0);
|
|
448
|
+
} else if (item.length === 0) {
|
|
449
|
+
// ignore
|
|
450
|
+
} else if (
|
|
451
|
+
sizes.length > 0 &&
|
|
452
|
+
(last = sizes[sizes.length - 1]) !== 0
|
|
453
|
+
) {
|
|
454
|
+
const remaining = 0xffffffff - last;
|
|
455
|
+
if (remaining >= item.length) {
|
|
456
|
+
sizes[sizes.length - 1] += item.length;
|
|
1150
457
|
} else {
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
writeU32(thing.length);
|
|
1154
|
-
flush();
|
|
1155
|
-
buffers.push(thing);
|
|
458
|
+
sizes.push(item.length - remaining);
|
|
459
|
+
sizes[sizes.length - 2] = 0xffffffff;
|
|
1156
460
|
}
|
|
461
|
+
} else {
|
|
462
|
+
sizes.push(item.length);
|
|
1157
463
|
}
|
|
1158
|
-
break;
|
|
1159
464
|
}
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
465
|
+
const header = Buffer.allocUnsafe(
|
|
466
|
+
HEADER_SIZE + I32_SIZE * (1 + sizes.length)
|
|
467
|
+
);
|
|
468
|
+
header[0] = LAZY_HEADER;
|
|
469
|
+
header.writeUInt32LE(sizes.length, HEADER_SIZE);
|
|
470
|
+
for (let j = 0; j < sizes.length; j++) {
|
|
471
|
+
header.writeUInt32LE(sizes[j], HEADER_SIZE + I32_SIZE * (1 + j));
|
|
472
|
+
}
|
|
473
|
+
write(header);
|
|
474
|
+
for (const item of serializedData) {
|
|
475
|
+
if (typeof item === "function") {
|
|
476
|
+
result.push(item);
|
|
477
|
+
} else {
|
|
478
|
+
write(item);
|
|
1169
479
|
}
|
|
1170
|
-
break;
|
|
1171
480
|
}
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
481
|
+
continue;
|
|
482
|
+
} else if (type === "symbol") {
|
|
483
|
+
flush(i);
|
|
484
|
+
sectionStart = i + 1;
|
|
485
|
+
const operation =
|
|
486
|
+
/** @type {MEASURE_START_OPERATION_TYPE | MEASURE_END_OPERATION_TYPE} */
|
|
487
|
+
(/** @type {unknown} */ (thing));
|
|
488
|
+
if (operation === MEASURE_START_OPERATION) {
|
|
489
|
+
measureStack.push(writtenBytes);
|
|
490
|
+
} else if (operation === MEASURE_END_OPERATION) {
|
|
491
|
+
const size =
|
|
492
|
+
writtenBytes - /** @type {number} */ (measureStack.pop());
|
|
493
|
+
writeValuesSection([size], [], []);
|
|
1176
494
|
}
|
|
495
|
+
continue;
|
|
496
|
+
} else {
|
|
497
|
+
sectionSize += ESTIMATED_VALUE_SIZE;
|
|
1177
498
|
}
|
|
499
|
+
if (sectionSize >= MAX_SECTION_SIZE) flush(i + 1);
|
|
1178
500
|
}
|
|
1179
|
-
flush();
|
|
1180
|
-
|
|
1181
|
-
allocationScope.leftOverBuffer = leftOverBuffer;
|
|
1182
|
-
|
|
1183
|
-
// avoid leaking memory
|
|
1184
|
-
currentBuffer = null;
|
|
1185
|
-
leftOverBuffer = null;
|
|
1186
|
-
allocationScope = /** @type {EXPECTED_ANY} */ (undefined);
|
|
1187
|
-
const _buffers = buffers;
|
|
1188
|
-
buffers = /** @type {EXPECTED_ANY} */ (undefined);
|
|
1189
|
-
return _buffers;
|
|
501
|
+
flush(data.length);
|
|
502
|
+
return result;
|
|
1190
503
|
}
|
|
1191
504
|
|
|
1192
505
|
/**
|
|
@@ -1200,7 +513,7 @@ class BinaryMiddleware extends SerializerMiddleware {
|
|
|
1200
513
|
}
|
|
1201
514
|
|
|
1202
515
|
/**
|
|
1203
|
-
* Create lazy deserialized.
|
|
516
|
+
* Create lazy deserialized.
|
|
1204
517
|
* @param {SerializedType} content content
|
|
1205
518
|
* @param {Context} context context object
|
|
1206
519
|
* @returns {LazyFunction<DeserializedType, SerializedType>} lazy function
|
|
@@ -1234,16 +547,35 @@ class BinaryMiddleware extends SerializerMiddleware {
|
|
|
1234
547
|
* @returns {DeserializedType} deserialized data
|
|
1235
548
|
*/
|
|
1236
549
|
_deserialize(data, context) {
|
|
1237
|
-
const state = new ReadState(data, context
|
|
550
|
+
const state = new ReadState(data, context);
|
|
551
|
+
/** @type {DeserializedType | undefined} */
|
|
552
|
+
let result;
|
|
1238
553
|
while (state.currentBuffer !== null) {
|
|
554
|
+
/** @type {DeserializedType} */
|
|
555
|
+
let part;
|
|
1239
556
|
if (typeof state.currentBuffer === "function") {
|
|
1240
|
-
|
|
557
|
+
part = [this._deserializeLazy(state.currentBuffer, context)];
|
|
1241
558
|
state.nextDataItem();
|
|
1242
559
|
} else {
|
|
1243
|
-
|
|
560
|
+
const header = state.readU8();
|
|
561
|
+
if (header === VALUES_HEADER) {
|
|
562
|
+
part = readValuesSection(state);
|
|
563
|
+
} else if (header === LAZY_HEADER) {
|
|
564
|
+
part = [
|
|
565
|
+
this._createLazyDeserialized(readLazySection(state), context)
|
|
566
|
+
];
|
|
567
|
+
} else {
|
|
568
|
+
throw new Error(`Unexpected header byte 0x${header.toString(16)}`);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
// a single-section stream needs no copying: reuse its array as the result
|
|
572
|
+
if (result === undefined) {
|
|
573
|
+
result = part;
|
|
574
|
+
} else {
|
|
575
|
+
for (let j = 0; j < part.length; j++) result.push(part[j]);
|
|
1244
576
|
}
|
|
1245
577
|
}
|
|
1246
|
-
return
|
|
578
|
+
return result === undefined ? [] : result;
|
|
1247
579
|
}
|
|
1248
580
|
}
|
|
1249
581
|
|