Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

thanks for you contributions~ #83

Open
chnwine opened this issue Apr 2, 2024 · 5 comments
Open

thanks for you contributions~ #83

chnwine opened this issue Apr 2, 2024 · 5 comments

Comments

@chnwine
Copy link

chnwine commented Apr 2, 2024

hi,

I'm looking for a goja http request library, and found you git fulfill my question very much. i read some code about http\promise\cookie, the code is beautiful and strong so that i think it's a pity too little star.

you code give me a lot help, make me save plenty time, if possible I am willing to pay you for a week of coffee or more.

thanks again

@shiroyk
Copy link
Owner

shiroyk commented Apr 3, 2024

Happy to know that my work could assist you. new branch ski hasn't been merged into the main branch yet. the branch has fixed some errors after the refactoring, and the license has been changed from AGPL to MIT.

@chnwine
Copy link
Author

chnwine commented Apr 4, 2024

amazing refactoring, you must take a lot of time for it.
it works in my project after two hours i try it.

next i will try some script in my project.

thanks for you job again

@chnwine
Copy link
Author

chnwine commented Apr 5, 2024

you are so diligent, i see you refactor lot of code every day. hope my attention not bother to you.

in the module name of 'js.VM', i wish has a method like RunModule, it dosn't call the 'default function' but call the name i given, in golang code excute js function It looks more complete and simple.

😊

@shiroyk
Copy link
Owner

shiroyk commented Apr 5, 2024

If you want to run a specific exported function, you can customize a method.

func RunModuleFunc(funcName, source string, args ...any) (ret goja.Value, err error) {
	vm, err := js.GetScheduler().Get()
	if err != nil {
		return nil, err
	}
	mod, err := vm.Loader().CompileModule("", source)
	if err != nil {
		return nil, err
	}

	rt := vm.Runtime()
	instance := rt.GetModuleInstance(mod)
	if instance == nil {
		if err = mod.Link(); err != nil {
			return nil, err
		}
		promise := rt.CyclicModuleRecordEvaluate(mod, vm.Loader().ResolveModule)
		if promise.State() == goja.PromiseStateRejected {
			return nil, promise.Result().Export().(error)
		}
		instance = rt.GetModuleInstance(mod)
	}
	value := instance.GetBindingValue(funcName)
	if value == nil {
		return nil, errors.New("function not found")
	}
	call, ok := goja.AssertFunction(value)
	if !ok {
		return nil, errors.New("export is not a function")
	}

	jsArgs := make([]goja.Value, len(args))
	for i, arg := range args {
		jsArgs[i] = rt.ToValue(arg)
	}

	ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second)
	defer cancelFunc()

	vm.Run(ctx, func() { ret, err = call(goja.Undefined(), jsArgs...) })

	return
}

func main() {
	ret, err := RunModuleFunc("sum", `exports.sum = (a, b) => a + b`, 1, 2)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(ret.Export())
}

@chnwine
Copy link
Author

chnwine commented Apr 5, 2024

If you want to run a specific exported function, you can customize a method.

func RunModuleFunc(funcName, source string, args ...any) (ret goja.Value, err error) {
	vm, err := js.GetScheduler().Get()
	if err != nil {
		return nil, err
	}
	mod, err := vm.Loader().CompileModule("", source)
	if err != nil {
		return nil, err
	}

	rt := vm.Runtime()
	instance := rt.GetModuleInstance(mod)
	if instance == nil {
		if err = mod.Link(); err != nil {
			return nil, err
		}
		promise := rt.CyclicModuleRecordEvaluate(mod, vm.Loader().ResolveModule)
		if promise.State() == goja.PromiseStateRejected {
			return nil, promise.Result().Export().(error)
		}
		instance = rt.GetModuleInstance(mod)
	}
	value := instance.GetBindingValue(funcName)
	if value == nil {
		return nil, errors.New("function not found")
	}
	call, ok := goja.AssertFunction(value)
	if !ok {
		return nil, errors.New("export is not a function")
	}

	jsArgs := make([]goja.Value, len(args))
	for i, arg := range args {
		jsArgs[i] = rt.ToValue(arg)
	}

	ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second)
	defer cancelFunc()

	vm.Run(ctx, func() { ret, err = call(goja.Undefined(), jsArgs...) })

	return
}

func main() {
	ret, err := RunModuleFunc("sum", `exports.sum = (a, b) => a + b`, 1, 2)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(ret.Export())
}

actually i did it as you code, I am deeply grateful for your help. 😊

func callScript(script string, method string, args goja.Value) (ret goja.Value, err error) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Minute*10)
	ctx = ski.NewContext(ctx, nil)
	defer cancel()

	vm, _ := js.GetScheduler().Get()
	mapper := goja.TagFieldNameMapper("json", true)
	vm.Runtime().SetFieldNameMapper(mapper)
	module, err := vm.Loader().CompileModule("js", script)
	if err != nil {
		return nil, err
	}

	opts := &slog.HandlerOptions{Level: slog.LevelDebug}
	handler := slog.NewTextHandler(os.Stdout, opts)
	logger := ski.WithLogger(ctx, slog.New(handler))

	vm.Run(logger, func() {
		instance := vm.Runtime().GetModuleInstance(module)
		if instance == nil {
			if err = module.Link(); err != nil {
				return
			}
			resolve := vm.Loader().ResolveModule
			promise := vm.Runtime().CyclicModuleRecordEvaluate(module, resolve)
			switch promise.State() {
			case goja.PromiseStateRejected:
				err = promise.Result().Export().(error)
				return
			}
			instance = vm.Runtime().GetModuleInstance(module)
		}
		if !slice.Contain(module.GetExportedNames(), method) {
			err = fmt.Errorf("module not export %s function", method)
		}

		var call goja.Callable
		value, ok := instance.GetBindingValue(method), false
		if call, ok = goja.AssertFunction(value); !ok {
			err = fmt.Errorf("export name %s is not function", method)
		}
		if ret, err = call(args, vm.Context()); err != nil {
			err = fmt.Errorf("call method %s error: %s ", method, err)
		}
	})
	return
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants