solid-tag-runtime 0.0.11 → 0.0.13
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/ARCHITECTURE.md +167 -38
- package/README.md +76 -885
- package/docs/README.md +23 -0
- package/docs/api/compile-cache.md +103 -0
- package/docs/api/html.md +83 -0
- package/docs/api/runtime.md +87 -0
- package/docs/compile-cache.md +271 -0
- package/docs/getting-started.md +105 -0
- package/docs/html-runtime.md +112 -0
- package/docs/lifecycle-events.md +77 -0
- package/docs/modules.md +93 -0
- package/docs/rendering.md +65 -0
- package/docs/solid-render.md +111 -0
- package/examples/basic.js +41 -0
- package/examples/compile-cache.js +35 -0
- package/examples/main.tsx +318 -0
- package/examples/render.html +79 -0
- package/index.d.ts +183 -27
- package/package.json +5 -3
- package/src/compile-cache.js +340 -0
- package/src/compiler.js +86 -38
- package/src/html.js +191 -19
- package/src/index.js +6 -0
- package/src/runtime.js +656 -74
package/ARCHITECTURE.md
CHANGED
|
@@ -518,77 +518,166 @@ This avoids introducing a second template language, implicit lexical scope rules
|
|
|
518
518
|
|
|
519
519
|
## 9. Compiler adapter boundary
|
|
520
520
|
|
|
521
|
-
The runtime engine
|
|
521
|
+
The runtime engine remains independent of the `solid-tag` AST. `0.0.13` formalizes a linker-ready **CompiledArtifact** boundary so compiler work can be cached before runtime-specific linking.
|
|
522
522
|
|
|
523
|
-
|
|
523
|
+
Preferred compiler contract:
|
|
524
524
|
|
|
525
525
|
```ts
|
|
526
526
|
interface RuntimeCompiler {
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
527
|
+
fingerprint?: string | ((context: CompileContext) => string | Promise<string>);
|
|
528
|
+
cacheContext?: (context: CompileContext) => unknown | Promise<unknown>;
|
|
529
|
+
|
|
530
|
+
compile?(
|
|
531
|
+
source: string,
|
|
532
|
+
context: CompileContext,
|
|
533
|
+
): CompiledArtifact | Promise<CompiledArtifact>;
|
|
534
|
+
|
|
535
|
+
// Transitional compatibility path:
|
|
536
|
+
analyze?(source, context): { imports: ImportReference[] };
|
|
537
|
+
transform?(source, context): { code: string; diagnostics?: unknown[] };
|
|
536
538
|
}
|
|
537
539
|
```
|
|
538
540
|
|
|
539
|
-
The default adapter
|
|
541
|
+
The default adapter in `src/compiler.js` uses `solid-tag` and provides a stable fingerprint. JSX transformation runs **before** linking and intentionally leaves module specifiers unresolved. The resulting artifact is analyzed after transformation so import-reference offsets point into compiled JavaScript, not the original JSX source.
|
|
540
542
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
543
|
+
Conceptual artifact:
|
|
544
|
+
|
|
545
|
+
```ts
|
|
546
|
+
interface CompiledArtifact {
|
|
547
|
+
schema: 1;
|
|
548
|
+
code: string;
|
|
549
|
+
imports: ImportReference[];
|
|
550
|
+
diagnostics: unknown[];
|
|
551
|
+
sourceMap?: string;
|
|
552
|
+
}
|
|
544
553
|
```
|
|
545
554
|
|
|
555
|
+
The older `analyze()` + `transform()` pair remains supported for custom compilers. For that compatibility path the runtime transforms first, then analyzes the transformed code to construct the same artifact shape.
|
|
556
|
+
|
|
557
|
+
A custom compiler may compile normally without a fingerprint, but persistent artifact reuse is disabled because the runtime must never guess compiler identity.
|
|
558
|
+
|
|
546
559
|
### Why this boundary exists
|
|
547
560
|
|
|
548
|
-
It
|
|
561
|
+
It separates:
|
|
549
562
|
|
|
550
|
-
|
|
563
|
+
```text
|
|
564
|
+
compiler
|
|
565
|
+
syntax transformation + module-reference analysis
|
|
551
566
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
- reverse/tagged transformations for tooling
|
|
567
|
+
linker
|
|
568
|
+
runtime resolution + dependency URL rewriting
|
|
569
|
+
```
|
|
556
570
|
|
|
557
|
-
|
|
571
|
+
That boundary supports persistent compile caching and also keeps future TSX compilers, compiler workers, build-time artifacts, and alternate parsers independent from graph/link execution.
|
|
558
572
|
|
|
559
|
-
## 10.
|
|
573
|
+
## 10. Compile, cache, and linking pipeline
|
|
560
574
|
|
|
561
|
-
|
|
575
|
+
The source-module pipeline is now explicitly:
|
|
562
576
|
|
|
563
577
|
```text
|
|
564
578
|
source
|
|
565
579
|
↓
|
|
566
|
-
|
|
580
|
+
compile source syntax
|
|
567
581
|
↓
|
|
568
|
-
|
|
582
|
+
CompiledArtifact
|
|
583
|
+
│ transformed code
|
|
584
|
+
│ unresolved import specifiers
|
|
585
|
+
│ import offsets into transformed code
|
|
586
|
+
│ diagnostics/source map
|
|
587
|
+
│
|
|
588
|
+
├──────── optional persistent cache boundary
|
|
589
|
+
│
|
|
569
590
|
↓
|
|
570
|
-
resolve
|
|
591
|
+
resolve imports against current runtime graph
|
|
571
592
|
↓
|
|
572
|
-
ensure
|
|
593
|
+
ensure current dependency module URLs
|
|
573
594
|
↓
|
|
574
|
-
rewrite import
|
|
595
|
+
rewrite artifact import ranges
|
|
575
596
|
↓
|
|
576
|
-
|
|
597
|
+
linked executable JavaScript
|
|
577
598
|
↓
|
|
578
|
-
|
|
599
|
+
module URL backend
|
|
579
600
|
↓
|
|
580
|
-
import
|
|
601
|
+
native import/evaluation
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
For `/features/Counter.jsx`, the persistent artifact may still contain:
|
|
605
|
+
|
|
606
|
+
```js
|
|
607
|
+
import { createSignal } from "solid-js";
|
|
608
|
+
import html from "@solidjs/html";
|
|
609
|
+
import { Button } from "../ui/Button.jsx";
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
Only the linker turns those specifiers into current host bridges, external URLs, or generated runtime module URLs.
|
|
613
|
+
|
|
614
|
+
### Persistent compile cache
|
|
615
|
+
|
|
616
|
+
`0.0.13` adds an opt-in persistent compile cache.
|
|
617
|
+
|
|
618
|
+
The stored artifact is **pre-link**. Never persist:
|
|
619
|
+
|
|
620
|
+
- dependency Blob/data URLs
|
|
621
|
+
- linked executable source
|
|
622
|
+
- module URL backend output
|
|
623
|
+
- native module namespaces/import promises
|
|
624
|
+
- host bridge identities
|
|
625
|
+
- custom resolver output
|
|
626
|
+
|
|
627
|
+
Logical compile identity is content-addressed from:
|
|
628
|
+
|
|
629
|
+
```text
|
|
630
|
+
artifact ABI
|
|
631
|
+
+ compiler fingerprint
|
|
632
|
+
+ source format
|
|
633
|
+
+ compile-affecting context hash
|
|
634
|
+
+ exact source SHA-256
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
Module ID is excluded by default. Dependency source/version, resolver state, host values, and module URL backend are also excluded because they belong to linking/evaluation rather than compilation.
|
|
638
|
+
|
|
639
|
+
This means identical source can reuse one artifact under multiple module IDs while relative imports are still linked independently per importer.
|
|
640
|
+
|
|
641
|
+
Built-in stores:
|
|
642
|
+
|
|
643
|
+
```text
|
|
644
|
+
createIndexedDBCompileCache() recommended persistent browser backend
|
|
645
|
+
createLocalStorageCompileCache() convenience/small-artifact backend
|
|
646
|
+
createMemoryCompileCache() tests/benchmarks/process-local reuse
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
Persistent caching is configured on `createRuntime({ compileCache })` and remains fully opt-in.
|
|
650
|
+
|
|
651
|
+
### Invalidation layers
|
|
652
|
+
|
|
653
|
+
The runtime now distinguishes:
|
|
654
|
+
|
|
655
|
+
```text
|
|
656
|
+
compile artifact
|
|
657
|
+
linked executable graph
|
|
658
|
+
native evaluated module identity
|
|
581
659
|
```
|
|
582
660
|
|
|
583
|
-
|
|
661
|
+
Normal `runtime.invalidate(id)` invalidates linked/evaluated state while preserving the reusable compiled artifact. `runtime.invalidate(id, { compile: true })` additionally forces only the requested module to compile fresh on its next link. Dependents relink but retain their own compiler artifacts.
|
|
662
|
+
|
|
663
|
+
`runtime.update(id, newSource)` naturally computes a different content key for the changed source. Old persistent artifacts are not eagerly deleted because they may still be useful to another runtime, tab, module ID, or undo/revert operation.
|
|
664
|
+
|
|
665
|
+
Public `runtime.compile()` retains its existing meaning: it returns linked/executable code and URL. Internal persistent artifacts are not silently substituted into the public result.
|
|
666
|
+
|
|
667
|
+
### Cache controls
|
|
584
668
|
|
|
585
669
|
```text
|
|
586
|
-
/
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
└── ../ui/Button.jsx → compiled virtual source URL
|
|
670
|
+
use read reusable artifact; compile/write on miss
|
|
671
|
+
refresh compile requested module fresh and replace artifact
|
|
672
|
+
bypass compile requested module fresh without persistent read/write
|
|
590
673
|
```
|
|
591
674
|
|
|
675
|
+
Explicit persistent management lives under `runtime.compileCache` and is separate from graph removal/invalidation.
|
|
676
|
+
|
|
677
|
+
### Failure model
|
|
678
|
+
|
|
679
|
+
Persistent caching is an optimization. Read/write/validation/pruning failures emit compile-cache lifecycle diagnostics and fall back to normal compilation whenever possible. Explicit management operations may surface the storage error because the caller explicitly requested that storage mutation.
|
|
680
|
+
|
|
592
681
|
## 11. Resolution rules
|
|
593
682
|
|
|
594
683
|
Resolution order is conceptually:
|
|
@@ -1191,7 +1280,7 @@ The shared render adapter lazily resolves the host application's own `solid-js`
|
|
|
1191
1280
|
10. Initial light-DOM child nodes are captured once and exposed as reusable `props.children`; named slots and dynamic child recapture are not part of this phase.
|
|
1192
1281
|
11. Multiple elements may share one evaluated module namespace while owning independent Solid component roots.
|
|
1193
1282
|
12. Disconnect disposes the mounted root; reconnect mounts a fresh component instance from the retained declaration inputs.
|
|
1194
|
-
13. Custom-element registration is global/idempotent per `CustomElementRegistry
|
|
1283
|
+
13. Custom-element registration is global/idempotent per `CustomElementRegistry`, but controller creation does **not** eagerly upgrade existing `solid-render` elements. Initial `register()` / `observe()` first install the complete declarative script batch and then ensure the custom element is registered. `registerSolidRenderElement()` remains available for explicit/custom-registry use.
|
|
1195
1284
|
14. Runtime/controller disposal tears down both script-owned mounts and connected `solid-render` instances so no Solid owners are orphaned.
|
|
1196
1285
|
|
|
1197
1286
|
Rendering lifecycle joins the existing HTML event stream through `render-mounting`, `render-mounted`, `render-disposing`, and `render-disposed`; failures are also reported through `html-error` with `render`/`solid-render` operations. Lifecycle subscriptions remain observational and cannot alter rendering.
|
|
@@ -1235,3 +1324,43 @@ Rules now enforced:
|
|
|
1235
1324
|
7. `/ui/Button.jsx` and `./ui/Button.jsx` both resolve to the same registered virtual ID `/ui/Button.jsx` when imported at top level from the correct runtime.
|
|
1236
1325
|
|
|
1237
1326
|
This keeps DOM routing and module routing failures separate and produces actionable errors instead of accidental browser network requests.
|
|
1327
|
+
|
|
1328
|
+
|
|
1329
|
+
### 0.0.12 — declarative registration barrier for `solid-render`
|
|
1330
|
+
|
|
1331
|
+
Decision: an existing `<solid-render>` must never fail simply because its referenced `<script module>` has not yet been installed by the HTML adapter's initial registration pass.
|
|
1332
|
+
|
|
1333
|
+
The 0.0.11 routing fix correctly selected the containing runtime, but `createHTMLRuntime()` still registered the global custom element immediately. Defining a custom element upgrades already-present `<solid-render>` nodes synchronously. Their `connectedCallback()` could therefore call `runtime.import("/ui/Button.jsx")` before `html.register()` had scanned and defined an earlier `<script module="/ui/Button.jsx">`, producing a legitimate but transient `ModuleResolutionError`.
|
|
1334
|
+
|
|
1335
|
+
Rules now enforced:
|
|
1336
|
+
|
|
1337
|
+
1. `createHTMLRuntime()` installs the controller in the shared registry but does not eagerly define/upgrade `<solid-render>`.
|
|
1338
|
+
2. Initial `register()` and initial `observe()` install their complete matching script batch first, then ensure the global custom element is registered. This preserves document-level declaration-before-instance semantics even though custom-element upgrade timing is synchronous.
|
|
1339
|
+
3. If the `solid-render` class was already registered globally by another controller, a connected instance may still run before this controller's declaration pass. A missing virtual module during an active registration/observer pass is treated as a pending reference rather than a terminal render error.
|
|
1340
|
+
4. After the registration/observer batch settles, pending instances inside that controller's root are retried. If the module is still missing after the batch, normal `solid-render` error semantics apply.
|
|
1341
|
+
5. A pending instance is also retried when its selected runtime later emits `module-defined` for the resolved module ID. This supports dynamically arriving declarative/programmatic modules without remounting already-successful instances.
|
|
1342
|
+
6. Retries remain generation-guarded, so stale async work cannot replace a newer module/component/runtime identity.
|
|
1343
|
+
7. The existing graph invariant remains unchanged: all declarations in a discovered script batch are defined before entry/render execution or recovery mounts are allowed to succeed.
|
|
1344
|
+
|
|
1345
|
+
This separates three orderings that must all be correct: DOM parsing order, custom-element upgrade/connection timing, and runtime module-definition timing.
|
|
1346
|
+
|
|
1347
|
+
### 0.0.13 — pre-link persistent compile cache and structured documentation
|
|
1348
|
+
|
|
1349
|
+
Decision: persistent caching stores only fully syntax-compiled, linker-ready artifacts. Runtime-specific dependency resolution, generated module URLs, host bridge identity, and native evaluation remain session-local.
|
|
1350
|
+
|
|
1351
|
+
Rules now enforced:
|
|
1352
|
+
|
|
1353
|
+
1. JSX transformation happens before runtime linking; import metadata is collected against transformed code so cached offsets remain valid.
|
|
1354
|
+
2. Persistent artifact identity includes artifact ABI, compiler fingerprint, source format, compile-affecting context, and exact source SHA-256.
|
|
1355
|
+
3. Module ID, dependency versions, resolver state, host values, and URL-backend choice are not part of the default compile key.
|
|
1356
|
+
4. Identical source may therefore share an artifact across module IDs while relative imports are linked separately for each importer.
|
|
1357
|
+
5. The default `solid-tag` compiler exposes a stable fingerprint. Custom compilers without a fingerprint continue to work but persistent caching is bypassed rather than guessed.
|
|
1358
|
+
6. `runtime.invalidate()` preserves compiler artifacts by default. `{ compile: true }` forces only the requested module to compile fresh; dependents relink without forced recompilation.
|
|
1359
|
+
7. `runtime.compile(id, { cache: "use" | "refresh" | "bypass" })` controls compiler-artifact lookup while preserving the existing public linked/executable compile result.
|
|
1360
|
+
8. `runtime.compileCache.invalidate()` and `.clear()` manage stored artifacts without deleting runtime module definitions.
|
|
1361
|
+
9. IndexedDB, localStorage, and memory providers share one async store contract. Provider failures never make normal compilation unavailable. Quota-style write failures trigger pruning plus one retry; a failed retry becomes an observational cache error while the freshly compiled in-memory artifact remains usable.
|
|
1362
|
+
10. Optional `maxAge`, `maxEntries`, and `maxBytes` bounds provide deliberately simple pruning; sophisticated global LRU and cross-tab locking remain deferred.
|
|
1363
|
+
11. Compile-cache lifecycle events remain observational and integrate with the existing typed subscription system.
|
|
1364
|
+
12. Package documentation is now organized under `docs/`, with feature guides and `docs/api/` references. The root README is an entry point; this architecture file remains the engineering handoff/decision log.
|
|
1365
|
+
13. HTML documentation explicitly requires `<solid-render></solid-render>` rather than XML-style `<solid-render />`; custom elements are not HTML void elements and self-closing syntax can accidentally capture following DOM as initial `props.children`.
|
|
1366
|
+
|