Skip to content

feat: ESM resolver hardening, http loader, dev-mode globals#1965

Draft
NathanWalker wants to merge 3 commits into
mainfrom
feat/hmr-dev-sessions
Draft

feat: ESM resolver hardening, http loader, dev-mode globals#1965
NathanWalker wants to merge 3 commits into
mainfrom
feat/hmr-dev-sessions

Conversation

@NathanWalker

@NathanWalker NathanWalker commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Framework-agnostic hot module replacement on Android with native ES modules: the device fetches modules over HTTP from the Vite dev server and applies hot updates without restarting the process.

The runtime's entire dev surface is one namespace object, globalThis.__NS_DEV__, carrying primitives, each traceable to a V8-embedder or OS constraint:

Member Why it must be native
configureRuntime(config) Import map / volatile URL patterns consumed inside V8's synchronous ResolveModuleCallback
invalidateModules(urls) Drops host-owned v8::Module records + prewarm cache + arms a CFNetwork cache-bust nonce
kickstartPrefetch(urls) Parallel HTTP prewarm of a server-computed closure, so V8's serial synchronous import walk doesn't trip the launch watchdog
getLoadedModuleUrls() Registry introspection for the JS full-reload path
setDevBootComplete(bool) Disarms cold-boot-only behaviors (runloop pump, kickstart wait)

Every HMR policy decision, boot orchestration, import.meta.hot, full reload, CSS apply, the WebSocket protocol is JS in @nativescript/vite. No native dev-session state machine, no reload orchestration, no hot-callback registries exist in the runtime, and on-device tests pin both the present members and the absent globals.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 50f1939e-94cc-445f-820f-32bac89692f9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@NathanWalker NathanWalker force-pushed the feat/hmr-dev-sessions branch 2 times, most recently from fb386eb to 708fecd Compare June 16, 2026 17:07
@NathanWalker NathanWalker changed the title feat: HMR dev-sessions, ESM resolver hardening, dev-mode runtime globals feat: ESM resolver hardening, http loader, dev-mode globals Jul 3, 2026
Adds the Hot Module Replacement runtime layer plus the supporting ESM
resolver hardening and dev-session globals that make hot reload viable on
Android.

* `import.meta.hot`: `data`, `accept`, `dispose`, `prune`, `decline`,
  `invalidate`, `on`/`off`/`send` event surface.
* Dev-session globals (`__nsStartDevSession`, `__nsReloadDevApp`,
  `__nsInvalidateModules`, `__nsRunHmrDispose`, `__nsRunHmrPrune`,
  `__nsHasDeclinedModule`, `__nsKickstartHmrPrefetch`,
  `__nsGetLoadedModuleUrls`, `__nsApplyStyleUpdate`,
  `__nsConfigureDevRuntime`/`__nsConfigureRuntime`,
  `__nsTerminateAllWorkers`).
* Speculative HTTP module prefetch (opt-in) 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.cpp` 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.
* Android runtime-dex support for `.extend()` classes created during HMR
  that the static binding generator can't see at build time: runtime DEX
  generation with `$`/`_` inner-class normalization (`DexFactory`),
  dev/HMR class-resolution fallback (`ClassResolver`), and dev-flag /
  `logScriptLoading` plumbing (`AppConfig`, `DevFlags`).
…ract

The runtime explicitly does not implement HMR policy. import.meta.hot, the
hot-data/accept/dispose/prune registries, and dev-session state move to the
JS HMR clients (eg, @nativescript/vite); native keeps only the sync HTTP
module fetch, prewarm cache + list-mode kickstart, eviction plumbing, and
the dev-boot-complete signal. Dev helpers are consolidated under __NS_DEV__.

Also fixes dynamic import() error propagation: with top-level-await enabled,
Module::Evaluate() returns a promise instead of an empty MaybeLocal on throw,
so the previous empty-check never fired and import() resolved a
half-evaluated namespace, silently swallowing module evaluation errors. The
callback now checks Module::GetStatus() for kErrored (HTTP, blob, and
generic paths) and rejects with the module's real exception, matching iOS.
Removes the httpModulePrefetch app-config flag and speculative prefetching;
list-mode kickstart remains.
@NathanWalker NathanWalker force-pushed the feat/hmr-dev-sessions branch from 08e7b8e to 696d4fc Compare July 3, 2026 23:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant