From b9f8de0857b921d797503d97d6b4228f8ba0d94a Mon Sep 17 00:00:00 2001 From: LEI Zongmin Date: Thu, 11 Jul 2024 21:41:29 +0800 Subject: [PATCH 1/2] Add support for registering import module callback functions in quickjs module --- internal/jsbuiltin/src/00_module.js | 21 +++++++++++++++++++++ internal/jsexecutor/jsexecutor.go | 11 ++++++++++- quickjs/quickjs.go | 17 ++++++++++++++--- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/internal/jsbuiltin/src/00_module.js b/internal/jsbuiltin/src/00_module.js index 5d49ae9..a542bf0 100644 --- a/internal/jsbuiltin/src/00_module.js +++ b/internal/jsbuiltin/src/00_module.js @@ -193,4 +193,25 @@ return module; require.cache = {}; jssh.require = require; jssh.requiremodule = requiremodule; + + const importModuleCallbacks = []; + + const registerImportModuleCallback = (callback) => { + if (typeof callback !== "function") { + throw new TypeError("callback must be a function"); + } + importModuleCallbacks.push(callback); + }; + + const callImportModuleCallbacks = (name, dir) => { + for (const callback of importModuleCallbacks) { + const result = callback(name, dir); + if (result) { + return result; + } + } + }; + + jssh.registerImportModuleCallback = registerImportModuleCallback; + jssh.callImportModuleCallbacks = callImportModuleCallbacks; } diff --git a/internal/jsexecutor/jsexecutor.go b/internal/jsexecutor/jsexecutor.go index fe4efd7..18b79b3 100644 --- a/internal/jsexecutor/jsexecutor.go +++ b/internal/jsexecutor/jsexecutor.go @@ -15,7 +15,9 @@ type JSFunction = func(ctx *JSContext, this JSValue, args []JSValue) JSValue // // NewJSRuntime 创建新的JSRuntime实例 func NewJSRuntime() JSRuntime { - return quickjs.NewRuntime() + runtime := quickjs.NewRuntime() + runtime.SetModuleLoader(moduleLoader) + return runtime } // IsGoFunction 判断是否为Go的函数类型 @@ -238,3 +240,10 @@ func anySliceToJSValue(ctx *quickjs.Context, v reflect.Value, vt reflect.Type) q } return arr } + +// RegisterModuleLoader 注册模块加载器 +func RegisterModuleLoader(loader func(ctx *JSContext, moduleName string) (string, error)) { + moduleLoader = loader +} + +var moduleLoader func(ctx *JSContext, moduleName string) (string, error) diff --git a/quickjs/quickjs.go b/quickjs/quickjs.go index deaebb6..d518d16 100644 --- a/quickjs/quickjs.go +++ b/quickjs/quickjs.go @@ -21,7 +21,8 @@ import ( import "C" type Runtime struct { - ref *C.JSRuntime + ref *C.JSRuntime + moduleLoader func(ctx *Context, moduleName string) (string, error) } func NewRuntime() Runtime { @@ -42,7 +43,17 @@ func (r Runtime) NewContext() *Context { C.JS_AddIntrinsicOperators(ref) C.JS_EnableBignumExt(ref, C.int(1)) - return &Context{ref: ref} + ctx := &Context{ref: ref} + + if r.moduleLoader != nil { + C.JS_SetModuleLoaderFunc(r.ref, nil, (*C.JSModuleLoaderFunc)(C.InvokeModuleLoader), unsafe.Pointer(ctx)) + } + + return ctx +} + +func (r *Runtime) SetModuleLoader(loader func(ctx *Context, moduleName string) (string, error)) { + r.moduleLoader = loader } func (r Runtime) ExecutePendingJob() (Context, error) { @@ -400,7 +411,7 @@ func (v Value) SetByInt64(idx int64, val Value) { } func (v Value) SetByUint32(idx uint32, val Value) { - C.JS_SetPropertyUint32(v.ctx.ref, v.ref, C.uint32_t(idx), val.ref) + C.JS_SetPropertyUint32(v.ctx.ref, v.ref, C.uint32_t(idx)) } func (v Value) Len() int64 { return v.Get("length").Int64() } From c7427c2d231d0a5b634720e341ebf4e2a16c4682 Mon Sep 17 00:00:00 2001 From: leizongmin Date: Thu, 11 Jul 2024 14:05:36 +0000 Subject: [PATCH 2/2] fix --- quickjs/quickjs.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/quickjs/quickjs.go b/quickjs/quickjs.go index d518d16..157f47a 100644 --- a/quickjs/quickjs.go +++ b/quickjs/quickjs.go @@ -21,8 +21,8 @@ import ( import "C" type Runtime struct { - ref *C.JSRuntime - moduleLoader func(ctx *Context, moduleName string) (string, error) + ref *C.JSRuntime + moduleLoader func(ctx *Context, moduleName string) (string, error) } func NewRuntime() Runtime { @@ -46,7 +46,16 @@ func (r Runtime) NewContext() *Context { ctx := &Context{ref: ref} if r.moduleLoader != nil { - C.JS_SetModuleLoaderFunc(r.ref, nil, (*C.JSModuleLoaderFunc)(C.InvokeModuleLoader), unsafe.Pointer(ctx)) + // typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx, const char *module_name, void *opaque); + moduleLoaderFunc := func(_ *C.JSContext, cModuleName *C.char, opaque unsafe.Pointer) *C.JSModuleDef { + moduleName := C.GoString(cModuleName) + source, err := r.moduleLoader(ctx, moduleName) + if err != nil { + panic(err) + } + return C.JS_Eval(ctx.ref, C.CString(source), C.size_t(len(source)), cModuleName, C.JS_EVAL_TYPE_MODULE) + } + C.JS_SetModuleLoaderFunc(r.ref, nil, *C.JSModuleLoaderFunc(moduleLoaderFunc), unsafe.Pointer(ctx)) } return ctx @@ -411,7 +420,7 @@ func (v Value) SetByInt64(idx int64, val Value) { } func (v Value) SetByUint32(idx uint32, val Value) { - C.JS_SetPropertyUint32(v.ctx.ref, v.ref, C.uint32_t(idx)) + C.JS_SetPropertyUint32(v.ctx.ref, v.ref, C.uint32_t(idx), val.ref) } func (v Value) Len() int64 { return v.Get("length").Int64() }