Skip to content

Commit 5a7149a

Browse files
committed
js: auto-generate getters and setters for calls to MakeWrapper
Currently the documentation for js.MakeWrapper is: "MakeWrapper creates a JavaScript object which has wrappers for the exported methods of i. Use explicit getter and setter methods to expose struct fields to JavaScript." Where the value passed to MakeWrapper is a struct value (or more interestingly a pointer to a struct value) we can actually auto-generate getters and setters in the Javascript world, rather than requiring explicit getters and setters to be defined on the Go side.
1 parent 558a913 commit 5a7149a

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

js/js.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,29 @@ func MakeWrapper(i interface{}) *Object {
144144
return Global.Call("$externalizeFunction", v.Get(m.Get("prop").String()), m.Get("typ"), true).Call("apply", v, args)
145145
})
146146
}
147+
fields := v.Get("constructor").Get("fields")
148+
if fields == Undefined {
149+
if e := v.Get("constructor").Get("elem"); e != Undefined {
150+
fields = e.Get("fields")
151+
}
152+
}
153+
if fields != Undefined {
154+
for i := 0; i < fields.Length(); i++ {
155+
f := fields.Index(i)
156+
if !f.Get("exported").Bool() {
157+
continue
158+
}
159+
op := Global.Get("Object").New()
160+
op.Set("get", func() *Object {
161+
return Global.Call("$externalize", v.Get("$val").Get(f.Get("prop").String()), f.Get("typ"))
162+
})
163+
op.Set("set", func(jv *Object) {
164+
gv := Global.Call("$internalize", jv, f.Get("typ"))
165+
v.Get("$val").Set(f.Get("prop").String(), gv)
166+
})
167+
Global.Get("Object").Call("defineProperty", o, f.Get("prop"), op)
168+
}
169+
}
147170
return o
148171
}
149172

js/js_test.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@ func TestMakeFunc(t *testing.T) {
423423
}
424424

425425
type M struct {
426+
Name string
427+
426428
f int
427429
}
428430

@@ -436,7 +438,7 @@ func (m *M) Method(a interface{}) map[string]string {
436438
}
437439

438440
func TestMakeWrapper(t *testing.T) {
439-
m := &M{42}
441+
m := &M{f: 42}
440442
if !js.Global.Call("eval", `(function(m) { return m.Method({x: 1})["y"] === "z"; })`).Invoke(js.MakeWrapper(m)).Bool() {
441443
t.Fail()
442444
}
@@ -453,6 +455,21 @@ func TestMakeWrapper(t *testing.T) {
453455
js.Global.Call("eval", `(function(f, m) { f(m); })`).Invoke(f, js.MakeWrapper(m))
454456
}
455457

458+
func TestMakeWrapperFields(t *testing.T) {
459+
want := "Gopher"
460+
m := &M{Name: want}
461+
o := js.MakeWrapper(m)
462+
js.Global.Set("banana", o)
463+
if got := js.Global.Call("eval", `(function(o) { return o["banana"].Name; })`).Invoke(js.Global).String(); got != want {
464+
t.Fatalf("wanted %v; got %v", want, got)
465+
}
466+
want = "JS"
467+
js.Global.Call("eval", `(function(o) { o["banana"].Name = "`+want+`"; })`).Invoke(js.Global)
468+
if got := m.Name; got != want {
469+
t.Fatalf("wanted %v; got %v", want, got)
470+
}
471+
}
472+
456473
func TestCallWithNull(t *testing.T) {
457474
c := make(chan int, 1)
458475
js.Global.Set("test", func() {

0 commit comments

Comments
 (0)