From 3cea30a2773250af4f74ace1744de2a982cd4df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=98=B8=EF=B8=8F?= <29265684+buffermet@users.noreply.github.com> Date: Thu, 5 Dec 2024 12:49:54 +0100 Subject: [PATCH 1/6] Improve parsing and error handling in js bindings. --- js/data.go | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/js/data.go b/js/data.go index e2bfe5b0..b9d7812e 100644 --- a/js/data.go +++ b/js/data.go @@ -9,24 +9,46 @@ import ( ) func btoa(call otto.FunctionCall) otto.Value { - varValue := base64.StdEncoding.EncodeToString([]byte(call.Argument(0).String())) - v, err := otto.ToValue(varValue) + argv := call.ArgumentList + argc := len(argv) + if argc != 1 { + return ReportError("btoa: expected 1 argument, %d given instead.", argc) + } + + arg := argv[0] + if (!arg.IsString()) { + return ReportError("btoa: single argument must be a string.") + } + + encoded := base64.StdEncoding.EncodeToString([]byte(arg.String())) + v, err := otto.ToValue(encoded) if err != nil { - return ReportError("Could not convert to string: %s", varValue) + return ReportError("btoa: could not convert to string: %s", err.Error()) } return v } func atob(call otto.FunctionCall) otto.Value { - varValue, err := base64.StdEncoding.DecodeString(call.Argument(0).String()) - if err != nil { - return ReportError("Could not decode string: %s", call.Argument(0).String()) + argv := call.ArgumentList + argc := len(argv) + if argc != 1 { + return ReportError("atob: expected 1 argument, %d given instead.", argc) } - v, err := otto.ToValue(string(varValue)) + arg := argv[0] + if (!arg.IsString()) { + return ReportError("btoa: single argument must be a string.") + } + + decoded, err := base64.StdEncoding.DecodeString(arg.String()) if err != nil { - return ReportError("Could not convert to string: %s", varValue) + return ReportError("atob: could not decode string: %s", err.Error()) + } + + v, err := otto.ToValue(string(decoded)) + if err != nil { + return ReportError("atob: could not convert to string: %s", decoded) } return v @@ -39,7 +61,12 @@ func gzipCompress(call otto.FunctionCall) otto.Value { return ReportError("gzipCompress: expected 1 argument, %d given instead.", argc) } - uncompressedBytes := []byte(argv[0].String()) + arg := argv[0] + if (!arg.IsString()) { + return ReportError("btoa: single argument must be a string.") + } + + uncompressedBytes := []byte(arg.String()) var writerBuffer bytes.Buffer gzipWriter := gzip.NewWriter(&writerBuffer) @@ -53,7 +80,7 @@ func gzipCompress(call otto.FunctionCall) otto.Value { v, err := otto.ToValue(string(compressedBytes)) if err != nil { - return ReportError("Could not convert to string: %s", err.Error()) + return ReportError("gzipCompress: could not convert to string: %s", err.Error()) } return v @@ -83,7 +110,7 @@ func gzipDecompress(call otto.FunctionCall) otto.Value { decompressedBytes := decompressedBuffer.Bytes() v, err := otto.ToValue(string(decompressedBytes)) if err != nil { - return ReportError("Could not convert to string: %s", err.Error()) + return ReportError("gzipDecompress: could not convert to string: %s", err.Error()) } return v From 3e8063c2c7e3098374c9c72c56a85c96b95dcd66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=98=B8=EF=B8=8F?= <29265684+buffermet@users.noreply.github.com> Date: Thu, 5 Dec 2024 12:52:27 +0100 Subject: [PATCH 2/6] misc --- js/data.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/data.go b/js/data.go index b9d7812e..42afaee4 100644 --- a/js/data.go +++ b/js/data.go @@ -63,7 +63,7 @@ func gzipCompress(call otto.FunctionCall) otto.Value { arg := argv[0] if (!arg.IsString()) { - return ReportError("btoa: single argument must be a string.") + return ReportError("gzipCompress: single argument must be a string.") } uncompressedBytes := []byte(arg.String()) From 9ed0fadd24940552825ab15b1253a025334c4139 Mon Sep 17 00:00:00 2001 From: buffermet <29265684+buffermet@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:11:48 +0100 Subject: [PATCH 3/6] Begin implementing JavaScript Crypto API, add basic Uint8Array methods. --- js/crypto.go | 29 +++++++++++++++++++++++++++++ js/data.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ js/init.go | 6 ++++++ 3 files changed, 82 insertions(+) create mode 100644 js/crypto.go diff --git a/js/crypto.go b/js/crypto.go new file mode 100644 index 00000000..7128b965 --- /dev/null +++ b/js/crypto.go @@ -0,0 +1,29 @@ +package js + +import ( + "crypto/sha1" + + "github.com/robertkrimen/otto" +) + +func cryptoSha1(call otto.FunctionCall) otto.Value { + argv := call.ArgumentList + argc := len(argv) + if argc != 1 { + return ReportError("Crypto.sha1: expected 1 argument, %d given instead.", argc) + } + + arg := argv[0] + if (!arg.IsString()) { + return ReportError("Crypto.sha1: single argument must be a string.") + } + + hasher := sha1.New() + hasher.Write([]byte(arg.String())) + v, err := otto.ToValue(string(hasher.Sum(nil))) + if err != nil { + return ReportError("Crypto.sha1: could not convert to string: %s", err) + } + + return v +} diff --git a/js/data.go b/js/data.go index 42afaee4..c3c2e164 100644 --- a/js/data.go +++ b/js/data.go @@ -8,6 +8,53 @@ import ( "github.com/robertkrimen/otto" ) +func textEncode(call otto.FunctionCall) otto.Value { + argv := call.ArgumentList + argc := len(argv) + if argc != 1 { + return ReportError("textEncode: expected 1 argument, %d given instead.", argc) + } + + arg := argv[0] + if (!arg.IsString()) { + return ReportError("textEncode: single argument must be a string.") + } + + encoded := []byte(arg.String()) + vm := otto.New() + v, err := vm.ToValue(encoded) + if err != nil { + return ReportError("textEncode: could not convert to []uint8: %s", err.Error()) + } + + return v +} + +func textDecode(call otto.FunctionCall) otto.Value { + argv := call.ArgumentList + argc := len(argv) + if argc != 1 { + return ReportError("textDecode: expected 1 argument, %d given instead.", argc) + } + + arg, err := argv[0].Export() + if err != nil { + return ReportError("textDecode: could not export argument value:", err.Error()) + } + byteArr, ok := arg.([]byte) + if !ok { + return ReportError("textDecode: single argument must be of type []uint8.", argc) + } + + decoded := string(byteArr) + v, err := otto.ToValue(decoded) + if err != nil { + return ReportError("textDecode: could not convert to string: %s", err.Error()) + } + + return v +} + func btoa(call otto.FunctionCall) otto.Value { argv := call.ArgumentList argc := len(argv) diff --git a/js/init.go b/js/init.go index 6415dd88..1aaa52cd 100644 --- a/js/init.go +++ b/js/init.go @@ -27,10 +27,16 @@ func init() { plugin.Defines["log_error"] = log_error plugin.Defines["log_fatal"] = log_fatal + plugin.Defines["Crypto"] = map[string]interface{}{ + "sha1": cryptoSha1, + } + plugin.Defines["btoa"] = btoa plugin.Defines["atob"] = atob plugin.Defines["gzipCompress"] = gzipCompress plugin.Defines["gzipDecompress"] = gzipDecompress + plugin.Defines["textEncode"] = textEncode + plugin.Defines["textDecode"] = textDecode plugin.Defines["httpRequest"] = httpRequest plugin.Defines["http"] = httpPackage{} From 30257fd547a0f218b9051d3b65c722ecb2a654b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=98=B8=EF=B8=8F?= <29265684+buffermet@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:43:48 +0100 Subject: [PATCH 4/6] misc --- js/data.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/data.go b/js/data.go index c3c2e164..346a0aa4 100644 --- a/js/data.go +++ b/js/data.go @@ -41,7 +41,7 @@ func textDecode(call otto.FunctionCall) otto.Value { if err != nil { return ReportError("textDecode: could not export argument value:", err.Error()) } - byteArr, ok := arg.([]byte) + byteArr, ok := arg.([]uint8) if !ok { return ReportError("textDecode: single argument must be of type []uint8.", argc) } From 243d3e701618026e7738fb0e58ed28c4a5186795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=98=B8=EF=B8=8F?= <29265684+buffermet@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:33:04 +0100 Subject: [PATCH 5/6] Fix error messages. --- js/data.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/data.go b/js/data.go index 346a0aa4..ad62f3a8 100644 --- a/js/data.go +++ b/js/data.go @@ -39,11 +39,11 @@ func textDecode(call otto.FunctionCall) otto.Value { arg, err := argv[0].Export() if err != nil { - return ReportError("textDecode: could not export argument value:", err.Error()) + return ReportError("textDecode: could not export argument value: %s", err.Error()) } byteArr, ok := arg.([]uint8) if !ok { - return ReportError("textDecode: single argument must be of type []uint8.", argc) + return ReportError("textDecode: single argument must be of type []uint8.") } decoded := string(byteArr) @@ -95,7 +95,7 @@ func atob(call otto.FunctionCall) otto.Value { v, err := otto.ToValue(string(decoded)) if err != nil { - return ReportError("atob: could not convert to string: %s", decoded) + return ReportError("atob: could not convert to string: %s", err.Error()) } return v From 1d7a49a952605c790ffb43b017fadc14235a1279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=98=B8=EF=B8=8F?= <29265684+buffermet@users.noreply.github.com> Date: Fri, 6 Dec 2024 17:09:27 +0100 Subject: [PATCH 6/6] misc --- js/data.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/data.go b/js/data.go index ad62f3a8..6fe48f22 100644 --- a/js/data.go +++ b/js/data.go @@ -85,7 +85,7 @@ func atob(call otto.FunctionCall) otto.Value { arg := argv[0] if (!arg.IsString()) { - return ReportError("btoa: single argument must be a string.") + return ReportError("atob: single argument must be a string.") } decoded, err := base64.StdEncoding.DecodeString(arg.String())