@series-inc/rundot-syncplay 5.23.0-beta.7
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 +610 -0
- package/dist/animation.d.ts +119 -0
- package/dist/animation.js +488 -0
- package/dist/asset-cooking.d.ts +82 -0
- package/dist/asset-cooking.js +364 -0
- package/dist/authority-room.d.ts +217 -0
- package/dist/authority-room.js +701 -0
- package/dist/bot-documents.d.ts +115 -0
- package/dist/bot-documents.js +549 -0
- package/dist/bot-primitives.d.ts +152 -0
- package/dist/bot-primitives.js +472 -0
- package/dist/browser.d.ts +57 -0
- package/dist/browser.js +53 -0
- package/dist/canonical.d.ts +12 -0
- package/dist/canonical.js +288 -0
- package/dist/certification.d.ts +455 -0
- package/dist/certification.js +1855 -0
- package/dist/chaos-certification.d.ts +56 -0
- package/dist/chaos-certification.js +1397 -0
- package/dist/cjs/animation.js +495 -0
- package/dist/cjs/asset-cooking.js +372 -0
- package/dist/cjs/authority-room.js +704 -0
- package/dist/cjs/bot-documents.js +556 -0
- package/dist/cjs/bot-primitives.js +482 -0
- package/dist/cjs/browser.js +96 -0
- package/dist/cjs/canonical.js +299 -0
- package/dist/cjs/certification.js +1860 -0
- package/dist/cjs/chaos-certification.js +1402 -0
- package/dist/cjs/collections.js +36 -0
- package/dist/cjs/collision.js +96 -0
- package/dist/cjs/commands.js +987 -0
- package/dist/cjs/config-bundle.js +491 -0
- package/dist/cjs/creator.js +30 -0
- package/dist/cjs/deterministic-primitives.js +134 -0
- package/dist/cjs/deterministic-session.js +1410 -0
- package/dist/cjs/ecs-lite.js +155 -0
- package/dist/cjs/effects-adapter.js +97 -0
- package/dist/cjs/engine-complete.js +2297 -0
- package/dist/cjs/engine-core-proof.js +70 -0
- package/dist/cjs/engine-parity-matrix.js +874 -0
- package/dist/cjs/engine-parity.js +3183 -0
- package/dist/cjs/engine-runtime.js +3141 -0
- package/dist/cjs/errors.js +22 -0
- package/dist/cjs/events.js +247 -0
- package/dist/cjs/examples/counter-duel.js +157 -0
- package/dist/cjs/examples/fixed-arena.js +368 -0
- package/dist/cjs/index.js +229 -0
- package/dist/cjs/input-authority.js +150 -0
- package/dist/cjs/input-button.js +256 -0
- package/dist/cjs/input-timeline.js +418 -0
- package/dist/cjs/instant-replay.js +66 -0
- package/dist/cjs/lag-compensation3d.js +837 -0
- package/dist/cjs/local-authority-server-runner.js +1121 -0
- package/dist/cjs/local-authority-wire.js +1497 -0
- package/dist/cjs/local-authority.js +817 -0
- package/dist/cjs/local-ws-adapter.js +150 -0
- package/dist/cjs/match-log.js +61 -0
- package/dist/cjs/math.js +157 -0
- package/dist/cjs/mock-network-adapter.js +26 -0
- package/dist/cjs/movement.js +703 -0
- package/dist/cjs/movement3d.js +1246 -0
- package/dist/cjs/multiclient-authority.js +308 -0
- package/dist/cjs/multiplayer-service.js +434 -0
- package/dist/cjs/navigation.js +347 -0
- package/dist/cjs/navmesh.js +1437 -0
- package/dist/cjs/networked-client.js +691 -0
- package/dist/cjs/networked-input-authority.js +443 -0
- package/dist/cjs/node.js +47 -0
- package/dist/cjs/number-lab.js +78 -0
- package/dist/cjs/offline-session.js +370 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/pause-resume.js +43 -0
- package/dist/cjs/physics-cert.js +426 -0
- package/dist/cjs/physics2d.js +751 -0
- package/dist/cjs/physics3d.js +1996 -0
- package/dist/cjs/prediction-culling.js +203 -0
- package/dist/cjs/protocol-lab.js +1299 -0
- package/dist/cjs/r3f-render-adapter.js +209 -0
- package/dist/cjs/random.js +59 -0
- package/dist/cjs/replay-bundle.js +1598 -0
- package/dist/cjs/replay-inspect.js +236 -0
- package/dist/cjs/replay-scoring.js +68 -0
- package/dist/cjs/replay.js +356 -0
- package/dist/cjs/reports.js +181 -0
- package/dist/cjs/rollback-history.js +251 -0
- package/dist/cjs/runtime-guards.js +111 -0
- package/dist/cjs/sample-lab.js +145 -0
- package/dist/cjs/sample-scenes.js +752 -0
- package/dist/cjs/schema-artifacts.js +359 -0
- package/dist/cjs/schema-codegen.js +544 -0
- package/dist/cjs/schema-dsl-binary.js +655 -0
- package/dist/cjs/schema.js +319 -0
- package/dist/cjs/sdk-offline.js +99 -0
- package/dist/cjs/session-promotion.js +74 -0
- package/dist/cjs/session-snapshot.js +265 -0
- package/dist/cjs/session-wire.js +216 -0
- package/dist/cjs/signals.js +103 -0
- package/dist/cjs/sparse-set.js +169 -0
- package/dist/cjs/synctest.js +136 -0
- package/dist/cjs/system-lifecycle.js +286 -0
- package/dist/cjs/timers.js +61 -0
- package/dist/cjs/tools/static-checker.js +1468 -0
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/venus-mp-budget.js +125 -0
- package/dist/cjs/ws-frame.js +255 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +11379 -0
- package/dist/collections.d.ts +9 -0
- package/dist/collections.js +30 -0
- package/dist/collision.d.ts +25 -0
- package/dist/collision.js +85 -0
- package/dist/commands.d.ts +137 -0
- package/dist/commands.js +977 -0
- package/dist/config-bundle.d.ts +89 -0
- package/dist/config-bundle.js +483 -0
- package/dist/creator.d.ts +20 -0
- package/dist/creator.js +11 -0
- package/dist/deterministic-primitives.d.ts +59 -0
- package/dist/deterministic-primitives.js +126 -0
- package/dist/deterministic-session.d.ts +197 -0
- package/dist/deterministic-session.js +1401 -0
- package/dist/ecs-lite.d.ts +26 -0
- package/dist/ecs-lite.js +152 -0
- package/dist/effects-adapter.d.ts +21 -0
- package/dist/effects-adapter.js +94 -0
- package/dist/engine-complete.d.ts +45 -0
- package/dist/engine-complete.js +2292 -0
- package/dist/engine-core-proof.d.ts +26 -0
- package/dist/engine-core-proof.js +66 -0
- package/dist/engine-parity-matrix.d.ts +300 -0
- package/dist/engine-parity-matrix.js +869 -0
- package/dist/engine-parity.d.ts +74 -0
- package/dist/engine-parity.js +3178 -0
- package/dist/engine-runtime.d.ts +351 -0
- package/dist/engine-runtime.js +3123 -0
- package/dist/errors.d.ts +11 -0
- package/dist/errors.js +17 -0
- package/dist/events.d.ts +45 -0
- package/dist/events.js +242 -0
- package/dist/examples/counter-duel.d.ts +43 -0
- package/dist/examples/counter-duel.js +150 -0
- package/dist/examples/fixed-arena.d.ts +110 -0
- package/dist/examples/fixed-arena.js +356 -0
- package/dist/index.d.ts +101 -0
- package/dist/index.js +66 -0
- package/dist/input-authority.d.ts +82 -0
- package/dist/input-authority.js +147 -0
- package/dist/input-button.d.ts +36 -0
- package/dist/input-button.js +249 -0
- package/dist/input-timeline.d.ts +65 -0
- package/dist/input-timeline.js +412 -0
- package/dist/instant-replay.d.ts +59 -0
- package/dist/instant-replay.js +62 -0
- package/dist/lag-compensation3d.d.ts +146 -0
- package/dist/lag-compensation3d.js +827 -0
- package/dist/local-authority-server-runner.d.ts +79 -0
- package/dist/local-authority-server-runner.js +1118 -0
- package/dist/local-authority-wire.d.ts +142 -0
- package/dist/local-authority-wire.js +1477 -0
- package/dist/local-authority.d.ts +160 -0
- package/dist/local-authority.js +810 -0
- package/dist/local-ws-adapter.d.ts +14 -0
- package/dist/local-ws-adapter.js +146 -0
- package/dist/match-log.d.ts +74 -0
- package/dist/match-log.js +57 -0
- package/dist/math.d.ts +41 -0
- package/dist/math.js +154 -0
- package/dist/mock-network-adapter.d.ts +13 -0
- package/dist/mock-network-adapter.js +23 -0
- package/dist/movement.d.ts +155 -0
- package/dist/movement.js +694 -0
- package/dist/movement3d.d.ts +195 -0
- package/dist/movement3d.js +1238 -0
- package/dist/multiclient-authority.d.ts +30 -0
- package/dist/multiclient-authority.js +305 -0
- package/dist/multiplayer-service.d.ts +153 -0
- package/dist/multiplayer-service.js +429 -0
- package/dist/navigation.d.ts +91 -0
- package/dist/navigation.js +338 -0
- package/dist/navmesh.d.ts +236 -0
- package/dist/navmesh.js +1423 -0
- package/dist/networked-client.d.ts +124 -0
- package/dist/networked-client.js +688 -0
- package/dist/networked-input-authority.d.ts +51 -0
- package/dist/networked-input-authority.js +439 -0
- package/dist/node.d.ts +22 -0
- package/dist/node.js +19 -0
- package/dist/number-lab.d.ts +15 -0
- package/dist/number-lab.js +75 -0
- package/dist/offline-session.d.ts +2 -0
- package/dist/offline-session.js +367 -0
- package/dist/pause-resume.d.ts +48 -0
- package/dist/pause-resume.js +40 -0
- package/dist/physics-cert.d.ts +40 -0
- package/dist/physics-cert.js +389 -0
- package/dist/physics2d.d.ts +142 -0
- package/dist/physics2d.js +741 -0
- package/dist/physics3d.d.ts +285 -0
- package/dist/physics3d.js +1979 -0
- package/dist/prediction-culling.d.ts +34 -0
- package/dist/prediction-culling.js +200 -0
- package/dist/protocol-lab.d.ts +115 -0
- package/dist/protocol-lab.js +1295 -0
- package/dist/r3f-render-adapter.d.ts +61 -0
- package/dist/r3f-render-adapter.js +203 -0
- package/dist/random.d.ts +13 -0
- package/dist/random.js +55 -0
- package/dist/replay-bundle.d.ts +150 -0
- package/dist/replay-bundle.js +1586 -0
- package/dist/replay-inspect.d.ts +60 -0
- package/dist/replay-inspect.js +228 -0
- package/dist/replay-scoring.d.ts +28 -0
- package/dist/replay-scoring.js +65 -0
- package/dist/replay.d.ts +17 -0
- package/dist/replay.js +351 -0
- package/dist/reports.d.ts +176 -0
- package/dist/reports.js +174 -0
- package/dist/rollback-history.d.ts +46 -0
- package/dist/rollback-history.js +247 -0
- package/dist/runtime-guards.d.ts +1 -0
- package/dist/runtime-guards.js +108 -0
- package/dist/sample-lab.d.ts +32 -0
- package/dist/sample-lab.js +134 -0
- package/dist/sample-scenes.d.ts +86 -0
- package/dist/sample-scenes.js +745 -0
- package/dist/schema-artifacts.d.ts +49 -0
- package/dist/schema-artifacts.js +356 -0
- package/dist/schema-codegen.d.ts +21 -0
- package/dist/schema-codegen.js +538 -0
- package/dist/schema-dsl-binary.d.ts +75 -0
- package/dist/schema-dsl-binary.js +648 -0
- package/dist/schema.d.ts +87 -0
- package/dist/schema.js +315 -0
- package/dist/sdk-offline.d.ts +34 -0
- package/dist/sdk-offline.js +96 -0
- package/dist/session-promotion.d.ts +26 -0
- package/dist/session-promotion.js +70 -0
- package/dist/session-snapshot.d.ts +95 -0
- package/dist/session-snapshot.js +255 -0
- package/dist/session-wire.d.ts +89 -0
- package/dist/session-wire.js +211 -0
- package/dist/signals.d.ts +31 -0
- package/dist/signals.js +99 -0
- package/dist/sparse-set.d.ts +34 -0
- package/dist/sparse-set.js +165 -0
- package/dist/synctest.d.ts +31 -0
- package/dist/synctest.js +133 -0
- package/dist/system-lifecycle.d.ts +72 -0
- package/dist/system-lifecycle.js +281 -0
- package/dist/timers.d.ts +17 -0
- package/dist/timers.js +53 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.js +4 -0
- package/dist/tools/static-checker.d.ts +31 -0
- package/dist/tools/static-checker.js +1462 -0
- package/dist/tools/vite-plugin.d.ts +69 -0
- package/dist/tools/vite-plugin.js +203 -0
- package/dist/types.d.ts +148 -0
- package/dist/types.js +1 -0
- package/dist/venus-mp-budget.d.ts +29 -0
- package/dist/venus-mp-budget.js +122 -0
- package/dist/ws-frame.d.ts +49 -0
- package/dist/ws-frame.js +247 -0
- package/package.json +169 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.canonicalize = canonicalize;
|
|
4
|
+
exports.canonicalStringify = canonicalStringify;
|
|
5
|
+
exports.cloneCanonical = cloneCanonical;
|
|
6
|
+
exports.decodeCanonicalValue = decodeCanonicalValue;
|
|
7
|
+
exports.defaultChecksum = defaultChecksum;
|
|
8
|
+
exports.encodeCanonicalBytes = encodeCanonicalBytes;
|
|
9
|
+
exports.decodeCanonicalBytes = decodeCanonicalBytes;
|
|
10
|
+
exports.encodeUtf8 = encodeUtf8;
|
|
11
|
+
exports.decodeUtf8 = decodeUtf8;
|
|
12
|
+
const errors_js_1 = require("./errors.js");
|
|
13
|
+
const reservedTag = '$rdm';
|
|
14
|
+
function canonicalize(value) {
|
|
15
|
+
return canonicalizeValue(value, new WeakSet());
|
|
16
|
+
}
|
|
17
|
+
function canonicalStringify(value) {
|
|
18
|
+
return JSON.stringify(canonicalize(value));
|
|
19
|
+
}
|
|
20
|
+
function cloneCanonical(value) {
|
|
21
|
+
return decodeCanonical(JSON.parse(canonicalStringify(value)));
|
|
22
|
+
}
|
|
23
|
+
function decodeCanonicalValue(value) {
|
|
24
|
+
return decodeCanonical(value);
|
|
25
|
+
}
|
|
26
|
+
function defaultChecksum(value) {
|
|
27
|
+
return fnv1a64(canonicalStringify(value));
|
|
28
|
+
}
|
|
29
|
+
function encodeCanonicalBytes(value) {
|
|
30
|
+
return encodeUtf8(canonicalStringify(value));
|
|
31
|
+
}
|
|
32
|
+
function decodeCanonicalBytes(bytes) {
|
|
33
|
+
return decodeCanonical(JSON.parse(decodeUtf8(bytes)));
|
|
34
|
+
}
|
|
35
|
+
function encodeUtf8(source) {
|
|
36
|
+
if (typeof TextEncoder !== 'undefined') {
|
|
37
|
+
return new TextEncoder().encode(source);
|
|
38
|
+
}
|
|
39
|
+
if (typeof Buffer !== 'undefined') {
|
|
40
|
+
return Uint8Array.from(Buffer.from(source, 'utf8'));
|
|
41
|
+
}
|
|
42
|
+
throw new errors_js_1.SyncplayError('No UTF-8 encoder is available in this runtime', {
|
|
43
|
+
code: 'canonical.utf8-encoder',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function decodeUtf8(bytes) {
|
|
47
|
+
if (typeof TextDecoder !== 'undefined') {
|
|
48
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
49
|
+
}
|
|
50
|
+
if (typeof Buffer !== 'undefined') {
|
|
51
|
+
return Buffer.from(bytes).toString('utf8');
|
|
52
|
+
}
|
|
53
|
+
throw new errors_js_1.SyncplayError('No UTF-8 decoder is available in this runtime', {
|
|
54
|
+
code: 'canonical.utf8-decoder',
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Recognize an already-canonical sentinel tag and return it (with container
|
|
59
|
+
* contents re-canonicalized), or undefined when the record is NOT a
|
|
60
|
+
* well-formed tag — the caller then rejects the reserved key as usual.
|
|
61
|
+
*/
|
|
62
|
+
function passThroughCanonicalTag(record, seen) {
|
|
63
|
+
const tag = record[reservedTag];
|
|
64
|
+
// rdm-ignore-next-line determinism/no-object-key-order: keys are used only for an order-independent count and membership check
|
|
65
|
+
const keys = Object.keys(record);
|
|
66
|
+
if ((tag === 'nan' || tag === 'infinity' || tag === 'negative-infinity' || tag === 'negative-zero' || tag === 'undefined')
|
|
67
|
+
&& keys.length === 1) {
|
|
68
|
+
return { [reservedTag]: tag };
|
|
69
|
+
}
|
|
70
|
+
if (tag === 'bigint' && keys.length === 2 && typeof record.value === 'string') {
|
|
71
|
+
return { [reservedTag]: 'bigint', value: record.value };
|
|
72
|
+
}
|
|
73
|
+
if (tag === 'typed-array' && keys.length === 3 && typeof record.constructor === 'string' && Array.isArray(record.bytes)
|
|
74
|
+
&& record.bytes.every((byte) => typeof byte === 'number' && Number.isInteger(byte) && byte >= 0 && byte <= 255)) {
|
|
75
|
+
return { [reservedTag]: 'typed-array', constructor: record.constructor, bytes: [...record.bytes] };
|
|
76
|
+
}
|
|
77
|
+
if (tag === 'map' && keys.length === 2 && Array.isArray(record.entries)
|
|
78
|
+
&& record.entries.every((entry) => Array.isArray(entry) && entry.length === 2)) {
|
|
79
|
+
const entries = record.entries.map((entry) => {
|
|
80
|
+
const pair = entry;
|
|
81
|
+
return [canonicalizeValue(pair[0], seen), canonicalizeValue(pair[1], seen)];
|
|
82
|
+
});
|
|
83
|
+
return { [reservedTag]: 'map', entries };
|
|
84
|
+
}
|
|
85
|
+
if (tag === 'set' && keys.length === 2 && Array.isArray(record.values)) {
|
|
86
|
+
return { [reservedTag]: 'set', values: record.values.map((item) => canonicalizeValue(item, seen)) };
|
|
87
|
+
}
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
function canonicalizeValue(value, seen) {
|
|
91
|
+
if (value === null) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
if (typeof value === 'boolean' || typeof value === 'string') {
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
if (typeof value === 'number') {
|
|
98
|
+
if (Number.isNaN(value)) {
|
|
99
|
+
return { [reservedTag]: 'nan' };
|
|
100
|
+
}
|
|
101
|
+
if (value === Infinity) {
|
|
102
|
+
return { [reservedTag]: 'infinity' };
|
|
103
|
+
}
|
|
104
|
+
if (value === -Infinity) {
|
|
105
|
+
return { [reservedTag]: 'negative-infinity' };
|
|
106
|
+
}
|
|
107
|
+
if (Object.is(value, -0)) {
|
|
108
|
+
return { [reservedTag]: 'negative-zero' };
|
|
109
|
+
}
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
if (typeof value === 'bigint') {
|
|
113
|
+
return { [reservedTag]: 'bigint', value: value.toString() };
|
|
114
|
+
}
|
|
115
|
+
if (value === undefined) {
|
|
116
|
+
return { [reservedTag]: 'undefined' };
|
|
117
|
+
}
|
|
118
|
+
if (typeof value === 'function' || typeof value === 'symbol') {
|
|
119
|
+
throw new errors_js_1.SyncplayError('Functions and symbols are not deterministic state values', {
|
|
120
|
+
code: 'canonical.unsupported-value',
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if (seen.has(value)) {
|
|
124
|
+
throw new errors_js_1.SyncplayError('Cyclic deterministic state is not supported', {
|
|
125
|
+
code: 'canonical.cycle',
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
seen.add(value);
|
|
129
|
+
if (Array.isArray(value)) {
|
|
130
|
+
const result = value.map((item) => canonicalizeValue(item, seen));
|
|
131
|
+
seen.delete(value);
|
|
132
|
+
return result;
|
|
133
|
+
}
|
|
134
|
+
if (ArrayBuffer.isView(value)) {
|
|
135
|
+
const typedArray = value;
|
|
136
|
+
const bytes = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);
|
|
137
|
+
const result = {
|
|
138
|
+
[reservedTag]: 'typed-array',
|
|
139
|
+
constructor: typedArray.constructor.name,
|
|
140
|
+
bytes: Array.from(bytes),
|
|
141
|
+
};
|
|
142
|
+
seen.delete(value);
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
if (value instanceof Map) {
|
|
146
|
+
const entries = Array.from(value.entries()).map(([entryKey, entryValue]) => {
|
|
147
|
+
const key = canonicalizeValue(entryKey, seen);
|
|
148
|
+
return [key, canonicalizeValue(entryValue, seen)];
|
|
149
|
+
});
|
|
150
|
+
entries.sort((a, b) => canonicalCompare(a[0], b[0]));
|
|
151
|
+
seen.delete(value);
|
|
152
|
+
return { [reservedTag]: 'map', entries };
|
|
153
|
+
}
|
|
154
|
+
if (value instanceof Set) {
|
|
155
|
+
const values = Array.from(value.values()).map((item) => canonicalizeValue(item, seen));
|
|
156
|
+
values.sort(canonicalCompare);
|
|
157
|
+
seen.delete(value);
|
|
158
|
+
return { [reservedTag]: 'set', values };
|
|
159
|
+
}
|
|
160
|
+
if (Object.getPrototypeOf(value) !== Object.prototype) {
|
|
161
|
+
seen.delete(value);
|
|
162
|
+
throw new errors_js_1.SyncplayError('Class instances and built-ins require explicit serializers', {
|
|
163
|
+
code: 'canonical.class-instance',
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
const record = value;
|
|
167
|
+
if (Object.prototype.hasOwnProperty.call(record, reservedTag)) {
|
|
168
|
+
// Idempotency: a WELL-FORMED sentinel tag is an already-canonical value
|
|
169
|
+
// (e.g. checksumming a canonicalizeState projection re-enters canonicalize
|
|
170
|
+
// with `{$rdm:'negative-zero'}` objects — a -0 state field must not make
|
|
171
|
+
// getChecksum throw every frame). Container tags re-canonicalize their
|
|
172
|
+
// contents (a no-op when truly canonical). Anything else with the reserved
|
|
173
|
+
// key is still rejected — user state cannot squat on `$rdm`.
|
|
174
|
+
const passedThrough = passThroughCanonicalTag(record, seen);
|
|
175
|
+
if (passedThrough !== undefined) {
|
|
176
|
+
seen.delete(value);
|
|
177
|
+
return passedThrough;
|
|
178
|
+
}
|
|
179
|
+
seen.delete(value);
|
|
180
|
+
throw new errors_js_1.SyncplayError(`State objects cannot use reserved key ${reservedTag}`, {
|
|
181
|
+
code: 'canonical.reserved-key',
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
const result = {};
|
|
185
|
+
for (const key of Object.keys(record).sort(compareUniqueStrings)) {
|
|
186
|
+
result[key] = canonicalizeValue(record[key], seen);
|
|
187
|
+
}
|
|
188
|
+
seen.delete(value);
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
function decodeCanonical(value) {
|
|
192
|
+
if (value === null || typeof value === 'boolean' || typeof value === 'string' || typeof value === 'number') {
|
|
193
|
+
return value;
|
|
194
|
+
}
|
|
195
|
+
if (Array.isArray(value)) {
|
|
196
|
+
return value.map((item) => decodeCanonical(item));
|
|
197
|
+
}
|
|
198
|
+
const record = value;
|
|
199
|
+
const tag = record[reservedTag];
|
|
200
|
+
if (typeof tag === 'string') {
|
|
201
|
+
if (tag === 'nan') {
|
|
202
|
+
return Number.NaN;
|
|
203
|
+
}
|
|
204
|
+
if (tag === 'infinity') {
|
|
205
|
+
return Infinity;
|
|
206
|
+
}
|
|
207
|
+
if (tag === 'negative-infinity') {
|
|
208
|
+
return -Infinity;
|
|
209
|
+
}
|
|
210
|
+
if (tag === 'negative-zero') {
|
|
211
|
+
return -0;
|
|
212
|
+
}
|
|
213
|
+
if (tag === 'undefined') {
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
if (tag === 'bigint') {
|
|
217
|
+
return BigInt(record.value);
|
|
218
|
+
}
|
|
219
|
+
if (tag === 'map') {
|
|
220
|
+
const entries = record.entries;
|
|
221
|
+
return new Map(entries.map(([entryKey, entryValue]) => [decodeCanonical(entryKey), decodeCanonical(entryValue)]));
|
|
222
|
+
}
|
|
223
|
+
if (tag === 'set') {
|
|
224
|
+
const values = record.values;
|
|
225
|
+
return new Set(values.map((item) => decodeCanonical(item)));
|
|
226
|
+
}
|
|
227
|
+
if (tag === 'typed-array') {
|
|
228
|
+
return decodeTypedArray(record);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const result = {};
|
|
232
|
+
for (const key of Object.keys(record).sort(compareUniqueStrings)) {
|
|
233
|
+
result[key] = decodeCanonical(record[key]);
|
|
234
|
+
}
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
function compareUniqueStrings(left, right) {
|
|
238
|
+
return left < right ? -1 : 1;
|
|
239
|
+
}
|
|
240
|
+
function decodeTypedArray(record) {
|
|
241
|
+
const constructorName = record.constructor;
|
|
242
|
+
if (typeof constructorName !== 'string') {
|
|
243
|
+
throw new errors_js_1.SyncplayError('Typed array canonical value is missing a constructor name', {
|
|
244
|
+
code: 'canonical.invalid-typed-array',
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
const bytes = Uint8Array.from(record.bytes);
|
|
248
|
+
const buffer = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
249
|
+
switch (constructorName) {
|
|
250
|
+
case 'Int8Array':
|
|
251
|
+
return new Int8Array(buffer);
|
|
252
|
+
case 'Uint8Array':
|
|
253
|
+
return new Uint8Array(buffer);
|
|
254
|
+
case 'Uint8ClampedArray':
|
|
255
|
+
return new Uint8ClampedArray(buffer);
|
|
256
|
+
case 'Int16Array':
|
|
257
|
+
return new Int16Array(buffer);
|
|
258
|
+
case 'Uint16Array':
|
|
259
|
+
return new Uint16Array(buffer);
|
|
260
|
+
case 'Int32Array':
|
|
261
|
+
return new Int32Array(buffer);
|
|
262
|
+
case 'Uint32Array':
|
|
263
|
+
return new Uint32Array(buffer);
|
|
264
|
+
case 'Float32Array':
|
|
265
|
+
return new Float32Array(buffer);
|
|
266
|
+
case 'Float64Array':
|
|
267
|
+
return new Float64Array(buffer);
|
|
268
|
+
case 'BigInt64Array':
|
|
269
|
+
return new BigInt64Array(buffer);
|
|
270
|
+
case 'BigUint64Array':
|
|
271
|
+
return new BigUint64Array(buffer);
|
|
272
|
+
case 'DataView':
|
|
273
|
+
return new DataView(buffer);
|
|
274
|
+
default:
|
|
275
|
+
throw new errors_js_1.SyncplayError(`Unsupported typed array constructor: ${constructorName}`, {
|
|
276
|
+
code: 'canonical.unsupported-typed-array',
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function canonicalCompare(a, b) {
|
|
281
|
+
const aText = JSON.stringify(a);
|
|
282
|
+
const bText = JSON.stringify(b);
|
|
283
|
+
if (aText < bText) {
|
|
284
|
+
return -1;
|
|
285
|
+
}
|
|
286
|
+
if (aText > bText) {
|
|
287
|
+
return 1;
|
|
288
|
+
}
|
|
289
|
+
return 0;
|
|
290
|
+
}
|
|
291
|
+
function fnv1a64(value) {
|
|
292
|
+
let hash = 0xcbf29ce484222325n;
|
|
293
|
+
const prime = 0x100000001b3n;
|
|
294
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
295
|
+
hash ^= BigInt(value.charCodeAt(index));
|
|
296
|
+
hash = BigInt.asUintN(64, hash * prime);
|
|
297
|
+
}
|
|
298
|
+
return hash.toString(16).padStart(16, '0');
|
|
299
|
+
}
|