solid-tag-runtime 0.0.13 → 0.0.15
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 +114 -2
- package/README.md +85 -19
- package/docs/README.md +5 -2
- package/docs/api/html.md +8 -0
- package/docs/api/solid.md +71 -0
- package/docs/getting-started.md +29 -22
- package/docs/html-runtime.md +12 -0
- package/docs/lifecycle-events.md +2 -0
- package/docs/rendering.md +6 -0
- package/docs/solid-runtime-setup.md +181 -0
- package/docs/wrapperless-delegation.md +81 -0
- package/examples/solid-runtime.js +24 -0
- package/package.json +7 -1
- package/solid.d.ts +77 -0
- package/src/html/delegated-events.js +69 -0
- package/src/html/delegation-host.js +29 -0
- package/src/html.js +76 -1
- package/src/render.js +4 -0
- package/src/solid/import-map.js +29 -0
- package/src/solid/index.js +67 -0
- package/src/solid/integration.js +30 -0
- package/src/solid/packages.js +24 -0
- package/src/solid/providers/esm-sh.js +81 -0
- package/src/solid/providers/index.js +22 -0
- package/src/solid/providers/jsdelivr.js +45 -0
- package/src/solid/resolve.js +287 -0
package/ARCHITECTURE.md
CHANGED
|
@@ -44,7 +44,9 @@ The runtime should allow applications to:
|
|
|
44
44
|
11. support normal JavaScript modules in the same graph
|
|
45
45
|
12. declaratively mount runtime component exports through the HTML adapter
|
|
46
46
|
13. reuse existing runtime modules through a light-DOM `solid-render` custom element
|
|
47
|
-
14.
|
|
47
|
+
14. optionally resolve a coherent standard Solid package family without teaching the core runtime about providers
|
|
48
|
+
15. lazily establish Solid 2 delegated-event infrastructure for wrapperless range mounts while preserving independent reactive roots
|
|
49
|
+
16. keep the JSX compiler replaceable behind a narrow adapter
|
|
48
50
|
|
|
49
51
|
## 3. Current non-goals
|
|
50
52
|
|
|
@@ -58,6 +60,8 @@ The initial package does not attempt to provide:
|
|
|
58
60
|
- circular runtime source-module support
|
|
59
61
|
- transparent live replacement of already-held component references
|
|
60
62
|
- full HMR propagation semantics
|
|
63
|
+
- provider/CDN policy inside the core `createRuntime()` implementation
|
|
64
|
+
- automatic import-map mutation
|
|
61
65
|
|
|
62
66
|
These may be added later without changing the module-first public model. HTML script discovery was added in `0.0.2` as a separate browser adapter rather than as a responsibility of the core module engine.
|
|
63
67
|
|
|
@@ -69,7 +73,11 @@ Application
|
|
|
69
73
|
├── host Solid runtime
|
|
70
74
|
│ ├── solid-js
|
|
71
75
|
│ ├── @solidjs/web
|
|
72
|
-
│
|
|
76
|
+
│ ├── @solidjs/html
|
|
77
|
+
│ └── @solidjs/signals
|
|
78
|
+
│
|
|
79
|
+
├── solid-tag-runtime/solid (optional setup/provider integration)
|
|
80
|
+
│ └── resolves host namespaces, then calls the normal runtime
|
|
73
81
|
│
|
|
74
82
|
└── solid-tag-runtime
|
|
75
83
|
│
|
|
@@ -153,6 +161,39 @@ runtime.dispose();
|
|
|
153
161
|
|
|
154
162
|
Lifecycle subscriptions are synchronous observational notifications. They do not intercept or modify runtime behavior. Resolution behavior remains customizable through `resolve()`, compilation through the compiler adapter, and executable-module creation through `ModuleUrlBackend`.
|
|
155
163
|
|
|
164
|
+
### Optional Solid integration subpath
|
|
165
|
+
|
|
166
|
+
`solid-tag-runtime/solid` is additive and does not change the low-level runtime contract:
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
const modules = await loadSolidModules(options?);
|
|
170
|
+
const runtime = await createSolidRuntime(options?);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The integration resolves the canonical family:
|
|
174
|
+
|
|
175
|
+
```text
|
|
176
|
+
solid-js
|
|
177
|
+
@solidjs/web
|
|
178
|
+
@solidjs/html
|
|
179
|
+
@solidjs/signals
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
`loadSolidModules()` returns ordinary namespaces compatible with the existing `modules` option. `createSolidRuntime()` composes that loader with the normal runtime and installs one private `SolidRuntimeIntegration` capability used by higher-level DOM features. Caller-provided modules win over automatic defaults.
|
|
183
|
+
|
|
184
|
+
Important boundaries:
|
|
185
|
+
|
|
186
|
+
1. `createRuntime()` remains synchronous and never performs provider/import-map work.
|
|
187
|
+
2. Provider-specific logic is isolated under `src/solid/providers/`.
|
|
188
|
+
3. Existing browser/import-map mappings are authoritative and are never rewritten.
|
|
189
|
+
4. A versioned Solid-family mapping becomes a provider/version identity anchor for generated siblings.
|
|
190
|
+
5. esm.sh generated siblings externalize authoritative mapped dependencies and pin coordinated missing dependencies when no anchor exists.
|
|
191
|
+
6. jsDelivr mixed-provider cases that cannot safely preserve core Solid identity fail rather than silently loading another runtime.
|
|
192
|
+
7. CDN fallback uses a package-tested Solid family version when no versioned anchor exists; provider `latest` is not the hidden default.
|
|
193
|
+
8. The integration layer may inspect page import maps and effective resolution, but it never mutates import maps.
|
|
194
|
+
|
|
195
|
+
The integration registry itself is a private `WeakMap<runtime, integration>`; the core module graph does not store provider metadata or DOM delegation state.
|
|
196
|
+
|
|
156
197
|
## 6. Module kinds
|
|
157
198
|
|
|
158
199
|
The runtime currently has three module record kinds.
|
|
@@ -516,6 +557,36 @@ The adapter does not transform arbitrary document HTML into JSX and does not cur
|
|
|
516
557
|
|
|
517
558
|
This avoids introducing a second template language, implicit lexical scope rules, or ambiguous ownership of already-parsed DOM.
|
|
518
559
|
|
|
560
|
+
### Wrapperless Solid 2 delegated-event integration
|
|
561
|
+
|
|
562
|
+
A bare declarative render keeps the existing marker-range ownership model:
|
|
563
|
+
|
|
564
|
+
```text
|
|
565
|
+
<script render> A <script render> B
|
|
566
|
+
↓ ↓
|
|
567
|
+
createRoot A createRoot B
|
|
568
|
+
↓ ↓
|
|
569
|
+
insert(range A) insert(range B)
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
Solid 2 delegated handlers may require a DOM render/delegation context for the containing `Document`. A runtime created through `createSolidRuntime()` therefore carries a private lazy capability:
|
|
573
|
+
|
|
574
|
+
```ts
|
|
575
|
+
ensureDelegation(document);
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
The first wrapperless range mount calls it immediately before its normal `createRoot() + insert()` path. The capability:
|
|
579
|
+
|
|
580
|
+
1. creates/reuses one lightweight `render(() => undefined, document)` host keyed by **Document × `@solidjs/web` namespace identity**;
|
|
581
|
+
2. ensures the delegated event set through that same renderer namespace;
|
|
582
|
+
3. does not render application components inside the host;
|
|
583
|
+
4. does not use `runWithOwner()` and does not parent wrapperless roots under the host owner;
|
|
584
|
+
5. stays alive independently of any one marker range.
|
|
585
|
+
|
|
586
|
+
Selector rendering (`render="#target"`) remains normal container rendering. `<solid-render>` remains a persistent light-DOM container and is unchanged by this integration. Low-level runtimes created by `createRuntime()` do not receive this capability automatically.
|
|
587
|
+
|
|
588
|
+
The delegated event helper prefers `@solidjs/web.DelegatedEvents` when available and otherwise uses the standard Solid/dom-expressions delegated UI-event family. Registration is idempotent per renderer/document pair.
|
|
589
|
+
|
|
519
590
|
## 9. Compiler adapter boundary
|
|
520
591
|
|
|
521
592
|
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.
|
|
@@ -1364,3 +1435,44 @@ Rules now enforced:
|
|
|
1364
1435
|
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
1436
|
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
1437
|
|
|
1438
|
+
### 0.0.14 — additive Solid runtime setup and lazy wrapperless delegation
|
|
1439
|
+
|
|
1440
|
+
Decision: add `solid-tag-runtime/solid` as an opt-in integration layer while keeping `createRuntime()` provider-agnostic and synchronous.
|
|
1441
|
+
|
|
1442
|
+
Public setup layers:
|
|
1443
|
+
|
|
1444
|
+
```text
|
|
1445
|
+
createRuntime()
|
|
1446
|
+
low-level; caller supplies already-resolved namespaces
|
|
1447
|
+
|
|
1448
|
+
loadSolidModules()
|
|
1449
|
+
resolves/imports the coordinated Solid family
|
|
1450
|
+
|
|
1451
|
+
createSolidRuntime()
|
|
1452
|
+
loadSolidModules + createRuntime + private lazy Solid integration
|
|
1453
|
+
```
|
|
1454
|
+
|
|
1455
|
+
Resolution rules preserve explicit/effective page mappings before provider generation. Provider-specific URL logic lives outside the core runtime. The built-in fallback policy targets the tested Solid `2.0.0-rc.13` family rather than silently following CDN `latest`. esm.sh generation uses dependency externalization/pinning to preserve one Solid identity; its family model treats `@solidjs/signals` as the Solid 2 reactive core consumed by `solid-js`, with `@solidjs/web` and `@solidjs/html` layered above it. jsDelivr mixed-provider situations that cannot be guaranteed are rejected. Import maps are read-only inputs and are never mutated.
|
|
1456
|
+
|
|
1457
|
+
Decision: fix wrapperless Solid 2 delegated events with the smallest ownership-preserving change. `createSolidRuntime()` installs `ensureDelegation(document)` but does not execute it eagerly. The first wrapperless range mount creates/reuses one document-level delegation host per `Document × @solidjs/web namespace`, ensures delegated event types, then proceeds with the existing independent `createRoot() + insert()` mount.
|
|
1458
|
+
|
|
1459
|
+
The delegation host is infrastructure only. It is not a shared application owner, is not a parent of declarative roots, is not disposed with an individual range, and does not change selector rendering or `<solid-render>` container ownership. Low-level `createRuntime()` behavior is unchanged.
|
|
1460
|
+
|
|
1461
|
+
### 0.0.15 — declaration-driven observer scheduling
|
|
1462
|
+
|
|
1463
|
+
Decision: harden `solid-tag-runtime/html` observation by filtering `MutationObserver` child-list records before `enqueueObserverScan()` is scheduled. The observer no longer rescans its root for arbitrary UI DOM churn.
|
|
1464
|
+
|
|
1465
|
+
A mutation requires observer work when at least one of these is true:
|
|
1466
|
+
|
|
1467
|
+
1. an added node is, or contains, an element matching the controller's runtime declaration selector;
|
|
1468
|
+
2. an added node is, or contains, `<solid-render>`, preserving observer-batch retry behavior for newly connected renderer instances;
|
|
1469
|
+
3. a removed subtree contains the active anchor for a mounted declarative render, so detached render ownership can still be disposed;
|
|
1470
|
+
4. the host MutationObserver/DOM implementation cannot be classified safely, in which case the runtime conservatively preserves the previous scan behavior.
|
|
1471
|
+
|
|
1472
|
+
Explicit `html.flush()` remains a forced scan and does not apply mutation filtering. Empty mutation batches from custom/test `MutationObserver` implementations also retain conservative scan behavior for compatibility.
|
|
1473
|
+
|
|
1474
|
+
Reason: HTML lifecycle subscribers, devtools, status panels, and normal application rendering may mutate DOM inside a document-scoped observer. Previously every child-list mutation queued a full discovery scan, `observer-batch` could cause subscriber UI updates, and those updates could schedule another scan indefinitely. Observer scheduling must be driven by possible runtime-declaration effects rather than arbitrary DOM activity.
|
|
1475
|
+
|
|
1476
|
+
Invariant: unrelated DOM mutations must not enqueue runtime discovery or emit `observer-batch`. Observing `document` is therefore robust against diagnostic/application UI churn, while matching declarations and mounted-render cleanup remain live.
|
|
1477
|
+
|
|
1478
|
+
Regression coverage: package tests verify unrelated child-list additions enqueue no observer batch, matching runtime scripts still register normally, an `observer-batch` subscriber may render unrelated DOM without recursively triggering additional scans, and relevant declaration removals still dispose mounted render ownership. The browser playground test suite carries the same feedback-loop regression against the native `MutationObserver`.
|
package/README.md
CHANGED
|
@@ -11,10 +11,16 @@ pre-link compiled artifact
|
|
|
11
11
|
↓
|
|
12
12
|
solid-tag-runtime linker
|
|
13
13
|
↓
|
|
14
|
-
|
|
14
|
+
host Solid runtime
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
The core package is module-first and DOM-independent. Browser discovery, ownership, declarative rendering, and `<solid-render>` live in
|
|
17
|
+
The core package is module-first and DOM-independent. Browser discovery, ownership, declarative rendering, and `<solid-render>` live in `solid-tag-runtime/html`. Optional Solid setup/provider helpers live in `solid-tag-runtime/solid`.
|
|
18
|
+
|
|
19
|
+
## 0.0.15 observer hardening
|
|
20
|
+
|
|
21
|
+
`0.0.15` filters `MutationObserver` records before scheduling HTML discovery. Ordinary UI DOM changes no longer enqueue a full runtime scan or emit an `observer-batch`; matching runtime declarations, `<solid-render>` retry boundaries, and removals that can detach mounted declarative renders still trigger observer work. Explicit `html.flush()` remains a deterministic forced scan.
|
|
22
|
+
|
|
23
|
+
This prevents lifecycle/devtools subscribers that render diagnostics into an observed document from creating observer → event → DOM mutation feedback loops.
|
|
18
24
|
|
|
19
25
|
## Install
|
|
20
26
|
|
|
@@ -22,7 +28,36 @@ The core package is module-first and DOM-independent. Browser discovery, ownersh
|
|
|
22
28
|
npm install solid-tag-runtime solid-tag
|
|
23
29
|
```
|
|
24
30
|
|
|
25
|
-
##
|
|
31
|
+
## Easiest Solid setup
|
|
32
|
+
|
|
33
|
+
`0.0.14` adds an opt-in high-level Solid integration:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { createSolidRuntime } from "solid-tag-runtime/solid";
|
|
37
|
+
|
|
38
|
+
const runtime = await createSolidRuntime({
|
|
39
|
+
modules: {
|
|
40
|
+
"@app/state": state,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The helper resolves the standard family:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
solid-js
|
|
49
|
+
@solidjs/web
|
|
50
|
+
@solidjs/html
|
|
51
|
+
@solidjs/signals
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Existing browser/bundler resolution and import-map mappings are preferred. Missing packages may be filled through an inferred/configured provider. Existing mappings are never rewritten, and user-provided modules override automatic defaults.
|
|
55
|
+
|
|
56
|
+
`createSolidRuntime()` also installs a **lazy** Solid DOM integration used by wrapperless `<script render>` mounts. It does not establish a document render/delegation host until a wrapperless render actually needs one.
|
|
57
|
+
|
|
58
|
+
See [Solid runtime setup](./docs/solid-runtime-setup.md).
|
|
59
|
+
|
|
60
|
+
## Low-level setup remains unchanged
|
|
26
61
|
|
|
27
62
|
```ts
|
|
28
63
|
import * as Solid from "solid-js";
|
|
@@ -37,7 +72,36 @@ const runtime = createRuntime({
|
|
|
37
72
|
"@solidjs/html": { default: html },
|
|
38
73
|
},
|
|
39
74
|
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`createRuntime()` remains synchronous and does not know about CDNs, browser import maps, Solid version inference, or document event delegation.
|
|
78
|
+
|
|
79
|
+
## Composable Solid module loader
|
|
80
|
+
|
|
81
|
+
If you want provider-aware setup but still want to call `createRuntime()` yourself:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { loadSolidModules } from "solid-tag-runtime/solid";
|
|
85
|
+
import { createRuntime } from "solid-tag-runtime";
|
|
86
|
+
|
|
87
|
+
const solidModules = await loadSolidModules({
|
|
88
|
+
source: "auto",
|
|
89
|
+
fallbackProvider: "esm.sh",
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const runtime = createRuntime({
|
|
93
|
+
modules: {
|
|
94
|
+
...solidModules,
|
|
95
|
+
"@app/state": state,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Provider logic is isolated from the core runtime. `loadSolidModules()` reads existing mappings/resolution but never mutates import maps. If a host resolves only part of the Solid family but its identity is opaque, automatic CDN mixing is rejected rather than risking a second Solid runtime.
|
|
101
|
+
|
|
102
|
+
## Define runtime modules
|
|
40
103
|
|
|
104
|
+
```ts
|
|
41
105
|
runtime.define("/Greeting.jsx", `
|
|
42
106
|
export default function Greeting() {
|
|
43
107
|
return <p>Hello from runtime JSX</p>;
|
|
@@ -79,11 +143,15 @@ Bare `render` mounts in place without adding a wrapper:
|
|
|
79
143
|
```html
|
|
80
144
|
<script type="solid-jsx" module="/Message.jsx" render>
|
|
81
145
|
export default function Message() {
|
|
82
|
-
return <
|
|
146
|
+
return <button onClick={() => console.log("clicked")}>Click</button>;
|
|
83
147
|
}
|
|
84
148
|
</script>
|
|
85
149
|
```
|
|
86
150
|
|
|
151
|
+
When the runtime was created with `createSolidRuntime()`, wrapperless mounting lazily ensures Solid's document-level delegated-event infrastructure while keeping every declaration in its own independently disposable `createRoot() + insert()` root.
|
|
152
|
+
|
|
153
|
+
See [Wrapperless delegation](./docs/wrapperless-delegation.md).
|
|
154
|
+
|
|
87
155
|
## Reusable `<solid-render>` instances
|
|
88
156
|
|
|
89
157
|
```html
|
|
@@ -101,7 +169,7 @@ Bare `render` mounts in place without adding a wrapper:
|
|
|
101
169
|
|
|
102
170
|
## Persistent compile cache
|
|
103
171
|
|
|
104
|
-
|
|
172
|
+
The opt-in compile cache persists **pre-link compiler artifacts**. Runtime-specific linked URLs and evaluated module namespaces are never persisted.
|
|
105
173
|
|
|
106
174
|
```ts
|
|
107
175
|
import {
|
|
@@ -120,29 +188,23 @@ const runtime = createRuntime({
|
|
|
120
188
|
});
|
|
121
189
|
```
|
|
122
190
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
```ts
|
|
126
|
-
await runtime.compile("/App.jsx", { cache: "use" });
|
|
127
|
-
await runtime.compile("/App.jsx", { cache: "refresh" });
|
|
128
|
-
await runtime.compile("/App.jsx", { cache: "bypass" });
|
|
129
|
-
|
|
130
|
-
await runtime.compileCache.invalidate("/App.jsx");
|
|
131
|
-
await runtime.compileCache.clear();
|
|
132
|
-
```
|
|
191
|
+
See [Persistent compile cache](./docs/compile-cache.md).
|
|
133
192
|
|
|
134
193
|
## Documentation
|
|
135
194
|
|
|
136
|
-
|
|
195
|
+
Detailed documentation lives under [`docs/`](./docs/README.md):
|
|
137
196
|
|
|
138
197
|
- [Getting started](./docs/getting-started.md)
|
|
198
|
+
- [Solid runtime setup and providers](./docs/solid-runtime-setup.md)
|
|
139
199
|
- [Runtime modules and resolution](./docs/modules.md)
|
|
140
200
|
- [HTML runtime and ownership](./docs/html-runtime.md)
|
|
141
201
|
- [Declarative rendering](./docs/rendering.md)
|
|
202
|
+
- [Wrapperless delegation](./docs/wrapperless-delegation.md)
|
|
142
203
|
- [`<solid-render>`](./docs/solid-render.md)
|
|
143
204
|
- [Lifecycle events](./docs/lifecycle-events.md)
|
|
144
205
|
- [Persistent compile cache](./docs/compile-cache.md)
|
|
145
206
|
- [Core runtime API](./docs/api/runtime.md)
|
|
207
|
+
- [Solid integration API](./docs/api/solid.md)
|
|
146
208
|
- [HTML runtime API](./docs/api/html.md)
|
|
147
209
|
- [Compile-cache API](./docs/api/compile-cache.md)
|
|
148
210
|
|
|
@@ -150,17 +212,20 @@ For engineering invariants and design decisions, see [`ARCHITECTURE.md`](./ARCHI
|
|
|
150
212
|
|
|
151
213
|
## Browser import maps
|
|
152
214
|
|
|
153
|
-
When loading from an import map, map
|
|
215
|
+
When loading from an import map, map every used package subpath to the same release:
|
|
154
216
|
|
|
155
217
|
```json
|
|
156
218
|
{
|
|
157
219
|
"imports": {
|
|
158
|
-
"solid-tag-runtime": "https://esm.sh/solid-tag-runtime@0.0.
|
|
159
|
-
"solid-tag-runtime/html": "https://esm.sh/solid-tag-runtime@0.0.
|
|
220
|
+
"solid-tag-runtime": "https://esm.sh/solid-tag-runtime@0.0.15",
|
|
221
|
+
"solid-tag-runtime/html": "https://esm.sh/solid-tag-runtime@0.0.15/html",
|
|
222
|
+
"solid-tag-runtime/solid": "https://esm.sh/solid-tag-runtime@0.0.15/solid"
|
|
160
223
|
}
|
|
161
224
|
}
|
|
162
225
|
```
|
|
163
226
|
|
|
227
|
+
The Solid helper does **not** inject or mutate import maps.
|
|
228
|
+
|
|
164
229
|
## Current limitations
|
|
165
230
|
|
|
166
231
|
- runtime-defined source-module cycles are not supported yet
|
|
@@ -168,3 +233,4 @@ When loading from an import map, map both entries to the same version:
|
|
|
168
233
|
- persistent compile caching is an optimization, not a security sandbox
|
|
169
234
|
- already-held namespace/component references are not mutated by module updates
|
|
170
235
|
- TypeScript/TSX support depends on the configured compiler
|
|
236
|
+
- the built-in provider layer currently supports esm.sh and jsDelivr; unsafe mixed-provider cases fail rather than silently loading a second Solid runtime
|
package/docs/README.md
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# solid-tag-runtime documentation
|
|
2
2
|
|
|
3
|
-
`solid-tag-runtime` is a runtime module system for dynamically defined Solid JSX/JavaScript modules. The core package remains module-first and DOM-independent; browser/DOM behavior lives in `solid-tag-runtime/html`.
|
|
3
|
+
`solid-tag-runtime` is a runtime module system for dynamically defined Solid JSX/JavaScript modules. The core package remains module-first and DOM-independent; browser/DOM behavior lives in `solid-tag-runtime/html`, and optional Solid setup/provider logic lives in `solid-tag-runtime/solid`.
|
|
4
4
|
|
|
5
5
|
## Start here
|
|
6
6
|
|
|
7
7
|
- [Getting started](./getting-started.md)
|
|
8
|
+
- [Solid runtime setup and provider resolution](./solid-runtime-setup.md)
|
|
8
9
|
- [Runtime modules and resolution](./modules.md)
|
|
9
10
|
- [HTML runtime and ownership](./html-runtime.md)
|
|
10
11
|
- [Declarative rendering](./rendering.md)
|
|
12
|
+
- [Wrapperless Solid 2 delegation](./wrapperless-delegation.md)
|
|
11
13
|
- [`<solid-render>`](./solid-render.md)
|
|
12
14
|
- [Lifecycle events](./lifecycle-events.md)
|
|
13
15
|
- [Persistent compile cache](./compile-cache.md)
|
|
@@ -15,9 +17,10 @@
|
|
|
15
17
|
## API reference
|
|
16
18
|
|
|
17
19
|
- [Core runtime API](./api/runtime.md)
|
|
20
|
+
- [Solid integration API](./api/solid.md)
|
|
18
21
|
- [HTML runtime API](./api/html.md)
|
|
19
22
|
- [Compile-cache API](./api/compile-cache.md)
|
|
20
23
|
|
|
21
24
|
## Engineering design
|
|
22
25
|
|
|
23
|
-
The root [`ARCHITECTURE.md`](../ARCHITECTURE.md) is the engineering handoff and decision log. It documents internal invariants, compiler/linker boundaries, ownership rules, and compatibility decisions.
|
|
26
|
+
The root [`ARCHITECTURE.md`](../ARCHITECTURE.md) is the engineering handoff and decision log. It documents internal invariants, compiler/linker boundaries, ownership rules, provider-resolution boundaries, and compatibility decisions.
|
package/docs/api/html.md
CHANGED
|
@@ -35,6 +35,8 @@ await html.flush(options?);
|
|
|
35
35
|
html.disconnect();
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
`observe()` filters child-list mutation records and schedules discovery only for mutations that can affect runtime declarations, `<solid-render>` retry work, or mounted declarative-render cleanup. `flush()` bypasses that filter and forces a scan.
|
|
39
|
+
|
|
38
40
|
## Explicit ownership
|
|
39
41
|
|
|
40
42
|
```ts
|
|
@@ -81,3 +83,9 @@ const observer = await observeHTML(runtime, options?);
|
|
|
81
83
|
```
|
|
82
84
|
|
|
83
85
|
For rendering semantics see [Declarative rendering](../rendering.md) and [`<solid-render>`](../solid-render.md).
|
|
86
|
+
|
|
87
|
+
## Wrapperless delegated events
|
|
88
|
+
|
|
89
|
+
For bare `<script render>` ranges, automatic Solid delegated-event setup is available when the underlying runtime was created with `createSolidRuntime()` from `solid-tag-runtime/solid`.
|
|
90
|
+
|
|
91
|
+
The HTML adapter asks the runtime's private Solid integration to establish document-level delegation lazily, then keeps the declaration in its existing independent `createRoot() + insert()` lifecycle. Selector renders and `<solid-render>` retain their existing container semantics.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Solid integration API
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
import {
|
|
5
|
+
createSolidRuntime,
|
|
6
|
+
loadSolidModules,
|
|
7
|
+
inspectSolidResolution,
|
|
8
|
+
SOLID_RUNTIME_PACKAGES,
|
|
9
|
+
TESTED_SOLID_VERSION,
|
|
10
|
+
} from "solid-tag-runtime/solid";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## `loadSolidModules(options?)`
|
|
14
|
+
|
|
15
|
+
Returns the standard Solid family as host-module namespaces:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
const modules = await loadSolidModules({
|
|
19
|
+
source: "auto",
|
|
20
|
+
fallbackProvider: "esm.sh",
|
|
21
|
+
version: "2.0.0-rc.13",
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Options:
|
|
26
|
+
|
|
27
|
+
- `source`: `"auto" | "host" | "esm.sh" | "jsdelivr"`
|
|
28
|
+
- `fallbackProvider`: `"esm.sh" | "jsdelivr"`
|
|
29
|
+
- `version`: provider fallback version when no versioned anchor exists
|
|
30
|
+
- `modules`: already-resolved standard namespaces
|
|
31
|
+
- `specifiers`: explicit URL/specifier overrides
|
|
32
|
+
- `document`: optional document for read-only import-map inspection
|
|
33
|
+
|
|
34
|
+
`source: "auto"` refuses to mix a partially resolved opaque host Solid family with CDN-generated siblings when the existing runtime identity cannot be established safely.
|
|
35
|
+
|
|
36
|
+
## `createSolidRuntime(options?)`
|
|
37
|
+
|
|
38
|
+
Async convenience factory:
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
const runtime = await createSolidRuntime({
|
|
42
|
+
modules: {
|
|
43
|
+
"@app/state": state,
|
|
44
|
+
},
|
|
45
|
+
solid: {
|
|
46
|
+
source: "auto",
|
|
47
|
+
fallbackProvider: "esm.sh",
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
All ordinary runtime options remain available. `modules` supplied by the caller override automatic Solid defaults.
|
|
53
|
+
|
|
54
|
+
The factory also installs the private lazy delegation capability used by wrapperless HTML rendering.
|
|
55
|
+
|
|
56
|
+
## `inspectSolidResolution(options?)`
|
|
57
|
+
|
|
58
|
+
Read-only helper for tooling/debugging:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
const info = inspectSolidResolution();
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Returns detected import-map mappings plus inferred provider/version information. It does not import modules and does not mutate the page.
|
|
65
|
+
|
|
66
|
+
## Constants
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
SOLID_RUNTIME_PACKAGES;
|
|
70
|
+
TESTED_SOLID_VERSION;
|
|
71
|
+
```
|
package/docs/getting-started.md
CHANGED
|
@@ -6,7 +6,29 @@
|
|
|
6
6
|
npm install solid-tag-runtime solid-tag
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
The runtime intentionally does not bundle its own Solid runtime.
|
|
9
|
+
The runtime intentionally does not bundle its own Solid runtime.
|
|
10
|
+
|
|
11
|
+
## High-level Solid setup
|
|
12
|
+
|
|
13
|
+
For the shortest setup path:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createSolidRuntime } from "solid-tag-runtime/solid";
|
|
17
|
+
|
|
18
|
+
const runtime = await createSolidRuntime({
|
|
19
|
+
modules: {
|
|
20
|
+
"@app/state": state,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This resolves/imports the standard Solid family and installs lazy wrapperless event-delegation support.
|
|
26
|
+
|
|
27
|
+
See [Solid runtime setup](./solid-runtime-setup.md) for import-map/provider/version behavior.
|
|
28
|
+
|
|
29
|
+
## Low-level setup
|
|
30
|
+
|
|
31
|
+
If the host already owns exact namespaces, keep using the synchronous core primitive:
|
|
10
32
|
|
|
11
33
|
```ts
|
|
12
34
|
import * as Solid from "solid-js";
|
|
@@ -43,23 +65,7 @@ const module = await runtime.import("/Counter.jsx");
|
|
|
43
65
|
module.default;
|
|
44
66
|
```
|
|
45
67
|
|
|
46
|
-
Relative imports between runtime modules work normally
|
|
47
|
-
|
|
48
|
-
```ts
|
|
49
|
-
runtime.define("/ui/Button.jsx", `
|
|
50
|
-
export function Button(props) {
|
|
51
|
-
return <button>{props.children}</button>;
|
|
52
|
-
}
|
|
53
|
-
`);
|
|
54
|
-
|
|
55
|
-
runtime.define("/App.jsx", `
|
|
56
|
-
import { Button } from "./ui/Button.jsx";
|
|
57
|
-
|
|
58
|
-
export default function App() {
|
|
59
|
-
return <Button>Hello</Button>;
|
|
60
|
-
}
|
|
61
|
-
`);
|
|
62
|
-
```
|
|
68
|
+
Relative imports between runtime modules work normally.
|
|
63
69
|
|
|
64
70
|
## Browser HTML adapter
|
|
65
71
|
|
|
@@ -89,17 +95,18 @@ Declarative source:
|
|
|
89
95
|
</script>
|
|
90
96
|
```
|
|
91
97
|
|
|
92
|
-
See [HTML runtime](./html-runtime.md), [declarative rendering](./rendering.md), and [`<solid-render>`](./solid-render.md)
|
|
98
|
+
See [HTML runtime](./html-runtime.md), [declarative rendering](./rendering.md), and [`<solid-render>`](./solid-render.md).
|
|
93
99
|
|
|
94
100
|
## Browser import maps
|
|
95
101
|
|
|
96
|
-
|
|
102
|
+
Map every used package subpath explicitly:
|
|
97
103
|
|
|
98
104
|
```json
|
|
99
105
|
{
|
|
100
106
|
"imports": {
|
|
101
|
-
"solid-tag-runtime": "https://esm.sh/solid-tag-runtime@0.0.
|
|
102
|
-
"solid-tag-runtime/html": "https://esm.sh/solid-tag-runtime@0.0.
|
|
107
|
+
"solid-tag-runtime": "https://esm.sh/solid-tag-runtime@0.0.15",
|
|
108
|
+
"solid-tag-runtime/html": "https://esm.sh/solid-tag-runtime@0.0.15/html",
|
|
109
|
+
"solid-tag-runtime/solid": "https://esm.sh/solid-tag-runtime@0.0.15/solid"
|
|
103
110
|
}
|
|
104
111
|
}
|
|
105
112
|
```
|
package/docs/html-runtime.md
CHANGED
|
@@ -29,6 +29,10 @@ await html.observe({ registerExisting: false });
|
|
|
29
29
|
await html.flush();
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
The live observer is declaration-driven rather than mutation-driven. It inspects each `MutationRecord` before scheduling discovery and ignores ordinary UI child-list changes that cannot add a matching runtime declaration or require mounted-render cleanup. This means a document-scoped controller can coexist with application/devtools DOM updates without repeatedly rescanning the document.
|
|
33
|
+
|
|
34
|
+
`flush()` is intentionally different: it remains an explicit forced scan and can be used as a deterministic synchronization point even when no relevant observer mutation was seen.
|
|
35
|
+
|
|
32
36
|
## Script declarations
|
|
33
37
|
|
|
34
38
|
```html
|
|
@@ -110,3 +114,11 @@ html.setAppendTarget(document.head);
|
|
|
110
114
|
```
|
|
111
115
|
|
|
112
116
|
`root` controls discovery/observation; `appendTarget` controls where explicit additions are inserted. Reparenting the exact same root node does not require `setRoot()`.
|
|
117
|
+
|
|
118
|
+
## Solid-aware wrapperless rendering
|
|
119
|
+
|
|
120
|
+
A low-level `createRuntime()` controller behaves exactly as before and does not install Solid-specific document infrastructure.
|
|
121
|
+
|
|
122
|
+
When the runtime comes from `createSolidRuntime()` in `solid-tag-runtime/solid`, a bare `<script render>` can lazily request the document-level delegated-event setup required by Solid 2. Each marker-range declaration still owns an independent reactive root and disposer; the delegation host is infrastructure only and is not a shared reactive owner.
|
|
123
|
+
|
|
124
|
+
See [Solid runtime setup](./solid-runtime-setup.md) and [Wrapperless delegation](./wrapperless-delegation.md).
|
package/docs/lifecycle-events.md
CHANGED
|
@@ -74,4 +74,6 @@ html.subscribe("element-registered", event => {
|
|
|
74
74
|
|
|
75
75
|
HTML events cover ownership, observation, roots, entry execution, render mounting/disposal, warnings, and errors.
|
|
76
76
|
|
|
77
|
+
`observer-batch` is emitted only when observer work is actually scheduled. Unrelated child-list mutations are filtered before discovery, so a lifecycle subscriber may render diagnostics/status UI inside an observed document without causing a self-sustaining observer/event loop. Explicit `html.flush()` still performs and reports a forced scan.
|
|
78
|
+
|
|
77
79
|
Listener exceptions are isolated from runtime/HTML operations and are reported to the console rather than aborting the underlying action.
|
package/docs/rendering.md
CHANGED
|
@@ -16,6 +16,8 @@ A runtime script can define a module and mount one component instance.
|
|
|
16
16
|
|
|
17
17
|
Without `component`, rendering selects `module.default`.
|
|
18
18
|
|
|
19
|
+
Selector rendering continues to use normal Solid container rendering.
|
|
20
|
+
|
|
19
21
|
## Named export
|
|
20
22
|
|
|
21
23
|
```html
|
|
@@ -49,6 +51,10 @@ Bare `render` means mount at the exact declaration position:
|
|
|
49
51
|
|
|
50
52
|
The adapter replaces the declaration with an owned marker range. No wrapper is introduced.
|
|
51
53
|
|
|
54
|
+
Each in-place render owns its own `createRoot() + insert()` lifecycle. When the runtime comes from `createSolidRuntime()`, the first wrapperless mount lazily establishes the document-level Solid delegation infrastructure needed by delegated handlers such as `onClick`. That infrastructure is not the reactive owner of the mounted ranges.
|
|
55
|
+
|
|
56
|
+
See [Wrapperless Solid 2 delegation](./wrapperless-delegation.md).
|
|
57
|
+
|
|
52
58
|
## Registration ordering
|
|
53
59
|
|
|
54
60
|
All matching declarations in a discovered batch are defined before any `entry` or `render` declaration executes. An importer may therefore appear before its dependency in document order.
|