@absolutejs/absolute 0.19.0-beta.1068 → 0.19.0-beta.1069
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/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/build.js.map +2 -2
- package/dist/dev/client/handlers/html.ts +23 -22
- package/dist/dev/client/handlers/svelte.ts +46 -8
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
|
@@ -187,9 +187,12 @@ const updateHTMLBody = (
|
|
|
187
187
|
const newInlineScripts = collectInlineScripts(tempDiv);
|
|
188
188
|
|
|
189
189
|
const htmlStructureChanged = didHTMLStructureChange(container, tempDiv);
|
|
190
|
+
const inlineScriptsChanged = didInlineScriptsChange(
|
|
191
|
+
oldInlineScripts,
|
|
192
|
+
newInlineScripts
|
|
193
|
+
);
|
|
190
194
|
const scriptsChanged =
|
|
191
|
-
didScriptsChange(existingScripts, newScripts) ||
|
|
192
|
-
didInlineScriptsChange(oldInlineScripts, newInlineScripts);
|
|
195
|
+
didScriptsChange(existingScripts, newScripts) || inlineScriptsChanged;
|
|
193
196
|
|
|
194
197
|
if (htmlStructureChanged || scriptsChanged) {
|
|
195
198
|
patchDOMInPlace(container, htmlBody);
|
|
@@ -207,27 +210,22 @@ const updateHTMLBody = (
|
|
|
207
210
|
// changed. A pure markup edit (e.g. a heading) leaves inline-script
|
|
208
211
|
// state and `addEventListener` handlers intact.
|
|
209
212
|
if (scriptsChanged) {
|
|
210
|
-
|
|
213
|
+
// Clone (which strips listeners via cloneNode) ONLY when an inline
|
|
214
|
+
// script changed: a changed inline script re-runs in place below
|
|
215
|
+
// and would otherwise double-bind on elements that still carry the
|
|
216
|
+
// old handler. Unchanged inline scripts are skipped on re-exec, and
|
|
217
|
+
// external modules are re-imported via `import()` whose module cache
|
|
218
|
+
// means an unchanged body never re-runs — cloning for those would
|
|
219
|
+
// orphan their listeners forever (the regression this fixes).
|
|
220
|
+
if (inlineScriptsChanged) {
|
|
221
|
+
cloneInteractiveElements(container);
|
|
222
|
+
}
|
|
211
223
|
reExecuteScripts(container, newScripts, oldInlineScripts);
|
|
212
224
|
}
|
|
213
225
|
});
|
|
214
226
|
sessionStorage.removeItem('__HMR_ACTIVE__');
|
|
215
227
|
};
|
|
216
228
|
|
|
217
|
-
const cloneHmrListenerElements = (container: HTMLElement) => {
|
|
218
|
-
container
|
|
219
|
-
.querySelectorAll('[data-hmr-listeners-attached]')
|
|
220
|
-
.forEach((elem) => {
|
|
221
|
-
const cloned = elem.cloneNode(true);
|
|
222
|
-
if (elem.parentNode) {
|
|
223
|
-
elem.parentNode.replaceChild(cloned, elem);
|
|
224
|
-
}
|
|
225
|
-
if (cloned instanceof Element) {
|
|
226
|
-
cloned.removeAttribute('data-hmr-listeners-attached');
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
};
|
|
230
|
-
|
|
231
229
|
const replaceInlineScript = (script: Element) => {
|
|
232
230
|
if (script.hasAttribute('data-hmr-client')) {
|
|
233
231
|
return;
|
|
@@ -266,7 +264,13 @@ const updateHTMLBodyDirect = (
|
|
|
266
264
|
restoreFormState(savedState.forms);
|
|
267
265
|
restoreScrollState(savedState.scroll);
|
|
268
266
|
|
|
269
|
-
|
|
267
|
+
// Unlike `updateHTMLBody` (which re-imports externals as ES modules and
|
|
268
|
+
// must not clone unchanged ones), this path rebuilds EVERY external
|
|
269
|
+
// script below as a fresh `<script src?t=>` tag that always
|
|
270
|
+
// re-executes. So a single clone here is correct and necessary: it
|
|
271
|
+
// gives each re-running script a pristine element to bind once, with no
|
|
272
|
+
// double-binding.
|
|
273
|
+
cloneInteractiveElements(container);
|
|
270
274
|
|
|
271
275
|
removeOldScripts(container);
|
|
272
276
|
newScripts.forEach((scriptInfo) => {
|
|
@@ -304,10 +308,7 @@ const collectInlineScripts = (elem: HTMLElement) =>
|
|
|
304
308
|
elem.querySelectorAll('script:not([src]):not([data-hmr-client])')
|
|
305
309
|
).map((script) => script.textContent || '');
|
|
306
310
|
|
|
307
|
-
const didInlineScriptsChange = (
|
|
308
|
-
oldInline: string[],
|
|
309
|
-
newInline: string[]
|
|
310
|
-
) =>
|
|
311
|
+
const didInlineScriptsChange = (oldInline: string[], newInline: string[]) =>
|
|
311
312
|
oldInline.length !== newInline.length ||
|
|
312
313
|
oldInline.some((content, idx) => content !== newInline[idx]);
|
|
313
314
|
|
|
@@ -273,13 +273,31 @@ export const handleSvelteUpdate = (message: {
|
|
|
273
273
|
const svelteWindow: SvelteHmrWindow = window;
|
|
274
274
|
const acceptRegistry = svelteWindow.__SVELTE_HMR_ACCEPT__;
|
|
275
275
|
|
|
276
|
-
// Save the OLD module's accept callback BEFORE importing.
|
|
277
|
-
|
|
276
|
+
// Save the OLD module's accept callback BEFORE importing. The exact
|
|
277
|
+
// key is the broadcast `pageModuleUrl`; on the happy path it matches
|
|
278
|
+
// the key the module server registered. If it doesn't (the registry
|
|
279
|
+
// was repopulated under a slightly different URL key, or `bun --hot`
|
|
280
|
+
// re-evaluated the module and reset `__SVELTE_HMR_ACCEPT__`), fall back
|
|
281
|
+
// to a suffix/basename match so we still find the callback. Exact match
|
|
282
|
+
// always wins, so the happy path is unchanged.
|
|
283
|
+
let acceptFn = acceptRegistry?.[pageModuleUrl];
|
|
284
|
+
if (!acceptFn && acceptRegistry) {
|
|
285
|
+
const wantBase = pageModuleUrl.split('?')[0] ?? pageModuleUrl;
|
|
286
|
+
const hit = Object.keys(acceptRegistry).find(
|
|
287
|
+
(key) =>
|
|
288
|
+
key === wantBase ||
|
|
289
|
+
key.endsWith(wantBase) ||
|
|
290
|
+
wantBase.endsWith(key)
|
|
291
|
+
);
|
|
292
|
+
if (hit) acceptFn = acceptRegistry[hit];
|
|
293
|
+
}
|
|
278
294
|
|
|
279
295
|
import(modulePath)
|
|
280
296
|
.then((newModule) => {
|
|
297
|
+
let applied = false;
|
|
281
298
|
if (acceptFn) {
|
|
282
299
|
acceptFn(newModule);
|
|
300
|
+
applied = true;
|
|
283
301
|
}
|
|
284
302
|
|
|
285
303
|
/* $.hmr_accept swaps component code in place but re-runs
|
|
@@ -290,15 +308,35 @@ export const handleSvelteUpdate = (message: {
|
|
|
290
308
|
* bootstrap — so that state carries across (issue #41). */
|
|
291
309
|
const preserved = window.__HMR_PRESERVED_STATE__;
|
|
292
310
|
const remount = window.__SVELTE_REMOUNT__;
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
311
|
+
const hasPreserved =
|
|
312
|
+
preserved && Object.keys(preserved).length > 0;
|
|
313
|
+
|
|
314
|
+
if (applied) {
|
|
315
|
+
if (typeof remount === 'function' && hasPreserved) {
|
|
316
|
+
remount({
|
|
317
|
+
...(window.__INITIAL_PROPS__ ?? {}),
|
|
318
|
+
...preserved
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
} else if (typeof remount === 'function') {
|
|
322
|
+
/* Resilience fallback: no accept callback was found, so
|
|
323
|
+
* `$.hmr` never wired the freshly imported module in. The
|
|
324
|
+
* import warmed the module cache; remount the page with
|
|
325
|
+
* merged props to actually apply the new code instead of
|
|
326
|
+
* silently doing nothing. */
|
|
298
327
|
remount({
|
|
299
328
|
...(window.__INITIAL_PROPS__ ?? {}),
|
|
300
|
-
...preserved
|
|
329
|
+
...(preserved ?? {})
|
|
301
330
|
});
|
|
331
|
+
} else {
|
|
332
|
+
/* Last resort: nothing can apply the update in place. */
|
|
333
|
+
console.warn(
|
|
334
|
+
'[HMR] Svelte accept callback missing and no remount available; reloading'
|
|
335
|
+
);
|
|
336
|
+
window.__HMR_PRESERVED_STATE__ = undefined;
|
|
337
|
+
window.location.reload();
|
|
338
|
+
|
|
339
|
+
return undefined;
|
|
302
340
|
}
|
|
303
341
|
window.__HMR_PRESERVED_STATE__ = undefined;
|
|
304
342
|
|