mirror of
https://github.com/pocketbase/pocketbase.git
synced 2026-09-08 23:50:47 +02:00
backported JSVM toString
This commit is contained in:
@@ -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)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
+6467
-6455
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user