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 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 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); }
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; } } }
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 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); }
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 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); }
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); }
// 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); }
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); }
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); }
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); }
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); }
// 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); }
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()); } }
// 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); }
private static void OnPlayModeStateChanged(PlayModeStateChange playModeStateChange) { if (playModeStateChange == PlayModeStateChange.EnteredEditMode) { EditorApplication.delayCall += () => { var vm = DuktapeVM.GetInstance(); if (vm != null) { vm.Destroy(); } }; } }
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); }
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); }