jz 0.5.1 → 0.7.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.
Files changed (86) hide show
  1. package/README.md +315 -318
  2. package/bench/README.md +369 -0
  3. package/bench/bench.svg +102 -0
  4. package/cli.js +104 -30
  5. package/dist/interop.js +1 -0
  6. package/dist/jz.js +6024 -0
  7. package/index.d.ts +126 -0
  8. package/index.js +362 -84
  9. package/interop.js +159 -186
  10. package/jz.svg +5 -0
  11. package/jzify/arguments.js +97 -0
  12. package/jzify/bundler.js +382 -0
  13. package/jzify/classes.js +328 -0
  14. package/jzify/hoist-vars.js +177 -0
  15. package/jzify/index.js +51 -0
  16. package/jzify/names.js +37 -0
  17. package/jzify/switch.js +106 -0
  18. package/jzify/transform.js +349 -0
  19. package/layout.js +184 -0
  20. package/module/array.js +377 -176
  21. package/module/collection.js +639 -145
  22. package/module/console.js +55 -43
  23. package/module/core.js +264 -153
  24. package/module/date.js +15 -3
  25. package/module/function.js +73 -6
  26. package/module/index.js +2 -1
  27. package/module/json.js +226 -61
  28. package/module/math.js +551 -187
  29. package/module/number.js +327 -60
  30. package/module/object.js +474 -184
  31. package/module/regex.js +255 -25
  32. package/module/schema.js +24 -6
  33. package/module/simd.js +117 -0
  34. package/module/string.js +621 -226
  35. package/module/symbol.js +1 -1
  36. package/module/timer.js +9 -14
  37. package/module/typedarray.js +459 -73
  38. package/package.json +58 -14
  39. package/src/abi/index.js +39 -23
  40. package/src/abi/string.js +38 -41
  41. package/src/ast.js +460 -0
  42. package/src/autoload.js +29 -24
  43. package/src/bridge.js +111 -0
  44. package/src/compile/analyze-scans.js +824 -0
  45. package/src/compile/analyze.js +1600 -0
  46. package/src/compile/emit-assign.js +411 -0
  47. package/src/compile/emit.js +3512 -0
  48. package/src/compile/flow-types.js +103 -0
  49. package/src/{compile.js → compile/index.js} +778 -128
  50. package/src/{infer.js → compile/infer.js} +62 -98
  51. package/src/compile/loop-divmod.js +155 -0
  52. package/src/{narrow.js → compile/narrow.js} +409 -106
  53. package/src/compile/peel-stencil.js +261 -0
  54. package/src/compile/plan/advise.js +370 -0
  55. package/src/compile/plan/common.js +150 -0
  56. package/src/compile/plan/index.js +122 -0
  57. package/src/compile/plan/inline.js +682 -0
  58. package/src/compile/plan/literals.js +1199 -0
  59. package/src/compile/plan/loops.js +472 -0
  60. package/src/compile/plan/scope.js +649 -0
  61. package/src/compile/program-facts.js +423 -0
  62. package/src/ctx.js +220 -64
  63. package/src/ir.js +589 -172
  64. package/src/kind-traits.js +132 -0
  65. package/src/kind.js +524 -0
  66. package/src/op-policy.js +57 -0
  67. package/src/{optimize.js → optimize/index.js} +1432 -473
  68. package/src/optimize/vectorize.js +4660 -0
  69. package/src/param-reps.js +65 -0
  70. package/src/parse.js +44 -0
  71. package/src/{prepare.js → prepare/index.js} +649 -205
  72. package/src/prepare/lift-iife.js +149 -0
  73. package/src/reps.js +116 -0
  74. package/src/resolve.js +12 -3
  75. package/src/static.js +208 -0
  76. package/src/type.js +651 -0
  77. package/src/{assemble.js → wat/assemble.js} +275 -55
  78. package/src/wat/optimize.js +3938 -0
  79. package/transform.js +21 -0
  80. package/wasi.js +47 -5
  81. package/src/analyze.js +0 -3818
  82. package/src/emit.js +0 -3040
  83. package/src/jzify.js +0 -1580
  84. package/src/plan.js +0 -2132
  85. package/src/vectorize.js +0 -1088
  86. /package/src/{codegen.js → wat/codegen.js} +0 -0
package/transform.js ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * jz/transform — full JS source → canonical jz source.
3
+ *
4
+ * Parses, lowers full-JS forms (var/function/class/switch/==/undefined/…) into the
5
+ * jz subset via jzify, and pretty-prints back to jz source. The compile path runs
6
+ * jzify on the AST directly (default-on); this is the standalone source→source tool
7
+ * for tooling and REPLs ("clean my JS to the subset", auto-transform on paste).
8
+ *
9
+ * @module jz/transform
10
+ */
11
+ import { parse } from 'subscript/feature/jessie'
12
+ import jzify from './jzify/index.js'
13
+ import { codegen } from './src/wat/codegen.js'
14
+
15
+ /**
16
+ * @param {string} code - full-JS source
17
+ * @returns {string} canonical jz source
18
+ */
19
+ export default function transform(code) {
20
+ return codegen(jzify(parse(code)))
21
+ }
package/wasi.js CHANGED
@@ -1,9 +1,18 @@
1
1
  /**
2
- * WASI Preview 1 polyfill for jz modules.
2
+ * WASI shim for jz-emitted modules — NOT a general WASI Preview 1 runtime.
3
3
  *
4
- * Provides wasi_snapshot_preview1 imports for environments without native WASI.
5
- * The compiled .wasm uses standard WASI — runs natively on wasmtime/wasmer/deno.
6
- * This polyfill is only needed for browsers and plain Node.
4
+ * jz emits only the few `wasi_snapshot_preview1` imports its lowerings use:
5
+ * `fd_write` (console.log/error), `fd_read` (stdin), `clock_time_get`
6
+ * (Date.now/performance.now/timers), `random_get` (only with `{ randomSeed: true }`,
7
+ * to seed Math.random), plus no-op `proc_exit` / `environ_*` stubs. This shim
8
+ * implements exactly that set, so jz modules run in browsers and plain Node
9
+ * without native WASI. (The compiled `.wasm` uses standard WASI and runs on
10
+ * wasmtime/wasmer/deno natively — the shim is only for hosts that lack WASI.)
11
+ *
12
+ * It is deliberately NOT a complete Preview 1 polyfill: `args_get`,
13
+ * `fd_fdstat_get`, `fd_prestat_dir_name`, `poll_oneoff`, `path_*` etc. are absent
14
+ * because jz never emits them. To run an arbitrary (e.g. C-compiled) WASI program,
15
+ * use a real runtime — wasmtime/wasmer/deno or Node's `node:wasi`.
7
16
  *
8
17
  * @example
9
18
  * import { instantiate } from 'jz/wasi'
@@ -19,6 +28,8 @@
19
28
  * @param {function} [opts.write] - Custom write: (fd, text) => void
20
29
  * @param {function} [opts.read] - Custom read: (fd, buf: Uint8Array) => bytesRead
21
30
  */
31
+ const TEXT_DEC = new TextDecoder() // reused across every fd_write (was per-iov alloc)
32
+
22
33
  export function wasi(opts = {}) {
23
34
  let mem = null
24
35
  const fallbackWrite = (fd, text) => {
@@ -52,7 +63,7 @@ export function wasi(opts = {}) {
52
63
  for (let i = 0; i < iovs_len; i++) {
53
64
  const ptr = dv.getUint32(iovs + i * 8, true)
54
65
  const len = dv.getUint32(iovs + i * 8 + 4, true)
55
- write(fd, new TextDecoder().decode(new Uint8Array(mem.buffer, ptr, len)))
66
+ write(fd, TEXT_DEC.decode(new Uint8Array(mem.buffer, ptr, len)))
56
67
  written += len
57
68
  }
58
69
  dv.setUint32(nwritten, written, true)
@@ -66,6 +77,14 @@ export function wasi(opts = {}) {
66
77
  dv.setBigInt64(result_ptr, now, true)
67
78
  return 0
68
79
  },
80
+ // Present only for modules compiled with { randomSeed: true } — one read of
81
+ // OS entropy to seed Math.random. Prefers crypto; falls back to Math.random.
82
+ random_get(buf, buf_len) {
83
+ const bytes = new Uint8Array(mem.buffer, buf, buf_len)
84
+ if (globalThis.crypto?.getRandomValues) globalThis.crypto.getRandomValues(bytes)
85
+ else for (let i = 0; i < buf_len; i++) bytes[i] = (Math.random() * 256) | 0
86
+ return 0
87
+ },
69
88
  proc_exit() {},
70
89
  environ_sizes_get(count_ptr, size_ptr) {
71
90
  const dv = new DataView(mem.buffer)
@@ -79,6 +98,29 @@ export function wasi(opts = {}) {
79
98
  }
80
99
  }
81
100
 
101
+ /**
102
+ * Drive a `host: 'wasi'` module's WASM timer queue from JS scheduling.
103
+ *
104
+ * The wasi timer lowering compiles `setTimeout`/`setInterval` into an in-wasm
105
+ * queue drained by the exported `__timer_tick` (returns ms until the next due
106
+ * callback, ≤0 when the queue is empty). A native runtime ticks it from its own
107
+ * event loop; in a JS host we poll via `setInterval`, stopping once the queue
108
+ * drains. No-op for modules without timers. (The `host: 'js'` build lowers to
109
+ * `env.setTimeout` instead — that path lives in interop.js, not here.)
110
+ *
111
+ * @param {WebAssembly.Instance} inst
112
+ */
113
+ export const attachTimers = (inst) => {
114
+ if (!inst.exports.__timer_tick) return
115
+ const tick = inst.exports.__timer_tick
116
+ let hadTimers = false
117
+ const id = setInterval(() => {
118
+ const remaining = tick()
119
+ if (remaining > 0) hadTimers = true
120
+ if (hadTimers && remaining <= 0) clearInterval(id)
121
+ }, 1)
122
+ }
123
+
82
124
  /**
83
125
  * Compile and instantiate a jz WASI module.
84
126
  * @param {BufferSource} wasm