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); }
private static void replace_by_builtin(IntPtr ctx, string t, uint k) { DuktapeDLL.duk_builtins_reg_get(ctx, k); // c DuktapeDLL.duk_get_prop_string(ctx, -2, t); // cs // copy static fields from c# to c DuktapeDLL.duk_enum(ctx, -1, 0); while (DuktapeDLL.duk_next(ctx, -1, true)) { DuktapeDLL.duk_dup(ctx, -2); if (!DuktapeDLL.duk_has_prop(ctx, -6)) { DuktapeDLL.duk_put_prop(ctx, -5); } else { DuktapeDLL.duk_pop_2(ctx); // pop key and value } } DuktapeDLL.duk_pop(ctx); // pop enum DuktapeDLL.duk_get_prop_string(ctx, -2, "prototype"); // c prototype DuktapeDLL.duk_get_prop_string(ctx, -2, "prototype"); // cs prototype <stack> [c, cs, c.prototype, cs.prototype] DuktapeDLL.duk_set_prototype(ctx, -2); // c.prototype = cs.prototype <stack> [c, cs, c.prototype] DuktapeDLL.duk_pop(ctx); // pop c.prototype DuktapeDLL.duk_put_prop_string(ctx, -2, "_raw"); // cs._raw = c DuktapeDLL.duk_put_prop_string(ctx, -2, t); // <global> }
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_delegate <T>(IntPtr ctx, int idx, out T o) where T : class { if (DuktapeDLL.duk_is_object(ctx, idx) ||/* && check if js delegate type (hidden property) */ DuktapeDLL.duk_is_function(ctx, idx)) { DuktapeDLL.duk_get_prop_string(ctx, idx, DuktapeVM.OBJ_PROP_NATIVE_WEAK); var refid = DuktapeDLL.duk_get_int(ctx, -1); DuktapeDLL.duk_pop(ctx); var cache = DuktapeVM.GetObjectCache(ctx); DuktapeDelegate fn; if (cache.TryGetTypedWeakObject(refid, out fn) && fn != null) { o = fn.target as T; return(true); } // 默认赋值操作 DuktapeDLL.duk_dup(ctx, idx); var heapptr = DuktapeDLL.duk_get_heapptr(ctx, idx); fn = new DuktapeDelegate(ctx, DuktapeDLL.duk_unity_ref(ctx)); var vm = DuktapeVM.GetVM(ctx); o = vm.CreateDelegate(typeof(T), fn) as T; // DuktapeDelegate 拥有 js 对象的强引用, 此 js 对象无法释放 cache 中的 object, 所以这里用弱引用注册 // 会出现的问题是, 如果 c# 没有对 DuktapeDelegate 的强引用, 那么反复 get_delegate 会重复创建 DuktapeDelegate refid = cache.AddWeakObject(fn); DuktapeDLL.duk_unity_set_prop_i(ctx, idx, DuktapeVM.OBJ_PROP_NATIVE_WEAK, refid); cache.AddJSValue(o, heapptr); return(true); } o = null; return(false); }
private static string duk_get_stacktrace(IntPtr ctx) { var stacktrace = "stacktrace:\n"; for (int i = -2; ; i--) { DuktapeDLL.duk_inspect_callstack_entry(ctx, i); if (!DuktapeDLL.duk_is_undefined(ctx, -1)) { DuktapeDLL.duk_get_prop_string(ctx, -1, "lineNumber"); var lineNumber = DuktapeDLL.duk_to_int(ctx, -1); DuktapeDLL.duk_get_prop_string(ctx, -2, "function"); DuktapeDLL.duk_get_prop_string(ctx, -1, "name"); var funcName = DuktapeDLL.duk_safe_to_string(ctx, -1); DuktapeDLL.duk_get_prop_string(ctx, -2, "fileName"); var fileName = DuktapeDLL.duk_safe_to_string(ctx, -1); DuktapeDLL.duk_pop_n(ctx, 4); stacktrace += (duk_source_position ?? default_duk_source_position)(ctx, funcName, fileName, lineNumber); stacktrace += "\n"; } else { DuktapeDLL.duk_pop(ctx); break; } } return(stacktrace); }
protected static int object_dtor(IntPtr ctx) { if (DuktapeDLL.duk_get_prop_string(ctx, 0, DuktapeVM.OBJ_PROP_NATIVE)) { var id = DuktapeDLL.duk_get_int(ctx, -1); DuktapeVM.GetObjectCache(ctx)?.RemoveObject(id); } DuktapeDLL.duk_pop(ctx); // pop native return(0); }
public static bool duk_retrive_object(IntPtr ctx, string el0) { DuktapeDLL.duk_dup_top(ctx); if (!DuktapeDLL.duk_get_prop_string(ctx, -1, el0)) // [parent, el0] { DuktapeDLL.duk_remove(ctx, -2); return(false); } DuktapeDLL.duk_remove(ctx, -2); return(true); }
public static void PrintError(IntPtr ctx, int idx, string filename) { string err; if (DuktapeDLL.duk_is_error(ctx, idx)) { DuktapeDLL.duk_get_prop_string(ctx, idx, "stack"); err = DuktapeDLL.duk_safe_to_string(ctx, -1); DuktapeDLL.duk_pop(ctx); } else { err = DuktapeDLL.duk_safe_to_string(ctx, idx); } if (duk_source_position != default_duk_source_position) { var errlines = err.Split('\n'); err = ""; if (_stRegex == null) { _stRegex = new Regex(@"^\s+at\s(.+)\s\((.+\.js):(\d+)\)(.*)$", RegexOptions.Compiled); } for (var i = 0; i < errlines.Length; i++) { var line = errlines[i]; var matches = _stRegex.Matches(line); if (matches.Count == 1) { var match = matches[0]; if (match.Groups.Count >= 4) { var funcName = match.Groups[1].Value; var fileName = match.Groups[2].Value; var lineNumber = 0; int.TryParse(match.Groups[3].Value, out lineNumber); var extra = match.Groups.Count >= 5 ? match.Groups[4].Value : ""; var sroucePosition = duk_source_position(ctx, funcName, fileName, lineNumber); err += $" at {sroucePosition}{extra}\n"; continue; } } err += line + "\n"; } } if (filename != null) { Debug.LogError($"[JSError][{filename}] {err}"); } else { Debug.LogError($"[JSError] {err}"); } }
public static void duk_begin_namespace(IntPtr ctx, string el) // [parent] { // Debug.LogFormat("begin namespace {0}", DuktapeDLL.duk_get_top(ctx)); if (!DuktapeDLL.duk_get_prop_string(ctx, -1, el)) // [parent, el] { DuktapeDLL.duk_pop(ctx); // [parent] DuktapeDLL.duk_push_object(ctx); // [parent, new_object] DuktapeDLL.duk_dup_top(ctx); // [parent, new_object] DuktapeDLL.duk_put_prop_string(ctx, -3, el); // [parent, el] } }
// 获取全局函数并调用 (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); }
// public static bool duk_rebind_this(IntPtr ctx, Matrix4x4 o) // { // DuktapeDLL.duk_push_this(ctx); // DuktapeDLL.duk_unity_put16f(ctx, -1, ...); // DuktapeDLL.duk_pop(ctx); // return true; // } public static bool duk_get_native_refid(IntPtr ctx, int idx, out int id) { if (!DuktapeDLL.duk_is_null_or_undefined(ctx, idx)) { if (DuktapeDLL.duk_get_prop_string(ctx, idx, DuktapeVM.OBJ_PROP_NATIVE)) { id = DuktapeDLL.duk_get_int(ctx, -1); return(true); } DuktapeDLL.duk_pop(ctx); // pop OBJ_PROP_NATIVE } id = 0; return(false); }
public static bool duk_retrive_object(IntPtr ctx, params string[] els) { DuktapeDLL.duk_dup_top(ctx); for (int i = 1, size = els.Length; i < size; i++) { var el = els[i]; if (!DuktapeDLL.duk_get_prop_string(ctx, -1, el)) // [parent, el] { DuktapeDLL.duk_remove(ctx, -2); return(false); } DuktapeDLL.duk_remove(ctx, -2); } return(true); }
public static bool duk_get_cached_object(IntPtr ctx, int idx, out object o) { if (DuktapeDLL.duk_get_prop_string(ctx, idx, DuktapeVM.OBJ_PROP_NATIVE)) { var id = DuktapeDLL.duk_get_int(ctx, -1); DuktapeDLL.duk_pop(ctx); return(DuktapeVM.GetObjectCache(ctx).TryGetObject(id, out o)); } else { DuktapeDLL.duk_pop(ctx); } o = null; return(false); }
protected static void duk_add_event(IntPtr ctx, string name, DuktapeDLL.duk_c_function add_op, DuktapeDLL.duk_c_function remove_op, int idx) { idx = DuktapeDLL.duk_normalize_index(ctx, idx); DuktapeDLL.duk_get_prop_string(ctx, idx, DuktapeVM.OBJ_PROP_NATIVE); // 直接在 event object 上复制主对象的引用id var refid = DuktapeDLL.duk_get_int(ctx, -1); DuktapeDLL.duk_pop(ctx); DuktapeDLL.duk_push_object(ctx); DuktapeDLL.duk_unity_set_prop_i(ctx, -1, DuktapeVM.OBJ_PROP_NATIVE, refid); DuktapeDLL.duk_push_c_function(ctx, add_op, 1); DuktapeDLL.duk_put_prop_string(ctx, -2, "on"); DuktapeDLL.duk_push_c_function(ctx, remove_op, 1); DuktapeDLL.duk_put_prop_string(ctx, -2, "off"); DuktapeDLL.duk_put_prop_string(ctx, idx, name); }
// 记录栈状态 public void BeginInvoke(IntPtr ctx) { // Debug.Log($"BeginInvoke: {_savedState}"); if (_jsInvoker == null) { this.Push(ctx); // push this if (!DuktapeDLL.duk_is_function(ctx, -1)) { // Debug.Log("DuktapeDelegate based on Dispatcher"); DuktapeDLL.duk_get_prop_string(ctx, -1, "dispatch"); DuktapeDLL.duk_remove(ctx, -2); // remove this } _jsInvoker = new DuktapeFunction(ctx, DuktapeDLL.duk_unity_ref(ctx)); } _jsInvoker.Push(ctx); // push function this.Push(ctx); // push this _savedState = DuktapeDLL.duk_get_top(ctx); }
public static bool duk_rebind_native(IntPtr ctx, int idx, object o) { if (DuktapeDLL.duk_is_null_or_undefined(ctx, idx)) // or check for object? { return(true); } if (DuktapeDLL.duk_get_prop_string(ctx, idx, DuktapeVM.OBJ_PROP_NATIVE)) { var id = DuktapeDLL.duk_get_int(ctx, -1); DuktapeDLL.duk_pop(ctx); // pop OBJ_PROP_NATIVE return(DuktapeVM.GetObjectCache(ctx).ReplaceObject(id, o)); } else { DuktapeDLL.duk_pop(ctx); } return(false); }
private static string duk_get_stacktrace(IntPtr ctx) { var stacktrace = "\n"; uint malloc_count = 0; uint malloc_size = 0; var vm = DuktapeVM.GetVM(ctx); if (vm != null) { vm.GetMemoryState(out malloc_count, out malloc_size); if (malloc_count != 0) { stacktrace += $"allocations: {malloc_count} [{malloc_size}]\n"; } } stacktrace += "stacktrace:\n"; for (int i = -2; ; i--) { DuktapeDLL.duk_inspect_callstack_entry(ctx, i); if (!DuktapeDLL.duk_is_undefined(ctx, -1)) { DuktapeDLL.duk_get_prop_string(ctx, -1, "lineNumber"); var lineNumber = DuktapeDLL.duk_to_int(ctx, -1); DuktapeDLL.duk_get_prop_string(ctx, -2, "function"); DuktapeDLL.duk_get_prop_string(ctx, -1, "name"); var funcName = DuktapeDLL.duk_safe_to_string(ctx, -1); DuktapeDLL.duk_get_prop_string(ctx, -2, "fileName"); var fileName = DuktapeDLL.duk_safe_to_string(ctx, -1); DuktapeDLL.duk_pop_n(ctx, 4); stacktrace += (duk_source_position ?? default_duk_source_position)(ctx, funcName, fileName, lineNumber); stacktrace += "\n"; } else { DuktapeDLL.duk_pop(ctx); break; } } return(stacktrace); }
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); }
protected static void duk_add_event_instanced(IntPtr ctx, string name, DuktapeDLL.duk_c_function add_op, DuktapeDLL.duk_c_function remove_op, int idx) { idx = DuktapeDLL.duk_normalize_index(ctx, idx); DuktapeDLL.duk_get_prop_string(ctx, idx, DuktapeVM.OBJ_PROP_NATIVE); // 直接在 event object 上复制主对象的引用id var refid = DuktapeDLL.duk_get_int(ctx, -1); DuktapeDLL.duk_pop(ctx); DuktapeDLL.duk_push_object(ctx); // [evtobj] DuktapeDLL.duk_unity_set_prop_i(ctx, -1, DuktapeVM.OBJ_PROP_NATIVE, refid); DuktapeDLL.duk_push_string(ctx, name); // [evtobj, name] DuktapeDLL.duk_dup(ctx, -2); // [evtobj, name, evtobj] DuktapeDLL.duk_push_c_function(ctx, add_op, 1); DuktapeDLL.duk_put_prop_string(ctx, -2, "on"); DuktapeDLL.duk_push_c_function(ctx, remove_op, 1); DuktapeDLL.duk_put_prop_string(ctx, -2, "off"); // [evtobj, name, evtobj] DuktapeDLL.duk_def_prop(ctx, idx, DuktapeDLL.DUK_DEFPROP_HAVE_VALUE | DuktapeDLL.DUK_DEFPROP_SET_ENUMERABLE | DuktapeDLL.DUK_DEFPROP_CLEAR_CONFIGURABLE); // [evtobj] }
public void PushProperty(IntPtr ctx, string property) { this.Push(ctx); // push this DuktapeDLL.duk_get_prop_string(ctx, -1, property); DuktapeDLL.duk_remove(ctx, -2); // remove this }
// push 当前函数的 prototype public void PushPrototype(IntPtr ctx) { this.Push(ctx); DuktapeDLL.duk_get_prop_string(ctx, -1, "prototype"); DuktapeDLL.duk_remove(ctx, -2); }