solid-tag-runtime 0.0.7 → 0.0.9
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 +166 -1
- package/README.md +272 -15
- package/html.d.ts +166 -63
- package/index.d.ts +42 -1
- package/package.json +1 -1
- package/src/events.js +63 -0
- package/src/html.js +1061 -53
- package/src/render.js +205 -0
- package/src/runtime.js +198 -94
package/ARCHITECTURE.md
CHANGED
|
@@ -42,7 +42,9 @@ The runtime should allow applications to:
|
|
|
42
42
|
9. observe runtime lifecycle transitions for tooling/tracing
|
|
43
43
|
10. inspect dependencies and compiled source
|
|
44
44
|
11. support normal JavaScript modules in the same graph
|
|
45
|
-
12.
|
|
45
|
+
12. declaratively mount runtime component exports through the HTML adapter
|
|
46
|
+
13. reuse existing runtime modules through a light-DOM `solid-render` custom element
|
|
47
|
+
14. keep the JSX compiler replaceable behind a narrow adapter
|
|
46
48
|
|
|
47
49
|
## 3. Current non-goals
|
|
48
50
|
|
|
@@ -101,6 +103,7 @@ const runtime = createRuntime(options);
|
|
|
101
103
|
|
|
102
104
|
```ts
|
|
103
105
|
runtime.define(id, source, options?);
|
|
106
|
+
runtime.defineMany(definitions);
|
|
104
107
|
runtime.update(id, source, options?);
|
|
105
108
|
```
|
|
106
109
|
|
|
@@ -138,9 +141,18 @@ runtime.getModuleInfo(id);
|
|
|
138
141
|
|
|
139
142
|
```ts
|
|
140
143
|
runtime.invalidate(id);
|
|
144
|
+
runtime.remove(id, options?);
|
|
145
|
+
runtime.clear(options?);
|
|
146
|
+
|
|
147
|
+
runtime.subscribe(listener);
|
|
148
|
+
runtime.subscribe(type, listener);
|
|
149
|
+
runtime.subscribe(types, listener);
|
|
150
|
+
|
|
141
151
|
runtime.dispose();
|
|
142
152
|
```
|
|
143
153
|
|
|
154
|
+
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
|
+
|
|
144
156
|
## 6. Module kinds
|
|
145
157
|
|
|
146
158
|
The runtime currently has three module record kinds.
|
|
@@ -232,6 +244,10 @@ await html.observe({ registerExisting: false });
|
|
|
232
244
|
The controller exposes:
|
|
233
245
|
|
|
234
246
|
```ts
|
|
247
|
+
html.subscribe(listener);
|
|
248
|
+
html.subscribe(type, listener);
|
|
249
|
+
html.subscribe(types, listener);
|
|
250
|
+
|
|
235
251
|
html.register(options?);
|
|
236
252
|
html.observe(options?);
|
|
237
253
|
html.flush(options?);
|
|
@@ -1031,3 +1047,152 @@ Invariants:
|
|
|
1031
1047
|
8. `removeElement()` is the canonical operation for releasing shared WeakMap ownership.
|
|
1032
1048
|
|
|
1033
1049
|
Regression coverage: package tests cover batch definition and duplicate rejection, dependency removal/invalidation, clear-with-host-preservation, lifecycle event delivery/unsubscribe, owned element updates, identity-change rejection, ownership release, DOM removal, and preserving a runtime module while releasing its HTML element.
|
|
1050
|
+
|
|
1051
|
+
### 0.0.8 — selective lifecycle subscriptions and HTML observability
|
|
1052
|
+
|
|
1053
|
+
Decision: expand lifecycle observation into typed, independently removable subscriptions on both the core runtime and the HTML adapter. Keep lifecycle subscriptions observational and separate from behavioral hooks/interceptors.
|
|
1054
|
+
|
|
1055
|
+
Core subscription forms:
|
|
1056
|
+
|
|
1057
|
+
```ts
|
|
1058
|
+
runtime.subscribe(listener);
|
|
1059
|
+
runtime.subscribe("module-error", listener);
|
|
1060
|
+
runtime.subscribe(["module-evaluating", "module-evaluated"], listener);
|
|
1061
|
+
```
|
|
1062
|
+
|
|
1063
|
+
HTML controllers expose the same shape:
|
|
1064
|
+
|
|
1065
|
+
```ts
|
|
1066
|
+
html.subscribe(listener);
|
|
1067
|
+
html.subscribe("element-registered", listener);
|
|
1068
|
+
html.subscribe(["observer-batch", "html-error"], listener);
|
|
1069
|
+
```
|
|
1070
|
+
|
|
1071
|
+
Each call creates an independent subscription and returns its own disposer. Disposing one subscription never affects another registration of the same callback or subscriptions to other event groups. Subscriber exceptions are reported but cannot alter runtime/HTML operations.
|
|
1072
|
+
|
|
1073
|
+
Core event additions:
|
|
1074
|
+
|
|
1075
|
+
```text
|
|
1076
|
+
module-updated
|
|
1077
|
+
modules-defined
|
|
1078
|
+
module-resolving
|
|
1079
|
+
module-resolved
|
|
1080
|
+
module-linking
|
|
1081
|
+
module-linked
|
|
1082
|
+
```
|
|
1083
|
+
|
|
1084
|
+
The evaluation pipeline is now observed in semantic order:
|
|
1085
|
+
|
|
1086
|
+
```text
|
|
1087
|
+
module-linking
|
|
1088
|
+
↓
|
|
1089
|
+
module-resolving / module-resolved
|
|
1090
|
+
↓
|
|
1091
|
+
module-linked
|
|
1092
|
+
↓
|
|
1093
|
+
module-compiled
|
|
1094
|
+
↓
|
|
1095
|
+
module-evaluating
|
|
1096
|
+
↓
|
|
1097
|
+
module-evaluated
|
|
1098
|
+
```
|
|
1099
|
+
|
|
1100
|
+
`module-resolved` exposes the logical resolution result and resolution kind, while `module-linked` exposes source specifier → resolved module-ID dependencies without exposing Blob/data URL implementation details. `modules-defined` marks the completion of a `defineMany()` batch after buffered per-module events become observable. `module-updated` supplements the backward-compatible `module-defined { operation: "update" }` event with an explicit semantic update notification.
|
|
1101
|
+
|
|
1102
|
+
`module-error` remains one event with a structured pipeline phase instead of creating separate error event types. Supported phases are `resolve`, `analyze`, `compile`, `link`, `url-create`, `evaluate`, and `host-bridge`.
|
|
1103
|
+
|
|
1104
|
+
HTML controller event additions:
|
|
1105
|
+
|
|
1106
|
+
```text
|
|
1107
|
+
element-discovered
|
|
1108
|
+
element-claimed
|
|
1109
|
+
element-loading
|
|
1110
|
+
element-loaded
|
|
1111
|
+
element-registered
|
|
1112
|
+
element-updating
|
|
1113
|
+
element-updated
|
|
1114
|
+
element-removing
|
|
1115
|
+
element-released
|
|
1116
|
+
element-removed
|
|
1117
|
+
observer-connected
|
|
1118
|
+
observer-disconnected
|
|
1119
|
+
observer-batch
|
|
1120
|
+
root-changing
|
|
1121
|
+
root-changed
|
|
1122
|
+
append-target-changed
|
|
1123
|
+
entry-executing
|
|
1124
|
+
entry-executed
|
|
1125
|
+
html-error
|
|
1126
|
+
```
|
|
1127
|
+
|
|
1128
|
+
HTML ownership events include an origin describing the ingestion path (`initial-scan`, `observer`, `register-element`, `append`, `add-module`, etc.). The observer emits summarized `observer-batch` events instead of exposing raw `MutationRecord` values. Root/append-target events belong only to the HTML controller and are deliberately not mixed into core runtime events.
|
|
1129
|
+
|
|
1130
|
+
Architectural boundary:
|
|
1131
|
+
|
|
1132
|
+
```text
|
|
1133
|
+
Observation
|
|
1134
|
+
runtime.subscribe()
|
|
1135
|
+
html.subscribe()
|
|
1136
|
+
|
|
1137
|
+
Behavior customization
|
|
1138
|
+
resolve()
|
|
1139
|
+
compiler adapter
|
|
1140
|
+
ModuleUrlBackend
|
|
1141
|
+
```
|
|
1142
|
+
|
|
1143
|
+
Lifecycle listeners are not interceptors: they cannot cancel evaluation, rewrite source, change resolution, or alter cache behavior. If source/evaluation interception is needed later, it must be designed as a separate hook contract with explicit ordering, async, cancellation, and caching semantics.
|
|
1144
|
+
|
|
1145
|
+
Implementation note: core and HTML event streams share a small internal dispatcher so all/selective subscription behavior, independent disposers, and listener-error isolation have identical semantics while keeping separate event unions.
|
|
1146
|
+
|
|
1147
|
+
Regression coverage: package tests cover catch-all, single-type, and multi-type subscriptions; independent unsubscribe; listener exception isolation; update/batch events; resolution/link/evaluation ordering and payloads; structured resolution errors; HTML ownership origins; observer connect/disconnect/batch events; root and append-target events; external source loading; entry execution; update/removal events; HTML error reporting; and HTML subscriber exception isolation.
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
### 0.0.9 — shared declarative rendering and `solid-render`
|
|
1152
|
+
|
|
1153
|
+
Decision: rendering remains entirely inside `solid-tag-runtime/html`. The core runtime still owns module identity, resolution, linking, execution, caching, invalidation, and host-module injection; it has no DOM or component-mounting responsibility.
|
|
1154
|
+
|
|
1155
|
+
Two public rendering forms now share one internal rendering core:
|
|
1156
|
+
|
|
1157
|
+
```text
|
|
1158
|
+
<script module render>
|
|
1159
|
+
define source + mount one component instance
|
|
1160
|
+
|
|
1161
|
+
<solid-render module>
|
|
1162
|
+
reference an existing module + mount one component instance
|
|
1163
|
+
```
|
|
1164
|
+
|
|
1165
|
+
Declarative script rendering follows these invariants:
|
|
1166
|
+
|
|
1167
|
+
- `render="#selector"` imports the module, selects `default` unless `component="Name"` is present, and uses normal Solid container rendering.
|
|
1168
|
+
- bare `render` replaces the declaration with start/end comment markers and mounts with positional insertion before the end marker; no wrapper element is introduced.
|
|
1169
|
+
- every discovered module in a batch is defined before any `entry` or render action executes.
|
|
1170
|
+
- `entry` and `render` on the same declaration are rejected as ambiguous.
|
|
1171
|
+
- anonymous `render` declarations receive internal runtime IDs just like anonymous entries.
|
|
1172
|
+
- render ownership/disposal is stored on the HTML declaration record and remains separate from module lifetime.
|
|
1173
|
+
- `updateElement()` remounts a rendered declaration after source/component/render metadata changes while preserving the same logical module identity.
|
|
1174
|
+
- `removeElement()` disposes mounted UI before releasing declaration/module ownership.
|
|
1175
|
+
- observer-discovered render declarations use the same batch/ownership pipeline as ordinary declarations.
|
|
1176
|
+
|
|
1177
|
+
The shared render adapter lazily resolves the host application's own `solid-js` and `@solidjs/web` modules through the runtime (with `solid-js/web` as a compatibility fallback). This preserves the no-duplicate-Solid invariant and keeps the HTML package free of a direct Solid dependency. Tests/special hosts may inject a render adapter.
|
|
1178
|
+
|
|
1179
|
+
`solid-render` invariants:
|
|
1180
|
+
|
|
1181
|
+
1. It references an existing runtime module; it never defines source.
|
|
1182
|
+
2. Missing `component` means `namespace.default`; `component="Name"` selects a named export.
|
|
1183
|
+
3. `data-solid-runtime` selects the HTML runtime through the shared controller registry. With no attribute, a single unambiguous controller may be used.
|
|
1184
|
+
4. The element remains in the DOM and is the light-DOM mount container. Wrapperless rendering belongs to bare `<script render>`.
|
|
1185
|
+
5. Renderer configuration (`module`, `component`, `data-solid-runtime`) is never forwarded as component props.
|
|
1186
|
+
6. Declarative props use `prop:*`; kebab names normalize to camelCase. Empty/presence values are boolean `true`, other values remain strings.
|
|
1187
|
+
7. `.props` carries arbitrary JavaScript references and overrides declarative props.
|
|
1188
|
+
8. Prop changes update a reactive prop facade and do not remount the component, preserving local state.
|
|
1189
|
+
9. Module/component/runtime identity changes increment a generation token, dispose the current owner, and remount. Stale async import successes and failures are ignored; they cannot mount or report an error against a newer identity.
|
|
1190
|
+
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.
|
|
1191
|
+
11. Multiple elements may share one evaluated module namespace while owning independent Solid component roots.
|
|
1192
|
+
12. Disconnect disposes the mounted root; reconnect mounts a fresh component instance from the retained declaration inputs.
|
|
1193
|
+
13. Custom-element registration is global/idempotent per `CustomElementRegistry`. `createHTMLRuntime()` registers it after installing the controller in the shared registry; registration/observation paths remain idempotent. `registerSolidRenderElement()` remains available for explicit/custom-registry use.
|
|
1194
|
+
14. Runtime/controller disposal tears down both script-owned mounts and connected `solid-render` instances so no Solid owners are orphaned.
|
|
1195
|
+
|
|
1196
|
+
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.
|
|
1197
|
+
|
|
1198
|
+
The first `solid-render` phase intentionally excludes named slots, Shadow DOM, automatic numeric/JSON coercion, arbitrary unprefixed prop forwarding, loading/fallback templates, and expression evaluation inside attributes.
|
package/README.md
CHANGED
|
@@ -107,8 +107,8 @@ Browser import maps must map the subpath explicitly as well as the package root:
|
|
|
107
107
|
```json
|
|
108
108
|
{
|
|
109
109
|
"imports": {
|
|
110
|
-
"solid-tag-runtime": "https://esm.sh/solid-tag-runtime@0.0.
|
|
111
|
-
"solid-tag-runtime/html": "https://esm.sh/solid-tag-runtime@0.0.
|
|
110
|
+
"solid-tag-runtime": "https://esm.sh/solid-tag-runtime@0.0.9",
|
|
111
|
+
"solid-tag-runtime/html": "https://esm.sh/solid-tag-runtime@0.0.9/html"
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
```
|
|
@@ -138,6 +138,155 @@ await html.register();
|
|
|
138
138
|
await html.observe({ registerExisting: false });
|
|
139
139
|
```
|
|
140
140
|
|
|
141
|
+
|
|
142
|
+
## Render runtime UI
|
|
143
|
+
|
|
144
|
+
`solid-tag-runtime/html` can now mount component exports as an HTML-adapter concern while the core runtime remains DOM-independent.
|
|
145
|
+
|
|
146
|
+
There are two complementary forms:
|
|
147
|
+
|
|
148
|
+
```text
|
|
149
|
+
<script module>
|
|
150
|
+
define a runtime module
|
|
151
|
+
|
|
152
|
+
<script module render>
|
|
153
|
+
define a module + mount one instance
|
|
154
|
+
|
|
155
|
+
<solid-render module>
|
|
156
|
+
reference an existing module + mount one instance
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Define and render in one declaration
|
|
160
|
+
|
|
161
|
+
Render the default export into a normal Solid container:
|
|
162
|
+
|
|
163
|
+
```html
|
|
164
|
+
<div id="app"></div>
|
|
165
|
+
|
|
166
|
+
<script
|
|
167
|
+
type="solid-jsx"
|
|
168
|
+
data-solid-runtime="main"
|
|
169
|
+
module="/App.jsx"
|
|
170
|
+
render="#app"
|
|
171
|
+
>
|
|
172
|
+
export default function App() {
|
|
173
|
+
return <h1>Hello from runtime JSX</h1>;
|
|
174
|
+
}
|
|
175
|
+
</script>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
`render` defaults to `module.default`. Select a named export with `component`:
|
|
179
|
+
|
|
180
|
+
```html
|
|
181
|
+
<script
|
|
182
|
+
type="solid-jsx"
|
|
183
|
+
module="/widgets.jsx"
|
|
184
|
+
render="#app"
|
|
185
|
+
component="Counter"
|
|
186
|
+
>
|
|
187
|
+
export function Counter() {
|
|
188
|
+
return <button>Counter</button>;
|
|
189
|
+
}
|
|
190
|
+
</script>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Bare `render` mounts at the declaration's exact sibling position without adding a wrapper:
|
|
194
|
+
|
|
195
|
+
```html
|
|
196
|
+
<p>Before</p>
|
|
197
|
+
|
|
198
|
+
<script type="solid-jsx" module="/Message.jsx" render>
|
|
199
|
+
export default function Message() {
|
|
200
|
+
return <strong>Hello</strong>;
|
|
201
|
+
}
|
|
202
|
+
</script>
|
|
203
|
+
|
|
204
|
+
<p>After</p>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The adapter replaces the declaration with an owned start/end marker range and inserts the component between the markers. The module definition and mount lifecycle remain separate: removing the declaration through `html.removeElement()` disposes the Solid owner while module removal follows the existing lifecycle options.
|
|
208
|
+
|
|
209
|
+
`entry` and `render` are intentionally mutually exclusive on one declaration. Use separate declarations when a side-effect entry and a mounted component are both needed.
|
|
210
|
+
|
|
211
|
+
All matching modules in one scan/observer batch are defined before any `entry` or `render` action executes, so a render declaration may import a dependency declared later in the same batch.
|
|
212
|
+
|
|
213
|
+
### Reuse an existing module with `<solid-render>`
|
|
214
|
+
|
|
215
|
+
`<solid-render>` references an already-defined module and remains as the light-DOM mount container:
|
|
216
|
+
|
|
217
|
+
```html
|
|
218
|
+
<solid-render
|
|
219
|
+
data-solid-runtime="main"
|
|
220
|
+
module="/Counter.jsx"
|
|
221
|
+
></solid-render>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Named export:
|
|
225
|
+
|
|
226
|
+
```html
|
|
227
|
+
<solid-render
|
|
228
|
+
data-solid-runtime="main"
|
|
229
|
+
module="/widgets.jsx"
|
|
230
|
+
component="Counter"
|
|
231
|
+
></solid-render>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Component props use an explicit namespace so renderer configuration can never collide with component prop names:
|
|
235
|
+
|
|
236
|
+
```html
|
|
237
|
+
<solid-render
|
|
238
|
+
module="/UserCard.jsx"
|
|
239
|
+
prop:name="Alice"
|
|
240
|
+
prop:module="billing"
|
|
241
|
+
prop:compact
|
|
242
|
+
></solid-render>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Declarative values are conservative:
|
|
246
|
+
|
|
247
|
+
```text
|
|
248
|
+
prop:name="Alice" → "Alice"
|
|
249
|
+
prop:compact → true
|
|
250
|
+
prop:count="42" → "42"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Kebab-case prop names normalize to camelCase (`prop:user-id` → `userId`). Arbitrary JavaScript references use the `.props` property:
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
const renderer = document.querySelector("solid-render");
|
|
257
|
+
|
|
258
|
+
renderer.props = {
|
|
259
|
+
user,
|
|
260
|
+
onSave,
|
|
261
|
+
service,
|
|
262
|
+
};
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Programmatic props override `prop:*` attributes. Prop changes update the existing component instance reactively and preserve local Solid state. Changes to `module`, `component`, or `data-solid-runtime` dispose the current component and mount a new identity.
|
|
266
|
+
|
|
267
|
+
Initial light-DOM children become `props.children`:
|
|
268
|
+
|
|
269
|
+
```html
|
|
270
|
+
<solid-render module="/Card.jsx" prop:title="Profile">
|
|
271
|
+
<p>Hello from HTML.</p>
|
|
272
|
+
<solid-render module="/SaveButton.jsx"></solid-render>
|
|
273
|
+
</solid-render>
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
The first implementation deliberately has no named-slot system and no Shadow DOM. Nested `<solid-render>` elements work through normal custom-element connection when captured children are instantiated.
|
|
277
|
+
|
|
278
|
+
`createHTMLRuntime()` ensures the custom element is registered globally once after the controller has entered the shared runtime registry. `registerHTML()` / `observeHTML()` keep the same idempotent guarantee. Most applications therefore do not need to call a registration helper directly.
|
|
279
|
+
|
|
280
|
+
For custom registries, tests, or explicit registration, the helper remains available:
|
|
281
|
+
|
|
282
|
+
```ts
|
|
283
|
+
import { registerSolidRenderElement } from "solid-tag-runtime/html";
|
|
284
|
+
|
|
285
|
+
registerSolidRenderElement();
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Multiple `<solid-render>` elements may share one cached runtime module namespace while each mounted component owns independent Solid state. Async module changes are generation-guarded so a stale import can never replace a newer `module`/`component`/runtime selection.
|
|
289
|
+
|
|
141
290
|
A scope is written to owned script elements as:
|
|
142
291
|
|
|
143
292
|
```html
|
|
@@ -572,28 +721,136 @@ removes everything. The returned array contains the IDs that were removed.
|
|
|
572
721
|
|
|
573
722
|
### Lifecycle events
|
|
574
723
|
|
|
724
|
+
`0.0.8` expands lifecycle subscriptions into a typed event stream with independent join/leave semantics.
|
|
725
|
+
|
|
726
|
+
Subscribe to everything:
|
|
727
|
+
|
|
575
728
|
```ts
|
|
576
729
|
const unsubscribe = runtime.subscribe(event => {
|
|
577
730
|
console.log(event.type, event);
|
|
578
731
|
});
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
Subscribe to one event type:
|
|
735
|
+
|
|
736
|
+
```ts
|
|
737
|
+
const leaveErrors = runtime.subscribe(
|
|
738
|
+
"module-error",
|
|
739
|
+
event => {
|
|
740
|
+
console.error(event.phase, event.error);
|
|
741
|
+
},
|
|
742
|
+
);
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
Subscribe to several event types:
|
|
746
|
+
|
|
747
|
+
```ts
|
|
748
|
+
const leaveEvaluation = runtime.subscribe(
|
|
749
|
+
["module-evaluating", "module-evaluated"],
|
|
750
|
+
event => {
|
|
751
|
+
console.log(event.type, event.id);
|
|
752
|
+
},
|
|
753
|
+
);
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
Each call owns an independent subscription:
|
|
757
|
+
|
|
758
|
+
```ts
|
|
759
|
+
leaveEvaluation();
|
|
760
|
+
// the error subscription remains active
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
Core events include:
|
|
764
|
+
|
|
765
|
+
```text
|
|
766
|
+
module-defined
|
|
767
|
+
module-updated
|
|
768
|
+
modules-defined
|
|
769
|
+
|
|
770
|
+
module-resolving
|
|
771
|
+
module-resolved
|
|
772
|
+
|
|
773
|
+
module-linking
|
|
774
|
+
module-linked
|
|
775
|
+
|
|
776
|
+
module-invalidated
|
|
777
|
+
module-compiled
|
|
778
|
+
module-evaluating
|
|
779
|
+
module-evaluated
|
|
780
|
+
|
|
781
|
+
module-removed
|
|
782
|
+
module-error
|
|
783
|
+
|
|
784
|
+
runtime-cleared
|
|
785
|
+
runtime-disposed
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
`module-resolved` reports how a specifier was resolved (`relative`, `registered`, `custom`, `native`, and so on). `module-linked` exposes the logical dependency mapping used to link a source module. `modules-defined` marks the completion of a `defineMany()` batch after all definitions have been installed.
|
|
789
|
+
|
|
790
|
+
`module-error.phase` is one of the runtime pipeline phases such as `resolve`, `analyze`, `compile`, `link`, `url-create`, `evaluate`, or `host-bridge`.
|
|
791
|
+
|
|
792
|
+
Subscribers are observational only: they cannot cancel or modify runtime operations, and subscriber exceptions are isolated from runtime execution. Behavioral extension remains separate through the resolver, compiler adapter, and module URL backend.
|
|
793
|
+
|
|
794
|
+
### HTML lifecycle events
|
|
795
|
+
|
|
796
|
+
The HTML controller has its own event stream because DOM ownership/observation is intentionally separate from the core module engine:
|
|
797
|
+
|
|
798
|
+
```ts
|
|
799
|
+
const leaveHTML = html.subscribe(event => {
|
|
800
|
+
console.log(event.type, event);
|
|
801
|
+
});
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
The same selective forms are supported:
|
|
805
|
+
|
|
806
|
+
```ts
|
|
807
|
+
const leaveOwnership = html.subscribe(
|
|
808
|
+
["element-claimed", "element-registered", "element-removed"],
|
|
809
|
+
event => {
|
|
810
|
+
console.log(event.type, event.moduleId);
|
|
811
|
+
},
|
|
812
|
+
);
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
HTML events include:
|
|
816
|
+
|
|
817
|
+
```text
|
|
818
|
+
element-discovered
|
|
819
|
+
element-claimed
|
|
820
|
+
element-loading
|
|
821
|
+
element-loaded
|
|
822
|
+
element-registered
|
|
823
|
+
|
|
824
|
+
element-updating
|
|
825
|
+
element-updated
|
|
826
|
+
element-removing
|
|
827
|
+
element-released
|
|
828
|
+
element-removed
|
|
829
|
+
|
|
830
|
+
observer-connected
|
|
831
|
+
observer-disconnected
|
|
832
|
+
observer-batch
|
|
833
|
+
|
|
834
|
+
root-changing
|
|
835
|
+
root-changed
|
|
836
|
+
append-target-changed
|
|
837
|
+
|
|
838
|
+
entry-executing
|
|
839
|
+
entry-executed
|
|
840
|
+
|
|
841
|
+
render-mounting
|
|
842
|
+
render-mounted
|
|
843
|
+
render-disposing
|
|
844
|
+
render-disposed
|
|
579
845
|
|
|
580
|
-
|
|
581
|
-
unsubscribe();
|
|
846
|
+
html-error
|
|
582
847
|
```
|
|
583
848
|
|
|
584
|
-
|
|
849
|
+
Ownership-related events include an `origin` describing how the element entered the controller (`observer`, `append`, `register-element`, `add-module`, and related internal scan origins). This is useful for tracing observer/manual-registration races and proving that an explicit `append()` was not processed a second time by the observer.
|
|
585
850
|
|
|
586
|
-
- `
|
|
587
|
-
- `module-invalidated`
|
|
588
|
-
- `module-compiled`
|
|
589
|
-
- `module-evaluating`
|
|
590
|
-
- `module-evaluated`
|
|
591
|
-
- `module-removed`
|
|
592
|
-
- `module-error`
|
|
593
|
-
- `runtime-cleared`
|
|
594
|
-
- `runtime-disposed`
|
|
851
|
+
`observer-batch` summarizes a DOM discovery pass instead of exposing noisy raw `MutationRecord` objects. `element-loading` / `element-loaded` are emitted for `src`-backed modules, and entry events distinguish evaluation caused by an HTML `entry` declaration from an ordinary `runtime.import()`. Render events cover both `<script render>` and `<solid-render>`; `source` identifies `script-render` versus `solid-render`, and `mode` identifies selector, in-place, or container mounting.
|
|
595
852
|
|
|
596
|
-
|
|
853
|
+
Like core runtime subscribers, HTML subscribers are observational and exception-isolated.
|
|
597
854
|
|
|
598
855
|
## HTML-owned module updates and removal
|
|
599
856
|
|