jseption 0.0.3 → 0.0.5
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 +112 -4
- package/dist/bytecode.js +162 -2
- package/dist/bytecode.js.map +1 -1
- package/dist/embed.d.ts +5 -0
- package/dist/embed.js +44 -12
- package/dist/embed.js.map +1 -1
- package/dist/interpreter.js +15 -4
- package/dist/interpreter.js.map +1 -1
- package/dist/jit.js +12 -4
- package/dist/jit.js.map +1 -1
- package/dist/jit_runtime.d.ts +2 -0
- package/dist/jit_runtime.js +11 -0
- package/dist/jit_runtime.js.map +1 -1
- package/dist/jseption.d.ts +6 -0
- package/dist/jseption.js +4 -0
- package/dist/jseption.js.map +1 -1
- package/dist/membrane.d.ts +16 -0
- package/dist/membrane.js +576 -0
- package/dist/membrane.js.map +1 -0
- package/dist/module.d.ts +28 -0
- package/dist/module.js +1166 -0
- package/dist/module.js.map +1 -0
- package/dist/opcodes.js +1 -1
- package/dist/opcodes.js.map +1 -1
- package/dist/parser.d.ts +31 -0
- package/dist/parser.js +2862 -62
- package/dist/parser.js.map +1 -1
- package/dist/qjs.js +86 -17
- package/dist/qjs.js.map +1 -1
- package/dist/quickjs.d.ts +8 -0
- package/dist/quickjs.js +21 -2
- package/dist/quickjs.js.map +1 -1
- package/dist/std.d.ts +2 -0
- package/dist/std.js +34 -0
- package/dist/std.js.map +1 -1
- package/dist/values.d.ts +78 -0
- package/dist/values.js +85 -0
- package/dist/values.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -104,6 +104,82 @@ checksum only catches accidental corruption; bytecode that passes through storag
|
|
|
104
104
|
service you do not control needs a signature you verify before loading. See
|
|
105
105
|
`docs/BYTECODE.md` for the format and the measurements.
|
|
106
106
|
|
|
107
|
+
## Running TypeScript
|
|
108
|
+
|
|
109
|
+
TypeScript runs the way Node runs it with type stripping: the erasable syntax is
|
|
110
|
+
removed and the rest runs as JavaScript, with no type checking. Pass
|
|
111
|
+
`JS_EVAL_FLAG_STRIP_TYPES` to `JS_Eval`; the command line strips `.ts`, `.mts` and
|
|
112
|
+
`.cts` files, and `--strip-types` applies it to `-e`.
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
JS_Eval(ctx, 'const id = <T,>(x: T): T => x; id<number>(41) + 1', 'app.ts',
|
|
116
|
+
JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAG_STRIP_TYPES); // 42
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The stripping is built into the parser, so error positions and stacks are those
|
|
120
|
+
of the JavaScript with the types blanked, and plain JavaScript compiles as fast as
|
|
121
|
+
before. As in Node, `enum`, namespaces with values, parameter properties,
|
|
122
|
+
`import x = require(...)` and `export =` are rejected because they need generated
|
|
123
|
+
code. `docs/TYPESCRIPT.md` lists what is stripped and how ambiguous syntax is read.
|
|
124
|
+
|
|
125
|
+
## JSX and TSX
|
|
126
|
+
|
|
127
|
+
`JS_EVAL_FLAG_JSX` compiles JSX in the parser, as TypeScript compiles it. With
|
|
128
|
+
`JS_EVAL_FLAG_STRIP_TYPES` as well, it compiles TSX. There is no build step.
|
|
129
|
+
|
|
130
|
+
* **Modules** use the automatic runtime (`jsx: "react-jsx"`). Elements are calls of
|
|
131
|
+
`jsx`, `jsxs` and `Fragment`, imported from `react/jsx-runtime`. A
|
|
132
|
+
`/** @jsxImportSource x */` pragma imports them from `x/jsx-runtime` instead.
|
|
133
|
+
* **Scripts** use the classic runtime (`React.createElement`, or the `@jsx` and
|
|
134
|
+
`@jsxFrag` pragmas).
|
|
135
|
+
* **The module loader** compiles `.tsx` ids (or a `type: 'tsx'` result) as TSX and
|
|
136
|
+
`.jsx` ids as JSX.
|
|
137
|
+
* **The command line** runs `.tsx` and `.jsx` files as modules, and `--jsx` applies
|
|
138
|
+
the flag to `-e`.
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
JS_SetModuleLoader(rt, { load: (id) => files[id] }); // '/app.tsx', 'react/jsx-runtime', ...
|
|
142
|
+
await guestPromiseToHost(ctx, JS_ImportModule(ctx, '/app.tsx'));
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`docs/JSX.md` covers the runtimes, pragmas, text and entity rules, and what is not
|
|
146
|
+
supported.
|
|
147
|
+
|
|
148
|
+
## Modules
|
|
149
|
+
|
|
150
|
+
ES modules work as in QuickJS: `import` and `export` in every form, live bindings,
|
|
151
|
+
cycles, `export *` with its ambiguity rules, namespace objects, top-level `await`,
|
|
152
|
+
dynamic `import()`, `import.meta`, and JSON modules (`with { type: "json" }`). The
|
|
153
|
+
embedder decides what a specifier means. With no loader set, nothing can be imported,
|
|
154
|
+
so the sandbox stays closed by default.
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import { JS_SetModuleLoader, JS_ImportModule, guestPromiseToHost, drainJobs } from 'jseption';
|
|
158
|
+
|
|
159
|
+
JS_SetModuleLoader(rt, {
|
|
160
|
+
// optional; the default resolves ./, ../ and / against the importing module, URL style
|
|
161
|
+
resolve: (specifier, referrer) => new URL(specifier, referrer ?? location.href).href,
|
|
162
|
+
// source text, module bytecode, or { source, url, type, exports }, or a promise of one
|
|
163
|
+
load: async (url) => ({ source: await (await fetch(url)).text(), url }),
|
|
164
|
+
});
|
|
165
|
+
const ns = await guestPromiseToHost(ctx, JS_ImportModule(ctx, 'https://example.test/app.js'));
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The loader may be asynchronous: the whole graph is fetched first, in parallel where
|
|
169
|
+
possible, then linked and evaluated. A synchronous loader keeps everything synchronous.
|
|
170
|
+
`load` can return a host module, `{ exports: { fetch } }`, whose values are marshalled
|
|
171
|
+
into the guest, so guest code can `import { fetch } from "host:net"`. It can also
|
|
172
|
+
return bytecode from `JS_WriteObject`, so a precompiled graph loads without parsing.
|
|
173
|
+
`JS_EvalModule(ctx, source, url)` evaluates source text as a module.
|
|
174
|
+
`JS_Eval` with `JS_EVAL_TYPE_MODULE` keeps QuickJS's behaviour and returns the
|
|
175
|
+
evaluation promise.
|
|
176
|
+
|
|
177
|
+
The command line runs `.mjs` and `.mts` files as modules, detects `.js` and `.ts` files
|
|
178
|
+
that start with `import` or `export`, and takes `-m` to force module mode or `--script`
|
|
179
|
+
to force a script. Its loader reads relative and absolute paths from disk; bare
|
|
180
|
+
specifiers are not resolved. `docs/MODULES.md` describes the design and the loader
|
|
181
|
+
contract.
|
|
182
|
+
|
|
107
183
|
## Passing values between host and guest
|
|
108
184
|
|
|
109
185
|
Guest values are host values, but the sandbox forbids handing the guest an object whose
|
|
@@ -130,6 +206,36 @@ run when they settle) and preserves shared references and cycles. `fromGuest` do
|
|
|
130
206
|
reverse, turning guest functions into host functions that call into the guest. See
|
|
131
207
|
`examples/fetch.ts`.
|
|
132
208
|
|
|
209
|
+
### Live host objects (the membrane)
|
|
210
|
+
|
|
211
|
+
`exposeLive` hands the guest a live view of a host API instead of a copy. Every host
|
|
212
|
+
object or function reachable from the root crosses as a proxy created on first use;
|
|
213
|
+
each operation is forwarded to the host object and its result converted the same way,
|
|
214
|
+
so nested objects, returned instances and constructed objects are proxied too:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
import { exposeLive } from 'jseption';
|
|
218
|
+
|
|
219
|
+
exposeLive(ctx, 'Intl', Intl); // the page's real Intl, read-only
|
|
220
|
+
JS_Eval(ctx, `new Intl.DateTimeFormat('en-US', { hour: 'numeric', minute: '2-digit', timeZone: 'UTC' })
|
|
221
|
+
.format(new Date(0))`, 'guest.js', JS_EVAL_TYPE_GLOBAL); // '12:00 AM'
|
|
222
|
+
|
|
223
|
+
exposeLive(ctx, 'store', store, { writable: true, allow: (target, key) => key !== 'internal' });
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Primitives cross as values, host arrays as snapshot guest arrays, `Date`/`RegExp`/typed
|
|
227
|
+
arrays/errors as copies, promises as guest promises; guest arguments are copied
|
|
228
|
+
(`fromGuest`), a proxy passed back is unwrapped to its host object, and guest callbacks
|
|
229
|
+
become host functions. The sandbox rules are always on: host intrinsics (`Function`,
|
|
230
|
+
`eval`, `globalThis`, `Object`, `Reflect`, `Proxy`, the intrinsic prototypes, ...) never
|
|
231
|
+
cross; `constructor`, `prototype`, `__proto__`, `caller`, `callee` and `arguments` read as
|
|
232
|
+
`undefined`; a proxy's prototype is the guest's `Object.prototype`; host functions are
|
|
233
|
+
only callable and constructible; host exceptions become guest errors of the same type;
|
|
234
|
+
writes need `writable: true`. The membrane cannot see inside host code, so expose narrow
|
|
235
|
+
roots (`Intl`, `TextEncoder`, a purpose-built facade), never broad objects such as the
|
|
236
|
+
DOM or anything that reaches host globals. See `docs/MEMBRANE.md` for the model, the
|
|
237
|
+
rules and the limits.
|
|
238
|
+
|
|
133
239
|
## Layout
|
|
134
240
|
|
|
135
241
|
```
|
|
@@ -137,8 +243,9 @@ src/atoms.ts atom table (JS_ATOM_*), tagged integer atoms, atom -> proper
|
|
|
137
243
|
src/values.ts JSValue, object metadata, bytecode & frame structures
|
|
138
244
|
src/opcodes.ts opcode table generated from quickjs-opcode.h
|
|
139
245
|
src/quickjs.ts runtime, context, property layer over Reflect, calls, conversions, jobs
|
|
140
|
-
src/parser.ts tokenizer, parser, bytecode emitter, variable/label resolution, eval
|
|
246
|
+
src/parser.ts tokenizer, parser (with TypeScript type stripping and JSX), bytecode emitter, variable/label resolution, eval
|
|
141
247
|
src/bytecode.ts bytecode serialization (JS_WriteObject / JS_ReadObject)
|
|
248
|
+
src/module.ts ES modules: loader, linking, evaluation, namespaces, import(), import.meta
|
|
142
249
|
src/interpreter.ts JS_CallInternal, closures, generators, async functions (fallback tier)
|
|
143
250
|
src/jit.ts bytecode -> host JavaScript compiler (stack-to-register, relooper)
|
|
144
251
|
src/jit_runtime.ts the helpers generated code calls into (the only engine touchpoint)
|
|
@@ -147,6 +254,7 @@ src/std.ts print / console / std / os helpers for the CLI (subset of qu
|
|
|
147
254
|
src/qjs.ts command line interpreter
|
|
148
255
|
src/dump.ts bytecode disassembler
|
|
149
256
|
src/embed.ts host <-> guest value marshalling (expose, toGuest, fromGuest, promises)
|
|
257
|
+
src/membrane.ts live host objects for the guest (exposeLive, toGuestLive)
|
|
150
258
|
examples/ embedding examples (fetch facade)
|
|
151
259
|
bench/ benchmark programs and runners (host vs compiled vs interpreted)
|
|
152
260
|
tests/ bun tests, including the QuickJS test suite files in tests/qjs/
|
|
@@ -214,9 +322,9 @@ Differences from the C implementation:
|
|
|
214
322
|
* Memory management relies on the host garbage collector: there is no reference
|
|
215
323
|
counting, `JS_FreeValue`/`JS_DupValue` are no-ops, and `WeakRef` / `FinalizationRegistry`
|
|
216
324
|
use the host weak references.
|
|
217
|
-
*
|
|
218
|
-
|
|
219
|
-
|
|
325
|
+
* `Atomics` and `SharedArrayBuffer` threads are not ported. `JS_WriteObject` /
|
|
326
|
+
`JS_ReadObject` serialize compiled scripts and modules only, not arbitrary values,
|
|
327
|
+
in a jseption-specific format.
|
|
220
328
|
* Number formatting and parsing use the host conversions (they are specified by
|
|
221
329
|
ECMAScript, so the results are identical).
|
|
222
330
|
|
package/dist/bytecode.js
CHANGED
|
@@ -35,7 +35,8 @@
|
|
|
35
35
|
*/
|
|
36
36
|
import { JS_ATOM_END, JS_ATOM_raw, JS_ATOM_TAG_INT, JS_ATOM_TYPE_STRING, __JS_AtomIsTaggedInt } from "./atoms.js";
|
|
37
37
|
import { JS_GetFunctionData, JS_ThrowSyntaxError, JS_ThrowTypeError, JS_NewArray, JS_DefinePropertyValue, JS_DefinePropertyValueUint32, JS_IsException, JS_PROP_ENUMERABLE, hooks } from "./quickjs.js";
|
|
38
|
-
import { JSClosureVar, JSFunctionBytecode, JSVarDef } from "./values.js";
|
|
38
|
+
import { JSClosureVar, JSFunctionBytecode, JSVarDef, JSModuleDef, JSReqModuleEntry, JSExportEntry, JSStarExportEntry, JSImportEntry } from "./values.js";
|
|
39
|
+
import { js_module_set_function, hooks_bytecode } from "./module.js";
|
|
39
40
|
import { short_opcode_info } from "./opcodes.js";
|
|
40
41
|
import { JSEPTION_VERSION } from "./version.js";
|
|
41
42
|
/* keep each function's source text (Function.prototype.toString); off by default */
|
|
@@ -320,6 +321,51 @@ class BCWriter {
|
|
|
320
321
|
for (const v of b.cpool)
|
|
321
322
|
this.value(v);
|
|
322
323
|
}
|
|
324
|
+
/* a compiled module (JS_WriteModule): its requests, entries and body function */
|
|
325
|
+
module(m) {
|
|
326
|
+
const out = this.out;
|
|
327
|
+
out.u8(11 /* BCTag.MODULE */);
|
|
328
|
+
this.atom(m.module_name);
|
|
329
|
+
out.leb(m.req_module_entries.length);
|
|
330
|
+
for (const rme of m.req_module_entries) {
|
|
331
|
+
this.atom(rme.module_name);
|
|
332
|
+
if (rme.attributes === null) {
|
|
333
|
+
out.leb(0);
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
const keys = Object.keys(rme.attributes);
|
|
337
|
+
out.leb(keys.length + 1);
|
|
338
|
+
for (const k of keys) {
|
|
339
|
+
out.leb(this.string_ref(k));
|
|
340
|
+
out.leb(this.string_ref(rme.attributes[k]));
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
out.leb(m.export_entries.length);
|
|
345
|
+
for (const me of m.export_entries) {
|
|
346
|
+
out.u8(me.export_type);
|
|
347
|
+
if (me.export_type === 0 /* JSExportType.LOCAL */) {
|
|
348
|
+
out.leb(me.var_idx);
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
out.leb(me.req_module_idx);
|
|
352
|
+
this.atom(me.local_name);
|
|
353
|
+
}
|
|
354
|
+
this.atom(me.export_name);
|
|
355
|
+
}
|
|
356
|
+
out.leb(m.star_export_entries.length);
|
|
357
|
+
for (const se of m.star_export_entries)
|
|
358
|
+
out.leb(se.req_module_idx);
|
|
359
|
+
out.leb(m.import_entries.length);
|
|
360
|
+
for (const mi of m.import_entries) {
|
|
361
|
+
out.leb(mi.var_idx);
|
|
362
|
+
out.u8(mi.is_star ? 1 : 0);
|
|
363
|
+
this.atom(mi.import_name);
|
|
364
|
+
out.leb(mi.req_module_idx);
|
|
365
|
+
}
|
|
366
|
+
out.u8(m.has_tla ? 1 : 0);
|
|
367
|
+
this.function(m.func_bytecode);
|
|
368
|
+
}
|
|
323
369
|
/* the byte code with its atom operands renumbered (JS_WriteFunctionBytecode) */
|
|
324
370
|
byte_code(b) {
|
|
325
371
|
const len = b.byte_code_len;
|
|
@@ -453,6 +499,25 @@ function checksum(buf, end) {
|
|
|
453
499
|
bytecode function that does not close over variables). Returns null with a pending
|
|
454
500
|
exception on failure. */
|
|
455
501
|
export function JS_WriteObject(ctx, obj, flags = 0) {
|
|
502
|
+
if (obj instanceof JSModuleDef) {
|
|
503
|
+
/* a module compiled with JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY */
|
|
504
|
+
if (obj.kind !== 0 /* JSModuleKind.JS */ || obj.func_bytecode === null) {
|
|
505
|
+
JS_ThrowTypeError(ctx, 'JS_WriteObject: only JavaScript modules can be written');
|
|
506
|
+
return null;
|
|
507
|
+
}
|
|
508
|
+
const w = new BCWriter(ctx, flags);
|
|
509
|
+
try {
|
|
510
|
+
w.module(obj);
|
|
511
|
+
return w.finish(w.out);
|
|
512
|
+
}
|
|
513
|
+
catch (e) {
|
|
514
|
+
if (e instanceof BCWriteError) {
|
|
515
|
+
JS_ThrowTypeError(ctx, 'JS_WriteObject: ' + e.message);
|
|
516
|
+
return null;
|
|
517
|
+
}
|
|
518
|
+
throw e;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
456
521
|
const fd = JS_GetFunctionData(obj);
|
|
457
522
|
if (fd === null) {
|
|
458
523
|
JS_ThrowTypeError(ctx, 'JS_WriteObject: not a bytecode function (expected the result of JS_EVAL_FLAG_COMPILE_ONLY)');
|
|
@@ -810,6 +875,93 @@ class BCReader {
|
|
|
810
875
|
this.depth--;
|
|
811
876
|
return b;
|
|
812
877
|
}
|
|
878
|
+
/* a compiled module (JS_ReadModule) */
|
|
879
|
+
module() {
|
|
880
|
+
const m = new JSModuleDef(this.atom());
|
|
881
|
+
m.realm = this.ctx;
|
|
882
|
+
const nreq = this.count();
|
|
883
|
+
for (let i = 0; i < nreq; i++) {
|
|
884
|
+
const name = this.atom();
|
|
885
|
+
const n = this.leb();
|
|
886
|
+
let attrs = null;
|
|
887
|
+
if (n > 0) {
|
|
888
|
+
if (n - 1 > this.end - this.pos)
|
|
889
|
+
this.truncated();
|
|
890
|
+
attrs = Object.create(null);
|
|
891
|
+
for (let j = 0; j < n - 1; j++) {
|
|
892
|
+
const k = this.string();
|
|
893
|
+
attrs[k] = this.string();
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
m.req_module_entries.push(new JSReqModuleEntry(name, attrs));
|
|
897
|
+
}
|
|
898
|
+
const req_idx = () => {
|
|
899
|
+
const i = this.leb();
|
|
900
|
+
if (i >= nreq)
|
|
901
|
+
this.fail(`invalid module request index ${i}`);
|
|
902
|
+
return i;
|
|
903
|
+
};
|
|
904
|
+
const nexp = this.count();
|
|
905
|
+
const local_exports = [];
|
|
906
|
+
for (let i = 0; i < nexp; i++) {
|
|
907
|
+
const type = this.u8();
|
|
908
|
+
let me;
|
|
909
|
+
if (type === 0 /* JSExportType.LOCAL */) {
|
|
910
|
+
const var_idx = this.leb();
|
|
911
|
+
local_exports.push(var_idx);
|
|
912
|
+
me = new JSExportEntry(0, this.atom(), 0 /* JSExportType.LOCAL */);
|
|
913
|
+
me.var_idx = var_idx;
|
|
914
|
+
me.local_name = me.export_name;
|
|
915
|
+
}
|
|
916
|
+
else if (type === 1 /* JSExportType.INDIRECT */) {
|
|
917
|
+
const idx = req_idx();
|
|
918
|
+
const local_name = this.atom();
|
|
919
|
+
me = new JSExportEntry(local_name, this.atom(), 1 /* JSExportType.INDIRECT */);
|
|
920
|
+
me.req_module_idx = idx;
|
|
921
|
+
}
|
|
922
|
+
else {
|
|
923
|
+
this.fail('invalid export entry');
|
|
924
|
+
}
|
|
925
|
+
m.export_entries.push(me);
|
|
926
|
+
}
|
|
927
|
+
const nstar = this.count();
|
|
928
|
+
for (let i = 0; i < nstar; i++)
|
|
929
|
+
m.star_export_entries.push(new JSStarExportEntry(req_idx()));
|
|
930
|
+
const nimp = this.count();
|
|
931
|
+
const imports = [];
|
|
932
|
+
for (let i = 0; i < nimp; i++) {
|
|
933
|
+
const var_idx = this.leb();
|
|
934
|
+
const is_star = this.u8();
|
|
935
|
+
if (is_star > 1)
|
|
936
|
+
this.fail('invalid import entry');
|
|
937
|
+
const mi = new JSImportEntry(var_idx, is_star === 1, this.atom());
|
|
938
|
+
mi.req_module_idx = req_idx();
|
|
939
|
+
m.import_entries.push(mi);
|
|
940
|
+
imports.push({ var_idx, is_star: is_star === 1 });
|
|
941
|
+
}
|
|
942
|
+
const tla = this.u8();
|
|
943
|
+
if (tla > 1)
|
|
944
|
+
this.fail('invalid module flags');
|
|
945
|
+
m.has_tla = tla === 1;
|
|
946
|
+
if (this.u8() !== 9 /* BCTag.FUNCTION_BYTECODE */)
|
|
947
|
+
this.fail('the module body is not a function');
|
|
948
|
+
const b = this.function();
|
|
949
|
+
if (b.func_kind !== 2 /* JSFunctionKind.ASYNC */)
|
|
950
|
+
this.fail('the module body is not an async function');
|
|
951
|
+
/* the entries index the closure variables of the body */
|
|
952
|
+
const ncv = b.closure_var.length;
|
|
953
|
+
for (const v of local_exports)
|
|
954
|
+
if (v >= ncv)
|
|
955
|
+
this.fail(`invalid export variable index ${v}`);
|
|
956
|
+
for (const { var_idx, is_star } of imports) {
|
|
957
|
+
if (var_idx >= ncv)
|
|
958
|
+
this.fail(`invalid import variable index ${var_idx}`);
|
|
959
|
+
if (b.closure_var[var_idx].is_local !== is_star)
|
|
960
|
+
this.fail('invalid import variable');
|
|
961
|
+
}
|
|
962
|
+
js_module_set_function(m, b);
|
|
963
|
+
return m;
|
|
964
|
+
}
|
|
813
965
|
/* patch the atom operands and check the instruction boundaries and the constant pool
|
|
814
966
|
indices (JS_ReadFunctionBytecode) */
|
|
815
967
|
fixup_byte_code(b) {
|
|
@@ -891,7 +1043,14 @@ export function JS_ReadObject(ctx, buf) {
|
|
|
891
1043
|
r.header();
|
|
892
1044
|
r.string_table();
|
|
893
1045
|
r.atom_table();
|
|
894
|
-
|
|
1046
|
+
const tag = r.u8();
|
|
1047
|
+
if (tag === 11 /* BCTag.MODULE */) {
|
|
1048
|
+
const m = r.module();
|
|
1049
|
+
if (r.pos !== r.end)
|
|
1050
|
+
r.fail('trailing bytes after the root value');
|
|
1051
|
+
return m;
|
|
1052
|
+
}
|
|
1053
|
+
if (tag !== 9 /* BCTag.FUNCTION_BYTECODE */)
|
|
895
1054
|
r.fail('the root value is not a function');
|
|
896
1055
|
b = r.function();
|
|
897
1056
|
if (r.pos !== r.end)
|
|
@@ -908,4 +1067,5 @@ export function JS_ReadObject(ctx, buf) {
|
|
|
908
1067
|
return JS_ThrowSyntaxError(ctx, 'JS_ReadObject: the root function has closure variables');
|
|
909
1068
|
return hooks.js_closure(ctx, b, null, null);
|
|
910
1069
|
}
|
|
1070
|
+
hooks_bytecode.read = (ctx, bytes) => JS_ReadObject(ctx, bytes);
|
|
911
1071
|
//# sourceMappingURL=bytecode.js.map
|