backported JSVM toString

This commit is contained in:
Gani Georgiev
2024-10-18 16:32:43 +03:00
parent e18ea88113
commit cffbe83399
4 changed files with 6550 additions and 6463 deletions
+28
View File
@@ -301,6 +301,34 @@ func baseBinds(vm *goja.Runtime) {
return string(bodyBytes), nil return string(bodyBytes), nil
}) })
vm.Set("toString", func(raw any, maxReaderBytes int) (string, error) {
switch v := raw.(type) {
case io.Reader:
if maxReaderBytes == 0 {
maxReaderBytes = rest.DefaultMaxMemory
}
limitReader := io.LimitReader(v, int64(maxReaderBytes))
bodyBytes, readErr := io.ReadAll(limitReader)
if readErr != nil {
return "", readErr
}
return string(bodyBytes), nil
default:
str, err := cast.ToStringE(v)
if err == nil {
return str, nil
}
// as a last attempt try to json encode the value
rawBytes, _ := json.Marshal(raw)
return string(rawBytes), nil
}
})
vm.Set("sleep", func(milliseconds int64) { vm.Set("sleep", func(milliseconds int64) {
time.Sleep(time.Duration(milliseconds) * time.Millisecond) time.Sleep(time.Duration(milliseconds) * time.Millisecond)
}) })
+36 -1
View File
@@ -47,7 +47,7 @@ func TestBaseBindsCount(t *testing.T) {
vm := goja.New() vm := goja.New()
baseBinds(vm) baseBinds(vm)
testBindsCount(vm, "this", 17, t) testBindsCount(vm, "this", 18, t)
} }
func TestBaseBindsSleep(t *testing.T) { func TestBaseBindsSleep(t *testing.T) {
@@ -92,6 +92,41 @@ func TestBaseBindsReaderToString(t *testing.T) {
} }
} }
func TestBaseBindsToString(t *testing.T) {
vm := goja.New()
baseBinds(vm)
vm.Set("scenarios", []struct {
Name string
Value any
Expected string
}{
{"null", nil, ""},
{"string", "test", "test"},
{"number", -12.4, "-12.4"},
{"bool", true, "true"},
{"arr", []int{1, 2, 3}, `[1,2,3]`},
{"obj", map[string]any{"test": 123}, `{"test":123}`},
{"reader", strings.NewReader("test"), "test"},
{"struct", struct {
Name string
private string
}{Name: "123", private: "456"}, `{"Name":"123"}`},
})
_, err := vm.RunString(`
for (let s of scenarios) {
let result = toString(s.value)
if (result != s.expected) {
throw new Error('[' + s.name + '] Expected string ' + s.expected + ', got ' + result);
}
}
`)
if err != nil {
t.Fatal(err)
}
}
func TestBaseBindsCookie(t *testing.T) { func TestBaseBindsCookie(t *testing.T) {
app, _ := tests.NewTestApp() app, _ := tests.NewTestApp()
defer app.Cleanup() defer app.Cleanup()
File diff suppressed because it is too large Load Diff
+19 -7
View File
@@ -194,22 +194,34 @@ declare var $app: PocketBase
declare var $template: template.Registry declare var $template: template.Registry
/** /**
* readerToString reads the content of the specified io.Reader until * This method is superseded by toString.
* EOF or maxBytes are reached.
* *
* If maxBytes is not specified it will read up to 32MB. * @deprecated
* @group PocketBase
*/
declare function readerToString(reader: any, maxBytes?: number): string;
/**
* toString stringifies the specified value.
* *
* Note that after this call the reader can't be used anymore. * Support optional second maxBytes argument to limit the max read bytes
* when the value is a io.Reader (default to 32MB).
*
* Types that don't have explicit string representation are json serialized.
* *
* Example: * Example:
* *
* ` + "```" + `js * ` + "```" + `js
* const rawBody = readerToString(c.request().body) * // io.Reader
* const ex1 = toString(e.request.body)
*
* // slice of bytes ("hello")
* const ex2 = toString([104 101 108 108 111])
* ` + "```" + ` * ` + "```" + `
* *
* @group PocketBase * @group PocketBase
*/ */
declare function readerToString(reader: any, maxBytes?: number): string; declare function toString(val: any, maxBytes?: number): string;
/** /**
* sleep pauses the current goroutine for at least the specified user duration (in ms). * sleep pauses the current goroutine for at least the specified user duration (in ms).
@@ -713,7 +725,7 @@ declare namespace $os {
* const cmd = $os.cmd('ls', '-sl') * const cmd = $os.cmd('ls', '-sl')
* *
* // execute the command and return its standard output as string * // execute the command and return its standard output as string
* const output = String.fromCharCode(...cmd.output()); * const output = toString(cmd.output());
* ` + "```" + ` * ` + "```" + `
*/ */
export let cmd: exec.command export let cmd: exec.command