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); } } } } }
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); } }
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); } }
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); }
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); }
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); } }
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); } } } } }
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); } }
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); }
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); }
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); }
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); } }
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); } }
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)); } }
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); } } }
///<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]); } }