Candidate hrefs in try order (see wasmShimCandidateUrls).
Dynamic-import indirection. initWasm passes a
new Function-built importer so neither TypeScript nor Vite resolves the
specifier at build time.
The winning candidate's module namespace.
The single candidate's own error when only one URL was tried (so the
override and dev-server paths log exactly what they always did), otherwise
an AggregateError naming every URL in order — attributing a real failure
(shim served as text/plain, blocked by CSP, corrupt) to the LAST
candidate would point at a directory that exists in no layout.
Import the first URL that yields something shaped like the wasm-bindgen shim, trying the candidates in order.
Split out of initWasm and given an injectable importer because
initWasmcannot exercise a SUCCESSFUL walk under vitest: it reaches the shim through anew Function('url', 'return import(url)')indirection that vitest's VM module runner does not service, so every candidate it tries rejects and a regression back to "use candidate 0 only" would still end in the TypeScript fallback and pass every gate.Two rules, both load-bearing:
defaultto count as a hit. A host that answers the entry chunk's miss with a 200 carrying an empty body, or a JavaScript stub/redirect module standing in for the absent artifact, yields a namespace whosedefaultis missing or is not a function; ending the loop there would blow up onwasmModule.default()before the real candidate is ever tried — #1649's exact symptom, surviving on that host class. (An HTML error page is a different case and needs no help here: HTML does not parse as an ES module, so it REJECTS the import and thecatcharm above already moves on.) The check only reads a property, so nothing is instantiated and the "commit to the winner" rule below is untouched.default()and the staleness check against that module alone: re-running them elsewhere could instantiate the binary twice, and would hide a genuinely stale artifact behind the next candidate's 404.