From 14367e2384f2fb69544d0ce8c25c6486c64c51d6 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sun, 1 Dec 2019 00:12:42 -0700 Subject: [PATCH] correctly handle the fact that nodeName is uppercase (#251) * correctly handle the fact that nodeName is uppercase --- dom.go | 2 +- dom_native.go | 6 ++++++ dom_test.go | 20 ++++++++++---------- dom_wasmjs_gopherjs.go | 7 +++++++ 4 files changed, 24 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..276b581c 100644 --- a/dom_wasmjs_gopherjs.go +++ b/dom_wasmjs_gopherjs.go @@ -30,6 +30,13 @@ func RenderIntoNode(node js.Value, c Component) error { return renderIntoNode("RenderIntoNode", wrapObject(node), c) } +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)).String() +} + var ( global = wrapObject(js.Global()) undefined = wrappedObject{js.Undefined()}