Exemple #1
0
        public static int duk_addSearchPath(IntPtr ctx)
        {
            var path = DuktapeAux.duk_require_string(ctx, 0);

            DuktapeVM.GetVM(ctx).AddSearchPath(path);
            return(0);
        }
Exemple #2
0
        public static int duk_dofile(IntPtr ctx)
        {
            var filename = DuktapeAux.duk_require_string(ctx, 0);

            DuktapeVM.GetVM(ctx).EvalFile(filename);
            return(0);
        }
Exemple #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);
        }
Exemple #4
0
        public static bool duk_get_classvalue(IntPtr ctx, int idx, out IO.ByteBuffer o)
        {
            object obj;

            if (duk_get_cached_object(ctx, idx, out obj))
            {
                if (obj is IO.ByteBuffer)
                {
                    o = (IO.ByteBuffer)obj;
                    return(true);
                }
            }
            if (DuktapeDLL.duk_is_buffer_data(ctx, idx))
            {
                var allocator = DuktapeVM.GetVM(ctx).GetByteBufferAllocator();
                if (allocator != null)
                {
                    uint length;
                    var  pointer = DuktapeDLL.duk_unity_get_buffer_data(ctx, idx, out length);
                    o = allocator.Alloc((int)length);
                    allocator.AutoRelease(o);
                    o.WriteBytes(pointer, (int)length);
                    return(true);
                }
            }
            o = null;
            return(false);
        }
Exemple #5
0
        public void Destroy()
        {
            try
            {
                _instance = null;
                if (_ctx != null)
                {
                    var ctx = _ctx.rawValue;
                    _ctx.Destroy();
                    _ctx            = null;
                    _lastContextPtr = IntPtr.Zero;
                    _lastContext    = null;
                    _contexts.Clear();
                    _objectCache.Clear();
                    DuktapeDLL.duk_unity_destroy_heap(ctx);
                    // Debug.LogWarning("duk_destroy_heap");
                }

                if (_updateTimer != 0)
                {
                    DuktapeRunner.Clear(_updateTimer);
                    _updateTimer = 0;
                }
            }
            finally
            {
                if (_memAllocPool != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(_memAllocPool);
                    _memAllocPool = IntPtr.Zero;
                }
            }
        }
Exemple #6
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);
        }
Exemple #7
0
        private static SourceMap GetSourceMap(IntPtr ctx, string fileName)
        {
            SourceMap sourceMap;

            if (!_sourceMaps.TryGetValue(fileName, out sourceMap))
            {
                try
                {
                    var vm           = DuktapeVM.GetVM(ctx);
                    var resolvedPath = vm.ResolvePath(fileName + ".map");
                    if (resolvedPath != null)
                    {
                        using (var stream = File.OpenRead(resolvedPath))
                        {
                            var parser = new SourceMapParser();
                            var reader = new StreamReader(stream);
                            sourceMap = parser.ParseSourceMap(reader);
                            // Debug.Log($"[SourceMapHelper] parse sourceMap: {sourceMap.File} ({resolvedPath})");
                        }
                    }
                }
                finally
                {
                    _sourceMaps[fileName] = sourceMap;
                }
            }
            return(sourceMap);
        }
 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);
 }
Exemple #9
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);
        }
Exemple #10
0
        private static SourceMap GetSourceMap(IntPtr ctx, string fileName)
        {
            SourceMap sourceMap;

            if (!_sourceMaps.TryGetValue(fileName, out sourceMap))
            {
                try
                {
                    var fileResolver = DuktapeVM.GetVM(ctx).fileResolver;
                    var fileContent  = fileResolver.ReadAllBytes(fileName + ".map");
                    if (fileContent != null && fileContent.Length > 0)
                    {
                        using (var stream = new MemoryStream(fileContent))
                        {
                            var parser = new SourceMapParser();
                            var reader = new StreamReader(stream);
                            sourceMap = parser.ParseSourceMap(reader);
                            // Debug.Log($"[SourceMapHelper] parse sourceMap: {sourceMap.File} ({resolvedPath})");
                        }
                    }
                }
                finally
                {
                    _sourceMaps[fileName] = sourceMap;
                }
            }
            return(sourceMap);
        }
        public static void duk_bind_native(IntPtr ctx, int idx, object o)
        {
            var type  = o.GetType();
            var vm    = DuktapeVM.GetVM(ctx);
            var cache = vm.GetObjectCache();
            var id    = cache.AddObject(o);

            if (id >= 0)
            {
                DuktapeDLL.duk_unity_set_refid(ctx, idx, id);
            }

            if (DuktapeVM.GetVM(ctx).PushChainedPrototypeOf(ctx, type))
            {
                DuktapeDLL.duk_set_prototype(ctx, -2);
            }
            else
            {
                Debug.LogWarning($"no prototype found for {type}");
            }
            if (!type.IsValueType)
            {
                var heapptr = DuktapeDLL.duk_get_heapptr(ctx, idx);
                cache.AddJSValue(o, heapptr);
            }
        }
 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);
 }
        public static int duk_dostring(IntPtr ctx)
        {
            var source   = DuktapeDLL.duk_get_string(ctx, 0);
            var filename = DuktapeDLL.duk_get_string(ctx, 1);

            DuktapeVM.GetVM(ctx).EvalSource(source, filename);
            return(0);
        }
Exemple #14
0
        private static void duk_unity_unref(IntPtr ctx, uint refid, object target)
        {
            var cache = DuktapeVM.GetObjectCache(ctx);

            // cache.RemoveJSValue(target);
            cache.RemoveDelegate((IntPtr)target);
            DuktapeDLL.duk_unity_unref(ctx, refid);
        }
Exemple #15
0
        // private static void duk_unity_unref_delegate(IntPtr ctx, uint refid, object target)
        // {
        //     var cache = DuktapeVM.GetObjectCache(ctx);
        //     cache.RemoveJSValue(target);
        // }

        private static void duk_unity_unref(IntPtr ctx, uint refid, object target)
        {
            var cache = DuktapeVM.GetObjectCache(ctx);
            var t     = cache.RemoveDelegate((IntPtr)target);

            // Debug.LogErrorFormat("release delegate ptr {0} {1}", target, t);
            DuktapeDLL.duk_unity_unref(ctx, refid);
        }
        public static bool duk_rebind_native(IntPtr ctx, int idx, object o)
        {
            int id;

            if (DuktapeDLL.duk_unity_get_refid(ctx, idx, out id))
            {
                return(DuktapeVM.GetObjectCache(ctx).ReplaceObject(id, o));
            }
            return(false);
        }
Exemple #17
0
 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);
 }
Exemple #18
0
        protected static int object_dtor(IntPtr ctx)
        {
            int id;

            if (DuktapeDLL.duk_unity_get_refid(ctx, 0, out id))
            {
                // Debug.LogErrorFormat("remove refid {0}", id);
                DuktapeVM.GetObjectCache(ctx)?.RemoveObject(id);
            }
            return(0);
        }
Exemple #19
0
        public static bool duk_get_cached_object(IntPtr ctx, int idx, out object o)
        {
            int id;

            if (DuktapeDLL.duk_unity_get_refid(ctx, idx, out id))
            {
                return(DuktapeVM.GetObjectCache(ctx).TryGetObject(id, out o));
            }
            //TODO: if o is Delegate, try get from delegate cache list
            o = null;
            return(false);
        }
Exemple #20
0
        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);
        }
Exemple #21
0
        // 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);
        }
        // push 一个对象实例 (调用者需要自行负责提前null检查)
        private static void duk_push_object(IntPtr ctx, object o)
        {
            var    cache = DuktapeVM.GetObjectCache(ctx);
            IntPtr heapptr;

            if (cache.TryGetJSValue(o, out heapptr))
            {
                DuktapeDLL.duk_push_heapptr(ctx, heapptr);
                return;
            }
            DuktapeDLL.duk_push_object(ctx);
            duk_bind_native(ctx, -1, o);
        }
Exemple #23
0
        protected static void duk_begin_special(IntPtr ctx, string name)
        {
            DuktapeDLL.duk_push_c_function(ctx, object_private_ctor, 0); // ctor
            DuktapeDLL.duk_dup(ctx, -1);
            DuktapeDLL.duk_dup(ctx, -1);
            var typeValue = new DuktapeFunction(ctx, DuktapeDLL.duk_unity_ref(ctx)); // ctor, ctor

            DuktapeVM.GetVM(ctx).AddSpecial(name, typeValue);
            DuktapeDLL.duk_put_prop_string(ctx, -3, name);        // ctor
            DuktapeDLL.duk_push_object(ctx);                      // ctor, prototype
            DuktapeDLL.duk_dup_top(ctx);                          // ctor, prototype, prototype
            DuktapeDLL.duk_put_prop_string(ctx, -3, "prototype"); // ctor, prototype
        }
        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);
            }
            int id;

            if (DuktapeDLL.duk_unity_get_refid(ctx, idx, out id))
            {
                return(DuktapeVM.GetObjectCache(ctx).ReplaceObject(id, o));
            }
            return(false);
        }
        void OnGUI()
        {
            var vm = DuktapeVM.GetInstance();

            if (vm == null)
            {
                EditorGUILayout.HelpBox("No Running VM", MessageType.Info);
                return;
            }

            uint objectCount;
            uint allocBytes;
            uint poolBytes;

            vm.GetMemoryState(out objectCount, out allocBytes, out poolBytes);
            EditorGUILayout.IntField("Objects", (int)objectCount);
            if (allocBytes > 1024 * 1024 * 2)
            {
                EditorGUILayout.FloatField("Allocated Memory (MB)", (float)allocBytes / 1024f / 1024f);
            }
            else if (allocBytes > 1024 * 2)
            {
                EditorGUILayout.FloatField("Allocated Memory (KB)", (float)allocBytes / 1024f);
            }
            else
            {
                EditorGUILayout.IntField("Allocated Memory", (int)allocBytes);
            }

            if (poolBytes != 0)
            {
                EditorGUILayout.IntField("Pool Size", (int)poolBytes);
                EditorGUILayout.FloatField("Used (%)", (float)allocBytes * 100f / poolBytes);
            }

            EditorGUILayout.IntField("Exported Types", vm.GetExportedTypeCount());

            var objectCache = vm.GetObjectCache();

            EditorGUILayout.IntField("ManagedObject Count", objectCache.GetManagedObjectCount());
            EditorGUILayout.IntField("JSObject Count", objectCache.GetJSObjectCount());
            EditorGUILayout.IntField("Delegate Count", objectCache.GetDelegateCount());

            var scheduler = DuktapeRunner.GetScheduler();

            if (scheduler != null)
            {
                EditorGUILayout.IntField("Active Timer", scheduler.GetActiveTimeHandleCount());
            }
        }
Exemple #26
0
        // push 一个对象实例 (调用者需要自行负责提前null检查)
        private static void duk_push_object(IntPtr ctx, object o)
        {
            var    cache = DuktapeVM.GetObjectCache(ctx);
            IntPtr heapptr;

            if (cache.TryGetJSValue(o, out heapptr))
            {
                // Debug.LogWarningFormat("cache hit push {0}", heapptr);
                DuktapeDLL.duk_push_heapptr(ctx, heapptr);
                return;
            }
            DuktapeDLL.duk_push_object(ctx);
            duk_bind_native(ctx, -1, o);
        }
Exemple #27
0
 private static void OnPlayModeStateChanged(PlayModeStateChange playModeStateChange)
 {
     if (playModeStateChange == PlayModeStateChange.EnteredEditMode)
     {
         EditorApplication.delayCall += () =>
         {
             var vm = DuktapeVM.GetInstance();
             if (vm != null)
             {
                 vm.Destroy();
             }
         };
     }
 }
Exemple #28
0
        public static int duk_dostring(IntPtr ctx)
        {
            // var source = DuktapeDLL.duk_get_string(ctx, 0);
            uint len;
            var  buffer_ptr = DuktapeDLL.duk_unity_get_lstring(ctx, 0, out len);

            if (len > 0)
            {
                var bytes = new byte[len];
                Marshal.Copy(buffer_ptr, bytes, 0, (int)len);
                var filename = DuktapeDLL.duk_get_string(ctx, 1);
                DuktapeVM.GetVM(ctx).EvalSource(filename, bytes);
            }
            return(0);
        }
 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);
 }
Exemple #30
0
        public DuktapeThread(DuktapeFunction fn)
        {
            var ctx = fn.ctx;
            var vm  = DuktapeVM.GetContext(ctx).vm;
            var idx = DuktapeDLL.duk_push_thread(ctx);

            DuktapeDLL.duk_dup(ctx, -1);
            var ptr = DuktapeDLL.duk_get_heapptr(ctx, -1);

            _thread        = new DuktapeValue(ctx, DuktapeDLL.duk_unity_ref(ctx), ptr);
            _threadContext = new DuktapeContext(vm, DuktapeDLL.duk_get_context(ctx, idx));
            if (fn.Push(_threadContext.rawValue))
            {
            }

            DuktapeDLL.duk_pop(ctx);
        }