Open evanw opened 3 years ago
I don't know how applicable it is here, but in Yarn we also happen to deal with filesystem path portability, and our solution to this problem is to always only work with Posix paths (ie even on Windows our path representation is /c:/foo/bar
), only translating them back into their native version (c:\foo\bar
) right when we have to pass them to the Node APIs.
Since the title now implies the problem is just with IsAbs
: The problem is with the path/filepath
package, not just with filepath.IsAbs
. For example, filepath.Dir
fails to split on backslashes and filepath.Join
inserts forward slashes instead of backward slashes.
When run sample code above on linux it prints false too! It's not just about WebAssembly. Python solved this problem with different module for unix and windows. That is posixpath and ntpath according to docs https://docs.python.org/3/library/os.path.html
It looks like this also affects other modules outside of path/filepath
too. The os.MkdirAll
and os.IsPathSeparator
functions also doesn't work on Windows when using WebAssembly.
WASI emulates an UNIX environment and thus uses UNIX path separators. WASI contains various things that make it very clear that it is a UNIX environment and not a Windows environment, like device and inode numbers which don't have a direct Windows counterpart AFAIK. It also doesn't have junctions, but hardlinks and symlinks. Further more it uses a single namespace file descriptors which are plain integers just like UNIX, while Windows uses HANDLE's which are pointers and a separate namespace for sockets.
Edit: I thought Go uses WASI. Looks like it has it's own wasm syscall interface instead. My bad.
Currently wasm target uses the IsAbs
from internal/filepathlite/path_unix.go
, which just compare the start of the path with /
.
Considering that wasm may run on different platforms, maybe calling the absolute path check in the js environment would be a good idea? Otherwise we would have to create a huge function that can determine the path format of all supported platforms.
We have https://nodejs.org/api/path.html#pathisabsolutepath in Node.js. For browser environments, perhaps allowing users to create flexible polyfills would be a more compatible idea.
Change https://go.dev/cl/604695 mentions this issue: fix: use host node.js function to parse path in wasm
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Here's a quick demonstration of the problem. Make a file called
main.go
that looks like this:Run this program natively on Windows:
Run this program via WebAssembly on Windows:
What did you expect to see?
I expected to see
IsAbs: true
in both cases.What did you see instead?
I see
IsAbs: true
when running a native executable on Windows but I seeIsAbs: false
when running via WebAssembly on Windows.I'm the developer behind esbuild, a JavaScript bundler written in Go. I publish native executables for all major operating system and architecture combinations, and I also separately publish a WebAssembly executable. The WebAssembly executable is intended to enable people to use esbuild in the browser and also in scenarios where they want to use esbuild outside of the browser in an os-independent context, which is the promise of WebAssembly.
Here is the context for this issue: https://github.com/evanw/esbuild/issues/687. The Yarn JavaScript package manager would like to use the WebAssembly version of esbuild instead of the native version. They try to avoid install scripts with platform-specific behavior since it messes with their preferred package installation strategy. Thus the same directory tree must be able to work on all platforms.
I have (perhaps incorrectly) assumed that Go's WebAssembly build target produces a cross-platform executable. This doesn't appear to be the case. It also doesn't appear to be something that can be fixed in a backwards-compatible manner, so I can understand if you either won't or can't fix it. It does seem like a bug to me because it violated my expectations of what the behavior should be, so I have reported it as a bug. But it's also possible that the WebAssembly build target only works in Unix-style environments by design and I was incorrect in assuming it would be cross-platform.
Regardless, I could use some advice for what to do here. Am I on my own for how to fix this? I imagine I could essentially fork the Go standard library and try to include both copies in the WebAssembly build. But I would prefer not to do that if possible.