jseption 0.0.1 → 0.0.3

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 CHANGED
@@ -33,6 +33,7 @@ JSEPTION_JIT=0 bun test # run the suite on the interpreter tier only
33
33
  JSEPTION_JIT=always bun test # compile every function that runs (no lazy tier-up)
34
34
  JSEPTION_JIT_DUMP=1 bun run src/qjs.ts file.js # print the generated host code
35
35
  bun run bench/inproc.ts # host vs tier modes, incl. cold-code bundles
36
+ bun run bench/bytecode.ts file.js # compile vs read precompiled bytecode vs run
36
37
  ```
37
38
 
38
39
  ## Installing
@@ -72,6 +73,37 @@ engine metadata kept in a `WeakMap`). Engine code signals exceptions with the
72
73
  the two conventions meet at the call boundary. See `docs/PORTING.md` and
73
74
  `docs/HOST_VALUES.md` for the internals.
74
75
 
76
+ ## Precompiled bytecode
77
+
78
+ A script can be compiled ahead of time and loaded without parsing, as with QuickJS's
79
+ `JS_WriteObject` / `JS_ReadObject`:
80
+
81
+ ```ts
82
+ import { JS_Eval, JS_EVAL_TYPE_GLOBAL, JS_EVAL_FLAG_COMPILE_ONLY, JS_WriteObject, JS_ReadObject,
83
+ JS_EvalFunction, JS_IsException } from 'jseption';
84
+
85
+ /* at build time */
86
+ const fn = JS_Eval(ctx, src, 'runtime.js', JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAG_COMPILE_ONLY);
87
+ const bytes = JS_WriteObject(ctx, fn); /* Uint8Array, or null with an exception pending */
88
+
89
+ /* at run time, in any runtime of the same jseption version */
90
+ const loaded = JS_ReadObject(ctx2, bytes); /* JS_EXCEPTION (a SyntaxError) on bad input */
91
+ if (!JS_IsException(loaded)) JS_EvalFunction(ctx2, loaded);
92
+ ```
93
+
94
+ Reading is 18x (host JIT on) to 37x (JIT off, as on iOS) faster than parsing a 300 KB
95
+ bundle. Line numbers in error stacks are kept; function source text (for
96
+ `Function.prototype.toString`) is dropped unless `JS_WRITE_OBJ_SOURCE` is passed. The
97
+ bytes record the jseption version and only load in that version.
98
+
99
+ **Only load bytecode you produced yourself.** As in QuickJS, the reader checks the format
100
+ (version, bounds, tags, indices, instruction boundaries, a checksum) but not the meaning
101
+ of the byte code: hand-made bytecode can reach engine states the parser never produces,
102
+ so loading untrusted bytecode is not safe even though running untrusted source is. The
103
+ checksum only catches accidental corruption; bytecode that passes through storage or a
104
+ service you do not control needs a signature you verify before loading. See
105
+ `docs/BYTECODE.md` for the format and the measurements.
106
+
75
107
  ## Passing values between host and guest
76
108
 
77
109
  Guest values are host values, but the sandbox forbids handing the guest an object whose
@@ -106,6 +138,7 @@ src/values.ts JSValue, object metadata, bytecode & frame structures
106
138
  src/opcodes.ts opcode table generated from quickjs-opcode.h
107
139
  src/quickjs.ts runtime, context, property layer over Reflect, calls, conversions, jobs
108
140
  src/parser.ts tokenizer, parser, bytecode emitter, variable/label resolution, eval
141
+ src/bytecode.ts bytecode serialization (JS_WriteObject / JS_ReadObject)
109
142
  src/interpreter.ts JS_CallInternal, closures, generators, async functions (fallback tier)
110
143
  src/jit.ts bytecode -> host JavaScript compiler (stack-to-register, relooper)
111
144
  src/jit_runtime.ts the helpers generated code calls into (the only engine touchpoint)
@@ -181,8 +214,9 @@ Differences from the C implementation:
181
214
  * Memory management relies on the host garbage collector: there is no reference
182
215
  counting, `JS_FreeValue`/`JS_DupValue` are no-ops, and `WeakRef` / `FinalizationRegistry`
183
216
  use the host weak references.
184
- * ES modules (`import` / `export`), `Atomics`, `SharedArrayBuffer` threads and the
185
- bytecode serialization (`JS_WriteObject` / `JS_ReadObject`) are not ported.
217
+ * ES modules (`import` / `export`), `Atomics` and `SharedArrayBuffer` threads are not
218
+ ported. `JS_WriteObject` / `JS_ReadObject` serialize compiled scripts (bytecode
219
+ function trees) only, not arbitrary values, in a jseption-specific format.
186
220
  * Number formatting and parsing use the host conversions (they are specified by
187
221
  ECMAScript, so the results are identical).
188
222
 
@@ -0,0 +1,6 @@
1
+ import { JSContext, JSValue } from './quickjs.ts';
2
+ export declare const JS_WRITE_OBJ_SOURCE: number;
3
+ export declare const BC_MAGIC: number[];
4
+ export declare const BC_FORMAT = 1;
5
+ export declare function JS_WriteObject(ctx: JSContext, obj: JSValue, flags?: number): Uint8Array | null;
6
+ export declare function JS_ReadObject(ctx: JSContext, buf: Uint8Array): JSValue;