gofront 1.6.1 → 1.8.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 (132) hide show
  1. package/README.md +45 -49
  2. package/package.json +12 -8
  3. package/src/backend/js/expressions.js +1627 -148
  4. package/src/backend/js/fmt-runtime.js +573 -0
  5. package/src/backend/js/index.js +508 -102
  6. package/src/backend/js/runtime.js +1997 -106
  7. package/src/backend/js/statements.js +931 -87
  8. package/src/backend/js/stdlib/bits.js +87 -14
  9. package/src/backend/js/stdlib/builder.js +41 -6
  10. package/src/backend/js/stdlib/bytes.js +253 -7
  11. package/src/backend/js/stdlib/errors.js +7 -1
  12. package/src/backend/js/stdlib/fmt.js +349 -10
  13. package/src/backend/js/stdlib/index.js +19 -2
  14. package/src/backend/js/stdlib/json.js +1167 -0
  15. package/src/backend/js/stdlib/maps.js +0 -8
  16. package/src/backend/js/stdlib/math.js +17 -1
  17. package/src/backend/js/stdlib/simd.js +34 -0
  18. package/src/backend/js/stdlib/slices.js +36 -6
  19. package/src/backend/js/stdlib/strconv.js +10 -5
  20. package/src/backend/js/stdlib/strings.js +83 -4
  21. package/src/backend/js/stdlib/testing.js +7 -0
  22. package/src/backend/js/stdlib/time.js +79 -55
  23. package/src/backend/js/stdlib/unicode.js +1 -1
  24. package/src/backend/js/stdlib/utf8.js +1 -1
  25. package/src/backend/js/templ.js +38 -76
  26. package/src/backend/js/type-info.js +272 -0
  27. package/src/backend/shared/fmt-types.js +188 -0
  28. package/src/backend/wasm/boundary.js +446 -72
  29. package/src/backend/wasm/emit-builtins.js +320 -13
  30. package/src/backend/wasm/emit-exprs.js +1404 -199
  31. package/src/backend/wasm/emit-maps.js +61 -13
  32. package/src/backend/wasm/emit-stmts.js +1359 -164
  33. package/src/backend/wasm/emit.js +518 -74
  34. package/src/backend/wasm/encode.js +128 -13
  35. package/src/backend/wasm/globals.js +452 -0
  36. package/src/backend/wasm/index.js +194 -2489
  37. package/src/backend/wasm/method-expr.js +381 -0
  38. package/src/backend/wasm/module-emitter.js +2240 -0
  39. package/src/backend/wasm/monomorph.js +62 -4
  40. package/src/backend/wasm/optimize.js +4 -2
  41. package/src/backend/wasm/prescan.js +397 -0
  42. package/src/backend/wasm/stdlib/bytes.js +1804 -127
  43. package/src/backend/wasm/stdlib/core.js +1574 -199
  44. package/src/backend/wasm/stdlib/index.js +3 -5
  45. package/src/backend/wasm/stdlib/io.js +1567 -150
  46. package/src/backend/wasm/stdlib/packages.js +2 -0
  47. package/src/backend/wasm/stdlib/simd.js +499 -0
  48. package/src/backend/wasm/stdlib/time.js +1041 -12
  49. package/src/backend/wasm/types.js +221 -15
  50. package/src/backend/wasm/variadic.js +93 -0
  51. package/src/backend/wasm/wat.js +84 -20
  52. package/src/{cli-core.js → cli/cli-core.js} +236 -10
  53. package/src/{test-runner.js → cli/test-runner.js} +332 -39
  54. package/src/{vendor.js → cli/vendor.js} +89 -15
  55. package/src/compiler.js +107 -269
  56. package/src/dts-parser.js +71 -14
  57. package/src/index.js +15 -169
  58. package/src/{lexer.js → lexer/lexer.js} +102 -55
  59. package/src/{tokens.js → lexer/tokens.js} +1 -0
  60. package/src/link/sourcemap.js +97 -0
  61. package/src/link/stdlib.js +515 -0
  62. package/src/link/wasm.js +294 -0
  63. package/src/lower/bounds.js +394 -0
  64. package/src/lower/boxing.js +1 -6
  65. package/src/lower/captures.js +176 -32
  66. package/src/lower/embedding.js +2 -1
  67. package/src/lower/index.js +26 -18
  68. package/src/lower/json-codecs.js +1398 -0
  69. package/src/lower/ownership.js +22 -1
  70. package/src/lower/range.js +86 -1
  71. package/src/lower/reachability.js +132 -0
  72. package/src/parser/declarations.js +58 -13
  73. package/src/parser/expressions.js +29 -7
  74. package/src/parser/index.js +2 -1
  75. package/src/parser/statements.js +37 -22
  76. package/src/parser/struct-tag.js +144 -0
  77. package/src/{templ-parser.js → parser/templ.js} +138 -15
  78. package/src/parser/types.js +130 -13
  79. package/src/resolver.js +22 -1
  80. package/src/typechecker/assignability.js +215 -11
  81. package/src/typechecker/const-fold.js +356 -0
  82. package/src/typechecker/constants.js +256 -0
  83. package/src/typechecker/expressions.js +960 -99
  84. package/src/typechecker/index.js +491 -72
  85. package/src/typechecker/init-order.js +330 -0
  86. package/src/typechecker/resolve.js +596 -52
  87. package/src/typechecker/statements.js +157 -17
  88. package/src/typechecker/stdlib/core.js +333 -55
  89. package/src/typechecker/stdlib/excluded.js +898 -0
  90. package/src/typechecker/stdlib/extended.js +359 -26
  91. package/src/typechecker/{stdlib.js → stdlib/index.js} +6 -4
  92. package/src/typechecker/stdlib/simd.js +123 -0
  93. package/src/typechecker/termination.js +1 -1
  94. package/src/typechecker/types.js +165 -26
  95. package/stdlib/bytes/iter.go +192 -0
  96. package/stdlib/bytes/search.go +240 -0
  97. package/stdlib/bytes/split.go +218 -0
  98. package/stdlib/cmp/cmp.go +65 -0
  99. package/stdlib/encoding/json/errors.go +31 -0
  100. package/stdlib/encoding/json/indent.go +71 -0
  101. package/stdlib/encoding/json/number.go +12 -0
  102. package/stdlib/encoding/json/stream.go +173 -0
  103. package/stdlib/errors/overlay.go +12 -0
  104. package/stdlib/hash/hash.go +53 -0
  105. package/stdlib/internal/jsonrt/dec.go +738 -0
  106. package/stdlib/internal/jsonrt/enc.go +366 -0
  107. package/stdlib/internal/jsonrt/indent.go +135 -0
  108. package/stdlib/internal/jsonrt/number.go +27 -0
  109. package/stdlib/internal/jsonrt/reader.go +73 -0
  110. package/stdlib/internal/jsonrt/scanner.go +649 -0
  111. package/stdlib/io/io.go +346 -0
  112. package/stdlib/iter/iter.go +18 -0
  113. package/stdlib/maps/iter.go +65 -0
  114. package/stdlib/math/extra.go +270 -0
  115. package/stdlib/slices/extra.go +73 -0
  116. package/stdlib/slices/iter.go +113 -0
  117. package/stdlib/sort/sort.go +561 -0
  118. package/stdlib/strconv/quote.go +341 -0
  119. package/stdlib/strings/extra.go +35 -0
  120. package/stdlib/strings/iter.go +122 -0
  121. package/stdlib/sync/extra.go +105 -0
  122. package/stdlib/unicode/unicode.go +112 -0
  123. package/stdlib/unicode/utf8/bytes.go +239 -0
  124. package/src/backend/wasm/const-fold.js +0 -205
  125. package/src/backend/wasm/emit-stdlib.js +0 -13
  126. /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
  127. /package/src/{colors.js → cli/colors.js} +0 -0
  128. /package/src/{dev-server.js → cli/dev-server.js} +0 -0
  129. /package/src/{minifier.js → cli/minifier.js} +0 -0
  130. /package/src/{project-config.js → cli/project-config.js} +0 -0
  131. /package/src/{pwa.js → cli/pwa.js} +0 -0
  132. /package/src/{templ-lexer.js → lexer/templ-lexer.js} +0 -0
package/README.md CHANGED
@@ -136,45 +136,41 @@ example/simple/
136
136
  app.js ← generated output
137
137
  ```
138
138
 
139
- ### Reactive (signals + d.ts imports)
139
+ ### Preact (components, hooks + d.ts tuples)
140
140
 
141
- Same app rebuilt with [reactive.js](https://github.com/seriva/microtastic), a tiny
142
- signals-based reactive framework. Demonstrates how GoFront integrates with external JS
143
- libraries via `.d.ts` type declarations — the entire reactive API surface is typed via a
144
- hand-written `browser.d.ts` shim and exercised from GoFront source.
141
+ Same app rebuilt with [Preact](https://preactjs.com), using function components and hooks (`useState`, `useEffect`). Demonstrates how GoFront integrates with external JS libraries via `.d.ts` type declarations — TypeScript tuple return signatures (`[T, (v: T) => void]`) map directly to Go multi-value returns, allowing idiomatic Go hook destructuring:
145
142
 
146
- > **Note:** Microtastic is now archived. This example is kept as a reference for
147
- > `.d.ts` interop with third-party signal libraries. For new projects, use the native
148
- > `.templ` or `gom` approaches shown below.
143
+ ```go
144
+ func TodoItem(p TodoItemProps) VNode {
145
+ editing, setEditing := useState(false)
146
+ return h("li", map[string]any{"class": itemClass(p.Todo, editing)}, ...)
147
+ }
148
+ ```
149
149
 
150
150
  ```
151
- example/reactive/
151
+ example/preact/
152
152
  src/
153
- types.go ← Todo, Stats, AppElements structs
154
- store.go ← reactive state: Signals.create/computed/computedAsync/batch/update
155
- render.go ← Reactive.Component lifecycle · ctx.bind* · setupStatsBar
156
- styles.go ← per-section cssClass() scoped styles
157
- main.go ← async boot, Reactive.mount loading placeholder, signal.subscribe/once
153
+ types.go ← Todo, Stats, and props structs
154
+ components.go ← TodoItem, Header, InputRow, Footer, StatsBar Preact components
155
+ main.go ← App root component, async storage load, save, drag-and-drop
158
156
  utils/
159
157
  utils.go ← Plural() · generic Filter
160
- browser.d.ts ← Signal · ComponentContext · Signals/Reactive namespaces · htmlTag
161
- reactive.js ← signals framework (from microtastic)
162
- index.html ← loads reactive.js, exposes helpers, imports app.js
158
+ preact.d.ts ← VNode · h · render · useState · useEffect · useRef · sleep
159
+ vendor.js ← bundled Preact & Preact hooks
160
+ index.html ← loads vendor.js, imports app.js
163
161
  app.js ← generated output
164
162
  ```
165
163
 
166
- The reactive example covers the full reactive.js API surface:
164
+ The preact example covers:
167
165
 
168
166
  | Category | Features used |
169
167
  |---|---|
170
- | HTML helpers | `html` tagged template (via `htmlTag`), `trusted`, `join` |
171
- | CSS | `cssClass` scoped styles with nested `&` selectors |
172
- | Signals | `create`, `computed`, `computedAsync`, `batch`, `get`, `peek`, `set`, `update`, `subscribe`, `once` |
173
- | Reactive namespace | `mount` (loading placeholder), `createComponent`, `scan` |
174
- | Component context | `bind`, `bindAttr`, `bindBoolAttr`, `bindClass`, `bindText`, `bindStyle`, `bindMultiple`, `computed` |
175
- | Component lifecycle | `state`, `template`, `styles`, `mount`, `mountTo`, `appendTo`, `refs` (via `data-ref`) |
176
- | Component instance | `signal`, `effect`, `on` (auto-cleanup event listeners) |
177
- | Scan attributes | `data-model`, `data-text`, `data-html`, `data-if`, `data-visible`, `data-class-*`, `data-attr-*`, `data-bool-*`, `data-on-*`, `data-ref` |
168
+ | Hyperscript | `h(type, props, ...children)` with variadic and array children |
169
+ | Function components | Pure function components with Go struct props |
170
+ | Hooks | `useState` with tuple destructuring (`state, setState := useState(init)`), `useEffect` |
171
+ | Tuples | Multi-value returns from TypeScript `.d.ts` tuple types |
172
+ | Vendoring | Bundled subpath packages (`preact/hooks`) with named global exports |
173
+ | Typed persistence | `encoding/json` `Marshal`/`Unmarshal` of `[]Todo` to `localStorage`, driven by struct tags |
178
174
 
179
175
  ### templ (template files + direct DOM codegen)
180
176
 
@@ -232,6 +228,7 @@ Key syntax features:
232
228
  - `@Component(args)` — call another templ component and mount it as a child
233
229
  - `if cond { } else if cond { } else { }` — conditional rendering (arbitrary depth)
234
230
  - `for _, v := range slice { }` — loop rendering inside template bodies
231
+ - Go expressions in template bodies are type-checked like the rest of the package
235
232
  - `switch expr { case v: ... default: ... }` — switch rendering inside template bodies
236
233
  - `@templ.Raw(htmlStr)` — inject raw/trusted HTML (uses `insertAdjacentHTML`)
237
234
  - `ref="name"` — capture the element at mount time into an optional `refs map[string]any`
@@ -276,17 +273,15 @@ Key types and functions (all accessed as `gom.*`, no import needed):
276
273
 
277
274
  ### Features demonstrated
278
275
 
279
- The simple and reactive examples cover: structs & methods, iota constants, named return
276
+ The simple and preact examples cover: structs & methods, iota constants, named return
280
277
  values, closures, slices, `for range`, `switch`, cross-package imports, multi-file
281
278
  same-package compilation, `async`/`await`, `defer`/`recover`, localStorage persistence,
282
- DOM APIs, and generic utility functions (`Filter[T]`, `Map[T, U]`).
279
+ DOM APIs, and generic utility functions (`Filter[T]`).
283
280
 
284
- The reactive example additionally demonstrates: external `.d.ts` type imports,
285
- `declare namespace` patterns for typing JS libraries, the full reactive signal graph
286
- (source signals → computed signals → async computed → DOM bindings), reactive UI with
287
- no `querySelector` or `getElementById` in application code, and `Reactive.Component`
288
- as the primary composition unit (state, template, styles, mount lifecycle, `data-ref`
289
- element refs, auto-cleanup event listeners).
281
+ The preact example additionally demonstrates: external `.d.ts` type imports,
282
+ TypeScript tuple return mapping to Go multi-value returns (`state, setState := useState(...)`),
283
+ Preact function components with field-only struct props, hooks-driven reactive rendering,
284
+ and npm dependency vendoring (`preact`, `preact/hooks`).
290
285
 
291
286
  The gom example additionally demonstrates: **the `gom` built-in stdlib package**,
292
287
  styles as nodes (`gom.Style` + `gom.MountTo`), `gom.Map` for list rendering, the
@@ -335,11 +330,17 @@ example/hybrid/
335
330
 
336
331
  ### Build and run
337
332
 
333
+ The examples are not committed pre-built. Build them once, then serve an example's
334
+ directory and open it in a browser:
335
+
338
336
  ```sh
339
337
  npm run build # compile all example applications
340
- # open the respective index.html in a browser
338
+ npx serve example/simple # then open the printed address
341
339
  ```
342
340
 
341
+ `example/preact/vendor.js` is the exception: it is committed, and
342
+ `node src/index.js prep example/preact` regenerates it.
343
+
343
344
  ---
344
345
 
345
346
  ## The Hybrid Architecture: JS + WasmGC
@@ -404,6 +405,7 @@ The compiler analyzes both sides of the boundary and synthesizes a facade into `
404
405
  - **Slices & Arrays:** Slices and arrays copy element-wise in both directions; TypedArrays (`Float32Array`, `Int32Array`, etc.) are natively accepted.
405
406
  - **Closures & Interfaces:** Function values, callbacks, and named non-empty interfaces cross the boundary transparently.
406
407
  - **Shared Linear-Memory Buffers:** `gofront/shared` (`shared.NewFloat32`, etc.) exposes zero-copy TypedArray views over linear memory for bulk per-frame data.
408
+ - **WASM SIMD (`gofront/simd`, experimental):** 4-wide float vector type (`simd.F32x4`) compiling directly to native `v128` instructions with zero GC overhead, including `simd.LoadF32x4`/`StoreF32x4` for direct linear-memory access (about 1.6× faster than a scalar loop on a particle-integration benchmark).
407
409
  - **WASM Loader:** The generated JS bundle automatically fetches `app.wasm` relative to `app.js` (`import.meta.url`, customizable via `globalThis.__GOFRONT_WASM_URL` or `globalThis.__GOFRONT_WASM_BYTES`).
408
410
  - **WAT Inspection:** Passing `--emit-wat` writes human-readable `app.wat` alongside the binary module.
409
411
  - **Binaryen Optimization:** Passing `--release` or `--wasm-opt` optimizes `app.wasm` via Binaryen (`-O3` + GUFA), achieving ~23% smaller binaries and generating `app.wasm.map` source maps.
@@ -452,31 +454,25 @@ For detailed command flags, project configuration (`gofront.json`), multi-file p
452
454
  * [Go to JS Mapping](docs/compilation-mapping.md) — what each construct compiles to
453
455
  * [Go Compatibility Differences](docs/go-compatibility.md) — where GoFront deliberately differs from Go
454
456
  * [Compiler Architecture & Internals](docs/architecture.md) — pipeline stages and source layout
455
-
456
- ---
457
-
458
- ## Roadmap
459
-
460
- See [`docs/roadmap.md`](docs/roadmap.md) for the full roadmap and release history.
461
- Design documents for planned features are organised by release under `docs/v*/`
462
- (e.g. [`docs/v0.0.8/`](docs/v0.0.8/), [`docs/v1.2.0/`](docs/v1.2.0/), [`docs/v1.3.0/`](docs/v1.3.0/), [`docs/v1.6.0/`](docs/v1.6.0/)).
457
+ * [Changelog](CHANGELOG.md) — release history and upgrade notes
463
458
 
464
459
  ---
465
460
 
466
461
  ## Tests
467
462
 
468
463
  ```sh
469
- npm test # unit, zero-alloc perf, and example tests (~1,800+ tests, no browser required)
464
+ npm test # unit, zero-alloc perf, and example tests (~2,900 tests, no browser required)
470
465
  npm run test:e2e # E2E browser tests (Playwright, headless Chromium)
471
- npm run bench # Möller–Trumbore raycast benchmark comparing pure JS vs hybrid WASM
466
+ npm run bench # Raycast, JSON, and SIMD particle benchmarks (pure JS vs hybrid WASM)
472
467
  ```
473
468
 
474
- **Unit tests** (~1,800+) cover language features, type errors, edge cases, DOM (jsdom),
475
- external `.d.ts`, npm resolver, multi-file compilation, embedded structs, string
476
- formatting, map iteration order, integer overflow semantics, unused variable detection,
469
+ **Unit tests** (~2,900) cover language features, type errors, edge cases, DOM (jsdom),
470
+ external `.d.ts`, npm resolver, TypeScript tuple return signatures, multi-file compilation,
471
+ embedded structs, string formatting, compile-time `encoding/json` serialization with struct tags,
472
+ map iteration order, integer overflow semantics, unused variable detection,
477
473
  unused import detection, semantic difference verification, stdlib shim packages, generics,
478
474
  the `testing` framework itself, the WasmGC backend and JS↔WASM boundary, `gofront/shared`
479
- linear-memory buffers, Binaryen optimization, and `.templ` file compilation (element rendering,
475
+ linear-memory buffers, `gofront/simd` vector arithmetic, Binaryen optimization, and `.templ` file compilation (element rendering,
480
476
  interpolation, boolean attrs, component calls, scoped `css` declarations with class hashing,
481
477
  `if/else/else-if` chains, `for range`, `switch/case/default`, `@templ.Raw()` raw HTML injection,
482
478
  SVG namespace handling, mixed `.go`+`.templ` packages).
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "gofront",
3
- "version": "1.6.1",
3
+ "version": "1.8.0",
4
4
  "author": "Luuk van Venrooij",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "https://github.com/seriva/gofront.git"
8
+ "url": "git+https://github.com/seriva/gofront.git"
9
9
  },
10
10
  "bugs": {
11
11
  "url": "https://github.com/seriva/gofront/issues"
@@ -28,27 +28,31 @@
28
28
  },
29
29
  "type": "module",
30
30
  "files": [
31
- "src/"
31
+ "src/",
32
+ "stdlib/"
32
33
  ],
33
34
  "bin": {
34
- "gofront": "./src/index.js"
35
+ "gofront": "src/index.js"
35
36
  },
36
37
  "scripts": {
37
- "build": "node src/index.js example/simple/src -o example/simple/app.js && node src/index.js example/reactive/src -o example/reactive/app.js && node src/index.js example/gom/src -o example/gom/app.js && node src/index.js example/templ/src -o example/templ/app.js && node src/index.js example/webgl/src -o example/webgl/app.js && node src/index.js example/hybrid/src -o example/hybrid/app.js",
38
- "test": "node test/unit/run.js && node test/e2e/perf/zero-alloc.js && node src/index.js test --dom example/...",
38
+ "build": "node scripts/build-examples.js",
39
+ "test": "node test/unit/run.js && node test/perf/zero-alloc.js && node test/perf/bce-mathx.js && node src/index.js test --dom example/...",
39
40
  "test:e2e": "playwright test",
40
41
  "test:coverage": "c8 --include='src/**' --reporter=text --reporter=lcov node test/unit/run.js",
41
- "bench": "node --expose-gc test/e2e/perf/raycast-bench.js",
42
+ "bench": "node --expose-gc test/perf/raycast-bench.js && node test/perf/json-bench.js && node --expose-gc test/perf/particle-bench.js",
43
+ "check:layers": "node scripts/check-layers.js",
42
44
  "format": "biome format --write .",
43
- "check": "biome check . && sentrux check && sentrux gate && node src/index.js check example/...",
45
+ "check": "biome check . && node scripts/check-layers.js && sentrux check && sentrux gate && node src/index.js check example/...",
44
46
  "prepare": "lefthook install"
45
47
  },
46
48
  "devDependencies": {
47
49
  "@biomejs/biome": "^2.5.15",
48
50
  "@playwright/test": "^1.63.0",
49
51
  "c8": "^12.0.0",
52
+ "esbuild": "^0.28.2",
50
53
  "jsdom": "^30.1.2",
51
54
  "lefthook": "^2.1.17",
55
+ "preact": "^11.0.1",
52
56
  "serve": "^14.2.6"
53
57
  },
54
58
  "optionalDependencies": {