wip rename
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
package builtin
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package builtin
|
package functions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package builtin
|
package functions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -18,21 +18,21 @@ func (t TestArgs) Validate() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAsyncBuiltin(t *testing.T) {
|
func TestAsyncFunction(t *testing.T) {
|
||||||
RegisterAsyncBuiltin("testAsync", func(_ context.Context, args TestArgs) (string, error) {
|
RegisterAsyncFunction("testAsync", func(_ context.Context, args TestArgs) (string, error) {
|
||||||
return "result: " + args.Field1, nil
|
return "result: " + args.Field1, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
registryMutex.RLock()
|
registryMutex.RLock()
|
||||||
builtin, ok := builtinRegistry["testAsync"]
|
fn, ok := functionRegistry["testAsync"]
|
||||||
registryMutex.RUnlock()
|
registryMutex.RUnlock()
|
||||||
|
|
||||||
require.True(t, ok, "testAsync should be registered")
|
require.True(t, ok, "testAsync should be registered")
|
||||||
assert.Contains(t, builtin.Definition(), "Promise<string>", "definition should include Promise<string>")
|
assert.Contains(t, fn.Definition(), "Promise<string>", "definition should include Promise<string>")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAsyncBuiltinResolution(t *testing.T) {
|
func TestAsyncFunctionResolution(t *testing.T) {
|
||||||
RegisterAsyncBuiltin("resolveTest", func(_ context.Context, args TestArgs) (string, error) {
|
RegisterAsyncFunction("resolveTest", func(_ context.Context, args TestArgs) (string, error) {
|
||||||
return "test-result", nil
|
return "test-result", nil
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -43,15 +43,15 @@ func TestAsyncBuiltinResolution(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
vm.SetCanBlock(true)
|
vm.SetCanBlock(true)
|
||||||
|
|
||||||
RegisterBuiltins(context.Background(), vm)
|
RegisterFunctions(context.Background(), vm)
|
||||||
|
|
||||||
result, err := vm.Eval(`resolveTest("hello")`, quickjs.EvalGlobal)
|
result, err := vm.Eval(`resolveTest("hello")`, quickjs.EvalGlobal)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, result)
|
assert.NotNil(t, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAsyncBuiltinRejection(t *testing.T) {
|
func TestAsyncFunctionRejection(t *testing.T) {
|
||||||
RegisterAsyncBuiltin("rejectTest", func(_ context.Context, args TestArgs) (string, error) {
|
RegisterAsyncFunction("rejectTest", func(_ context.Context, args TestArgs) (string, error) {
|
||||||
return "", assert.AnError
|
return "", assert.AnError
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ func TestAsyncBuiltinRejection(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
vm.SetCanBlock(true)
|
vm.SetCanBlock(true)
|
||||||
|
|
||||||
RegisterBuiltins(context.Background(), vm)
|
RegisterFunctions(context.Background(), vm)
|
||||||
|
|
||||||
result, err := vm.Eval(`rejectTest({field1: "hello"})`, quickjs.EvalGlobal)
|
result, err := vm.Eval(`rejectTest({field1: "hello"})`, quickjs.EvalGlobal)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -70,7 +70,7 @@ func TestAsyncBuiltinRejection(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNonPromise(t *testing.T) {
|
func TestNonPromise(t *testing.T) {
|
||||||
RegisterBuiltin("nonPromiseTest", func(_ context.Context, args TestArgs) (string, error) {
|
RegisterFunction("nonPromiseTest", func(_ context.Context, args TestArgs) (string, error) {
|
||||||
return "sync-result", nil
|
return "sync-result", nil
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ func TestNonPromise(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
vm.SetCanBlock(true)
|
vm.SetCanBlock(true)
|
||||||
|
|
||||||
RegisterBuiltins(context.Background(), vm)
|
RegisterFunctions(context.Background(), vm)
|
||||||
|
|
||||||
result, err := vm.Eval(`nonPromiseTest({field1: "hello"})`, quickjs.EvalGlobal)
|
result, err := vm.Eval(`nonPromiseTest({field1: "hello"})`, quickjs.EvalGlobal)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package builtin
|
package functions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -8,12 +8,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
builtinRegistry = make(map[string]Builtin)
|
functionRegistry = make(map[string]Function)
|
||||||
registryMutex sync.RWMutex
|
registryMutex sync.RWMutex
|
||||||
collector *typeCollector
|
collector *typeCollector
|
||||||
)
|
)
|
||||||
|
|
||||||
func registerBuiltin[A Args, R any](name string, isAsync bool, fn Func[A, R]) {
|
func registerFunction[A Args, R any](name string, isAsync bool, fn RawFunc[A, R]) {
|
||||||
registryMutex.Lock()
|
registryMutex.Lock()
|
||||||
defer registryMutex.Unlock()
|
defer registryMutex.Unlock()
|
||||||
|
|
||||||
@@ -23,14 +23,14 @@ func registerBuiltin[A Args, R any](name string, isAsync bool, fn Func[A, R]) {
|
|||||||
|
|
||||||
tType := reflect.TypeFor[A]()
|
tType := reflect.TypeFor[A]()
|
||||||
if tType.Kind() != reflect.Struct {
|
if tType.Kind() != reflect.Struct {
|
||||||
panic(fmt.Sprintf("builtin %s: argument must be a struct type, got %v", name, tType))
|
panic(fmt.Sprintf("function %s: argument must be a struct type, got %v", name, tType))
|
||||||
}
|
}
|
||||||
|
|
||||||
fnType := reflect.TypeOf(fn)
|
fnType := reflect.TypeOf(fn)
|
||||||
types := collector.collectTypes(tType, fnType)
|
types := collector.collectTypes(tType, fnType)
|
||||||
paramTypes := collector.getParamTypes()
|
paramTypes := collector.getParamTypes()
|
||||||
|
|
||||||
builtinRegistry[name] = &builtinImpl[A, R]{
|
functionRegistry[name] = &functionImpl[A, R]{
|
||||||
name: name,
|
name: name,
|
||||||
fn: fn,
|
fn: fn,
|
||||||
types: types,
|
types: types,
|
||||||
@@ -38,7 +38,7 @@ func registerBuiltin[A Args, R any](name string, isAsync bool, fn Func[A, R]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetBuiltinsDeclarations() string {
|
func GetFunctionDeclarations() string {
|
||||||
registryMutex.RLock()
|
registryMutex.RLock()
|
||||||
defer registryMutex.RUnlock()
|
defer registryMutex.RUnlock()
|
||||||
|
|
||||||
@@ -46,14 +46,14 @@ func GetBuiltinsDeclarations() string {
|
|||||||
var typeDefs []string
|
var typeDefs []string
|
||||||
var functionDecls []string
|
var functionDecls []string
|
||||||
|
|
||||||
for _, builtin := range builtinRegistry {
|
for _, fn := range functionRegistry {
|
||||||
for _, t := range builtin.Types() {
|
for _, t := range fn.Types() {
|
||||||
if !typeDefinitions[t] {
|
if !typeDefinitions[t] {
|
||||||
typeDefinitions[t] = true
|
typeDefinitions[t] = true
|
||||||
typeDefs = append(typeDefs, t)
|
typeDefs = append(typeDefs, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
functionDecls = append(functionDecls, builtin.Definition())
|
functionDecls = append(functionDecls, fn.Definition())
|
||||||
}
|
}
|
||||||
|
|
||||||
result := strings.Join(typeDefs, "\n\n")
|
result := strings.Join(typeDefs, "\n\n")
|
||||||
@@ -65,14 +65,14 @@ func GetBuiltinsDeclarations() string {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterBuiltin[T Args, R any](name string, fn Func[T, R]) {
|
func GetRegisteredFunctions() map[string]Function {
|
||||||
registerBuiltin(name, false, fn)
|
return functionRegistry
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterAsyncBuiltin[T Args, R any](name string, fn Func[T, R]) {
|
func RegisterFunction[T Args, R any](name string, fn RawFunc[T, R]) {
|
||||||
registerBuiltin(name, true, fn)
|
registerFunction(name, false, fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetBuiltins() map[string]Builtin {
|
func RegisterAsyncFunction[T Args, R any](name string, fn RawFunc[T, R]) {
|
||||||
return builtinRegistry
|
registerFunction(name, true, fn)
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package builtin
|
package functions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -6,39 +6,39 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Builtin interface {
|
type Function interface {
|
||||||
Name() string
|
Name() string
|
||||||
Types() []string
|
Types() []string
|
||||||
Definition() string
|
Definition() string
|
||||||
WrapFn(context.Context) func(...any) (any, error)
|
WrapFn(context.Context) func(...any) (any, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Func[A Args, R any] func(ctx context.Context, args A) (R, error)
|
type RawFunc[A Args, R any] func(context.Context, A) (R, error)
|
||||||
|
|
||||||
type Args interface {
|
type Args interface {
|
||||||
Validate() error
|
Validate() error
|
||||||
}
|
}
|
||||||
|
|
||||||
type builtinImpl[A Args, R any] struct {
|
type functionImpl[A Args, R any] struct {
|
||||||
name string
|
name string
|
||||||
fn Func[A, R]
|
fn RawFunc[A, R]
|
||||||
definition string
|
definition string
|
||||||
types []string
|
types []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *builtinImpl[A, R]) Name() string {
|
func (b *functionImpl[A, R]) Name() string {
|
||||||
return b.name
|
return b.name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *builtinImpl[A, R]) Types() []string {
|
func (b *functionImpl[A, R]) Types() []string {
|
||||||
return b.types
|
return b.types
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *builtinImpl[A, R]) Definition() string {
|
func (b *functionImpl[A, R]) Definition() string {
|
||||||
return b.definition
|
return b.definition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *builtinImpl[A, R]) WrapFn(ctx context.Context) func(...any) (any, error) {
|
func (b *functionImpl[A, R]) WrapFn(ctx context.Context) func(...any) (any, error) {
|
||||||
return func(allArgs ...any) (any, error) {
|
return func(allArgs ...any) (any, error) {
|
||||||
// Populate Arguments
|
// Populate Arguments
|
||||||
var fnArgs A
|
var fnArgs A
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package builtin
|
package functions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package builtin
|
package functions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -18,11 +18,11 @@ func (t TestBasicArgs) Validate() error { return nil }
|
|||||||
|
|
||||||
func TestBasicType(t *testing.T) {
|
func TestBasicType(t *testing.T) {
|
||||||
resetRegistry()
|
resetRegistry()
|
||||||
RegisterBuiltin[TestBasicArgs, string]("basic", func(ctx context.Context, args TestBasicArgs) (string, error) {
|
RegisterFunction[TestBasicArgs, string]("basic", func(ctx context.Context, args TestBasicArgs) (string, error) {
|
||||||
return args.Name, nil
|
return args.Name, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
defs := GetBuiltinsDeclarations()
|
defs := GetFunctionDeclarations()
|
||||||
assert.Contains(t, defs, "declare function basic(name: string, age: number): string;")
|
assert.Contains(t, defs, "declare function basic(name: string, age: number): string;")
|
||||||
assert.Contains(t, defs, "interface TestBasicArgs")
|
assert.Contains(t, defs, "interface TestBasicArgs")
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ func TestBasicType(t *testing.T) {
|
|||||||
func resetRegistry() {
|
func resetRegistry() {
|
||||||
registryLock.Lock()
|
registryLock.Lock()
|
||||||
defer registryLock.Unlock()
|
defer registryLock.Unlock()
|
||||||
builtinRegistry = make(map[string]Builtin)
|
functionRegistry = make(map[string]Function)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -47,11 +47,11 @@ func (t TestComplexArgs) Validate() error { return nil }
|
|||||||
|
|
||||||
func TestComplexTypes(t *testing.T) {
|
func TestComplexTypes(t *testing.T) {
|
||||||
resetRegistry()
|
resetRegistry()
|
||||||
RegisterBuiltin[TestComplexArgs, bool]("complex", func(ctx context.Context, args TestComplexArgs) (bool, error) {
|
RegisterFunction[TestComplexArgs, bool]("complex", func(ctx context.Context, args TestComplexArgs) (bool, error) {
|
||||||
return args.Flag, nil
|
return args.Flag, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
defs := GetBuiltinsDeclarations()
|
defs := GetFunctionDeclarations()
|
||||||
assert.Contains(t, defs, "declare function complex(items: number[], data: Record<string, any>, flag: boolean): boolean;")
|
assert.Contains(t, defs, "declare function complex(items: number[], data: Record<string, any>, flag: boolean): boolean;")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,11 +66,11 @@ func (t TestNestedArgs) Validate() error { return nil }
|
|||||||
|
|
||||||
func TestNestedStruct(t *testing.T) {
|
func TestNestedStruct(t *testing.T) {
|
||||||
resetRegistry()
|
resetRegistry()
|
||||||
RegisterBuiltin[TestNestedArgs, string]("nested", func(ctx context.Context, args TestNestedArgs) (string, error) {
|
RegisterFunction[TestNestedArgs, string]("nested", func(ctx context.Context, args TestNestedArgs) (string, error) {
|
||||||
return args.User.FirstName, nil
|
return args.User.FirstName, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
defs := GetBuiltinsDeclarations()
|
defs := GetFunctionDeclarations()
|
||||||
assert.Contains(t, defs, "declare function nested(user: {}): string;")
|
assert.Contains(t, defs, "declare function nested(user: {}): string;")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,11 +84,11 @@ func (t TestOptionalArgs) Validate() error { return nil }
|
|||||||
|
|
||||||
func TestOptionalFields(t *testing.T) {
|
func TestOptionalFields(t *testing.T) {
|
||||||
resetRegistry()
|
resetRegistry()
|
||||||
RegisterBuiltin[TestOptionalArgs, string]("optional", func(ctx context.Context, args TestOptionalArgs) (string, error) {
|
RegisterFunction[TestOptionalArgs, string]("optional", func(ctx context.Context, args TestOptionalArgs) (string, error) {
|
||||||
return args.Name, nil
|
return args.Name, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
defs := GetBuiltinsDeclarations()
|
defs := GetFunctionDeclarations()
|
||||||
assert.Contains(t, defs, "declare function optional(name: string, age?: number | null, score?: number | null): string;")
|
assert.Contains(t, defs, "declare function optional(name: string, age?: number | null, score?: number | null): string;")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,11 +105,11 @@ func (t TestResultArgs) Validate() error { return nil }
|
|||||||
|
|
||||||
func TestResultStruct(t *testing.T) {
|
func TestResultStruct(t *testing.T) {
|
||||||
resetRegistry()
|
resetRegistry()
|
||||||
RegisterBuiltin[TestResultArgs, TestResult]("result", func(ctx context.Context, args TestResultArgs) (TestResult, error) {
|
RegisterFunction[TestResultArgs, TestResult]("result", func(ctx context.Context, args TestResultArgs) (TestResult, error) {
|
||||||
return TestResult{ID: 1}, nil
|
return TestResult{ID: 1}, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
defs := GetBuiltinsDeclarations()
|
defs := GetFunctionDeclarations()
|
||||||
assert.Contains(t, defs, "declare function result(input: string): TestResult;")
|
assert.Contains(t, defs, "declare function result(input: string): TestResult;")
|
||||||
assert.Contains(t, defs, "interface TestResult {id: number; data: number[]}")
|
assert.Contains(t, defs, "interface TestResult {id: number; data: number[]}")
|
||||||
}
|
}
|
||||||
@@ -126,11 +126,11 @@ type TestAsyncResult struct {
|
|||||||
|
|
||||||
func TestAsyncPromise(t *testing.T) {
|
func TestAsyncPromise(t *testing.T) {
|
||||||
resetRegistry()
|
resetRegistry()
|
||||||
RegisterAsyncBuiltin[TestAsyncArgs, *TestAsyncStatus]("async", func(ctx context.Context, args TestAsyncArgs) (*TestAsyncStatus, error) {
|
RegisterAsyncFunction[TestAsyncArgs, *TestAsyncStatus]("async", func(ctx context.Context, args TestAsyncArgs) (*TestAsyncStatus, error) {
|
||||||
return &TestAsyncStatus{Code: 200}, nil
|
return &TestAsyncStatus{Code: 200}, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
defs := GetBuiltinsDeclarations()
|
defs := GetFunctionDeclarations()
|
||||||
assert.Contains(t, defs, "declare function async(url: string): Promise<TestAsyncStatus | null>;")
|
assert.Contains(t, defs, "declare function async(url: string): Promise<TestAsyncStatus | null>;")
|
||||||
assert.Contains(t, defs, "interface TestAsyncStatus")
|
assert.Contains(t, defs, "interface TestAsyncStatus")
|
||||||
}
|
}
|
||||||
@@ -151,11 +151,11 @@ func (t TestNestedPointerArgs) Validate() error { return nil }
|
|||||||
|
|
||||||
func TestNestedPointerInResult(t *testing.T) {
|
func TestNestedPointerInResult(t *testing.T) {
|
||||||
resetRegistry()
|
resetRegistry()
|
||||||
RegisterBuiltin[TestNestedPointerArgs, *TestNestedPointerResult]("pointerResult", func(ctx context.Context, args TestNestedPointerArgs) (*TestNestedPointerResult, error) {
|
RegisterFunction[TestNestedPointerArgs, *TestNestedPointerResult]("pointerResult", func(ctx context.Context, args TestNestedPointerArgs) (*TestNestedPointerResult, error) {
|
||||||
return &TestNestedPointerResult{Value: "test"}, nil
|
return &TestNestedPointerResult{Value: "test"}, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
defs := GetBuiltinsDeclarations()
|
defs := GetFunctionDeclarations()
|
||||||
assert.Contains(t, defs, "declare function pointerResult(id: number): TestNestedPointerResult | null;")
|
assert.Contains(t, defs, "declare function pointerResult(id: number): TestNestedPointerResult | null;")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,11 +167,11 @@ func (t TestUintArgs) Validate() error { return nil }
|
|||||||
|
|
||||||
func TestUintType(t *testing.T) {
|
func TestUintType(t *testing.T) {
|
||||||
resetRegistry()
|
resetRegistry()
|
||||||
RegisterBuiltin[TestUintArgs, uint]("uint", func(ctx context.Context, args TestUintArgs) (uint, error) {
|
RegisterFunction[TestUintArgs, uint]("uint", func(ctx context.Context, args TestUintArgs) (uint, error) {
|
||||||
return args.Value, nil
|
return args.Value, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
defs := GetBuiltinsDeclarations()
|
defs := GetFunctionDeclarations()
|
||||||
assert.Contains(t, defs, "declare function uint(value: number): number;")
|
assert.Contains(t, defs, "declare function uint(value: number): number;")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,11 +183,11 @@ func (t TestFloatArgs) Validate() error { return nil }
|
|||||||
|
|
||||||
func TestFloatType(t *testing.T) {
|
func TestFloatType(t *testing.T) {
|
||||||
resetRegistry()
|
resetRegistry()
|
||||||
RegisterBuiltin[TestFloatArgs, float32]("float", func(ctx context.Context, args TestFloatArgs) (float32, error) {
|
RegisterFunction[TestFloatArgs, float32]("float", func(ctx context.Context, args TestFloatArgs) (float32, error) {
|
||||||
return float32(args.Amount), nil
|
return float32(args.Amount), nil
|
||||||
})
|
})
|
||||||
|
|
||||||
defs := GetBuiltinsDeclarations()
|
defs := GetFunctionDeclarations()
|
||||||
assert.Contains(t, defs, "declare function float(amount: number): number;")
|
assert.Contains(t, defs, "declare function float(amount: number): number;")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,11 +201,11 @@ func (t TestPointerInArgs) Validate() error { return nil }
|
|||||||
|
|
||||||
func TestNestedPointerStruct(t *testing.T) {
|
func TestNestedPointerStruct(t *testing.T) {
|
||||||
resetRegistry()
|
resetRegistry()
|
||||||
RegisterBuiltin[TestPointerInArgs, string]("nestedPointer", func(ctx context.Context, args TestPointerInArgs) (string, error) {
|
RegisterFunction[TestPointerInArgs, string]("nestedPointer", func(ctx context.Context, args TestPointerInArgs) (string, error) {
|
||||||
return "test", nil
|
return "test", nil
|
||||||
})
|
})
|
||||||
|
|
||||||
defs := GetBuiltinsDeclarations()
|
defs := GetFunctionDeclarations()
|
||||||
assert.Contains(t, defs, "declare function nestedPointer(user?: {} | null): string;")
|
assert.Contains(t, defs, "declare function nestedPointer(user?: {} | null): string;")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,11 +217,11 @@ func (t TestErrorOnlyArgs) Validate() error { return nil }
|
|||||||
|
|
||||||
func TestErrorOnlyReturn(t *testing.T) {
|
func TestErrorOnlyReturn(t *testing.T) {
|
||||||
resetRegistry()
|
resetRegistry()
|
||||||
RegisterBuiltin[TestErrorOnlyArgs, struct{}]("errorOnly", func(ctx context.Context, args TestErrorOnlyArgs) (struct{}, error) {
|
RegisterFunction[TestErrorOnlyArgs, struct{}]("errorOnly", func(ctx context.Context, args TestErrorOnlyArgs) (struct{}, error) {
|
||||||
return struct{}{}, nil
|
return struct{}{}, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
defs := GetBuiltinsDeclarations()
|
defs := GetFunctionDeclarations()
|
||||||
assert.Contains(t, defs, "declare function errorOnly(input: string): {};")
|
assert.Contains(t, defs, "declare function errorOnly(input: string): {};")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/evanw/esbuild/pkg/api"
|
"github.com/evanw/esbuild/pkg/api"
|
||||||
"modernc.org/quickjs"
|
"modernc.org/quickjs"
|
||||||
"reichard.io/poiesis/internal/builtin"
|
"reichard.io/poiesis/internal/functions"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Runtime struct {
|
type Runtime struct {
|
||||||
@@ -59,7 +59,7 @@ func (r *Runtime) populateGlobals() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register Custom Functions
|
// Register Custom Functions
|
||||||
for name, builtin := range builtin.GetBuiltins() {
|
for name, builtin := range functions.GetRegisteredFunctions() {
|
||||||
// Register Main Function
|
// Register Main Function
|
||||||
if err := r.vm.RegisterFunc(name, builtin.WrapFn(r.ctx), false); err != nil {
|
if err := r.vm.RegisterFunc(name, builtin.WrapFn(r.ctx), false); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
package standard
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"modernc.org/quickjs"
|
|
||||||
|
|
||||||
"reichard.io/poiesis/internal/builtin"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFetchReturnsPromise(t *testing.T) {
|
|
||||||
vm, err := quickjs.NewVM()
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer func() {
|
|
||||||
_ = vm.Close()
|
|
||||||
}()
|
|
||||||
vm.SetCanBlock(true)
|
|
||||||
|
|
||||||
builtin.RegisterBuiltins(context.Background(), vm)
|
|
||||||
|
|
||||||
result, err := vm.Eval(`fetch({input: "https://example.com"})`, quickjs.EvalGlobal)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.NotNil(t, result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFetchAsyncAwait(t *testing.T) {
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
_, _ = w.Write([]byte(`{"status":"ok"}`))
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
vm, err := quickjs.NewVM()
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer func() {
|
|
||||||
_ = vm.Close()
|
|
||||||
}()
|
|
||||||
vm.SetCanBlock(true)
|
|
||||||
|
|
||||||
builtin.RegisterBuiltins(context.Background(), vm)
|
|
||||||
|
|
||||||
result, err := vm.Eval(`fetch({input: "`+server.URL+`"})`, quickjs.EvalGlobal)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
if obj, ok := result.(*quickjs.Object); ok {
|
|
||||||
var arr []any
|
|
||||||
if err := obj.Into(&arr); err == nil && len(arr) > 0 {
|
|
||||||
if response, ok := arr[0].(map[string]any); ok {
|
|
||||||
assert.True(t, response["ok"].(bool))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package standard
|
package stdlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -8,9 +8,13 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"reichard.io/poiesis/internal/builtin"
|
"reichard.io/poiesis/internal/functions"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
functions.RegisterAsyncFunction("fetch", Fetch)
|
||||||
|
}
|
||||||
|
|
||||||
type FetchArgs struct {
|
type FetchArgs struct {
|
||||||
Input string `json:"input"`
|
Input string `json:"input"`
|
||||||
Init *RequestInit `json:"init,omitempty"`
|
Init *RequestInit `json:"init,omitempty"`
|
||||||
@@ -106,17 +110,3 @@ func Fetch(_ context.Context, args FetchArgs) (Response, error) {
|
|||||||
Headers: resultHeaders,
|
Headers: resultHeaders,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Add(_ context.Context, args AddArgs) (int, error) {
|
|
||||||
return args.A + args.B, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Greet(_ context.Context, args GreetArgs) (string, error) {
|
|
||||||
return fmt.Sprintf("Hello, %s!", args.Name), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
builtin.RegisterAsyncBuiltin("fetch", Fetch)
|
|
||||||
builtin.RegisterBuiltin("add", Add)
|
|
||||||
builtin.RegisterBuiltin("greet", Greet)
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package standard
|
package stdlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"modernc.org/quickjs"
|
||||||
|
"reichard.io/poiesis/internal/functions"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFetch(t *testing.T) {
|
func TestFetch(t *testing.T) {
|
||||||
@@ -97,24 +99,47 @@ func TestFetchDefaults(t *testing.T) {
|
|||||||
assert.True(t, result.OK)
|
assert.True(t, result.OK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAdd(t *testing.T) {
|
func TestFetchReturnsPromise(t *testing.T) {
|
||||||
ctx := context.Background()
|
vm, err := quickjs.NewVM()
|
||||||
result, err := Add(ctx, AddArgs{A: 5, B: 10})
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 15, result)
|
defer func() {
|
||||||
|
_ = vm.Close()
|
||||||
|
}()
|
||||||
|
vm.SetCanBlock(true)
|
||||||
|
|
||||||
result, err = Add(ctx, AddArgs{A: -3, B: 7})
|
functions.RegisterBuiltins(context.Background(), vm)
|
||||||
|
|
||||||
|
result, err := vm.Eval(`fetch({input: "https://example.com"})`, quickjs.EvalGlobal)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 4, result)
|
assert.NotNil(t, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGreet(t *testing.T) {
|
func TestFetchAsyncAwait(t *testing.T) {
|
||||||
ctx := context.Background()
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
result, err := Greet(ctx, GreetArgs{Name: "World"})
|
w.Header().Set("Content-Type", "application/json")
|
||||||
require.NoError(t, err)
|
w.WriteHeader(http.StatusOK)
|
||||||
assert.Equal(t, "Hello, World!", result)
|
_, _ = w.Write([]byte(`{"status":"ok"}`))
|
||||||
|
}))
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
result, err = Greet(ctx, GreetArgs{Name: "Alice"})
|
vm, err := quickjs.NewVM()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "Hello, Alice!", result)
|
defer func() {
|
||||||
|
_ = vm.Close()
|
||||||
|
}()
|
||||||
|
vm.SetCanBlock(true)
|
||||||
|
|
||||||
|
functions.RegisterBuiltins(context.Background(), vm)
|
||||||
|
|
||||||
|
result, err := vm.Eval(`fetch({input: "`+server.URL+`"})`, quickjs.EvalGlobal)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if obj, ok := result.(*quickjs.Object); ok {
|
||||||
|
var arr []any
|
||||||
|
if err := obj.Into(&arr); err == nil && len(arr) > 0 {
|
||||||
|
if response, ok := arr[0].(map[string]any); ok {
|
||||||
|
assert.True(t, response["ok"].(bool))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user