Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
        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);
        }
Exemplo n.º 6
0
 // 获取全局函数并调用 (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);
 }
Exemplo n.º 7
0
 // 记录栈状态
 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);
 }
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
        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);
            }
        }
Exemplo n.º 10
0
        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);
            }
        }
Exemplo n.º 11
0
        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);
        }