Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

question: should syscall/js be importable on other non-wasm platforms? #31158

Closed
bradleypeabody opened this issue Mar 30, 2019 · 5 comments
Closed
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@bradleypeabody
Copy link

What version of Go are you using (go version)?

$ go version
go version go1.12.1 darwin/amd64

Does this issue reproduce with the latest release?

Yes

What did you do?

Trying to write code that compiles in WebAssembly and in other architectures that imports syscall/js is not possible (package only exists in wasm).

While I certainly understand the reason the package isn't there on other platforms, while writing Vugu (github.com/vugu/vugu) I've encountered an issue which is that that of writing UI components that run in wasm, but also are executable on the server to render a page server-side. Of course the code in question is not executed on the server-side, but the component may be written with various references to types and funcs in js.

Obviously it is possible to use build constraints to make a program that optionally includes the right code for different platforms, but this is not necessarily trivial or a good developer experience (at least in this case, in my opinion).

Is there a specific reason that on Linux for example I shouldn't be able to import syscall/js and have the same types, but everything otherwise fails or returns zero values?

I realize it's a bit of a strange request, but there is at least some smaller scale precedent in things like os.Getegid() - it returns -1 on Windows rather than the function just not being present.

It wouldn't be difficult to do or maintain, but I don't know if there is already some rule or philosophy as to why this approach isn't good.

What do you think? Should I be able to declare a variable of type js.Value in my code on another platform and have it compile? (Even if it will always be a zero value)

@bradleypeabody bradleypeabody changed the title syscall/js Can syscall/js be imported on other non-wasm platforms? Mar 30, 2019
@andybons andybons changed the title Can syscall/js be imported on other non-wasm platforms? question: can syscall/js be imported on other non-wasm platforms? Apr 4, 2019
@andybons andybons added this to the Unreleased milestone Apr 4, 2019
@andybons andybons added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Apr 4, 2019
@andybons
Copy link
Member

andybons commented Apr 4, 2019

@neelance @agnivade

@bradleypeabody bradleypeabody changed the title question: can syscall/js be imported on other non-wasm platforms? question: should syscall/js be importable on other non-wasm platforms? Apr 4, 2019
@agnivade
Copy link
Contributor

agnivade commented Apr 5, 2019

The os package is meant to be cross-platform. Hence, you can use it anywhere. But the syscall packages are low-level and are always meant to be guarded with build tags. All syscall code is written with build tags. I think it is un-idiomatic to have a sycall/js package run on non-wasm platforms.

From what I understand, you are basically looking to write "isomorphic" wasm code without using build tags to control whether the code runs on server or client. Things might change with the wasi spec coming into the picture (#31105).

But for now, I think using build tags are the way to go. You might want to write a wrapper package which goes the normal path for js,wasm and returns zero values for other targets. Then use that package in your code.

I will defer to @neelance if he has any further thoughts.

@bradleypeabody
Copy link
Author

bradleypeabody commented Apr 5, 2019

Thanks for the feedback - got it on syscall packages, makes sense.

you are basically looking to write "isomorphic" wasm code without using build tags to control whether the code runs on server or client.

Yes, or at least that would be the simplest developer experience if it is possible to achieve.

I thought about a wrapper package and it's certainly an option, but I'm concerned it will feel crufty and unnecessary for the most common case. (And developers will look at it and rightly ask, why can't I just use syscall/js...) A solution that works at the code generator I think would be more elegant, and incidentally easier to maintain, for Vugu. Perhaps the code generator can emit a server-side copy of the code with interface{} instead of js.Value, etc., or even omit the offending code - that might actually produce a correct server-side-rendered program in a lot of cases (and leave the edge cases to be handled manually by the developer just moving stuff into the right files and doing the build tags manually).

In any case, thanks for the suggestion. I'll definitely weigh the pros and cons and see what makes sense.

(UPDATE: actually, I think if I provide my own copy of syscall/js which is just the stub implementation I was originally describing, I can output a separate copy of the program with the appropriate build tag (e.g. !wasm) and just change the import, e.g. import js "github.com/vugu/vugu/js-stub")

Assuming WASI moves forward and provides a more standardized interface for external access to things, I guess it's possible that could potentially lead to a package that would exist both in browser and on-server... But it means building and running server code with GOOS=wasi - which, while I won't count it out, I know for sure a lot of people won't want to mess around with. Which basically just points back to what you've already said, figure out a way to use build tags.

@neelance
Copy link
Member

neelance commented Apr 5, 2019

I think @agnivade already explained it quite well. The abstraction you are looking for should happen on a different level (virtual DOM) and with build tags you can make sure that the code which uses syscall/js gets excluded if necessary.

@bradleypeabody
Copy link
Author

Okay cool. Thanks to the both of you for taking the time to answer. I agree, I'll be able to handle this in my package using build tags. I'll go ahead and close this issue.

@golang golang locked and limited conversation to collaborators Apr 4, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

5 participants