-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: syscall/js: stricter conversion methods #29642
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
Comments
What about only adding @bradfitz I'd like your opinion on this if you don't mind. |
Thanks @neelance.
The
Yes, I think an inconsistency of this sort in a brand new API would be a shame. In a Slack discussion we also came up with
|
Avoiding the panic sounds important to me, just from the perspective of being able to catch when a problem occurs - using standard "if err != nil" approach - for handling. I'd steer clear of option 1. 😄 |
Name wise.. the |
Out of the three options, I definitely prefer option 2. It's a little more complicated than option 1, but avoids panics. Also, compare the situation to converting strings to other types in Go. The strconv package Parse_Type_() functions like ParseInt() and ParseBool() accept a string and return an error if the string couldn't be converted to that type. |
I'm now in favor of the panic method, as described here. |
Re: the bikeshed; Rust has chosen https://docs.rs/wasm-bindgen/0.2.11/wasm_bindgen/struct.JsValue.html |
I think we should not return an error value (or |
@neelance on the question of returning an error/bool vs panic, I'm not sure it's that clear cut. A number of JavaScript APIs allow fields of effectively union type. e.g. To my mind, if we have to make a decision one way or the other here it should be somewhat guided by how often such a pattern would need to be handled in practice. I don't have any gut feel/numbers on that. Alternatively, don't force a decision between the two, instead add additional API methods for the error/bool handling, effectively a hybrid of options 1 and 2.
|
I don't understand this, please post example code. |
Actually, I'm wrong here. Because you'd almost certainly use So I agree, the |
Think we're waiting on @bradfitz to opine on this... Anyone else? Would it be possible to get this in for 1.12, given that WASM is still experimental? |
I think it is too late in the cycle to get this into 1.12. Also, we don't seem to have a consensus yet. |
Definitely too late for 1.12. Sorry. |
Adding MustString() or do nothing at all is the best solution. Using To*/As* indicate that a conversion of some sort is taking place. If the type is a float with value 3.1415, and I invoking We are actually getting current value. Get is a better prefix as in option 2 and 3 is also hard to use. Example |
The problem with
despite there being a Instead, having a consistent API is much clearer and less susceptible to user error:
|
I would like to propose an alternative, inspired by https://golang.org/pkg/reflect/#Value.String: For non-string values instead of using JS's type conversion we use the following string representations:
This has the following properties:
The downside of the inconsistency between If one is processing external data and strict type checking is required, then explicit checking of the |
@neelance and I discussed this further offline. I think the conclusion we reached is that what I'm after is better suited to a package/approach that sits atop |
Do you have a report, @myitcv? |
Haven't had a chance yet @bradfitz. So I'd suggest we either put this on hold or close it. We can always resurrect the issue later if needs be |
Closing per discussion with @golang/proposal-review |
@andybons What about my proposal to change the results of |
Change https://golang.org/cl/169757 mentions this issue: |
This change modifies Value.String() to use the following representations for non-string values: <undefined> <null> <boolean: true> <number: 42> <symbol> <object> <function> It avoids JavaScript conversion semantics in the Go API and lowers the risk of hidden bugs by unexpected conversions, e.g. the conversion of the number 42 to the string "42". See discussion in #29642. This is a breaking change, which are still allowed for syscall/js. The impact should be small since it only affects uses of Value.String() with non-string values, which should be uncommon. Updates #29642. Change-Id: I2c27be6e24befe8cb713031fbf66f7b6041e7148 Reviewed-on: https://go-review.googlesource.com/c/go/+/169757 Run-TryBot: Richard Musiol <neelance@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This proposal is based on work originally done for GopherJS in gopherjs/gopherjs#617.
Problem
Currently, any
syscall.js.Value
can haveString()
called on it, and that is guaranteed to succeed, because JavaScript'sString(thing)
function can take anything as an argument (this is where it is used). For example:gives:
By contrast, the
Int()
,Float()
, andBool()
methods are much stricter. They require ajs.Value
with a JavaScript type ofnumber
,number
andboolean
respectively. Consider the following example forInt()
:gives:
I believe that the strictness of
Int()
,Float()
andBool()
methods is correct; with this strictness, I can make strong assertions about the fact that only anumber
,number
orboolean
can have been the source value. I discuss below whether panic-ing is the correct approach when the source type is incorrect.By contrast, I believe the current implementation of
String()
will cause issues. Precisely because I can't make any assertions about the source value: I can't opt-out of this automatic conversion that happens along the way. Instead everywhere I callString()
I need to defensively code to ensure that I actually have astring
value on the JavaScript side before treating it as such on the Go side:gives:
However, the current implementation of
String()
is useful in one important respect (thanks to @neelance for reminding me of this):fmt
. It allows ajs.Value
value to implementfmt.Stringer
. Having the JavaScriptString()
representation of a value makes sense to me.That said, we can't just change
String()
to be as strict asInt()
et al.Potential solution
My proposal is that we leave
String()
as is forfmt
reasons, removeInt()
,Float()
andBool()
, and choose one of the following options (there could be others):Option 1: define
AsX()
methods that have the same strict semantics asInt()
et al currently do:That is, unless a method saw the a
boolean
,number
,number
orstring
(respectively) JavaScript typed value, it would panic.Option 2: same as option 1, but instead of panic-ing, return an error:
Option 3: switch to more of an encoding parse style:
This would also have the added benefit of being slightly more future proof in case we decided to relax the very strict semantics of requiring a
boolean
,number
,number
orstring
, and instead allowedundefined
andnull
to be interpreted as the zero value (encoding/json
behaves in this way).Notes
As
method name prefix above is of course not set in stonesyscall/js
docs should also spell out any conversions that happen along the way too. For example, when converting a string valueJavaScript <-> Go
we end up performing aUTF16 <-> UTF8
conversion. This point is not tied to this proposal however, I just mention it in passing given the main focus of the proposal/issue is conversionJavaScript <-> Go
cc @neelance
The text was updated successfully, but these errors were encountered: