From 5784b769903006aae49e4e273dccf22a0c1cd4ea Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 3 Apr 2026 07:51:45 +0000 Subject: [PATCH] fix(wasm): harden renderToString arg handling Add type guards for variant and locale inputs at the WASM boundary and a js+wasm integration test suite for renderToString behavior. Co-Authored-By: Virgil --- cmd/wasm/main.go | 8 +++++-- cmd/wasm/main_test.go | 55 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 cmd/wasm/main_test.go diff --git a/cmd/wasm/main.go b/cmd/wasm/main.go index a3c0db2..aa6997a 100644 --- a/cmd/wasm/main.go +++ b/cmd/wasm/main.go @@ -13,14 +13,18 @@ import ( // This is intentional: the WASM module is a rendering engine for trusted content // produced server-side or by the application's own templates. func renderToString(_ js.Value, args []js.Value) any { - if len(args) < 1 { + if len(args) < 1 || args[0].Type() != js.TypeString { return "" } variant := args[0].String() + if variant == "" { + return "" + } + ctx := html.NewContext() - if len(args) >= 2 { + if len(args) >= 2 && args[1].Type() == js.TypeString { ctx.Locale = args[1].String() } diff --git a/cmd/wasm/main_test.go b/cmd/wasm/main_test.go new file mode 100644 index 0000000..4184caa --- /dev/null +++ b/cmd/wasm/main_test.go @@ -0,0 +1,55 @@ +//go:build js && wasm + +package main + +import ( + "testing" + + "syscall/js" +) + +func TestRenderToString_Good(t *testing.T) { + gotAny := renderToString(js.Value{}, []js.Value{ + js.ValueOf("C"), + js.ValueOf("en-GB"), + js.ValueOf(map[string]any{"C": "hello"}), + }) + + got, ok := gotAny.(string) + if !ok { + t.Fatalf("renderToString should return string, got %T", gotAny) + } + + want := `
hello
` + if got != want { + t.Fatalf("renderToString(...) = %q, want %q", got, want) + } +} + +func TestRenderToString_VariantTypeGuard(t *testing.T) { + if got := renderToString(js.Value{}, []js.Value{js.ValueOf(123)}); got != "" { + t.Fatalf("non-string variant should be empty, got %q", got) + } + + if got := renderToString(js.Value{}, []js.Value{}); got != "" { + t.Fatalf("missing variant should be empty, got %q", got) + } +} + +func TestRenderToString_LocaleTypeGuard(t *testing.T) { + gotAny := renderToString(js.Value{}, []js.Value{ + js.ValueOf("C"), + js.ValueOf(123), + js.ValueOf(map[string]any{"C": "x"}), + }) + + got, ok := gotAny.(string) + if !ok { + t.Fatalf("renderToString should return string, got %T", gotAny) + } + + want := `
x
` + if got != want { + t.Fatalf("renderToString with non-string locale = %q, want %q", got, want) + } +}