feat(planning): grille hebdomadaire complète avec API et filtres
- Connexion API via proxy Angular (résolution CORS, base path /api) - Import CSS ng-zorro global pour les modales et composants - Filtres Camion/Show câblés sur l'affichage de la grille - Camions affichés via TrucksService (linkés au show du même créneau) - Panneau de détails : spectacles + camions du jour sélectionné - Modale de création de spectacle stylisée avec fond et centrage - Positionnement précis des events à la minute dans leur créneau - Auto-scroll vers l'heure courante au chargement - Ligne "maintenant" sur la colonne du jour actuel - Régénération des services OpenAPI (nouveaux noms de types) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+3
-1
@@ -7,6 +7,8 @@
|
||||
[](README.md)
|
||||
[](LICENSE)
|
||||
|
||||
<img align="right" src="./assets/performance.png" width="380"/>
|
||||
|
||||
The msgpackr package is an extremely fast MessagePack NodeJS/JavaScript implementation. Currently, it is significantly faster than any other known implementations, faster than Avro (for JS), and generally faster than native V8 JSON.stringify/parse, on NodeJS. It also includes an optional record extension (the `r` in msgpackr), for defining record structures that makes MessagePack even faster and more compact, often over twice as fast as even native JSON functions, several times faster than other JS implementations, and 15-50% more compact. See the performance section for more details. Structured cloning (with support for cyclical references) is also supported through optional extensions.
|
||||
|
||||
## Basic Usage
|
||||
@@ -102,7 +104,7 @@ packr.pack(bigDataWithLotsOfObjects);
|
||||
|
||||
Another way to further leverage the benefits of the msgpackr record structures is to use streams that naturally allow for data to reuse based on previous record structures. The stream classes have the record structure extension enabled by default and provide excellent out-of-the-box performance.
|
||||
|
||||
When creating a new `Packr`, `Unpackr`, `PackrStream`, or `UnpackrStream` instance, we can enable or disable the record structure extension with the `useRecords` property. When this is `false`, the record structure extension will be disabled (standard/compatibility mode), and all objects will revert to being serialized using MessagePack `map`s, and all `map`s will be deserialized to JS `Object`s as properties (like the standalone `pack` and `unpack` functions).
|
||||
When creating a new `Packr`, `Unpackr`, `PackrStream`, or `UnpackrStream` instance, we can enable or disable the record structure extension with the `useRecords` property. When this is `false`, the record structure extension will be disabled (standard/compatibility mode), and all objects will revert to being serialized using MessageMap `map`s, and all `map`s will be deserialized to JS `Object`s as properties (like the standalone `pack` and `unpack` functions).
|
||||
|
||||
Streaming with record structures works by encoding a structure the first time it is seen in a stream and referencing the structure in later messages that are sent across that stream. When an encoder can expect a decoder to understand previous structure references, this can be configured using the `sequential: true` flag, which is auto-enabled by streams, but can also be used with Packr instances.
|
||||
|
||||
|
||||
+16
-26
@@ -1,34 +1,24 @@
|
||||
Here are more comprehensive benchmarks. This is comparison with the next fastest JS projects using the benchmark tool from `msgpack-lite` (and data is from some clinical research data we use that has a good mix of different value types and structures). It also includes comparison to V8 native JSON functionality, and JavaScript Avro (`avsc`, a very optimized Avro implementation):
|
||||
|
||||
---------------------------------------------------------- | ------: | ----: | -----: | -----:
|
||||
msgpackr w/ shared structures: packr.pack(obj); | 254700 | 5001 | 50929
|
||||
msgpackr w/ shared structures: packr.unpack(buf); | 711700 | 5000 | 142340
|
||||
require("msgpackr").pack(obj); | 234000 | 5000 | 46800
|
||||
require("msgpackr").unpack(buf); | 186500 | 5000 | 37300
|
||||
buf = Buffer(JSON.stringify(obj)); | 297900 | 5000 | 59580
|
||||
obj = JSON.parse(buf); | 216600 | 5001 | 43311
|
||||
buf = require("msgpack-lite").encode(obj); | 114000 | 5001 | 22795
|
||||
obj = require("msgpack-lite").decode(buf); | 40700 | 5006 | 8130
|
||||
buf = require("@msgpack/msgpack").encode(obj); | 166100 | 5000 | 33220
|
||||
obj = require("@msgpack/msgpack").decode(buf); | 136500 | 5002 | 27289
|
||||
buf = require("msgpack-js-v5").encode(obj); | 41600 | 5000 | 8320
|
||||
obj = require("msgpack-js-v5").decode(buf); | 70200 | 5004 | 14028
|
||||
buf = require("msgpack-js").encode(obj); | 40400 | 5012 | 8060
|
||||
obj = require("msgpack-js").decode(buf); | 67100 | 5002 | 13414
|
||||
buf = require("msgpack5")().encode(obj); | 15800 | 5024 | 3144
|
||||
obj = require("msgpack5")().decode(buf); | 30600 | 5004 | 6115
|
||||
buf = require("notepack").encode(obj); | 125100 | 5002 | 25009
|
||||
obj = require("notepack").decode(buf); | 98600 | 5004 | 19704
|
||||
require("what-the-pack")... encoder.encode(obj); | 150300 | 5001 | 30053
|
||||
require("what-the-pack")... encoder.decode(buf); | 100100 | 5000 | 20020
|
||||
obj = require("msgpack-unpack").decode(buf); | 14900 | 5031 | 2961
|
||||
require("avsc")...make schema/type...type.toBuffer(obj); | 266600 | 5000 | 53320
|
||||
require("avsc")...make schema/type...type.fromBuffer(obj); | 370200 | 5000 | 74040
|
||||
operation | op | ms | op/s
|
||||
---------------------------------------------------------- | ------: | ----: | -----:
|
||||
buf = Buffer(JSON.stringify(obj)); | 82000 | 5004 | 16386
|
||||
obj = JSON.parse(buf); | 88600 | 5000 | 17720
|
||||
require("msgpackr").pack(obj); | 161500 | 5002 | 32287
|
||||
require("msgpackr").unpack(buf); | 94600 | 5004 | 18904
|
||||
msgpackr w/ shared structures: packr.pack(obj); | 178400 | 5002 | 35665
|
||||
msgpackr w/ shared structures: packr.unpack(buf); | 376700 | 5000 | 75340
|
||||
buf = require("msgpack-lite").encode(obj); | 30100 | 5012 | 6005
|
||||
obj = require("msgpack-lite").decode(buf); | 16200 | 5001 | 3239
|
||||
buf = require("notepack").encode(obj); | 62600 | 5005 | 12507
|
||||
obj = require("notepack").decode(buf); | 32400 | 5007 | 6470
|
||||
require("what-the-pack")... encoder.encode(obj); | 63500 | 5002 | 12694
|
||||
require("what-the-pack")... encoder.decode(buf); | 32000 | 5001 | 6398
|
||||
require("avsc")...make schema/type...type.toBuffer(obj); | 84600 | 5003 | 16909
|
||||
require("avsc")...make schema/type...type.toBuffer(obj); | 99300 | 5001 | 19856
|
||||
|
||||
(`avsc` is schema-based and more comparable in style to msgpackr with shared structures).
|
||||
|
||||
(note that benchmarks below are several years old)
|
||||
|
||||
Here is a benchmark of streaming data (again borrowed from `msgpack-lite`'s benchmarking), where msgpackr is able to take advantage of the structured record extension and really pull away from other tools:
|
||||
|
||||
operation (1000000 x 2) | op | ms | op/s
|
||||
|
||||
+19
-42
@@ -31,6 +31,13 @@
|
||||
var inlineObjectReadThreshold = 2;
|
||||
var readStruct;
|
||||
var BlockedFunction; // we use search and replace to change the next call to BlockedFunction to avoid CSP issues for
|
||||
// no-eval build
|
||||
try {
|
||||
new BlockedFunction ('');
|
||||
} catch(error) {
|
||||
// if eval variants are not supported, do not create inline object readers ever
|
||||
inlineObjectReadThreshold = Infinity;
|
||||
}
|
||||
|
||||
class Unpackr {
|
||||
constructor(options) {
|
||||
@@ -496,18 +503,11 @@
|
||||
function readObject() {
|
||||
// This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
|
||||
if (readObject.count++ > inlineObjectReadThreshold) {
|
||||
let optimizedReadObject;
|
||||
try {
|
||||
optimizedReadObject = structure.read = (new BlockedFunction ('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
||||
'({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
|
||||
} catch(error) {
|
||||
// in CF workers, the new BlockedFunction call could begin to fail at any point in time
|
||||
inlineObjectReadThreshold = Infinity; // disable going forward
|
||||
return readObject(); // recursively try again
|
||||
}
|
||||
let readObject = structure.read = (new BlockedFunction ('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
||||
'({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
|
||||
if (structure.highByte === 0)
|
||||
structure.read = createSecondByteReader(firstId, structure.read);
|
||||
return optimizedReadObject() // second byte is already read, if there is one so immediately read object
|
||||
return readObject() // second byte is already read, if there is one so immediately read object
|
||||
}
|
||||
let object = {};
|
||||
for (let i = 0, l = structure.length; i < l; i++) {
|
||||
@@ -576,45 +576,26 @@
|
||||
} else if ((byte1 & 0xe0) === 0xc0) {
|
||||
// 2 bytes
|
||||
const byte2 = src[position$1++] & 0x3f;
|
||||
const codePoint = ((byte1 & 0x1f) << 6) | byte2;
|
||||
// Reject overlong encoding: 2-byte sequences must encode values >= 0x80
|
||||
if (codePoint < 0x80) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else {
|
||||
units.push(codePoint);
|
||||
}
|
||||
units.push(((byte1 & 0x1f) << 6) | byte2);
|
||||
} else if ((byte1 & 0xf0) === 0xe0) {
|
||||
// 3 bytes
|
||||
const byte2 = src[position$1++] & 0x3f;
|
||||
const byte3 = src[position$1++] & 0x3f;
|
||||
const codePoint = ((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3;
|
||||
// Reject overlong encoding: 3-byte sequences must encode values >= 0x800
|
||||
// Also reject surrogates (0xD800-0xDFFF)
|
||||
if (codePoint < 0x800 || (codePoint >= 0xD800 && codePoint <= 0xDFFF)) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else {
|
||||
units.push(codePoint);
|
||||
}
|
||||
units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);
|
||||
} else if ((byte1 & 0xf8) === 0xf0) {
|
||||
// 4 bytes
|
||||
const byte2 = src[position$1++] & 0x3f;
|
||||
const byte3 = src[position$1++] & 0x3f;
|
||||
const byte4 = src[position$1++] & 0x3f;
|
||||
let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;
|
||||
// Reject overlong encoding: 4-byte sequences must encode values >= 0x10000
|
||||
// Also reject values > 0x10FFFF (maximum valid Unicode)
|
||||
if (unit < 0x10000 || unit > 0x10FFFF) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else if (unit > 0xffff) {
|
||||
if (unit > 0xffff) {
|
||||
unit -= 0x10000;
|
||||
units.push(((unit >>> 10) & 0x3ff) | 0xd800);
|
||||
unit = 0xdc00 | (unit & 0x3ff);
|
||||
units.push(unit);
|
||||
} else {
|
||||
units.push(unit);
|
||||
}
|
||||
units.push(unit);
|
||||
} else {
|
||||
units.push(0xFFFD); // replacement character for invalid lead byte
|
||||
units.push(byte1);
|
||||
}
|
||||
|
||||
if (units.length >= 0x1000) {
|
||||
@@ -977,7 +958,7 @@
|
||||
if (length <= 40) {
|
||||
let out = view.getBigUint64(start);
|
||||
for (let i = start + 8; i < end; i += 8) {
|
||||
out <<= BigInt(64);
|
||||
out <<= BigInt(64n);
|
||||
out |= view.getBigUint64(i);
|
||||
}
|
||||
return out
|
||||
@@ -1296,13 +1277,9 @@
|
||||
hasSharedUpdate = false;
|
||||
let encodingError;
|
||||
try {
|
||||
if (packr.randomAccessStructure && value && typeof value === 'object') {
|
||||
if (value.constructor === Object) writeStruct(value); // simple object
|
||||
else if (value.constructor !== Map && !Array.isArray(value) && !extensionClasses.some(extClass => value instanceof extClass)) {
|
||||
// allow user classes, if they don't need special handling (but do use toJSON if available)
|
||||
writeStruct(value.toJSON ? value.toJSON() : value);
|
||||
} else pack(value);
|
||||
} else
|
||||
if (packr.randomAccessStructure && value && value.constructor && value.constructor === Object)
|
||||
writeStruct(value);
|
||||
else
|
||||
pack(value);
|
||||
let lastBundle = bundledStrings;
|
||||
if (bundledStrings)
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+19
-42
@@ -30,6 +30,13 @@
|
||||
var sequentialMode = false;
|
||||
var inlineObjectReadThreshold = 2;
|
||||
var readStruct;
|
||||
// no-eval build
|
||||
try {
|
||||
new Function('');
|
||||
} catch(error) {
|
||||
// if eval variants are not supported, do not create inline object readers ever
|
||||
inlineObjectReadThreshold = Infinity;
|
||||
}
|
||||
|
||||
class Unpackr {
|
||||
constructor(options) {
|
||||
@@ -495,18 +502,11 @@
|
||||
function readObject() {
|
||||
// This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
|
||||
if (readObject.count++ > inlineObjectReadThreshold) {
|
||||
let optimizedReadObject;
|
||||
try {
|
||||
optimizedReadObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
||||
'({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
|
||||
} catch(error) {
|
||||
// in CF workers, the new Function call could begin to fail at any point in time
|
||||
inlineObjectReadThreshold = Infinity; // disable going forward
|
||||
return readObject(); // recursively try again
|
||||
}
|
||||
let readObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
||||
'({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
|
||||
if (structure.highByte === 0)
|
||||
structure.read = createSecondByteReader(firstId, structure.read);
|
||||
return optimizedReadObject() // second byte is already read, if there is one so immediately read object
|
||||
return readObject() // second byte is already read, if there is one so immediately read object
|
||||
}
|
||||
let object = {};
|
||||
for (let i = 0, l = structure.length; i < l; i++) {
|
||||
@@ -575,45 +575,26 @@
|
||||
} else if ((byte1 & 0xe0) === 0xc0) {
|
||||
// 2 bytes
|
||||
const byte2 = src[position$1++] & 0x3f;
|
||||
const codePoint = ((byte1 & 0x1f) << 6) | byte2;
|
||||
// Reject overlong encoding: 2-byte sequences must encode values >= 0x80
|
||||
if (codePoint < 0x80) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else {
|
||||
units.push(codePoint);
|
||||
}
|
||||
units.push(((byte1 & 0x1f) << 6) | byte2);
|
||||
} else if ((byte1 & 0xf0) === 0xe0) {
|
||||
// 3 bytes
|
||||
const byte2 = src[position$1++] & 0x3f;
|
||||
const byte3 = src[position$1++] & 0x3f;
|
||||
const codePoint = ((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3;
|
||||
// Reject overlong encoding: 3-byte sequences must encode values >= 0x800
|
||||
// Also reject surrogates (0xD800-0xDFFF)
|
||||
if (codePoint < 0x800 || (codePoint >= 0xD800 && codePoint <= 0xDFFF)) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else {
|
||||
units.push(codePoint);
|
||||
}
|
||||
units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);
|
||||
} else if ((byte1 & 0xf8) === 0xf0) {
|
||||
// 4 bytes
|
||||
const byte2 = src[position$1++] & 0x3f;
|
||||
const byte3 = src[position$1++] & 0x3f;
|
||||
const byte4 = src[position$1++] & 0x3f;
|
||||
let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;
|
||||
// Reject overlong encoding: 4-byte sequences must encode values >= 0x10000
|
||||
// Also reject values > 0x10FFFF (maximum valid Unicode)
|
||||
if (unit < 0x10000 || unit > 0x10FFFF) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else if (unit > 0xffff) {
|
||||
if (unit > 0xffff) {
|
||||
unit -= 0x10000;
|
||||
units.push(((unit >>> 10) & 0x3ff) | 0xd800);
|
||||
unit = 0xdc00 | (unit & 0x3ff);
|
||||
units.push(unit);
|
||||
} else {
|
||||
units.push(unit);
|
||||
}
|
||||
units.push(unit);
|
||||
} else {
|
||||
units.push(0xFFFD); // replacement character for invalid lead byte
|
||||
units.push(byte1);
|
||||
}
|
||||
|
||||
if (units.length >= 0x1000) {
|
||||
@@ -976,7 +957,7 @@
|
||||
if (length <= 40) {
|
||||
let out = view.getBigUint64(start);
|
||||
for (let i = start + 8; i < end; i += 8) {
|
||||
out <<= BigInt(64);
|
||||
out <<= BigInt(64n);
|
||||
out |= view.getBigUint64(i);
|
||||
}
|
||||
return out
|
||||
@@ -1295,13 +1276,9 @@
|
||||
hasSharedUpdate = false;
|
||||
let encodingError;
|
||||
try {
|
||||
if (packr.randomAccessStructure && value && typeof value === 'object') {
|
||||
if (value.constructor === Object) writeStruct(value); // simple object
|
||||
else if (value.constructor !== Map && !Array.isArray(value) && !extensionClasses.some(extClass => value instanceof extClass)) {
|
||||
// allow user classes, if they don't need special handling (but do use toJSON if available)
|
||||
writeStruct(value.toJSON ? value.toJSON() : value);
|
||||
} else pack(value);
|
||||
} else
|
||||
if (packr.randomAccessStructure && value && value.constructor && value.constructor === Object)
|
||||
writeStruct(value);
|
||||
else
|
||||
pack(value);
|
||||
let lastBundle = bundledStrings;
|
||||
if (bundledStrings)
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+29
-60
@@ -32,6 +32,13 @@ C1.name = 'MessagePack 0xC1';
|
||||
var sequentialMode = false;
|
||||
var inlineObjectReadThreshold = 2;
|
||||
var readStruct$1, onLoadedStructures$1, onSaveState;
|
||||
// no-eval build
|
||||
try {
|
||||
new Function('');
|
||||
} catch(error) {
|
||||
// if eval variants are not supported, do not create inline object readers ever
|
||||
inlineObjectReadThreshold = Infinity;
|
||||
}
|
||||
|
||||
class Unpackr {
|
||||
constructor(options) {
|
||||
@@ -501,18 +508,11 @@ function createStructureReader(structure, firstId) {
|
||||
function readObject() {
|
||||
// This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
|
||||
if (readObject.count++ > inlineObjectReadThreshold) {
|
||||
let optimizedReadObject;
|
||||
try {
|
||||
optimizedReadObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
||||
'({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
|
||||
} catch(error) {
|
||||
// in CF workers, the new Function call could begin to fail at any point in time
|
||||
inlineObjectReadThreshold = Infinity; // disable going forward
|
||||
return readObject(); // recursively try again
|
||||
}
|
||||
let readObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
||||
'({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
|
||||
if (structure.highByte === 0)
|
||||
structure.read = createSecondByteReader(firstId, structure.read);
|
||||
return optimizedReadObject() // second byte is already read, if there is one so immediately read object
|
||||
return readObject() // second byte is already read, if there is one so immediately read object
|
||||
}
|
||||
let object = {};
|
||||
for (let i = 0, l = structure.length; i < l; i++) {
|
||||
@@ -621,45 +621,26 @@ function readStringJS(length) {
|
||||
} else if ((byte1 & 0xe0) === 0xc0) {
|
||||
// 2 bytes
|
||||
const byte2 = src[position$1++] & 0x3f;
|
||||
const codePoint = ((byte1 & 0x1f) << 6) | byte2;
|
||||
// Reject overlong encoding: 2-byte sequences must encode values >= 0x80
|
||||
if (codePoint < 0x80) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else {
|
||||
units.push(codePoint);
|
||||
}
|
||||
units.push(((byte1 & 0x1f) << 6) | byte2);
|
||||
} else if ((byte1 & 0xf0) === 0xe0) {
|
||||
// 3 bytes
|
||||
const byte2 = src[position$1++] & 0x3f;
|
||||
const byte3 = src[position$1++] & 0x3f;
|
||||
const codePoint = ((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3;
|
||||
// Reject overlong encoding: 3-byte sequences must encode values >= 0x800
|
||||
// Also reject surrogates (0xD800-0xDFFF)
|
||||
if (codePoint < 0x800 || (codePoint >= 0xD800 && codePoint <= 0xDFFF)) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else {
|
||||
units.push(codePoint);
|
||||
}
|
||||
units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);
|
||||
} else if ((byte1 & 0xf8) === 0xf0) {
|
||||
// 4 bytes
|
||||
const byte2 = src[position$1++] & 0x3f;
|
||||
const byte3 = src[position$1++] & 0x3f;
|
||||
const byte4 = src[position$1++] & 0x3f;
|
||||
let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;
|
||||
// Reject overlong encoding: 4-byte sequences must encode values >= 0x10000
|
||||
// Also reject values > 0x10FFFF (maximum valid Unicode)
|
||||
if (unit < 0x10000 || unit > 0x10FFFF) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else if (unit > 0xffff) {
|
||||
if (unit > 0xffff) {
|
||||
unit -= 0x10000;
|
||||
units.push(((unit >>> 10) & 0x3ff) | 0xd800);
|
||||
unit = 0xdc00 | (unit & 0x3ff);
|
||||
units.push(unit);
|
||||
} else {
|
||||
units.push(unit);
|
||||
}
|
||||
units.push(unit);
|
||||
} else {
|
||||
units.push(0xFFFD); // replacement character for invalid lead byte
|
||||
units.push(byte1);
|
||||
}
|
||||
|
||||
if (units.length >= 0x1000) {
|
||||
@@ -1032,7 +1013,7 @@ currentExtensions[0x42] = data => {
|
||||
if (length <= 40) {
|
||||
let out = view.getBigUint64(start);
|
||||
for (let i = start + 8; i < end; i += 8) {
|
||||
out <<= BigInt(64);
|
||||
out <<= BigInt(64n);
|
||||
out |= view.getBigUint64(i);
|
||||
}
|
||||
return out
|
||||
@@ -1362,13 +1343,9 @@ class Packr extends Unpackr {
|
||||
hasSharedUpdate = false;
|
||||
let encodingError;
|
||||
try {
|
||||
if (packr.randomAccessStructure && value && typeof value === 'object') {
|
||||
if (value.constructor === Object) writeStruct(value); // simple object
|
||||
else if (value.constructor !== Map && !Array.isArray(value) && !extensionClasses.some(extClass => value instanceof extClass)) {
|
||||
// allow user classes, if they don't need special handling (but do use toJSON if available)
|
||||
writeStruct(value.toJSON ? value.toJSON() : value);
|
||||
} else pack(value);
|
||||
} else
|
||||
if (packr.randomAccessStructure && value && value.constructor && value.constructor === Object)
|
||||
writeStruct(value);
|
||||
else
|
||||
pack(value);
|
||||
let lastBundle = bundledStrings;
|
||||
if (bundledStrings)
|
||||
@@ -3172,7 +3149,6 @@ class UnpackrStream extends stream.Transform {
|
||||
options.objectMode = true;
|
||||
super(options);
|
||||
options.structures = [];
|
||||
this.maxIncompleteBufferSize = options.maxIncompleteBufferSize !== undefined ? options.maxIncompleteBufferSize : 0x4000000;
|
||||
this.unpackr = options.unpackr || new Unpackr(options);
|
||||
}
|
||||
_transform(chunk, encoding, callback) {
|
||||
@@ -3185,23 +3161,19 @@ class UnpackrStream extends stream.Transform {
|
||||
values = this.unpackr.unpackMultiple(chunk);
|
||||
} catch(error) {
|
||||
if (error.incomplete) {
|
||||
let incompleteBuffer = chunk.slice(error.lastPosition);
|
||||
if (incompleteBuffer.length > this.maxIncompleteBufferSize) {
|
||||
this.incompleteBuffer = null;
|
||||
return callback(new Error('Maximum incomplete buffer size exceeded'))
|
||||
}
|
||||
this.incompleteBuffer = incompleteBuffer;
|
||||
this.incompleteBuffer = chunk.slice(error.lastPosition);
|
||||
values = error.values;
|
||||
} else {
|
||||
return callback(error)
|
||||
}
|
||||
else
|
||||
throw error
|
||||
} finally {
|
||||
for (let value of values || []) {
|
||||
if (value === null)
|
||||
value = this.getNullValue();
|
||||
this.push(value);
|
||||
}
|
||||
}
|
||||
for (let value of values || []) {
|
||||
if (value === null)
|
||||
value = this.getNullValue();
|
||||
this.push(value);
|
||||
}
|
||||
callback();
|
||||
if (callback) callback();
|
||||
}
|
||||
getNullValue() {
|
||||
return Symbol.for(null)
|
||||
@@ -3324,9 +3296,6 @@ exports.FLOAT32_OPTIONS = FLOAT32_OPTIONS;
|
||||
exports.NEVER = NEVER;
|
||||
exports.Packr = Packr;
|
||||
exports.PackrStream = PackrStream;
|
||||
exports.RESERVE_START_SPACE = RESERVE_START_SPACE;
|
||||
exports.RESET_BUFFER_MODE = RESET_BUFFER_MODE;
|
||||
exports.REUSE_BUFFER_MODE = REUSE_BUFFER_MODE;
|
||||
exports.Unpackr = Unpackr;
|
||||
exports.UnpackrStream = UnpackrStream;
|
||||
exports.addExtension = addExtension;
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+19
-51
@@ -30,6 +30,13 @@
|
||||
var sequentialMode = false;
|
||||
var inlineObjectReadThreshold = 2;
|
||||
var readStruct$1, onLoadedStructures$1, onSaveState;
|
||||
// no-eval build
|
||||
try {
|
||||
new Function('');
|
||||
} catch(error) {
|
||||
// if eval variants are not supported, do not create inline object readers ever
|
||||
inlineObjectReadThreshold = Infinity;
|
||||
}
|
||||
|
||||
let Unpackr$1 = class Unpackr {
|
||||
constructor(options) {
|
||||
@@ -499,18 +506,11 @@
|
||||
function readObject() {
|
||||
// This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
|
||||
if (readObject.count++ > inlineObjectReadThreshold) {
|
||||
let optimizedReadObject;
|
||||
try {
|
||||
optimizedReadObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
||||
'({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
|
||||
} catch(error) {
|
||||
// in CF workers, the new Function call could begin to fail at any point in time
|
||||
inlineObjectReadThreshold = Infinity; // disable going forward
|
||||
return readObject(); // recursively try again
|
||||
}
|
||||
let readObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
||||
'({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
|
||||
if (structure.highByte === 0)
|
||||
structure.read = createSecondByteReader(firstId, structure.read);
|
||||
return optimizedReadObject() // second byte is already read, if there is one so immediately read object
|
||||
return readObject() // second byte is already read, if there is one so immediately read object
|
||||
}
|
||||
let object = {};
|
||||
for (let i = 0, l = structure.length; i < l; i++) {
|
||||
@@ -617,45 +617,26 @@
|
||||
} else if ((byte1 & 0xe0) === 0xc0) {
|
||||
// 2 bytes
|
||||
const byte2 = src[position$1++] & 0x3f;
|
||||
const codePoint = ((byte1 & 0x1f) << 6) | byte2;
|
||||
// Reject overlong encoding: 2-byte sequences must encode values >= 0x80
|
||||
if (codePoint < 0x80) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else {
|
||||
units.push(codePoint);
|
||||
}
|
||||
units.push(((byte1 & 0x1f) << 6) | byte2);
|
||||
} else if ((byte1 & 0xf0) === 0xe0) {
|
||||
// 3 bytes
|
||||
const byte2 = src[position$1++] & 0x3f;
|
||||
const byte3 = src[position$1++] & 0x3f;
|
||||
const codePoint = ((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3;
|
||||
// Reject overlong encoding: 3-byte sequences must encode values >= 0x800
|
||||
// Also reject surrogates (0xD800-0xDFFF)
|
||||
if (codePoint < 0x800 || (codePoint >= 0xD800 && codePoint <= 0xDFFF)) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else {
|
||||
units.push(codePoint);
|
||||
}
|
||||
units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);
|
||||
} else if ((byte1 & 0xf8) === 0xf0) {
|
||||
// 4 bytes
|
||||
const byte2 = src[position$1++] & 0x3f;
|
||||
const byte3 = src[position$1++] & 0x3f;
|
||||
const byte4 = src[position$1++] & 0x3f;
|
||||
let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;
|
||||
// Reject overlong encoding: 4-byte sequences must encode values >= 0x10000
|
||||
// Also reject values > 0x10FFFF (maximum valid Unicode)
|
||||
if (unit < 0x10000 || unit > 0x10FFFF) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else if (unit > 0xffff) {
|
||||
if (unit > 0xffff) {
|
||||
unit -= 0x10000;
|
||||
units.push(((unit >>> 10) & 0x3ff) | 0xd800);
|
||||
unit = 0xdc00 | (unit & 0x3ff);
|
||||
units.push(unit);
|
||||
} else {
|
||||
units.push(unit);
|
||||
}
|
||||
units.push(unit);
|
||||
} else {
|
||||
units.push(0xFFFD); // replacement character for invalid lead byte
|
||||
units.push(byte1);
|
||||
}
|
||||
|
||||
if (units.length >= 0x1000) {
|
||||
@@ -1028,7 +1009,7 @@
|
||||
if (length <= 40) {
|
||||
let out = view.getBigUint64(start);
|
||||
for (let i = start + 8; i < end; i += 8) {
|
||||
out <<= BigInt(64);
|
||||
out <<= BigInt(64n);
|
||||
out |= view.getBigUint64(i);
|
||||
}
|
||||
return out
|
||||
@@ -1357,13 +1338,9 @@
|
||||
hasSharedUpdate = false;
|
||||
let encodingError;
|
||||
try {
|
||||
if (packr.randomAccessStructure && value && typeof value === 'object') {
|
||||
if (value.constructor === Object) writeStruct(value); // simple object
|
||||
else if (value.constructor !== Map && !Array.isArray(value) && !extensionClasses.some(extClass => value instanceof extClass)) {
|
||||
// allow user classes, if they don't need special handling (but do use toJSON if available)
|
||||
writeStruct(value.toJSON ? value.toJSON() : value);
|
||||
} else pack(value);
|
||||
} else
|
||||
if (packr.randomAccessStructure && value && value.constructor && value.constructor === Object)
|
||||
writeStruct(value);
|
||||
else
|
||||
pack(value);
|
||||
let lastBundle = bundledStrings;
|
||||
if (bundledStrings)
|
||||
@@ -3294,15 +3271,6 @@
|
||||
var deserialized = unpack(serialized);
|
||||
assert.equal(deserialized, data);
|
||||
});
|
||||
test('overlong UTF-8 string', function () {
|
||||
const payload = Buffer.concat([
|
||||
Buffer.from([0xa2]), // msgpack fixstr, 2 bytes
|
||||
Buffer.from([0xc0, 0xaf]), // overlong "/"
|
||||
]);
|
||||
|
||||
const result = unpack(payload);
|
||||
assert.notEqual(result, '/');
|
||||
});
|
||||
test('use ArrayBuffer', function () {
|
||||
const data = {prop: 'a test'};
|
||||
var serialized = pack(data);
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+16
-35
@@ -34,6 +34,13 @@
|
||||
var inlineObjectReadThreshold = 2;
|
||||
var readStruct, onLoadedStructures, onSaveState;
|
||||
var BlockedFunction; // we use search and replace to change the next call to BlockedFunction to avoid CSP issues for
|
||||
// no-eval build
|
||||
try {
|
||||
new BlockedFunction ('');
|
||||
} catch(error) {
|
||||
// if eval variants are not supported, do not create inline object readers ever
|
||||
inlineObjectReadThreshold = Infinity;
|
||||
}
|
||||
|
||||
class Unpackr {
|
||||
constructor(options) {
|
||||
@@ -506,18 +513,11 @@
|
||||
function readObject() {
|
||||
// This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
|
||||
if (readObject.count++ > inlineObjectReadThreshold) {
|
||||
let optimizedReadObject;
|
||||
try {
|
||||
optimizedReadObject = structure.read = (new BlockedFunction ('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
||||
'({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
|
||||
} catch(error) {
|
||||
// in CF workers, the new BlockedFunction call could begin to fail at any point in time
|
||||
inlineObjectReadThreshold = Infinity; // disable going forward
|
||||
return readObject(); // recursively try again
|
||||
}
|
||||
let readObject = structure.read = (new BlockedFunction ('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
||||
'({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
|
||||
if (structure.highByte === 0)
|
||||
structure.read = createSecondByteReader(firstId, structure.read);
|
||||
return optimizedReadObject() // second byte is already read, if there is one so immediately read object
|
||||
return readObject() // second byte is already read, if there is one so immediately read object
|
||||
}
|
||||
let object = {};
|
||||
for (let i = 0, l = structure.length; i < l; i++) {
|
||||
@@ -626,45 +626,26 @@
|
||||
} else if ((byte1 & 0xe0) === 0xc0) {
|
||||
// 2 bytes
|
||||
const byte2 = src[position++] & 0x3f;
|
||||
const codePoint = ((byte1 & 0x1f) << 6) | byte2;
|
||||
// Reject overlong encoding: 2-byte sequences must encode values >= 0x80
|
||||
if (codePoint < 0x80) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else {
|
||||
units.push(codePoint);
|
||||
}
|
||||
units.push(((byte1 & 0x1f) << 6) | byte2);
|
||||
} else if ((byte1 & 0xf0) === 0xe0) {
|
||||
// 3 bytes
|
||||
const byte2 = src[position++] & 0x3f;
|
||||
const byte3 = src[position++] & 0x3f;
|
||||
const codePoint = ((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3;
|
||||
// Reject overlong encoding: 3-byte sequences must encode values >= 0x800
|
||||
// Also reject surrogates (0xD800-0xDFFF)
|
||||
if (codePoint < 0x800 || (codePoint >= 0xD800 && codePoint <= 0xDFFF)) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else {
|
||||
units.push(codePoint);
|
||||
}
|
||||
units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);
|
||||
} else if ((byte1 & 0xf8) === 0xf0) {
|
||||
// 4 bytes
|
||||
const byte2 = src[position++] & 0x3f;
|
||||
const byte3 = src[position++] & 0x3f;
|
||||
const byte4 = src[position++] & 0x3f;
|
||||
let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;
|
||||
// Reject overlong encoding: 4-byte sequences must encode values >= 0x10000
|
||||
// Also reject values > 0x10FFFF (maximum valid Unicode)
|
||||
if (unit < 0x10000 || unit > 0x10FFFF) {
|
||||
units.push(0xFFFD); // replacement character
|
||||
} else if (unit > 0xffff) {
|
||||
if (unit > 0xffff) {
|
||||
unit -= 0x10000;
|
||||
units.push(((unit >>> 10) & 0x3ff) | 0xd800);
|
||||
unit = 0xdc00 | (unit & 0x3ff);
|
||||
units.push(unit);
|
||||
} else {
|
||||
units.push(unit);
|
||||
}
|
||||
units.push(unit);
|
||||
} else {
|
||||
units.push(0xFFFD); // replacement character for invalid lead byte
|
||||
units.push(byte1);
|
||||
}
|
||||
|
||||
if (units.length >= 0x1000) {
|
||||
@@ -1037,7 +1018,7 @@
|
||||
if (length <= 40) {
|
||||
let out = view.getBigUint64(start);
|
||||
for (let i = start + 8; i < end; i += 8) {
|
||||
out <<= BigInt(64);
|
||||
out <<= BigInt(64n);
|
||||
out |= view.getBigUint64(i);
|
||||
}
|
||||
return out
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
-3
@@ -60,8 +60,6 @@ export function decode(messagePack: Buffer | Uint8Array, options?: UnpackOptions
|
||||
export function addExtension(extension: Extension): void
|
||||
export function clearSource(): void
|
||||
export function roundFloat32(float32Number: number): number
|
||||
export function decodeIter(bufferIterator: Iterable<Buffer | Uint8Array> | Iterator<Buffer | Uint8Array> | AsyncIterable<Buffer | Uint8Array> | AsyncIterator<Buffer | Uint8Array>, options?: Options): AsyncGenerator<any>
|
||||
export function encodeIter(objectIterator: Iterable<Buffer | Uint8Array> | Iterator<Buffer | Uint8Array> | AsyncIterable<Buffer | Uint8Array> | AsyncIterator<Buffer | Uint8Array>, options?: Options): IterableIterator<Buffer> | Promise<AsyncIterableIterator<Buffer>>
|
||||
export const C1: {}
|
||||
export let isNativeAccelerationEnabled: boolean
|
||||
|
||||
@@ -90,4 +88,3 @@ export class UnpackrStream extends Transform {
|
||||
export class PackrStream extends Transform {
|
||||
constructor(options?: Options | { highWaterMark: number, emitClose: boolean, allowHalfOpen: boolean })
|
||||
}
|
||||
export { PackrStream as EncoderStream, UnpackrStream as DecoderStream };
|
||||
-3
@@ -60,8 +60,6 @@ export function decode(messagePack: Buffer | Uint8Array, options?: UnpackOptions
|
||||
export function addExtension(extension: Extension): void
|
||||
export function clearSource(): void
|
||||
export function roundFloat32(float32Number: number): number
|
||||
export function decodeIter(bufferIterator: Iterable<Buffer | Uint8Array> | Iterator<Buffer | Uint8Array> | AsyncIterable<Buffer | Uint8Array> | AsyncIterator<Buffer | Uint8Array>, options?: Options): AsyncGenerator<any>
|
||||
export function encodeIter(objectIterator: Iterable<Buffer | Uint8Array> | Iterator<Buffer | Uint8Array> | AsyncIterable<Buffer | Uint8Array> | AsyncIterator<Buffer | Uint8Array>, options?: Options): IterableIterator<Buffer> | Promise<AsyncIterableIterator<Buffer>>
|
||||
export const C1: {}
|
||||
export let isNativeAccelerationEnabled: boolean
|
||||
|
||||
@@ -90,4 +88,3 @@ export class UnpackrStream extends Transform {
|
||||
export class PackrStream extends Transform {
|
||||
constructor(options?: Options | { highWaterMark: number, emitClose: boolean, allowHalfOpen: boolean })
|
||||
}
|
||||
export { PackrStream as EncoderStream, UnpackrStream as DecoderStream };
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
export { Packr, Encoder, addExtension, pack, encode, NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT, REUSE_BUFFER_MODE, RESET_BUFFER_MODE, RESERVE_START_SPACE } from './pack.js'
|
||||
export { Packr, Encoder, addExtension, pack, encode, NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } from './pack.js'
|
||||
export { Unpackr, Decoder, C1, unpack, unpackMultiple, decode, FLOAT32_OPTIONS, clearSource, roundFloat32, isNativeAccelerationEnabled } from './unpack.js'
|
||||
import './struct.js'
|
||||
export { PackrStream, UnpackrStream, PackrStream as EncoderStream, UnpackrStream as DecoderStream } from './stream.js'
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
export { Unpackr, Decoder, Packr, Encoder, pack, encode, unpack, decode, addExtension, FLOAT32_OPTIONS, REUSE_BUFFER_MODE, RESET_BUFFER_MODE, RESERVE_START_SPACE } from '.'
|
||||
export { Unpackr, Decoder, Packr, Encoder, pack, encode, unpack, decode, addExtension, FLOAT32_OPTIONS } from '.'
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
export { Unpackr, Decoder, Packr, Encoder, pack, encode, unpack, decode, addExtension, FLOAT32_OPTIONS, REUSE_BUFFER_MODE, RESET_BUFFER_MODE, RESERVE_START_SPACE } from '.'
|
||||
export { Unpackr, Decoder, Packr, Encoder, pack, encode, unpack, decode, addExtension, FLOAT32_OPTIONS } from '.'
|
||||
|
||||
+3
-7
@@ -123,13 +123,9 @@ export class Packr extends Unpackr {
|
||||
hasSharedUpdate = false
|
||||
let encodingError;
|
||||
try {
|
||||
if (packr.randomAccessStructure && value && typeof value === 'object') {
|
||||
if (value.constructor === Object) writeStruct(value); // simple object
|
||||
else if (value.constructor !== Map && !Array.isArray(value) && !extensionClasses.some(extClass => value instanceof extClass)) {
|
||||
// allow user classes, if they don't need special handling (but do use toJSON if available)
|
||||
writeStruct(value.toJSON ? value.toJSON() : value);
|
||||
} else pack(value)
|
||||
} else
|
||||
if (packr.randomAccessStructure && value && value.constructor && value.constructor === Object)
|
||||
writeStruct(value);
|
||||
else
|
||||
pack(value)
|
||||
let lastBundle = bundledStrings;
|
||||
if (bundledStrings)
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "msgpackr",
|
||||
"author": "Kris Zyp",
|
||||
"version": "1.11.12",
|
||||
"version": "1.11.5",
|
||||
"description": "Ultra-fast MessagePack implementation with extensions for records and structured cloning",
|
||||
"license": "MIT",
|
||||
"types": "./index.d.ts",
|
||||
|
||||
+10
-15
@@ -25,7 +25,6 @@ export class UnpackrStream extends Transform {
|
||||
options.objectMode = true
|
||||
super(options)
|
||||
options.structures = []
|
||||
this.maxIncompleteBufferSize = options.maxIncompleteBufferSize !== undefined ? options.maxIncompleteBufferSize : 0x4000000
|
||||
this.unpackr = options.unpackr || new Unpackr(options)
|
||||
}
|
||||
_transform(chunk, encoding, callback) {
|
||||
@@ -38,23 +37,19 @@ export class UnpackrStream extends Transform {
|
||||
values = this.unpackr.unpackMultiple(chunk)
|
||||
} catch(error) {
|
||||
if (error.incomplete) {
|
||||
let incompleteBuffer = chunk.slice(error.lastPosition)
|
||||
if (incompleteBuffer.length > this.maxIncompleteBufferSize) {
|
||||
this.incompleteBuffer = null
|
||||
return callback(new Error('Maximum incomplete buffer size exceeded'))
|
||||
}
|
||||
this.incompleteBuffer = incompleteBuffer
|
||||
this.incompleteBuffer = chunk.slice(error.lastPosition)
|
||||
values = error.values
|
||||
} else {
|
||||
return callback(error)
|
||||
}
|
||||
else
|
||||
throw error
|
||||
} finally {
|
||||
for (let value of values || []) {
|
||||
if (value === null)
|
||||
value = this.getNullValue()
|
||||
this.push(value)
|
||||
}
|
||||
}
|
||||
for (let value of values || []) {
|
||||
if (value === null)
|
||||
value = this.getNullValue()
|
||||
this.push(value)
|
||||
}
|
||||
callback()
|
||||
if (callback) callback()
|
||||
}
|
||||
getNullValue() {
|
||||
return Symbol.for(null)
|
||||
|
||||
+16
-35
@@ -29,6 +29,13 @@ var sequentialMode = false
|
||||
var inlineObjectReadThreshold = 2
|
||||
var readStruct, onLoadedStructures, onSaveState
|
||||
var BlockedFunction // we use search and replace to change the next call to BlockedFunction to avoid CSP issues for
|
||||
// no-eval build
|
||||
try {
|
||||
new Function('')
|
||||
} catch(error) {
|
||||
// if eval variants are not supported, do not create inline object readers ever
|
||||
inlineObjectReadThreshold = Infinity
|
||||
}
|
||||
|
||||
export class Unpackr {
|
||||
constructor(options) {
|
||||
@@ -501,18 +508,11 @@ function createStructureReader(structure, firstId) {
|
||||
function readObject() {
|
||||
// This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
|
||||
if (readObject.count++ > inlineObjectReadThreshold) {
|
||||
let optimizedReadObject
|
||||
try {
|
||||
optimizedReadObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
||||
'({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read)
|
||||
} catch(error) {
|
||||
// in CF workers, the new Function call could begin to fail at any point in time
|
||||
inlineObjectReadThreshold = Infinity // disable going forward
|
||||
return readObject(); // recursively try again
|
||||
}
|
||||
let readObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
||||
'({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read)
|
||||
if (structure.highByte === 0)
|
||||
structure.read = createSecondByteReader(firstId, structure.read)
|
||||
return optimizedReadObject() // second byte is already read, if there is one so immediately read object
|
||||
return readObject() // second byte is already read, if there is one so immediately read object
|
||||
}
|
||||
let object = {}
|
||||
for (let i = 0, l = structure.length; i < l; i++) {
|
||||
@@ -621,45 +621,26 @@ function readStringJS(length) {
|
||||
} else if ((byte1 & 0xe0) === 0xc0) {
|
||||
// 2 bytes
|
||||
const byte2 = src[position++] & 0x3f
|
||||
const codePoint = ((byte1 & 0x1f) << 6) | byte2
|
||||
// Reject overlong encoding: 2-byte sequences must encode values >= 0x80
|
||||
if (codePoint < 0x80) {
|
||||
units.push(0xFFFD) // replacement character
|
||||
} else {
|
||||
units.push(codePoint)
|
||||
}
|
||||
units.push(((byte1 & 0x1f) << 6) | byte2)
|
||||
} else if ((byte1 & 0xf0) === 0xe0) {
|
||||
// 3 bytes
|
||||
const byte2 = src[position++] & 0x3f
|
||||
const byte3 = src[position++] & 0x3f
|
||||
const codePoint = ((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3
|
||||
// Reject overlong encoding: 3-byte sequences must encode values >= 0x800
|
||||
// Also reject surrogates (0xD800-0xDFFF)
|
||||
if (codePoint < 0x800 || (codePoint >= 0xD800 && codePoint <= 0xDFFF)) {
|
||||
units.push(0xFFFD) // replacement character
|
||||
} else {
|
||||
units.push(codePoint)
|
||||
}
|
||||
units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3)
|
||||
} else if ((byte1 & 0xf8) === 0xf0) {
|
||||
// 4 bytes
|
||||
const byte2 = src[position++] & 0x3f
|
||||
const byte3 = src[position++] & 0x3f
|
||||
const byte4 = src[position++] & 0x3f
|
||||
let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4
|
||||
// Reject overlong encoding: 4-byte sequences must encode values >= 0x10000
|
||||
// Also reject values > 0x10FFFF (maximum valid Unicode)
|
||||
if (unit < 0x10000 || unit > 0x10FFFF) {
|
||||
units.push(0xFFFD) // replacement character
|
||||
} else if (unit > 0xffff) {
|
||||
if (unit > 0xffff) {
|
||||
unit -= 0x10000
|
||||
units.push(((unit >>> 10) & 0x3ff) | 0xd800)
|
||||
unit = 0xdc00 | (unit & 0x3ff)
|
||||
units.push(unit)
|
||||
} else {
|
||||
units.push(unit)
|
||||
}
|
||||
units.push(unit)
|
||||
} else {
|
||||
units.push(0xFFFD) // replacement character for invalid lead byte
|
||||
units.push(byte1)
|
||||
}
|
||||
|
||||
if (units.length >= 0x1000) {
|
||||
@@ -1032,7 +1013,7 @@ currentExtensions[0x42] = data => {
|
||||
if (length <= 40) {
|
||||
let out = view.getBigUint64(start)
|
||||
for (let i = start + 8; i < end; i += 8) {
|
||||
out <<= BigInt(64)
|
||||
out <<= BigInt(64n)
|
||||
out |= view.getBigUint64(i)
|
||||
}
|
||||
return out
|
||||
|
||||
Reference in New Issue
Block a user