feat: HMR dev-sessions, ESM resolver hardening, dev-mode runtime globals#383
feat: HMR dev-sessions, ESM resolver hardening, dev-mode runtime globals#383NathanWalker wants to merge 12 commits into
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
| globalTemplate->Set(urlPropertyName, URLTemplate); | ||
| } | ||
|
|
||
| void URLImpl::InstallBlobMethods(v8::Local<v8::Context> context) { |
There was a problem hiding this comment.
Blob can likely be split into separate PR. Not directly attributable to this pull request (at a time, I used blob urls with hmr updates but found standard http networking of es modules to suffice fine) - but useful on it's own.
8310eac to
2c5d877
Compare
6dfbacd to
f7cdfcc
Compare
|
I'm not sure I understand the goal of these "dev sessions"? What do these need specifically from the runtime that's not an "user land" thing? |
Yeah good question @edusperoni, the "dev session" naming here probably over (or mis) characterizes things. The "session" part is just the contract for booting from a dev server over HTTP instead of the on-disk bundle. It does three things a one-shot bundle loader doesnt: point resolution at an HTTP origin + install the import map before the first import, give a re-entrant boot (import client > import entry) that can re-run for a full reload without relaunching the process, and bubble import failures back as a rejected promise so the client can show an overlay instead of the app just dying. Could it be userland? I think the thing that trips people up (tripped me up too) is that on the web HMR is userland because the browser is the runtime; it already ships a spec ESM loader that fetches over HTTP and a host-owned module map you poke at by varying the URL. Vite's client gets to be "just JS" because it sits on top of that. Here V8 is embedded by us, and bare V8 ships no loader at all; every piece of it is an embedder host callback only native can install. So the litmus test is pretty clean: anything that has to install/drive a V8 host callback or mutate V8's module map cant be userland, everything else stays in JS. This may help expand a few things:
So really these globals arent "a dev-session feature" so much as the embedder half of a spec ESM loader + an identity-preserving module map. The part the browser hands Vite for free. The two that could move to JS if we want a smaller surface are __nsApplyStyleUpdate (just Application.addCss + restyle) and __nsGetLoadedModuleUrls (introspection). Lmk if you see the boundary differently. |
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.
[skip ci]
[skip ci]
…XCTest HTTP server [skip ci]
…opAndWait [skip ci]
In debug builds the module loader swallows compile/require errors (CompileScript returns an empty script; RunModule logs and returns success) so a bad HMR edit doesn't abort the main app. That also swallowed a *worker's* entry-script error, so `worker.onerror` never fired (e.g. a worker loaded from a syntactically invalid script hung the spec until the Jasmine async timeout). Gate the debug swallow on `!isWorker`: worker isolates now propagate the error (as release already does) and keep the V8 exception pending so the worker entry's TryCatch routes it to `worker.onerror`. Main-isolate HMR behavior is unchanged.
…harden test server Quarantine (harness-level specFilter, no submodule edit; see TestRunnerTests/QUARANTINED_TESTS.md): - "HMR hot.data" + "URL Key Canonicalization" (8 specs): the in-runner Embassy test server can't answer the runtime's synchronous NSURLConnection GET (getPeerName EINVAL / no response delivered). The HMR loader itself works; this is a test-harness limitation, documented for re-enable. Test-server robustness (kept; also pre-stages the un-quarantine): - DefaultHTTPServer.handleNewConnection: tolerate getPeerName() failure and serve with a placeholder peer instead of crashing (fixes the DefaultHTTPServer.swift:87 EXC_BREAKPOINT) or dropping the connection. - /esm/timeout.mjs: respond via non-blocking loop.call(withDelay:) instead of Thread.sleep, which wedged the single-threaded event loop. - Serve the /ns/m/... hot-data aliases and /ns/core bridge endpoints. [skip ci]
d24c897 to
4289539
Compare
Adds robust Hot Module Replacement 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/sendevent surface.__nsStartDevSession,__nsReloadDevApp,__nsInvalidateModules,__nsRunHmrDispose,__nsRunHmrPrune,__nsKickstartHmrPrefetch,__nsGetLoadedModuleUrls,__nsApplyStyleUpdate,__nsConfigureDevRuntime,__nsTerminateAllWorkers).__ns_hmr__/v<N>and__ns_boot__/b<N>tag prefixes sharehot.dataidentity across reload cycles.ModuleInternalCallbacks.mmto:.jsonimports into synthetic ES modules.