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

syscall/js: Make syscall/js optional when compiling wasm? #27766

Open
justinclift opened this Issue Sep 20, 2018 · 31 comments

Comments

Projects
None yet
8 participants
@justinclift

justinclift commented Sep 20, 2018

At present, when we compile to wasm syscall/js is automatically included.

This forces the runtime to either be a browser (eg Firefox, Chrome, etc), or at least pretend to be one.

That's kind of non-optimal, as some of the wasm execution environments presently being developed aren't targeted at browser environments. eg:

In the WebAssembly Gophers Slack channel we have people asking about non-browser use cases fairly often. It seems likely that'll be a fairly standard use case, if it can be catered to as well.

How feasible would it be to have some way to suppress the default syscall/js inclusion, or otherwise make it optional?

@Xe

This comment has been minimized.

Xe commented Sep 20, 2018

I have investigated creating a custom GOOS in the past, but it fails with that attached gnarly linker error. Guidance on it would be helpful, as implementing this would unblock the use of Go for my server side webassembly things.

@sbinet

This comment has been minimized.

Member

sbinet commented Sep 20, 2018

Loosely related to #25612 and github.com/go-interpreter/wagon

@peterbourgon

This comment has been minimized.

Member

peterbourgon commented Sep 20, 2018

Little to add except that I also have use cases for Go-to-wasm that don't involve a browser, and I'd be happy to chat about them to anyone interested in the issue.

@bcmills

This comment has been minimized.

Member

bcmills commented Sep 22, 2018

CC @neelance @cherrymui

@neelance

This comment has been minimized.

Member

neelance commented Sep 22, 2018

If you don't have syscall/js, then you'd need something else to interact with the environment. Since there currently is no standard API in the WebAssembly ecosystem, I don't see why we should invent yet another API on our own. If such a standard API emerges in the future, I'd be happy to adopt it.

Today, I would implement the backend API of syscall/js as much as needed for the standard libraries, but no further. You don't need to implement full JavaScript for it. Do you see any significant downsides to this approach?

@justinclift

This comment has been minimized.

justinclift commented Sep 22, 2018

@Xe @peterbourgon Probably best for you to jump in here. 😄

@Xe

This comment has been minimized.

Xe commented Sep 22, 2018

@neelance for now I have been using https://github.com/CommonWA/cwa-spec as an imaginary system ABI. What calls would we need to add to this for Go? The time call is one of them.

@neelance

This comment has been minimized.

Member

neelance commented Sep 22, 2018

Is there any effort to get https://github.com/CommonWA/cwa-spec adopted by https://github.com/WebAssembly, maybe as an official spec?

@justinclift

This comment has been minimized.

justinclift commented Sep 22, 2018

@peterbourgon

This comment has been minimized.

Member

peterbourgon commented Sep 25, 2018

@neelance

If you don't have syscall/js, then you'd need something else to interact with the environment.

Essentially I want to punt on this question. I want to compile Go down to a WebAssembly module, exporting a set of functions as a sort of public API, and binding to or declaring (somehow) a set of import functions, to consume other modules. I want to load and run this module in a server-side environment, with no relation to JS. CommonWA is not of much interest to me (us) in this context.

@neelance

This comment has been minimized.

Member

neelance commented Sep 25, 2018

@peterbourgon

Would you want to call the functions concurrently or only one at a time?
Which types of parameters and return values do you expect?
Would they do HTTP requests to other services?

@peterbourgon

This comment has been minimized.

Member

peterbourgon commented Sep 25, 2018

@neelance I wouldn't take anything off the table in terms of functionality. If you're looking for some kind of examples, I can try to dig something up; let me know.

edit: To be clear, I would want to be able to answer each of those questions differently, in different modules.

@Xe

This comment has been minimized.

Xe commented Sep 26, 2018

@peterbourgon in this case using CommonWA (note: I am not married to CommonWA, it's just not something made by me and looks like it could easily be the basis we could build off of as a community to make it better for everyone) would us all just be standardizing on the set of things the binaries the Go compiler emits would be depending on. These things would then be implemented by the JS side of things too.

@justinclift

This comment has been minimized.

justinclift commented Sep 26, 2018

@peterbourgon

If you're looking for some kind of examples, I can try to dig something up; let me know.

Please do, they'd likely help. 😄

@DavidHuie

This comment has been minimized.

DavidHuie commented Oct 3, 2018

I have a similar use case to @peterbourgon in mind. Wasm on the server creates the opportunity for new types of features, such as user developed, server executed extensions to products. I'd love to use Go for these sorts of things!

@rsc rsc modified the milestones: Go1.12, Go1.13 Nov 14, 2018

@neelance

This comment has been minimized.

Member

neelance commented Nov 14, 2018

Sorry, but I still don't see why syscall/js prevents people from using non-JavaScript hosts. It is only an interface, it should be possible to implement it without having full-blown JavaScript.

@Xe

This comment has been minimized.

Xe commented Nov 14, 2018

What can non-JavaScript hosts do to stub it out or "break" all of its functionality?

@neelance

This comment has been minimized.

Member

neelance commented Nov 14, 2018

@Xe I don't get your question.

@Xe

This comment has been minimized.

Xe commented Nov 14, 2018

@neelance What is the minimal implementation required for every function to have to return an error-like response?

@neelance

This comment has been minimized.

Member

neelance commented Nov 15, 2018

@Xe That of course depends on the function. I would just start with an empty stub of each function which logs its execution and then add the implementation step by step.

@Xe

This comment has been minimized.

Xe commented Nov 15, 2018

Yes, can you please provide these empty stubs? I can't figure them out on my own apparently.

@neelance

This comment has been minimized.

Member

neelance commented Nov 15, 2018

I don't even know which WebAssembly host you are trying to use.

@neelance

This comment has been minimized.

Member

neelance commented Nov 15, 2018

The import functions that you need to stub are the ones you find in

this.importObject = {

@Xe

This comment has been minimized.

Xe commented Nov 15, 2018

For all of these functions: https://github.com/golang/go/blob/master/src/syscall/js/js_js.s

  • What is the stack layout in relative ordinal bytes?
  • What values are arguments?
  • What values are returns?
  • What is the "zero" return?
  • What is a C-like analogue?

These are things that I must know to implement these calls and have not been able to reverse-engineer on my own.

@neelance

This comment has been minimized.

Member

neelance commented Nov 15, 2018

It's the normal Go calling convention. All arguments and return values live on the stack. You can find the function signatures in https://github.com/golang/go/blob/master/src/html/template/js.go and in the wasm_exec.js I linked above. You can also find the stack offsets in the wasm_exec.js if you don't want to calculate them on your own. A quick Google search got me this: https://science.raphael.poss.name/go-calling-convention-x86-64.html

@neelance

This comment has been minimized.

Member

neelance commented Nov 15, 2018

C has a different calling convention than Go, so you won't be able to use simple C function signatures.

@Xe

This comment has been minimized.

Xe commented Nov 15, 2018

I realize the calling convention is different, I would translate that by hand. I want to just know what i should return for the values such that it will get error-like responses, consider go.runtimeNanotime:

The stack layout in relative ordinal bytes is something like this:

sp+0 -> stack pointer
sp+8 -> expected int64 return value

There are no arguments to this function and there is one int64 return that signifies an integer number. The zero return in this function is the value zero, as such:

func runtime.nanotime() int64 {
  return 0
}

The idea is that this kind of basic documentation about what the ABI expects (and what values are zero-like) will provide people who want to use Go in WebAssembly on the server side guidance on how to stub out functionality that they don't want to support (for example, the very reasonable case of being not a browser and not having a javascript VM involved, so Javascript interaction is not needed and thus removable). Can you please help?

@neelance

This comment has been minimized.

Member

neelance commented Nov 16, 2018

@Xe Sorry, I don't have that right now. The os package will also require syscall/js to not return zero all the time. I can only recommend that you start with a simple example, add what's necessary to make it work and then continue from there. I can help you further if you have a specific error that you don't know how to resolve.

@Xe

This comment has been minimized.

Xe commented Nov 16, 2018

Then if it shouldn't return 0 all the time, what is the valid thing to do?

@neelance

This comment has been minimized.

Member

neelance commented Nov 16, 2018

Fulfill the interface good enough that it supports the actions that you want to support or that it at least does not crash on initialization. Specifics depend on the case.

@neelance

This comment has been minimized.

Member

neelance commented Nov 16, 2018

I can help you further if you have a specific error that you don't know how to resolve.

This still holds. I don't see how I can give you more information without implementing it myself. There is no specification that you can fulfill in one go. You'll have to start with some concrete example that you want to make pass and then we can figure out together what is necessary to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment