-
Notifications
You must be signed in to change notification settings - Fork 42
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
wasm: Port of the library using sycall/js
#59
Conversation
dom_wasm.go and event_wasm.go started has a copy of the gopherjs version. I modified them to support `gopherwasm/js`.
Since we have have dedicated files for wasm we can use `syscall/js` directly.
I think this package needs to shift towards being code generated from the HTML spec, which would mitigate this point, as well as allowing code generation of simple tests too. It would also allow us to remove the slightly awkward usage that comes from having embedded structs. |
🤣 good luck & have fun to whoever attempts that.
How is it awkward? The DOM APIs can be modeled rather well with composition, actually, and the current Go API allows passing "base types" to functions, without having to rely on interfaces and a million getter methods. |
Also, what happened to the idea of using github.com/hajimehoshi/gopherwasm for this, to avoid code duplication? |
My main gripe is actually more a function of the fact that in GopherJS, with
In the WASM world, don't we need to do everything with methods in any case? Because we don't have the |
Such a drastic change would need to be considered for v2 or another package. It’s not in scope of this PR/issue.
The 2nd paragraph of the PR description and the linked comment in the issue describes the rationale. |
Well, I'm definitely not a fan of the massive amount of code duplication. That is to say, I'd very much like to avoid it. |
@dominikh Have you seen the initial implementation using I see pros an cons to both approaches. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I've tested the Wasm dom
implementation in this PR with github.com/shurcooL/tictactoe, a small/medium-sized project that uses honnef.co/go/js/dom
. After making some minor modifications, it was working, which is very promising:
I have 2 change requests for this PR so far, see inline comments.
dom_wasm.go
Outdated
return els | ||
} | ||
|
||
// TODO (yml): Find out if we really want to modify this signature |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not want to modify the signature. First, it causes the API to differ between GopherJS and Wasm. Second, it causes *htmlDocument
to no longer satisfy the Document
interface:
panic: interface conversion: *dom.htmlDocument is not dom.HTMLDocument: missing method LastModified
Third, converting the lastModified
Date to string and parsing it back to time.Time
is not efficient.
Instead, let's use the same Date -> time.Time
conversion process that GopherJS uses (it uses the Date.getTime method), which resolves all those issues:
func (d *htmlDocument) LastModified() time.Time {
return time.Unix(0, int64(d.Object.Get("lastModified").Call("getTime").Int()) * 1000000)
}
dom_wasm.go
Outdated
// new features are added to the DOM. | ||
// | ||
// If you depend on none of the APIs changing unexpectedly, you're | ||
// advised to vendor this package. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, I'd prefer we avoid duplicating the package comment, since we can avoid it. Let's delete it here and in dom.go
, and move it to a new file doc.go
that just has the package comment and package clause.
Also, please move the import comment to just doc.go
file (and remove it elsewhere).
* Moved the comments to a doc.go * Improved to the implementation of LastModified to make the signature compatible
@shurcooL not sure I did the right thing to approve your changes. I pushed a commit in branch. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure I did the right thing to approve your changes.
Your changes look good so far, thanks for making them!
Just one minor issue I spotted, see inline comment.
doc.go
Outdated
// If you depend on none of the APIs changing unexpectedly, you're | ||
// advised to vendor this package. | ||
|
||
package dom // import "honnef.co/go/js/dom" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The package comment must be immediately preceding the package clause. There can't be a blank line separating them, otherwise it's not parsed as a package comment by godoc
. So please remove the blank line on line 113.
Reference: https://golang.org/doc/effective_go.html#commentary.
dom_wasm.go
Outdated
// new features are added to the DOM. | ||
// | ||
// If you depend on none of the APIs changing unexpectedly, you're | ||
// advised to vendor this package. | ||
package dom // import "honnef.co/go/js/dom" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove the import comment here as well, so it's only in doc.go
file.
@shurcooL I did all the changes mentioned above. This time I started to I am wondering if the very exact build target |
Perfect, thanks!
That's a good catch. godoc.org has support for displaying docs for GopherJS-only packages (see golang/gddo#343), but I think it will treat the current code as an empty linux/amd64 package, displaying no docs other than the package comment. To fix that, we can just add a |
(Edit: Moved comment to issue #57.) |
This is what I was referring to in #59 (comment):
|
Sorry, I missed that part of your comment. |
Thank you for working on this PR @yml. It has helped us better understand what it looks like to add Wasm support to this package and how viable it was to reuse the existing I'll close this PR since we're not going to proceed with this exact approach, but much of the work done here can carry over into a future PR to implement the updated issue #57. Let's continue to do discussion/planning there. |
This change implements the starting point of a new v2 major version of the dom package. It is now implemented on top of the syscall/js API, which is supported by Go WebAssembly and GopherJS (as of version 1.12-2). The design goal has been to stay as close as possible to v1 API to make the transition easier to make. The only changes that were done were out of neccessity: - All struct fields with `js:"foo"` tags have been replaced with equivalent methods - Underlying() returns js.Value instead of *js.Object - AddEventListener() returns js.Func instead of func(*js.Object) There is a remaining TODO in window.RequestAnimationFrame method to make it so that cancelling the callback via CancelAnimationFrame makes it so the js.Func wrapper's Release method is called. Arranging this is difficult (it requires either having an internal map and sync primitive for tracking js.Func by IDs, or changing the return value of the RequestAnimationFrame method from int to something where the js.Func and its Release method can be accessed easily. The current implementation is functional but may end up using more memory in some situations. It's not blocking for the initial alpha release, so it remains a TODO for now. This implementation was based on work done in by @yml in Pull Request #59. Fixes #57. Co-authored-by: Yann Malet <yann.malet@gmail.com>
This change implements the starting point of a new v2 major version of the dom package. It is now implemented on top of the syscall/js API, which is supported by Go WebAssembly and GopherJS (as of version 1.12-2). The design goal has been to stay as close as possible to v1 API to make the transition easier to make. The only changes that were done were out of necessity: - All struct fields with `js:"foo"` tags have been replaced with equivalent methods - Underlying() returns js.Value instead of *js.Object - AddEventListener() returns js.Func instead of func(*js.Object) - GetBoundingClientRect() returns *Rect instead of ClientRect Update GetBoundingClientRect to return DOMRect instead of the legacy ClientRect. A breaking API change was needed to make it return a pointer rather than a value, so it was a good opportunity to also update the type at the same time. There is a remaining TODO in window.RequestAnimationFrame method to make it so that canceling the callback via CancelAnimationFrame makes it so the js.Func wrapper's Release method is called. Arranging this is difficult (it requires either having an internal map and sync primitive for tracking js.Func by IDs, or changing the return value of the RequestAnimationFrame method from int to something where the js.Func and its Release method can be accessed easily. The current implementation is functional but may end up using more memory in some situations. It's not blocking for the initial alpha release, so it remains a TODO for now. Document API stability; v2 is currently in alpha and more API changes may be done before it exits alpha state. This implementation was based on work done by @yml in Pull Request #59. Fixes #57. Co-authored-by: Yann Malet <yann.malet@gmail.com> Co-authored-by: Dominik Honnef <dominik@honnef.co> GitHub-Pull-Request: #69
Status: This branch is able to compile and run simple program on GOOS=js GOARCH=wasm
The strategy for this branch follows Dimitry's recomendation.
The advantage is that their is no backward incompatible chnages for gopherjs. The downside is that their is a lot of duplicated code that will need to be kept in sync going forward.
From an API perspective the only incompatible changes is LastModified it now returns an error.
func (d *htmlDocument) LastModified() (time.Time, error) {
...
}
Another unfortunate source of awkwardness is the fact that I had to Named the embded struct to avoid the name conflict with the value in HTMLButtonElement.
I have no prior experience with using this library nor with the gopherjs compiler so everything need to be taken with a grain of salt..
Please let me know if there is any interest in merging this kind of changes in the main repo.
Resolves #57.