msgpackr 1.7.0-alpha7 → 1.7.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 +1 -1
- package/dist/index.js +23 -5
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +53 -53
- package/dist/index.min.js.map +1 -1
- package/dist/node.cjs +93 -49
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +104 -49
- package/dist/test.js.map +1 -1
- package/index.d.ts +62 -14
- package/pack.d.ts +1 -9
- package/pack.js +0 -1
- package/package.json +8 -3
- package/struct.js +70 -44
- package/unpack.d.ts +2 -53
- package/unpack.js +23 -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
|
|
193
|
+
if (currentStructures?.restoreStructures)
|
|
193
194
|
restoreStructures();
|
|
194
195
|
currentStructures = null;
|
|
195
196
|
src = null;
|
|
@@ -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 {
|
|
@@ -886,7 +895,16 @@
|
|
|
886
895
|
|
|
887
896
|
// the registration of the record definition extension (as "r")
|
|
888
897
|
const recordDefinition = (id, highByte) => {
|
|
889
|
-
|
|
898
|
+
let structure;
|
|
899
|
+
if (currentUnpackr.freezeData) {
|
|
900
|
+
currentUnpackr.freezeData = false;
|
|
901
|
+
try {
|
|
902
|
+
structure = read();
|
|
903
|
+
} finally {
|
|
904
|
+
currentUnpackr.freezeData = true;
|
|
905
|
+
}
|
|
906
|
+
} else
|
|
907
|
+
structure = read();
|
|
890
908
|
let firstByte = id;
|
|
891
909
|
if (highByte !== undefined) {
|
|
892
910
|
id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id);
|
|
@@ -1988,6 +2006,14 @@
|
|
|
1988
2006
|
const TYPE_NAMES = ['num', 'object', 'string', 'ascii'];
|
|
1989
2007
|
TYPE_NAMES[DATE] = 'date';
|
|
1990
2008
|
const float32Headers = [false, true, true, false, false, true, true, false];
|
|
2009
|
+
let evalSupported;
|
|
2010
|
+
try {
|
|
2011
|
+
new Function('');
|
|
2012
|
+
evalSupported = true;
|
|
2013
|
+
} catch(error) {
|
|
2014
|
+
// if eval variants are not supported, do not create inline object readers ever
|
|
2015
|
+
}
|
|
2016
|
+
|
|
1991
2017
|
let updatedPosition;
|
|
1992
2018
|
const hasNodeBuffer$1 = typeof Buffer !== 'undefined';
|
|
1993
2019
|
let textEncoder$1, currentSource;
|
|
@@ -2412,9 +2438,8 @@
|
|
|
2412
2438
|
this.lastTypedStructuresLength = typed.length;
|
|
2413
2439
|
return named;
|
|
2414
2440
|
}
|
|
2415
|
-
var sourceSymbol = Symbol('source');
|
|
2441
|
+
var sourceSymbol = Symbol.for('source');
|
|
2416
2442
|
function readStruct$1(src, position, srcEnd, unpackr) {
|
|
2417
|
-
// var stringLength = (src[position++] << 8) | src[position++];
|
|
2418
2443
|
let recordId = src[position++] - 0x20;
|
|
2419
2444
|
if (recordId >= 24) {
|
|
2420
2445
|
switch(recordId) {
|
|
@@ -2445,23 +2470,13 @@
|
|
|
2445
2470
|
};
|
|
2446
2471
|
var prototype = construct.prototype;
|
|
2447
2472
|
let properties = [];
|
|
2448
|
-
Object.defineProperty(prototype, 'toJSON', {
|
|
2449
|
-
value() {
|
|
2450
|
-
// return an enumerable object with own properties to JSON stringify
|
|
2451
|
-
let resolved = {};
|
|
2452
|
-
for (let i = 0, l = properties.length; i < l; i++) {
|
|
2453
|
-
let key = properties[i].key;
|
|
2454
|
-
resolved[key] = this[key];
|
|
2455
|
-
}
|
|
2456
|
-
return resolved;
|
|
2457
|
-
},
|
|
2458
|
-
// not enumerable or anything
|
|
2459
|
-
});
|
|
2460
2473
|
let currentOffset = 0;
|
|
2461
2474
|
let lastRefProperty;
|
|
2462
2475
|
for (let i = 0, l = structure.length; i < l; i++) {
|
|
2463
2476
|
let definition = structure[i];
|
|
2464
2477
|
let [ type, size, key, enumerationOffset ] = definition;
|
|
2478
|
+
if (key === '__proto__')
|
|
2479
|
+
key = '__proto_';
|
|
2465
2480
|
let property = {
|
|
2466
2481
|
key,
|
|
2467
2482
|
offset: currentOffset,
|
|
@@ -2475,13 +2490,13 @@
|
|
|
2475
2490
|
case 0: getRef = () => 0; break;
|
|
2476
2491
|
case 1:
|
|
2477
2492
|
getRef = (source, position) => {
|
|
2478
|
-
let ref = source.
|
|
2493
|
+
let ref = source.bytes[position + property.offset];
|
|
2479
2494
|
return ref >= 0xf6 ? toConstant(ref) : ref;
|
|
2480
2495
|
};
|
|
2481
2496
|
break;
|
|
2482
2497
|
case 2:
|
|
2483
2498
|
getRef = (source, position) => {
|
|
2484
|
-
let src = source.
|
|
2499
|
+
let src = source.bytes;
|
|
2485
2500
|
let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
|
|
2486
2501
|
let ref = dataView.getUint16(position + property.offset, true);
|
|
2487
2502
|
return ref >= 0xff00 ? toConstant(ref & 0xff) : ref;
|
|
@@ -2489,7 +2504,7 @@
|
|
|
2489
2504
|
break;
|
|
2490
2505
|
case 4:
|
|
2491
2506
|
getRef = (source, position) => {
|
|
2492
|
-
let src = source.
|
|
2507
|
+
let src = source.bytes;
|
|
2493
2508
|
let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
|
|
2494
2509
|
let ref = dataView.getUint32(position + property.offset, true);
|
|
2495
2510
|
return ref >= 0xffffff00 ? toConstant(ref & 0xff) : ref;
|
|
@@ -2505,9 +2520,8 @@
|
|
|
2505
2520
|
lastRefProperty.next = property;
|
|
2506
2521
|
lastRefProperty = property;
|
|
2507
2522
|
property.multiGetCount = 0;
|
|
2508
|
-
get = function() {
|
|
2509
|
-
let
|
|
2510
|
-
let src = source.src;
|
|
2523
|
+
get = function(source) {
|
|
2524
|
+
let src = source.bytes;
|
|
2511
2525
|
let position = source.position;
|
|
2512
2526
|
let refStart = currentOffset + position;
|
|
2513
2527
|
let ref = getRef(source, position);
|
|
@@ -2523,7 +2537,7 @@
|
|
|
2523
2537
|
next = next.next;
|
|
2524
2538
|
}
|
|
2525
2539
|
if (end == null)
|
|
2526
|
-
end = source.
|
|
2540
|
+
end = source.bytesEnd - refStart;
|
|
2527
2541
|
if (source.srcString) {
|
|
2528
2542
|
return source.srcString.slice(ref, end);
|
|
2529
2543
|
}
|
|
@@ -2539,7 +2553,7 @@
|
|
|
2539
2553
|
asciiEnd = null;
|
|
2540
2554
|
} while((next = next.next));
|
|
2541
2555
|
if (asciiEnd == null)
|
|
2542
|
-
asciiEnd = source.
|
|
2556
|
+
asciiEnd = source.bytesEnd - refStart
|
|
2543
2557
|
source.srcString = src.toString('latin1', refStart, refStart + asciiEnd);
|
|
2544
2558
|
return source.srcString.slice(ref, end);
|
|
2545
2559
|
}
|
|
@@ -2557,13 +2571,12 @@
|
|
|
2557
2571
|
if (lastRefProperty && !lastRefProperty.next)
|
|
2558
2572
|
lastRefProperty.next = property;
|
|
2559
2573
|
lastRefProperty = property;
|
|
2560
|
-
get = function() {
|
|
2561
|
-
let source = this[sourceSymbol];
|
|
2574
|
+
get = function(source) {
|
|
2562
2575
|
let position = source.position;
|
|
2563
2576
|
let refStart = currentOffset + position;
|
|
2564
2577
|
let ref = getRef(source, position);
|
|
2565
2578
|
if (typeof ref !== 'number') return ref;
|
|
2566
|
-
let src = source.
|
|
2579
|
+
let src = source.bytes;
|
|
2567
2580
|
let end, next = property.next;
|
|
2568
2581
|
while(next) {
|
|
2569
2582
|
end = next.getRef(source, position);
|
|
@@ -2574,7 +2587,7 @@
|
|
|
2574
2587
|
next = next.next;
|
|
2575
2588
|
}
|
|
2576
2589
|
if (end == null)
|
|
2577
|
-
end = source.
|
|
2590
|
+
end = source.bytesEnd - refStart;
|
|
2578
2591
|
if (type === UTF8) {
|
|
2579
2592
|
return src.toString('utf8', ref + refStart, end + refStart);
|
|
2580
2593
|
} else {
|
|
@@ -2590,9 +2603,8 @@
|
|
|
2590
2603
|
case NUMBER:
|
|
2591
2604
|
switch(size) {
|
|
2592
2605
|
case 4:
|
|
2593
|
-
get = function () {
|
|
2594
|
-
let
|
|
2595
|
-
let src = source.src;
|
|
2606
|
+
get = function (source) {
|
|
2607
|
+
let src = source.bytes;
|
|
2596
2608
|
let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
|
|
2597
2609
|
let position = source.position + property.offset;
|
|
2598
2610
|
let value = dataView.getInt32(position, true);
|
|
@@ -2609,9 +2621,8 @@
|
|
|
2609
2621
|
};
|
|
2610
2622
|
break;
|
|
2611
2623
|
case 8:
|
|
2612
|
-
get = function () {
|
|
2613
|
-
let
|
|
2614
|
-
let src = source.src;
|
|
2624
|
+
get = function (source) {
|
|
2625
|
+
let src = source.bytes;
|
|
2615
2626
|
let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
|
|
2616
2627
|
let value = dataView.getFloat64(source.position + property.offset, true);
|
|
2617
2628
|
if (isNaN(value)) {
|
|
@@ -2623,9 +2634,8 @@
|
|
|
2623
2634
|
};
|
|
2624
2635
|
break;
|
|
2625
2636
|
case 1:
|
|
2626
|
-
get = function () {
|
|
2627
|
-
let
|
|
2628
|
-
let src = source.src;
|
|
2637
|
+
get = function (source) {
|
|
2638
|
+
let src = source.bytes;
|
|
2629
2639
|
let value = src[source.position + property.offset];
|
|
2630
2640
|
return value < 0xf6 ? value : toConstant(value);
|
|
2631
2641
|
};
|
|
@@ -2633,9 +2643,8 @@
|
|
|
2633
2643
|
}
|
|
2634
2644
|
break;
|
|
2635
2645
|
case DATE:
|
|
2636
|
-
get = function () {
|
|
2637
|
-
let
|
|
2638
|
-
let src = source.src;
|
|
2646
|
+
get = function (source) {
|
|
2647
|
+
let src = source.bytes;
|
|
2639
2648
|
let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
|
|
2640
2649
|
return new Date(dataView.getFloat64(source.position + property.offset, true));
|
|
2641
2650
|
};
|
|
@@ -2644,15 +2653,45 @@
|
|
|
2644
2653
|
}
|
|
2645
2654
|
property.get = get;
|
|
2646
2655
|
}
|
|
2647
|
-
|
|
2648
|
-
|
|
2656
|
+
// TODO: load the srcString for faster string decoding on toJSON
|
|
2657
|
+
if (evalSupported) {
|
|
2658
|
+
let objectLiteralProperties = [];
|
|
2659
|
+
let args = [];
|
|
2660
|
+
let i = 0;
|
|
2661
|
+
for (let property of properties) { // assign in enumeration order
|
|
2662
|
+
Object.defineProperty(prototype, property.key, { get: withSource(property.get), enumerable: true });
|
|
2663
|
+
let valueFunction = 'v' + i++;
|
|
2664
|
+
args.push(valueFunction);
|
|
2665
|
+
objectLiteralProperties.push('[' + JSON.stringify(property.key) + ']:' + valueFunction + '(s)');
|
|
2666
|
+
}
|
|
2667
|
+
let toObject = (new Function(...args, 'return function(s){return{' + objectLiteralProperties.join(',') + '}}')).apply(null, properties.map(prop => prop.get));
|
|
2668
|
+
Object.defineProperty(prototype, 'toJSON', {
|
|
2669
|
+
value() {
|
|
2670
|
+
return toObject(this[sourceSymbol]);
|
|
2671
|
+
}
|
|
2672
|
+
});
|
|
2673
|
+
} else {
|
|
2674
|
+
Object.defineProperty(prototype, 'toJSON', {
|
|
2675
|
+
value() {
|
|
2676
|
+
// return an enumerable object with own properties to JSON stringify
|
|
2677
|
+
let resolved = {};
|
|
2678
|
+
for (let i = 0, l = properties.length; i < l; i++) {
|
|
2679
|
+
let key = properties[i].key;
|
|
2680
|
+
|
|
2681
|
+
resolved[key] = this[key];
|
|
2682
|
+
}
|
|
2683
|
+
return resolved;
|
|
2684
|
+
},
|
|
2685
|
+
// not enumerable or anything
|
|
2686
|
+
});
|
|
2687
|
+
}
|
|
2649
2688
|
}
|
|
2650
2689
|
var instance = new construct();
|
|
2651
2690
|
instance[sourceSymbol] = {
|
|
2652
|
-
src,
|
|
2691
|
+
bytes: src,
|
|
2653
2692
|
position,
|
|
2654
2693
|
srcString: '',
|
|
2655
|
-
srcEnd
|
|
2694
|
+
bytesEnd: srcEnd
|
|
2656
2695
|
};
|
|
2657
2696
|
return instance;
|
|
2658
2697
|
}
|
|
@@ -2665,12 +2704,17 @@
|
|
|
2665
2704
|
}
|
|
2666
2705
|
throw new Error('Unknown constant');
|
|
2667
2706
|
}
|
|
2707
|
+
function withSource(get) {
|
|
2708
|
+
return function() {
|
|
2709
|
+
return get(this[sourceSymbol]);
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2668
2712
|
|
|
2669
2713
|
function saveState$1() {
|
|
2670
2714
|
if (currentSource) {
|
|
2671
|
-
currentSource.
|
|
2715
|
+
currentSource.bytes = Uint8Array.prototype.slice.call(currentSource.bytes, currentSource.position, currentSource.bytesEnd);
|
|
2672
2716
|
currentSource.position = 0;
|
|
2673
|
-
currentSource.
|
|
2717
|
+
currentSource.bytesEnd = currentSource.bytes.length;
|
|
2674
2718
|
}
|
|
2675
2719
|
}
|
|
2676
2720
|
function prepareStructures$1(structures, packr) {
|
|
@@ -3037,6 +3081,17 @@
|
|
|
3037
3081
|
assert.deepEqual(data, deserialized);
|
|
3038
3082
|
assert.equal(deserialized.extendedInstance.getDouble(), 8);
|
|
3039
3083
|
});
|
|
3084
|
+
test('proto handling', function() {
|
|
3085
|
+
var objectWithProto = JSON.parse('{"__proto__":{"foo":3}}');
|
|
3086
|
+
var decoded = unpack(pack(objectWithProto));
|
|
3087
|
+
assert(!decoded.foo);
|
|
3088
|
+
var objectsWithProto = [objectWithProto, objectWithProto, objectWithProto, objectWithProto, objectWithProto, objectWithProto];
|
|
3089
|
+
let packr = new Packr$1();
|
|
3090
|
+
var decoded = packr.unpack(packr.pack(objectsWithProto));
|
|
3091
|
+
for (let object of decoded) {
|
|
3092
|
+
assert(!decoded.foo);
|
|
3093
|
+
}
|
|
3094
|
+
});
|
|
3040
3095
|
|
|
3041
3096
|
test.skip('text decoder', function() {
|
|
3042
3097
|
let td = new TextDecoder('ISO-8859-15');
|