Skip to content

fix(node-loader): short-circuit http(s) resolves and handle empty parentURL - #78

Open
beldevem wants to merge 1 commit into
native-federation:mainfrom
beldevem:fix/node-loader-http-resolve-and-empty-parenturl
Open

fix(node-loader): short-circuit http(s) resolves and handle empty parentURL#78
beldevem wants to merge 1 commit into
native-federation:mainfrom
beldevem:fix/node-loader-http-resolve-and-empty-parenturl

Conversation

@beldevem

Copy link
Copy Markdown

Fixes #77

Problem

resolve() in src/scripts/node-loader.ts didn't short-circuit for absolute http(s) URLs the way load() already does, causing two real-world failures when a native-federation host loads a remote over http(s) in a Node SSR process (module.register()-based loader hooks):

  1. A relative specifier that is a sibling chunk of an already-loaded remote bundle (e.g. ./chunk-abc.js imported from https://remote-host/remote/entry.js) isn't in the import map, so resolve() fell through to nextResolve() which only understands file:/data:/node: specifiers and threw ERR_INVALID_URL.
  2. context.parentURL can arrive as an empty string (not undefined) under module.register()'s worker-thread hook execution. resolveSpecifier()'s parentURL ? ... : baseURL check treated the empty string as falsy and silently fell back to the local baseURL instead of the remote's base, breaking both relative sibling-chunk resolution and import-map scope matching for that remote.

Fix

  • resolve() now short-circuits for absolute http(s) URLs whether mapped via the import map, resolved as a relative sibling-chunk specifier, or already absolute mirroring the short-circuit load() already does.
  • load() now records the last remote base URL it fetched (lastRemoteBaseURL); resolve() falls back to it when context.parentURL is empty, so relative sibling-chunk imports and scope matching keep working even when the parent URL is lost.
  • load() now also returns responseURL for http(s) modules.

Tests

Added coverage in node-loader.spec.ts for the previously-untested scenarios: a mapped http(s) specifier short-circuiting instead of hitting nextResolve, a relative sibling-chunk specifier resolving via the URL algorithm, and the empty-parentURL fallback to the last loaded remote base. Updated the two existing load() tests to account for the new responseURL field. All 25 tests pass; node-loader.ts itself has zero TypeScript/lint errors.

Related: native-federation/angular-adapter#132 (filed against the wrong repo before the actual bug source was traced here).

…entURL

- resolve() now short-circuits for absolute http(s) URLs (mapped via the
  import map, a sibling-chunk relative specifier, or an already-absolute
  specifier), mirroring what load() already does. Without this, Node's
  nextResolve() falls through to package.json-scope resolution and throws
  ERR_INVALID_URL for any remote whose bundle has a chunk importing another
  chunk or a scoped shared dependency.
- context.parentURL can arrive as an empty string (not just missing) under
  module.register()'s worker-thread hook execution, which broke both
  relative sibling-chunk resolution and import-map scope matching (it
  silently fell back to the local cwd file:// base). load() now records the
  last remote base URL it fetched, and resolve() falls back to it when
  parentURL is empty.
- load() now also returns responseURL so relative imports from within a
  loaded remote module have a correct base even when parentURL propagates
  correctly.

Fixes native-federation#77
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.

[Bug]: (SSR) node-loader resolve() throws ERR_INVALID_URL for remote sibling chunks; parentURL can arrive empty

1 participant