@elaraai/east 1.0.45 → 1.0.46
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/src/containers/sortedmap.d.ts +22 -0
- package/dist/src/containers/sortedmap.d.ts.map +1 -1
- package/dist/src/containers/sortedmap.js +31 -2
- package/dist/src/containers/sortedmap.js.map +1 -1
- package/dist/src/containers/sortedset.d.ts +22 -0
- package/dist/src/containers/sortedset.d.ts.map +1 -1
- package/dist/src/containers/sortedset.js +31 -2
- package/dist/src/containers/sortedset.js.map +1 -1
- package/dist/src/expr/blob.d.ts +6 -1
- package/dist/src/expr/blob.d.ts.map +1 -1
- package/dist/src/expr/blob.js +6 -1
- package/dist/src/expr/blob.js.map +1 -1
- package/dist/src/expr/libs/blob.d.ts +10 -1
- package/dist/src/expr/libs/blob.d.ts.map +1 -1
- package/dist/src/expr/libs/blob.js +10 -1
- package/dist/src/expr/libs/blob.js.map +1 -1
- package/dist/src/fuzz.d.ts.map +1 -1
- package/dist/src/fuzz.js +11 -2
- package/dist/src/fuzz.js.map +1 -1
- package/dist/src/serialization/beast2/index.d.ts +76 -22
- package/dist/src/serialization/beast2/index.d.ts.map +1 -1
- package/dist/src/serialization/beast2/index.js +87 -720
- package/dist/src/serialization/beast2/index.js.map +1 -1
- package/dist/src/serialization/beast2/index.spec.js +147 -4
- package/dist/src/serialization/beast2/index.spec.js.map +1 -1
- package/dist/src/serialization/beast2/shared.d.ts +79 -0
- package/dist/src/serialization/beast2/shared.d.ts.map +1 -0
- package/dist/src/serialization/beast2/shared.js +143 -0
- package/dist/src/serialization/beast2/shared.js.map +1 -0
- package/dist/src/serialization/beast2/v4/container.d.ts +67 -0
- package/dist/src/serialization/beast2/v4/container.d.ts.map +1 -0
- package/dist/src/serialization/beast2/v4/container.js +727 -0
- package/dist/src/serialization/beast2/v4/container.js.map +1 -0
- package/dist/src/serialization/beast2/{sourcemap-table.d.ts → v4/sourcemap-table.d.ts} +2 -2
- package/dist/src/serialization/beast2/v4/sourcemap-table.d.ts.map +1 -0
- package/dist/src/serialization/beast2/{sourcemap-table.js → v4/sourcemap-table.js} +2 -2
- package/dist/src/serialization/beast2/v4/sourcemap-table.js.map +1 -0
- package/dist/src/serialization/beast2/{string-table.d.ts → v4/string-table.d.ts} +1 -1
- package/dist/src/serialization/beast2/v4/string-table.d.ts.map +1 -0
- package/dist/src/serialization/beast2/{string-table.js → v4/string-table.js} +1 -1
- package/dist/src/serialization/beast2/v4/string-table.js.map +1 -0
- package/dist/src/serialization/beast2/{type-table.d.ts → v4/type-table.d.ts} +6 -4
- package/dist/src/serialization/beast2/v4/type-table.d.ts.map +1 -0
- package/dist/src/serialization/beast2/{type-table.js → v4/type-table.js} +103 -10
- package/dist/src/serialization/beast2/v4/type-table.js.map +1 -0
- package/dist/src/serialization/beast2/{value-table.d.ts → v4/value-table.d.ts} +2 -2
- package/dist/src/serialization/beast2/v4/value-table.d.ts.map +1 -0
- package/dist/src/serialization/beast2/{value-table.js → v4/value-table.js} +3 -3
- package/dist/src/serialization/beast2/v4/value-table.js.map +1 -0
- package/dist/src/serialization/beast2/v5/codec.d.ts +213 -0
- package/dist/src/serialization/beast2/v5/codec.d.ts.map +1 -0
- package/dist/src/serialization/beast2/v5/codec.js +954 -0
- package/dist/src/serialization/beast2/v5/codec.js.map +1 -0
- package/dist/src/serialization/beast2/v5/deflate.d.ts +16 -0
- package/dist/src/serialization/beast2/v5/deflate.d.ts.map +1 -0
- package/dist/src/serialization/beast2/v5/deflate.js +172 -0
- package/dist/src/serialization/beast2/v5/deflate.js.map +1 -0
- package/dist/src/serialization/beast2/v5/frames.d.ts +150 -0
- package/dist/src/serialization/beast2/v5/frames.d.ts.map +1 -0
- package/dist/src/serialization/beast2/v5/frames.js +284 -0
- package/dist/src/serialization/beast2/v5/frames.js.map +1 -0
- package/dist/src/serialization/beast2/v5/index.spec.d.ts +6 -0
- package/dist/src/serialization/beast2/v5/index.spec.d.ts.map +1 -0
- package/dist/src/serialization/beast2/v5/index.spec.js +484 -0
- package/dist/src/serialization/beast2/v5/index.spec.js.map +1 -0
- package/dist/src/serialization/beast2/v5/stream.d.ts +177 -0
- package/dist/src/serialization/beast2/v5/stream.d.ts.map +1 -0
- package/dist/src/serialization/beast2/v5/stream.js +447 -0
- package/dist/src/serialization/beast2/v5/stream.js.map +1 -0
- package/dist/src/serialization/beast2/v5/type-section.d.ts +81 -0
- package/dist/src/serialization/beast2/v5/type-section.d.ts.map +1 -0
- package/dist/src/serialization/beast2/v5/type-section.js +211 -0
- package/dist/src/serialization/beast2/v5/type-section.js.map +1 -0
- package/dist/src/serialization/beast2/version.d.ts +40 -0
- package/dist/src/serialization/beast2/version.d.ts.map +1 -0
- package/dist/src/serialization/beast2/version.js +23 -0
- package/dist/src/serialization/beast2/version.js.map +1 -0
- package/dist/src/serialization/index.d.ts +1 -1
- package/dist/src/serialization/index.d.ts.map +1 -1
- package/dist/src/serialization/index.js +1 -1
- package/dist/src/serialization/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/src/serialization/beast2/sourcemap-table.d.ts.map +0 -1
- package/dist/src/serialization/beast2/sourcemap-table.js.map +0 -1
- package/dist/src/serialization/beast2/string-table.d.ts.map +0 -1
- package/dist/src/serialization/beast2/string-table.js.map +0 -1
- package/dist/src/serialization/beast2/type-table.d.ts.map +0 -1
- package/dist/src/serialization/beast2/type-table.js.map +0 -1
- package/dist/src/serialization/beast2/value-table.d.ts.map +0 -1
- package/dist/src/serialization/beast2/value-table.js.map +0 -1
|
@@ -3,696 +3,101 @@
|
|
|
3
3
|
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
|
-
* Beast2
|
|
6
|
+
* Beast2 container — version-agnostic public entry points.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* Functions: IR encoded directly — EastTypeType schema positions auto-emit type table indices.
|
|
13
|
-
*
|
|
14
|
-
* See devdocs/BEAST2.md for the full specification.
|
|
8
|
+
* Decoders dispatch on the magic's version byte (`v4` = 0x04, `v5` = 0x05) so
|
|
9
|
+
* every entry point accepts blobs of either container version. Encoders write
|
|
10
|
+
* the v4 container by default. See `SPEC.md` for the magic registry and
|
|
11
|
+
* version policy, `v4/SPEC.md` and `v5/SPEC.md` for the wire formats.
|
|
15
12
|
*/
|
|
16
13
|
import { toEastTypeValue } from "../../type_of_type.js";
|
|
17
|
-
import { isVariant
|
|
18
|
-
import { BufferWriter, BufferReader } from "../binary-utils.js";
|
|
19
|
-
import { ref } from "../../containers/ref.js";
|
|
20
|
-
import { matrix } from "../../containers/matrix.js";
|
|
21
|
-
import { EAST_IR_SYMBOL, EAST_CAPTURES_SYMBOL, EAST_SOURCE_MAP_SYMBOL, ReturnException, compile_internal } from "../../compile.js";
|
|
22
|
-
import { InternalError } from "../../error.js";
|
|
14
|
+
import { isVariant } from "../../containers/variant.js";
|
|
23
15
|
import { IRType } from "../../ir.js";
|
|
24
16
|
import { EastIR, AsyncEastIR } from "../../eastir.js";
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
17
|
+
import {} from "./shared.js";
|
|
18
|
+
import { MAGIC_BYTES, encodeBeast2V4For, decodeBeast2V4For, decodeBeast2V4, decodeIRWithSourceMapV4, } from "./v4/container.js";
|
|
19
|
+
import { encodeBeast2V5For, decodeBeast2V5For, decodeBeast2V5ForAsync, decodeBeast2V5, decodeIRWithSourceMapV5, } from "./v5/codec.js";
|
|
20
|
+
import { BEAST2_WRITE_VERSION } from "./version.js";
|
|
21
|
+
export { MAGIC_BYTES } from "./v4/container.js";
|
|
22
|
+
export { MAGIC_BYTES_V5 } from "./v5/codec.js";
|
|
23
|
+
export { Beast2Writer, encodeBeast2SegmentsFor, iterBeast2SegmentsFor, Beast2Pages, openBeast2PagesFor, } from "./v5/stream.js";
|
|
24
|
+
// =============================================================================
|
|
25
|
+
// Magic dispatch
|
|
26
|
+
// =============================================================================
|
|
27
|
+
export { BEAST2_WRITE_VERSION, BEAST2_READ_VERSIONS } from "./version.js";
|
|
33
28
|
/**
|
|
34
|
-
*
|
|
35
|
-
* with no compiled IR, for the "no IR attached" diagnostic.
|
|
29
|
+
* Sniffs the container version from a blob's magic bytes.
|
|
36
30
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* (`typeof`, `Object.prototype.toString`) or guarded, so the diagnostic can never
|
|
42
|
-
* throw and mask the real failure.
|
|
43
|
-
*
|
|
44
|
-
* @param value - the value found where an East function with IR was expected
|
|
45
|
-
* @returns a single-line, length-bounded description
|
|
31
|
+
* @param data - the blob to inspect
|
|
32
|
+
* @returns the container version (4 or 5)
|
|
33
|
+
* @throws {Error} When the data is too short, the magic prefix is wrong, or
|
|
34
|
+
* the version byte is unknown.
|
|
46
35
|
*/
|
|
47
|
-
function
|
|
48
|
-
const kind = typeof value; // total — never throws
|
|
49
|
-
const tag = Object.prototype.toString.call(value); // safe [[Class]]; no user code
|
|
50
|
-
const parts = [`typeof=${kind}`, `tag=${tag}`];
|
|
51
|
-
try {
|
|
52
|
-
if (kind === "function") {
|
|
53
|
-
const name = value.name;
|
|
54
|
-
if (typeof name === "string" && name)
|
|
55
|
-
parts.push(`name=${name}`);
|
|
56
|
-
// Built-in toString (not the possibly-overridden value.toString) → the source text.
|
|
57
|
-
const src = Function.prototype.toString.call(value).replace(/\s+/g, " ");
|
|
58
|
-
parts.push(`source=${src.length > 160 ? `${src.slice(0, 160)}…` : src}`);
|
|
59
|
-
parts.push(`hasCaptures=${value[EAST_CAPTURES_SYMBOL] !== undefined}`);
|
|
60
|
-
parts.push(`hasSourceMap=${value[EAST_SOURCE_MAP_SYMBOL] !== undefined}`);
|
|
61
|
-
}
|
|
62
|
-
else if (value !== null && value !== undefined) {
|
|
63
|
-
const ctorName = value.constructor?.name;
|
|
64
|
-
if (typeof ctorName === "string")
|
|
65
|
-
parts.push(`constructor=${ctorName}`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
catch {
|
|
69
|
-
parts.push("(preview unavailable)");
|
|
70
|
-
}
|
|
71
|
-
return parts.join(" ");
|
|
72
|
-
}
|
|
73
|
-
// =============================================================================
|
|
74
|
-
// Magic bytes (v2: last byte = 0x02)
|
|
75
|
-
// =============================================================================
|
|
76
|
-
export const MAGIC_BYTES = new Uint8Array([0x89, 0x45, 0x61, 0x73, 0x74, 0x0D, 0x0A, 0x04]);
|
|
77
|
-
function verifyMagic(data) {
|
|
36
|
+
function sniffVersion(data) {
|
|
78
37
|
if (data.length < 8) {
|
|
79
38
|
throw new Error(`Data too short for Beast2 format: ${data.length} bytes`);
|
|
80
39
|
}
|
|
81
|
-
for (let i = 0; i <
|
|
40
|
+
for (let i = 0; i < 7; i++) {
|
|
82
41
|
if (data[i] !== MAGIC_BYTES[i]) {
|
|
83
|
-
|
|
84
|
-
throw new Error(`Invalid Beast2 magic at offset ${i}: expected 0x${MAGIC_BYTES[i].toString(16)}, got 0x${data[i].toString(16)}`);
|
|
85
|
-
throw new Error(`Unknown Beast2 version: 0x${data[i].toString(16)}`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
// =============================================================================
|
|
90
|
-
// Value encoder factory
|
|
91
|
-
// =============================================================================
|
|
92
|
-
/**
|
|
93
|
-
* Build a value encoder closure tree for the given type.
|
|
94
|
-
* The tree is built once and reused for every encode call.
|
|
95
|
-
*/
|
|
96
|
-
function buildEncoder(type, typeCtx = new Map()) {
|
|
97
|
-
switch (type.type) {
|
|
98
|
-
case "Never":
|
|
99
|
-
return () => { throw new Error("Cannot encode value of type Never"); };
|
|
100
|
-
case "Null":
|
|
101
|
-
return () => { };
|
|
102
|
-
case "Boolean":
|
|
103
|
-
return (value, writer) => writer.writeUint8(value ? 1 : 0);
|
|
104
|
-
case "Integer":
|
|
105
|
-
return (value, writer) => writer.writeZigzag(value);
|
|
106
|
-
case "Float":
|
|
107
|
-
return (value, writer) => writer.writeFloat64LE(value);
|
|
108
|
-
case "String":
|
|
109
|
-
return (value, writer, ctx) => {
|
|
110
|
-
let idx = ctx.stringTable.get(value);
|
|
111
|
-
if (idx === undefined) {
|
|
112
|
-
idx = ctx.stringTable.size;
|
|
113
|
-
ctx.stringTable.set(value, idx);
|
|
114
|
-
}
|
|
115
|
-
writer.writeVarint(idx);
|
|
116
|
-
};
|
|
117
|
-
case "DateTime":
|
|
118
|
-
return (value, writer) => writer.writeZigzag(BigInt(value.valueOf()));
|
|
119
|
-
case "Blob":
|
|
120
|
-
return (value, writer) => {
|
|
121
|
-
writer.writeVarint(value.length);
|
|
122
|
-
writer.writeBytes(value);
|
|
123
|
-
};
|
|
124
|
-
case "Ref":
|
|
125
|
-
case "Array":
|
|
126
|
-
case "Set":
|
|
127
|
-
case "Dict": {
|
|
128
|
-
// v4: all mutable containers are in the value table, encoded as varint(index)
|
|
129
|
-
return (value, writer, ctx) => {
|
|
130
|
-
const idx = ctx.indexMap.get(value);
|
|
131
|
-
if (idx === undefined)
|
|
132
|
-
throw new InternalError(`Mutable ${type.type} not found in value table during encode`);
|
|
133
|
-
writer.writeVarint(idx);
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
case "Struct": {
|
|
137
|
-
const fieldEncoders = [];
|
|
138
|
-
const ret = (value, writer, ctx) => {
|
|
139
|
-
for (const [name, enc] of fieldEncoders)
|
|
140
|
-
enc(value[name], writer, ctx);
|
|
141
|
-
};
|
|
142
|
-
for (const { name, type: fieldType } of type.value) {
|
|
143
|
-
fieldEncoders.push([name, buildEncoder(fieldType, typeCtx)]);
|
|
144
|
-
}
|
|
145
|
-
return ret;
|
|
146
|
-
}
|
|
147
|
-
case "Variant": {
|
|
148
|
-
const caseEncoders = {};
|
|
149
|
-
const caseTags = {};
|
|
150
|
-
const ret = (value, writer, ctx) => {
|
|
151
|
-
writer.writeVarint(caseTags[value.type]);
|
|
152
|
-
caseEncoders[value.type](value.value, writer, ctx);
|
|
153
|
-
};
|
|
154
|
-
for (let i = 0; i < type.value.length; i++) {
|
|
155
|
-
const { name, type: caseType } = type.value[i];
|
|
156
|
-
caseTags[name] = i;
|
|
157
|
-
caseEncoders[name] = buildEncoder(caseType, typeCtx);
|
|
158
|
-
}
|
|
159
|
-
return ret;
|
|
160
|
-
}
|
|
161
|
-
case "Recursive": {
|
|
162
|
-
if (type.value.type === "wrapper") {
|
|
163
|
-
let inner;
|
|
164
|
-
const ret = (value, writer, ctx) => inner(value, writer, ctx);
|
|
165
|
-
typeCtx.set(type.value.value.id, ret);
|
|
166
|
-
inner = buildEncoder(type.value.value.inner, typeCtx);
|
|
167
|
-
return ret;
|
|
168
|
-
}
|
|
169
|
-
const target = typeCtx.get(type.value.value);
|
|
170
|
-
if (!target)
|
|
171
|
-
throw new InternalError("Recursive type context not found during encoder build");
|
|
172
|
-
return target;
|
|
42
|
+
throw new Error(`Invalid Beast2 magic at offset ${i}: expected 0x${MAGIC_BYTES[i].toString(16)}, got 0x${data[i].toString(16)}`);
|
|
173
43
|
}
|
|
174
|
-
case "Function":
|
|
175
|
-
case "AsyncFunction": {
|
|
176
|
-
// Build IR encoder in the same typeCtx so recursive types resolve correctly
|
|
177
|
-
const fnIrEncoder = buildEncoder(irTypeValue, typeCtx);
|
|
178
|
-
const captureEncoderCache = new Map();
|
|
179
|
-
return (value, writer, ctx) => {
|
|
180
|
-
const ir = value[EAST_IR_SYMBOL];
|
|
181
|
-
if (!ir)
|
|
182
|
-
throw new Error(`Cannot serialize function: no IR attached (${describeNoIrValue(value)})`);
|
|
183
|
-
fnIrEncoder(ir, writer, ctx);
|
|
184
|
-
const captures = value[EAST_CAPTURES_SYMBOL];
|
|
185
|
-
const captureList = ir.value.captures;
|
|
186
|
-
writer.writeVarint(captureList.length);
|
|
187
|
-
for (const captureVar of captureList) {
|
|
188
|
-
const name = captureVar.value.name;
|
|
189
|
-
const captureType = captureVar.value.type;
|
|
190
|
-
if (!captures)
|
|
191
|
-
throw new InternalError("Function has captures but no EAST_CAPTURES_SYMBOL");
|
|
192
|
-
const entry = captures[name];
|
|
193
|
-
if (!entry)
|
|
194
|
-
throw new InternalError(`Capture '${name}' not found`);
|
|
195
|
-
let enc = captureEncoderCache.get(captureType);
|
|
196
|
-
if (!enc) {
|
|
197
|
-
enc = buildEncoder(captureType, typeCtx);
|
|
198
|
-
captureEncoderCache.set(captureType, enc);
|
|
199
|
-
}
|
|
200
|
-
enc(entry.value, writer, ctx);
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
case "Vector":
|
|
205
|
-
return (value, writer) => {
|
|
206
|
-
writer.writeVarint(value.length);
|
|
207
|
-
writer.writeBytes(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
|
|
208
|
-
};
|
|
209
|
-
case "Matrix":
|
|
210
|
-
return (value, writer) => {
|
|
211
|
-
writer.writeVarint(value.rows);
|
|
212
|
-
writer.writeVarint(value.cols);
|
|
213
|
-
writer.writeBytes(new Uint8Array(value.data.buffer, value.data.byteOffset, value.data.byteLength));
|
|
214
|
-
};
|
|
215
|
-
default:
|
|
216
|
-
throw new Error(`Unknown type: ${type.type}`);
|
|
217
44
|
}
|
|
45
|
+
const version = data[7];
|
|
46
|
+
if (version === 0x04)
|
|
47
|
+
return 4;
|
|
48
|
+
if (version === 0x05)
|
|
49
|
+
return 5;
|
|
50
|
+
throw new Error(`Unknown Beast2 version: 0x${version.toString(16)}`);
|
|
218
51
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Build a value decoder closure tree for the given type.
|
|
224
|
-
* The tree is built once and reused for every decode call.
|
|
225
|
-
*/
|
|
226
|
-
function buildDecoder(type, typeCtx = new Map()) {
|
|
227
|
-
switch (type.type) {
|
|
228
|
-
case "Never":
|
|
229
|
-
return () => { throw new Error("Cannot decode value of type Never"); };
|
|
230
|
-
case "Null":
|
|
231
|
-
return () => null;
|
|
232
|
-
case "Boolean":
|
|
233
|
-
return (reader) => reader.readBoolean();
|
|
234
|
-
case "Integer":
|
|
235
|
-
return (reader) => reader.readZigzag();
|
|
236
|
-
case "Float":
|
|
237
|
-
return (reader) => reader.readFloat64LE();
|
|
238
|
-
case "String":
|
|
239
|
-
return (reader, ctx) => {
|
|
240
|
-
const idx = reader.readVarint();
|
|
241
|
-
if (idx >= ctx.stringTable.length)
|
|
242
|
-
throw new Error(`String table index ${idx} out of bounds (table has ${ctx.stringTable.length} entries)`);
|
|
243
|
-
return ctx.stringTable[idx];
|
|
244
|
-
};
|
|
245
|
-
case "DateTime":
|
|
246
|
-
return (reader) => new Date(Number(reader.readZigzag()));
|
|
247
|
-
case "Blob":
|
|
248
|
-
return (reader) => reader.readBytes(reader.readVarint());
|
|
249
|
-
case "Ref":
|
|
250
|
-
case "Array":
|
|
251
|
-
case "Set":
|
|
252
|
-
case "Dict": {
|
|
253
|
-
// v4: mutable containers are read as varint(table_index) — the actual
|
|
254
|
-
// content was decoded from the mutable_value_table_section.
|
|
255
|
-
return (reader, ctx) => {
|
|
256
|
-
const idx = reader.readVarint();
|
|
257
|
-
if (idx >= ctx.mutableValues.length)
|
|
258
|
-
throw new Error(`Invalid mutable value table index ${idx} (table has ${ctx.mutableValues.length} entries)`);
|
|
259
|
-
return ctx.mutableValues[idx];
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
case "Struct": {
|
|
263
|
-
const fields = type.value;
|
|
264
|
-
const names = [];
|
|
265
|
-
const decoders = [];
|
|
266
|
-
const ret = (reader, ctx) => {
|
|
267
|
-
const result = {};
|
|
268
|
-
for (let i = 0; i < names.length; i++)
|
|
269
|
-
result[names[i]] = decoders[i](reader, ctx);
|
|
270
|
-
return result;
|
|
271
|
-
};
|
|
272
|
-
for (const { name, type: fieldType } of fields) {
|
|
273
|
-
names.push(name);
|
|
274
|
-
decoders.push(buildDecoder(fieldType, typeCtx));
|
|
275
|
-
}
|
|
276
|
-
return ret;
|
|
277
|
-
}
|
|
278
|
-
case "Variant": {
|
|
279
|
-
const caseDecoders = [];
|
|
280
|
-
const ret = (reader, ctx) => {
|
|
281
|
-
const tagIndex = reader.readVarint();
|
|
282
|
-
if (tagIndex >= caseDecoders.length)
|
|
283
|
-
throw new Error(`Invalid variant tag ${tagIndex}`);
|
|
284
|
-
const [caseName, caseDec] = caseDecoders[tagIndex];
|
|
285
|
-
return variant(caseName, caseDec(reader, ctx));
|
|
286
|
-
};
|
|
287
|
-
for (const { name, type: caseType } of type.value) {
|
|
288
|
-
caseDecoders.push([name, buildDecoder(caseType, typeCtx)]);
|
|
289
|
-
}
|
|
290
|
-
return ret;
|
|
291
|
-
}
|
|
292
|
-
case "Recursive": {
|
|
293
|
-
if (type.value.type === "wrapper") {
|
|
294
|
-
let inner;
|
|
295
|
-
const ret = (reader, ctx) => inner(reader, ctx);
|
|
296
|
-
typeCtx.set(type.value.value.id, ret);
|
|
297
|
-
inner = buildDecoder(type.value.value.inner, typeCtx);
|
|
298
|
-
return ret;
|
|
299
|
-
}
|
|
300
|
-
const target = typeCtx.get(type.value.value);
|
|
301
|
-
if (!target)
|
|
302
|
-
throw new InternalError("Recursive type context not found during decoder build");
|
|
303
|
-
return target;
|
|
304
|
-
}
|
|
305
|
-
case "Function":
|
|
306
|
-
case "AsyncFunction": {
|
|
307
|
-
const isAsync = type.type === "AsyncFunction";
|
|
308
|
-
const fnType = type;
|
|
309
|
-
const fnIrDecoder = buildDecoder(irTypeValue, typeCtx);
|
|
310
|
-
const captureDecoderCache = new Map();
|
|
311
|
-
return (reader, ctx) => {
|
|
312
|
-
const ir = fnIrDecoder(reader, ctx);
|
|
313
|
-
if (ir.type !== (isAsync ? "AsyncFunction" : "Function")) {
|
|
314
|
-
throw new Error(`Expected ${fnType.type} IR, got ${ir.type}`);
|
|
315
|
-
}
|
|
316
|
-
// Decode captures
|
|
317
|
-
const captureCount = reader.readVarint();
|
|
318
|
-
if (captureCount !== ir.value.captures.length) {
|
|
319
|
-
throw new Error(`Capture count mismatch: IR has ${ir.value.captures.length}, data has ${captureCount}`);
|
|
320
|
-
}
|
|
321
|
-
const captureContext = {};
|
|
322
|
-
const typeContext = {};
|
|
323
|
-
for (const captureVar of ir.value.captures) {
|
|
324
|
-
const name = captureVar.value.name;
|
|
325
|
-
const captureType = captureVar.value.type;
|
|
326
|
-
// Get or build cached decoder for this capture type
|
|
327
|
-
let dec = captureDecoderCache.get(captureType);
|
|
328
|
-
if (!dec) {
|
|
329
|
-
dec = buildDecoder(captureType, typeCtx);
|
|
330
|
-
captureDecoderCache.set(captureType, dec);
|
|
331
|
-
}
|
|
332
|
-
const captureValue = dec(reader, ctx);
|
|
333
|
-
captureContext[name] = captureVar.value.mutable
|
|
334
|
-
? variant("boxed", captureValue)
|
|
335
|
-
: variant("value", captureValue);
|
|
336
|
-
typeContext[name] = captureType;
|
|
337
|
-
}
|
|
338
|
-
// Compile IR to callable function — mutate in place to avoid object spread allocations
|
|
339
|
-
ir.value.isAsync = isAsync;
|
|
340
|
-
const compiled = compile_internal(ir, typeContext, ctx.platformFns, ctx.asyncPlatformFns, ctx.platform, true, EMPTY_SET);
|
|
341
|
-
const rawFn = compiled(captureContext);
|
|
342
|
-
const fn = isAsync
|
|
343
|
-
? async (...inputs) => {
|
|
344
|
-
try {
|
|
345
|
-
return await rawFn(...inputs);
|
|
346
|
-
}
|
|
347
|
-
catch (e) {
|
|
348
|
-
if (e instanceof ReturnException)
|
|
349
|
-
return e.value;
|
|
350
|
-
throw e;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
: (...inputs) => {
|
|
354
|
-
try {
|
|
355
|
-
return rawFn(...inputs);
|
|
356
|
-
}
|
|
357
|
-
catch (e) {
|
|
358
|
-
if (e instanceof ReturnException)
|
|
359
|
-
return e.value;
|
|
360
|
-
throw e;
|
|
361
|
-
}
|
|
362
|
-
};
|
|
363
|
-
// Attach IR, captures, and source map for re-serialization
|
|
364
|
-
Object.defineProperty(fn, EAST_IR_SYMBOL, { value: ir, writable: false, enumerable: false, configurable: false });
|
|
365
|
-
Object.defineProperty(fn, EAST_CAPTURES_SYMBOL, { value: captureContext, writable: false, enumerable: false, configurable: false });
|
|
366
|
-
if (ctx.sourceMap) {
|
|
367
|
-
Object.defineProperty(fn, EAST_SOURCE_MAP_SYMBOL, { value: ctx.sourceMap, writable: false, enumerable: false, configurable: false });
|
|
368
|
-
}
|
|
369
|
-
return fn;
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
case "Vector": {
|
|
373
|
-
const elemType = type.value.type;
|
|
374
|
-
const bpe = elemType === "Float" ? 8 : elemType === "Integer" ? 8 : 1;
|
|
375
|
-
return (reader) => {
|
|
376
|
-
const len = reader.readVarint();
|
|
377
|
-
const raw = new Uint8Array(reader.readBytesView(len * bpe));
|
|
378
|
-
if (elemType === "Float")
|
|
379
|
-
return new Float64Array(raw.buffer, 0, len);
|
|
380
|
-
if (elemType === "Integer")
|
|
381
|
-
return new BigInt64Array(raw.buffer, 0, len);
|
|
382
|
-
return new Uint8ClampedArray(raw.buffer, 0, len);
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
case "Matrix": {
|
|
386
|
-
const elemType = type.value.type;
|
|
387
|
-
const bpe = elemType === "Float" ? 8 : elemType === "Integer" ? 8 : 1;
|
|
388
|
-
return (reader) => {
|
|
389
|
-
const rows = reader.readVarint();
|
|
390
|
-
const cols = reader.readVarint();
|
|
391
|
-
const raw = new Uint8Array(reader.readBytesView(rows * cols * bpe));
|
|
392
|
-
if (elemType === "Float")
|
|
393
|
-
return matrix(new Float64Array(raw.buffer, 0, rows * cols), rows, cols);
|
|
394
|
-
if (elemType === "Integer")
|
|
395
|
-
return matrix(new BigInt64Array(raw.buffer, 0, rows * cols), rows, cols);
|
|
396
|
-
return matrix(new Uint8ClampedArray(raw.buffer, 0, rows * cols), rows, cols);
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
default:
|
|
400
|
-
throw new Error(`Unknown type: ${type.type}`);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
// =============================================================================
|
|
404
|
-
// String table section
|
|
405
|
-
// =============================================================================
|
|
406
|
-
// String table functions extracted to beast2-string-table.ts
|
|
407
|
-
// =============================================================================
|
|
408
|
-
// IR encoder/decoder (module-level singletons)
|
|
409
|
-
// =============================================================================
|
|
410
|
-
const irTypeValue = toEastTypeValue(IRType);
|
|
411
|
-
// =============================================================================
|
|
412
|
-
// Mutable value table section (v4)
|
|
413
|
-
// =============================================================================
|
|
414
|
-
function writeValueTableEntry(entry, writer, ctx, encTypeCtx) {
|
|
415
|
-
const type = entry.type;
|
|
416
|
-
const value = entry.value;
|
|
417
|
-
// Write kind tag
|
|
418
|
-
writer.writeUint8(entry.kind);
|
|
419
|
-
// Element encoder — handles both inline (non-mutable) and table-ref (mutable) cases
|
|
420
|
-
const encodeElem = (elemType, val, w, c) => {
|
|
421
|
-
if (isMutableType(elemType)) {
|
|
422
|
-
const idx = c.indexMap.get(val);
|
|
423
|
-
if (idx === undefined)
|
|
424
|
-
throw new InternalError("Nested mutable value not in value table");
|
|
425
|
-
w.writeVarint(idx);
|
|
426
|
-
}
|
|
427
|
-
else {
|
|
428
|
-
buildEncoder(elemType, encTypeCtx)(val, w, c);
|
|
429
|
-
}
|
|
430
|
-
};
|
|
431
|
-
switch (type.type) {
|
|
432
|
-
case "Array": {
|
|
433
|
-
if (!ctx.typeTable.has(type.value))
|
|
434
|
-
ctx.typeTable.addETV(type.value);
|
|
435
|
-
writer.writeVarint(ctx.typeTable.indexOf(type.value));
|
|
436
|
-
writer.writeVarint(value.length);
|
|
437
|
-
for (const item of value)
|
|
438
|
-
encodeElem(type.value, item, writer, ctx);
|
|
439
|
-
break;
|
|
440
|
-
}
|
|
441
|
-
case "Set": {
|
|
442
|
-
if (!ctx.typeTable.has(type.value))
|
|
443
|
-
ctx.typeTable.addETV(type.value);
|
|
444
|
-
writer.writeVarint(ctx.typeTable.indexOf(type.value));
|
|
445
|
-
writer.writeVarint(value.size);
|
|
446
|
-
for (const key of value)
|
|
447
|
-
encodeElem(type.value, key, writer, ctx);
|
|
448
|
-
break;
|
|
449
|
-
}
|
|
450
|
-
case "Dict": {
|
|
451
|
-
if (!ctx.typeTable.has(type.value.key))
|
|
452
|
-
ctx.typeTable.addETV(type.value.key);
|
|
453
|
-
if (!ctx.typeTable.has(type.value.value))
|
|
454
|
-
ctx.typeTable.addETV(type.value.value);
|
|
455
|
-
writer.writeVarint(ctx.typeTable.indexOf(type.value.key));
|
|
456
|
-
writer.writeVarint(ctx.typeTable.indexOf(type.value.value));
|
|
457
|
-
writer.writeVarint(value.size);
|
|
458
|
-
for (const [k, v] of value) {
|
|
459
|
-
encodeElem(type.value.key, k, writer, ctx);
|
|
460
|
-
encodeElem(type.value.value, v, writer, ctx);
|
|
461
|
-
}
|
|
462
|
-
break;
|
|
463
|
-
}
|
|
464
|
-
case "Ref": {
|
|
465
|
-
if (!ctx.typeTable.has(type.value))
|
|
466
|
-
ctx.typeTable.addETV(type.value);
|
|
467
|
-
writer.writeVarint(ctx.typeTable.indexOf(type.value));
|
|
468
|
-
encodeElem(type.value, value.value, writer, ctx);
|
|
469
|
-
break;
|
|
470
|
-
}
|
|
52
|
+
export function encodeBeast2For(type, options) {
|
|
53
|
+
if ((options?.version ?? BEAST2_WRITE_VERSION) === 4) {
|
|
54
|
+
return encodeBeast2V4For(type, options);
|
|
471
55
|
}
|
|
56
|
+
return encodeBeast2V5For(type, options);
|
|
472
57
|
}
|
|
473
|
-
function
|
|
474
|
-
const
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
// Each entry is prefixed with varint(byte_length), enabling trivial skip in pass 1.
|
|
484
|
-
// Pass 1: read entry headers, pre-allocate empty containers, skip element data by byte length
|
|
485
|
-
const entryOffsets = new Array(entryCount);
|
|
486
|
-
const entryLengths = new Array(entryCount);
|
|
487
|
-
for (let i = 0; i < entryCount; i++) {
|
|
488
|
-
const entryByteLength = reader.readVarint();
|
|
489
|
-
const entryStart = reader.offset;
|
|
490
|
-
const kindTag = reader.readUint8();
|
|
491
|
-
switch (kindTag) {
|
|
492
|
-
case TAG_ARRAY: {
|
|
493
|
-
reader.readVarint(); // elem type idx (skip)
|
|
494
|
-
const count = reader.readVarint();
|
|
495
|
-
ctx.mutableValues.push(new Array(count));
|
|
496
|
-
break;
|
|
497
|
-
}
|
|
498
|
-
case TAG_SET: {
|
|
499
|
-
reader.readVarint(); // elem type idx (skip)
|
|
500
|
-
reader.readVarint(); // count (skip — Set doesn't pre-allocate by count)
|
|
501
|
-
ctx.mutableValues.push(new Set());
|
|
502
|
-
break;
|
|
503
|
-
}
|
|
504
|
-
case TAG_DICT: {
|
|
505
|
-
reader.readVarint(); // key type idx (skip)
|
|
506
|
-
reader.readVarint(); // val type idx (skip)
|
|
507
|
-
reader.readVarint(); // count (skip)
|
|
508
|
-
ctx.mutableValues.push(new Map());
|
|
509
|
-
break;
|
|
510
|
-
}
|
|
511
|
-
case TAG_REF: {
|
|
512
|
-
reader.readVarint(); // inner type idx (skip)
|
|
513
|
-
ctx.mutableValues.push(ref(undefined));
|
|
514
|
-
break;
|
|
515
|
-
}
|
|
516
|
-
default:
|
|
517
|
-
throw new Error(`Unknown value table kind tag 0x${kindTag.toString(16)}`);
|
|
518
|
-
}
|
|
519
|
-
entryOffsets[i] = entryStart;
|
|
520
|
-
entryLengths[i] = entryByteLength;
|
|
521
|
-
// Skip to next entry using byte length
|
|
522
|
-
reader.offset = entryStart + entryByteLength;
|
|
523
|
-
}
|
|
524
|
-
if (reader.offset !== sectionEnd) {
|
|
525
|
-
throw new Error(`Value table section size mismatch: expected ${sectionEnd}, got ${reader.offset}`);
|
|
526
|
-
}
|
|
527
|
-
// Pre-build decoders for ALL recursive types in the decoded type table into
|
|
528
|
-
// a shared typeCtx. This ensures cross-type references resolve correctly
|
|
529
|
-
// (e.g., IR arrays inside Functions reference both IRType and EastTypeType).
|
|
530
|
-
const decTypeCtx = new Map();
|
|
531
|
-
for (const t of ctx.typeTable) {
|
|
532
|
-
if (t.type === "Recursive" && t.value?.type === "wrapper") {
|
|
533
|
-
buildDecoder(t, decTypeCtx);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
// Cache decoders by element type index — most entries share the same type
|
|
537
|
-
const decoderCache = new Map();
|
|
538
|
-
const getCachedDecoder = (typeIdx) => {
|
|
539
|
-
let dec = decoderCache.get(typeIdx);
|
|
540
|
-
if (!dec) {
|
|
541
|
-
dec = buildDecoder(ctx.typeTable[typeIdx], decTypeCtx);
|
|
542
|
-
decoderCache.set(typeIdx, dec);
|
|
58
|
+
export function decodeBeast2For(type, options) {
|
|
59
|
+
const typeValue = toTypeValue(type);
|
|
60
|
+
// Version decoders are built lazily on first use — most call sites only ever
|
|
61
|
+
// see one container version.
|
|
62
|
+
let v4;
|
|
63
|
+
let v5;
|
|
64
|
+
return (data) => {
|
|
65
|
+
if (sniffVersion(data) === 5) {
|
|
66
|
+
v5 ??= decodeBeast2V5For(typeValue, options);
|
|
67
|
+
return v5(data);
|
|
543
68
|
}
|
|
544
|
-
|
|
69
|
+
v4 ??= decodeBeast2V4For(typeValue, options);
|
|
70
|
+
return v4(data);
|
|
545
71
|
};
|
|
546
|
-
// Pass 2: fill elements in REVERSE order — children (higher indices) before parents.
|
|
547
|
-
// The walker produces parents-before-children, so reversing ensures a parent's
|
|
548
|
-
// element decoders (e.g., Function compilers) see fully-populated child entries.
|
|
549
|
-
for (let i = entryCount - 1; i >= 0; i--) {
|
|
550
|
-
const r = new BufferReader(reader.buffer, entryOffsets[i]);
|
|
551
|
-
const kindTag = r.readUint8();
|
|
552
|
-
switch (kindTag) {
|
|
553
|
-
case TAG_ARRAY: {
|
|
554
|
-
const elemTypeIdx = r.readVarint();
|
|
555
|
-
const elemType = ctx.typeTable[elemTypeIdx];
|
|
556
|
-
const count = r.readVarint();
|
|
557
|
-
const arr = ctx.mutableValues[i];
|
|
558
|
-
const isMut = isMutableType(elemType);
|
|
559
|
-
const dec = isMut ? null : getCachedDecoder(elemTypeIdx);
|
|
560
|
-
for (let j = 0; j < count; j++) {
|
|
561
|
-
arr[j] = isMut ? ctx.mutableValues[r.readVarint()] : dec(r, ctx);
|
|
562
|
-
}
|
|
563
|
-
break;
|
|
564
|
-
}
|
|
565
|
-
case TAG_SET: {
|
|
566
|
-
const elemTypeIdx = r.readVarint();
|
|
567
|
-
const elemType = ctx.typeTable[elemTypeIdx];
|
|
568
|
-
const count = r.readVarint();
|
|
569
|
-
const set = ctx.mutableValues[i];
|
|
570
|
-
const isMut = isMutableType(elemType);
|
|
571
|
-
const dec = isMut ? null : getCachedDecoder(elemTypeIdx);
|
|
572
|
-
for (let j = 0; j < count; j++) {
|
|
573
|
-
set.add(isMut ? ctx.mutableValues[r.readVarint()] : dec(r, ctx));
|
|
574
|
-
}
|
|
575
|
-
break;
|
|
576
|
-
}
|
|
577
|
-
case TAG_DICT: {
|
|
578
|
-
const keyTypeIdx = r.readVarint();
|
|
579
|
-
const valTypeIdx = r.readVarint();
|
|
580
|
-
const keyType = ctx.typeTable[keyTypeIdx];
|
|
581
|
-
const valType = ctx.typeTable[valTypeIdx];
|
|
582
|
-
const count = r.readVarint();
|
|
583
|
-
const map = ctx.mutableValues[i];
|
|
584
|
-
const keyMut = isMutableType(keyType);
|
|
585
|
-
const valMut = isMutableType(valType);
|
|
586
|
-
const keyDec = keyMut ? null : getCachedDecoder(keyTypeIdx);
|
|
587
|
-
const valDec = valMut ? null : getCachedDecoder(valTypeIdx);
|
|
588
|
-
for (let j = 0; j < count; j++) {
|
|
589
|
-
const k = keyMut ? ctx.mutableValues[r.readVarint()] : keyDec(r, ctx);
|
|
590
|
-
const v = valMut ? ctx.mutableValues[r.readVarint()] : valDec(r, ctx);
|
|
591
|
-
map.set(k, v);
|
|
592
|
-
}
|
|
593
|
-
break;
|
|
594
|
-
}
|
|
595
|
-
case TAG_REF: {
|
|
596
|
-
const innerTypeIdx = r.readVarint();
|
|
597
|
-
const innerType = ctx.typeTable[innerTypeIdx];
|
|
598
|
-
const rv = ctx.mutableValues[i];
|
|
599
|
-
if (isMutableType(innerType)) {
|
|
600
|
-
rv.value = ctx.mutableValues[r.readVarint()];
|
|
601
|
-
}
|
|
602
|
-
else {
|
|
603
|
-
rv.value = getCachedDecoder(innerTypeIdx)(r, ctx);
|
|
604
|
-
}
|
|
605
|
-
break;
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
72
|
}
|
|
610
|
-
export function
|
|
611
|
-
const
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
const stringTable = new Map();
|
|
622
|
-
// Build the mutable value table by walking the value graph.
|
|
623
|
-
// The walk also discovers the source map from any function in the value graph.
|
|
624
|
-
const vtResult = buildValueTable(value, typeValue, builder);
|
|
625
|
-
const vtEntries = vtResult.entries;
|
|
626
|
-
const indexMap = buildIndexMap(vtEntries);
|
|
627
|
-
// Source map: explicit option > root value > discovered during walk > null
|
|
628
|
-
const sourceMap = options?.sourceMap
|
|
629
|
-
?? value?.[EAST_SOURCE_MAP_SYMBOL]
|
|
630
|
-
?? vtResult.sourceMap
|
|
631
|
-
?? null;
|
|
632
|
-
const ctx = { indexMap, typeTable: builder, stringTable };
|
|
633
|
-
// Encode value table entries FIRST — this discovers types and strings
|
|
634
|
-
// from inside mutable containers (which are varint refs in the value stream)
|
|
635
|
-
const vtWriter = new BufferWriter();
|
|
636
|
-
vtWriter.writeVarint(vtEntries.length);
|
|
637
|
-
for (const entry of vtEntries) {
|
|
638
|
-
// Buffer each entry, then write varint(byte_length) + entry bytes
|
|
639
|
-
const entryWriter = new BufferWriter();
|
|
640
|
-
writeValueTableEntry(entry, entryWriter, ctx, setupTypeCtx);
|
|
641
|
-
const entryBytes = entryWriter.toUint8Array();
|
|
642
|
-
vtWriter.writeVarint(entryBytes.length);
|
|
643
|
-
vtWriter.writeBytes(entryBytes);
|
|
644
|
-
}
|
|
645
|
-
// Encode the value stream (mutable containers are written as varint indices)
|
|
646
|
-
const valueWriter = new BufferWriter();
|
|
647
|
-
valueEncoder(value, valueWriter, ctx);
|
|
648
|
-
// Source map filenames must be added to stringTable before writing string table section
|
|
649
|
-
const smWriter = new BufferWriter();
|
|
650
|
-
writeSourceMapSection(sourceMap, stringTable, smWriter);
|
|
651
|
-
// Write the final blob: magic + type table + string table + source map + value table + value data
|
|
652
|
-
const writer = new BufferWriter();
|
|
653
|
-
writer.writeBytes(MAGIC_BYTES);
|
|
654
|
-
writeTypeTableSection(baseRootIdx, builder.entries, writer);
|
|
655
|
-
writeStringTableSection(stringTable, writer);
|
|
656
|
-
writer.writeBytes(smWriter.toUint8Array());
|
|
657
|
-
// Write value table section with byte-length prefix
|
|
658
|
-
const vtBytes = vtWriter.toUint8Array();
|
|
659
|
-
writer.writeVarint(vtBytes.length);
|
|
660
|
-
writer.writeBytes(vtBytes);
|
|
661
|
-
writer.writeBytes(valueWriter.toUint8Array());
|
|
662
|
-
return writer.toUint8Array();
|
|
73
|
+
export function decodeBeast2ForAsync(type, options) {
|
|
74
|
+
const typeValue = toTypeValue(type);
|
|
75
|
+
let v4;
|
|
76
|
+
let v5;
|
|
77
|
+
return async (data) => {
|
|
78
|
+
if (sniffVersion(data) === 5) {
|
|
79
|
+
v5 ??= decodeBeast2V5ForAsync(typeValue, options);
|
|
80
|
+
return v5(data);
|
|
81
|
+
}
|
|
82
|
+
v4 ??= decodeBeast2V4For(typeValue, options);
|
|
83
|
+
return v4(data);
|
|
663
84
|
};
|
|
664
85
|
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
const ctx = {
|
|
681
|
-
mutableValues: [],
|
|
682
|
-
typeTable,
|
|
683
|
-
stringTable,
|
|
684
|
-
sourceMap,
|
|
685
|
-
platform,
|
|
686
|
-
platformFns,
|
|
687
|
-
asyncPlatformFns,
|
|
688
|
-
};
|
|
689
|
-
readMutableValueTableSection(reader, ctx);
|
|
690
|
-
const value = valueDecoder(reader, ctx);
|
|
691
|
-
if (reader.offset !== data.length) {
|
|
692
|
-
throw new Error(`${data.length - reader.offset} trailing bytes at offset ${reader.offset}`);
|
|
693
|
-
}
|
|
694
|
-
return value;
|
|
695
|
-
};
|
|
86
|
+
// =============================================================================
|
|
87
|
+
// Public API — Decode (self-describing)
|
|
88
|
+
// =============================================================================
|
|
89
|
+
/**
|
|
90
|
+
* Decodes a self-describing blob using its embedded root type.
|
|
91
|
+
*
|
|
92
|
+
* @param data - a beast2 blob of any supported container version
|
|
93
|
+
* @param options - decode options (platform functions for decoded functions)
|
|
94
|
+
* @returns the blob's root type and decoded value
|
|
95
|
+
*/
|
|
96
|
+
export function decodeBeast2(data, options) {
|
|
97
|
+
if (sniffVersion(data) === 5) {
|
|
98
|
+
return decodeBeast2V5(data, options);
|
|
99
|
+
}
|
|
100
|
+
return decodeBeast2V4(data, options);
|
|
696
101
|
}
|
|
697
102
|
// =============================================================================
|
|
698
103
|
// Public API — EastIR bundle (IR + source map travelling together)
|
|
@@ -705,8 +110,8 @@ export function decodeBeast2For(type, options) {
|
|
|
705
110
|
/** Encode an EastIR (or AsyncEastIR) as a beast2 blob that carries both the
|
|
706
111
|
* IR and its source map. Prefer this over `encodeBeast2For(IRType)(ir)` when
|
|
707
112
|
* encoding a program rather than opaque IR data. */
|
|
708
|
-
export function encodeEastIR(eastIR) {
|
|
709
|
-
return encodeBeast2For(IRType, { sourceMap: eastIR.source_map })(eastIR.ir);
|
|
113
|
+
export function encodeEastIR(eastIR, options) {
|
|
114
|
+
return encodeBeast2For(IRType, { ...options, sourceMap: eastIR.source_map })(eastIR.ir);
|
|
710
115
|
}
|
|
711
116
|
/** Decode a beast2 blob whose root is a Function IR into an EastIR. The
|
|
712
117
|
* returned wrapper has its source_map populated from the blob's source_map
|
|
@@ -730,58 +135,13 @@ export function decodeAsyncEastIR(data) {
|
|
|
730
135
|
result.source_map = sourceMap;
|
|
731
136
|
return result;
|
|
732
137
|
}
|
|
733
|
-
/** Internal: decode IRType blob
|
|
734
|
-
*
|
|
138
|
+
/** Internal: decode an IRType blob of any container version and return both
|
|
139
|
+
* the IR value and the decoded source map. */
|
|
735
140
|
function decodeIRWithSourceMap(data) {
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
const { typeTable } = readTypeTableSection(reader);
|
|
739
|
-
const stringTable = readStringTableSection(reader);
|
|
740
|
-
const sourceMap = readSourceMapSection(reader, stringTable);
|
|
741
|
-
const irTypeValue = toEastTypeValue(IRType);
|
|
742
|
-
const valueDecoder = buildDecoder(irTypeValue);
|
|
743
|
-
const ctx = {
|
|
744
|
-
mutableValues: [],
|
|
745
|
-
typeTable,
|
|
746
|
-
stringTable,
|
|
747
|
-
sourceMap,
|
|
748
|
-
platform: [],
|
|
749
|
-
platformFns: {},
|
|
750
|
-
asyncPlatformFns: new Set(),
|
|
751
|
-
};
|
|
752
|
-
readMutableValueTableSection(reader, ctx);
|
|
753
|
-
const ir = valueDecoder(reader, ctx);
|
|
754
|
-
if (reader.offset !== data.length) {
|
|
755
|
-
throw new Error(`${data.length - reader.offset} trailing bytes at offset ${reader.offset}`);
|
|
141
|
+
if (sniffVersion(data) === 5) {
|
|
142
|
+
return decodeIRWithSourceMapV5(data);
|
|
756
143
|
}
|
|
757
|
-
return
|
|
758
|
-
}
|
|
759
|
-
// =============================================================================
|
|
760
|
-
// Public API — Decode (self-describing)
|
|
761
|
-
// =============================================================================
|
|
762
|
-
export function decodeBeast2(data, options) {
|
|
763
|
-
verifyMagic(data);
|
|
764
|
-
const reader = new BufferReader(data, MAGIC_BYTES.length);
|
|
765
|
-
const { rootType, typeTable } = readTypeTableSection(reader);
|
|
766
|
-
const stringTable = readStringTableSection(reader);
|
|
767
|
-
const sourceMap = readSourceMapSection(reader, stringTable);
|
|
768
|
-
const valueDecoder = buildDecoder(rootType);
|
|
769
|
-
const platform = options?.platform ?? [];
|
|
770
|
-
const ctx = {
|
|
771
|
-
mutableValues: [],
|
|
772
|
-
typeTable,
|
|
773
|
-
stringTable,
|
|
774
|
-
sourceMap,
|
|
775
|
-
platform,
|
|
776
|
-
platformFns: Object.fromEntries(platform.map(fn => [fn.name, fn.fn])),
|
|
777
|
-
asyncPlatformFns: new Set(platform.filter(fn => fn.type === 'async').map(fn => fn.name)),
|
|
778
|
-
};
|
|
779
|
-
readMutableValueTableSection(reader, ctx);
|
|
780
|
-
const value = valueDecoder(reader, ctx);
|
|
781
|
-
if (reader.offset !== data.length) {
|
|
782
|
-
throw new Error(`${data.length - reader.offset} trailing bytes at offset ${reader.offset}`);
|
|
783
|
-
}
|
|
784
|
-
return { type: rootType, value };
|
|
144
|
+
return decodeIRWithSourceMapV4(data);
|
|
785
145
|
}
|
|
786
146
|
// =============================================================================
|
|
787
147
|
// Re-exports
|
|
@@ -793,4 +153,11 @@ export function compileFunctionIR(ir, platform) {
|
|
|
793
153
|
export function compileAsyncFunctionIR(ir, platform) {
|
|
794
154
|
return new AsyncEastIR(ir).compile(platform);
|
|
795
155
|
}
|
|
156
|
+
// =============================================================================
|
|
157
|
+
// Internal helpers
|
|
158
|
+
// =============================================================================
|
|
159
|
+
/** Normalizes an `EastType | EastTypeValue` to `EastTypeValue`. */
|
|
160
|
+
function toTypeValue(type) {
|
|
161
|
+
return isVariant(type) ? type : toEastTypeValue(type);
|
|
162
|
+
}
|
|
796
163
|
//# sourceMappingURL=index.js.map
|