@nativescript/vite 8.0.0-alpha.11 → 8.0.0-alpha.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/configuration/angular.d.ts +34 -1
- package/configuration/angular.js +165 -2
- package/configuration/angular.js.map +1 -1
- package/helpers/angular/inject-hmr-vite-ignore.d.ts +75 -0
- package/helpers/angular/inject-hmr-vite-ignore.js +288 -0
- package/helpers/angular/inject-hmr-vite-ignore.js.map +1 -0
- package/helpers/resolver.js +9 -1
- package/helpers/resolver.js.map +1 -1
- package/hmr/client/index.js +98 -0
- package/hmr/client/index.js.map +1 -1
- package/hmr/server/websocket.js +296 -13
- package/hmr/server/websocket.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-inject `/* @vite-ignore *\/` into Angular's HMR initializer dynamic
|
|
3
|
+
* imports.
|
|
4
|
+
*
|
|
5
|
+
* # Why this exists
|
|
6
|
+
*
|
|
7
|
+
* Angular's compiler (`@angular/compiler`'s `compileHmrInitializer`) emits
|
|
8
|
+
* each `@Component`-decorated class's HMR loader as:
|
|
9
|
+
*
|
|
10
|
+
* ```js
|
|
11
|
+
* function FooComponent_HmrLoad(t) {
|
|
12
|
+
* import(\/* @vite-ignore *\/ i0.ɵɵgetReplaceMetadataURL(id, t, import.meta.url))
|
|
13
|
+
* .then((m) => m.default && i0.ɵɵreplaceMetadata(FooComponent, m.default, ...));
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* The `\/* @vite-ignore *\/` annotation tells Vite "do not try to
|
|
18
|
+
* statically analyze this dynamic import" — the URL is computed at
|
|
19
|
+
* runtime by `ɵɵgetReplaceMetadataURL`, which produces something like
|
|
20
|
+
* `http://host/ns/m/<componentDir>/@ng/component?c=<id>&t=<ts>` to be
|
|
21
|
+
* resolved by Analog's `liveReloadPlugin` middleware on the dev server.
|
|
22
|
+
*
|
|
23
|
+
* Somewhere along the post-Angular transform chain — empirically the
|
|
24
|
+
* `compact: false` Babel pass driven by the Angular linker, but
|
|
25
|
+
* potentially other plugins as well — the leading-argument comment is
|
|
26
|
+
* being dropped. By the time the file lands on the device, the
|
|
27
|
+
* compiled emit reads:
|
|
28
|
+
*
|
|
29
|
+
* ```js
|
|
30
|
+
* import(i0.ɵɵgetReplaceMetadataURL(id, t, import.meta.url))
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* Vite's static analyzer logs:
|
|
34
|
+
*
|
|
35
|
+
* > The above dynamic import cannot be analyzed by Vite.
|
|
36
|
+
*
|
|
37
|
+
* and rewrites the call site to route through Vite's runtime resolver,
|
|
38
|
+
* which fails on the iOS runtime because the resolver expects a
|
|
39
|
+
* statically-known module specifier. The HMR loader IIFE runs at every
|
|
40
|
+
* component module evaluation (gated by `ngDevMode`), so the failure
|
|
41
|
+
* fires at boot for the FIRST `@Component` whose module is evaluated —
|
|
42
|
+
* typically a base/utility component like `ConfirmationDialogBaseComponent`
|
|
43
|
+
* — and aborts session startup with:
|
|
44
|
+
*
|
|
45
|
+
* > TypeError at Module.ɵɵgetReplaceMetadataURL
|
|
46
|
+
*
|
|
47
|
+
* Re-inserting the annotation downstream of every other transform makes
|
|
48
|
+
* us tolerant of upstream comment-loss without depending on the linker's
|
|
49
|
+
* comment behaviour. The fix is purely additive: if the comment is still
|
|
50
|
+
* present (Angular versions that emit it differently, or future
|
|
51
|
+
* compilers that wrap the URL in an alternate helper), `appendIfMissing`
|
|
52
|
+
* leaves the import untouched.
|
|
53
|
+
*
|
|
54
|
+
* # Idempotence
|
|
55
|
+
*
|
|
56
|
+
* The helper is safe to call repeatedly on the same source — once the
|
|
57
|
+
* annotation is present, subsequent calls become a no-op match by match.
|
|
58
|
+
* Vite's transform pipeline can replay cached transforms during a
|
|
59
|
+
* single dev session, so idempotence is required, not optional.
|
|
60
|
+
*
|
|
61
|
+
* # Surface area
|
|
62
|
+
*
|
|
63
|
+
* We only touch `import()` calls whose argument expression contains
|
|
64
|
+
* `ɵɵgetReplaceMetadataURL` (matching either the literal Unicode form
|
|
65
|
+
* or the escaped `\u0275\u0275getReplaceMetadataURL`). Every other
|
|
66
|
+
* dynamic import is left alone — an over-broad sweep would suppress
|
|
67
|
+
* Vite warnings on user dynamic imports that genuinely should be
|
|
68
|
+
* statically analyzed.
|
|
69
|
+
*/
|
|
70
|
+
const ANGULAR_HMR_IDENTIFIER = 'getReplaceMetadataURL';
|
|
71
|
+
const VITE_IGNORE_COMMENT = '/* @vite-ignore */';
|
|
72
|
+
/**
|
|
73
|
+
* Inject `/* @vite-ignore *\/` into every `import()` whose argument
|
|
74
|
+
* references Angular's `ɵɵgetReplaceMetadataURL`. Returns the original
|
|
75
|
+
* code unchanged when no qualifying imports are found.
|
|
76
|
+
*/
|
|
77
|
+
export function injectAngularHmrViteIgnore(code) {
|
|
78
|
+
if (!code)
|
|
79
|
+
return code;
|
|
80
|
+
// Cheap pre-check: bail out before walking the source if neither
|
|
81
|
+
// the unicode nor the escape form of the identifier is anywhere in
|
|
82
|
+
// the file. The vast majority of files aren't components, so this
|
|
83
|
+
// short-circuit is the hot path.
|
|
84
|
+
if (!code.includes(ANGULAR_HMR_IDENTIFIER))
|
|
85
|
+
return code;
|
|
86
|
+
let output = '';
|
|
87
|
+
let cursor = 0;
|
|
88
|
+
let changed = false;
|
|
89
|
+
while (cursor < code.length) {
|
|
90
|
+
const importIndex = findNextImportCall(code, cursor);
|
|
91
|
+
if (importIndex === -1) {
|
|
92
|
+
output += code.slice(cursor);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
const openParenIndex = findOpenParenAfter(code, importIndex + 'import'.length);
|
|
96
|
+
if (openParenIndex === -1) {
|
|
97
|
+
output += code.slice(cursor, importIndex + 'import'.length);
|
|
98
|
+
cursor = importIndex + 'import'.length;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const closeParenIndex = findMatchingDelimiter(code, openParenIndex, '(', ')');
|
|
102
|
+
if (closeParenIndex === -1) {
|
|
103
|
+
output += code.slice(cursor, openParenIndex + 1);
|
|
104
|
+
cursor = openParenIndex + 1;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const argumentBody = code.slice(openParenIndex + 1, closeParenIndex);
|
|
108
|
+
if (!referencesReplaceMetadataUrl(argumentBody)) {
|
|
109
|
+
output += code.slice(cursor, closeParenIndex + 1);
|
|
110
|
+
cursor = closeParenIndex + 1;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (alreadyAnnotated(argumentBody)) {
|
|
114
|
+
output += code.slice(cursor, closeParenIndex + 1);
|
|
115
|
+
cursor = closeParenIndex + 1;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
// Insert the annotation immediately after `import(` so the
|
|
119
|
+
// original argument expression — including any leading
|
|
120
|
+
// whitespace the upstream emitter chose — keeps its byte
|
|
121
|
+
// layout. This preserves source-map line stability for the
|
|
122
|
+
// rest of the file: only column offsets after the injection
|
|
123
|
+
// shift, never line numbers.
|
|
124
|
+
output += code.slice(cursor, openParenIndex + 1);
|
|
125
|
+
output += ` ${VITE_IGNORE_COMMENT} `;
|
|
126
|
+
output += code.slice(openParenIndex + 1, closeParenIndex + 1);
|
|
127
|
+
cursor = closeParenIndex + 1;
|
|
128
|
+
changed = true;
|
|
129
|
+
}
|
|
130
|
+
return changed ? output : code;
|
|
131
|
+
}
|
|
132
|
+
function findNextImportCall(source, startIndex) {
|
|
133
|
+
let i = startIndex;
|
|
134
|
+
while (i < source.length) {
|
|
135
|
+
const next = source.indexOf('import', i);
|
|
136
|
+
if (next === -1)
|
|
137
|
+
return -1;
|
|
138
|
+
// Reject `import.meta` and `import ` keyword forms; only
|
|
139
|
+
// `import(` (with optional whitespace) is a dynamic import.
|
|
140
|
+
const tail = next + 'import'.length;
|
|
141
|
+
const before = source.charCodeAt(next - 1);
|
|
142
|
+
const isWordCharBefore = isIdentifierPart(before);
|
|
143
|
+
if (!isWordCharBefore) {
|
|
144
|
+
let scan = tail;
|
|
145
|
+
while (scan < source.length && isWhitespace(source.charCodeAt(scan)))
|
|
146
|
+
scan++;
|
|
147
|
+
if (source.charCodeAt(scan) === 0x28 /* '(' */) {
|
|
148
|
+
return next;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
i = tail;
|
|
152
|
+
}
|
|
153
|
+
return -1;
|
|
154
|
+
}
|
|
155
|
+
function findOpenParenAfter(source, index) {
|
|
156
|
+
let i = index;
|
|
157
|
+
while (i < source.length && isWhitespace(source.charCodeAt(i)))
|
|
158
|
+
i++;
|
|
159
|
+
if (source.charCodeAt(i) === 0x28 /* '(' */)
|
|
160
|
+
return i;
|
|
161
|
+
return -1;
|
|
162
|
+
}
|
|
163
|
+
function alreadyAnnotated(argumentBody) {
|
|
164
|
+
// Trim only the leading whitespace + comments — body may have many
|
|
165
|
+
// non-`@vite-ignore` block comments later that we don't want to
|
|
166
|
+
// confuse for an already-applied annotation.
|
|
167
|
+
let i = 0;
|
|
168
|
+
while (i < argumentBody.length) {
|
|
169
|
+
const c = argumentBody.charCodeAt(i);
|
|
170
|
+
if (isWhitespace(c)) {
|
|
171
|
+
i++;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
if (c === 0x2f /* '/' */ && argumentBody.charCodeAt(i + 1) === 0x2a /* '*' */) {
|
|
175
|
+
const closeIndex = argumentBody.indexOf('*/', i + 2);
|
|
176
|
+
if (closeIndex === -1)
|
|
177
|
+
return false;
|
|
178
|
+
const commentBody = argumentBody.slice(i + 2, closeIndex);
|
|
179
|
+
if (commentBody.includes('@vite-ignore'))
|
|
180
|
+
return true;
|
|
181
|
+
i = closeIndex + 2;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
// First non-whitespace, non-block-comment token — there's no
|
|
185
|
+
// annotation in the leading whitespace window.
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
function referencesReplaceMetadataUrl(argumentBody) {
|
|
191
|
+
if (!argumentBody)
|
|
192
|
+
return false;
|
|
193
|
+
if (argumentBody.includes(ANGULAR_HMR_IDENTIFIER))
|
|
194
|
+
return true;
|
|
195
|
+
// `\u0275\u0275getReplaceMetadataURL` — unicode-escaped form some
|
|
196
|
+
// transforms emit. The substring above already covers the suffix
|
|
197
|
+
// regardless of the prefix encoding, so this branch is mostly
|
|
198
|
+
// defensive — keep it explicit so future changes to the identifier
|
|
199
|
+
// (e.g. a `replaceMetadataURL` rename without `ɵɵ`) don't silently
|
|
200
|
+
// stop matching.
|
|
201
|
+
return /\\u0275\\u0275getReplaceMetadataURL/.test(argumentBody);
|
|
202
|
+
}
|
|
203
|
+
function isWhitespace(code) {
|
|
204
|
+
return code === 0x20 || code === 0x09 || code === 0x0a || code === 0x0d || code === 0x0b || code === 0x0c;
|
|
205
|
+
}
|
|
206
|
+
function isIdentifierPart(code) {
|
|
207
|
+
if (Number.isNaN(code))
|
|
208
|
+
return false;
|
|
209
|
+
if (code === 0x5f /* '_' */ || code === 0x24 /* '$' */)
|
|
210
|
+
return true;
|
|
211
|
+
if (code >= 0x30 && code <= 0x39)
|
|
212
|
+
return true;
|
|
213
|
+
if (code >= 0x41 && code <= 0x5a)
|
|
214
|
+
return true;
|
|
215
|
+
if (code >= 0x61 && code <= 0x7a)
|
|
216
|
+
return true;
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Comment- and string-aware paren matcher. Used to find the closing
|
|
221
|
+
* `)` for `import(` even when the argument expression contains
|
|
222
|
+
* commented-out parens, template literals, or nested calls. Imported
|
|
223
|
+
* inline (rather than from `synthesize-decorator-ctor-parameters.ts`'s
|
|
224
|
+
* private helper) so this file has no internal dependencies and can
|
|
225
|
+
* be tested in isolation.
|
|
226
|
+
*/
|
|
227
|
+
function findMatchingDelimiter(source, openIndex, openChar, closeChar) {
|
|
228
|
+
if (openIndex < 0 || source[openIndex] !== openChar)
|
|
229
|
+
return -1;
|
|
230
|
+
let depth = 0;
|
|
231
|
+
let quote = null;
|
|
232
|
+
let escape = false;
|
|
233
|
+
let inLineComment = false;
|
|
234
|
+
let inBlockComment = false;
|
|
235
|
+
for (let index = openIndex; index < source.length; index++) {
|
|
236
|
+
const char = source[index];
|
|
237
|
+
const next = source[index + 1];
|
|
238
|
+
if (inLineComment) {
|
|
239
|
+
if (char === '\n')
|
|
240
|
+
inLineComment = false;
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (inBlockComment) {
|
|
244
|
+
if (char === '*' && next === '/') {
|
|
245
|
+
inBlockComment = false;
|
|
246
|
+
index++;
|
|
247
|
+
}
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
if (quote) {
|
|
251
|
+
if (escape) {
|
|
252
|
+
escape = false;
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
if (char === '\\') {
|
|
256
|
+
escape = true;
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
if (char === quote)
|
|
260
|
+
quote = null;
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
if (char === '/' && next === '/') {
|
|
264
|
+
inLineComment = true;
|
|
265
|
+
index++;
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
if (char === '/' && next === '*') {
|
|
269
|
+
inBlockComment = true;
|
|
270
|
+
index++;
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
if (char === '"' || char === "'" || char === '`') {
|
|
274
|
+
quote = char;
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
if (char === openChar) {
|
|
278
|
+
depth++;
|
|
279
|
+
}
|
|
280
|
+
else if (char === closeChar) {
|
|
281
|
+
depth--;
|
|
282
|
+
if (depth === 0)
|
|
283
|
+
return index;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return -1;
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=inject-hmr-vite-ignore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-hmr-vite-ignore.js","sourceRoot":"","sources":["../../../../../packages/vite/helpers/angular/inject-hmr-vite-ignore.ts"],"names":[],"mappings":"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"}
|
package/helpers/resolver.js
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import { resolveNativeScriptPlatformFile } from './utils.js';
|
|
3
|
+
const normalizeImporterId = (importer) => {
|
|
4
|
+
const cleanImporter = importer.split('?', 1)[0];
|
|
5
|
+
if (!cleanImporter.startsWith('/@fs/')) {
|
|
6
|
+
return cleanImporter;
|
|
7
|
+
}
|
|
8
|
+
return /^\/\@fs\/[A-Za-z]:/.test(cleanImporter) ? cleanImporter.slice('/@fs/'.length) : cleanImporter.slice('/@fs'.length);
|
|
9
|
+
};
|
|
3
10
|
export default function NativeScriptPlugin(options) {
|
|
4
11
|
return {
|
|
5
12
|
name: 'vite:nativescript',
|
|
13
|
+
enforce: 'pre',
|
|
6
14
|
resolveId(source, importer) {
|
|
7
15
|
const platform = options.platform;
|
|
8
16
|
if (!platform || !importer || source.startsWith('.') === false) {
|
|
9
17
|
return null;
|
|
10
18
|
}
|
|
11
|
-
const resolved = path.resolve(path.dirname(importer), source);
|
|
19
|
+
const resolved = path.resolve(path.dirname(normalizeImporterId(importer)), source);
|
|
12
20
|
const extVariants = ['.ts', '.js'];
|
|
13
21
|
for (const ext of extVariants) {
|
|
14
22
|
const file = resolveNativeScriptPlatformFile(resolved + ext, platform);
|
package/helpers/resolver.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../../packages/vite/helpers/resolver.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,+BAA+B,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,OAAqD;IAC/F,OAAO;QACN,IAAI,EAAE,mBAAmB;
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../../packages/vite/helpers/resolver.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,+BAA+B,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,mBAAmB,GAAG,CAAC,QAAgB,EAAU,EAAE;IACxD,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEhD,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxC,OAAO,aAAa,CAAC;IACtB,CAAC;IAED,OAAO,oBAAoB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC5H,CAAC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,OAAqD;IAC/F,OAAO;QACN,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,KAAK;QAEd,SAAS,CAAC,MAAM,EAAE,QAAQ;YACzB,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;YAClC,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC;gBAChE,OAAO,IAAI,CAAC;YACb,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YACnF,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAEnC,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;gBAC/B,MAAM,IAAI,GAAG,+BAA+B,CAAC,QAAQ,GAAG,GAAG,EAAE,QAAQ,CAAC,CAAC;gBACvE,IAAI,IAAI,EAAE,CAAC;oBACV,OAAO,IAAI,CAAC;gBACb,CAAC;YACF,CAAC;YAED,OAAO,IAAI,CAAC;QACb,CAAC;QAED,SAAS,CAAC,IAAI,EAAE,EAAE;YACjB,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzB,+EAA+E;gBAC/E,OAAO;oBACN,IAAI;oBACJ,GAAG,EAAE,IAAI;iBACT,CAAC;YACH,CAAC;QACF,CAAC;KACD,CAAC;AACH,CAAC"}
|
package/hmr/client/index.js
CHANGED
|
@@ -1717,6 +1717,104 @@ async function handleHmrMessage(ev) {
|
|
|
1717
1717
|
return;
|
|
1718
1718
|
}
|
|
1719
1719
|
else {
|
|
1720
|
+
// Vite custom-event dispatch.
|
|
1721
|
+
//
|
|
1722
|
+
// `server.ws.send('event-name', payload)` from any Vite plugin lands
|
|
1723
|
+
// on the wire as `{ type: 'custom', event: 'event-name', data: payload }`.
|
|
1724
|
+
// On the web, Vite's stock client owns a `customListenersMap` that
|
|
1725
|
+
// fires every `import.meta.hot.on('event-name', cb)` callback. We
|
|
1726
|
+
// don't run Vite's stock client on device — the iOS runtime owns
|
|
1727
|
+
// the listener registry via `__NS_DISPATCH_HOT_EVENT__` (the
|
|
1728
|
+
// counterpart to `import.meta.hot.on` populated by user code +
|
|
1729
|
+
// compiled Angular components). Forwarding `type: 'custom'` here
|
|
1730
|
+
// is the only thing standing between server-emitted events and
|
|
1731
|
+
// the listeners they were meant for.
|
|
1732
|
+
//
|
|
1733
|
+
// `angular:component-update` is the canonical example. Analog's
|
|
1734
|
+
// plugin sends it on `.html` / component-style edits; the
|
|
1735
|
+
// compiled component `.mjs` registered a listener that
|
|
1736
|
+
// dynamic-imports `/@ng/component?c=<id>&t=<ts>` and calls
|
|
1737
|
+
// `ɵɵreplaceMetadata` on the live class — swapping the template
|
|
1738
|
+
// definition AND walking live `LView`s to recreate matching views
|
|
1739
|
+
// in-place. The page stays mounted and only the changed bits
|
|
1740
|
+
// re-render. We MUST `return` after dispatch so the reboot path
|
|
1741
|
+
// (`handleAngularHotUpdateMessage` → `__reboot_ng_modules__`)
|
|
1742
|
+
// never runs for these updates — that's the whole point of the
|
|
1743
|
+
// component-replacement pipeline.
|
|
1744
|
+
//
|
|
1745
|
+
// All other custom events are forwarded but NOT short-circuited
|
|
1746
|
+
// (Vite spec: custom events are additive — they don't replace
|
|
1747
|
+
// any framework-specific handling). The reboot path falls through
|
|
1748
|
+
// for `ns:angular-update` (the legacy/`.ts`-edit broadcast) and
|
|
1749
|
+
// for any framework not yet using the in-place replacement path.
|
|
1750
|
+
if (msg.type === 'custom' && typeof msg.event === 'string') {
|
|
1751
|
+
// Dispatch every Vite "custom" event through the runtime's
|
|
1752
|
+
// `__NS_DISPATCH_HOT_EVENT__` bridge so `import.meta.hot.on(event, cb)`
|
|
1753
|
+
// callbacks fire on the device. Critical contract: this is the
|
|
1754
|
+
// ONLY route by which Analog's `angular:component-update` reaches
|
|
1755
|
+
// the compiled component's `(d) => d.id === id && Component_HmrLoad(...)`
|
|
1756
|
+
// listener — without it, server-side broadcasts log green
|
|
1757
|
+
// (`(client) hmr update`) while the device sees nothing happen.
|
|
1758
|
+
//
|
|
1759
|
+
// Diagnostic policy: log "no dispatcher" loud (boot-time rt-bridge
|
|
1760
|
+
// failure), and listener exceptions loud (compiled HmrLoad
|
|
1761
|
+
// fetch/parse error). Successful dispatches are silent — the
|
|
1762
|
+
// runtime's `[import.meta.hot] dispatch summary` line carries
|
|
1763
|
+
// the per-event match-count diagnostic.
|
|
1764
|
+
try {
|
|
1765
|
+
const dispatch = globalThis.__NS_DISPATCH_HOT_EVENT__;
|
|
1766
|
+
if (typeof dispatch === 'function') {
|
|
1767
|
+
dispatch(msg.event, msg.data);
|
|
1768
|
+
}
|
|
1769
|
+
else {
|
|
1770
|
+
console.warn(`[hmr-client][custom] no __NS_DISPATCH_HOT_EVENT__ available for '${msg.event}'`);
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
catch (err) {
|
|
1774
|
+
console.warn('[hmr-client][custom] dispatch threw for', msg.event, err);
|
|
1775
|
+
}
|
|
1776
|
+
if (msg.event === 'angular:component-update') {
|
|
1777
|
+
if (VERBOSE)
|
|
1778
|
+
console.log('[hmr-client][custom] dispatched angular:component-update — skipping reboot path');
|
|
1779
|
+
// Walk the apply-progress overlay through its
|
|
1780
|
+
// remaining stages for the in-place template-swap
|
|
1781
|
+
// path. The full reboot path
|
|
1782
|
+
// (`handleAngularHotUpdateMessage`) drives the
|
|
1783
|
+
// overlay itself ('received' → 'evicting' →
|
|
1784
|
+
// 'reimporting' → 'rebooting' → 'complete'); the
|
|
1785
|
+
// in-place path bypasses that handler entirely
|
|
1786
|
+
// because the work happens inside Angular's
|
|
1787
|
+
// `ɵɵreplaceMetadata` after the runtime forwards the
|
|
1788
|
+
// `angular:component-update` event to the compiled
|
|
1789
|
+
// component's listener. Without this update the
|
|
1790
|
+
// overlay would freeze at 5% ('received') even
|
|
1791
|
+
// though the visual swap completes a few frames
|
|
1792
|
+
// later — exactly the "Preparing update (5%)" stuck
|
|
1793
|
+
// frame we have been chasing.
|
|
1794
|
+
//
|
|
1795
|
+
// We transition straight to 'reimporting' to
|
|
1796
|
+
// communicate that metadata is being fetched (the
|
|
1797
|
+
// runtime listener fires `__ns_import('/@ng/component?c=...&t=...')`),
|
|
1798
|
+
// then schedule 'complete' on the next macrotask so
|
|
1799
|
+
// the auto-hide timer kicks in. The actual
|
|
1800
|
+
// template swap is fire-and-forget from this point;
|
|
1801
|
+
// the user sees the overlay close at the same time
|
|
1802
|
+
// as Angular re-renders the bound text/structure.
|
|
1803
|
+
try {
|
|
1804
|
+
const filePath = typeof msg.data?.id === 'string' ? decodeURIComponent(msg.data.id).split('@')[0] : undefined;
|
|
1805
|
+
const detail = filePath ? `Applying template update to ${filePath}` : 'Applying template update';
|
|
1806
|
+
setUpdateOverlayStage('reimporting', { detail });
|
|
1807
|
+
setTimeout(() => {
|
|
1808
|
+
try {
|
|
1809
|
+
setUpdateOverlayStage('complete', { detail: filePath ? `Updated ${filePath}` : 'Update applied' });
|
|
1810
|
+
}
|
|
1811
|
+
catch { }
|
|
1812
|
+
}, 16);
|
|
1813
|
+
}
|
|
1814
|
+
catch { }
|
|
1815
|
+
return;
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1720
1818
|
if (msg.type === 'ns:angular-update' && typeof msg.version === 'number') {
|
|
1721
1819
|
setGraphVersion(Number(msg.version || getGraphVersion() || 0));
|
|
1722
1820
|
}
|