public void EvalSource(string source, string filename) { if (filename == null) { filename = "eval"; } if (string.IsNullOrEmpty(source)) { return; } var ctx = _ctx.rawValue; DuktapeDLL.duk_push_string(ctx, source); DuktapeDLL.duk_push_string(ctx, filename); if (DuktapeDLL.duk_pcompile(ctx, 0) != 0) { DuktapeAux.PrintError(ctx, -1, filename); DuktapeDLL.duk_pop(ctx); } else { // Debug.LogFormat("check top {0}", DuktapeDLL.duk_get_top(ctx)); if (DuktapeDLL.duk_pcall(ctx, 0) != DuktapeDLL.DUK_EXEC_SUCCESS) { DuktapeAux.PrintError(ctx, -1, filename); } DuktapeDLL.duk_pop(ctx); // Debug.LogFormat("check top {0}", DuktapeDLL.duk_get_top(ctx)); } }
public static bool duk_get_type(IntPtr ctx, int idx, out Type o) { if (DuktapeDLL.duk_is_string(ctx, idx)) { var name = DuktapeDLL.duk_get_string(ctx, idx); o = DuktapeAux.GetType(name); return(o != null); } else { uint refid_t; //TODO: 增加一个隐藏属性记录jsobject对应类型 (constructor, object) if (DuktapeDLL.duk_unity_get_type_refid(ctx, idx, out refid_t)) { var vm = DuktapeVM.GetVM(ctx); o = vm.GetExportedType(refid_t); // Debug.Log($"get type from exported registry {o}:{refid}"); return(o != null); } else { int refid; if (DuktapeDLL.duk_unity_get_refid(ctx, idx, out refid)) { var cache = DuktapeVM.GetObjectCache(ctx); cache.TryGetTypedObject(refid, out o); // Debug.Log($"get type from objectcache registry {o}:{refid}"); return(o != null); } } } o = null; return(false); }
private static duk_ret_t cb_load_module(IntPtr ctx) { var module_id = DuktapeAux.duk_require_string(ctx, 0); DuktapeDLL.duk_get_prop_string(ctx, 2, "filename"); var filename = DuktapeAux.duk_require_string(ctx, -1); var source = GetVM(ctx)._fileResolver.ReadAllBytes(filename); // Debug.LogFormat("cb_load_module module_id:'{0}', filename:'{1}', resolved:'{2}'\n", module_id, filename, resolvedPath); do { if (source != null && source.Length > 0) // bytecode is unsupported { if (source[0] != 0xbf) { DuktapeDLL.duk_unity_push_lstring(ctx, source, (uint)source.Length); } else { DuktapeDLL.duk_type_error(ctx, "cannot load module (bytecode): %s", module_id); } break; } DuktapeDLL.duk_type_error(ctx, "cannot load module: %s", module_id); } while (false); return(1); }
public static bool duk_get_type(IntPtr ctx, int idx, out Type o) { if (DuktapeDLL.duk_is_string(ctx, idx)) { var name = DuktapeDLL.duk_get_string(ctx, idx); o = DuktapeAux.GetType(name); return(o != null); } else { //TODO: 增加一个隐藏属性记录jsobject对应类型 (constructor, object) if (DuktapeDLL.duk_get_prop_string(ctx, idx, DuktapeVM.OBJ_PROP_EXPORTED_REFID)) { var vm = DuktapeVM.GetVM(ctx); var refid = DuktapeDLL.duk_get_uint(ctx, -1); DuktapeDLL.duk_pop(ctx); o = vm.GetExportedType(refid); // Debug.Log($"get type from exported registry {o}:{refid}"); return(o != null); } else if (DuktapeDLL.duk_get_prop_string(ctx, idx, DuktapeVM.OBJ_PROP_NATIVE)) { var cache = DuktapeVM.GetObjectCache(ctx); var refid = DuktapeDLL.duk_get_int(ctx, -1); DuktapeDLL.duk_pop(ctx); cache.TryGetTypedObject(refid, out o); // Debug.Log($"get type from objectcache registry {o}:{refid}"); return(o != null); } } o = null; return(false); }
public void EvalMain(string filename, byte[] source) { if (source == null || source.Length == 0) { return; } if (source[0] == 0xbf) { //NOTE: module is not supported in bytecode mode EvalSource(filename, source); } else { if (filename == null) { filename = "eval"; } var ctx = _ctx.rawValue; var top = DuktapeDLL.duk_get_top(ctx); DuktapeDLL.duk_unity_push_lstring(ctx, source, (uint)source.Length); var err = DuktapeDLL.duk_module_node_peval_main(ctx, filename); // var err = DuktapeDLL.duk_peval(ctx); // var err = DuktapeDLL.duk_peval_string_noresult(ctx, source); // Debug.Log($"load main module: {filename} ({resolvedPath})"); if (err != 0) { DuktapeAux.PrintError(ctx, -1, filename); // Debug.LogErrorFormat("eval main error: {0}\n{1}", DuktapeDLL.duk_safe_to_string(ctx, -1), filename); } DuktapeDLL.duk_set_top(ctx, top); } }
public static int duk_addSearchPath(IntPtr ctx) { var path = DuktapeAux.duk_require_string(ctx, 0); DuktapeVM.GetVM(ctx).AddSearchPath(path); return(0); }
public static int duk_dofile(IntPtr ctx) { var filename = DuktapeAux.duk_require_string(ctx, 0); DuktapeVM.GetVM(ctx).EvalFile(filename); return(0); }
public bool InvokeMemberWithBooleanReturn(string name) { var member = GetMember(name); if (member != null) { var ctx = member.context.rawValue; if (ctx != IntPtr.Zero) { member.Push(ctx); this.Push(ctx); var ret = DuktapeDLL.duk_pcall_method(ctx, 0); if (ret != DuktapeDLL.DUK_EXEC_SUCCESS) { DuktapeAux.PrintError(ctx, -1); DuktapeDLL.duk_pop(ctx); throw new Exception("InvokeMemberWithBooleanReturn failed"); } var o = DuktapeDLL.duk_get_boolean_default(ctx, -1, false); DuktapeDLL.duk_pop(ctx); return(o); } } return(false); }
public static int GetType(IntPtr ctx) { string name; duk_get_primitive(ctx, 0, out name); //TODO: type 缓存; 从 jsobject hidden property 中读 refid var type = DuktapeAux.GetType(name); duk_push_classvalue(ctx, type); return(1); }
public DuktapeVM(IO.ByteBufferAllocator allocator = null) { _instance = this; _byteBufferAllocator = allocator; var ctx = DuktapeDLL.duk_create_heap_default(); _ctx = new DuktapeContext(this, ctx); DuktapeAux.duk_open(ctx); DuktapeVM.duk_open_module(ctx); DuktapeDLL.duk_unity_open(ctx); }
// 根据当前栈参数数量调用函数 // 调用失败时抛异常, 成功时栈上保留返回值 public void EndInvoke(IntPtr ctx) { var nargs = DuktapeDLL.duk_get_top(ctx) - _savedState; var ret = DuktapeDLL.duk_pcall_method(ctx, nargs); if (ret != DuktapeDLL.DUK_EXEC_SUCCESS) { DuktapeAux.PrintError(ctx, -1); DuktapeDLL.duk_pop(ctx); throw new Exception("duktape delegate exception"); } }
// 获取全局函数并调用 (do not cache it) public void Invoke(string funcName) { DuktapeDLL.duk_push_global_object(_ctx); DuktapeDLL.duk_get_prop_string(_ctx, -1, funcName); if (DuktapeDLL.duk_is_function(_ctx, -1)) { if (DuktapeDLL.duk_pcall(_ctx, 0) != DuktapeDLL.DUK_EXEC_SUCCESS) { DuktapeAux.PrintError(_ctx, -1); } } DuktapeDLL.duk_pop_2(_ctx); }
// poolSize: 预分配内存 public DuktapeVM(IO.ByteBufferAllocator allocator = null, int poolSize = 0) { _instance = this; _byteBufferAllocator = allocator; _memAllocPoolSize = poolSize >= 0 ? (uint)poolSize : 0; _memAllocPool = _memAllocPoolSize != 0 ? Marshal.AllocHGlobal(poolSize) : IntPtr.Zero; var ctx = DuktapeDLL.duk_unity_create_heap(_memAllocPool, _memAllocPoolSize); _ctx = new DuktapeContext(this, ctx); DuktapeDLL.duk_unity_open(ctx); DuktapeAux.duk_open(ctx); DuktapeVM.duk_open_module(ctx); }
public byte[] Compile(string filename, byte[] bytes) { try { // return _vm.DumpBytecode(filename, bytes); return(DuktapeAux.DumpBytecode(_ctx, filename, bytes)); } catch (Exception exception) { Debug.LogError(exception); return(null); } }
public object EvalSource(string filename, byte[] source) { object retValue = null; if (source == null || source.Length == 0) { return(retValue); } if (filename == null) { filename = "eval"; } var ctx = _ctx.rawValue; if (source[0] == 0xbf) { // load bytecode... var buffer_ptr = DuktapeDLL.duk_push_fixed_buffer(ctx, (uint)source.Length); Marshal.Copy(source, 0, buffer_ptr, source.Length); DuktapeDLL.duk_load_function(ctx); } else { DuktapeDLL.duk_unity_push_lstring(ctx, source, (uint)source.Length); DuktapeDLL.duk_push_string(ctx, filename); if (DuktapeDLL.duk_pcompile(ctx, 0) != 0) { DuktapeAux.PrintError(ctx, -1, filename); DuktapeDLL.duk_pop(ctx); throw new Exception("[duktape] source compile failed"); } } // Debug.LogFormat("check top {0}", DuktapeDLL.duk_get_top(ctx)); if (DuktapeDLL.duk_pcall(ctx, 0) != DuktapeDLL.DUK_EXEC_SUCCESS) { DuktapeAux.PrintError(ctx, -1, filename); DuktapeDLL.duk_pop(ctx); throw new Exception("[duktape] source eval failed"); } DuktapeBinding.duk_get_var(ctx, -1, out retValue); DuktapeDLL.duk_pop(ctx); return(retValue); // Debug.LogFormat("check top {0}", DuktapeDLL.duk_get_top(ctx)); }
// 函数对象以及nargs数的参数必须由调用者保证已经入栈, 然后才能调用 _InternalCall // 调用完成后栈顶为函数返回值, 或异常对象 public void _InternalPCall(IntPtr ctx, int nargs) { if (_argv != null) { var length = _argv.Length; nargs += length; for (var i = 0; i < length; i++) { _argv[i].Push(ctx); } } var ret = DuktapeDLL.duk_pcall(ctx, nargs); if (ret != DuktapeDLL.DUK_EXEC_SUCCESS) { DuktapeAux.PrintError(ctx, -1); // throw new Exception(err); } }
public void EvalSource(string filename, byte[] source) { if (source == null || source.Length == 0) { return; } if (filename == null) { filename = "eval"; } var ctx = _ctx.rawValue; do { if (source[0] == 0xbf) { // load bytecode... var buffer_ptr = DuktapeDLL.duk_push_fixed_buffer(ctx, (uint)source.Length); Marshal.Copy(source, 0, buffer_ptr, source.Length); DuktapeDLL.duk_load_function(ctx); } else { DuktapeDLL.duk_unity_push_lstring(ctx, source, (uint)source.Length); DuktapeDLL.duk_push_string(ctx, filename); if (DuktapeDLL.duk_pcompile(ctx, 0) != 0) { DuktapeAux.PrintError(ctx, -1, filename); DuktapeDLL.duk_pop(ctx); break; } } // Debug.LogFormat("check top {0}", DuktapeDLL.duk_get_top(ctx)); if (DuktapeDLL.duk_pcall(ctx, 0) != DuktapeDLL.DUK_EXEC_SUCCESS) { DuktapeAux.PrintError(ctx, -1, filename); } DuktapeDLL.duk_pop(ctx); // Debug.LogFormat("check top {0}", DuktapeDLL.duk_get_top(ctx)); } while (false); }
public void InvokeMember(string name) { var member = GetMember(name); if (member != null) { var ctx = member.context.rawValue; if (ctx != IntPtr.Zero) { member.Push(ctx); this.Push(ctx); var ret = DuktapeDLL.duk_pcall_method(ctx, 0); if (ret != DuktapeDLL.DUK_EXEC_SUCCESS) { DuktapeAux.PrintError(ctx, -1); // throw new Exception(err); } DuktapeDLL.duk_pop(ctx); } } }
public void EvalMain(string filename) { filename = EnsureExtension(filename); var ctx = _ctx.rawValue; var top = DuktapeDLL.duk_get_top(ctx); var resolvedPath = ResolvePath(filename); var source = _fileManager.ReadAllText(resolvedPath); DuktapeDLL.duk_push_string(ctx, source); var err = DuktapeDLL.duk_module_node_peval_main(ctx, filename); // var err = DuktapeDLL.duk_peval(ctx); // var err = DuktapeDLL.duk_peval_string_noresult(ctx, source); // Debug.Log($"load main module: {filename} ({resolvedPath})"); if (err != 0) { DuktapeAux.PrintError(ctx, -1, filename); // Debug.LogErrorFormat("eval main error: {0}\n{1}", DuktapeDLL.duk_safe_to_string(ctx, -1), filename); } DuktapeDLL.duk_set_top(ctx, top); }
private static duk_ret_t cb_resolve_module(IntPtr ctx) { var module_id = EnsureExtension(DuktapeAux.duk_require_string(ctx, 0)); var parent_id = DuktapeAux.duk_require_string(ctx, 1); var resolve_to = module_id; // Debug.LogFormat("cb_resolve_module module_id:'{0}', parent_id:'{1}'\n", module_id, parent_id); if (module_id.StartsWith("./") || module_id.StartsWith("../") || module_id.Contains("/./") || module_id.Contains("/../")) { // 显式相对路径直接从 parent 模块路径拼接 var parent_path = PathUtils.GetDirectoryName(parent_id); try { resolve_to = PathUtils.ExtractPath(PathUtils.Combine(parent_path, module_id), '/'); } catch { // 不能提升到源代码目录外面 DuktapeDLL.duk_type_error(ctx, "invalid module path (out of sourceRoot): %s", module_id); return(1); } } // Debug.LogFormat("resolve_cb(1): id:{0}', parent-id:'{1}', resolve-to:'{2}'", module_id, parent_id, resolve_to); // if (GetVM(ctx).ResolvePath(resolve_to) == null) // { // DuktapeDLL.duk_type_error(ctx, "cannot find module: %s", module_id); // return 1; // } if (resolve_to != null) { DuktapeDLL.duk_push_string(ctx, resolve_to); } else { DuktapeDLL.duk_type_error(ctx, "cannot find module: %s", module_id); } return(1); }
private static duk_ret_t cb_load_module(IntPtr ctx) { var module_id = DuktapeAux.duk_require_string(ctx, 0); DuktapeDLL.duk_get_prop_string(ctx, 2, "filename"); var filename = DuktapeAux.duk_require_string(ctx, -1); var resolvedPath = GetVM(ctx).ResolvePath(filename); // Debug.LogFormat("cb_load_module module_id:'{0}', filename:'{1}', resolved:'{2}'\n", module_id, filename, resolvedPath); var source = GetVM(ctx)._fileManager.ReadAllText(resolvedPath); if (source != null) { DuktapeDLL.duk_push_string(ctx, source); } else { DuktapeDLL.duk_type_error(ctx, "cannot load module: %s", module_id); } return(1); }
public static byte[] DumpBytecode(IntPtr ctx, string filename, byte[] source) { if (ctx == IntPtr.Zero) { throw new InvalidOperationException(); } if (source == null || source.Length == 0) { return(null); } if (source[0] == 0xbf) { return(source); } if (filename == null) { filename = "eval"; } DuktapeDLL.duk_unity_push_lstring(ctx, source, (uint)source.Length); DuktapeDLL.duk_push_string(ctx, filename); if (DuktapeDLL.duk_pcompile(ctx, 0) != 0) { DuktapeAux.PrintError(ctx, -1, filename); DuktapeDLL.duk_pop(ctx); return(null); } else { DuktapeDLL.duk_dump_function(ctx); uint buffer_size; var buffer_ptr = DuktapeDLL.duk_unity_require_buffer_data(ctx, -1, out buffer_size); var bytes = new byte[buffer_size]; Marshal.Copy(buffer_ptr, bytes, 0, (int)buffer_size); DuktapeDLL.duk_pop(ctx); return(bytes); } }
private IEnumerator _InitializeStep(IDuktapeListener listener, int step) { var ctx = DuktapeDLL.duk_create_heap_default(); _ctx = new DuktapeContext(this, ctx); DuktapeAux.duk_open(ctx); DuktapeVM.duk_open_module(ctx); DuktapeDLL.duk_unity_open(ctx); DuktapeDLL.duk_push_global_object(ctx); DuktapeJSBuiltins.reg(ctx); listener?.OnTypesBinding(this); var exportedTypes = this.GetType().Assembly.GetExportedTypes(); var bindingTypes = new List <Type>(exportedTypes.Length); var ctxAsArgs = new object[] { ctx }; for (int i = 0, size = exportedTypes.Length; i < size; i++) { var type = exportedTypes[i]; #if UNITY_EDITOR if (type.IsDefined(typeof(JSAutoRunAttribute), false)) { try { var run = type.GetMethod("Run", BindingFlags.Static | BindingFlags.Public); if (run != null) { run.Invoke(null, null); } } catch (Exception exception) { Debug.LogWarning($"JSAutoRun failed: {exception}"); } continue; } #endif var attributes = type.GetCustomAttributes(typeof(JSBindingAttribute), false); if (attributes.Length == 1) { var jsBinding = attributes[0] as JSBindingAttribute; if (jsBinding.Version == 0 || jsBinding.Version == VERSION) { bindingTypes.Add(type); } else { if (listener != null) { listener.OnBindingError(this, type); } } } } var numRegInvoked = bindingTypes.Count; for (var i = 0; i < numRegInvoked; ++i) { var type = bindingTypes[i]; var reg = type.GetMethod("reg"); if (reg != null) { reg.Invoke(null, ctxAsArgs); if (listener != null) { listener.OnProgress(this, i, numRegInvoked); } if (i % step == 0) { yield return(null); } } } if (listener != null) { listener.OnBinded(this, numRegInvoked); } // Debug.LogFormat("exported {0} classes", _exported.Count); // 设置导出类的继承链 foreach (var kv in _exported) { var type = kv.Key; var baseType = type.BaseType; if (baseType == null) { // Debug.Log($"baseType is null, for {type}"); continue; } var fn = kv.Value; fn.PushPrototype(ctx); if (PushChainedPrototypeOf(ctx, baseType)) { // Debug.LogFormat($"set {type} super {baseType}"); DuktapeDLL.duk_set_prototype(ctx, -2); } else { Debug.LogWarning($"fail to push prototype, for {type}: {baseType}"); } DuktapeDLL.duk_pop(ctx); } DuktapeJSBuiltins.postreg(ctx); DuktapeDLL.duk_pop(ctx); // pop global _updateTimer = DuktapeRunner.SetInterval(this.OnUpdate, 100f); if (listener != null) { listener.OnLoaded(this); } }
public byte[] DumpBytecode(string filename, byte[] source) { return(_ctx != null?DuktapeAux.DumpBytecode(_ctx.rawValue, filename, source) : null); }