msgpackr 1.11.14 → 1.12.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/dist/index-no-eval.cjs +7 -1
- package/dist/index-no-eval.cjs.map +1 -1
- package/dist/index-no-eval.min.js +1 -1
- package/dist/index-no-eval.min.js.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/node.cjs +7 -1
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +76 -1
- package/dist/test.js.map +1 -1
- package/pack.js +7 -1
- package/package.json +1 -1
package/dist/test.js
CHANGED
|
@@ -1357,7 +1357,13 @@
|
|
|
1357
1357
|
hasSharedUpdate = false;
|
|
1358
1358
|
let encodingError;
|
|
1359
1359
|
try {
|
|
1360
|
-
|
|
1360
|
+
// readOnlyStructures: skip the random-access struct write path so NO new struct is
|
|
1361
|
+
// minted. randomAccessStructure stays true (the struct READ path and the struct-safe
|
|
1362
|
+
// integer boundary are preserved, so existing struct data still decodes), but objects
|
|
1363
|
+
// fall through to the normal pack()->writeObject->writeRecord path and are written as
|
|
1364
|
+
// classic shared-structure records (byte range 0x40-0x7f, disjoint from struct headers
|
|
1365
|
+
// at 0x20-0x3f) — the bounded, width-agnostic encoding used before struct mode.
|
|
1366
|
+
if (packr.randomAccessStructure && !packr.readOnlyStructures && value && typeof value === 'object') {
|
|
1361
1367
|
if (value.constructor === Object) writeStruct(value); // simple object
|
|
1362
1368
|
else if (value.constructor !== Map && !Array.isArray(value) && !extensionClasses.some(extClass => value instanceof extClass)) {
|
|
1363
1369
|
// allow user classes, if they don't need special handling (but do use toJSON if available)
|
|
@@ -4849,5 +4855,74 @@
|
|
|
4849
4855
|
});
|
|
4850
4856
|
});
|
|
4851
4857
|
|
|
4858
|
+
suite('msgpackr – readOnlyStructures (write-disable, read-compatible)', function () {
|
|
4859
|
+
// readOnlyStructures keeps randomAccessStructure decode semantics — existing random-access
|
|
4860
|
+
// struct data still decodes and the struct-safe integer boundary is preserved — but never mints
|
|
4861
|
+
// a new random-access structure on write. Objects fall through to the classic shared-structure
|
|
4862
|
+
// record path (bytes 0x40-0x7f, disjoint from struct headers at 0x20-0x3f), the bounded,
|
|
4863
|
+
// width-agnostic encoding used before struct mode. This is the mechanism for disabling typed
|
|
4864
|
+
// structures on an existing store without breaking reads.
|
|
4865
|
+
const sharedStore = () => {
|
|
4866
|
+
let saved;
|
|
4867
|
+
return { getStructures: () => saved, saveStructures: (s) => { saved = s; return true; } };
|
|
4868
|
+
};
|
|
4869
|
+
|
|
4870
|
+
test('decodes pre-existing random-access structs (read stays enabled)', function () {
|
|
4871
|
+
const full = new Packr({ randomAccessStructure: true, useRecords: true });
|
|
4872
|
+
const rec = { a: 1, b: 'hello', c: true, n: 42 };
|
|
4873
|
+
const buf = full.pack(rec);
|
|
4874
|
+
assert.ok(buf[0] >= 0x20 && buf[0] < 0x40, 'control: full encoder emits a random-access struct');
|
|
4875
|
+
|
|
4876
|
+
const ro = new Packr({ randomAccessStructure: true, useRecords: true, readOnlyStructures: true });
|
|
4877
|
+
ro.typedStructs = full.typedStructs; // share the existing random-access dictionary
|
|
4878
|
+
assert.deepEqual(ro.unpack(buf), rec);
|
|
4879
|
+
});
|
|
4880
|
+
|
|
4881
|
+
test('writes classic shared-structure records (0x40-0x7f), never a random-access struct', function () {
|
|
4882
|
+
const ro = new Packr({ randomAccessStructure: true, useRecords: true, readOnlyStructures: true, ...sharedStore() });
|
|
4883
|
+
const rec = { x: 9, y: 'world', z: [1, 2, 3], nested: { deep: 50, k: 42 } };
|
|
4884
|
+
const b1 = ro.pack(rec);
|
|
4885
|
+
assert.ok(b1[0] >= 0x40 && b1[0] < 0x80, 'expected a classic record (0x40-0x7f), got 0x' + b1[0].toString(16));
|
|
4886
|
+
assert.strictEqual(ro.typedStructs ? ro.typedStructs.length : 0, 0, 'no random-access struct minted');
|
|
4887
|
+
assert.deepEqual(ro.unpack(b1), rec);
|
|
4888
|
+
// a second record of the same shape reuses the shared classic structure (still classic)
|
|
4889
|
+
const b2 = ro.pack({ x: 1, y: 'a', z: [], nested: { deep: 0, k: 0 } });
|
|
4890
|
+
assert.ok(b2[0] >= 0x40 && b2[0] < 0x80, 'second record also classic');
|
|
4891
|
+
});
|
|
4892
|
+
|
|
4893
|
+
test('preserves the struct-safe integer boundary (nested 0x20-0x3f ints do not collide)', function () {
|
|
4894
|
+
const ro = new Packr({ randomAccessStructure: true, useRecords: true, readOnlyStructures: true, ...sharedStore() });
|
|
4895
|
+
for (const v of [0x1f, 0x20, 0x2a, 0x3f, 0x40, 0x7f]) {
|
|
4896
|
+
assert.deepEqual(ro.unpack(ro.pack({ v, nested: { w: v } })), { v, nested: { w: v } });
|
|
4897
|
+
}
|
|
4898
|
+
});
|
|
4899
|
+
|
|
4900
|
+
test('a normal randomAccessStructure reader decodes readOnly classic records (replication compat)', function () {
|
|
4901
|
+
let saved;
|
|
4902
|
+
const store = { getStructures: () => saved, saveStructures: (s) => { saved = s; return true; } };
|
|
4903
|
+
const ro = new Packr({ randomAccessStructure: true, useRecords: true, readOnlyStructures: true, ...store });
|
|
4904
|
+
const roBuf = ro.pack({ p: 'q', n: 42 });
|
|
4905
|
+
assert.ok(roBuf[0] >= 0x40 && roBuf[0] < 0x80, 'readOnly writes a classic record');
|
|
4906
|
+
|
|
4907
|
+
// A peer that is NOT readOnly (a normal struct-writing node) shares the classic-structure
|
|
4908
|
+
// store and decodes the classic record correctly — no mapsAsObjects needed, since classic
|
|
4909
|
+
// records decode to objects natively.
|
|
4910
|
+
const peer = new Packr({ randomAccessStructure: true, useRecords: true, ...store });
|
|
4911
|
+
assert.deepEqual(peer.unpack(roBuf), { p: 'q', n: 42 });
|
|
4912
|
+
});
|
|
4913
|
+
|
|
4914
|
+
test('every object shape uses the classic path (null-proto, shadowed ctor) — no random-access struct', function () {
|
|
4915
|
+
const ro = new Packr({ randomAccessStructure: true, useRecords: true, readOnlyStructures: true, ...sharedStore() });
|
|
4916
|
+
|
|
4917
|
+
const np = Object.create(null); np.a = 1; np.b = 'x';
|
|
4918
|
+
assert.deepEqual(ro.unpack(ro.pack(np)), { a: 1, b: 'x' });
|
|
4919
|
+
|
|
4920
|
+
const cs = { constructor: 'shadow', a: 1 };
|
|
4921
|
+
assert.deepEqual(ro.unpack(ro.pack(cs)), { constructor: 'shadow', a: 1 });
|
|
4922
|
+
|
|
4923
|
+
assert.strictEqual(ro.typedStructs ? ro.typedStructs.length : 0, 0, 'no random-access struct minted for any shape');
|
|
4924
|
+
});
|
|
4925
|
+
});
|
|
4926
|
+
|
|
4852
4927
|
})(chai, null, module, fs);
|
|
4853
4928
|
//# sourceMappingURL=test.js.map
|