@@ -16,19 +16,32 @@ import (
16
16
)
17
17
18
18
// ref is used to identify a JavaScript value, since the value itself can not be passed to WebAssembly.
19
- // A JavaScript number (64-bit float, except NaN) is represented by its IEEE 754 binary representation.
19
+ //
20
+ // The JavaScript value "undefined" is represented by the value 0.
21
+ // A JavaScript number (64-bit float, except 0 and NaN) is represented by its IEEE 754 binary representation.
20
22
// All other values are represented as an IEEE 754 binary representation of NaN with bits 0-31 used as
21
23
// an ID and bits 32-33 used to differentiate between string, symbol, function and object.
22
24
type ref uint64
23
25
24
- // nanHead are the upper 32 bits of a ref which are set if the value is not a JavaScript number or NaN itself .
26
+ // nanHead are the upper 32 bits of a ref which are set if the value is not encoded as an IEEE 754 number (see above) .
25
27
const nanHead = 0x7FF80000
26
28
27
- // Value represents a JavaScript value.
29
+ // Wrapper is implemented by types that are backed by a JavaScript value.
30
+ type Wrapper interface {
31
+ // JSValue returns a JavaScript value associated with an object.
32
+ JSValue () Value
33
+ }
34
+
35
+ // Value represents a JavaScript value. The zero value is the JavaScript value "undefined".
28
36
type Value struct {
29
37
ref ref
30
38
}
31
39
40
+ // JSValue implements Wrapper interface.
41
+ func (v Value ) JSValue () Value {
42
+ return v
43
+ }
44
+
32
45
func makeValue (v ref ) Value {
33
46
return Value {ref : v }
34
47
}
@@ -38,6 +51,9 @@ func predefValue(id uint32) Value {
38
51
}
39
52
40
53
func floatValue (f float64 ) Value {
54
+ if f == 0 {
55
+ return valueZero
56
+ }
41
57
if f != f {
42
58
return valueNaN
43
59
}
@@ -56,8 +72,9 @@ func (e Error) Error() string {
56
72
}
57
73
58
74
var (
75
+ valueUndefined = Value {ref : 0 }
59
76
valueNaN = predefValue (0 )
60
- valueUndefined = predefValue (1 )
77
+ valueZero = predefValue (1 )
61
78
valueNull = predefValue (2 )
62
79
valueTrue = predefValue (3 )
63
80
valueFalse = predefValue (4 )
@@ -90,21 +107,21 @@ func Global() Value {
90
107
// | ---------------------- | ---------------------- |
91
108
// | js.Value | [its value] |
92
109
// | js.TypedArray | typed array |
93
- // | js.Callback | function |
110
+ // | js.Func | function |
94
111
// | nil | null |
95
112
// | bool | boolean |
96
113
// | integers and floats | number |
97
114
// | string | string |
98
115
// | []interface{} | new array |
99
116
// | map[string]interface{} | new object |
117
+ //
118
+ // Panics if x is not one of the expected types.
100
119
func ValueOf (x interface {}) Value {
101
120
switch x := x .(type ) {
102
- case Value :
121
+ case Value : // should precede Wrapper to avoid a loop
103
122
return x
104
- case TypedArray :
105
- return x .Value
106
- case Callback :
107
- return x .Value
123
+ case Wrapper :
124
+ return x .JSValue ()
108
125
case nil :
109
126
return valueNull
110
127
case bool :
@@ -318,13 +335,18 @@ func (v Value) New(args ...interface{}) Value {
318
335
func valueNew (v ref , args []ref ) (ref , bool )
319
336
320
337
func (v Value ) isNumber () bool {
321
- return v .ref >> 32 & nanHead != nanHead || v .ref == valueNaN .ref
338
+ return v .ref == valueZero .ref ||
339
+ v .ref == valueNaN .ref ||
340
+ (v .ref != valueUndefined .ref && v .ref >> 32 & nanHead != nanHead )
322
341
}
323
342
324
343
func (v Value ) float (method string ) float64 {
325
344
if ! v .isNumber () {
326
345
panic (& ValueError {method , v .Type ()})
327
346
}
347
+ if v .ref == valueZero .ref {
348
+ return 0
349
+ }
328
350
return * (* float64 )(unsafe .Pointer (& v .ref ))
329
351
}
330
352
@@ -350,6 +372,26 @@ func (v Value) Bool() bool {
350
372
}
351
373
}
352
374
375
+ // Truthy returns the JavaScript "truthiness" of the value v. In JavaScript,
376
+ // false, 0, "", null, undefined, and NaN are "falsy", and everything else is
377
+ // "truthy". See https://developer.mozilla.org/en-US/docs/Glossary/Truthy.
378
+ func (v Value ) Truthy () bool {
379
+ switch v .Type () {
380
+ case TypeUndefined , TypeNull :
381
+ return false
382
+ case TypeBoolean :
383
+ return v .Bool ()
384
+ case TypeNumber :
385
+ return v .ref != valueNaN .ref && v .ref != valueZero .ref
386
+ case TypeString :
387
+ return v .String () != ""
388
+ case TypeSymbol , TypeFunction , TypeObject :
389
+ return true
390
+ default :
391
+ panic ("bad type" )
392
+ }
393
+ }
394
+
353
395
// String returns the value v converted to string according to JavaScript type conversions.
354
396
func (v Value ) String () string {
355
397
str , length := valuePrepareString (v .ref )
0 commit comments