msgpackr 1.7.0-beta1 → 1.7.1
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/dist/index.js +23 -12
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +54 -54
- package/dist/index.min.js.map +1 -1
- package/dist/node.cjs +78 -40
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +106 -40
- package/dist/test.js.map +1 -1
- package/index.d.ts +62 -14
- package/pack.d.ts +1 -9
- package/pack.js +9 -9
- package/package.json +8 -3
- package/struct.js +55 -28
- package/unpack.d.ts +2 -53
- package/unpack.js +14 -6
package/dist/test.js
CHANGED
|
@@ -179,6 +179,7 @@
|
|
|
179
179
|
let result;
|
|
180
180
|
if (currentUnpackr.randomAccessStructure && src[position] < 0x40 && src[position] >= 0x20 && readStruct) {
|
|
181
181
|
result = readStruct(src, position, srcEnd, currentUnpackr);
|
|
182
|
+
src = null; // dispose of this so that recursive unpack calls don't save state
|
|
182
183
|
if (!(options && options.lazy) && result)
|
|
183
184
|
result = result.toJSON();
|
|
184
185
|
position = srcEnd;
|
|
@@ -189,7 +190,7 @@
|
|
|
189
190
|
|
|
190
191
|
if (position == srcEnd) {
|
|
191
192
|
// finished reading this source, cleanup references
|
|
192
|
-
if (currentStructures.restoreStructures)
|
|
193
|
+
if (currentStructures && currentStructures.restoreStructures)
|
|
193
194
|
restoreStructures();
|
|
194
195
|
currentStructures = null;
|
|
195
196
|
src = null;
|
|
@@ -204,7 +205,7 @@
|
|
|
204
205
|
// else more to read, but we are reading sequentially, so don't clear source yet
|
|
205
206
|
return result
|
|
206
207
|
} catch(error) {
|
|
207
|
-
if (currentStructures
|
|
208
|
+
if (currentStructures && currentStructures.restoreStructures)
|
|
208
209
|
restoreStructures();
|
|
209
210
|
clearSource();
|
|
210
211
|
if (error instanceof RangeError || error.message.startsWith('Unexpected end of buffer') || position > srcEnd) {
|
|
@@ -244,7 +245,10 @@
|
|
|
244
245
|
if (currentUnpackr.mapsAsObjects) {
|
|
245
246
|
let object = {};
|
|
246
247
|
for (let i = 0; i < token; i++) {
|
|
247
|
-
|
|
248
|
+
let key = readKey();
|
|
249
|
+
if (key === '__proto__')
|
|
250
|
+
key = '__proto_';
|
|
251
|
+
object[key] = read();
|
|
248
252
|
}
|
|
249
253
|
return object
|
|
250
254
|
} else {
|
|
@@ -473,7 +477,7 @@
|
|
|
473
477
|
// This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
|
|
474
478
|
if (readObject.count++ > inlineObjectReadThreshold) {
|
|
475
479
|
let readObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
|
476
|
-
'({' + structure.map(key => validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
|
|
480
|
+
'({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
|
|
477
481
|
if (structure.highByte === 0)
|
|
478
482
|
structure.read = createSecondByteReader(firstId, structure.read);
|
|
479
483
|
return readObject() // second byte is already read, if there is one so immediately read object
|
|
@@ -481,6 +485,8 @@
|
|
|
481
485
|
let object = {};
|
|
482
486
|
for (let i = 0, l = structure.length; i < l; i++) {
|
|
483
487
|
let key = structure[i];
|
|
488
|
+
if (key === '__proto__')
|
|
489
|
+
key = '__proto_';
|
|
484
490
|
object[key] = read();
|
|
485
491
|
}
|
|
486
492
|
if (currentUnpackr.freezeData)
|
|
@@ -601,7 +607,10 @@
|
|
|
601
607
|
if (currentUnpackr.mapsAsObjects) {
|
|
602
608
|
let object = {};
|
|
603
609
|
for (let i = 0; i < length; i++) {
|
|
604
|
-
|
|
610
|
+
let key = readKey();
|
|
611
|
+
if (key === '__proto__')
|
|
612
|
+
key = '__proto_';
|
|
613
|
+
object[key] = read();
|
|
605
614
|
}
|
|
606
615
|
return object
|
|
607
616
|
} else {
|
|
@@ -1171,12 +1180,11 @@
|
|
|
1171
1180
|
writeStruct(value);
|
|
1172
1181
|
else
|
|
1173
1182
|
pack(value);
|
|
1174
|
-
if (bundledStrings$1) {
|
|
1175
|
-
writeBundles(start, pack);
|
|
1176
|
-
}
|
|
1177
|
-
packr.offset = position$1; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
|
|
1178
1183
|
if (referenceMap && referenceMap.idsToInsert) {
|
|
1179
|
-
|
|
1184
|
+
let incrementPosition = referenceMap.idsToInsert.length * 6;
|
|
1185
|
+
if (bundledStrings$1)
|
|
1186
|
+
writeBundles(start, pack, incrementPosition);
|
|
1187
|
+
position$1 += incrementPosition;
|
|
1180
1188
|
if (position$1 > safeEnd)
|
|
1181
1189
|
makeRoom(position$1);
|
|
1182
1190
|
packr.offset = position$1;
|
|
@@ -1184,6 +1192,9 @@
|
|
|
1184
1192
|
referenceMap = null;
|
|
1185
1193
|
return serialized
|
|
1186
1194
|
}
|
|
1195
|
+
if (bundledStrings$1)
|
|
1196
|
+
writeBundles(start, pack, 0);
|
|
1197
|
+
packr.offset = position$1; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
|
|
1187
1198
|
if (encodeOptions & REUSE_BUFFER_MODE) {
|
|
1188
1199
|
target.start = start;
|
|
1189
1200
|
target.end = position$1;
|
|
@@ -1962,9 +1973,9 @@
|
|
|
1962
1973
|
return serialized
|
|
1963
1974
|
}
|
|
1964
1975
|
|
|
1965
|
-
function writeBundles(start, pack) {
|
|
1976
|
+
function writeBundles(start, pack, incrementPosition) {
|
|
1966
1977
|
if (bundledStrings$1.length > 0) {
|
|
1967
|
-
targetView.setUint32(bundledStrings$1.position + start, position$1 - bundledStrings$1.position - start);
|
|
1978
|
+
targetView.setUint32(bundledStrings$1.position + start, position$1 + incrementPosition - bundledStrings$1.position - start);
|
|
1968
1979
|
let writeStrings = bundledStrings$1;
|
|
1969
1980
|
bundledStrings$1 = null;
|
|
1970
1981
|
pack(writeStrings[0]);
|
|
@@ -1997,6 +2008,14 @@
|
|
|
1997
2008
|
const TYPE_NAMES = ['num', 'object', 'string', 'ascii'];
|
|
1998
2009
|
TYPE_NAMES[DATE] = 'date';
|
|
1999
2010
|
const float32Headers = [false, true, true, false, false, true, true, false];
|
|
2011
|
+
let evalSupported;
|
|
2012
|
+
try {
|
|
2013
|
+
new Function('');
|
|
2014
|
+
evalSupported = true;
|
|
2015
|
+
} catch(error) {
|
|
2016
|
+
// if eval variants are not supported, do not create inline object readers ever
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2000
2019
|
let updatedPosition;
|
|
2001
2020
|
const hasNodeBuffer$1 = typeof Buffer !== 'undefined';
|
|
2002
2021
|
let textEncoder$1, currentSource;
|
|
@@ -2433,7 +2452,7 @@
|
|
|
2433
2452
|
case 27: recordId = src[position++] + (src[position++] << 8) + (src[position++] << 16) + (src[position++] << 24); break;
|
|
2434
2453
|
}
|
|
2435
2454
|
}
|
|
2436
|
-
let structure = unpackr.typedStructs
|
|
2455
|
+
let structure = unpackr.typedStructs && unpackr.typedStructs[recordId];
|
|
2437
2456
|
if (!structure) {
|
|
2438
2457
|
// copy src buffer because getStructures will override it
|
|
2439
2458
|
src = Uint8Array.prototype.slice.call(src, position, srcEnd);
|
|
@@ -2453,23 +2472,13 @@
|
|
|
2453
2472
|
};
|
|
2454
2473
|
var prototype = construct.prototype;
|
|
2455
2474
|
let properties = [];
|
|
2456
|
-
Object.defineProperty(prototype, 'toJSON', {
|
|
2457
|
-
value() {
|
|
2458
|
-
// return an enumerable object with own properties to JSON stringify
|
|
2459
|
-
let resolved = {};
|
|
2460
|
-
for (let i = 0, l = properties.length; i < l; i++) {
|
|
2461
|
-
let key = properties[i].key;
|
|
2462
|
-
resolved[key] = this[key];
|
|
2463
|
-
}
|
|
2464
|
-
return resolved;
|
|
2465
|
-
},
|
|
2466
|
-
// not enumerable or anything
|
|
2467
|
-
});
|
|
2468
2475
|
let currentOffset = 0;
|
|
2469
2476
|
let lastRefProperty;
|
|
2470
2477
|
for (let i = 0, l = structure.length; i < l; i++) {
|
|
2471
2478
|
let definition = structure[i];
|
|
2472
2479
|
let [ type, size, key, enumerationOffset ] = definition;
|
|
2480
|
+
if (key === '__proto__')
|
|
2481
|
+
key = '__proto_';
|
|
2473
2482
|
let property = {
|
|
2474
2483
|
key,
|
|
2475
2484
|
offset: currentOffset,
|
|
@@ -2513,8 +2522,7 @@
|
|
|
2513
2522
|
lastRefProperty.next = property;
|
|
2514
2523
|
lastRefProperty = property;
|
|
2515
2524
|
property.multiGetCount = 0;
|
|
2516
|
-
get = function() {
|
|
2517
|
-
let source = this[sourceSymbol];
|
|
2525
|
+
get = function(source) {
|
|
2518
2526
|
let src = source.bytes;
|
|
2519
2527
|
let position = source.position;
|
|
2520
2528
|
let refStart = currentOffset + position;
|
|
@@ -2565,8 +2573,7 @@
|
|
|
2565
2573
|
if (lastRefProperty && !lastRefProperty.next)
|
|
2566
2574
|
lastRefProperty.next = property;
|
|
2567
2575
|
lastRefProperty = property;
|
|
2568
|
-
get = function() {
|
|
2569
|
-
let source = this[sourceSymbol];
|
|
2576
|
+
get = function(source) {
|
|
2570
2577
|
let position = source.position;
|
|
2571
2578
|
let refStart = currentOffset + position;
|
|
2572
2579
|
let ref = getRef(source, position);
|
|
@@ -2598,8 +2605,7 @@
|
|
|
2598
2605
|
case NUMBER:
|
|
2599
2606
|
switch(size) {
|
|
2600
2607
|
case 4:
|
|
2601
|
-
get = function () {
|
|
2602
|
-
let source = this[sourceSymbol];
|
|
2608
|
+
get = function (source) {
|
|
2603
2609
|
let src = source.bytes;
|
|
2604
2610
|
let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
|
|
2605
2611
|
let position = source.position + property.offset;
|
|
@@ -2617,8 +2623,7 @@
|
|
|
2617
2623
|
};
|
|
2618
2624
|
break;
|
|
2619
2625
|
case 8:
|
|
2620
|
-
get = function () {
|
|
2621
|
-
let source = this[sourceSymbol];
|
|
2626
|
+
get = function (source) {
|
|
2622
2627
|
let src = source.bytes;
|
|
2623
2628
|
let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
|
|
2624
2629
|
let value = dataView.getFloat64(source.position + property.offset, true);
|
|
@@ -2631,8 +2636,7 @@
|
|
|
2631
2636
|
};
|
|
2632
2637
|
break;
|
|
2633
2638
|
case 1:
|
|
2634
|
-
get = function () {
|
|
2635
|
-
let source = this[sourceSymbol];
|
|
2639
|
+
get = function (source) {
|
|
2636
2640
|
let src = source.bytes;
|
|
2637
2641
|
let value = src[source.position + property.offset];
|
|
2638
2642
|
return value < 0xf6 ? value : toConstant(value);
|
|
@@ -2641,8 +2645,7 @@
|
|
|
2641
2645
|
}
|
|
2642
2646
|
break;
|
|
2643
2647
|
case DATE:
|
|
2644
|
-
get = function () {
|
|
2645
|
-
let source = this[sourceSymbol];
|
|
2648
|
+
get = function (source) {
|
|
2646
2649
|
let src = source.bytes;
|
|
2647
2650
|
let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
|
|
2648
2651
|
return new Date(dataView.getFloat64(source.position + property.offset, true));
|
|
@@ -2652,8 +2655,38 @@
|
|
|
2652
2655
|
}
|
|
2653
2656
|
property.get = get;
|
|
2654
2657
|
}
|
|
2655
|
-
|
|
2656
|
-
|
|
2658
|
+
// TODO: load the srcString for faster string decoding on toJSON
|
|
2659
|
+
if (evalSupported) {
|
|
2660
|
+
let objectLiteralProperties = [];
|
|
2661
|
+
let args = [];
|
|
2662
|
+
let i = 0;
|
|
2663
|
+
for (let property of properties) { // assign in enumeration order
|
|
2664
|
+
Object.defineProperty(prototype, property.key, { get: withSource(property.get), enumerable: true });
|
|
2665
|
+
let valueFunction = 'v' + i++;
|
|
2666
|
+
args.push(valueFunction);
|
|
2667
|
+
objectLiteralProperties.push('[' + JSON.stringify(property.key) + ']:' + valueFunction + '(s)');
|
|
2668
|
+
}
|
|
2669
|
+
let toObject = (new Function(...args, 'return function(s){return{' + objectLiteralProperties.join(',') + '}}')).apply(null, properties.map(prop => prop.get));
|
|
2670
|
+
Object.defineProperty(prototype, 'toJSON', {
|
|
2671
|
+
value() {
|
|
2672
|
+
return toObject(this[sourceSymbol]);
|
|
2673
|
+
}
|
|
2674
|
+
});
|
|
2675
|
+
} else {
|
|
2676
|
+
Object.defineProperty(prototype, 'toJSON', {
|
|
2677
|
+
value() {
|
|
2678
|
+
// return an enumerable object with own properties to JSON stringify
|
|
2679
|
+
let resolved = {};
|
|
2680
|
+
for (let i = 0, l = properties.length; i < l; i++) {
|
|
2681
|
+
let key = properties[i].key;
|
|
2682
|
+
|
|
2683
|
+
resolved[key] = this[key];
|
|
2684
|
+
}
|
|
2685
|
+
return resolved;
|
|
2686
|
+
},
|
|
2687
|
+
// not enumerable or anything
|
|
2688
|
+
});
|
|
2689
|
+
}
|
|
2657
2690
|
}
|
|
2658
2691
|
var instance = new construct();
|
|
2659
2692
|
instance[sourceSymbol] = {
|
|
@@ -2673,6 +2706,11 @@
|
|
|
2673
2706
|
}
|
|
2674
2707
|
throw new Error('Unknown constant');
|
|
2675
2708
|
}
|
|
2709
|
+
function withSource(get) {
|
|
2710
|
+
return function() {
|
|
2711
|
+
return get(this[sourceSymbol]);
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2676
2714
|
|
|
2677
2715
|
function saveState$1() {
|
|
2678
2716
|
if (currentSource) {
|
|
@@ -2706,7 +2744,7 @@
|
|
|
2706
2744
|
packr._mergeStructures(existing);
|
|
2707
2745
|
return compatible;
|
|
2708
2746
|
};
|
|
2709
|
-
packr.lastTypedStructuresLength = packr.typedStructs
|
|
2747
|
+
packr.lastTypedStructuresLength = packr.typedStructs && packr.typedStructs.length;
|
|
2710
2748
|
return structures;
|
|
2711
2749
|
}
|
|
2712
2750
|
|
|
@@ -3045,6 +3083,17 @@
|
|
|
3045
3083
|
assert.deepEqual(data, deserialized);
|
|
3046
3084
|
assert.equal(deserialized.extendedInstance.getDouble(), 8);
|
|
3047
3085
|
});
|
|
3086
|
+
test('proto handling', function() {
|
|
3087
|
+
var objectWithProto = JSON.parse('{"__proto__":{"foo":3}}');
|
|
3088
|
+
var decoded = unpack(pack(objectWithProto));
|
|
3089
|
+
assert(!decoded.foo);
|
|
3090
|
+
var objectsWithProto = [objectWithProto, objectWithProto, objectWithProto, objectWithProto, objectWithProto, objectWithProto];
|
|
3091
|
+
let packr = new Packr$1();
|
|
3092
|
+
var decoded = packr.unpack(packr.pack(objectsWithProto));
|
|
3093
|
+
for (let object of decoded) {
|
|
3094
|
+
assert(!decoded.foo);
|
|
3095
|
+
}
|
|
3096
|
+
});
|
|
3048
3097
|
|
|
3049
3098
|
test.skip('text decoder', function() {
|
|
3050
3099
|
let td = new TextDecoder('ISO-8859-15');
|
|
@@ -3113,6 +3162,23 @@
|
|
|
3113
3162
|
assert.equal(deserialized.uint16Array[1], 4);
|
|
3114
3163
|
});
|
|
3115
3164
|
|
|
3165
|
+
test('structured clone with bundled strings', function() {
|
|
3166
|
+
const packer = new Packr$1({
|
|
3167
|
+
structuredClone: true, // both options must be enabled
|
|
3168
|
+
bundleStrings: true,
|
|
3169
|
+
});
|
|
3170
|
+
|
|
3171
|
+
const v = {};
|
|
3172
|
+
|
|
3173
|
+
const shared = {
|
|
3174
|
+
name1: v,
|
|
3175
|
+
name2: v, // one key has to be named `data`
|
|
3176
|
+
};
|
|
3177
|
+
|
|
3178
|
+
let deserialized = packer.unpack(packer.pack(shared));
|
|
3179
|
+
assert.equal(deserialized.name1, deserialized.name2);
|
|
3180
|
+
});
|
|
3181
|
+
|
|
3116
3182
|
test('object without prototype', function(){
|
|
3117
3183
|
var data = Object.create(null);
|
|
3118
3184
|
data.test = 3;
|