Skip to content

Commit 8310eac

Browse files
committed
feat: HMR dev-sessions, ESM resolver hardening, dev-mode runtime globals
Adds the Hot Module Replacement runtime layer plus the supporting ESM resolver hardening and dev-session globals that make hot reload viable on iOS. * `import.meta.hot`: `data`, `accept`, `dispose`, `prune`, `decline`, `invalidate`, `on`/`off`/`send` event surface. * Dev-session globals (`__nsStartDevSession`, `__nsReloadDevApp`, `__nsInvalidateModules`, `__nsRunHmrDispose`, `__nsRunHmrPrune`, `__nsKickstartHmrPrefetch`, `__nsGetLoadedModuleUrls`, `__nsApplyStyleUpdate`, `__nsConfigureDevRuntime`, `__nsTerminateAllWorkers`). * Speculative HTTP module prefetch with canonical-key normalization so `__ns_hmr__/v<N>` and `__ns_boot__/b<N>` tag prefixes share `hot.data` identity across reload cycles. * ESM resolver hardening in `ModuleInternalCallbacks.mm` to: - Preserve synthetic-namespace identity (`ns-vendor://`, `optional:`, `node:`, `blob:`) — these are NOT filesystem paths. - Handle HTTP/HTTPS module URLs end-to-end (resolution, fetch, canonical-key collapse, dynamic import). - Compile `.json` imports into synthetic ES modules. * `NodeBuiltinsAndOptionalModulesTests.mjs`, `HttpEsmLoaderTests.js`, `hot-data-ext.{js,mjs}` test fixtures, plus integration wiring in `TestRunnerTests.swift` and the Jasmine boot harness.
1 parent ecd3598 commit 8310eac

21 files changed

Lines changed: 6455 additions & 918 deletions

NativeScript/runtime/DevFlags.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,20 @@ namespace tns {
1212
// Controlled by package.json setting: "logScriptLoading": true|false
1313
bool IsScriptLoadingLogEnabled();
1414

15+
// HTTP module loader flags
16+
//
17+
// Returns true when speculative HTTP module prefetching (the dep-graph BFS
18+
// kicked off after each successful HttpFetchText) should be enabled. Default
19+
// OFF so cold-boot behaviour is unchanged for users who have not opted in.
20+
// Controlled by package.json / nativescript.config: "httpModulePrefetch": true|false
21+
bool IsHttpModulePrefetchEnabled();
22+
23+
// Returns true when one log line should be emitted per HTTP fetch URL.
24+
// Default OFF because the volume is high (one line per fetch, hundreds per
25+
// cold boot, hundreds per HMR refresh). Opt in via package.json /
26+
// nativescript.config: "httpFetchUrlLog": true|false
27+
bool IsHttpFetchUrlLogEnabled();
28+
1529
// Security config
1630

1731
// In debug mode (RuntimeConfig.IsDebug): always returns true.

NativeScript/runtime/DevFlags.mm

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#import <Foundation/Foundation.h>
22

33
#include "DevFlags.h"
4+
#include "Helpers.h"
45
#include "Runtime.h"
56
#include "RuntimeConfig.h"
67
#include <vector>
@@ -13,6 +14,68 @@ bool IsScriptLoadingLogEnabled() {
1314
return value ? [value boolValue] : false;
1415
}
1516

17+
// HTTP module loader flags
18+
19+
// Reads `httpModulePrefetch` from app config (default: DISABLED).
20+
//
21+
// Apps that want to opt in for testing can set:
22+
//
23+
// // nativescript.config.ts
24+
// export default {
25+
// httpModulePrefetch: true,
26+
// } as NativeScriptConfig;
27+
//
28+
// Returning false here short-circuits both the cache lookup and the prefetch
29+
// wave in HttpFetchText, restoring the pre-prefetcher behavior bit-for-bit.
30+
bool IsHttpModulePrefetchEnabled() {
31+
static std::once_flag s_initFlag;
32+
static bool s_enabled = false;
33+
std::call_once(s_initFlag, []() {
34+
@autoreleasepool {
35+
id value = Runtime::GetAppConfigValue("httpModulePrefetch");
36+
if (value && [value respondsToSelector:@selector(boolValue)]) {
37+
s_enabled = [value boolValue];
38+
}
39+
}
40+
// Startup banner. Gated on the logScriptLoading flag so it stays silent
41+
// by default — flip the flag in nativescript.config.ts when diagnosing
42+
// why prefetch is or isn't engaging.
43+
//
44+
// [http-loader] prefetch=disabled ← expected default
45+
// [http-loader] prefetch=enabled ← only if config opt-in
46+
if (IsScriptLoadingLogEnabled()) {
47+
Log(@"[http-loader] prefetch=%s shared-session=on hmr-kickstart=on",
48+
s_enabled ? "enabled" : "disabled");
49+
}
50+
});
51+
return s_enabled;
52+
}
53+
54+
// Default OFF because the volume is high (one line per fetch, hundreds per
55+
// cold boot, hundreds per HMR refresh). Opt in via `nativescript.config.ts`:
56+
//
57+
// export default {
58+
// httpFetchUrlLog: true, // turn on for diagnosis only
59+
//
60+
// };
61+
bool IsHttpFetchUrlLogEnabled() {
62+
static std::once_flag s_initFlag;
63+
static bool s_enabled = false;
64+
std::call_once(s_initFlag, []() {
65+
@autoreleasepool {
66+
id value = Runtime::GetAppConfigValue("httpFetchUrlLog");
67+
if (value && [value respondsToSelector:@selector(boolValue)]) {
68+
s_enabled = [value boolValue];
69+
}
70+
}
71+
if (IsScriptLoadingLogEnabled()) {
72+
Log(@"[http-loader] fetch-url-log=%s",
73+
s_enabled ? "enabled" : "disabled");
74+
}
75+
});
76+
return s_enabled;
77+
}
78+
1679
// Security config
1780

1881
static std::once_flag s_securityConfigInitFlag;

NativeScript/runtime/HMRSupport.h

Lines changed: 312 additions & 9 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)