예제 #1
0
        public ScriptContext(ScriptRuntime runtime, int contextId)
        {
            _isValid   = true;
            _runtime   = runtime;
            _contextId = contextId;
            _ctx       = JSApi.JS_NewContext(_runtime);
            JSApi.JS_SetContextOpaque(_ctx, (IntPtr)_contextId);
            JSApi.JS_AddIntrinsicOperators(_ctx);
            _atoms            = new AtomCache(_ctx);
            _stringCache      = new JSStringCache(_ctx);
            _moduleCache      = JSApi.JS_NewObject(_ctx);
            _loadedModuleHash = new Dictionary <string, string>();

            _globalObject        = JSApi.JS_GetGlobalObject(_ctx);
            _objectConstructor   = JSApi.JS_GetProperty(_ctx, _globalObject, JSApi.JS_ATOM_Object);
            _numberConstructor   = JSApi.JS_GetProperty(_ctx, _globalObject, JSApi.JS_ATOM_Number);
            _proxyConstructor    = JSApi.JS_GetProperty(_ctx, _globalObject, JSApi.JS_ATOM_Proxy);
            _stringConstructor   = JSApi.JS_GetProperty(_ctx, _globalObject, JSApi.JS_ATOM_String);
            _functionConstructor = JSApi.JS_GetProperty(_ctx, _globalObject, JSApi.JS_ATOM_Function);
            _operatorCreate      = JSApi.JS_UNDEFINED;

            var operators = JSApi.JS_GetProperty(_ctx, _globalObject, JSApi.JS_ATOM_Operators);

            if (!operators.IsNullish())
            {
                if (operators.IsException())
                {
                    _ctx.print_exception();
                }
                else
                {
                    var create = JSApi.JS_GetProperty(_ctx, operators, GetAtom("create"));
                    JSApi.JS_FreeValue(_ctx, operators);
                    if (create.IsException())
                    {
                        _ctx.print_exception();
                    }
                    else
                    {
                        if (JSApi.JS_IsFunction(_ctx, create) == 1)
                        {
                            _operatorCreate = create;

                            // Function.prototype[Symbol.operatorSet] = Operators.create();
                            CreateDefaultOperators(_functionConstructor);
                        }
                        else
                        {
                            JSApi.JS_FreeValue(_ctx, create);
                        }
                    }
                }
            }
        }
예제 #2
0
 public void Reset()
 {
     if (_resetValid)
     {
         var rval = JSApi.JS_Call(_ctx, _resetFunc, _this_obj);
         if (rval.IsException())
         {
             _ctx.print_exception();
         }
         JSApi.JS_FreeValue(_ctx, rval);
     }
 }
예제 #3
0
 private void Call(JSValue func_obj)
 {
     if (JSApi.JS_IsFunction(_ctx, func_obj) == 1)
     {
         var rval = JSApi.JS_Call(_ctx, func_obj, _this_obj);
         if (rval.IsException())
         {
             _ctx.print_exception();
         }
         JSApi.JS_FreeValue(_ctx, rval);
     }
 }
예제 #4
0
        public static JSValue _js_game_object_get_components_in_parent(JSContext ctx, JSValue ctor, GameObject gameObject, Type type, bool includeInactive)
        {
            if (JSApi.JS_IsConstructor(ctx, ctor) == 1)
            {
                var header = JSApi.jsb_get_payload_header(ctor);
                if (header.type_id == BridgeObjectType.None) // it's a plain js value
                {
                    if (type == typeof(MonoBehaviour))
                    {
                        var array      = JSApi.JS_NewArray(ctx);
                        var length     = 0;
                        var allBridges = gameObject.GetComponentsInParent <JSBehaviour>(includeInactive);
                        for (int i = 0, size = allBridges.Length; i < size; i++)
                        {
                            var bridge     = allBridges[i];
                            var instanceOf = bridge.IsInstanceOf(ctor);
                            if (instanceOf == 1)
                            {
                                JSApi.JS_SetPropertyUint32(ctx, array, (uint)length, bridge.CloneValue());
                                length++;
                            }

                            if (instanceOf == -1)
                            {
                                ctx.print_exception();
                            }
                        }

                        return(array); // or return an empty array?
                    }
                }
            }

            return(JSApi.JS_UNDEFINED);
        }
예제 #5
0
        public static JSValue _js_game_object_get_components(JSContext ctx, JSValue ctor, GameObject gameObject, Type type, List <Component> results)
        {
            if (JSApi.JS_IsConstructor(ctx, ctor) == 1)
            {
                var header = JSApi.jsb_get_payload_header(ctor);
                if (header.type_id == BridgeObjectType.None) // it's a plain js value
                {
                    if (type == typeof(MonoBehaviour))
                    {
                        var allBridges = gameObject.GetComponents <JSBehaviour>();
                        for (int i = 0, size = allBridges.Length; i < size; i++)
                        {
                            var bridge     = allBridges[i];
                            var instanceOf = bridge.IsInstanceOf(ctor);
                            if (instanceOf == 1)
                            {
                                results.Add(bridge);
                            }

                            if (instanceOf == -1)
                            {
                                ctx.print_exception();
                            }
                        }

                        return(JSApi.JS_NULL);
                    }
                }
            }

            return(JSApi.JS_UNDEFINED);
        }
예제 #6
0
        public unsafe void EvalMain(byte[] input_bytes, string fileName)
        {
            var dirname        = PathUtils.GetDirectoryName(fileName);
            var filename_bytes = TextUtils.GetNullTerminatedBytes(fileName);
            var filename_atom  = GetAtom(fileName);
            var dirname_atom   = GetAtom(dirname);

            var exports_obj  = JSApi.JS_NewObject(_ctx);
            var require_obj  = JSApi.JS_DupValue(_ctx, _require);
            var module_obj   = _new_commonjs_module("", exports_obj, true);
            var filename_obj = JSApi.JS_AtomToString(_ctx, filename_atom);
            var dirname_obj  = JSApi.JS_AtomToString(_ctx, dirname_atom);
            var require_argv = new JSValue[5] {
                exports_obj, require_obj, module_obj, filename_obj, dirname_obj
            };

            JSApi.JS_SetProperty(_ctx, require_obj, GetAtom("moduleId"), JSApi.JS_DupValue(_ctx, filename_obj));

            fixed(byte *input_ptr = input_bytes)
            fixed(byte *resolved_id_ptr = filename_bytes)
            {
                var input_len = (size_t)(input_bytes.Length - 1);
                var func_val  = JSApi.JS_Eval(_ctx, input_ptr, input_len, resolved_id_ptr, JSEvalFlags.JS_EVAL_TYPE_GLOBAL | JSEvalFlags.JS_EVAL_FLAG_STRICT);

                if (func_val.IsException())
                {
                    FreeValues(require_argv);
                    _ctx.print_exception();
                    return;
                }

                if (JSApi.JS_IsFunction(_ctx, func_val) == 1)
                {
                    var rval = JSApi.JS_Call(_ctx, func_val, JSApi.JS_UNDEFINED, require_argv.Length, require_argv);
                    if (rval.IsException())
                    {
                        JSApi.JS_FreeValue(_ctx, func_val);
                        FreeValues(require_argv);
                        _ctx.print_exception();
                        return;
                    }
                }

                JSApi.JS_FreeValue(_ctx, func_val);
                FreeValues(require_argv);
            }
        }
예제 #7
0
        public ScriptContext(ScriptRuntime runtime, int contextId)
        {
            _isValid   = true;
            _runtime   = runtime;
            _contextId = contextId;
            _ctx       = JSApi.JS_NewContext(_runtime);
            JSApi.JS_SetContextOpaque(_ctx, (IntPtr)_contextId);
            JSApi.JS_AddIntrinsicOperators(_ctx);
            _atoms       = new AtomCache(_ctx);
            _moduleCache = JSApi.JS_NewObject(_ctx);

            _globalObject      = JSApi.JS_GetGlobalObject(_ctx);
            _numberConstructor = JSApi.JS_GetProperty(_ctx, _globalObject, JSApi.JS_ATOM_Number);
            _stringConstructor = JSApi.JS_GetProperty(_ctx, _globalObject, JSApi.JS_ATOM_String);
            _operatorCreate    = JSApi.JS_UNDEFINED;

            var operators = JSApi.JS_GetProperty(_ctx, _globalObject, JSApi.JS_ATOM_Operators);

            if (!operators.IsNullish())
            {
                if (operators.IsException())
                {
                    _ctx.print_exception();
                }
                else
                {
                    var create = JSApi.JS_GetProperty(_ctx, operators, GetAtom("create"));
                    JSApi.JS_FreeValue(_ctx, operators);
                    if (create.IsException())
                    {
                        _ctx.print_exception();
                    }
                    else
                    {
                        if (JSApi.JS_IsFunction(_ctx, create) == 1)
                        {
                            _operatorCreate = create;
                        }
                        else
                        {
                            JSApi.JS_FreeValue(_ctx, create);
                        }
                    }
                }
            }
        }
예제 #8
0
        public unsafe byte[] Compile(string filename, byte[] input_bytes, bool commonJSModule)
        {
            byte[] outputBytes = null;
            try
            {
                byte[] fn_bytes = null;
                if (commonJSModule)
                {
                    input_bytes = Utils.TextUtils.GetShebangNullTerminatedCommonJSBytes(input_bytes);
                }

                fn_bytes = Utils.TextUtils.GetNullTerminatedBytes(filename);
                fixed(byte *input_ptr = input_bytes)
                fixed(byte *fn_ptr = fn_bytes)
                {
                    var evalFlags = JSEvalFlags.JS_EVAL_FLAG_COMPILE_ONLY | JSEvalFlags.JS_EVAL_FLAG_STRICT;
                    var input_len = (size_t)(input_bytes.Length - 1);

                    if (!commonJSModule)
                    {
                        evalFlags |= JSEvalFlags.JS_EVAL_TYPE_MODULE;
                    }

                    var rval = JSApi.JS_Eval(_ctx, input_ptr, input_len, fn_ptr, evalFlags);

                    if (JSApi.JS_IsException(rval))
                    {
                        _ctx.print_exception(_logger, LogLevel.Error, "[ScriptCompiler]");
                    }
                    else
                    {
                        size_t psize;
                        var    byteCode = JSApi.JS_WriteObject(_ctx, out psize, rval, JSApi.JS_WRITE_OBJ_BYTECODE);
                        JSApi.JS_FreeValue(_ctx, rval);
                        if (byteCode != IntPtr.Zero)
                        {
                            var  tagSize  = sizeof(uint);
                            uint tagValue = commonJSModule ? ScriptRuntime.BYTECODE_COMMONJS_MODULE_TAG : ScriptRuntime.BYTECODE_ES6_MODULE_TAG;

                            outputBytes = new byte[psize + tagSize];
                            Buffer.BlockCopy(BitConverter.GetBytes(Utils.TextUtils.ToNetworkByteOrder(tagValue)), 0, outputBytes, 0, tagSize);
                            Marshal.Copy(byteCode, outputBytes, tagSize, psize);
                        }
                        JSApi.js_free(_ctx, byteCode);
                    }
                }
                return(outputBytes);
            }
            catch (Exception exception)
            {
                Debug.LogError(exception);
                return(null);
            }
        }
예제 #9
0
        private void OnError(IntPtr @in, size_t len)
        {
            JSValue val = JSApi.JS_UNDEFINED;

            if (len > 0)
            {
                unsafe
                {
                    byte *ptr = (byte *)@in;
                    if (ptr[len] == 0)
                    {
                        val = JSApi.JS_NewString(_jsContext, ptr);
                        if (val.IsException())
                        {
                            _jsContext.print_exception();
                            val = JSApi.JS_UNDEFINED;
                        }
                    }
                }
            }
            else
            {
                val = JSApi.JS_NewString(_jsContext, "connection timeout");
                if (val.IsException())
                {
                    _jsContext.print_exception();
                    val = JSApi.JS_UNDEFINED;
                }
            }
            CallScript("onerror", val);
            JSApi.JS_FreeValue(_jsContext, val);
        }
예제 #10
0
        public static unsafe JSModuleDef module_loader(JSContext ctx, string module_name, IntPtr opaque)
        {
            // Debug.LogFormat("module_loader: {0}", module_name);
            var mod        = JSModuleDef.Null;
            var runtime    = ScriptEngine.GetRuntime(ctx);
            var fileSystem = runtime._fileSystem;

            if (fileSystem.Exists(module_name))
            {
                var source      = fileSystem.ReadAllBytes(module_name);
                var input_bytes = TextUtils.GetNullTerminatedBytes(source);
                var fn_bytes    = TextUtils.GetNullTerminatedBytes(module_name);

                fixed(byte *input_ptr = input_bytes)
                fixed(byte *fn_ptr = fn_bytes)
                {
                    var input_len = (size_t)(input_bytes.Length - 1);
                    var func_val  = JSApi.JS_Eval(ctx, input_ptr, input_len, fn_ptr,
                                                  JSEvalFlags.JS_EVAL_TYPE_MODULE | JSEvalFlags.JS_EVAL_FLAG_COMPILE_ONLY);

                    if (JSApi.JS_IsException(func_val))
                    {
                        ctx.print_exception();
                        JSApi.JS_ThrowReferenceError(ctx, "module error");
                    }
                    else if (func_val.IsNullish())
                    {
                        JSApi.JS_ThrowReferenceError(ctx, "module is null");
                    }
                    else
                    {
                        mod = new JSModuleDef(func_val.u.ptr);
                        var meta = JSApi.JS_GetImportMeta(ctx, mod);
                        JSApi.JS_DefinePropertyValueStr(ctx, meta, "url",
                                                        JSApi.JS_NewString(ctx, $"file://{module_name}"), JSPropFlags.JS_PROP_C_W_E);
                        JSApi.JS_DefinePropertyValueStr(ctx, meta, "main",
                                                        JSApi.JS_NewBool(ctx, false), JSPropFlags.JS_PROP_C_W_E);
                        JSApi.JS_FreeValue(ctx, meta);
                    }
                }
            }
            else
            {
                JSApi.JS_ThrowReferenceError(ctx, "module load failed: file not found");
            }

            return(mod);
        }
예제 #11
0
        public void Invoke(JSValue[] argv)
        {
            if (_context == null)
            {
                return;
            }
            JSContext ctx  = _context;
            var       rVal = JSApi.JS_Call(ctx, _jsValue, _thisValue, argv.Length, argv);

            if (JSApi.JS_IsException(rVal))
            {
                ctx.print_exception();
            }

            JSApi.JS_FreeValue(ctx, rVal);
        }
예제 #12
0
        public unsafe byte[] Compile(string filename, byte[] input_bytes, bool commonJSModule)
        {
            byte[] outputBytes = null;
            try
            {
                byte[] fn_bytes = null;
                if (commonJSModule)
                {
                    input_bytes = Utils.TextUtils.GetShebangNullTerminatedCommonJSBytes(input_bytes);
                }

                fn_bytes = Utils.TextUtils.GetNullTerminatedBytes(filename);
                fixed(byte *input_ptr = input_bytes)
                fixed(byte *fn_ptr = fn_bytes)
                {
                    var input_len = (size_t)(input_bytes.Length - 1);
                    var rval      = JSApi.JS_Eval(_ctx, input_ptr, input_len, fn_ptr, JSEvalFlags.JS_EVAL_TYPE_MODULE | JSEvalFlags.JS_EVAL_FLAG_COMPILE_ONLY);

                    if (JSApi.JS_IsException(rval))
                    {
                        _ctx.print_exception();
                    }
                    else
                    {
                        size_t psize;
                        var    byteCode = JSApi.JS_WriteObject(_ctx, out psize, rval, JSApi.JS_WRITE_OBJ_BYTECODE);
                        if (byteCode != IntPtr.Zero)
                        {
                            outputBytes = new byte[psize];
                            Marshal.Copy(byteCode, outputBytes, 0, psize);
                        }
                        JSApi.js_free(_ctx, byteCode);
                    }
                }
                return(outputBytes);
            }
            catch (Exception exception)
            {
                Debug.LogError(exception);
                return(null);
            }
        }
예제 #13
0
        public unsafe void Invoke()
        {
            if (_context == null)
            {
                return;
            }
            JSContext ctx  = _context;
            var       argc = _args == null ? 0 : _args.Length;

            fixed(JSValue *ptr = _args)
            {
                var rVal = JSApi.JS_Call(ctx, _jsValue, _thisValue, argc, ptr);

                if (JSApi.JS_IsException(rVal))
                {
                    ctx.print_exception();
                }

                JSApi.JS_FreeValue(ctx, rVal);
            }
        }
예제 #14
0
        public static unsafe JSModuleDef module_loader(JSContext ctx, string module_name, IntPtr opaque)
        {
            // Debug.LogFormat("module_loader: {0}", module_name);
            var runtime    = ScriptEngine.GetRuntime(ctx);
            var fileSystem = runtime._fileSystem;

            if (!fileSystem.Exists(module_name))
            {
                JSApi.JS_ThrowReferenceError(ctx, "module not found");
                return(JSModuleDef.Null);
            }

            var source   = fileSystem.ReadAllBytes(module_name);
            var tagValue = TryReadByteCodeTagValue(source);

            if (tagValue == BYTECODE_COMMONJS_MODULE_TAG)
            {
                JSApi.JS_ThrowReferenceError(ctx, "commonjs module can not be loaded by import");
                return(JSModuleDef.Null);
            }

            if (tagValue == BYTECODE_ES6_MODULE_TAG)
            {
                // bytecode
                fixed(byte *intput_ptr = source)
                {
                    var modObj = JSApi.JS_ReadObject(ctx, intput_ptr + sizeof(uint), source.Length - sizeof(uint), JSApi.JS_READ_OBJ_BYTECODE);

                    if (!modObj.IsModule())
                    {
                        JSApi.JS_FreeValue(ctx, modObj);
                        JSApi.JS_ThrowReferenceError(ctx, "unsupported module object");
                        return(JSModuleDef.Null);
                    }

                    if (JSApi.JS_ResolveModule(ctx, modObj) < 0)
                    {
                        // fail
                        JSApi.JS_FreeValue(ctx, modObj);
                        JSApi.JS_ThrowReferenceError(ctx, "module resolve failed");
                        return(JSModuleDef.Null);
                    }

                    return(_NewModuleDef(ctx, modObj, module_name));
                }
            }

            // source
            var input_bytes = TextUtils.GetNullTerminatedBytes(source);
            var fn_bytes    = TextUtils.GetNullTerminatedBytes(module_name);

            fixed(byte *input_ptr = input_bytes)
            fixed(byte *fn_ptr = fn_bytes)
            {
                var input_len = (size_t)(input_bytes.Length - 1);
                var func_val  = JSApi.JS_Eval(ctx, input_ptr, input_len, fn_ptr, JSEvalFlags.JS_EVAL_TYPE_MODULE | JSEvalFlags.JS_EVAL_FLAG_COMPILE_ONLY);

                if (JSApi.JS_IsException(func_val))
                {
                    ctx.print_exception();
                    JSApi.JS_ThrowReferenceError(ctx, "module error");
                    return(JSModuleDef.Null);
                }

                if (func_val.IsNullish())
                {
                    JSApi.JS_ThrowReferenceError(ctx, "module is null");
                    return(JSModuleDef.Null);
                }

                return(_NewModuleDef(ctx, func_val, module_name));
            }
        }
예제 #15
0
        public unsafe object EvalMain(byte[] source, string module_id, string fullPath, Type expectedReturnType)
        {
            var tagValue = ScriptRuntime.TryReadByteCodeTagValue(source);

            if (tagValue == ScriptRuntime.BYTECODE_ES6_MODULE_TAG)
            {
                throw new Exception("es6 module bytecode as main is unsupported");
            }

            object csValue        = null;
            var    dirname        = PathUtils.GetDirectoryName(module_id);
            var    filename_bytes = TextUtils.GetNullTerminatedBytes(module_id);
            var    module_id_atom = GetAtom(module_id);
            var    dirname_atom   = GetAtom(dirname);
            var    full_path_atom = GetAtom(fullPath);

            var exports_obj   = JSApi.JS_NewObject(_ctx);
            var require_obj   = JSApi.JS_DupValue(_ctx, _require);
            var module_obj    = _new_commonjs_script_module(null, module_id, fullPath, exports_obj, false);
            var module_id_obj = JSApi.JS_AtomToString(_ctx, module_id_atom);
            var filename_obj  = JSApi.JS_AtomToString(_ctx, full_path_atom);
            var dirname_obj   = JSApi.JS_AtomToString(_ctx, dirname_atom);
            var require_argv  = new JSValue[5] {
                exports_obj, require_obj, module_obj, filename_obj, dirname_obj
            };

            JSApi.JS_SetProperty(_ctx, require_obj, GetAtom("moduleId"), JSApi.JS_DupValue(_ctx, module_id_obj));
            JSApi.JS_SetProperty(_ctx, require_obj, GetAtom("main"), JSApi.JS_DupValue(_ctx, module_obj));

            if (tagValue == ScriptRuntime.BYTECODE_COMMONJS_MODULE_TAG)
            {
                // bytecode
                fixed(byte *intput_ptr = source)
                {
                    var bytecodeFunc = JSApi.JS_ReadObject(_ctx, intput_ptr + sizeof(uint), source.Length - sizeof(uint), JSApi.JS_READ_OBJ_BYTECODE);

                    if (bytecodeFunc.tag == JSApi.JS_TAG_FUNCTION_BYTECODE)
                    {
                        var func_val = JSApi.JS_EvalFunction(_ctx, bytecodeFunc); // it's CallFree (bytecodeFunc)
                        if (JSApi.JS_IsFunction(_ctx, func_val) != 1)
                        {
                            JSApi.JS_FreeValue(_ctx, func_val);
                            FreeValues(require_argv);
                            throw new Exception("failed to eval bytecode module");
                        }

                        var rval = JSApi.JS_Call(_ctx, func_val, JSApi.JS_UNDEFINED);
                        JSApi.JS_FreeValue(_ctx, func_val);
                        if (rval.IsException())
                        {
                            _ctx.print_exception();
                            JSApi.JS_FreeValue(_ctx, rval);
                            FreeValues(require_argv);
                            throw new Exception("failed to eval bytecode module");
                        }

                        // success
                        Values.js_get_var(_ctx, rval, expectedReturnType, out csValue);
                        JSApi.JS_FreeValue(_ctx, rval);
                        JSApi.JS_SetProperty(_ctx, module_obj, GetAtom("loaded"), JSApi.JS_NewBool(_ctx, true));
                        FreeValues(require_argv);
                        return(csValue);
                    }

                    JSApi.JS_FreeValue(_ctx, bytecodeFunc);
                    FreeValues(require_argv);
                    throw new Exception("failed to eval bytecode module");
                }
            }
            else
            {
                // source
                var input_bytes = TextUtils.GetShebangNullTerminatedCommonJSBytes(source);
                fixed(byte *input_ptr = input_bytes)
                fixed(byte *resolved_id_ptr = filename_bytes)
                {
                    var input_len = (size_t)(input_bytes.Length - 1);
                    var func_val  = JSApi.JS_Eval(_ctx, input_ptr, input_len, resolved_id_ptr, JSEvalFlags.JS_EVAL_TYPE_GLOBAL | JSEvalFlags.JS_EVAL_FLAG_STRICT);

                    if (func_val.IsException())
                    {
                        FreeValues(require_argv);
                        _ctx.print_exception();
                        throw new Exception("failed to eval module");
                    }

                    if (JSApi.JS_IsFunction(_ctx, func_val) == 1)
                    {
                        var rval = JSApi.JS_Call(_ctx, func_val, JSApi.JS_UNDEFINED, require_argv.Length, require_argv);
                        if (rval.IsException())
                        {
                            JSApi.JS_FreeValue(_ctx, func_val);
                            FreeValues(require_argv);
                            _ctx.print_exception();
                            throw new Exception("failed to eval module");
                        }
                        Values.js_get_var(_ctx, rval, expectedReturnType, out csValue);
                        JSApi.JS_FreeValue(_ctx, rval);
                    }

                    JSApi.JS_FreeValue(_ctx, func_val);
                    JSApi.JS_SetProperty(_ctx, module_obj, GetAtom("loaded"), JSApi.JS_NewBool(_ctx, true));
                    FreeValues(require_argv);
                    return(csValue);
                }
            }
        }
예제 #16
0
        ///<summary>
        /// 实际定义运算符重载 (请保证 create 本身有效)
        ///</summary>
        public unsafe void Register(TypeRegister register, JSContext ctx, JSValue create)
        {
            var proto = register.FindChainedPrototypeOf(type);
            var argv  = new JSValue[_count];

            argv[0] = JSApi.JS_NewObject(ctx);
            for (int i = 0, len = self.Count; i < len; i++)
            {
                var def = self[i];
                // var funcVal = JSApi.JS_NewCFunction(ctx, def.func, def.op, def.length);
                JSApi.JS_DefinePropertyValue(ctx, argv[0], register.GetAtom(def.op), def.value, JSPropFlags.DEFAULT);
                // Debug.LogFormat("{0} operator {1}", type, def.op);
            }

            for (int i = 0, len = left.Count; i < len; i++)
            {
                var cross     = left[i];
                var sideCtor  = register.GetConstructor(cross.type);
                var operator_ = JSApi.JS_NewObject(ctx);
                var side      = "left";
                JSApi.JS_SetProperty(ctx, operator_, register.GetAtom(side), sideCtor);
                for (int opIndex = 0, opCount = cross.operators.Count; opIndex < opCount; opIndex++)
                {
                    var def = cross.operators[opIndex];
                    // var funcVal = JSApi.JS_NewCFunction(ctx, def.func, def.op, def.length);
                    JSApi.JS_DefinePropertyValue(ctx, operator_, register.GetAtom(def.op), def.value, JSPropFlags.DEFAULT);
                    argv[i + 1] = operator_;
                    // Debug.LogFormat("{0} {1} operator {2} {3} ({4})", type, side, def.op, cross.type, sideCtor);
                }
            }

            for (int i = 0, len = right.Count; i < len; i++)
            {
                var cross     = right[i];
                var sideCtor  = register.GetConstructor(cross.type);
                var operator_ = JSApi.JS_NewObject(ctx);
                var side      = "right";
                JSApi.JS_SetProperty(ctx, operator_, register.GetAtom(side), sideCtor);
                for (int opIndex = 0, opCount = cross.operators.Count; opIndex < opCount; opIndex++)
                {
                    var def = cross.operators[opIndex];
                    // var funcVal = JSApi.JS_NewCFunction(ctx, def.func, def.op, def.length);
                    JSApi.JS_DefinePropertyValue(ctx, operator_, register.GetAtom(def.op), def.value, JSPropFlags.DEFAULT);
                    argv[i + 1 + left.Count] = operator_;
                    // Debug.LogFormat("{0} {1} operator {2} {3} ({4})", type, side, def.op, cross.type, sideCtor);
                }
            }

            fixed(JSValue *ptr = argv)
            {
                var rval = JSApi.JS_Call(ctx, create, JSApi.JS_UNDEFINED, argv.Length, ptr);

                if (rval.IsException())
                {
                    ctx.print_exception(Utils.LogLevel.Warn, string.Format("[{0} operators failed]", type));
                }
                else
                {
                    JSApi.JS_DefinePropertyValue(ctx, proto, JSApi.JS_ATOM_Symbol_operatorSet, rval, JSPropFlags.DEFAULT);
                }
            }

            for (int i = 0, len = argv.Length; i < len; i++)
            {
                JSApi.JS_FreeValue(ctx, argv[i]);
            }
        }