public static bool js_get_delegate(JSContext ctx, JSValue val, Type delegateType, out Delegate o) { //TODO: 20200320 !!! 如果 o 不是 jsobject, 且是 Delegate 但不是 ScriptDelegate, 则 ... 处理 if (val.IsNullish()) { o = null; return(true); } if (JSApi.JS_IsObject(val) || JSApi.JS_IsFunction(ctx, val) == 1) { ScriptDelegate fn; var cache = ScriptEngine.GetObjectCache(ctx); if (cache.TryGetDelegate(val, out fn)) { // Debug.LogWarningFormat("cache hit {0}", heapptr); o = fn.Match(delegateType); if (o == null) { var types = ScriptEngine.GetTypeDB(ctx); var func = types.GetDelegateFunc(delegateType); o = Delegate.CreateDelegate(delegateType, fn, func, false); if (o != null) { fn.Add(o); } } return(o != null); } else { // 默认赋值操作 var types = ScriptEngine.GetTypeDB(ctx); var func = types.GetDelegateFunc(delegateType); if (func == null) { o = null; return(false); } fn = new ScriptDelegate(ScriptEngine.GetContext(ctx), val); o = Delegate.CreateDelegate(delegateType, fn, func, false); if (o != null) { fn.Add(o); } // ScriptDelegate 拥有 js 对象的强引用, 此 js 对象无法释放 cache 中的 object, 所以这里用弱引用注册 // 会出现的问题是, 如果 c# 没有对 ScriptDelegate 的强引用, 那么反复 get_delegate 会重复创建 ScriptDelegate // Debug.LogWarningFormat("cache create : {0}", heapptr); cache.AddDelegate(val, fn); return(o != null); } } // else if (DuktapeDLL.duk_is_object(ctx, idx)) // { // return js_get_classvalue<T>(ctx, idx, out o); // } o = null; return(false); }
/// <summary> /// 从 JSValue 反推 Delegate, JSValue 可能是一个 js function, cs delegate (js object) <br/> /// 注意: 会自动创建 ScriptDelegate 映射 /// </summary> public static bool js_get_delegate(JSContext ctx, JSValue val, Type delegateType, out Delegate o) { if (val.IsNullish()) { o = null; return(true); } // 检查 val 是否是一个委托对象 wrapped object if (JSApi.JS_IsObject(val)) { if (js_get_classvalue <Delegate>(ctx, val, out o)) { return(o == null || o.GetType() == delegateType); } if (JSApi.JS_IsFunction(ctx, val) == 1) { ScriptDelegate fn; var cache = ScriptEngine.GetObjectCache(ctx); if (cache.TryGetDelegate(val, out fn)) { // 已经存在映射关系, 找出符合预期类型的委托 o = fn.Match(delegateType); if (o == null) { // 存在 JSValue => Delegate 的多重映射 var types = ScriptEngine.GetTypeDB(ctx); var func = types.GetDelegateFunc(delegateType); o = Delegate.CreateDelegate(delegateType, fn, func, false); if (o != null) { fn.Add(o); } } return(o != null); } else { // 建立新的映射关系 var context = ScriptEngine.GetContext(ctx); var types = context.GetTypeDB(); var func = types.GetDelegateFunc(delegateType); if (func == null) { o = null; return(false); } fn = new ScriptDelegate(context, val); o = Delegate.CreateDelegate(delegateType, fn, func, false); if (o != null) { fn.Add(o); } return(o != null); } } } o = null; return(false); }