@holoscript/wasm 6.0.3 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,6 @@ High-performance HoloScript parser compiled to WebAssembly.
4
4
 
5
5
  ## Features
6
6
 
7
- - **10x faster parsing** compared to JavaScript implementation
8
7
  - **Browser-native** - runs directly in the browser without server
9
8
  - **Small footprint** - <500KB gzipped
10
9
  - **Full HoloScript support** - all language features including Brittney AI constructs
@@ -137,13 +136,25 @@ npm run test
137
136
 
138
137
  ## Performance
139
138
 
140
- Benchmarks on a typical development machine:
139
+ **The WASM parser is currently SLOWER than the JS parser at canonical
140
+ fixture sizes** due to JS↔linear-memory string marshalling overhead.
141
141
 
142
- | Operation | JavaScript | WASM | Speedup |
143
- | ------------------- | ---------- | ----- | ------- |
144
- | Parse 100 lines | 5ms | 0.5ms | 10x |
145
- | Parse 1000 lines | 50ms | 5ms | 10x |
146
- | Validate 1000 lines | 30ms | 2ms | 15x |
142
+ Measured on i7-11800H / Node v22.20.0 / `wasm-pack` release build
143
+ (`wasm-opt -O3 --enable-bulk-memory --enable-nontrapping-float-to-int`):
144
+
145
+ | Fixture | WASM vs JS speedup |
146
+ | ------------------ | ------------------------ |
147
+ | small (32 lines) | 0.66-0.74x (JS faster) |
148
+ | medium (78 lines) | 0.64-0.67x (JS faster) |
149
+ | large (142 lines) | 0.64-0.66x (JS faster) |
150
+
151
+ Native Rust (no WASM boundary) is ~1.3-1.4x faster than JS, so the
152
+ parser logic itself is competitive — the boundary is the bottleneck.
153
+
154
+ Use WASM only when the V8 JIT is not available (mobile WebViews,
155
+ edge workers, sandboxed runtimes).
156
+
157
+ Full methodology and raw data: `research/2026-04-19_todo-r2-wasm-bench-results.md`.
147
158
 
148
159
  ## Browser Compatibility
149
160
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holoscript/wasm",
3
- "version": "6.0.3",
3
+ "version": "7.0.0",
4
4
  "description": "HoloScript parser compiled to WebAssembly for high-performance browser execution",
5
5
  "main": "pkg/holoscript_wasm.js",
6
6
  "types": "pkg/holoscript_wasm.d.ts",
@@ -0,0 +1,365 @@
1
+ /* @ts-self-types="./holoscript_wasm.d.ts" */
2
+
3
+ export function init() {
4
+ wasm.init();
5
+ }
6
+
7
+ /**
8
+ * Parse HoloScript source code and return AST as JSON.
9
+ *
10
+ * # Arguments
11
+ * * `source` - The HoloScript source code to parse
12
+ *
13
+ * # Returns
14
+ * A JSON string containing the AST or an error object
15
+ * @param {string} source
16
+ * @returns {string}
17
+ */
18
+ export function parse(source) {
19
+ let deferred2_0;
20
+ let deferred2_1;
21
+ try {
22
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
23
+ const ptr0 = passStringToWasm0(source, wasm.__wbindgen_export2, wasm.__wbindgen_export3);
24
+ const len0 = WASM_VECTOR_LEN;
25
+ wasm.parse(retptr, ptr0, len0);
26
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
27
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
28
+ deferred2_0 = r0;
29
+ deferred2_1 = r1;
30
+ return getStringFromWasm0(r0, r1);
31
+ } finally {
32
+ wasm.__wbindgen_add_to_stack_pointer(16);
33
+ wasm.__wbindgen_export(deferred2_0, deferred2_1, 1);
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Parse HoloScript and return a pretty-printed JSON AST.
39
+ * @param {string} source
40
+ * @returns {string}
41
+ */
42
+ export function parse_pretty(source) {
43
+ let deferred2_0;
44
+ let deferred2_1;
45
+ try {
46
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
47
+ const ptr0 = passStringToWasm0(source, wasm.__wbindgen_export2, wasm.__wbindgen_export3);
48
+ const len0 = WASM_VECTOR_LEN;
49
+ wasm.parse_pretty(retptr, ptr0, len0);
50
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
51
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
52
+ deferred2_0 = r0;
53
+ deferred2_1 = r1;
54
+ return getStringFromWasm0(r0, r1);
55
+ } finally {
56
+ wasm.__wbindgen_add_to_stack_pointer(16);
57
+ wasm.__wbindgen_export(deferred2_0, deferred2_1, 1);
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Validate HoloScript source code without returning the full AST.
63
+ *
64
+ * # Returns
65
+ * `true` if the source is valid, `false` otherwise
66
+ * @param {string} source
67
+ * @returns {boolean}
68
+ */
69
+ export function validate(source) {
70
+ const ptr0 = passStringToWasm0(source, wasm.__wbindgen_export2, wasm.__wbindgen_export3);
71
+ const len0 = WASM_VECTOR_LEN;
72
+ const ret = wasm.validate(ptr0, len0);
73
+ return ret !== 0;
74
+ }
75
+
76
+ /**
77
+ * Get detailed validation results as JSON.
78
+ * @param {string} source
79
+ * @returns {string}
80
+ */
81
+ export function validate_detailed(source) {
82
+ let deferred2_0;
83
+ let deferred2_1;
84
+ try {
85
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
86
+ const ptr0 = passStringToWasm0(source, wasm.__wbindgen_export2, wasm.__wbindgen_export3);
87
+ const len0 = WASM_VECTOR_LEN;
88
+ wasm.validate_detailed(retptr, ptr0, len0);
89
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
90
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
91
+ deferred2_0 = r0;
92
+ deferred2_1 = r1;
93
+ return getStringFromWasm0(r0, r1);
94
+ } finally {
95
+ wasm.__wbindgen_add_to_stack_pointer(16);
96
+ wasm.__wbindgen_export(deferred2_0, deferred2_1, 1);
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Get the version of the WASM compiler.
102
+ * @returns {string}
103
+ */
104
+ export function version() {
105
+ let deferred1_0;
106
+ let deferred1_1;
107
+ try {
108
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
109
+ wasm.version(retptr);
110
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
111
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
112
+ deferred1_0 = r0;
113
+ deferred1_1 = r1;
114
+ return getStringFromWasm0(r0, r1);
115
+ } finally {
116
+ wasm.__wbindgen_add_to_stack_pointer(16);
117
+ wasm.__wbindgen_export(deferred1_0, deferred1_1, 1);
118
+ }
119
+ }
120
+
121
+ function __wbg_get_imports() {
122
+ const import0 = {
123
+ __proto__: null,
124
+ __wbg___wbindgen_throw_be289d5034ed271b: function(arg0, arg1) {
125
+ throw new Error(getStringFromWasm0(arg0, arg1));
126
+ },
127
+ __wbg_error_7534b8e9a36f1ab4: function(arg0, arg1) {
128
+ let deferred0_0;
129
+ let deferred0_1;
130
+ try {
131
+ deferred0_0 = arg0;
132
+ deferred0_1 = arg1;
133
+ console.error(getStringFromWasm0(arg0, arg1));
134
+ } finally {
135
+ wasm.__wbindgen_export(deferred0_0, deferred0_1, 1);
136
+ }
137
+ },
138
+ __wbg_new_8a6f238a6ece86ea: function() {
139
+ const ret = new Error();
140
+ return addHeapObject(ret);
141
+ },
142
+ __wbg_stack_0ed75d68575b0f3c: function(arg0, arg1) {
143
+ const ret = getObject(arg1).stack;
144
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export2, wasm.__wbindgen_export3);
145
+ const len1 = WASM_VECTOR_LEN;
146
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
147
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
148
+ },
149
+ __wbindgen_object_drop_ref: function(arg0) {
150
+ takeObject(arg0);
151
+ },
152
+ };
153
+ return {
154
+ __proto__: null,
155
+ "./holoscript_wasm_bg.js": import0,
156
+ };
157
+ }
158
+
159
+ function addHeapObject(obj) {
160
+ if (heap_next === heap.length) heap.push(heap.length + 1);
161
+ const idx = heap_next;
162
+ heap_next = heap[idx];
163
+
164
+ heap[idx] = obj;
165
+ return idx;
166
+ }
167
+
168
+ function dropObject(idx) {
169
+ if (idx < 132) return;
170
+ heap[idx] = heap_next;
171
+ heap_next = idx;
172
+ }
173
+
174
+ let cachedDataViewMemory0 = null;
175
+ function getDataViewMemory0() {
176
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
177
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
178
+ }
179
+ return cachedDataViewMemory0;
180
+ }
181
+
182
+ function getStringFromWasm0(ptr, len) {
183
+ ptr = ptr >>> 0;
184
+ return decodeText(ptr, len);
185
+ }
186
+
187
+ let cachedUint8ArrayMemory0 = null;
188
+ function getUint8ArrayMemory0() {
189
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
190
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
191
+ }
192
+ return cachedUint8ArrayMemory0;
193
+ }
194
+
195
+ function getObject(idx) { return heap[idx]; }
196
+
197
+ let heap = new Array(128).fill(undefined);
198
+ heap.push(undefined, null, true, false);
199
+
200
+ let heap_next = heap.length;
201
+
202
+ function passStringToWasm0(arg, malloc, realloc) {
203
+ if (realloc === undefined) {
204
+ const buf = cachedTextEncoder.encode(arg);
205
+ const ptr = malloc(buf.length, 1) >>> 0;
206
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
207
+ WASM_VECTOR_LEN = buf.length;
208
+ return ptr;
209
+ }
210
+
211
+ let len = arg.length;
212
+ let ptr = malloc(len, 1) >>> 0;
213
+
214
+ const mem = getUint8ArrayMemory0();
215
+
216
+ let offset = 0;
217
+
218
+ for (; offset < len; offset++) {
219
+ const code = arg.charCodeAt(offset);
220
+ if (code > 0x7F) break;
221
+ mem[ptr + offset] = code;
222
+ }
223
+ if (offset !== len) {
224
+ if (offset !== 0) {
225
+ arg = arg.slice(offset);
226
+ }
227
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
228
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
229
+ const ret = cachedTextEncoder.encodeInto(arg, view);
230
+
231
+ offset += ret.written;
232
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
233
+ }
234
+
235
+ WASM_VECTOR_LEN = offset;
236
+ return ptr;
237
+ }
238
+
239
+ function takeObject(idx) {
240
+ const ret = getObject(idx);
241
+ dropObject(idx);
242
+ return ret;
243
+ }
244
+
245
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
246
+ cachedTextDecoder.decode();
247
+ const MAX_SAFARI_DECODE_BYTES = 2146435072;
248
+ let numBytesDecoded = 0;
249
+ function decodeText(ptr, len) {
250
+ numBytesDecoded += len;
251
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
252
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
253
+ cachedTextDecoder.decode();
254
+ numBytesDecoded = len;
255
+ }
256
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
257
+ }
258
+
259
+ const cachedTextEncoder = new TextEncoder();
260
+
261
+ if (!('encodeInto' in cachedTextEncoder)) {
262
+ cachedTextEncoder.encodeInto = function (arg, view) {
263
+ const buf = cachedTextEncoder.encode(arg);
264
+ view.set(buf);
265
+ return {
266
+ read: arg.length,
267
+ written: buf.length
268
+ };
269
+ };
270
+ }
271
+
272
+ let WASM_VECTOR_LEN = 0;
273
+
274
+ let wasmModule, wasm;
275
+ function __wbg_finalize_init(instance, module) {
276
+ wasm = instance.exports;
277
+ wasmModule = module;
278
+ cachedDataViewMemory0 = null;
279
+ cachedUint8ArrayMemory0 = null;
280
+ wasm.__wbindgen_start();
281
+ return wasm;
282
+ }
283
+
284
+ async function __wbg_load(module, imports) {
285
+ if (typeof Response === 'function' && module instanceof Response) {
286
+ if (typeof WebAssembly.instantiateStreaming === 'function') {
287
+ try {
288
+ return await WebAssembly.instantiateStreaming(module, imports);
289
+ } catch (e) {
290
+ const validResponse = module.ok && expectedResponseType(module.type);
291
+
292
+ if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
293
+ console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
294
+
295
+ } else { throw e; }
296
+ }
297
+ }
298
+
299
+ const bytes = await module.arrayBuffer();
300
+ return await WebAssembly.instantiate(bytes, imports);
301
+ } else {
302
+ const instance = await WebAssembly.instantiate(module, imports);
303
+
304
+ if (instance instanceof WebAssembly.Instance) {
305
+ return { instance, module };
306
+ } else {
307
+ return instance;
308
+ }
309
+ }
310
+
311
+ function expectedResponseType(type) {
312
+ switch (type) {
313
+ case 'basic': case 'cors': case 'default': return true;
314
+ }
315
+ return false;
316
+ }
317
+ }
318
+
319
+ function initSync(module) {
320
+ if (wasm !== undefined) return wasm;
321
+
322
+
323
+ if (module !== undefined) {
324
+ if (Object.getPrototypeOf(module) === Object.prototype) {
325
+ ({module} = module)
326
+ } else {
327
+ console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
328
+ }
329
+ }
330
+
331
+ const imports = __wbg_get_imports();
332
+ if (!(module instanceof WebAssembly.Module)) {
333
+ module = new WebAssembly.Module(module);
334
+ }
335
+ const instance = new WebAssembly.Instance(module, imports);
336
+ return __wbg_finalize_init(instance, module);
337
+ }
338
+
339
+ async function __wbg_init(module_or_path) {
340
+ if (wasm !== undefined) return wasm;
341
+
342
+
343
+ if (module_or_path !== undefined) {
344
+ if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
345
+ ({module_or_path} = module_or_path)
346
+ } else {
347
+ console.warn('using deprecated parameters for the initialization function; pass a single object instead')
348
+ }
349
+ }
350
+
351
+ if (module_or_path === undefined) {
352
+ module_or_path = new URL('holoscript_wasm_bg.wasm', import.meta.url);
353
+ }
354
+ const imports = __wbg_get_imports();
355
+
356
+ if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
357
+ module_or_path = fetch(module_or_path);
358
+ }
359
+
360
+ const { instance, module } = await __wbg_load(await module_or_path, imports);
361
+
362
+ return __wbg_finalize_init(instance, module);
363
+ }
364
+
365
+ export { initSync, __wbg_init as default };