Filed here because BabylonJS/UrlLib has issues disabled; this issue is about the bundled UrlLib dependency. Move once that repo's issues are enabled, if desired.
Summary
UrlLib's UrlRequest reports local-file-not-found differently across platforms. Two platforms throw; two silently return success with a zero status code.
| Platform |
Source (in BabylonJS/UrlLib) |
Local file not found |
HTTP non-2xx |
| Win32 |
UrlRequest_Win32.cpp (via UrlRequest_Windows_Shared.h) |
success-task, m_statusCode = 0 |
success-task, real status code |
| UWP |
UrlRequest_UWP.cpp (via UrlRequest_Windows_Shared.h) |
success-task, m_statusCode = 0 |
success-task, real status code |
| Apple |
UrlRequest_Apple.mm |
throws ("No file exists at local path") |
success-task, real status code |
| Android |
UrlRequest_Android.cpp |
throws ("Failed to open asset") |
success-task, real status code |
| Unix |
UrlRequest_Unix.cpp |
(no local-file path; CURL handles) |
success-task, real status code |
HTTP non-2xx behavior is consistent (good — that's the W3C-compliant shape: transport succeeded, status code carries the outcome).
Local-file behavior is the bug — callers can't distinguish "file was loaded fine, server returned 0 bytes" from "file does not exist" on Windows family, without falling back to status-code heuristics.
Impact
#165 works around this in the XHR polyfill by treating any status < 200 || status >= 300 as a failure in the error event path. That's a defensible XHR-level decision (XHR has to check status code anyway for HTTP errors), but it papers over the platform inconsistency rather than fixing it. With this workaround in place, all callers via XMLHttpRequest see consistent behavior, but direct UrlLib callers still see the inconsistency.
Proposed fix
Two options, in decreasing order of preference:
-
Make Win32/UWP throw on local-file-not-found, matching Apple/Android. Callers can catch via arcana::expected::has_error(). This is the most internally consistent behavior and gives callers a clean way to distinguish transport failure from HTTP failure.
-
Alternatively, standardize on success-task + a synthetic status code (e.g., 404 for missing local file) across all platforms. Less invasive for existing callers, but conflates HTTP and transport semantics.
Either option requires updating Apple/Android in lockstep so all five paths agree.
Repro
const xhr = new XMLHttpRequest();
xhr.addEventListener("error", () => console.log("error fired"));
xhr.addEventListener("loadend", () => console.log("loadend; status=", xhr.status));
xhr.open("GET", "app:///Scripts/this_file_does_not_exist.js");
xhr.send();
Apple/Android (before #165): error fires.
Win32/UWP (before #165): only loadend fires; xhr.status is 0.
[Filed by Copilot on behalf of @bghgary]
Summary
UrlLib'sUrlRequestreports local-file-not-found differently across platforms. Two platforms throw; two silently return success with a zero status code.BabylonJS/UrlLib)UrlRequest_Win32.cpp(viaUrlRequest_Windows_Shared.h)m_statusCode = 0UrlRequest_UWP.cpp(viaUrlRequest_Windows_Shared.h)m_statusCode = 0UrlRequest_Apple.mm"No file exists at local path")UrlRequest_Android.cpp"Failed to open asset")UrlRequest_Unix.cppHTTP non-2xx behavior is consistent (good — that's the W3C-compliant shape: transport succeeded, status code carries the outcome).
Local-file behavior is the bug — callers can't distinguish "file was loaded fine, server returned 0 bytes" from "file does not exist" on Windows family, without falling back to status-code heuristics.
Impact
#165 works around this in the XHR polyfill by treating any
status < 200 || status >= 300as a failure in theerrorevent path. That's a defensible XHR-level decision (XHR has to check status code anyway for HTTP errors), but it papers over the platform inconsistency rather than fixing it. With this workaround in place, all callers viaXMLHttpRequestsee consistent behavior, but direct UrlLib callers still see the inconsistency.Proposed fix
Two options, in decreasing order of preference:
Make Win32/UWP throw on local-file-not-found, matching Apple/Android. Callers can catch via
arcana::expected::has_error(). This is the most internally consistent behavior and gives callers a clean way to distinguish transport failure from HTTP failure.Alternatively, standardize on success-task + a synthetic status code (e.g.,
404for missing local file) across all platforms. Less invasive for existing callers, but conflates HTTP and transport semantics.Either option requires updating Apple/Android in lockstep so all five paths agree.
Repro
Apple/Android (before #165):
errorfires.Win32/UWP (before #165): only
loadendfires;xhr.statusis0.[Filed by Copilot on behalf of @bghgary]