From 2ba86cc43de713291793ac1126b67f9441338d87 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sat, 30 Nov 2019 22:13:13 -0700 Subject: [PATCH 1/5] correctly handle the fact that nodeName is uppercase --- dom.go | 2 +- dom_native.go | 6 ++++++ dom_test.go | 20 ++++++++++---------- dom_wasmjs_gopherjs.go | 4 ++++ 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/dom.go b/dom.go index 0eb000e0..a897a3b4 100644 --- a/dom.go +++ b/dom.go @@ -1225,7 +1225,7 @@ func renderIntoNode(methodName string, node jsObject, c Component) error { if skip { panic("vecty: " + methodName + ": Component.SkipRender illegally returned true") } - expectTag := node.Get("nodeName").String() + expectTag := toLower(node.Get("nodeName").String()) if nextRender.tag != expectTag { return ElementMismatchError{method: methodName, got: nextRender.tag, want: expectTag} } diff --git a/dom_native.go b/dom_native.go index 0e53d7f0..a61ebb6d 100755 --- a/dom_native.go +++ b/dom_native.go @@ -2,6 +2,8 @@ package vecty +import "strings" + // Stubs for building Vecty under a native GOOS and GOARCH, so that Vecty // type-checks, lints, auto-completes, and serves documentation under godoc.org // as with any other normal Go package that is not under GOOS=js and @@ -37,6 +39,10 @@ func RenderIntoNode(node SyscallJSValue, c Component) error { return renderIntoNode("RenderIntoNode", node, c) } +func toLower(s string) string { + return strings.ToLower(s) +} + var ( global jsObject undefined wrappedObject diff --git a/dom_test.go b/dom_test.go index 77444c3c..883d10eb 100644 --- a/dom_test.go +++ b/dom_test.go @@ -563,7 +563,7 @@ func TestRerender_identical(t *testing.T) { ts.ints.mock(`global.Call("requestAnimationFrame", func)`, 0) ts.strings.mock(`global.Get("document").Get("readyState")`, "complete") - ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "body") + ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "BODY") ts.truthies.mock(`global.Get("document").Call("querySelector", "body")`, true) // Perform the initial render of the component. @@ -652,7 +652,7 @@ func TestRerender_change(t *testing.T) { ts.ints.mock(`global.Call("requestAnimationFrame", func)`, 0) ts.strings.mock(`global.Get("document").Get("readyState")`, "complete") - ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "body") + ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "BODY") ts.truthies.mock(`global.Get("document").Call("querySelector", "body")`, true) // Perform the initial render of the component. @@ -757,7 +757,7 @@ func TestRerender_Nested(t *testing.T) { ts.ints.mock(`global.Call("requestAnimationFrame", func)`, 0) ts.strings.mock(`global.Get("document").Get("readyState")`, "complete") - ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "body") + ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "BODY") ts.truthies.mock(`global.Get("document").Call("querySelector", "body")`, true) // Perform the initial render of the component. @@ -857,7 +857,7 @@ func TestRerender_persistent(t *testing.T) { ts.ints.mock(`global.Call("requestAnimationFrame", func)`, 0) ts.strings.mock(`global.Get("document").Get("readyState")`, "complete") - ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "body") + ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "BODY") ts.truthies.mock(`global.Get("document").Call("querySelector", "body")`, true) lastRenderedComponent = nil @@ -921,7 +921,7 @@ func TestRerender_persistent_direct(t *testing.T) { ts.ints.mock(`global.Call("requestAnimationFrame", func)`, 0) ts.strings.mock(`global.Get("document").Get("readyState")`, "complete") - ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "body") + ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "BODY") ts.truthies.mock(`global.Get("document").Call("querySelector", "body")`, true) lastRenderedComponent = nil @@ -987,7 +987,7 @@ func TestRenderBody_ExpectsBody(t *testing.T) { ts := testSuite(t) defer ts.done() - ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "body") + ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "BODY") ts.truthies.mock(`global.Get("document").Call("querySelector", "body")`, true) var gotPanic string @@ -1048,7 +1048,7 @@ func TestRenderBody_Standard_loaded(t *testing.T) { ts.strings.mock(`global.Get("document").Get("readyState")`, "loaded") ts.ints.mock(`global.Call("requestAnimationFrame", func)`, 0) - ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "body") + ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "BODY") ts.truthies.mock(`global.Get("document").Call("querySelector", "body")`, true) RenderBody(&componentFunc{ @@ -1067,7 +1067,7 @@ func TestRenderBody_Standard_loading(t *testing.T) { ts.strings.mock(`global.Get("document").Get("readyState")`, "loading") ts.ints.mock(`global.Call("requestAnimationFrame", func)`, 0) - ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "body") + ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "BODY") ts.truthies.mock(`global.Get("document").Call("querySelector", "body")`, true) RenderBody(&componentFunc{ @@ -1088,7 +1088,7 @@ func TestRenderBody_Nested(t *testing.T) { ts.strings.mock(`global.Get("document").Get("readyState")`, "complete") ts.ints.mock(`global.Call("requestAnimationFrame", func)`, 0) - ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "body") + ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "BODY") ts.truthies.mock(`global.Get("document").Call("querySelector", "body")`, true) RenderBody(&componentFunc{ @@ -1130,7 +1130,7 @@ func TestKeyedChild_DifferentType(t *testing.T) { ts.ints.mock(`global.Call("requestAnimationFrame", func)`, 0) ts.strings.mock(`global.Get("document").Get("readyState")`, "complete") - ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "body") + ts.strings.mock(`global.Get("document").Call("querySelector", "body").Get("nodeName")`, "BODY") ts.truthies.mock(`global.Get("document").Call("querySelector", "body")`, true) comp := &componentFunc{ diff --git a/dom_wasmjs_gopherjs.go b/dom_wasmjs_gopherjs.go index 098cbacf..d6f2a34a 100644 --- a/dom_wasmjs_gopherjs.go +++ b/dom_wasmjs_gopherjs.go @@ -30,6 +30,10 @@ func RenderIntoNode(node js.Value, c Component) error { return renderIntoNode("RenderIntoNode", wrapObject(node), c) } +func toLower(s string) string { + return valueOf(s).Call("toLowerCase").String() +} + var ( global = wrapObject(js.Global()) undefined = wrappedObject{js.Undefined()} From 578efa2e2c126eac0637ad35d075854a9c535305 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sat, 30 Nov 2019 23:06:26 -0700 Subject: [PATCH 2/5] workaround --- dom_wasmjs_gopherjs.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dom_wasmjs_gopherjs.go b/dom_wasmjs_gopherjs.go index d6f2a34a..2369b6d9 100644 --- a/dom_wasmjs_gopherjs.go +++ b/dom_wasmjs_gopherjs.go @@ -31,7 +31,13 @@ func RenderIntoNode(node js.Value, c Component) error { } func toLower(s string) string { - return valueOf(s).Call("toLowerCase").String() + // We must call the prototype method here to workaround a limitation of + // syscall/js in Go (but not GopherJS) where the following program will + // panic: https://gopherjs.github.io/playground/#/UxD9vDjbf0 + // + // panic: syscall/js: call of Value.Call on string + // + return js.Global.Get("String").Get("prototype").Get("toLowerCase").Call("call", js.ValueOf(s)) } var ( From e5fb70adad0c9ea6e76281d09e610adbff5d7309 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sat, 30 Nov 2019 23:09:30 -0700 Subject: [PATCH 3/5] better comment --- dom_wasmjs_gopherjs.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/dom_wasmjs_gopherjs.go b/dom_wasmjs_gopherjs.go index 2369b6d9..20be8827 100644 --- a/dom_wasmjs_gopherjs.go +++ b/dom_wasmjs_gopherjs.go @@ -32,11 +32,8 @@ func RenderIntoNode(node js.Value, c Component) error { func toLower(s string) string { // We must call the prototype method here to workaround a limitation of - // syscall/js in Go (but not GopherJS) where the following program will - // panic: https://gopherjs.github.io/playground/#/UxD9vDjbf0 - // - // panic: syscall/js: call of Value.Call on string - // + // syscall/js in both Go and GopherJS where we cannot call the + // `toLowerCase` string method. See https://github.com/golang/go/issues/35917 return js.Global.Get("String").Get("prototype").Get("toLowerCase").Call("call", js.ValueOf(s)) } From 4555c494cac1e7fbd0cd2ebffae7038e15cb1e16 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sat, 30 Nov 2019 23:10:43 -0700 Subject: [PATCH 4/5] fix typo --- dom_wasmjs_gopherjs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom_wasmjs_gopherjs.go b/dom_wasmjs_gopherjs.go index 20be8827..ab40dc67 100644 --- a/dom_wasmjs_gopherjs.go +++ b/dom_wasmjs_gopherjs.go @@ -34,7 +34,7 @@ func toLower(s string) string { // We must call the prototype method here to workaround a limitation of // syscall/js in both Go and GopherJS where we cannot call the // `toLowerCase` string method. See https://github.com/golang/go/issues/35917 - return js.Global.Get("String").Get("prototype").Get("toLowerCase").Call("call", js.ValueOf(s)) + return js.Global().Get("String").Get("prototype").Get("toLowerCase").Call("call", js.ValueOf(s)) } var ( From 7ee19ae71a606df0ad642dcff3fc9c2fe34cd60a Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sat, 30 Nov 2019 23:16:50 -0700 Subject: [PATCH 5/5] fix typo --- dom_wasmjs_gopherjs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom_wasmjs_gopherjs.go b/dom_wasmjs_gopherjs.go index ab40dc67..276b581c 100644 --- a/dom_wasmjs_gopherjs.go +++ b/dom_wasmjs_gopherjs.go @@ -34,7 +34,7 @@ func toLower(s string) string { // We must call the prototype method here to workaround a limitation of // syscall/js in both Go and GopherJS where we cannot call the // `toLowerCase` string method. See https://github.com/golang/go/issues/35917 - return js.Global().Get("String").Get("prototype").Get("toLowerCase").Call("call", js.ValueOf(s)) + return js.Global().Get("String").Get("prototype").Get("toLowerCase").Call("call", js.ValueOf(s)).String() } var (