@nativescript/vite 8.0.0-alpha.27 → 8.0.0-alpha.29
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.js +26 -128
- package/configuration/angular.js.map +1 -1
- package/configuration/base.js +2 -1
- package/configuration/base.js.map +1 -1
- package/configuration/javascript.js +5 -72
- package/configuration/javascript.js.map +1 -1
- package/configuration/typescript.js +4 -74
- package/configuration/typescript.js.map +1 -1
- package/helpers/angular/angular-linker.d.ts +5 -6
- package/helpers/angular/angular-linker.js +31 -110
- package/helpers/angular/angular-linker.js.map +1 -1
- package/helpers/angular/inject-component-hmr-registration.js +2 -70
- package/helpers/angular/inject-component-hmr-registration.js.map +1 -1
- package/helpers/angular/inject-hmr-vite-ignore.js +2 -69
- package/helpers/angular/inject-hmr-vite-ignore.js.map +1 -1
- package/helpers/angular/inline-decorator-component-templates.js +1 -170
- package/helpers/angular/inline-decorator-component-templates.js.map +1 -1
- package/helpers/angular/js-lexer.d.ts +4 -0
- package/helpers/angular/js-lexer.js +182 -0
- package/helpers/angular/js-lexer.js.map +1 -0
- package/helpers/angular/shared-linker.d.ts +31 -3
- package/helpers/angular/shared-linker.js +67 -14
- package/helpers/angular/shared-linker.js.map +1 -1
- package/helpers/angular/synthesize-decorator-ctor-parameters.js +2 -170
- package/helpers/angular/synthesize-decorator-ctor-parameters.js.map +1 -1
- package/helpers/angular/synthesize-injectable-factories.js +1 -174
- package/helpers/angular/synthesize-injectable-factories.js.map +1 -1
- package/helpers/app-components.d.ts +2 -1
- package/helpers/app-components.js.map +1 -1
- package/helpers/app-css-state.d.ts +8 -0
- package/helpers/app-css-state.js +8 -0
- package/helpers/app-css-state.js.map +1 -0
- package/helpers/bundler-context.d.ts +11 -0
- package/helpers/bundler-context.js +71 -0
- package/helpers/bundler-context.js.map +1 -0
- package/helpers/dev-host.d.ts +2 -1
- package/helpers/dev-host.js.map +1 -1
- package/helpers/hmr-scope.d.ts +26 -0
- package/helpers/hmr-scope.js +67 -0
- package/helpers/hmr-scope.js.map +1 -0
- package/helpers/main-entry.js +2 -3
- package/helpers/main-entry.js.map +1 -1
- package/helpers/nativeclass-esbuild-plugin.d.ts +2 -1
- package/helpers/nativeclass-esbuild-plugin.js.map +1 -1
- package/helpers/nativeclass-transform.js.map +1 -1
- package/helpers/platform-types.d.ts +2 -0
- package/helpers/platform-types.js +2 -0
- package/helpers/platform-types.js.map +1 -0
- package/helpers/prelink-angular.js +11 -29
- package/helpers/prelink-angular.js.map +1 -1
- package/helpers/ts-config-paths.d.ts +14 -0
- package/helpers/ts-config-paths.js +26 -0
- package/helpers/ts-config-paths.js.map +1 -1
- package/helpers/typescript-check.d.ts +2 -1
- package/helpers/typescript-check.js.map +1 -1
- package/helpers/workers.js +1 -1
- package/helpers/workers.js.map +1 -1
- package/hmr/client/css-handler.js +1 -17
- package/hmr/client/css-handler.js.map +1 -1
- package/hmr/client/utils.d.ts +1 -1
- package/hmr/client/utils.js +15 -59
- package/hmr/client/utils.js.map +1 -1
- package/hmr/frameworks/angular/server/strategy.js +3 -14
- package/hmr/frameworks/angular/server/strategy.js.map +1 -1
- package/hmr/frameworks/solid/server/strategy.js +3 -18
- package/hmr/frameworks/solid/server/strategy.js.map +1 -1
- package/hmr/frameworks/typescript/server/strategy.js +2 -15
- package/hmr/frameworks/typescript/server/strategy.js.map +1 -1
- package/hmr/frameworks/vue/client/index.js +0 -154
- package/hmr/frameworks/vue/client/index.js.map +1 -1
- package/hmr/server/core-sanitize.d.ts +3 -4
- package/hmr/server/core-sanitize.js +3 -4
- package/hmr/server/core-sanitize.js.map +1 -1
- package/hmr/server/framework-strategy.d.ts +9 -19
- package/hmr/server/vendor-bare-module-shims.d.ts +4 -0
- package/hmr/server/vendor-bare-module-shims.js +80 -0
- package/hmr/server/vendor-bare-module-shims.js.map +1 -0
- package/hmr/server/websocket-angular-entry.js +1 -1
- package/hmr/server/websocket-angular-entry.js.map +1 -1
- package/hmr/server/websocket-module-bindings.js +1 -1
- package/hmr/server/websocket-module-bindings.js.map +1 -1
- package/hmr/server/websocket-served-module-helpers.d.ts +4 -1
- package/hmr/server/websocket-served-module-helpers.js +19 -9
- package/hmr/server/websocket-served-module-helpers.js.map +1 -1
- package/hmr/server/websocket-vue-sfc.js +3 -3
- package/hmr/server/websocket-vue-sfc.js.map +1 -1
- package/hmr/server/websocket.d.ts +10 -33
- package/hmr/server/websocket.js +57 -754
- package/hmr/server/websocket.js.map +1 -1
- package/hmr/shared/runtime/dev-overlay-snapshots.d.ts +31 -0
- package/hmr/shared/runtime/dev-overlay-snapshots.js +324 -0
- package/hmr/shared/runtime/dev-overlay-snapshots.js.map +1 -0
- package/hmr/shared/runtime/dev-overlay.d.ts +3 -29
- package/hmr/shared/runtime/dev-overlay.js +3 -330
- package/hmr/shared/runtime/dev-overlay.js.map +1 -1
- package/hmr/shared/runtime/root-placeholder.js +9 -33
- package/hmr/shared/runtime/root-placeholder.js.map +1 -1
- package/hmr/shared/vendor/manifest.js +5 -82
- package/hmr/shared/vendor/manifest.js.map +1 -1
- package/package.json +53 -11
- package/hmr/server/websocket-ns-m-finalize.d.ts +0 -22
- package/hmr/server/websocket-ns-m-finalize.js +0 -88
- package/hmr/server/websocket-ns-m-finalize.js.map +0 -1
package/hmr/server/websocket.js
CHANGED
|
@@ -32,11 +32,15 @@ import { typescriptServerStrategy } from '../frameworks/typescript/server/strate
|
|
|
32
32
|
import { buildInlineTemplateBlock, createProcessSfcCode, extractTemplateRender, processTemplateVariantMinimal } from '../frameworks/vue/server/sfc-transforms.js';
|
|
33
33
|
import { astExtractImportsAndStripTypes } from '../helpers/ast-extract.js';
|
|
34
34
|
import { getProjectAppPath, getProjectAppRelativePath, getProjectAppVirtualPath } from '../../helpers/utils.js';
|
|
35
|
+
import { getAppCssState } from '../../helpers/app-css-state.js';
|
|
36
|
+
import { buildVueVendorShim, buildPiniaVendorShim } from './vendor-bare-module-shims.js';
|
|
35
37
|
import { buildRuntimeConfig, generateImportMap } from './import-map.js';
|
|
36
38
|
import { getCliFlags } from '../../helpers/cli-flags.js';
|
|
37
39
|
import { buildCoreUrl, buildCoreUrlPath, normalizeCoreSub as normalizeCoreSubCanonical } from '../../helpers/ns-core-url.js';
|
|
38
40
|
import { resolveDeviceReachableOrigin } from '../../helpers/dev-host.js';
|
|
39
41
|
import { isRuntimeGraphExcludedPath, matchesRuntimeGraphModuleId, normalizeRuntimeGraphPath, shouldIncludeRuntimeGraphFile, shouldSkipRuntimeGraphDirectoryName } from './runtime-graph-filter.js';
|
|
42
|
+
import { getHmrSourceRoots, isWithinHmrScope } from '../../helpers/hmr-scope.js';
|
|
43
|
+
import { getTsConfigData } from '../../helpers/ts-config-paths.js';
|
|
40
44
|
import { resolveAngularCoreHmrImportSource, rewriteAngularEntryRegisterOnly } from './websocket-angular-entry.js';
|
|
41
45
|
import { angularSourceHasSemanticDecorator, canonicalizeTransformRequestCacheKey, collectAngularEvictionUrls, collectAngularHotUpdateRoots, collectAngularTransformCacheInvalidationUrls, collectAngularTransitiveImportersForInvalidation, collectGraphUpdateModulesForHotUpdate, normalizeHotReloadMatchPath, shouldInvalidateAngularTransitiveImporters, shouldSuppressDefaultViteHotUpdate, shouldSuppressViteFullReloadPayload } from './websocket-angular-hot-update.js';
|
|
42
46
|
import { collectCssHotUpdatePaths } from './websocket-css-hot-update.js';
|
|
@@ -45,10 +49,11 @@ import { classifyBootRoute, classifyHmrUpdateKind, createColdBootRequestCounter,
|
|
|
45
49
|
import { createHmrPendingMessage } from './websocket-hmr-pending.js';
|
|
46
50
|
import { extractVitePrebundleId, filterExistingNodeModulesTransformCandidates, getBlockedDeviceNodeModulesReason, getFlattenedManifestMap, isCoreGlobalsReference, isEsmFrameworkPackageSpecifier, isLikelyNativeScriptPluginSpecifier, isLikelyNativeScriptRuntimePluginSpecifier, isNativeScriptCoreModule, isNativeScriptPluginModule, normalizeNativeScriptCoreSpecifier, normalizeNodeModulesSpecifier, resolveCandidateFilePath, resolveInternalRuntimePluginBareSpecifier, resolveNodeModulesPackageBoundary, resolveVendorFromCandidate, resolveVendorRouting, rewriteFsAbsoluteToNsM, shouldPreserveBareRuntimePluginSubpathImport, stripDecoratedServePrefixes, tryReadRawExplicitJavaScriptModule, viteDepsPathToBareSpecifier, } from './websocket-module-specifiers.js';
|
|
47
51
|
import { ensureNativeScriptModuleBindings, getProcessCodeResolvedSpecifierOverrides } from './websocket-module-bindings.js';
|
|
48
|
-
import { collectStaticExportNamesFromFile, collectStaticExportOriginsFromFile,
|
|
52
|
+
import { collectStaticExportNamesFromFile, collectStaticExportOriginsFromFile, normalizeCoreExportOriginsForRuntime, parseCoreBridgeRequest, resolveRuntimeCoreModulePath } from './websocket-core-bridge.js';
|
|
49
53
|
import { createSharedTransformRequestRunner } from './shared-transform-request.js';
|
|
50
54
|
import { formatNsMHmrServeTag, getNumericServeVersionTag, rewriteNsMImportPathForHmr } from './websocket-ns-m-paths.js';
|
|
51
|
-
import { ensureDynamicHmrImportHelper } from './websocket-served-module-helpers.js';
|
|
55
|
+
import { assertNoOptimizedArtifacts, buildBootProgressSnippet, collectTopLevelImportRecords, deduplicateLinkerImports, dedupeRtNamedImportsAgainstDestructures, ensureDestructureCoreImports, ensureDestructureRtImports, ensureDynamicHmrImportHelper, ensureGuardPlainDynamicImports, ensureVariableDynamicImportHelper, ensureVersionedRtImports, expandStarExports, extractExportMetadata, hoistTopLevelStaticImports, MODULE_IMPORT_ANALYSIS_PLUGINS, repairImportEqualsAssignments, stripCoreGlobalsImports, stripViteDynamicImportVirtual, wrapCommonJsModuleForDevice, } from './websocket-served-module-helpers.js';
|
|
56
|
+
export { buildBootProgressSnippet, wrapCommonJsModuleForDevice };
|
|
52
57
|
export { ensureNativeScriptModuleBindings, getProcessCodeResolvedSpecifierOverrides } from './websocket-module-bindings.js';
|
|
53
58
|
export { stripDecoratedServePrefixes, tryReadRawExplicitJavaScriptModule } from './websocket-module-specifiers.js';
|
|
54
59
|
export { collectStaticExportNamesFromFile, collectStaticExportOriginsFromFile, normalizeCoreExportOriginsForRuntime, parseCoreBridgeRequest } from './websocket-core-bridge.js';
|
|
@@ -81,6 +86,22 @@ catch { }
|
|
|
81
86
|
const __processEnvJson = JSON.stringify(__processEnvEntries);
|
|
82
87
|
const { parse, compileTemplate, compileScript } = vueSfcCompiler;
|
|
83
88
|
const APP_ROOT_DIR = getProjectAppPath();
|
|
89
|
+
// Absolute directories HMR is allowed to react to: the app source dir
|
|
90
|
+
// (`nativescript.config.ts` > `appPath`) plus tsconfig-configured shared
|
|
91
|
+
// libraries. Computed once per process (tsconfig data is itself memoized) and
|
|
92
|
+
// used to scope `handleHotUpdate` so non-source changes.
|
|
93
|
+
let _hmrSourceRoots = null;
|
|
94
|
+
function getHmrSourceRootsCached() {
|
|
95
|
+
if (_hmrSourceRoots)
|
|
96
|
+
return _hmrSourceRoots;
|
|
97
|
+
let tsConfig = {};
|
|
98
|
+
try {
|
|
99
|
+
tsConfig = getTsConfigData({ platform: '' });
|
|
100
|
+
}
|
|
101
|
+
catch { }
|
|
102
|
+
_hmrSourceRoots = getHmrSourceRoots(tsConfig);
|
|
103
|
+
return _hmrSourceRoots;
|
|
104
|
+
}
|
|
84
105
|
const APP_VIRTUAL_PREFIX = getProjectAppVirtualPath();
|
|
85
106
|
const APP_VIRTUAL_WITH_SLASH = `${APP_VIRTUAL_PREFIX}/`;
|
|
86
107
|
const DEFAULT_MAIN_ENTRY = getProjectAppRelativePath('app.ts');
|
|
@@ -148,9 +169,6 @@ function getHmrSocketRole(client) {
|
|
|
148
169
|
}
|
|
149
170
|
return typeof client.__nsHmrClientRole === 'string' && client.__nsHmrClientRole ? client.__nsHmrClientRole : 'unknown';
|
|
150
171
|
}
|
|
151
|
-
function shouldAllowLocalCoreSanitizerPaths(contextLabel) {
|
|
152
|
-
return /\bnode_modules\/@nativescript\/vite\/hmr\/(?:client|frameworks)\//.test(contextLabel);
|
|
153
|
-
}
|
|
154
172
|
export function prepareAngularEntryForDevice(code, importerPath, sfcFileMap, depFileMap, projectRoot, verbose = false, outputDirOverrideRel, httpOrigin, resolveVendorAsHttp = false) {
|
|
155
173
|
const rewrittenCode = rewriteImports(code, importerPath, sfcFileMap, depFileMap, projectRoot, verbose, outputDirOverrideRel, httpOrigin, resolveVendorAsHttp);
|
|
156
174
|
return rewriteAngularEntryRegisterOnly(rewrittenCode, resolveAngularCoreHmrImportSource(rewrittenCode, httpOrigin));
|
|
@@ -159,74 +177,6 @@ const processSfcCode = createProcessSfcCode(processCodeForDevice);
|
|
|
159
177
|
// Bare specifiers and special skip patterns (virtual, data:, etc.)
|
|
160
178
|
const VENDOR_PACKAGES = /^[A-Za-z@][^:\/\s]*$/;
|
|
161
179
|
const SKIP_PATTERNS = /^(?:data:|blob:|node:|virtual:|vite:|\0|\/@@?id|\/__vite|__vite|__x00__)/;
|
|
162
|
-
const MODULE_IMPORT_ANALYSIS_PLUGINS = ['typescript', 'jsx', 'importMeta', 'topLevelAwait', 'classProperties', 'classPrivateProperties', 'classPrivateMethods', 'decorators-legacy'];
|
|
163
|
-
function collectTopLevelImportRecords(code) {
|
|
164
|
-
if (!code || typeof code !== 'string' || !/\bimport\b/.test(code)) {
|
|
165
|
-
return [];
|
|
166
|
-
}
|
|
167
|
-
try {
|
|
168
|
-
const ast = babelParse(code, {
|
|
169
|
-
sourceType: 'module',
|
|
170
|
-
plugins: MODULE_IMPORT_ANALYSIS_PLUGINS,
|
|
171
|
-
});
|
|
172
|
-
const body = ast?.program?.body;
|
|
173
|
-
if (!Array.isArray(body)) {
|
|
174
|
-
return [];
|
|
175
|
-
}
|
|
176
|
-
return body
|
|
177
|
-
.filter((node) => t.isImportDeclaration(node) && typeof node.start === 'number' && typeof node.end === 'number' && typeof node.source?.value === 'string')
|
|
178
|
-
.map((node) => ({
|
|
179
|
-
start: node.start,
|
|
180
|
-
end: node.end,
|
|
181
|
-
text: code.slice(node.start, node.end),
|
|
182
|
-
source: node.source.value,
|
|
183
|
-
hasOnlyNamedSpecifiers: Array.isArray(node.specifiers) && node.specifiers.length > 0 && node.specifiers.every((spec) => t.isImportSpecifier(spec)),
|
|
184
|
-
namedBindings: Array.isArray(node.specifiers)
|
|
185
|
-
? node.specifiers
|
|
186
|
-
.filter((spec) => t.isImportSpecifier(spec) && typeof spec.start === 'number' && typeof spec.end === 'number')
|
|
187
|
-
.map((spec) => ({
|
|
188
|
-
importedName: t.isIdentifier(spec.imported) ? spec.imported.name : String(spec.imported?.value || ''),
|
|
189
|
-
text: code.slice(spec.start, spec.end),
|
|
190
|
-
}))
|
|
191
|
-
: [],
|
|
192
|
-
}));
|
|
193
|
-
}
|
|
194
|
-
catch {
|
|
195
|
-
return [];
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
function hoistTopLevelStaticImports(code) {
|
|
199
|
-
const imports = collectTopLevelImportRecords(code);
|
|
200
|
-
if (!imports.length) {
|
|
201
|
-
return code;
|
|
202
|
-
}
|
|
203
|
-
let stripped = code;
|
|
204
|
-
for (const imp of [...imports].sort((left, right) => right.start - left.start)) {
|
|
205
|
-
stripped = stripped.slice(0, imp.start) + stripped.slice(imp.end);
|
|
206
|
-
}
|
|
207
|
-
const hoisted = [];
|
|
208
|
-
const seen = new Set();
|
|
209
|
-
for (const imp of imports) {
|
|
210
|
-
const text = imp.text.trim();
|
|
211
|
-
if (!text || seen.has(text)) {
|
|
212
|
-
continue;
|
|
213
|
-
}
|
|
214
|
-
seen.add(text);
|
|
215
|
-
hoisted.push(text);
|
|
216
|
-
}
|
|
217
|
-
if (!hoisted.length) {
|
|
218
|
-
return stripped;
|
|
219
|
-
}
|
|
220
|
-
return `${hoisted.join('\n')}\n${stripped.replace(/^\s*\n+/, '')}`;
|
|
221
|
-
}
|
|
222
|
-
// Duplicate of `websocket-served-module-helpers.ts::buildBootProgressSnippet`
|
|
223
|
-
// — both copies must stay in lock-step. See the canonical doc there for
|
|
224
|
-
// why the snippet must remain fully synchronous (top-level await on a
|
|
225
|
-
// boot-tagged module trips the iOS 10 s async-module deadline).
|
|
226
|
-
export function buildBootProgressSnippet(bootModuleLabel) {
|
|
227
|
-
const normalizedLabel = JSON.stringify(String(bootModuleLabel || '').replace(/\\/g, '/'));
|
|
228
|
-
return [`const __nsBootGlobal=globalThis;`, `try{if(!__nsBootGlobal.__NS_HMR_BOOT_COMPLETE__){__nsBootGlobal.__NS_HMR_BOOT_MODULE_COUNT__=Number(__nsBootGlobal.__NS_HMR_BOOT_MODULE_COUNT__||0)+1;__nsBootGlobal.__NS_HMR_BOOT_LAST_MODULE__=${normalizedLabel};}}catch(__nsBootErr){}`, ''].join('\n');
|
|
229
|
-
}
|
|
230
180
|
function rewriteVitePrebundleImportsForDevice(code, preserveVendorImports) {
|
|
231
181
|
const imports = collectTopLevelImportRecords(code);
|
|
232
182
|
if (!imports.length) {
|
|
@@ -315,145 +265,6 @@ function guardBareDynamicImports(code) {
|
|
|
315
265
|
return code;
|
|
316
266
|
}
|
|
317
267
|
}
|
|
318
|
-
function stripCoreGlobalsImports(code) {
|
|
319
|
-
const pattern = /^\s*(?:import\s+(?:[^'"\n]*from\s+)?|export\s+\*\s+from\s+)["'][^"']*(?:@nativescript(?:[/_-])core(?:[\/_-])globals|@nativescript_core_globals)[^"']*["'];?\s*$/gm;
|
|
320
|
-
return code.replace(pattern, '');
|
|
321
|
-
}
|
|
322
|
-
function ensureVariableDynamicImportHelper(code) {
|
|
323
|
-
if (!code.includes('__variableDynamicImportRuntimeHelper')) {
|
|
324
|
-
return code;
|
|
325
|
-
}
|
|
326
|
-
if (PAT.VARIABLE_DYNAMIC_IMPORT_HELPER_PATTERN.test(code)) {
|
|
327
|
-
return code;
|
|
328
|
-
}
|
|
329
|
-
const helper = `const __variableDynamicImportRuntimeHelper = (map, request, importMode) => {\n` +
|
|
330
|
-
` try { if (request === '@') { return import(new URL('/ns/m/__invalid_at__.mjs', import.meta.url).href); } } catch {}\n` +
|
|
331
|
-
` const loader = map && (map[request] || map[request?.replace(/\\\\/g, "/")]);\n` +
|
|
332
|
-
` if (!loader) {\n` +
|
|
333
|
-
` const error = new Error(\"Cannot dynamically import: \" + request);\n` +
|
|
334
|
-
` error.code = 'ERR_MODULE_NOT_FOUND';\n` +
|
|
335
|
-
` return Promise.reject(error);\n` +
|
|
336
|
-
` }\n` +
|
|
337
|
-
` try {\n` +
|
|
338
|
-
` return loader(importMode);\n` +
|
|
339
|
-
` } catch (err) {\n` +
|
|
340
|
-
` return Promise.reject(err);\n` +
|
|
341
|
-
` }\n` +
|
|
342
|
-
`};\n`;
|
|
343
|
-
return `${helper}${code}`;
|
|
344
|
-
}
|
|
345
|
-
function ensureGuardPlainDynamicImports(code, origin) {
|
|
346
|
-
try {
|
|
347
|
-
if (!code || !/\bimport\s*\(/.test(code))
|
|
348
|
-
return code;
|
|
349
|
-
const wrapper = `const __ns_import = (s) => { try { if (s === '@') { return import(new URL('/ns/m/__invalid_at__.mjs', import.meta.url).href); } } catch {} return import(s); }\n`;
|
|
350
|
-
const replaced = code.replace(/(^|[^\.\w$])import\s*\(/g, (_m, p1) => `${p1}__ns_import(`);
|
|
351
|
-
if (replaced !== code) {
|
|
352
|
-
return wrapper + replaced;
|
|
353
|
-
}
|
|
354
|
-
return code;
|
|
355
|
-
}
|
|
356
|
-
catch {
|
|
357
|
-
return code;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
// `ensureDynamicHmrImportHelper` lives in
|
|
361
|
-
// `./websocket-served-module-helpers.js`. See that file for the
|
|
362
|
-
// architectural rationale and the current helper implementation.
|
|
363
|
-
async function expandStarExports(code, server, projectRoot, verbose, sharedTransformer) {
|
|
364
|
-
const STAR_RE = /^[ \t]*(export\s+\*\s+from\s+["'])([^"']+)(["'];?)[ \t]*$/gm;
|
|
365
|
-
let match;
|
|
366
|
-
const replacements = [];
|
|
367
|
-
while ((match = STAR_RE.exec(code)) !== null) {
|
|
368
|
-
const url = match[2];
|
|
369
|
-
if (!url.includes('/node_modules/'))
|
|
370
|
-
continue;
|
|
371
|
-
replacements.push({ full: match[0], url, prefix: match[1], suffix: match[3] });
|
|
372
|
-
}
|
|
373
|
-
if (!replacements.length)
|
|
374
|
-
return code;
|
|
375
|
-
// Pull target URLs through the shared runner when it's available so each
|
|
376
|
-
// node_modules path shares the 60s TTL cache with the main /ns/m pipeline
|
|
377
|
-
// and respects the global concurrency gate. Fan them out in parallel —
|
|
378
|
-
// this block used to be a serial `for await` loop, which dominated cold
|
|
379
|
-
// boot on apps with dozens of star-re-exports.
|
|
380
|
-
const transformer = sharedTransformer ?? ((url) => server.transformRequest(url));
|
|
381
|
-
const resolved = await Promise.all(replacements.map(async (rep) => {
|
|
382
|
-
try {
|
|
383
|
-
let vitePath = rep.url.replace(/^https?:\/\/[^/]+/, '');
|
|
384
|
-
vitePath = vitePath.replace(/^\/ns\/m\//, '/');
|
|
385
|
-
vitePath = vitePath.replace(/^\/__ns_boot__\/[^/]+/, '');
|
|
386
|
-
vitePath = vitePath.replace(/\/__ns_hmr__\/[^/]+/, '');
|
|
387
|
-
const result = await transformer(vitePath);
|
|
388
|
-
if (!result?.code)
|
|
389
|
-
return null;
|
|
390
|
-
const names = extractExportedNames(result.code);
|
|
391
|
-
if (!names.length)
|
|
392
|
-
return null;
|
|
393
|
-
if (verbose) {
|
|
394
|
-
console.log(`[ns/m] expanded export* -> ${names.length} names from ${vitePath}`);
|
|
395
|
-
}
|
|
396
|
-
return { rep, names };
|
|
397
|
-
}
|
|
398
|
-
catch {
|
|
399
|
-
return null;
|
|
400
|
-
}
|
|
401
|
-
}));
|
|
402
|
-
for (const entry of resolved) {
|
|
403
|
-
if (!entry)
|
|
404
|
-
continue;
|
|
405
|
-
const explicit = `export { ${entry.names.join(', ')} } from ${JSON.stringify(entry.rep.url)};`;
|
|
406
|
-
code = code.replace(entry.rep.full, explicit);
|
|
407
|
-
}
|
|
408
|
-
return code;
|
|
409
|
-
}
|
|
410
|
-
function extractExportedNames(code) {
|
|
411
|
-
return extractDirectExportedNames(code);
|
|
412
|
-
}
|
|
413
|
-
function repairImportEqualsAssignments(code) {
|
|
414
|
-
try {
|
|
415
|
-
if (!code || typeof code !== 'string')
|
|
416
|
-
return code;
|
|
417
|
-
code = code.replace(/(^|\n)\s*import\s*\{([^}]+)\}\s*=\s*([^;]+);?/g, (_m, p1, specList, rhs) => {
|
|
418
|
-
const cleaned = String(specList)
|
|
419
|
-
.split(',')
|
|
420
|
-
.map((s) => s.trim())
|
|
421
|
-
.filter(Boolean)
|
|
422
|
-
.map((seg) => seg.replace(/\s+as\s+/i, ': '))
|
|
423
|
-
.join(', ');
|
|
424
|
-
return `${p1}const { ${cleaned} } = ${rhs};`;
|
|
425
|
-
});
|
|
426
|
-
code = code.replace(/(^|\n)\s*import\s*\*\s*as\s*([A-Za-z_$][\w$]*)\s*=\s*([^;]+);?/g, (_m, p1, ns, rhs) => `${p1}const ${ns} = (${rhs});`);
|
|
427
|
-
code = code.replace(/(^|\n)\s*import\s+([A-Za-z_$][\w$]*)\s*=\s*([^;]+);?/g, (_m, p1, id, rhs) => `${p1}const ${id} = ${rhs};`);
|
|
428
|
-
}
|
|
429
|
-
catch { }
|
|
430
|
-
return code;
|
|
431
|
-
}
|
|
432
|
-
function ensureVersionedRtImports(code, origin, ver) {
|
|
433
|
-
if (!code || !origin || !Number.isFinite(ver))
|
|
434
|
-
return code;
|
|
435
|
-
code = code.replace(/(from\s+["'])(?:https?:\/\/[^"']+)?\/(?:\ns|ns)\/rt(?:\/[\d]+)?(["'])/g, (_m, p1, p3) => `${p1}/ns/rt/${ver}${p3}`);
|
|
436
|
-
code = code.replace(/(import\(\s*["'])(?:https?:\/\/[^"']+)?\/(?:\@ns|ns)\/rt(?:\/[\d]+)?(["']\s*\))/g, (_m, p1, p3) => `${p1}/ns/rt/${ver}${p3}`);
|
|
437
|
-
return code;
|
|
438
|
-
}
|
|
439
|
-
function stripViteDynamicImportVirtual(code) {
|
|
440
|
-
if (!/\/@id\/__x00__vite\/dynamic-import-helper/.test(code)) {
|
|
441
|
-
return code;
|
|
442
|
-
}
|
|
443
|
-
const original = code;
|
|
444
|
-
code = code.replace(/^[\t ]*import[^\n]*\/@id\/__x00__vite\/dynamic-import-helper[^\n]*$/gm, '');
|
|
445
|
-
if (/\/@id\/__x00__vite\/dynamic-import-helper/.test(code)) {
|
|
446
|
-
code = code.replace(/\/@id\/__x00__vite\/dynamic-import-helper[^"'`)]*/g, '/__NS_UNUSED_DYNAMIC_IMPORT_HELPER__');
|
|
447
|
-
}
|
|
448
|
-
if (!/__variableDynamicImportRuntimeHelper/.test(code)) {
|
|
449
|
-
const inline = `const __variableDynamicImportRuntimeHelper = (map, request, importMode) => {\n try { if (request === '@') { return import('/ns/m/__invalid_at__.mjs'); } } catch {}\n const loader = map && (map[request] || map[request?.replace(/\\\\/g, '/')]);\n if (!loader) { const e = new Error('Cannot dynamically import: ' + request); /*@ts-ignore*/ e.code = 'ERR_MODULE_NOT_FOUND'; return Promise.reject(e); }\n try { return loader(importMode); } catch (e) { return Promise.reject(e); }\n};\n`;
|
|
450
|
-
code = inline + code;
|
|
451
|
-
}
|
|
452
|
-
if (code !== original) {
|
|
453
|
-
code = `// [hmr-sanitize] removed virtual dynamic-import-helper\n${code}`;
|
|
454
|
-
}
|
|
455
|
-
return code;
|
|
456
|
-
}
|
|
457
268
|
// Detect (and log) `require('http(s)://...')` calls made from CJS shims.
|
|
458
269
|
// Pattern: HTTP-served ESM modules end up in NS-vite's `__nsRequire`
|
|
459
270
|
// shim with HTTP URLs as their relative resolution targets. The guard
|
|
@@ -539,43 +350,6 @@ function stripImportMetaHotBlocks(code) {
|
|
|
539
350
|
}
|
|
540
351
|
return result;
|
|
541
352
|
}
|
|
542
|
-
// Extract a quick set of export names and whether a default export exists from ESM code.
|
|
543
|
-
// This uses conservative regex scanning for metadata only (no code rewriting).
|
|
544
|
-
function extractExportMetadata(code) {
|
|
545
|
-
const named = new Set();
|
|
546
|
-
let hasDefault = /\bexport\s+default\b/.test(code);
|
|
547
|
-
try {
|
|
548
|
-
// export const foo, export let foo, export function bar, export class Baz
|
|
549
|
-
for (const m of code.matchAll(/\bexport\s+(?:const|let|var|function|class)\s+([A-Za-z_$][A-Za-z0-9_$]*)/g)) {
|
|
550
|
-
if (m[1])
|
|
551
|
-
named.add(m[1]);
|
|
552
|
-
}
|
|
553
|
-
// export { a, b as c }
|
|
554
|
-
for (const m of code.matchAll(/\bexport\s*\{([^}]+)\}/g)) {
|
|
555
|
-
const inner = (m[1] || '')
|
|
556
|
-
.split(',')
|
|
557
|
-
.map((s) => s.trim())
|
|
558
|
-
.filter(Boolean);
|
|
559
|
-
for (const seg of inner) {
|
|
560
|
-
// forms: name or name as alias or default as name
|
|
561
|
-
const dm = seg.match(/^([A-Za-z_$][A-Za-z0-9_$]*)(?:\s+as\s+([A-Za-z_$][A-Za-z0-9_$]*))?$/);
|
|
562
|
-
if (dm) {
|
|
563
|
-
const base = dm[1];
|
|
564
|
-
const alias = dm[2];
|
|
565
|
-
if (base === 'default') {
|
|
566
|
-
hasDefault = true;
|
|
567
|
-
continue;
|
|
568
|
-
}
|
|
569
|
-
named.add(alias || base);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
catch { }
|
|
575
|
-
// Remove default if accidentally included
|
|
576
|
-
named.delete('default');
|
|
577
|
-
return { hasDefault, named: Array.from(named) };
|
|
578
|
-
}
|
|
579
353
|
function normalizeImportPath(spec, importerDir) {
|
|
580
354
|
if (!spec)
|
|
581
355
|
return null;
|
|
@@ -775,8 +549,8 @@ function cleanCode(code) {
|
|
|
775
549
|
result = result.replace(PAT.VITE_CLIENT_IMPORT, '');
|
|
776
550
|
result = result.replace(PAT.IMPORT_META_HOT_ASSIGNMENT, '');
|
|
777
551
|
// Keep import.meta.hot call sites; runtime now provides a stable import.meta.hot.
|
|
778
|
-
result = ACTIVE_STRATEGY.preClean(result);
|
|
779
|
-
result = ACTIVE_STRATEGY.rewriteFrameworkImports(result);
|
|
552
|
+
result = ACTIVE_STRATEGY.preClean?.(result) ?? result;
|
|
553
|
+
result = ACTIVE_STRATEGY.rewriteFrameworkImports?.(result) ?? result;
|
|
780
554
|
// Vendor manifest-driven import rewrites
|
|
781
555
|
// NOTE: Static and side-effect vendor imports are intentionally NOT rewritten here.
|
|
782
556
|
// They are left as import statements so that ensureNativeScriptModuleBindings()
|
|
@@ -804,13 +578,11 @@ function cleanCode(code) {
|
|
|
804
578
|
}
|
|
805
579
|
result = result.replace(PAT.VITE_CLIENT_IMPORT, '').replace(PAT.IMPORT_META_HOT_ASSIGNMENT, '');
|
|
806
580
|
// Clean up HMR noise
|
|
807
|
-
result = ACTIVE_STRATEGY.postClean(result);
|
|
581
|
+
result = ACTIVE_STRATEGY.postClean?.(result) ?? result;
|
|
808
582
|
result = stripCoreGlobalsImports(result);
|
|
809
583
|
return result;
|
|
810
584
|
}
|
|
811
|
-
//
|
|
812
|
-
// APPLICATION IMPORT HELPERS
|
|
813
|
-
// ============================================================================
|
|
585
|
+
// Application import helpers
|
|
814
586
|
/**
|
|
815
587
|
* Check if a path is an application module (not node_modules, not vendor, not relative)
|
|
816
588
|
* This is generic and works for ANY project structure.
|
|
@@ -955,197 +727,6 @@ function normalizeAbsoluteFilesystemImport(spec, importerPath, projectRoot) {
|
|
|
955
727
|
}
|
|
956
728
|
return absolute;
|
|
957
729
|
}
|
|
958
|
-
/**
|
|
959
|
-
* After the Angular linker runs on code that Vite has already resolved (bare
|
|
960
|
-
* specifiers → full URLs), the linker injects NEW import statements with bare
|
|
961
|
-
* specifiers (e.g. `import {Component} from '@angular/core'`). These cause:
|
|
962
|
-
* 1. Duplicate-identifier SyntaxErrors (the name was already imported via URL)
|
|
963
|
-
* 2. Unresolvable bare specifiers at runtime on device
|
|
964
|
-
*
|
|
965
|
-
* This function:
|
|
966
|
-
* • builds a map packageName → resolvedURL from existing resolved imports
|
|
967
|
-
* • collects all binding names already imported per package
|
|
968
|
-
* • for each bare-specifier import, removes duplicate bindings
|
|
969
|
-
* • rewrites any genuinely-new bindings to use the resolved URL
|
|
970
|
-
*/
|
|
971
|
-
function deduplicateLinkerImports(code) {
|
|
972
|
-
if (!code)
|
|
973
|
-
return code;
|
|
974
|
-
try {
|
|
975
|
-
const imports = collectTopLevelImportRecords(code);
|
|
976
|
-
if (!imports.length) {
|
|
977
|
-
return code;
|
|
978
|
-
}
|
|
979
|
-
// ── Step 1: collect resolved imports already in the file ──────────
|
|
980
|
-
const pkgUrlMap = new Map();
|
|
981
|
-
const pkgBindings = new Map();
|
|
982
|
-
for (const imp of imports) {
|
|
983
|
-
const url = imp.source;
|
|
984
|
-
if (!/^https?:\/\//.test(url) && !url.startsWith('/')) {
|
|
985
|
-
continue;
|
|
986
|
-
}
|
|
987
|
-
const nmIdx = url.lastIndexOf('/node_modules/');
|
|
988
|
-
if (nmIdx === -1)
|
|
989
|
-
continue;
|
|
990
|
-
const afterNm = url.substring(nmIdx + '/node_modules/'.length);
|
|
991
|
-
const parts = afterNm.split('/');
|
|
992
|
-
const pkg = parts[0].startsWith('@') ? parts.slice(0, 2).join('/') : parts[0];
|
|
993
|
-
if (!pkgUrlMap.has(pkg))
|
|
994
|
-
pkgUrlMap.set(pkg, url);
|
|
995
|
-
if (imp.namedBindings.length) {
|
|
996
|
-
if (!pkgBindings.has(pkg))
|
|
997
|
-
pkgBindings.set(pkg, new Set());
|
|
998
|
-
for (const binding of imp.namedBindings) {
|
|
999
|
-
if (binding.importedName)
|
|
1000
|
-
pkgBindings.get(pkg).add(binding.importedName);
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
1004
|
-
if (pkgUrlMap.size === 0)
|
|
1005
|
-
return code;
|
|
1006
|
-
// ── Step 2: rewrite bare-specifier imports ───────────────────────
|
|
1007
|
-
const edits = [];
|
|
1008
|
-
for (const imp of imports) {
|
|
1009
|
-
if (!imp.hasOnlyNamedSpecifiers) {
|
|
1010
|
-
continue;
|
|
1011
|
-
}
|
|
1012
|
-
const specifier = imp.source;
|
|
1013
|
-
if (specifier.startsWith('/') || specifier.startsWith('.') || specifier.startsWith('http')) {
|
|
1014
|
-
continue;
|
|
1015
|
-
}
|
|
1016
|
-
const parts = specifier.split('/');
|
|
1017
|
-
const pkg = specifier.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0];
|
|
1018
|
-
const url = pkgUrlMap.get(pkg);
|
|
1019
|
-
if (!url) {
|
|
1020
|
-
continue;
|
|
1021
|
-
}
|
|
1022
|
-
const existing = pkgBindings.get(pkg) || new Set();
|
|
1023
|
-
const newBindings = imp.namedBindings.filter((binding) => !existing.has(binding.importedName));
|
|
1024
|
-
if (newBindings.length === 0) {
|
|
1025
|
-
edits.push({ start: imp.start, end: imp.end, text: '' });
|
|
1026
|
-
continue;
|
|
1027
|
-
}
|
|
1028
|
-
if (newBindings.length === imp.namedBindings.length) {
|
|
1029
|
-
continue;
|
|
1030
|
-
}
|
|
1031
|
-
for (const binding of newBindings) {
|
|
1032
|
-
existing.add(binding.importedName);
|
|
1033
|
-
}
|
|
1034
|
-
edits.push({
|
|
1035
|
-
start: imp.start,
|
|
1036
|
-
end: imp.end,
|
|
1037
|
-
text: `import { ${newBindings.map((binding) => binding.text).join(', ')} } from ${JSON.stringify(url)};`,
|
|
1038
|
-
});
|
|
1039
|
-
}
|
|
1040
|
-
if (!edits.length) {
|
|
1041
|
-
return code;
|
|
1042
|
-
}
|
|
1043
|
-
let next = code;
|
|
1044
|
-
for (const edit of edits.sort((left, right) => right.start - left.start)) {
|
|
1045
|
-
next = next.slice(0, edit.start) + edit.text + next.slice(edit.end);
|
|
1046
|
-
}
|
|
1047
|
-
return next;
|
|
1048
|
-
}
|
|
1049
|
-
catch {
|
|
1050
|
-
return code;
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
export function wrapCommonJsModuleForDevice(code, absolutePath) {
|
|
1054
|
-
if (!code)
|
|
1055
|
-
return code;
|
|
1056
|
-
try {
|
|
1057
|
-
const hasExportDefault = /\bexport\s+default\b/.test(code) || /export\s*\{\s*default\s*(?:as\s*default)?\s*\}/.test(code);
|
|
1058
|
-
const hasNamedExports = /\bexport\s+(?:const|let|var|function|class|async)\b/.test(code) || /\bexport\s*\{/.test(code);
|
|
1059
|
-
const hasCjsExports = /\bmodule\s*\.\s*exports\b/.test(code) || /\bexports\s*\.\s*\w/.test(code);
|
|
1060
|
-
if (hasExportDefault || hasNamedExports || !hasCjsExports) {
|
|
1061
|
-
return code;
|
|
1062
|
-
}
|
|
1063
|
-
const namedExports = new Set();
|
|
1064
|
-
const exportsRe = /\bexports\s*\.\s*([A-Za-z_$][\w$]*)\s*=/g;
|
|
1065
|
-
let em;
|
|
1066
|
-
while ((em = exportsRe.exec(code)) !== null) {
|
|
1067
|
-
const name = em[1];
|
|
1068
|
-
if (name !== '__esModule' && name !== 'default') {
|
|
1069
|
-
namedExports.add(name);
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
|
-
const defPropRe = /Object\s*\.\s*defineProperty\s*\(\s*exports\s*,\s*['"]([^'"]+)['"]/g;
|
|
1073
|
-
while ((em = defPropRe.exec(code)) !== null) {
|
|
1074
|
-
const name = em[1];
|
|
1075
|
-
if (name !== '__esModule' && name !== 'default') {
|
|
1076
|
-
namedExports.add(name);
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
// Static enumeration only sees `exports.foo = ...` and `Object.defineProperty(exports, 'foo', ...)`.
|
|
1080
|
-
// Real-world packages like lodash attach their entire surface to a function inside an IIFE and
|
|
1081
|
-
// then `module.exports = thatFunction`. Static analysis returns zero in that case. To handle
|
|
1082
|
-
// these modules we ALSO load the package in the dev-server's Node context (only when we have a
|
|
1083
|
-
// node_modules path) and merge the runtime keys. See `helpers/cjs-named-exports.ts` for the
|
|
1084
|
-
// reasoning and safety boundaries.
|
|
1085
|
-
if (absolutePath) {
|
|
1086
|
-
try {
|
|
1087
|
-
for (const n of getCjsNamedExports(absolutePath)) {
|
|
1088
|
-
namedExports.add(n);
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
catch {
|
|
1092
|
-
/* fall through to whatever we caught statically */
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
let suffix = `\nvar __cjs_mod = module.exports;\nexport default __cjs_mod;\n`;
|
|
1096
|
-
if (namedExports.size) {
|
|
1097
|
-
const entries = Array.from(namedExports);
|
|
1098
|
-
const temps = entries.map((name, i) => `var __cjs_e${i} = __cjs_mod[${JSON.stringify(name)}];`);
|
|
1099
|
-
const reExports = entries.map((name, i) => `__cjs_e${i} as ${name}`);
|
|
1100
|
-
suffix += `${temps.join(' ')}\nexport { ${reExports.join(', ')} };\n`;
|
|
1101
|
-
}
|
|
1102
|
-
const prelude = `var module = { exports: {} }; var exports = module.exports;\n` +
|
|
1103
|
-
`var __ns_cjs_require_base = (typeof globalThis.__nsBaseRequire === 'function' ? globalThis.__nsBaseRequire : (typeof globalThis.__nsRequire === 'function' ? globalThis.__nsRequire : (typeof globalThis.require === 'function' ? globalThis.require : undefined)));\n` +
|
|
1104
|
-
`var __ns_cjs_require_kind = (typeof globalThis.__nsBaseRequire === 'function' ? 'base-require' : (typeof globalThis.__nsRequire === 'function' ? 'vendor-require' : 'global-require'));\n` +
|
|
1105
|
-
`var require = function(spec) {\n` +
|
|
1106
|
-
` if (!__ns_cjs_require_base) { throw new Error('require is not defined'); }\n` +
|
|
1107
|
-
// Resolve relative specifiers against the HTTP-served module's URL
|
|
1108
|
-
// before delegating to NS's runtime require. Without this step,
|
|
1109
|
-
// \`require('./base64-vlq')\` inside a CJS module served from
|
|
1110
|
-
// \`http://.../ns/m/node_modules/source-map-js/lib/source-map-generator.js\`
|
|
1111
|
-
// would pass a literal '"./base64-vlq"' to the native require, which
|
|
1112
|
-
// has no notion of the current HTTP-module's location and either
|
|
1113
|
-
// throws "Module not found" or fetches an arbitrary filesystem path
|
|
1114
|
-
// that happens to parse as code (producing misleading syntax errors
|
|
1115
|
-
// like "missing ) after argument list" from unrelated modules).
|
|
1116
|
-
` var __nsResolvedSpec = spec;\n` +
|
|
1117
|
-
` try {\n` +
|
|
1118
|
-
` if (typeof spec === 'string' && (spec.indexOf('./') === 0 || spec.indexOf('../') === 0)) {\n` +
|
|
1119
|
-
` var __nsParentUrl = (typeof import.meta !== 'undefined' && import.meta && typeof import.meta.url === 'string') ? import.meta.url : null;\n` +
|
|
1120
|
-
` if (__nsParentUrl) {\n` +
|
|
1121
|
-
` var __nsResolvedUrl = new URL(spec, __nsParentUrl);\n` +
|
|
1122
|
-
` // Common Node-style bare extensions: prefer .js if the resolved URL lacks an extension in its last path segment.\n` +
|
|
1123
|
-
` if (!/\\.[A-Za-z0-9]+$/.test(__nsResolvedUrl.pathname.split('/').pop() || '')) {\n` +
|
|
1124
|
-
` __nsResolvedUrl.pathname = __nsResolvedUrl.pathname.replace(/\\/+$/, '') + '.js';\n` +
|
|
1125
|
-
` }\n` +
|
|
1126
|
-
` __nsResolvedSpec = __nsResolvedUrl.href;\n` +
|
|
1127
|
-
` }\n` +
|
|
1128
|
-
` }\n` +
|
|
1129
|
-
` } catch (e) {}\n` +
|
|
1130
|
-
` try { var __nsRecord = globalThis.__NS_RECORD_MODULE_PROVENANCE__; if (typeof __nsRecord === 'function') { __nsRecord(String(__nsResolvedSpec), { kind: __ns_cjs_require_kind, specifier: String(spec), url: __nsResolvedSpec !== spec ? __nsResolvedSpec : undefined, via: 'cjs-wrapper', parent: (typeof import.meta !== 'undefined' && import.meta && import.meta.url) ? import.meta.url : undefined }); } } catch (e) {}\n` +
|
|
1131
|
-
` var mod = __ns_cjs_require_base(__nsResolvedSpec);\n` +
|
|
1132
|
-
` try {\n` +
|
|
1133
|
-
` if (mod && (typeof mod === 'object' || typeof mod === 'function') && mod.default !== undefined) {\n` +
|
|
1134
|
-
` var keys = [];\n` +
|
|
1135
|
-
` try { keys = Object.keys(mod); } catch (e) {}\n` +
|
|
1136
|
-
` var defaultOnly = keys.length === 1 && keys[0] === 'default';\n` +
|
|
1137
|
-
` var esModuleOnly = keys.length === 2 && keys.indexOf('default') !== -1 && keys.indexOf('__esModule') !== -1;\n` +
|
|
1138
|
-
` if (mod.__esModule || defaultOnly || esModuleOnly) { return mod.default; }\n` +
|
|
1139
|
-
` }\n` +
|
|
1140
|
-
` } catch (e) {}\n` +
|
|
1141
|
-
` return mod;\n` +
|
|
1142
|
-
`};\n`;
|
|
1143
|
-
return `${prelude}${code}${suffix}`;
|
|
1144
|
-
}
|
|
1145
|
-
catch {
|
|
1146
|
-
return code;
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
730
|
/**
|
|
1150
731
|
* Process code for device: inject globals, remove framework imports
|
|
1151
732
|
*/
|
|
@@ -1678,198 +1259,6 @@ function processCodeForDevice(code, isVitePreBundled, preserveVendorImports = fa
|
|
|
1678
1259
|
// Assert that sanitized code no longer contains any Vite optimized deps artifacts
|
|
1679
1260
|
// or virtual ids that could break the HTTP ESM loader on device. Throws with
|
|
1680
1261
|
// a helpful diagnostics message if any are found.
|
|
1681
|
-
function assertNoOptimizedArtifacts(code, contextLabel) {
|
|
1682
|
-
try {
|
|
1683
|
-
const offenders = [];
|
|
1684
|
-
const lines = code.split('\n');
|
|
1685
|
-
const tests = [
|
|
1686
|
-
// Allow Vite dev indirections like /@id/ and /.vite/deps when served via HTTP.
|
|
1687
|
-
// Only flag clearly invalid virtual placeholders if they surface in output.
|
|
1688
|
-
/\b__VITE_PLUGIN__\b/,
|
|
1689
|
-
/\b__VITE_PRELOAD__\b/,
|
|
1690
|
-
];
|
|
1691
|
-
// Absolute or relative local @nativescript/core usage indicates a split realm risk; fail fast
|
|
1692
|
-
const localCore = /(^|[^\w@])(?:\.\.?\/|\/)??@nativescript[\/_-]core\//i;
|
|
1693
|
-
for (let i = 0; i < lines.length; i++) {
|
|
1694
|
-
const ln = lines[i];
|
|
1695
|
-
for (const re of tests) {
|
|
1696
|
-
if (re.test(ln)) {
|
|
1697
|
-
offenders.push(`${i + 1}: ${ln.substring(0, 200)}`);
|
|
1698
|
-
break;
|
|
1699
|
-
}
|
|
1700
|
-
}
|
|
1701
|
-
if (localCore.test(ln)) {
|
|
1702
|
-
// Comments can never cause split-realm risk at runtime — skip them.
|
|
1703
|
-
// Library authors commonly reference @nativescript/core in comments
|
|
1704
|
-
// (e.g. TSDoc /// <reference> directives, module resolution notes).
|
|
1705
|
-
const trimmed = ln.trimStart();
|
|
1706
|
-
if (trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('*')) {
|
|
1707
|
-
continue;
|
|
1708
|
-
}
|
|
1709
|
-
if (shouldAllowLocalCoreSanitizerPaths(contextLabel)) {
|
|
1710
|
-
continue;
|
|
1711
|
-
}
|
|
1712
|
-
offenders.push(`${i + 1}: ${ln.substring(0, 200)} [local-core-path]`);
|
|
1713
|
-
}
|
|
1714
|
-
if (offenders.length >= 10)
|
|
1715
|
-
break;
|
|
1716
|
-
}
|
|
1717
|
-
if (offenders.length) {
|
|
1718
|
-
const msg = `[sanitize-fail] Optimized deps/virtual id artifacts detected in ${contextLabel}. These cannot be evaluated by the device HTTP ESM loader. Offending lines (first ${Math.min(5, offenders.length)} shown):\n` + offenders.slice(0, 5).join('\n');
|
|
1719
|
-
const err = new Error(msg);
|
|
1720
|
-
// Attach details for server logs / higher-level handlers
|
|
1721
|
-
err.code = 'NS_SANITIZE_FAIL';
|
|
1722
|
-
err.offenders = offenders;
|
|
1723
|
-
throw err;
|
|
1724
|
-
}
|
|
1725
|
-
}
|
|
1726
|
-
catch (e) {
|
|
1727
|
-
// If diagnostics generation itself fails, do not mask the underlying issue
|
|
1728
|
-
throw e;
|
|
1729
|
-
}
|
|
1730
|
-
}
|
|
1731
|
-
// Ensure there are no lingering named imports from the unified core bridge.
|
|
1732
|
-
// Converts named imports from `/ns/core[/<sub>]` into default import +
|
|
1733
|
-
// destructuring. The package-main bridge serves a shape-shifted module whose
|
|
1734
|
-
// named exports come from `__ns_core_bridge.default` rather than ESM named
|
|
1735
|
-
// exports, so a named-import binding would be `undefined` at evaluation.
|
|
1736
|
-
function ensureDestructureCoreImports(code) {
|
|
1737
|
-
try {
|
|
1738
|
-
let result = code;
|
|
1739
|
-
let coreImportCounter = 0;
|
|
1740
|
-
const toDestructure = (specList) => specList
|
|
1741
|
-
.split(',')
|
|
1742
|
-
.map((s) => s.trim())
|
|
1743
|
-
.filter(Boolean)
|
|
1744
|
-
.map((seg) => {
|
|
1745
|
-
const m = seg.split(/\s+as\s+/i);
|
|
1746
|
-
return m.length === 2 ? `${m[0].trim()}: ${m[1].trim()}` : seg;
|
|
1747
|
-
})
|
|
1748
|
-
.join(', ');
|
|
1749
|
-
// import { A, B } from '/ns/core[/<sub>]'
|
|
1750
|
-
const reNamed = /(^|\n)\s*import\s*\{([^}]+)\}\s*from\s*["']((?:https?:\/\/[^"']+)?\/ns\/core(?:\/[^"']+)?)['"];?\s*/gm;
|
|
1751
|
-
result = result.replace(reNamed, (_full, pfx, specList, src) => {
|
|
1752
|
-
// Deep subpath URLs serve actual ESM with real named exports — skip.
|
|
1753
|
-
if (isDeepCoreSubpath(src))
|
|
1754
|
-
return _full;
|
|
1755
|
-
const tmp = `__ns_core_ns_re${coreImportCounter > 0 ? `_${coreImportCounter}` : ''}`;
|
|
1756
|
-
coreImportCounter++;
|
|
1757
|
-
const decl = `const { ${toDestructure(specList)} } = ${tmp};`;
|
|
1758
|
-
return `${pfx}import ${tmp} from ${JSON.stringify(src)};\n${decl}\n`;
|
|
1759
|
-
});
|
|
1760
|
-
// import Default, { A, B } from '/ns/core[/<sub>]'
|
|
1761
|
-
const reMixed = /(^|\n)\s*import\s+([A-Za-z_$][\w$]*)\s*,\s*\{([^}]+)\}\s*from\s*["']((?:https?:\/\/[^"']+)?\/ns\/core(?:\/[^"']+)?)['"];?\s*/gm;
|
|
1762
|
-
result = result.replace(reMixed, (_full, pfx, defName, specList, src) => {
|
|
1763
|
-
if (isDeepCoreSubpath(src))
|
|
1764
|
-
return _full;
|
|
1765
|
-
const decl = `const { ${toDestructure(specList)} } = ${defName};`;
|
|
1766
|
-
return `${pfx}import ${defName} from ${JSON.stringify(src)};\n${decl}\n`;
|
|
1767
|
-
});
|
|
1768
|
-
return result;
|
|
1769
|
-
}
|
|
1770
|
-
catch {
|
|
1771
|
-
return code;
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
// Converts any named imports from the runtime bridge (/ns/rt[/ver]) into a default import + destructuring.
|
|
1775
|
-
// This guarantees helper aliases like _resolveComponent remain bound even if we later normalize imports.
|
|
1776
|
-
function ensureDestructureRtImports(code) {
|
|
1777
|
-
try {
|
|
1778
|
-
let result = code;
|
|
1779
|
-
const toDestructure = (specList) => specList
|
|
1780
|
-
.split(',')
|
|
1781
|
-
.map((s) => s.trim())
|
|
1782
|
-
.filter(Boolean)
|
|
1783
|
-
.map((seg) => {
|
|
1784
|
-
// Preserve alias mapping (e.g., resolveComponent as _resolveComponent)
|
|
1785
|
-
const m = seg.split(/\s+as\s+/i);
|
|
1786
|
-
return m.length === 2 ? `${m[0].trim()}: ${m[1].trim()}` : seg;
|
|
1787
|
-
})
|
|
1788
|
-
.join(', ');
|
|
1789
|
-
const reNamed = /(^|\n)\s*import\s*\{([^}]+)\}\s*from\s*["']((?:https?:\/\/[^"']+)?\/ns\/rt(?:\/[\d]+)?)['"];?\s*/gm;
|
|
1790
|
-
result = result.replace(reNamed, (_full, pfx, specList, src) => {
|
|
1791
|
-
const tmp = `__ns_rt_ns_re`;
|
|
1792
|
-
const decl = `const { ${toDestructure(specList)} } = ${tmp};`;
|
|
1793
|
-
return `${pfx}import ${tmp} from ${JSON.stringify(src)};\n${decl}\n`;
|
|
1794
|
-
});
|
|
1795
|
-
const reMixed = /(^|\n)\s*import\s+([A-Za-z_$][\w$]*)\s*,\s*\{([^}]+)\}\s*from\s*["']((?:https?:\/\/[^"']+)?\/ns\/rt(?:\/[\d]+)?)['"];?\s*/gm;
|
|
1796
|
-
result = result.replace(reMixed, (_full, pfx, defName, specList, _src) => {
|
|
1797
|
-
const decl = `const { ${toDestructure(specList)} } = ${defName};`;
|
|
1798
|
-
return `${pfx}import ${defName} from ${JSON.stringify(_src)};\n${decl}\n`;
|
|
1799
|
-
});
|
|
1800
|
-
return result;
|
|
1801
|
-
}
|
|
1802
|
-
catch {
|
|
1803
|
-
return code;
|
|
1804
|
-
}
|
|
1805
|
-
}
|
|
1806
|
-
// Remove overlapping named imports from /ns/rt that duplicate bindings already provided
|
|
1807
|
-
// by destructuring a default /ns/rt import (e.g., const { $showModal } = __ns_rt_ns_1;).
|
|
1808
|
-
function dedupeRtNamedImportsAgainstDestructures(code) {
|
|
1809
|
-
try {
|
|
1810
|
-
let result = code;
|
|
1811
|
-
// Collect bindings created from any destructure of __ns_rt_ns* temps
|
|
1812
|
-
const rtDestructureRE = /(^|\n)\s*const\s*\{([^}]+)\}\s*=\s*(__ns_rt_ns(?:\d+|_re))\s*;?/gm;
|
|
1813
|
-
const rtBound = new Set();
|
|
1814
|
-
let m;
|
|
1815
|
-
while ((m = rtDestructureRE.exec(result)) !== null) {
|
|
1816
|
-
const specList = String(m[2] || '');
|
|
1817
|
-
specList
|
|
1818
|
-
.split(',')
|
|
1819
|
-
.map((s) => s.trim())
|
|
1820
|
-
.filter(Boolean)
|
|
1821
|
-
.forEach((seg) => {
|
|
1822
|
-
const bind = seg.includes(':') ? seg.split(':')[1].trim() : seg;
|
|
1823
|
-
if (bind)
|
|
1824
|
-
rtBound.add(bind);
|
|
1825
|
-
});
|
|
1826
|
-
}
|
|
1827
|
-
if (!rtBound.size)
|
|
1828
|
-
return result;
|
|
1829
|
-
// For any named import from /ns/rt (versioned or not), drop specifiers that are already bound
|
|
1830
|
-
const rtNamedImportRE = /(^|\n)\s*import\s*\{([^}]+)\}\s*from\s*["']((?:https?:\/\/[^"']+)?\/ns\/rt(?:\/[\d]+)?)["'];?\s*/gm;
|
|
1831
|
-
const edits = [];
|
|
1832
|
-
while ((m = rtNamedImportRE.exec(result)) !== null) {
|
|
1833
|
-
const full = m[0];
|
|
1834
|
-
const pfx = m[1] || '';
|
|
1835
|
-
const specList = String(m[2] || '');
|
|
1836
|
-
const src = m[3];
|
|
1837
|
-
const kept = [];
|
|
1838
|
-
specList
|
|
1839
|
-
.split(',')
|
|
1840
|
-
.map((s) => s.trim())
|
|
1841
|
-
.filter(Boolean)
|
|
1842
|
-
.forEach((seg) => {
|
|
1843
|
-
const importedName = seg.split(/\s+as\s+/i)[0].trim();
|
|
1844
|
-
if (!rtBound.has(importedName))
|
|
1845
|
-
kept.push(seg);
|
|
1846
|
-
});
|
|
1847
|
-
let replacement = '';
|
|
1848
|
-
if (kept.length) {
|
|
1849
|
-
replacement = `${pfx}import { ${kept.join(', ')} } from ${JSON.stringify(src)};`;
|
|
1850
|
-
}
|
|
1851
|
-
else {
|
|
1852
|
-
replacement = pfx || '';
|
|
1853
|
-
}
|
|
1854
|
-
edits.push({
|
|
1855
|
-
start: rtNamedImportRE.lastIndex - full.length,
|
|
1856
|
-
end: rtNamedImportRE.lastIndex,
|
|
1857
|
-
text: replacement,
|
|
1858
|
-
});
|
|
1859
|
-
}
|
|
1860
|
-
if (edits.length) {
|
|
1861
|
-
edits
|
|
1862
|
-
.sort((a, b) => b.start - a.start)
|
|
1863
|
-
.forEach((e) => {
|
|
1864
|
-
result = result.slice(0, e.start) + e.text + result.slice(e.end);
|
|
1865
|
-
});
|
|
1866
|
-
}
|
|
1867
|
-
return result;
|
|
1868
|
-
}
|
|
1869
|
-
catch {
|
|
1870
|
-
return code;
|
|
1871
|
-
}
|
|
1872
|
-
}
|
|
1873
1262
|
/**
|
|
1874
1263
|
* THE SINGLE REWRITE FUNCTION - used everywhere for consistency
|
|
1875
1264
|
*/
|
|
@@ -2458,9 +1847,7 @@ export function rewriteImports(code, importerPath, sfcFileMap, depFileMap, proje
|
|
|
2458
1847
|
});
|
|
2459
1848
|
return result;
|
|
2460
1849
|
}
|
|
2461
|
-
//
|
|
2462
|
-
// PLUGIN
|
|
2463
|
-
// ============================================================================
|
|
1850
|
+
// Plugin
|
|
2464
1851
|
function createHmrWebSocketPlugin(opts) {
|
|
2465
1852
|
const verbose = !!opts.verbose;
|
|
2466
1853
|
let wss = null;
|
|
@@ -3217,7 +2604,7 @@ function createHmrWebSocketPlugin(opts) {
|
|
|
3217
2604
|
try {
|
|
3218
2605
|
const origin = getServerOrigin(server);
|
|
3219
2606
|
code = ensureVersionedRtImports(code, origin, graphVersion);
|
|
3220
|
-
code = ACTIVE_STRATEGY.ensureVersionedImports(code, origin, graphVersion);
|
|
2607
|
+
code = ACTIVE_STRATEGY.ensureVersionedImports?.(code, origin, graphVersion) ?? code;
|
|
3221
2608
|
}
|
|
3222
2609
|
catch { }
|
|
3223
2610
|
// Compute rel .mjs output path
|
|
@@ -3273,7 +2660,7 @@ function createHmrWebSocketPlugin(opts) {
|
|
|
3273
2660
|
}
|
|
3274
2661
|
try {
|
|
3275
2662
|
depCode = ensureVersionedRtImports(depCode, getServerOrigin(server), graphVersion);
|
|
3276
|
-
depCode = ACTIVE_STRATEGY.ensureVersionedImports(depCode, getServerOrigin(server), graphVersion);
|
|
2663
|
+
depCode = ACTIVE_STRATEGY.ensureVersionedImports?.(depCode, getServerOrigin(server), graphVersion) ?? depCode;
|
|
3277
2664
|
}
|
|
3278
2665
|
catch { }
|
|
3279
2666
|
let depRel = depResolved.replace(/^\//, '').replace(/\.(tsx?|jsx?)$/i, '.mjs');
|
|
@@ -3770,79 +3157,10 @@ function createHmrWebSocketPlugin(opts) {
|
|
|
3770
3157
|
const pkg = bare;
|
|
3771
3158
|
let code = '';
|
|
3772
3159
|
if (pkg === 'vue' || pkg === 'nativescript-vue') {
|
|
3773
|
-
|
|
3774
|
-
code = `
|
|
3775
|
-
const g = globalThis;
|
|
3776
|
-
const reg = g.__nsVendorRegistry;
|
|
3777
|
-
const req = reg && g.__nsVendorRequire ? g.__nsVendorRequire : (g.__nsRequire || g.require);
|
|
3778
|
-
let mod = reg && reg.get('${pkg === 'vue' ? 'nativescript-vue' : 'nativescript-vue'}');
|
|
3779
|
-
if (!mod && req) {
|
|
3780
|
-
try { mod = req('${pkg === 'vue' ? 'nativescript-vue' : 'nativescript-vue'}'); } catch {}
|
|
3781
|
-
${pkg === 'vue' ? "if (!mod) { try { mod = req('vue'); } catch {} }" : ''}
|
|
3782
|
-
}
|
|
3783
|
-
mod = mod || {};
|
|
3784
|
-
const v = (mod.default ?? mod);
|
|
3785
|
-
export default v;
|
|
3786
|
-
export const defineComponent = v.defineComponent;
|
|
3787
|
-
export const resolveComponent = v.resolveComponent;
|
|
3788
|
-
export const createVNode = v.createVNode;
|
|
3789
|
-
export const createTextVNode = v.createTextVNode;
|
|
3790
|
-
export const createCommentVNode = v.createCommentVNode;
|
|
3791
|
-
export const Fragment = v.Fragment;
|
|
3792
|
-
export const withCtx = v.withCtx;
|
|
3793
|
-
export const openBlock = v.openBlock;
|
|
3794
|
-
export const createBlock = v.createBlock;
|
|
3795
|
-
export const createElementVNode = v.createElementVNode || v.createVNode;
|
|
3796
|
-
export const createElementBlock = v.createElementBlock || v.createBlock;
|
|
3797
|
-
export const renderSlot = v.renderSlot;
|
|
3798
|
-
export const mergeProps = v.mergeProps;
|
|
3799
|
-
export const toHandlers = v.toHandlers;
|
|
3800
|
-
export const renderList = v.renderList;
|
|
3801
|
-
export const normalizeProps = v.normalizeProps;
|
|
3802
|
-
export const guardReactiveProps = v.guardReactiveProps;
|
|
3803
|
-
export const withDirectives = v.withDirectives;
|
|
3804
|
-
export const resolveDirective = v.resolveDirective;
|
|
3805
|
-
export const withModifiers = v.withModifiers;
|
|
3806
|
-
export const withKeys = v.withKeys;
|
|
3807
|
-
export const ref = v.ref;
|
|
3808
|
-
export const shallowRef = v.shallowRef;
|
|
3809
|
-
export const unref = v.unref;
|
|
3810
|
-
export const computed = v.computed;
|
|
3811
|
-
export const onMounted = v.onMounted;
|
|
3812
|
-
export const onBeforeUnmount = v.onBeforeUnmount;
|
|
3813
|
-
export const onUnmounted = v.onUnmounted;
|
|
3814
|
-
export const watch = v.watch;
|
|
3815
|
-
export const nextTick = v.nextTick;
|
|
3816
|
-
export const createApp = v.createApp || (vm && vm.createApp);
|
|
3817
|
-
export const registerElement = v.registerElement || (vm && vm.registerElement);
|
|
3818
|
-
export const normalizeClass = v.normalizeClass;
|
|
3819
|
-
export const normalizeStyle = v.normalizeStyle;
|
|
3820
|
-
export const toDisplayString = v.toDisplayString;
|
|
3821
|
-
`;
|
|
3160
|
+
code = buildVueVendorShim(pkg);
|
|
3822
3161
|
}
|
|
3823
3162
|
else if (pkg === 'pinia') {
|
|
3824
|
-
|
|
3825
|
-
code = `
|
|
3826
|
-
const g = globalThis;
|
|
3827
|
-
const reg = g.__nsVendorRegistry;
|
|
3828
|
-
const req = reg && g.__nsVendorRequire ? g.__nsVendorRequire : (g.__nsRequire || g.require);
|
|
3829
|
-
let mod = reg && reg.get('pinia');
|
|
3830
|
-
if (!mod && req) { try { mod = req('pinia'); } catch {} }
|
|
3831
|
-
mod = mod || {};
|
|
3832
|
-
const p = (mod.default ?? mod);
|
|
3833
|
-
export default p;
|
|
3834
|
-
export const createPinia = p.createPinia;
|
|
3835
|
-
export const defineStore = p.defineStore;
|
|
3836
|
-
export const storeToRefs = p.storeToRefs;
|
|
3837
|
-
export const setActivePinia = p.setActivePinia;
|
|
3838
|
-
export const getActivePinia = p.getActivePinia;
|
|
3839
|
-
export const mapStores = p.mapStores;
|
|
3840
|
-
export const mapState = p.mapState;
|
|
3841
|
-
export const mapGetters = p.mapGetters;
|
|
3842
|
-
export const mapActions = p.mapActions;
|
|
3843
|
-
export const mapWritableState = p.mapWritableState;
|
|
3844
|
-
export const piniaSymbol = p.piniaSymbol;
|
|
3845
|
-
`;
|
|
3163
|
+
code = buildPiniaVendorShim();
|
|
3846
3164
|
}
|
|
3847
3165
|
res.statusCode = 200;
|
|
3848
3166
|
res.end(code || 'export {}\n');
|
|
@@ -4000,7 +3318,7 @@ export const piniaSymbol = p.piniaSymbol;
|
|
|
4000
3318
|
try {
|
|
4001
3319
|
const verNum = 0;
|
|
4002
3320
|
code = ensureVersionedRtImports(code, getServerOrigin(server), verNum);
|
|
4003
|
-
code = ACTIVE_STRATEGY.ensureVersionedImports(code, getServerOrigin(server), verNum);
|
|
3321
|
+
code = ACTIVE_STRATEGY.ensureVersionedImports?.(code, getServerOrigin(server), verNum) ?? code;
|
|
4004
3322
|
}
|
|
4005
3323
|
catch { }
|
|
4006
3324
|
// `/ns/m` URL finalize step.
|
|
@@ -5116,11 +4434,11 @@ export const piniaSymbol = p.piniaSymbol;
|
|
|
5116
4434
|
const verNum = Number(verFromPath || '0');
|
|
5117
4435
|
if (Number.isFinite(verNum) && verNum > 0) {
|
|
5118
4436
|
code = ensureVersionedRtImports(code, getServerOrigin(server), verNum);
|
|
5119
|
-
code = ACTIVE_STRATEGY.ensureVersionedImports(code, getServerOrigin(server), verNum);
|
|
4437
|
+
code = ACTIVE_STRATEGY.ensureVersionedImports?.(code, getServerOrigin(server), verNum) ?? code;
|
|
5120
4438
|
}
|
|
5121
4439
|
else {
|
|
5122
4440
|
code = ensureVersionedRtImports(code, getServerOrigin(server), graphVersion);
|
|
5123
|
-
code = ACTIVE_STRATEGY.ensureVersionedImports(code, getServerOrigin(server), graphVersion);
|
|
4441
|
+
code = ACTIVE_STRATEGY.ensureVersionedImports?.(code, getServerOrigin(server), graphVersion) ?? code;
|
|
5124
4442
|
}
|
|
5125
4443
|
}
|
|
5126
4444
|
catch { }
|
|
@@ -5827,7 +5145,7 @@ export const piniaSymbol = p.piniaSymbol;
|
|
|
5827
5145
|
try {
|
|
5828
5146
|
const origin = getServerOrigin(server);
|
|
5829
5147
|
inlineCode2 = ensureVersionedRtImports(inlineCode2, origin, Number(ver));
|
|
5830
|
-
inlineCode2 = ACTIVE_STRATEGY.ensureVersionedImports(inlineCode2, origin, Number(ver));
|
|
5148
|
+
inlineCode2 = ACTIVE_STRATEGY.ensureVersionedImports?.(inlineCode2, origin, Number(ver)) ?? inlineCode2;
|
|
5831
5149
|
}
|
|
5832
5150
|
catch { }
|
|
5833
5151
|
// Normalize imports/helpers via AST to ensure _defineComponent and other helpers are bound once
|
|
@@ -5941,7 +5259,7 @@ export const piniaSymbol = p.piniaSymbol;
|
|
|
5941
5259
|
try {
|
|
5942
5260
|
const origin = getServerOrigin(server);
|
|
5943
5261
|
code = ensureVersionedRtImports(code, origin, Number(ver));
|
|
5944
|
-
code = ACTIVE_STRATEGY.ensureVersionedImports(code, origin, Number(ver));
|
|
5262
|
+
code = ACTIVE_STRATEGY.ensureVersionedImports?.(code, origin, Number(ver)) ?? code;
|
|
5945
5263
|
}
|
|
5946
5264
|
catch { }
|
|
5947
5265
|
// Inline-template body path already runs processCodeForDevice (AST + sanitizers); no additional _defineComponent fix needed
|
|
@@ -6270,6 +5588,15 @@ export const piniaSymbol = p.piniaSymbol;
|
|
|
6270
5588
|
if (isRuntimeGraphExcludedPath(file)) {
|
|
6271
5589
|
return;
|
|
6272
5590
|
}
|
|
5591
|
+
// Authoritative "what triggers HMR" gate, applied before the pending
|
|
5592
|
+
// overlay broadcast below: react only to files inside the app source
|
|
5593
|
+
// dir (`appPath`) or a tsconfig-configured shared library.
|
|
5594
|
+
if (!isWithinHmrScope(file, getHmrSourceRootsCached())) {
|
|
5595
|
+
if (verbose) {
|
|
5596
|
+
console.log(`[ns-hmr][server] ignored change (outside HMR source scope): ${file}`);
|
|
5597
|
+
}
|
|
5598
|
+
return;
|
|
5599
|
+
}
|
|
6273
5600
|
// Always-on update timing. Captures the four phases (await,
|
|
6274
5601
|
// framework, broadcast, total) plus invalidated module count
|
|
6275
5602
|
// and recipient count. Emitted at the end of this function via
|
|
@@ -6512,8 +5839,9 @@ export const piniaSymbol = p.piniaSymbol;
|
|
|
6512
5839
|
// the framework's own template-update payload.
|
|
6513
5840
|
if (!file.endsWith('.css')) {
|
|
6514
5841
|
try {
|
|
6515
|
-
const
|
|
6516
|
-
const
|
|
5842
|
+
const appCssState = getAppCssState(server);
|
|
5843
|
+
const deps = appCssState?.deps;
|
|
5844
|
+
const appCssPath = appCssState?.path;
|
|
6517
5845
|
if (deps && appCssPath) {
|
|
6518
5846
|
const normalizedFile = path.resolve(file).replace(/\\/g, '/');
|
|
6519
5847
|
if (deps.has(normalizedFile)) {
|
|
@@ -7469,9 +6797,7 @@ if (typeof __VUE_HMR_RUNTIME__ === 'undefined') {
|
|
|
7469
6797
|
},
|
|
7470
6798
|
};
|
|
7471
6799
|
}
|
|
7472
|
-
// ----------
|
|
7473
6800
|
// Framework-specific HMR WebSocket plugins
|
|
7474
|
-
// ----------
|
|
7475
6801
|
export function hmrWebSocketVue(opts) {
|
|
7476
6802
|
ACTIVE_STRATEGY = resolveFrameworkStrategy('vue');
|
|
7477
6803
|
return createHmrWebSocketPlugin(opts);
|
|
@@ -7489,37 +6815,14 @@ export function hmrWebSocketTypescript(opts) {
|
|
|
7489
6815
|
return createHmrWebSocketPlugin(opts);
|
|
7490
6816
|
}
|
|
7491
6817
|
/**
|
|
7492
|
-
*
|
|
7493
|
-
*
|
|
7494
|
-
*
|
|
7495
|
-
*
|
|
7496
|
-
*
|
|
7497
|
-
*
|
|
7498
|
-
* `
|
|
7499
|
-
*
|
|
7500
|
-
* realms of `@nativescript/core` — a classic singleton-state split.
|
|
7501
|
-
* `internal/debug-sessions/LATEST-05-12-2026-HMR_CORE_REALM_SPLIT.md`
|
|
7502
|
-
* documents the symptom.
|
|
7503
|
-
*
|
|
7504
|
-
* Routing all platforms through `resolveDeviceReachableOrigin` keeps
|
|
7505
|
-
* them in lock-step:
|
|
7506
|
-
*
|
|
7507
|
-
* - Android wildcard / loopback → `10.0.2.2` (emulator NAT can't
|
|
7508
|
-
* reach the host's LAN IP; physical devices opt in via
|
|
7509
|
-
* `NS_HMR_PREFER_LAN_HOST=1`).
|
|
7510
|
-
*
|
|
7511
|
-
* - iOS / visionOS wildcard → `localhost` (simulator shares the
|
|
7512
|
-
* host's network stack; physical devices opt in via the same
|
|
7513
|
-
* `NS_HMR_PREFER_LAN_HOST=1` or `NS_HMR_HOST=<lan-ip>` env).
|
|
7514
|
-
*
|
|
7515
|
-
* - Explicit non-loopback `server.host` (e.g. a developer-set LAN
|
|
7516
|
-
* IP) on any platform → trusted verbatim.
|
|
7517
|
-
*
|
|
7518
|
-
* The old `resolvedUrls.network[0]` preference is intentionally
|
|
7519
|
-
* dropped — Vite reports a LAN IP whenever it detects one, but that
|
|
7520
|
-
* IP is neither reachable from an Android emulator nor consistent
|
|
7521
|
-
* with what `dev-host.ts` selects, so leaning on it created the
|
|
7522
|
-
* realm-split risk above.
|
|
6818
|
+
* Dev-server origin baked into every module served to the device
|
|
6819
|
+
* (`/ns/core/...`, `/ns/m/...`). MUST match the origin `dev-host.ts` bakes
|
|
6820
|
+
* into `bundle.mjs`; if they disagree V8 keys them as different modules and
|
|
6821
|
+
* the app ends up with two `@nativescript/core` realms (a singleton-state
|
|
6822
|
+
* split). `resolveDeviceReachableOrigin` keeps every platform in lock-step:
|
|
6823
|
+
* Android wildcard/loopback -> `10.0.2.2`, iOS/visionOS wildcard ->
|
|
6824
|
+
* `localhost`, explicit non-loopback `server.host` -> trusted verbatim
|
|
6825
|
+
* (physical devices opt into LAN via `NS_HMR_PREFER_LAN_HOST`/`NS_HMR_HOST`).
|
|
7523
6826
|
*/
|
|
7524
6827
|
function getServerOrigin(server) {
|
|
7525
6828
|
const platform = detectDevHostPlatform();
|