solid-tag-runtime 0.0.11 → 0.0.12
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 +20 -1
- package/README.md +17 -3
- package/package.json +1 -1
- package/src/html.js +191 -19
package/ARCHITECTURE.md
CHANGED
|
@@ -1191,7 +1191,7 @@ The shared render adapter lazily resolves the host application's own `solid-js`
|
|
|
1191
1191
|
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
1192
|
11. Multiple elements may share one evaluated module namespace while owning independent Solid component roots.
|
|
1193
1193
|
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
|
|
1194
|
+
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
1195
|
14. Runtime/controller disposal tears down both script-owned mounts and connected `solid-render` instances so no Solid owners are orphaned.
|
|
1196
1196
|
|
|
1197
1197
|
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 +1235,22 @@ Rules now enforced:
|
|
|
1235
1235
|
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
1236
|
|
|
1237
1237
|
This keeps DOM routing and module routing failures separate and produces actionable errors instead of accidental browser network requests.
|
|
1238
|
+
|
|
1239
|
+
|
|
1240
|
+
### 0.0.12 — declarative registration barrier for `solid-render`
|
|
1241
|
+
|
|
1242
|
+
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.
|
|
1243
|
+
|
|
1244
|
+
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`.
|
|
1245
|
+
|
|
1246
|
+
Rules now enforced:
|
|
1247
|
+
|
|
1248
|
+
1. `createHTMLRuntime()` installs the controller in the shared registry but does not eagerly define/upgrade `<solid-render>`.
|
|
1249
|
+
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.
|
|
1250
|
+
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.
|
|
1251
|
+
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.
|
|
1252
|
+
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.
|
|
1253
|
+
6. Retries remain generation-guarded, so stale async work cannot replace a newer module/component/runtime identity.
|
|
1254
|
+
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.
|
|
1255
|
+
|
|
1256
|
+
This separates three orderings that must all be correct: DOM parsing order, custom-element upgrade/connection timing, and runtime module-definition timing.
|
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.12",
|
|
111
|
+
"solid-tag-runtime/html": "https://esm.sh/solid-tag-runtime@0.0.12/html"
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
```
|
|
@@ -275,7 +275,7 @@ Initial light-DOM children become `props.children`:
|
|
|
275
275
|
|
|
276
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
277
|
|
|
278
|
-
|
|
278
|
+
The HTML adapter registers the custom element automatically **after the initial declarative script batch is installed** by `register()` / `registerHTML()` or the initial `observe()` / `observeHTML()` pass. `createHTMLRuntime()` intentionally does not upgrade existing `<solid-render>` elements immediately, because doing so could make them import modules before preceding `<script module>` declarations have been registered. Most applications therefore do not need to call a registration helper directly.
|
|
279
279
|
|
|
280
280
|
For custom registries, tests, or explicit registration, the helper remains available:
|
|
281
281
|
|
|
@@ -298,6 +298,20 @@ Both of these reference the same registered virtual module when used with the co
|
|
|
298
298
|
|
|
299
299
|
Top-level relative module references are normalized as virtual paths; they are not browser URL fetches.
|
|
300
300
|
|
|
301
|
+
A document may safely declare a module and immediately reference it later in the same HTML before calling `register()`:
|
|
302
|
+
|
|
303
|
+
```html
|
|
304
|
+
<script type="solid-jsx" module="/ui/Button.jsx">
|
|
305
|
+
export default function Button() {
|
|
306
|
+
return <button>Ready</button>;
|
|
307
|
+
}
|
|
308
|
+
</script>
|
|
309
|
+
|
|
310
|
+
<solid-render module="/ui/Button.jsx"></solid-render>
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
The adapter installs the declaration batch before existing `solid-render` instances mount. If the custom element class was already registered by another runtime, unresolved instances are retried when the matching module becomes available. A transient startup ordering race therefore does not surface as a `ModuleResolutionError`. If the registration/observer queue settles and the referenced virtual module is still absent, the normal `solid-render` error is reported; the retry behavior does not hide genuine missing-module mistakes.
|
|
314
|
+
|
|
301
315
|
A scope is written to owned script elements as:
|
|
302
316
|
|
|
303
317
|
```html
|
package/package.json
CHANGED
package/src/html.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SolidTagRuntimeError } from "./errors.js";
|
|
1
|
+
import { ModuleResolutionError, SolidTagRuntimeError } from "./errors.js";
|
|
2
2
|
import { createEventDispatcher } from "./events.js";
|
|
3
3
|
import { HTMLRenderError, createDefaultHTMLRenderAdapter, resolveRenderComponent } from "./render.js";
|
|
4
4
|
|
|
@@ -83,6 +83,9 @@ export function createHTMLRuntime(runtime, options = {}) {
|
|
|
83
83
|
queue: Promise.resolve(),
|
|
84
84
|
lastError: undefined,
|
|
85
85
|
connected: false,
|
|
86
|
+
registrationDepth: 0,
|
|
87
|
+
registrationPasses: 0,
|
|
88
|
+
solidRenderRetryScheduled: false,
|
|
86
89
|
initial: emptyRegistrationResult(),
|
|
87
90
|
};
|
|
88
91
|
|
|
@@ -127,10 +130,13 @@ export function createHTMLRuntime(runtime, options = {}) {
|
|
|
127
130
|
|
|
128
131
|
controller.api = api;
|
|
129
132
|
activeControllers.add(controller);
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
|
|
133
|
+
// Do not define/upgrade <solid-render> here. Existing declarative script
|
|
134
|
+
// modules must be installed first; otherwise connectedCallback() can import
|
|
135
|
+
// a module before register()/observe() has defined the preceding <script>.
|
|
136
|
+
// register()/observe() register the element after their initial script batch.
|
|
137
|
+
controller.runtimeModuleDefinedUnsubscribe = runtime.subscribe?.("module-defined", event => {
|
|
138
|
+
scheduleSolidRenderRetryForModule(controller, event.id);
|
|
139
|
+
});
|
|
134
140
|
controller.runtimeDisposeUnsubscribe = runtime.subscribe?.("runtime-disposed", () => {
|
|
135
141
|
void disposeController(controller, { runtimeDisposed: true });
|
|
136
142
|
});
|
|
@@ -147,21 +153,23 @@ export function createHTMLRuntime(runtime, options = {}) {
|
|
|
147
153
|
const origin = callOptions.origin ?? "initial-scan";
|
|
148
154
|
const discovered = Array.from(root.querySelectorAll(selector));
|
|
149
155
|
const elements = [];
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const accepted = acceptsDiscoveredElement(controller, element, callOptions);
|
|
153
|
-
emitHTML(controller, {
|
|
154
|
-
type: "element-discovered",
|
|
155
|
-
element,
|
|
156
|
-
moduleId: nonEmpty(element?.getAttribute?.("module")),
|
|
157
|
-
origin,
|
|
158
|
-
accepted,
|
|
159
|
-
});
|
|
160
|
-
if (accepted) elements.push(element);
|
|
161
|
-
else maybeWarnUnresolvedRenderScope(controller, element, callOptions, origin);
|
|
162
|
-
}
|
|
156
|
+
const pendingBeforeUpgrade = collectConnectedSolidRenderElements(controller, root);
|
|
157
|
+
controller.registrationDepth += 1;
|
|
163
158
|
|
|
164
159
|
try {
|
|
160
|
+
for (const element of discovered) {
|
|
161
|
+
const accepted = acceptsDiscoveredElement(controller, element, callOptions);
|
|
162
|
+
emitHTML(controller, {
|
|
163
|
+
type: "element-discovered",
|
|
164
|
+
element,
|
|
165
|
+
moduleId: nonEmpty(element?.getAttribute?.("module")),
|
|
166
|
+
origin,
|
|
167
|
+
accepted,
|
|
168
|
+
});
|
|
169
|
+
if (accepted) elements.push(element);
|
|
170
|
+
else maybeWarnUnresolvedRenderScope(controller, element, callOptions, origin);
|
|
171
|
+
}
|
|
172
|
+
|
|
165
173
|
const result = await processElements(controller, elements, {
|
|
166
174
|
...callOptions,
|
|
167
175
|
root,
|
|
@@ -169,11 +177,21 @@ export function createHTMLRuntime(runtime, options = {}) {
|
|
|
169
177
|
executeEntries: callOptions.executeEntries ?? controller.executeEntries,
|
|
170
178
|
executeRenders: callOptions.executeRenders ?? controller.executeRenders,
|
|
171
179
|
});
|
|
180
|
+
|
|
181
|
+
// Existing upgraded instances may have connected before this controller's
|
|
182
|
+
// declaration batch was installed. Retry those after the batch completes.
|
|
172
183
|
registerSolidRenderElement();
|
|
184
|
+
controller.registrationPasses += 1;
|
|
185
|
+
await retrySolidRenderElements(controller, pendingBeforeUpgrade, {
|
|
186
|
+
reason: "registration-complete",
|
|
187
|
+
forceMissingError: true,
|
|
188
|
+
});
|
|
173
189
|
return result;
|
|
174
190
|
} catch (error) {
|
|
175
191
|
emitHTMLError(controller, "register", error, { origin });
|
|
176
192
|
throw error;
|
|
193
|
+
} finally {
|
|
194
|
+
controller.registrationDepth = Math.max(0, controller.registrationDepth - 1);
|
|
177
195
|
}
|
|
178
196
|
}
|
|
179
197
|
|
|
@@ -186,6 +204,8 @@ export function createHTMLRuntime(runtime, options = {}) {
|
|
|
186
204
|
|
|
187
205
|
const root = getRoot(mergeOptions(controller, callOptions), "HTML runtime observe");
|
|
188
206
|
controller.observerOptions = { ...callOptions };
|
|
207
|
+
const pendingBeforeUpgrade = collectConnectedSolidRenderElements(controller, root);
|
|
208
|
+
controller.registrationDepth += 1;
|
|
189
209
|
|
|
190
210
|
try {
|
|
191
211
|
controller.initial = await connectObserver(controller, root, callOptions, {
|
|
@@ -193,9 +213,16 @@ export function createHTMLRuntime(runtime, options = {}) {
|
|
|
193
213
|
initial: true,
|
|
194
214
|
});
|
|
195
215
|
registerSolidRenderElement();
|
|
216
|
+
controller.registrationPasses += 1;
|
|
217
|
+
await retrySolidRenderElements(controller, pendingBeforeUpgrade, {
|
|
218
|
+
reason: "observation-ready",
|
|
219
|
+
forceMissingError: true,
|
|
220
|
+
});
|
|
196
221
|
} catch (error) {
|
|
197
222
|
disconnect();
|
|
198
223
|
throw error;
|
|
224
|
+
} finally {
|
|
225
|
+
controller.registrationDepth = Math.max(0, controller.registrationDepth - 1);
|
|
199
226
|
}
|
|
200
227
|
|
|
201
228
|
return api;
|
|
@@ -645,6 +672,8 @@ export function registerSolidRenderElement(options = {}) {
|
|
|
645
672
|
mount: undefined,
|
|
646
673
|
controller: undefined,
|
|
647
674
|
propObserver: undefined,
|
|
675
|
+
pendingModuleResolution: undefined,
|
|
676
|
+
pendingCheckGeneration: undefined,
|
|
648
677
|
});
|
|
649
678
|
}
|
|
650
679
|
|
|
@@ -700,6 +729,8 @@ function getSolidRenderState(element) {
|
|
|
700
729
|
mount: undefined,
|
|
701
730
|
controller: undefined,
|
|
702
731
|
propObserver: undefined,
|
|
732
|
+
pendingModuleResolution: undefined,
|
|
733
|
+
pendingCheckGeneration: undefined,
|
|
703
734
|
};
|
|
704
735
|
solidRenderInternals.set(element, state);
|
|
705
736
|
}
|
|
@@ -738,10 +769,12 @@ function startSolidRenderPropObserver(element, state) {
|
|
|
738
769
|
state.propObserver = observer;
|
|
739
770
|
}
|
|
740
771
|
|
|
741
|
-
async function remountSolidRender(element, reason) {
|
|
772
|
+
async function remountSolidRender(element, reason, options = {}) {
|
|
742
773
|
const state = getSolidRenderState(element);
|
|
743
774
|
if (!state.connected) return;
|
|
744
775
|
const generation = ++state.generation;
|
|
776
|
+
state.pendingModuleResolution = undefined;
|
|
777
|
+
state.pendingCheckGeneration = undefined;
|
|
745
778
|
await disposeSolidRenderMount(element, state, reason === "connect" ? "reconnect" : reason);
|
|
746
779
|
if (!state.connected || generation !== state.generation) return;
|
|
747
780
|
|
|
@@ -792,6 +825,8 @@ async function remountSolidRender(element, reason) {
|
|
|
792
825
|
|
|
793
826
|
mount.mode = "container";
|
|
794
827
|
state.mount = mount;
|
|
828
|
+
state.pendingModuleResolution = undefined;
|
|
829
|
+
state.pendingCheckGeneration = undefined;
|
|
795
830
|
emitHTML(controller, {
|
|
796
831
|
type: "render-mounted",
|
|
797
832
|
element,
|
|
@@ -807,6 +842,26 @@ async function remountSolidRender(element, reason) {
|
|
|
807
842
|
// failure belongs to the abandoned generation just like a stale success,
|
|
808
843
|
// so it must not overwrite/report against the current element state.
|
|
809
844
|
if (!state.connected || generation !== state.generation) return;
|
|
845
|
+
if (error instanceof ModuleResolutionError && controller) {
|
|
846
|
+
state.pendingModuleResolution = {
|
|
847
|
+
moduleId: nonEmpty(element.getAttribute?.("module")),
|
|
848
|
+
error,
|
|
849
|
+
};
|
|
850
|
+
|
|
851
|
+
// During startup or observer-driven DOM insertion a connected custom
|
|
852
|
+
// element can run before the matching declarative module has been
|
|
853
|
+
// installed. Treat that as a pending reference only until the relevant
|
|
854
|
+
// registration/observer queue has had a chance to settle.
|
|
855
|
+
if (!options.forceMissingError && (
|
|
856
|
+
controller.registrationDepth > 0
|
|
857
|
+
|| controller.connected
|
|
858
|
+
|| controller.registrationPasses === 0
|
|
859
|
+
)) {
|
|
860
|
+
schedulePendingSolidRenderResolutionCheck(element, state, controller, generation);
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
810
865
|
if (controller) {
|
|
811
866
|
emitHTMLError(controller, "solid-render", error, {
|
|
812
867
|
element,
|
|
@@ -985,6 +1040,116 @@ function mostSpecificController(controllers) {
|
|
|
985
1040
|
return undefined;
|
|
986
1041
|
}
|
|
987
1042
|
|
|
1043
|
+
function schedulePendingSolidRenderResolutionCheck(element, state, controller, generation) {
|
|
1044
|
+
if (state.pendingCheckGeneration === generation) return;
|
|
1045
|
+
state.pendingCheckGeneration = generation;
|
|
1046
|
+
|
|
1047
|
+
const schedule = globalThis.setTimeout ?? ((callback) => Promise.resolve().then(callback));
|
|
1048
|
+
schedule(async () => {
|
|
1049
|
+
if (!state.connected || generation !== state.generation) return;
|
|
1050
|
+
if (!state.pendingModuleResolution || state.mount) return;
|
|
1051
|
+
|
|
1052
|
+
// MutationObserver callbacks run before the next task. If this missing
|
|
1053
|
+
// module came from a script + solid-render insertion batch, controller.queue
|
|
1054
|
+
// now points at that registration work. Wait for it before deciding the
|
|
1055
|
+
// reference is genuinely unresolved.
|
|
1056
|
+
if (controller.connected) {
|
|
1057
|
+
try {
|
|
1058
|
+
await controller.queue;
|
|
1059
|
+
} catch {
|
|
1060
|
+
// Observer errors are reported through the normal controller path.
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
if (!state.connected || generation !== state.generation) return;
|
|
1065
|
+
if (!state.pendingModuleResolution || state.mount) return;
|
|
1066
|
+
|
|
1067
|
+
// A direct register() may still be loading external source. Do not report
|
|
1068
|
+
// a transient missing module while that pass is active.
|
|
1069
|
+
if (controller.registrationDepth > 0) {
|
|
1070
|
+
state.pendingCheckGeneration = undefined;
|
|
1071
|
+
schedulePendingSolidRenderResolutionCheck(element, state, controller, generation);
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
state.pendingCheckGeneration = undefined;
|
|
1076
|
+
await remountSolidRender(element, "pending-module-settled", {
|
|
1077
|
+
forceMissingError: true,
|
|
1078
|
+
});
|
|
1079
|
+
}, 0);
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
function collectConnectedSolidRenderElements(controller, root) {
|
|
1083
|
+
const elements = new Set();
|
|
1084
|
+
|
|
1085
|
+
for (const element of controller.renderElements ?? []) {
|
|
1086
|
+
const state = solidRenderInternals.get(element);
|
|
1087
|
+
if (state?.connected && rootContainsElement(root, element)) elements.add(element);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
if (root && typeof root.querySelectorAll === "function") {
|
|
1091
|
+
for (const element of Array.from(root.querySelectorAll("solid-render") ?? [])) {
|
|
1092
|
+
const state = solidRenderInternals.get(element);
|
|
1093
|
+
if (state?.connected) elements.add(element);
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
return [...elements];
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
async function retrySolidRenderElements(controller, elements, options = {}) {
|
|
1101
|
+
for (const element of elements ?? []) {
|
|
1102
|
+
const state = solidRenderInternals.get(element);
|
|
1103
|
+
if (!state?.connected) continue;
|
|
1104
|
+
if (state.mount && !state.pendingModuleResolution) continue;
|
|
1105
|
+
|
|
1106
|
+
let selected;
|
|
1107
|
+
try {
|
|
1108
|
+
selected = resolveHTMLControllerForElement(element);
|
|
1109
|
+
} catch {
|
|
1110
|
+
continue;
|
|
1111
|
+
}
|
|
1112
|
+
if (selected !== controller) continue;
|
|
1113
|
+
|
|
1114
|
+
await remountSolidRender(element, options.reason ?? "retry", {
|
|
1115
|
+
forceMissingError: options.forceMissingError === true,
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
function scheduleSolidRenderRetryForModule(controller, definedId) {
|
|
1121
|
+
if (controller.disposed || controller.solidRenderRetryScheduled) return;
|
|
1122
|
+
controller.solidRenderRetryScheduled = true;
|
|
1123
|
+
|
|
1124
|
+
const schedule = globalThis.queueMicrotask ?? (callback => Promise.resolve().then(callback));
|
|
1125
|
+
schedule(() => {
|
|
1126
|
+
controller.solidRenderRetryScheduled = false;
|
|
1127
|
+
if (controller.disposed) return;
|
|
1128
|
+
|
|
1129
|
+
const matches = [];
|
|
1130
|
+
for (const element of controller.renderElements) {
|
|
1131
|
+
const state = solidRenderInternals.get(element);
|
|
1132
|
+
if (!state?.connected || !state.pendingModuleResolution) continue;
|
|
1133
|
+
const requested = nonEmpty(element.getAttribute?.("module"));
|
|
1134
|
+
if (!requested) continue;
|
|
1135
|
+
let resolved;
|
|
1136
|
+
try {
|
|
1137
|
+
resolved = controller.runtime.resolve(requested);
|
|
1138
|
+
} catch {
|
|
1139
|
+
continue;
|
|
1140
|
+
}
|
|
1141
|
+
if (resolved === definedId) matches.push(element);
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
if (matches.length > 0) {
|
|
1145
|
+
void retrySolidRenderElements(controller, matches, {
|
|
1146
|
+
reason: "module-defined",
|
|
1147
|
+
forceMissingError: false,
|
|
1148
|
+
});
|
|
1149
|
+
}
|
|
1150
|
+
});
|
|
1151
|
+
}
|
|
1152
|
+
|
|
988
1153
|
function dispatchSolidRenderError(element, error) {
|
|
989
1154
|
try {
|
|
990
1155
|
const EventImpl = globalThis.CustomEvent;
|
|
@@ -1024,6 +1189,8 @@ async function disposeController(controller, options = {}) {
|
|
|
1024
1189
|
}
|
|
1025
1190
|
|
|
1026
1191
|
activeControllers.delete(controller);
|
|
1192
|
+
controller.runtimeModuleDefinedUnsubscribe?.();
|
|
1193
|
+
controller.runtimeModuleDefinedUnsubscribe = undefined;
|
|
1027
1194
|
controller.runtimeDisposeUnsubscribe?.();
|
|
1028
1195
|
controller.runtimeDisposeUnsubscribe = undefined;
|
|
1029
1196
|
controller.events.clear();
|
|
@@ -1163,6 +1330,11 @@ async function enqueueObserverScan(controller, callOptions = {}) {
|
|
|
1163
1330
|
}
|
|
1164
1331
|
|
|
1165
1332
|
await cleanupDetachedRenderedDeclarations(controller, root);
|
|
1333
|
+
await retrySolidRenderElements(
|
|
1334
|
+
controller,
|
|
1335
|
+
collectConnectedSolidRenderElements(controller, root),
|
|
1336
|
+
{ reason: "observer-batch-complete", forceMissingError: true },
|
|
1337
|
+
);
|
|
1166
1338
|
|
|
1167
1339
|
emitHTML(controller, {
|
|
1168
1340
|
type: "observer-batch",
|