@absolutejs/absolute 0.20.0-beta.170 → 0.20.0-beta.171
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/CHANGELOG.md +50 -0
- package/README.md +33 -4
- package/changelog.json +112 -0
- package/dist/angular/browser.js +2 -2
- package/dist/angular/browser.js.map +3 -3
- package/dist/angular/components/constants.js +1 -0
- package/dist/angular/components/core/streamingSlotRegistrar.js +2 -2
- package/dist/angular/components/core/streamingSlotRegistry.js +3 -3
- package/dist/angular/index.js +184 -29
- package/dist/angular/index.js.map +15 -14
- package/dist/angular/server.js +184 -29
- package/dist/angular/server.js.map +15 -14
- package/dist/build.js +1241 -853
- package/dist/build.js.map +32 -30
- package/dist/cli/{add-6a7pjkn9.js → add-ae6mg79m.js} +10 -10
- package/dist/cli/{analyze-606fshwa.js → analyze-e57zz9x8.js} +3 -3
- package/dist/cli/{androidEmulatorController-68jjdxmx.js → androidEmulatorController-vqc5m2rp.js} +6 -6
- package/dist/cli/{androidNativeWatcher-x032x9yr.js → androidNativeWatcher-s03aczxv.js} +6 -6
- package/dist/cli/{api-mshjr4ah.js → api-8ppxw487.js} +8 -8
- package/dist/cli/{build-g81xqbb9.js → build-fz7qbdn3.js} +3 -3
- package/dist/cli/{buildDepVendor-29d8v9cx.js → buildDepVendor-qvsh6dsj.js} +7 -3
- package/dist/cli/{compile-9y1w9zpj.js → compile-ndc36zna.js} +10 -7
- package/dist/cli/config/server.js +36 -6
- package/dist/cli/{db-5b4s1kvx.js → db-qbzjw3en.js} +2 -2
- package/dist/cli/{dev-hyeb89hp.js → dev-x49583aj.js} +43 -15
- package/dist/cli/{doctor-h55y9hj1.js → doctor-repprx92.js} +42 -12
- package/dist/cli/{emulatorDoctor-p3yt7140.js → emulatorDoctor-s1z5tkp7.js} +5 -5
- package/dist/cli/{emulatorInstaller-4pm2kx9w.js → emulatorInstaller-pgkdswvq.js} +6 -6
- package/dist/cli/{env-snb0597q.js → env-5nz1qm8e.js} +3 -3
- package/dist/cli/{expoDevController-0vj8dvkh.js → expoDevController-018anvbm.js} +6 -6
- package/dist/cli/{generate-20x1pkf7.js → generate-brvjesd6.js} +8 -8
- package/dist/cli/{heapDiff-wqj8vrq8.js → heapDiff-kncvdtn8.js} +3 -3
- package/dist/cli/htmx/htmx.min.js +1 -1
- package/dist/cli/{htmx-6mz2h7k1.js → htmx-5twhjz7p.js} +7 -7
- package/dist/cli/{index-w09fzs9f.js → index-0z5fgb80.js} +1 -1
- package/dist/cli/{index-exfkpjja.js → index-125cfzvn.js} +2 -2
- package/dist/cli/{index-32ge2w1f.js → index-25e7k849.js} +16 -8
- package/dist/cli/{index-ys2rzqhg.js → index-2shf4aya.js} +1 -1
- package/dist/cli/{index-74m7kh8c.js → index-3ewt17wm.js} +1 -1
- package/dist/cli/{index-zd3cna19.js → index-3sfcmb49.js} +1 -1
- package/dist/cli/{index-14fbvz34.js → index-50ag35xg.js} +2 -2
- package/dist/cli/{index-h5qx5jpk.js → index-7854xf0m.js} +1 -1
- package/dist/cli/{index-3y57kd7x.js → index-8khbn8qr.js} +3 -3
- package/dist/cli/{index-xw1byvzp.js → index-9djrap79.js} +1 -1
- package/dist/cli/{index-ppphkyps.js → index-a6xx0p9e.js} +1 -1
- package/dist/cli/{index-g4ehq6ev.js → index-aemhvvwb.js} +1 -1
- package/dist/cli/{index-z6f43b20.js → index-b1wht4q5.js} +1 -1
- package/dist/cli/{index-s3xvccq3.js → index-btp4fyf1.js} +2 -2
- package/dist/cli/{index-066qhc6n.js → index-cgmp9d02.js} +1 -1
- package/dist/cli/{index-3wz3mktm.js → index-gyjxrnnz.js} +1 -1
- package/dist/cli/index-jwfambwe.js +13 -0
- package/dist/cli/{index-3wm8p7rg.js → index-n6faa3m3.js} +1 -1
- package/dist/cli/{index-kye08pjx.js → index-pr1skxen.js} +1 -1
- package/dist/cli/{index-t8cf0zj9.js → index-prza6tkp.js} +3 -3
- package/dist/cli/{index-qbrzvmh9.js → index-q3snnhyd.js} +1 -1
- package/dist/cli/{index-3vmc30gf.js → index-rz56x932.js} +1 -1
- package/dist/cli/{index-9sksd8c8.js → index-vh68jb0e.js} +2 -2
- package/dist/cli/index.js +32 -32
- package/dist/cli/{info-mn125212.js → info-k124sh7g.js} +4 -4
- package/dist/cli/{inspect-c7s117j0.js → inspect-n6pcfvfw.js} +5 -5
- package/dist/cli/{iosNativeWatcher-0nm6qad5.js → iosNativeWatcher-wdq2fvj1.js} +7 -7
- package/dist/cli/{iosSimulatorController-hza2c3rv.js → iosSimulatorController-n97dpa8p.js} +7 -7
- package/dist/cli/{islands-dc54e5y1.js → islands-p4vgx7a2.js} +3 -3
- package/dist/cli/{logs-ej1add2b.js → logs-shg23fbt.js} +3 -3
- package/dist/cli/{ls-b6zz24nt.js → ls-0hfx323m.js} +3 -3
- package/dist/cli/{mem-5q7n3ymb.js → mem-16sy1707.js} +5 -5
- package/dist/cli/{migrate-6nm4kdf6.js → migrate-k91k050s.js} +2 -2
- package/dist/cli/{mobile-ajnnvqtv.js → mobile-nqdkk3gd.js} +13 -13
- package/dist/cli/prerender-010z771p.js +10 -0
- package/dist/cli/{prettier-phdtvqef.js → prettier-dh5fh786.js} +1 -1
- package/dist/cli/{ps-ezmzyscn.js → ps-pk7ncjac.js} +6 -6
- package/dist/cli/{psTui-3x3ykjve.js → psTui-50wf0b72.js} +7 -7
- package/dist/cli/{remoteMacProtocol-g09myqt5.js → remoteMacProtocol-g10s408w.js} +7 -7
- package/dist/cli/{remove-t8x1mrxg.js → remove-abaf0w6k.js} +8 -8
- package/dist/cli/{routes-3xj256gx.js → routes-mc3ymp8t.js} +3 -3
- package/dist/cli/{start-d6p831ny.js → start-t3cq57wn.js} +5 -5
- package/dist/cli/{typecheck-stbt0qt5.js → typecheck-209bemxm.js} +17 -4
- package/dist/cli/{workspace-61hh6jq1.js → workspace-7sbyyc59.js} +5 -5
- package/dist/client/chunks/islands-s2ta5ajb.js.map +1 -1
- package/dist/client/navigation.js +2 -1
- package/dist/client/navigation.js.map +3 -3
- package/dist/dev/client/domTracker.ts +52 -19
- package/dist/dev/client/frameworkDetect.ts +11 -0
- package/dist/dev/client/handlers/html.ts +6 -1
- package/dist/dev/client/handlers/htmx.ts +6 -1
- package/dist/dev/client/hmrClient.ts +10 -0
- package/dist/dev/serverBootstrap.js +112 -6
- package/dist/index.js +1147 -757
- package/dist/index.js.map +32 -30
- package/dist/islands/index.js +16 -5
- package/dist/islands/index.js.map +6 -6
- package/dist/mobile/index.js +2 -2
- package/dist/mobile/index.js.map +3 -3
- package/dist/react/components/index.js +2 -2
- package/dist/react/components/index.js.map +3 -3
- package/dist/react/index.js +85 -18
- package/dist/react/index.js.map +11 -11
- package/dist/react/server.js +71 -15
- package/dist/react/server.js.map +8 -8
- package/dist/src/angular/baseHref.d.ts +2 -0
- package/dist/src/angular/components/constants.d.ts +1 -0
- package/dist/src/angular/ssrRender.d.ts +1 -1
- package/dist/src/build/compileAngular.d.ts +15 -0
- package/dist/src/build/resolveBuildMode.d.ts +6 -0
- package/dist/src/build/scanAngularHandlerCalls.d.ts +3 -1
- package/dist/src/build/verifyAngularCoreUniqueness.d.ts +3 -1
- package/dist/src/cli/htmx/install.d.ts +1 -1
- package/dist/src/cli/typeGraphCoherence.d.ts +9 -2
- package/dist/src/constants.d.ts +1 -0
- package/dist/src/core/appErrorHooks.d.ts +8 -0
- package/dist/src/core/islandPageContext.d.ts +5 -1
- package/dist/src/core/requestContext.d.ts +5 -0
- package/dist/src/core/serverOnlyStaticFiles.d.ts +7 -0
- package/dist/src/dev/editorTempFiles.d.ts +3 -0
- package/dist/src/dev/hot/analyze.d.ts +1 -1
- package/dist/src/dev/hot/runtime.d.ts +20 -0
- package/dist/src/dev/importCost/instrument.d.ts +1 -1
- package/dist/src/dev/rebuildTrigger.d.ts +1 -0
- package/dist/src/utils/cleanStaleOutputs.d.ts +4 -1
- package/dist/src/utils/logger.d.ts +3 -2
- package/dist/src/utils/resolveConvention.d.ts +1 -0
- package/dist/src/utils/ssrErrorPage.d.ts +3 -0
- package/dist/svelte/index.js +85 -18
- package/dist/svelte/index.js.map +11 -11
- package/dist/svelte/router/Route.svelte.d.ts +1 -2
- package/dist/svelte/router/Router.svelte +2 -4
- package/dist/svelte/server.js +73 -16
- package/dist/svelte/server.js.map +9 -9
- package/dist/types/globals.d.ts +3 -0
- package/dist/types/svelteRouter.ts +3 -12
- package/dist/vue/components/Image.js +2 -2
- package/dist/vue/components/Image.js.map +3 -3
- package/dist/vue/components/index.js +2 -2
- package/dist/vue/components/index.js.map +3 -3
- package/dist/vue/index.js +158 -91
- package/dist/vue/index.js.map +12 -12
- package/dist/vue/server.js +144 -88
- package/dist/vue/server.js.map +9 -9
- package/package.json +1 -1
- package/dist/cli/prerender-fqpp0m1j.js +0 -10
- /package/dist/cli/{index-vtp20gwf.js → index-2bxfhs32.js} +0 -0
- /package/dist/cli/{index-fgz435qn.js → index-t8jmj8w1.js} +0 -0
|
@@ -1,13 +1,58 @@
|
|
|
1
1
|
import type {} from '../../types/globals';
|
|
2
2
|
/* Snapshot/restore for JS-modified DOM state across HMR updates.
|
|
3
3
|
* Before patching, captures text and dynamic children of elements with IDs.
|
|
4
|
-
* After patching, restores values that were changed by user scripts.
|
|
4
|
+
* After patching, restores values that were changed by user scripts.
|
|
5
|
+
*
|
|
6
|
+
* "Changed by user scripts" means the live value differs from what the
|
|
7
|
+
* server last sent for that element (the baseline), not from what it sends
|
|
8
|
+
* now. Comparing against the new markup alone would treat every edited
|
|
9
|
+
* text as a script change and put the old text back. The baseline is the
|
|
10
|
+
* page as parsed when the HMR client starts (captureServerDOM), then each
|
|
11
|
+
* update's markup. */
|
|
5
12
|
|
|
6
13
|
type DOMSnapshot = {
|
|
7
14
|
children: Map<string, string>;
|
|
8
15
|
text: Map<string, string>;
|
|
9
16
|
};
|
|
10
17
|
|
|
18
|
+
let serverBaseline: DOMSnapshot | null = null;
|
|
19
|
+
|
|
20
|
+
const collectIdState = (root: ParentNode): DOMSnapshot => {
|
|
21
|
+
const text = new Map<string, string>();
|
|
22
|
+
const children = new Map<string, string>();
|
|
23
|
+
|
|
24
|
+
root.querySelectorAll('[id]').forEach((elem) => {
|
|
25
|
+
const { childNodes } = elem;
|
|
26
|
+
const isTextLeaf = Array.from(childNodes).every(
|
|
27
|
+
(child) => child.nodeType === Node.TEXT_NODE
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
if (isTextLeaf && childNodes.length > 0) {
|
|
31
|
+
text.set(elem.id, elem.textContent || '');
|
|
32
|
+
} else if (elem.children.length > 0) {
|
|
33
|
+
children.set(elem.id, elem.innerHTML);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return { children, text };
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/* Record the server-rendered DOM as the baseline. Call once, when the HMR
|
|
41
|
+
* client starts: it runs at the end of <body>, before most page scripts
|
|
42
|
+
* have changed anything. */
|
|
43
|
+
export const captureServerDOM = (root: ParentNode | null | undefined) => {
|
|
44
|
+
if (!root || serverBaseline) return;
|
|
45
|
+
serverBaseline = collectIdState(root);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/* True when the live value still matches what the server last sent, i.e.
|
|
49
|
+
* no script touched it: the new server value wins. */
|
|
50
|
+
const isUntouched = (
|
|
51
|
+
baseline: Map<string, string> | undefined,
|
|
52
|
+
elId: string,
|
|
53
|
+
liveValue: string
|
|
54
|
+
) => baseline?.has(elId) === true && baseline.get(elId) === liveValue;
|
|
55
|
+
|
|
11
56
|
export const restoreDOMChanges = (
|
|
12
57
|
root: HTMLElement,
|
|
13
58
|
snapshot: DOMSnapshot,
|
|
@@ -15,12 +60,14 @@ export const restoreDOMChanges = (
|
|
|
15
60
|
) => {
|
|
16
61
|
const tempDiv = document.createElement('div');
|
|
17
62
|
tempDiv.innerHTML = newHTML;
|
|
63
|
+
const baseline = serverBaseline;
|
|
18
64
|
|
|
19
65
|
/* Restore JS-modified text on leaf elements */
|
|
20
66
|
snapshot.text.forEach((liveText, elId) => {
|
|
21
67
|
const newEl = tempDiv.querySelector(`#${CSS.escape(elId)}`);
|
|
22
68
|
const newText = newEl ? newEl.textContent || '' : '';
|
|
23
69
|
if (liveText === newText) return;
|
|
70
|
+
if (isUntouched(baseline?.text, elId, liveText)) return;
|
|
24
71
|
|
|
25
72
|
const liveEl = root.querySelector(`#${CSS.escape(elId)}`);
|
|
26
73
|
if (liveEl) {
|
|
@@ -33,29 +80,15 @@ export const restoreDOMChanges = (
|
|
|
33
80
|
const newEl = tempDiv.querySelector(`#${CSS.escape(elId)}`);
|
|
34
81
|
const newInner = newEl ? newEl.innerHTML : '';
|
|
35
82
|
if (liveHTML === newInner || liveHTML.length <= newInner.length) return;
|
|
83
|
+
if (isUntouched(baseline?.children, elId, liveHTML)) return;
|
|
36
84
|
|
|
37
85
|
const liveEl = root.querySelector(`#${CSS.escape(elId)}`);
|
|
38
86
|
if (liveEl) {
|
|
39
87
|
liveEl.innerHTML = liveHTML;
|
|
40
88
|
}
|
|
41
89
|
});
|
|
42
|
-
};
|
|
43
|
-
export const snapshotDOMChanges = (root: HTMLElement): DOMSnapshot => {
|
|
44
|
-
const text = new Map<string, string>();
|
|
45
|
-
const children = new Map<string, string>();
|
|
46
|
-
|
|
47
|
-
root.querySelectorAll('[id]').forEach((elem) => {
|
|
48
|
-
const { childNodes } = elem;
|
|
49
|
-
const isTextLeaf = Array.from(childNodes).every(
|
|
50
|
-
(child) => child.nodeType === Node.TEXT_NODE
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
if (isTextLeaf && childNodes.length > 0) {
|
|
54
|
-
text.set(elem.id, elem.textContent || '');
|
|
55
|
-
} else if (elem.children.length > 0) {
|
|
56
|
-
children.set(elem.id, elem.innerHTML);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
90
|
|
|
60
|
-
|
|
91
|
+
// The markup just applied is what the server sent last.
|
|
92
|
+
serverBaseline = collectIdState(tempDiv);
|
|
61
93
|
};
|
|
94
|
+
export const snapshotDOMChanges = (root: HTMLElement) => collectIdState(root);
|
|
@@ -61,3 +61,14 @@ export const getComponentNameFromPath = (filePath: string) => {
|
|
|
61
61
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
62
62
|
.join('');
|
|
63
63
|
};
|
|
64
|
+
/* Static (HTML/HTMX) pages are told which built page they are (see
|
|
65
|
+
* injectHMRIntoHTMLFile in build.ts). Every tab receives every page's
|
|
66
|
+
* html-update / htmx-update, so a tab applies only its own page's. A
|
|
67
|
+
* document without a page name (older builds) applies all of them. */
|
|
68
|
+
export const isUpdateForThisPage = (sourceFile: unknown) => {
|
|
69
|
+
const page = window.__HMR_PAGE__;
|
|
70
|
+
if (!page || typeof sourceFile !== 'string') return true;
|
|
71
|
+
const normalized = sourceFile.replace(/\\/g, '/');
|
|
72
|
+
|
|
73
|
+
return normalized.slice(normalized.lastIndexOf('/') + 1) === page;
|
|
74
|
+
};
|
|
@@ -14,7 +14,10 @@ import {
|
|
|
14
14
|
} from '../domState';
|
|
15
15
|
import { processCSSLinks, waitForCSSAndUpdate } from '../cssUtils';
|
|
16
16
|
import { patchHeadInPlace } from '../headPatch';
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
detectCurrentFramework,
|
|
19
|
+
isUpdateForThisPage
|
|
20
|
+
} from '../frameworkDetect';
|
|
18
21
|
import type { ScriptInfo } from '../../../types/client';
|
|
19
22
|
import { restoreDOMChanges, snapshotDOMChanges } from '../domTracker';
|
|
20
23
|
import { hmrState } from '../hmrState';
|
|
@@ -86,6 +89,7 @@ export const handleHTMLUpdate = (message: {
|
|
|
86
89
|
data: {
|
|
87
90
|
html?: string | { body?: string; head?: string } | null;
|
|
88
91
|
serverDuration?: number;
|
|
92
|
+
sourceFile?: string;
|
|
89
93
|
};
|
|
90
94
|
timestamp?: number;
|
|
91
95
|
}) => {
|
|
@@ -93,6 +97,7 @@ export const handleHTMLUpdate = (message: {
|
|
|
93
97
|
if (htmlFrameworkCheck !== 'html') {
|
|
94
98
|
return;
|
|
95
99
|
}
|
|
100
|
+
if (!isUpdateForThisPage(message.data.sourceFile)) return;
|
|
96
101
|
|
|
97
102
|
if (window.__REACT_ROOT__) {
|
|
98
103
|
window.__REACT_ROOT__ = undefined;
|
|
@@ -14,7 +14,10 @@ import {
|
|
|
14
14
|
} from '../domState';
|
|
15
15
|
import { processCSSLinks, waitForCSSAndUpdate } from '../cssUtils';
|
|
16
16
|
import { patchHeadInPlace } from '../headPatch';
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
detectCurrentFramework,
|
|
19
|
+
isUpdateForThisPage
|
|
20
|
+
} from '../frameworkDetect';
|
|
18
21
|
import { type HTMXSavedState, type ScriptInfo } from '../../../types/client';
|
|
19
22
|
import { hmrState } from '../hmrState';
|
|
20
23
|
import { sendAbsoluteHmrTiming } from '../hmrTiming';
|
|
@@ -72,11 +75,13 @@ export const handleHTMXUpdate = (message: {
|
|
|
72
75
|
data: {
|
|
73
76
|
html?: string | { body?: string; head?: string } | null;
|
|
74
77
|
serverDuration?: number;
|
|
78
|
+
sourceFile?: string;
|
|
75
79
|
};
|
|
76
80
|
timestamp?: number;
|
|
77
81
|
}) => {
|
|
78
82
|
const htmxFrameworkCheck = detectCurrentFramework();
|
|
79
83
|
if (htmxFrameworkCheck !== 'htmx') return;
|
|
84
|
+
if (!isUpdateForThisPage(message.data.sourceFile)) return;
|
|
80
85
|
|
|
81
86
|
if (window.__REACT_ROOT__) {
|
|
82
87
|
window.__REACT_ROOT__ = undefined;
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
type ServerSnapshot
|
|
16
16
|
} from './reconnect';
|
|
17
17
|
import { detectCurrentFramework } from './frameworkDetect';
|
|
18
|
+
import { captureServerDOM } from './domTracker';
|
|
18
19
|
import {
|
|
19
20
|
absoluteHmrClientTarget,
|
|
20
21
|
restoreAbsoluteHmrApply,
|
|
@@ -159,6 +160,15 @@ if (typeof window !== 'undefined') {
|
|
|
159
160
|
if (!window.__HMR_SERVER_VERSIONS__) {
|
|
160
161
|
window.__HMR_SERVER_VERSIONS__ = {};
|
|
161
162
|
}
|
|
163
|
+
// Static pages: remember the server-rendered text of elements with an
|
|
164
|
+
// id, so an HMR update can tell script changes from edited markup.
|
|
165
|
+
const framework = window.__HMR_FRAMEWORK__;
|
|
166
|
+
if (
|
|
167
|
+
(framework === 'html' || framework === 'htmx') &&
|
|
168
|
+
typeof document !== 'undefined'
|
|
169
|
+
) {
|
|
170
|
+
captureServerDOM(document.body);
|
|
171
|
+
}
|
|
162
172
|
}
|
|
163
173
|
|
|
164
174
|
// Catch uncaught runtime errors and show the error overlay
|
|
@@ -739,7 +739,7 @@ var init_workspacePackages = __esm(() => {
|
|
|
739
739
|
|
|
740
740
|
// src/dev/hot/analyze.ts
|
|
741
741
|
import { dirname, extname } from "path";
|
|
742
|
-
var ANALYZER_VERSION =
|
|
742
|
+
var ANALYZER_VERSION = 2, hashText = (text) => Bun.hash(text).toString(36), scriptKindFor = (tsc, path) => {
|
|
743
743
|
switch (extname(path)) {
|
|
744
744
|
case ".tsx":
|
|
745
745
|
return tsc.ScriptKind.TSX;
|
|
@@ -997,7 +997,23 @@ var ANALYZER_VERSION = 1, hashText = (text) => Bun.hash(text).toString(36), scri
|
|
|
997
997
|
while (current && (tsc.isParenthesizedExpression(current) || tsc.isAsExpression(current) || tsc.isSatisfiesExpression(current)))
|
|
998
998
|
current = current.expression;
|
|
999
999
|
return current !== undefined && (tsc.isArrowFunction(current) || tsc.isFunctionExpression(current));
|
|
1000
|
-
}, IDENTIFIER,
|
|
1000
|
+
}, IDENTIFIER, STATEFUL_FACTORIES, STATIC_IDENTIFIERS, isStaticExpression = (tsc, node) => {
|
|
1001
|
+
if (tsc.isParenthesizedExpression(node) || tsc.isAsExpression(node) || tsc.isSatisfiesExpression(node) || tsc.isSpreadElement(node) || tsc.isSpreadAssignment(node))
|
|
1002
|
+
return isStaticExpression(tsc, node.expression);
|
|
1003
|
+
if (tsc.isStringLiteral(node) || tsc.isNumericLiteral(node) || tsc.isBigIntLiteral(node) || tsc.isNoSubstitutionTemplateLiteral(node) || tsc.isRegularExpressionLiteral(node) || node.kind === tsc.SyntaxKind.TrueKeyword || node.kind === tsc.SyntaxKind.FalseKeyword || node.kind === tsc.SyntaxKind.NullKeyword || tsc.isOmittedExpression(node))
|
|
1004
|
+
return true;
|
|
1005
|
+
if (tsc.isIdentifier(node))
|
|
1006
|
+
return STATIC_IDENTIFIERS.has(node.text);
|
|
1007
|
+
if (tsc.isPrefixUnaryExpression(node))
|
|
1008
|
+
return isStaticExpression(tsc, node.operand);
|
|
1009
|
+
if (tsc.isArrayLiteralExpression(node))
|
|
1010
|
+
return node.elements.every((element) => isStaticExpression(tsc, element));
|
|
1011
|
+
if (tsc.isObjectLiteralExpression(node))
|
|
1012
|
+
return node.properties.every((property) => tsc.isSpreadAssignment(property) ? isStaticExpression(tsc, property) : tsc.isPropertyAssignment(property) && (!tsc.isComputedPropertyName(property.name) || isStaticExpression(tsc, property.name.expression)) && isStaticExpression(tsc, property.initializer));
|
|
1013
|
+
if (tsc.isTemplateExpression(node))
|
|
1014
|
+
return node.templateSpans.every((span) => isStaticExpression(tsc, span.expression));
|
|
1015
|
+
return false;
|
|
1016
|
+
}, rejection = (reason) => ({
|
|
1001
1017
|
ok: false,
|
|
1002
1018
|
reason
|
|
1003
1019
|
}), addImport = (scope, local, binding) => {
|
|
@@ -1008,14 +1024,23 @@ var ANALYZER_VERSION = 1, hashText = (text) => Bun.hash(text).toString(36), scri
|
|
|
1008
1024
|
if (!clause || clause.isTypeOnly)
|
|
1009
1025
|
return;
|
|
1010
1026
|
const specifier = statement.moduleSpecifier;
|
|
1011
|
-
const
|
|
1027
|
+
const written = tsc.isStringLiteralLike(specifier) || tsc.isIdentifier(specifier) ? specifier.text : undefined;
|
|
1028
|
+
const module = written === undefined ? undefined : resolveImport(written);
|
|
1012
1029
|
if (clause.name)
|
|
1013
|
-
addImport(scope, clause.name.text, {
|
|
1030
|
+
addImport(scope, clause.name.text, {
|
|
1031
|
+
module,
|
|
1032
|
+
name: "default",
|
|
1033
|
+
specifier: written
|
|
1034
|
+
});
|
|
1014
1035
|
const bindings = clause.namedBindings;
|
|
1015
1036
|
if (!bindings)
|
|
1016
1037
|
return;
|
|
1017
1038
|
if (tsc.isNamespaceImport(bindings)) {
|
|
1018
|
-
addImport(scope, bindings.name.text, {
|
|
1039
|
+
addImport(scope, bindings.name.text, {
|
|
1040
|
+
module,
|
|
1041
|
+
name: "*",
|
|
1042
|
+
specifier: written
|
|
1043
|
+
});
|
|
1019
1044
|
return;
|
|
1020
1045
|
}
|
|
1021
1046
|
for (const element of bindings.elements) {
|
|
@@ -1023,7 +1048,8 @@ var ANALYZER_VERSION = 1, hashText = (text) => Bun.hash(text).toString(36), scri
|
|
|
1023
1048
|
continue;
|
|
1024
1049
|
addImport(scope, element.name.text, {
|
|
1025
1050
|
module,
|
|
1026
|
-
name: (element.propertyName ?? element.name).text
|
|
1051
|
+
name: (element.propertyName ?? element.name).text,
|
|
1052
|
+
specifier: written
|
|
1027
1053
|
});
|
|
1028
1054
|
}
|
|
1029
1055
|
}, recordExportList = (tsc, scope, statement) => {
|
|
@@ -1397,8 +1423,58 @@ var ANALYZER_VERSION = 1, hashText = (text) => Bun.hash(text).toString(36), scri
|
|
|
1397
1423
|
edit(node.getStart(file), node.end - node.getStart(file), replacement);
|
|
1398
1424
|
}
|
|
1399
1425
|
};
|
|
1426
|
+
const statefulCall = (reference) => {
|
|
1427
|
+
if (reference.deferred || !reference.call)
|
|
1428
|
+
return;
|
|
1429
|
+
const imported = imports.get(reference.name);
|
|
1430
|
+
const factories = imported?.specifier ? STATEFUL_FACTORIES.get(imported.specifier) : undefined;
|
|
1431
|
+
if (!imported || !factories)
|
|
1432
|
+
return;
|
|
1433
|
+
const viaNamespace = imported.name === "*" && reference.member !== undefined;
|
|
1434
|
+
const name = viaNamespace ? reference.member : imported.name;
|
|
1435
|
+
const callee = viaNamespace ? reference.node.parent : reference.node;
|
|
1436
|
+
const call = callee.parent;
|
|
1437
|
+
if (!name || !factories.has(name) || !call || !tsc.isCallExpression(call) || call.expression !== callee)
|
|
1438
|
+
return;
|
|
1439
|
+
return { call, name };
|
|
1440
|
+
};
|
|
1441
|
+
const ownerId = (statement, node) => {
|
|
1442
|
+
const { node: root } = statement;
|
|
1443
|
+
if (!tsc.isVariableStatement(root))
|
|
1444
|
+
return statement.id;
|
|
1445
|
+
const declaration = root.declarationList.declarations.find((item) => item.pos <= node.pos && node.end <= item.end);
|
|
1446
|
+
const name = declaration ? bindingNames(tsc, declaration.name)[0] : undefined;
|
|
1447
|
+
if (!name)
|
|
1448
|
+
return statement.id;
|
|
1449
|
+
return statement.kind === "let" ? `${statement.id}:${name}` : `v:${name}`;
|
|
1450
|
+
};
|
|
1451
|
+
const rewriteStatefulCalls = (statement) => {
|
|
1452
|
+
if (statement.kind === "import" || statement.kind === "skip")
|
|
1453
|
+
return;
|
|
1454
|
+
const occurrences = new Map;
|
|
1455
|
+
for (const reference of statement.refs) {
|
|
1456
|
+
const found = statefulCall(reference);
|
|
1457
|
+
if (!found)
|
|
1458
|
+
continue;
|
|
1459
|
+
const { call, name } = found;
|
|
1460
|
+
const owner = ownerId(statement, call);
|
|
1461
|
+
const line = file.getLineAndCharacterOfPosition(call.getStart(file)).line + 1;
|
|
1462
|
+
const label = quote(`${name}(\u2026) on line ${line}`);
|
|
1463
|
+
const isStatic = call.arguments.every((argument) => isStaticExpression(tsc, argument));
|
|
1464
|
+
if (!isStatic && hasTopLevelAwait(tsc, call))
|
|
1465
|
+
continue;
|
|
1466
|
+
const textHash = hashText(call.getText(file));
|
|
1467
|
+
const occurrence = occurrences.get(`${owner}#${textHash}`) ?? 0;
|
|
1468
|
+
occurrences.set(`${owner}#${textHash}`, occurrence + 1);
|
|
1469
|
+
const key = quote(`${owner}#${textHash}#${occurrence}`);
|
|
1470
|
+
edit(call.getStart(file), 0, isStatic ? `__absH.p(${quote(owner)},${key},${label},()=>(` : `__absH.w(${quote(owner)},${key},${label},()=>(`);
|
|
1471
|
+
edit(call.end, 0, "))");
|
|
1472
|
+
}
|
|
1473
|
+
};
|
|
1400
1474
|
for (const statement of statements)
|
|
1401
1475
|
rewriteStatement(statement);
|
|
1476
|
+
for (const statement of statements)
|
|
1477
|
+
rewriteStatefulCalls(statement);
|
|
1402
1478
|
for (const statement of statements)
|
|
1403
1479
|
rewriteCellReferences(statement);
|
|
1404
1480
|
edits.sort(compareEdits);
|
|
@@ -1453,6 +1529,10 @@ var ANALYZER_VERSION = 1, hashText = (text) => Bun.hash(text).toString(36), scri
|
|
|
1453
1529
|
};
|
|
1454
1530
|
var init_analyze = __esm(() => {
|
|
1455
1531
|
IDENTIFIER = /^[A-Za-z_$][\w$]*$/;
|
|
1532
|
+
STATEFUL_FACTORIES = new Map([
|
|
1533
|
+
["@absolutejs/scoped-state", new Set(["scopedState"])]
|
|
1534
|
+
]);
|
|
1535
|
+
STATIC_IDENTIFIERS = new Set(["Infinity", "NaN", "undefined"]);
|
|
1456
1536
|
});
|
|
1457
1537
|
|
|
1458
1538
|
// src/dev/hot/runtime.ts
|
|
@@ -1464,6 +1544,7 @@ var records, recordFor = (path) => {
|
|
|
1464
1544
|
const created = {
|
|
1465
1545
|
cells: {},
|
|
1466
1546
|
generation: 0,
|
|
1547
|
+
instances: new Map,
|
|
1467
1548
|
keys: new Map,
|
|
1468
1549
|
lastChanged: new Set,
|
|
1469
1550
|
lastTimings: new Map,
|
|
@@ -1472,6 +1553,7 @@ var records, recordFor = (path) => {
|
|
|
1472
1553
|
revisions: new Map,
|
|
1473
1554
|
slots: new Map,
|
|
1474
1555
|
tag: 0,
|
|
1556
|
+
warned: new Set,
|
|
1475
1557
|
watchers: new Map
|
|
1476
1558
|
};
|
|
1477
1559
|
records.set(path, created);
|
|
@@ -1514,6 +1596,7 @@ var records, recordFor = (path) => {
|
|
|
1514
1596
|
record.generation += 1;
|
|
1515
1597
|
const pending = {
|
|
1516
1598
|
generation: record.generation,
|
|
1599
|
+
instances: new Map,
|
|
1517
1600
|
meta,
|
|
1518
1601
|
reran: new Set,
|
|
1519
1602
|
seen: new Set,
|
|
@@ -1549,6 +1632,7 @@ var records, recordFor = (path) => {
|
|
|
1549
1632
|
pending.slots.set(id, { generation, value });
|
|
1550
1633
|
return value;
|
|
1551
1634
|
};
|
|
1635
|
+
const where = (label) => `${label} of ${relative(process.cwd(), path) || path}`;
|
|
1552
1636
|
return {
|
|
1553
1637
|
cells: record.cells,
|
|
1554
1638
|
c: (name, id, init) => {
|
|
@@ -1576,6 +1660,14 @@ var records, recordFor = (path) => {
|
|
|
1576
1660
|
return previous.value;
|
|
1577
1661
|
return store(id, await ownedAsync(id, factory));
|
|
1578
1662
|
},
|
|
1663
|
+
p: (owner, key, label, create) => {
|
|
1664
|
+
const previous = record.instances.get(key);
|
|
1665
|
+
const value = previous ? previous.value : create();
|
|
1666
|
+
if (!previous && record.keys.has(owner))
|
|
1667
|
+
console.log(`[hmr] ${where(label)} is new or changed, so its state starts empty`);
|
|
1668
|
+
pending.instances.set(key, { owner, value });
|
|
1669
|
+
return value;
|
|
1670
|
+
},
|
|
1579
1671
|
r: (id, effect) => {
|
|
1580
1672
|
if (kept(id))
|
|
1581
1673
|
return;
|
|
@@ -1587,6 +1679,13 @@ var records, recordFor = (path) => {
|
|
|
1587
1679
|
return;
|
|
1588
1680
|
await ownedAsync(id, effect);
|
|
1589
1681
|
store(id, undefined);
|
|
1682
|
+
},
|
|
1683
|
+
w: (owner, key, label, create) => {
|
|
1684
|
+
if (record.keys.has(owner) && !record.warned.has(key)) {
|
|
1685
|
+
record.warned.add(key);
|
|
1686
|
+
console.warn(`[hmr] ${where(label)} ran again because its statement re-ran, so the state it holds was reset. Create it in its own top-level const (const visitorState = scopedState({ \u2026 })) and pass that to .use() to keep it across edits.`);
|
|
1687
|
+
}
|
|
1688
|
+
return create();
|
|
1590
1689
|
}
|
|
1591
1690
|
};
|
|
1592
1691
|
}, exportToken = (module, name, call) => {
|
|
@@ -1612,6 +1711,12 @@ var records, recordFor = (path) => {
|
|
|
1612
1711
|
await Promise.all([...replaced.values()].map((slot) => disposeValue(slot.value).catch((error) => console.error(`[hmr] disposing a replaced value failed:`, error))));
|
|
1613
1712
|
if (record.generation > 1)
|
|
1614
1713
|
logDisposed(record.path, counts);
|
|
1714
|
+
}, keptInstances = (record, pending) => {
|
|
1715
|
+
const instances = new Map(pending.instances);
|
|
1716
|
+
for (const [key, instance] of record.instances)
|
|
1717
|
+
if (!instances.has(key) && pending.seen.has(instance.owner) && !pending.reran.has(instance.owner))
|
|
1718
|
+
instances.set(key, instance);
|
|
1719
|
+
return instances;
|
|
1615
1720
|
}, commit = (record, pending) => {
|
|
1616
1721
|
if (record.pending !== pending)
|
|
1617
1722
|
return;
|
|
@@ -1625,6 +1730,7 @@ var records, recordFor = (path) => {
|
|
|
1625
1730
|
record.keys = pending.keys;
|
|
1626
1731
|
record.lastChanged = pending.changedExports;
|
|
1627
1732
|
record.lastTimings = pending.timings;
|
|
1733
|
+
record.instances = keptInstances(record, pending);
|
|
1628
1734
|
for (const name of pending.changedExports)
|
|
1629
1735
|
record.revisions.set(name, (record.revisions.get(name) ?? 0) + 1);
|
|
1630
1736
|
if (replaced.size === 0)
|