Skip to content
This repository was archived by the owner on Apr 30, 2019. It is now read-only.

proposal: support wrapping existing native objects #25

Open
emidoots opened this issue Jan 20, 2019 · 11 comments
Open

proposal: support wrapping existing native objects #25

emidoots opened this issue Jan 20, 2019 · 11 comments
Labels
enhancement New feature or request

Comments

@emidoots
Copy link

If you are making use of a library which only gives you an underlying *gopherjs/js.Object (GopherJS) or syscall/js.Value (WebAssembly) object, it is impossible to use this library with that object.

This is unfortunate because it makes interoperability hard: when you are given one of these underlying objects, you must use those APIs independently rather than being able to make use of this generic library. It means that in order to use this library, you must effectively switch completely to this library first.

The primary reason I bring this up is because Vecty will not expose this library but rather only the native object type, which means users of Vecty will not be able to use this package. I would like them to be able to.

I thus propose a way to wrap an existing native object and get back a gopherwasm/js.Value. This would be done by a function whose type signature changes based on a build tag:

Under GopherJS:

// Wrap wraps a *gopherjs/js.Object and returns a Value.
//
// When compiling under WebAssembly, this function signature instead takes a
// syscall/js.Value.
func Wrap(object *js.Object) Value

And under WebAssembly:

// Wrap wraps a syscall/js.Value and returns a Value.
//
// When compiling under WebAssembly, this function signature instead takes a
// *gopherjs/js.Object.
func Wrap(value js.Value) Value
@emidoots emidoots changed the title proposal: support wrapping existing objects proposal: support wrapping existing native objects Jan 20, 2019
@hajimehoshi hajimehoshi added the enhancement New feature or request label Jan 21, 2019
@hajimehoshi
Copy link
Member

I think your suggestion makes sense. I'm happy that you're trying to use GopherWasm at Vecty :-)

Wrap

My concern is the name: I'm worried the possibility that syscall/js would add a new function named Wrap. WrapAsGopherWasmValue or ToGopherWasmValue? Hmm.

@emidoots
Copy link
Author

I considered this, too, but I think it is unlikely as there was some prior discussion about adding a syscall/js.Wrap function and the name was effectively turned down on being too abstract: golang/go#28711 (comment)

I think it could be a good choice of naming here because this function would likely often be used when performing interoperability.

@hajimehoshi
Copy link
Member

Thank you! After reading the comment, I came up with the same concern: what will Wrap wrap? :-)

I think it could be a good choice of naming here because this function would likely often be used when performing interoperability.

I don't know other examples. Could you show me one?

@emidoots
Copy link
Author

Thank you! After reading the comment, I came up with the same concern: what will Wrap wrap? :-)

With syscall/js.Wrap you must wonder: What does it wrap? Does it wrap "js"? Does it wrap a "syscall"? That doesn't make sense.

With gopherwasm/js.Wrap, my thinking is that it wraps gopher or wasm. It wraps gopherwasm, like WrapGopherWasm. But since what it wraps changes based on the build tag, we would end up with WrapGopher and WrapWasm or something. So we omit that and end up with just Wrap.

I don't know other examples. Could you show me one?

Basically, I imagine this will be used often in conjunction with event handling in specific. For example in Vecty any time you define an event handler you will call this once or twice:

event.Input(func(e *vecty.Event) {
    p.Input = gopherwasm.Wrap(e.Target).Get("value").String()
    gopherwasm.Wrap(e.Value).Call("preventDefault")
    vecty.Rerender(p)
}),

But if the name is complex, long, hard to type, etc. it becomes much more verbose:

event.Input(func(e *vecty.Event) {
    p.Input = gopherwasm.ToGopherWasmValue(e.Target).Get("value").String()
    gopherwasm.ToGopherWasmValue(e.Value).Call("preventDefault")
    vecty.Rerender(p)
}),

@emidoots
Copy link
Author

WrapNative would be my second choice, but I still worry it is too long / verbose

@hajimehoshi
Copy link
Member

hajimehoshi commented Jan 21, 2019

Basically, I imagine this will be used often in conjunction with event handling in specific. For example in Vecty any time you define an event handler you will call this once or twice:

I meant that I was wondering if there are other libraries that use a function named Wrap for similar purpose so that I can confirm that Wrap is idiomatic in Go.

Thank you for your example, I think that makes sense.

@hajimehoshi
Copy link
Member

I found several examples like https://godoc.org/github.com/pkg/errors#Wrap

OK, I'm now convinced to add Wrap. Would you create a PR?

@emidoots
Copy link
Author

Ah, I see, I misunderstood. Yes, I will create a PR in the near future (but possibly not this weekend).

@hajimehoshi
Copy link
Member

https://tip.golang.org/doc/go1.12#syscall/js As Go 1.12 tries to introduce Wrapper, I'm now doubtful that Wrap is and will be safe 🤔

@emidoots
Copy link
Author

Hmm, interesting. I was actually thinking From might be a better name:

// From creates a gopherwasm Value from a syscall/js.Value or *gopherjs/js.Object.
func From(v js.Value) Value

@hajimehoshi
Copy link
Member

hajimehoshi commented Jan 25, 2019

Yet another suggestion: would it work if we extend ValueOf to accept js.Value or *js.Object?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants