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)) { var heapptr = DuktapeDLL.duk_get_heapptr(ctx, idx); var cache = DuktapeVM.GetObjectCache(ctx); DuktapeDelegate fn; if (cache.TryGetDelegate(heapptr, out fn)) { // Debug.LogWarningFormat("cache hit {0}", heapptr); o = fn.target as T; return(true); } // 默认赋值操作 DuktapeDLL.duk_dup(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 // Debug.LogWarningFormat("cache create : {0}", heapptr); cache.AddDelegate(heapptr, fn); return(true); } o = null; return(false); }
private static int _GetTimerFunction(IntPtr ctx, out DuktapeFunction fn) { if (!DuktapeDLL.duk_is_function(ctx, 0)) { fn = null; return(0); } if (!DuktapeDLL.duk_is_number(ctx, 1)) { fn = null; return(1); } var top_index = DuktapeDLL.duk_get_top_index(ctx); // Debug.Log($"_GetTimerFunction {top} ?? {DuktapeDLL.duk_get_top(ctx)}"); DuktapeValue[] argv = null; if (top_index > 1) { argv = new DuktapeValue[top_index - 1]; for (var i = 2; i <= top_index; i++) { DuktapeDLL.duk_dup(ctx, i); var argPtr = DuktapeDLL.duk_get_heapptr(ctx, -1); argv[i - 2] = new DuktapeValue(ctx, DuktapeDLL.duk_unity_ref(ctx), argPtr); } } DuktapeDLL.duk_dup(ctx, 0); var fnPtr = DuktapeDLL.duk_get_heapptr(ctx, -1); fn = new DuktapeFunction(ctx, DuktapeDLL.duk_unity_ref(ctx), fnPtr, argv); return(-1); }
public static bool duk_get_delegate <T>(IntPtr ctx, int idx, out T o) where T : class { //TODO: 20200320 !!! 如果 o 不是 jsobject, 且是 Delegate 但不是 DuktapeDelegate, 则 ... 处理 if (DuktapeDLL.duk_is_object(ctx, idx) || DuktapeDLL.duk_is_function(ctx, idx)) { var heapptr = DuktapeDLL.duk_get_heapptr(ctx, idx); var cache = DuktapeVM.GetObjectCache(ctx); DuktapeDelegate fn; if (cache.TryGetDelegate(heapptr, out fn)) { // Debug.LogWarningFormat("cache hit {0}", heapptr); o = fn.target as T; return(true); } // 默认赋值操作 DuktapeDLL.duk_dup(ctx, idx); fn = new DuktapeDelegate(ctx, DuktapeDLL.duk_unity_ref(ctx), heapptr); var vm = DuktapeVM.GetVM(ctx); o = vm.CreateDelegate(typeof(T), fn) as T; // DuktapeDelegate 拥有 js 对象的强引用, 此 js 对象无法释放 cache 中的 object, 所以这里用弱引用注册 // 会出现的问题是, 如果 c# 没有对 DuktapeDelegate 的强引用, 那么反复 get_delegate 会重复创建 DuktapeDelegate // Debug.LogWarningFormat("cache create : {0}", heapptr); cache.AddDelegate(heapptr, fn); return(true); } // else if (DuktapeDLL.duk_is_object(ctx, idx)) // { // return duk_get_classvalue<T>(ctx, idx, out o); // } o = null; return(false); }
public DuktapeFunction GetMember(string name) { DuktapeFunction method = null; if (!_methodCache.TryGetValue(name, out method)) { var ctx = _context.rawValue; if (ctx != IntPtr.Zero) { this.PushProperty(ctx, name); if (DuktapeDLL.duk_is_function(ctx, -1)) { var ptr = DuktapeDLL.duk_get_heapptr(ctx, -1); var refid = DuktapeDLL.duk_unity_ref(ctx); method = new DuktapeFunction(ctx, refid, ptr); } else { DuktapeDLL.duk_pop(ctx); } } _methodCache[name] = method; } return(method); }
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); }
// 获取全局函数并调用 (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 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_get_classvalue(IntPtr ctx, int idx, out DuktapeFunction o) { if (DuktapeDLL.duk_is_function(ctx, idx)) { object obj; if (duk_get_cached_object(ctx, idx, out obj)) { if (obj is DuktapeFunction) { o = (DuktapeFunction)obj; return(true); } } DuktapeDLL.duk_dup(ctx, idx); var ptr = DuktapeDLL.duk_get_heapptr(ctx, -1); var refid = DuktapeDLL.duk_unity_ref(ctx); o = new DuktapeFunction(ctx, refid, ptr); return(true); } o = null; return(false); }
protected static bool duk_match_type(IntPtr ctx, int idx, Type type) { if (type == null) { return(true); } if (type == typeof(object)) { return(true); } if (type == typeof(Type)) { Type otype; return(duk_get_type(ctx, idx, out otype)); // 只要求匹配 Type 本身, 不比较具体 Type // return otype == type; } var jstype = DuktapeDLL.duk_get_type(ctx, idx); switch (jstype) { // case duk_type_t.DUK_TYPE_NONE: case duk_type_t.DUK_TYPE_OBJECT: // objects, arrays, functions, threads if (DuktapeDLL.duk_is_array(ctx, idx)) { if (!type.IsArray && !_assignableFromArray.Contains(type)) { return(false); } } else if (DuktapeDLL.duk_is_function(ctx, idx)) { //TODO: 完善处理 delegate return(type == typeof(DuktapeFunction) || type.BaseType == typeof(MulticastDelegate)); } else if (DuktapeDLL.duk_is_thread(ctx, idx)) { return(false); } int refid; //TODO: 根据记录在jsobject 上的 分类标记 做进一步分支 (类型, 实例, 或特定优化类型) if (duk_get_native_refid(ctx, idx, out refid)) { var cache = DuktapeVM.GetObjectCache(ctx); return(cache.MatchObjectType(refid, type)); } return(true); case duk_type_t.DUK_TYPE_NUMBER: return(type.IsPrimitive || type.IsEnum); case duk_type_t.DUK_TYPE_STRING: return(type == typeof(string)); case duk_type_t.DUK_TYPE_UNDEFINED: case duk_type_t.DUK_TYPE_NULL: return(!type.IsValueType && !type.IsPrimitive); case duk_type_t.DUK_TYPE_BOOLEAN: return(type == typeof(bool)); case duk_type_t.DUK_TYPE_BUFFER: return(type == typeof(byte[]) || type == typeof(sbyte[]) /* || type == typeof(DuktapeBuffer) */); case duk_type_t.DUK_TYPE_POINTER: // return type == typeof(DuktapePointer); case duk_type_t.DUK_TYPE_LIGHTFUNC: default: return(false); } }
protected static bool duk_match_type(IntPtr ctx, int idx, Type type) { if (type == null) { return(true); } if (type == typeof(object)) { return(true); } if (type == typeof(Type)) { Type otype; return(duk_get_type(ctx, idx, out otype)); // 只要求匹配 Type 本身, 不比较具体 Type // return otype == type; } var jstype = DuktapeDLL.duk_get_type(ctx, idx); switch (jstype) { // case duk_type_t.DUK_TYPE_NONE: case duk_type_t.DUK_TYPE_OBJECT: // objects, arrays, functions, threads if (DuktapeDLL.duk_is_array(ctx, idx)) { if (!type.IsArray && !_assignableFromArray.Contains(type)) { return(false); } } else if (DuktapeDLL.duk_is_function(ctx, idx)) { //TODO: 完善处理 delegate return(type == typeof(DuktapeFunction) || type.BaseType == typeof(MulticastDelegate)); } else if (DuktapeDLL.duk_is_thread(ctx, idx)) { return(false); } int refid; if (duk_get_native_refid(ctx, idx, out refid)) { var cache = DuktapeVM.GetObjectCache(ctx); return(cache.MatchObjectType(refid, type)); } int typeid; if (DuktapeDLL.duk_unity_get_type_refid(ctx, idx, out typeid)) { var vm = DuktapeVM.GetVM(ctx); var eType = vm.GetExportedType(typeid); if (eType != null) { // Debug.LogFormat("match type? {0} {1} {2}", eType, type, typeid); return(eType == type); } // Debug.LogFormat("match type {0} with typeid {1}", type, typeid); } return(type.IsSubclassOf(typeof(DuktapeValue))); case duk_type_t.DUK_TYPE_NUMBER: return(type.IsPrimitive || type.IsEnum); case duk_type_t.DUK_TYPE_STRING: return(type == typeof(string)); case duk_type_t.DUK_TYPE_UNDEFINED: case duk_type_t.DUK_TYPE_NULL: return(!type.IsValueType && !type.IsPrimitive); case duk_type_t.DUK_TYPE_BOOLEAN: return(type == typeof(bool)); case duk_type_t.DUK_TYPE_BUFFER: return(type == typeof(byte[]) || type == typeof(sbyte[]) /* || type == typeof(DuktapeBuffer) */); case duk_type_t.DUK_TYPE_POINTER: // return type == typeof(DuktapePointer); case duk_type_t.DUK_TYPE_LIGHTFUNC: default: return(false); } }
public static bool duk_get_var(IntPtr ctx, int idx, out object o) { var jstype = DuktapeDLL.duk_get_type(ctx, idx); switch (jstype) { case duk_type_t.DUK_TYPE_BOOLEAN: /* ECMAScript boolean: 0 or 1 */ { o = DuktapeDLL.duk_get_boolean(ctx, idx); return(true); } case duk_type_t.DUK_TYPE_NUMBER: /* ECMAScript number: double */ { o = DuktapeDLL.duk_get_number(ctx, idx); return(true); } case duk_type_t.DUK_TYPE_STRING: /* ECMAScript string: CESU-8 / extended UTF-8 encoded */ { o = DuktapeDLL.duk_get_string(ctx, idx); return(true); } case duk_type_t.DUK_TYPE_OBJECT: /* ECMAScript object: includes objects, arrays, functions, threads */ { if (DuktapeDLL.duk_is_function(ctx, idx)) { DuktapeFunction func; var r = duk_get_classvalue(ctx, idx, out func); o = func; return(r); } if (duk_get_cached_object(ctx, idx, out o)) { return(true); } else { DuktapeObject val; var r = duk_get_classvalue(ctx, idx, out val); o = val; return(r); } } case duk_type_t.DUK_TYPE_BUFFER: /* fixed or dynamic, garbage collected byte buffer */ { uint length; var pointer = DuktapeDLL.duk_unity_get_buffer_data(ctx, idx, out length); var buffer = new byte[length]; o = buffer; Marshal.Copy(pointer, buffer, 0, (int)length); return(true); } case duk_type_t.DUK_TYPE_POINTER: /* raw void pointer */ case duk_type_t.DUK_TYPE_LIGHTFUNC: /* lightweight function pointer */ throw new NotImplementedException(); case duk_type_t.DUK_TYPE_NONE: /* no value, e.g. invalid index */ o = null; return(false); case duk_type_t.DUK_TYPE_UNDEFINED: /* ECMAScript undefined */ case duk_type_t.DUK_TYPE_NULL: /* ECMAScript null */ o = null; return(true); } o = null; return(false); }