private void Db_OnError(object obj, JavaScriptException e) { SetOutPut(string.Format("{0}脚本运行出错,第{2}行第{3}列,错误信息:{1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), e.Message, e.LineNumber, e.Column)); //将运行标签去除 SetCaretMark(null); SetControlsStatus(false); }
} // End Class JavaScriptException public void ProcessRequest(System.Web.HttpContext context) { // referer is html document. string refe = context.Request.UrlReferrer.OriginalString; string postData = "Referrer: " + refe + System.Environment.NewLine; if (context.Request.Form != null) { foreach (string key in context.Request.Form.AllKeys) { postData += key + ": " + context.Request.Form[key] + System.Environment.NewLine; } // Next key } // End if (context.Request.Form != null) System.Console.WriteLine(postData); if (context.Request.InputStream != null) { using (System.IO.StreamReader stream = new System.IO.StreamReader(context.Request.InputStream)) { string json = stream.ReadToEnd(); json = JsonPrettyPrinter.Format(json); PostData data = Newtonsoft.Json.JsonConvert.DeserializeObject <PostData>(json); JavaScriptException exJS = new JavaScriptException(data); System.Console.WriteLine(data); System.Console.WriteLine(exJS); } // End Using stream } // End if (context.Request.InputStream != null) context.Response.ContentType = "text/plain"; context.Response.Write("Hello World"); } // End Sub ProcessRequest
public Engine Execute(Program program) { ResetStatementsCount(); ResetTimeoutTicks(); ResetLastStatement(); ResetCallStack(); var scope = PoolStrictMode.Get(); scope.Setup(Options._IsStrict || program.Strict); DeclarationBindingInstantiation(DeclarationBindingType.GlobalCode, program.FunctionDeclarations, program.VariableDeclarations, null, null); var result = _statements.ExecuteProgram(program); if (result.Type == Completion.Throw) { var exception = new JavaScriptException(result.GetValueOrDefault()) .SetCallstack(this, result.Location); scope.Teardown(); PoolStrictMode.Put(scope); throw exception; } _completionValue = result.GetValueOrDefault(); scope.Teardown(); PoolStrictMode.Put(scope); return(this); }
public JavaScriptEvaluatorException(int exitCode, string stdout, string stderr, JavaScriptException[] exceptions) : base(String.Format("JavaScript interpreter exited with code {0} after throwing {3} exception(s):\r\n{1}\r\n{2}", exitCode, stdout, stderr, exceptions.Length)) { ExitCode = exitCode; ErrorText = stderr; Output = stdout; Exceptions = exceptions; }
public JavaScriptEvaluatorException (int exitCode, string stdout, string stderr, JavaScriptException[] exceptions) : base(FormatMessage(exitCode, stderr, exceptions)) { ExitCode = exitCode; ErrorText = stderr; Output = stdout; Exceptions = exceptions; }
protected Exception ConvertException(JavaScriptException jse) { // TODO return better stuff. var jsv = CreateJsObject(); jsv.FastAddProperty("message", new JsValue(jse.Message), false, true, false); return(new ManticoreException(jsv)); }
/// <summary> /// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.1 /// </summary> /// <param name="thisArg"></param> /// <param name="arguments"></param> /// <returns></returns> public override JsValue Call(JsValue thisArg, JsValue[] arguments) { using (new StrictModeScope(Strict, true)) { // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3 JsValue thisBinding; if (StrictModeScope.IsStrictModeCode) { thisBinding = thisArg; } else if (thisArg == Undefined.Instance || thisArg == Null.Instance) { thisBinding = Engine.Global; } else if (!thisArg.IsObject()) { thisBinding = TypeConverter.ToObject(Engine, thisArg); } else { thisBinding = thisArg; } var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(Engine, Scope); Engine.EnterExecutionContext(localEnv, localEnv, thisBinding); try { Engine.DeclarationBindingInstantiation( DeclarationBindingType.FunctionCode, _functionDeclaration.FunctionDeclarations, _functionDeclaration.VariableDeclarations, this, arguments); var result = Engine.ExecuteStatement(_functionDeclaration.Body); if (result.Type == Completion.Throw) { JavaScriptException ex = new JavaScriptException(result.GetValueOrDefault()); ex.Location = result.Location; throw ex; } if (result.Type == Completion.Return) { return(result.GetValueOrDefault()); } } finally { Engine.LeaveExecutionContext(); } return(Undefined.Instance); } }
public Error(JScript script, JavaScriptException ex) : base(script.Engine, ((ClrFunction)script.Engine.Global["Error"]).InstancePrototype) { this.error = ex; this.script = script; this.PopulateFields(); this.PopulateFunctions(); }
private static JavaScriptException?CreateJavaScriptException(LogMessage logMessage) { JavaScriptException?jsException = null; if (logMessage.Exception != null && !logMessage.Exception.IsEmpty()) { jsException = new JavaScriptException(logMessage.Exception.Message, logMessage.Exception.StackTrace); } return(jsException); }
public static void Print(this JavaScriptException e) { Terminal.WriteLine($"+==============================================+"); Terminal.WriteLine($"+=| {RCL.Wrap("JavaScript Exception", ConsoleColor.DarkRed)}"); Terminal.WriteLine($"+=| Column :{e.Column}"); Terminal.WriteLine($"+=| Location :{e.Location}"); Terminal.WriteLine($"+=| Line :{e.LineNumber}"); Terminal.WriteLine($"+=| Error :{e.Error}"); Terminal.WriteLine($"+=| Exception:{e.Message}"); Terminal.WriteLine($"+==============================================+"); }
internal void OnError(JavaScriptException jex) { lock (Scripts) { foreach (var s in Scripts) { try { s.Engine.CallGlobalFunction("onError", new Objects.Error(s, jex)); } catch (JavaScriptException) { } } } }
private static string GetType(JavaScriptException exception) { if (exception.InnerException != null) { return(exception.InnerException.GetType().FullName); } if (exception.Error.IsObject()) { return(exception.Error.ToString()); } return(exception.Error.Type.ToString()); }
public JavaScriptEvaluatorException(int exitCode, string stdout, string stderr, JavaScriptException[] exceptions) : base(String.Format( "JavaScript interpreter exited with code {0} after throwing {1} exception(s):\r\n{2}", exitCode, exceptions.Length, string.Join("\r\n", (from exc in exceptions select exc.ToString())) )) { ExitCode = exitCode; ErrorText = stderr; Output = stdout; Exceptions = exceptions; }
private static string FormatMessage (int exitCode, string stderr, JavaScriptException[] exceptions) { if (exceptions.Length == 0) return String.Format( "JavaScript interpreter exited with code {0}:\r\n{1}", exitCode, stderr ); return String.Format( "JavaScript interpreter exited with code {0} after throwing {1} exception(s):\r\n{2}", exitCode, exceptions.Length, string.Join("\r\n", (from exc in exceptions select exc.ToString())) ); }
public static void Show(IWin32Window owner, JavaScriptException exception) { if (owner == null) { throw new ArgumentNullException(nameof(owner)); } if (exception == null) { throw new ArgumentNullException(nameof(exception)); } using (var form = new ExceptionForm()) { form._exceptionThrown.Text = String.Format(form._exceptionThrown.Text, GetType(exception)); form._additionalInformation.Text = String.Format(form._additionalInformation.Text, GetMessage(exception)); form._location.Text = String.Format(form._location.Text, GetLocation(exception)); if (exception.DebugInformation == null || exception.DebugInformation.Globals.Count == 0) { form.Showing += (s, e) => { int dockPanelHeight = form._dockPanel.Height; form._dockPanel.Dispose(); form.MinimumSize = new Size(0, form.Height - dockPanelHeight); form.MaximumSize = new Size(int.MaxValue, form.Height - dockPanelHeight); }; } else { var callStack = new CallStackControl(); callStack.LoadCallStack(exception.DebugInformation); form.ShowPanel(callStack); var globalVariables = new VariablesControl { Text = "Globals" }; globalVariables.LoadVariables(exception.DebugInformation, VariablesMode.Globals); form.ShowPanel(globalVariables); var localVariables = new VariablesControl { Text = "Locals" }; localVariables.LoadVariables(exception.DebugInformation, VariablesMode.Locals); form.ShowPanel(localVariables); callStack.DockHandler.Activate(); } form.ShowDialog(owner); } }
private static string GetMessage(JavaScriptException exception) { if (exception.InnerException != null) { return(exception.InnerException.Message); } if (exception.Error.IsObject()) { if (String.IsNullOrEmpty(exception.Message)) { return("(none)"); } return(exception.Message); } return(exception.Error.ToString()); }
private static void HandleJintException(HttpActionExecutedContext ctx, JavaScriptException e) { //while (e.InnerException is JintException) //{ // e = (JintException)e.InnerException; //} ctx.Response = new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest, }; SerializeError(ctx, new { Url = ctx.Request.RequestUri.PathAndQuery, Error = e.Message }); }
/// <summary> /// Evaluates a script (expression) within the current execution context. /// </summary> /// <remarks> /// Internally, this is used for evaluating breakpoint conditions, but may also be used for e.g. watch lists /// in a debugger. /// </remarks> public JsValue Evaluate(Script script) { var context = _engine._activeEvaluationContext; if (context == null) { throw new DebugEvaluationException("Jint has no active evaluation context"); } int callStackSize = _engine.CallStack.Count; var list = new JintStatementList(null, script.Body); Completion result; try { result = list.Execute(context); } catch (Exception ex) { // An error in the evaluation may return a Throw Completion, or it may throw an exception: throw new DebugEvaluationException("An error occurred during debugger evaluation", ex); } finally { // Restore call stack while (_engine.CallStack.Count > callStackSize) { _engine.CallStack.Pop(); } } if (result.Type == CompletionType.Throw) { // TODO: Should we return an error here? (avoid exception overhead, since e.g. breakpoint // evaluation may be high volume. var error = result.GetValueOrDefault(); var ex = new JavaScriptException(error).SetCallstack(_engine, result.Location); throw new DebugEvaluationException("An error occurred during debugger evaluation", ex); } return(result.GetValueOrDefault()); }
private static string GetLocation(JavaScriptException exception) { if (exception.Location != null) { return(String.Format( "{0}({1},{2},{3},{4})", exception.Location.Source.Source, exception.Location.Start.Line, exception.Location.Start.Column + 1, exception.Location.End.Line, exception.Location.End.Column + 1 )); } var stackTrace = exception.StackTrace; if (stackTrace != null) { return(stackTrace.Split(new[] { '\n' }, 2)[0].Trim()); } return("(none)"); }
public static void PrettyPrintJavaScriptException(JavaScriptException ex) { }
public void LogError(JavaScriptException error) { AppendText(error.ToString(), Color.Red); }
private void HandleAssertInconclusiveException(AssertInconclusiveException ex) { var jsEx = new JavaScriptException(this.Engine, "Error", ex.Message, ex); throw jsEx; }
private static object InterpretLoop(Context cx, Interpreter.CallFrame frame, object throwable) { // throwable holds exception object to rethrow or catch // It is also used for continuation restart in which case // it holds ContinuationJump object DBL_MRK = UniqueTag.DOUBLE_MARK; object undefined = Undefined.instance; bool instructionCounting = (cx.instructionThreshold != 0); // arbitrary number to add to instructionCount when calling // other functions int INVOCATION_COST = 100; // arbitrary exception cost for instruction counting int EXCEPTION_COST = 100; string stringReg = null; int indexReg = -1; if (cx.lastInterpreterFrame != null) { // save the top frame from the previous interpretLoop // invocation on the stack if (cx.previousInterpreterInvocations == null) { cx.previousInterpreterInvocations = new ObjArray(); } cx.previousInterpreterInvocations.Push(cx.lastInterpreterFrame); } // When restarting continuation throwable is not null and to jump // to the code that rewind continuation state indexReg should be set // to -1. // With the normal call throwable == null and indexReg == -1 allows to // catch bugs with using indeReg to access array elements before // initializing indexReg. Interpreter.GeneratorState generatorState = null; if (throwable != null) { if (throwable is Interpreter.GeneratorState) { generatorState = (Interpreter.GeneratorState)throwable; // reestablish this call frame EnterFrame(cx, frame, ScriptRuntime.emptyArgs, true); throwable = null; } else { if (!(throwable is Interpreter.ContinuationJump)) { // It should be continuation Kit.CodeBug(); } } } object interpreterResult = null; double interpreterResultDbl = 0.0; for (; ; ) { try { if (throwable != null) { // Need to return both 'frame' and 'throwable' from // 'processThrowable', so just added a 'throwable' // member in 'frame'. frame = ProcessThrowable(cx, throwable, frame, indexReg, instructionCounting); throwable = frame.throwable; frame.throwable = null; } else { if (generatorState == null && frame.frozen) { Kit.CodeBug(); } } // Use local variables for constant values in frame // for faster access object[] stack = frame.stack; double[] sDbl = frame.sDbl; object[] vars = frame.varSource.stack; double[] varDbls = frame.varSource.sDbl; int[] varAttributes = frame.varSource.stackAttributes; byte[] iCode = frame.idata.itsICode; string[] strings = frame.idata.itsStringTable; // Use local for stackTop as well. Since execption handlers // can only exist at statement level where stack is empty, // it is necessary to save/restore stackTop only across // function calls and normal returns. int stackTop = frame.savedStackTop; // Store new frame in cx which is used for error reporting etc. cx.lastInterpreterFrame = frame; for (; ; ) { // Exception handler assumes that PC is already incremented // pass the instruction start when it searches the // exception handler int op = iCode[frame.pc++]; switch (op) { case Icode_GENERATOR: { // Back indent to ease implementation reading if (!frame.frozen) { // First time encountering this opcode: create new generator // object and return frame.pc--; // we want to come back here when we resume Interpreter.CallFrame generatorFrame = CaptureFrameForGenerator(frame); generatorFrame.frozen = true; NativeGenerator generator = new NativeGenerator(frame.scope, generatorFrame.fnOrScript, generatorFrame); frame.result = generator; goto Loop_break; } goto case Token.YIELD; } case Token.YIELD: { // We are now resuming execution. Fall through to YIELD case. // fall through... if (!frame.frozen) { return FreezeGenerator(cx, frame, stackTop, generatorState); } else { object obj = ThawGenerator(frame, stackTop, generatorState, op); if (obj != ScriptableConstants.NOT_FOUND) { throwable = obj; goto withoutExceptions_break; } goto Loop_continue; } goto case Icode_GENERATOR_END; } case Icode_GENERATOR_END: { // throw StopIteration frame.frozen = true; int sourceLine = GetIndex(iCode, frame.pc); generatorState.returnedException = new JavaScriptException(NativeIterator.GetStopIterationObject(frame.scope), frame.idata.itsSourceFile, sourceLine); goto Loop_break; } case Token.THROW: { object value = stack[stackTop]; if (value == DBL_MRK) { value = ScriptRuntime.WrapNumber(sDbl[stackTop]); } --stackTop; int sourceLine = GetIndex(iCode, frame.pc); throwable = new JavaScriptException(value, frame.idata.itsSourceFile, sourceLine); goto withoutExceptions_break; } case Token.RETHROW: { indexReg += frame.localShift; throwable = stack[indexReg]; goto withoutExceptions_break; } case Token.GE: case Token.LE: case Token.GT: case Token.LT: { stackTop = DoCompare(frame, op, stack, sDbl, stackTop); goto Loop_continue; } case Token.IN: case Token.INSTANCEOF: { stackTop = DoInOrInstanceof(cx, op, stack, sDbl, stackTop); goto Loop_continue; } case Token.EQ: case Token.NE: { --stackTop; bool valBln = DoEquals(stack, sDbl, stackTop); valBln ^= (op == Token.NE); stack[stackTop] = ScriptRuntime.WrapBoolean(valBln); goto Loop_continue; } case Token.SHEQ: case Token.SHNE: { --stackTop; bool valBln = DoShallowEquals(stack, sDbl, stackTop); valBln ^= (op == Token.SHNE); stack[stackTop] = ScriptRuntime.WrapBoolean(valBln); goto Loop_continue; } case Token.IFNE: { if (Stack_boolean(frame, stackTop--)) { frame.pc += 2; goto Loop_continue; } goto jumplessRun_break; } case Token.IFEQ: { if (!Stack_boolean(frame, stackTop--)) { frame.pc += 2; goto Loop_continue; } goto jumplessRun_break; } case Icode_IFEQ_POP: { if (!Stack_boolean(frame, stackTop--)) { frame.pc += 2; goto Loop_continue; } stack[stackTop--] = null; goto jumplessRun_break; } case Token.GOTO: { goto jumplessRun_break; } case Icode_GOSUB: { ++stackTop; stack[stackTop] = DBL_MRK; sDbl[stackTop] = frame.pc + 2; goto jumplessRun_break; } case Icode_STARTSUB: { if (stackTop == frame.emptyStackTop + 1) { // Call from Icode_GOSUB: store return PC address in the local indexReg += frame.localShift; stack[indexReg] = stack[stackTop]; sDbl[indexReg] = sDbl[stackTop]; --stackTop; } else { // Call from exception handler: exception object is already stored // in the local if (stackTop != frame.emptyStackTop) { Kit.CodeBug(); } } goto Loop_continue; } case Icode_RETSUB: { // indexReg: local to store return address if (instructionCounting) { AddInstructionCount(cx, frame, 0); } indexReg += frame.localShift; object value = stack[indexReg]; if (value != DBL_MRK) { // Invocation from exception handler, restore object to rethrow throwable = value; goto withoutExceptions_break; } // Normal return from GOSUB frame.pc = (int)sDbl[indexReg]; if (instructionCounting) { frame.pcPrevBranch = frame.pc; } goto Loop_continue; } case Icode_POP: { stack[stackTop] = null; stackTop--; goto Loop_continue; } case Icode_POP_RESULT: { frame.result = stack[stackTop]; frame.resultDbl = sDbl[stackTop]; stack[stackTop] = null; --stackTop; goto Loop_continue; } case Icode_DUP: { stack[stackTop + 1] = stack[stackTop]; sDbl[stackTop + 1] = sDbl[stackTop]; stackTop++; goto Loop_continue; } case Icode_DUP2: { stack[stackTop + 1] = stack[stackTop - 1]; sDbl[stackTop + 1] = sDbl[stackTop - 1]; stack[stackTop + 2] = stack[stackTop]; sDbl[stackTop + 2] = sDbl[stackTop]; stackTop += 2; goto Loop_continue; } case Icode_SWAP: { object o = stack[stackTop]; stack[stackTop] = stack[stackTop - 1]; stack[stackTop - 1] = o; double d = sDbl[stackTop]; sDbl[stackTop] = sDbl[stackTop - 1]; sDbl[stackTop - 1] = d; goto Loop_continue; } case Token.RETURN: { frame.result = stack[stackTop]; frame.resultDbl = sDbl[stackTop]; --stackTop; goto Loop_break; } case Token.RETURN_RESULT: { goto Loop_break; } case Icode_RETUNDEF: { frame.result = undefined; goto Loop_break; } case Token.BITNOT: { int rIntValue = Stack_int32(frame, stackTop); stack[stackTop] = DBL_MRK; sDbl[stackTop] = ~rIntValue; goto Loop_continue; } case Token.BITAND: case Token.BITOR: case Token.BITXOR: case Token.LSH: case Token.RSH: { stackTop = DoBitOp(frame, op, stack, sDbl, stackTop); goto Loop_continue; } case Token.URSH: { double lDbl = Stack_double(frame, stackTop - 1); int rIntValue = Stack_int32(frame, stackTop) & unchecked((int)(0x1F)); stack[--stackTop] = DBL_MRK; sDbl[stackTop] = (long)(((ulong)ScriptRuntime.ToUint32(lDbl)) >> rIntValue); goto Loop_continue; } case Token.NEG: case Token.POS: { double rDbl = Stack_double(frame, stackTop); stack[stackTop] = DBL_MRK; if (op == Token.NEG) { rDbl = -rDbl; } sDbl[stackTop] = rDbl; goto Loop_continue; } case Token.ADD: { --stackTop; DoAdd(stack, sDbl, stackTop, cx); goto Loop_continue; } case Token.SUB: case Token.MUL: case Token.DIV: case Token.MOD: { stackTop = DoArithmetic(frame, op, stack, sDbl, stackTop); goto Loop_continue; } case Token.NOT: { stack[stackTop] = ScriptRuntime.WrapBoolean(!Stack_boolean(frame, stackTop)); goto Loop_continue; } case Token.BINDNAME: { stack[++stackTop] = ScriptRuntime.Bind(cx, frame.scope, stringReg); goto Loop_continue; } case Token.STRICT_SETNAME: case Token.SETNAME: { object rhs = stack[stackTop]; if (rhs == DBL_MRK) { rhs = ScriptRuntime.WrapNumber(sDbl[stackTop]); } --stackTop; Scriptable lhs = (Scriptable)stack[stackTop]; stack[stackTop] = op == Token.SETNAME ? ScriptRuntime.SetName(lhs, rhs, cx, frame.scope, stringReg) : ScriptRuntime.StrictSetName(lhs, rhs, cx, frame.scope, stringReg); goto Loop_continue; } case Icode_SETCONST: { object rhs = stack[stackTop]; if (rhs == DBL_MRK) { rhs = ScriptRuntime.WrapNumber(sDbl[stackTop]); } --stackTop; Scriptable lhs = (Scriptable)stack[stackTop]; stack[stackTop] = ScriptRuntime.SetConst(lhs, rhs, cx, stringReg); goto Loop_continue; } case Token.DELPROP: case Icode_DELNAME: { stackTop = DoDelName(cx, op, stack, sDbl, stackTop); goto Loop_continue; } case Token.GETPROPNOWARN: { object lhs = stack[stackTop]; if (lhs == DBL_MRK) { lhs = ScriptRuntime.WrapNumber(sDbl[stackTop]); } stack[stackTop] = ScriptRuntime.GetObjectPropNoWarn(lhs, stringReg, cx); goto Loop_continue; } case Token.GETPROP: { object lhs = stack[stackTop]; if (lhs == DBL_MRK) { lhs = ScriptRuntime.WrapNumber(sDbl[stackTop]); } stack[stackTop] = ScriptRuntime.GetObjectProp(lhs, stringReg, cx, frame.scope); goto Loop_continue; } case Token.SETPROP: { object rhs = stack[stackTop]; if (rhs == DBL_MRK) { rhs = ScriptRuntime.WrapNumber(sDbl[stackTop]); } --stackTop; object lhs = stack[stackTop]; if (lhs == DBL_MRK) { lhs = ScriptRuntime.WrapNumber(sDbl[stackTop]); } stack[stackTop] = ScriptRuntime.SetObjectProp(lhs, stringReg, rhs, cx); goto Loop_continue; } case Icode_PROP_INC_DEC: { object lhs = stack[stackTop]; if (lhs == DBL_MRK) { lhs = ScriptRuntime.WrapNumber(sDbl[stackTop]); } stack[stackTop] = ScriptRuntime.PropIncrDecr(lhs, stringReg, cx, iCode[frame.pc]); ++frame.pc; goto Loop_continue; } case Token.GETELEM: { stackTop = DoGetElem(cx, frame, stack, sDbl, stackTop); goto Loop_continue; } case Token.SETELEM: { stackTop = DoSetElem(cx, stack, sDbl, stackTop); goto Loop_continue; } case Icode_ELEM_INC_DEC: { stackTop = DoElemIncDec(cx, frame, iCode, stack, sDbl, stackTop); goto Loop_continue; } case Token.GET_REF: { Ref @ref = (Ref)stack[stackTop]; stack[stackTop] = ScriptRuntime.RefGet(@ref, cx); goto Loop_continue; } case Token.SET_REF: { object value = stack[stackTop]; if (value == DBL_MRK) { value = ScriptRuntime.WrapNumber(sDbl[stackTop]); } --stackTop; Ref @ref = (Ref)stack[stackTop]; stack[stackTop] = ScriptRuntime.RefSet(@ref, value, cx); goto Loop_continue; } case Token.DEL_REF: { Ref @ref = (Ref)stack[stackTop]; stack[stackTop] = ScriptRuntime.RefDel(@ref, cx); goto Loop_continue; } case Icode_REF_INC_DEC: { Ref @ref = (Ref)stack[stackTop]; stack[stackTop] = ScriptRuntime.RefIncrDecr(@ref, cx, iCode[frame.pc]); ++frame.pc; goto Loop_continue; } case Token.LOCAL_LOAD: { ++stackTop; indexReg += frame.localShift; stack[stackTop] = stack[indexReg]; sDbl[stackTop] = sDbl[indexReg]; goto Loop_continue; } case Icode_LOCAL_CLEAR: { indexReg += frame.localShift; stack[indexReg] = null; goto Loop_continue; } case Icode_NAME_AND_THIS: { // stringReg: name ++stackTop; stack[stackTop] = ScriptRuntime.GetNameFunctionAndThis(stringReg, cx, frame.scope); ++stackTop; stack[stackTop] = ScriptRuntime.LastStoredScriptable(cx); goto Loop_continue; } case Icode_PROP_AND_THIS: { object obj = stack[stackTop]; if (obj == DBL_MRK) { obj = ScriptRuntime.WrapNumber(sDbl[stackTop]); } // stringReg: property stack[stackTop] = ScriptRuntime.GetPropFunctionAndThis(obj, stringReg, cx, frame.scope); ++stackTop; stack[stackTop] = ScriptRuntime.LastStoredScriptable(cx); goto Loop_continue; } case Icode_ELEM_AND_THIS: { object obj = stack[stackTop - 1]; if (obj == DBL_MRK) { obj = ScriptRuntime.WrapNumber(sDbl[stackTop - 1]); } object id = stack[stackTop]; if (id == DBL_MRK) { id = ScriptRuntime.WrapNumber(sDbl[stackTop]); } stack[stackTop - 1] = ScriptRuntime.GetElemFunctionAndThis(obj, id, cx); stack[stackTop] = ScriptRuntime.LastStoredScriptable(cx); goto Loop_continue; } case Icode_VALUE_AND_THIS: { object value = stack[stackTop]; if (value == DBL_MRK) { value = ScriptRuntime.WrapNumber(sDbl[stackTop]); } stack[stackTop] = ScriptRuntime.GetValueFunctionAndThis(value, cx); ++stackTop; stack[stackTop] = ScriptRuntime.LastStoredScriptable(cx); goto Loop_continue; } case Icode_CALLSPECIAL: { if (instructionCounting) { cx.instructionCount += INVOCATION_COST; } stackTop = DoCallSpecial(cx, frame, stack, sDbl, stackTop, iCode, indexReg); goto Loop_continue; } case Token.CALL: case Icode_TAIL_CALL: case Token.REF_CALL: { if (instructionCounting) { cx.instructionCount += INVOCATION_COST; } // stack change: function thisObj arg0 .. argN -> result // indexReg: number of arguments stackTop -= 1 + indexReg; // CALL generation ensures that fun and funThisObj // are already Scriptable and Callable objects respectively Callable fun = (Callable)stack[stackTop]; Scriptable funThisObj = (Scriptable)stack[stackTop + 1]; if (op == Token.REF_CALL) { object[] outArgs = GetArgsArray(stack, sDbl, stackTop + 2, indexReg); stack[stackTop] = ScriptRuntime.CallRef(fun, funThisObj, outArgs, cx); goto Loop_continue; } Scriptable calleeScope = frame.scope; if (frame.useActivation) { calleeScope = ScriptableObject.GetTopLevelScope(frame.scope); } if (fun is InterpretedFunction) { InterpretedFunction ifun = (InterpretedFunction)fun; if (frame.fnOrScript.securityDomain == ifun.securityDomain) { Interpreter.CallFrame callParentFrame = frame; Interpreter.CallFrame calleeFrame = new Interpreter.CallFrame(); if (op == Icode_TAIL_CALL) { // In principle tail call can re-use the current // frame and its stack arrays but it is hard to // do properly. Any exceptions that can legally // happen during frame re-initialization including // StackOverflowException during innocent looking // System.arraycopy may leave the current frame // data corrupted leading to undefined behaviour // in the catch code bellow that unwinds JS stack // on exceptions. Then there is issue about frame release // end exceptions there. // To avoid frame allocation a released frame // can be cached for re-use which would also benefit // non-tail calls but it is not clear that this caching // would gain in performance due to potentially // bad interaction with GC. callParentFrame = frame.parentFrame; // Release the current frame. See Bug #344501 to see why // it is being done here. ExitFrame(cx, frame, null); } InitFrame(cx, calleeScope, funThisObj, stack, sDbl, stackTop + 2, indexReg, ifun, callParentFrame, calleeFrame); if (op != Icode_TAIL_CALL) { frame.savedStackTop = stackTop; frame.savedCallOp = op; } frame = calleeFrame; goto StateLoop_continue; } } if (fun is NativeContinuation) { // Jump to the captured continuation Interpreter.ContinuationJump cjump; cjump = new Interpreter.ContinuationJump((NativeContinuation)fun, frame); // continuation result is the first argument if any // of continuation call if (indexReg == 0) { cjump.result = undefined; } else { cjump.result = stack[stackTop + 2]; cjump.resultDbl = sDbl[stackTop + 2]; } // Start the real unwind job throwable = cjump; goto withoutExceptions_break; } if (fun is IdFunctionObject) { IdFunctionObject ifun = (IdFunctionObject)fun; if (NativeContinuation.IsContinuationConstructor(ifun)) { frame.stack[stackTop] = CaptureContinuation(cx, frame.parentFrame, false); goto Loop_continue; } // Bug 405654 -- make best effort to keep Function.apply and // Function.call within this interpreter loop invocation if (BaseFunction.IsApplyOrCall(ifun)) { Callable applyCallable = ScriptRuntime.GetCallable(funThisObj); if (applyCallable is InterpretedFunction) { InterpretedFunction iApplyCallable = (InterpretedFunction)applyCallable; if (frame.fnOrScript.securityDomain == iApplyCallable.securityDomain) { frame = InitFrameForApplyOrCall(cx, frame, indexReg, stack, sDbl, stackTop, op, calleeScope, ifun, iApplyCallable); goto StateLoop_continue; } } } } // Bug 447697 -- make best effort to keep __noSuchMethod__ within this // interpreter loop invocation if (fun is ScriptRuntime.NoSuchMethodShim) { // get the shim and the actual method ScriptRuntime.NoSuchMethodShim noSuchMethodShim = (ScriptRuntime.NoSuchMethodShim)fun; Callable noSuchMethodMethod = noSuchMethodShim.noSuchMethodMethod; // if the method is in fact an InterpretedFunction if (noSuchMethodMethod is InterpretedFunction) { InterpretedFunction ifun = (InterpretedFunction)noSuchMethodMethod; if (frame.fnOrScript.securityDomain == ifun.securityDomain) { frame = InitFrameForNoSuchMethod(cx, frame, indexReg, stack, sDbl, stackTop, op, funThisObj, calleeScope, noSuchMethodShim, ifun); goto StateLoop_continue; } } } cx.lastInterpreterFrame = frame; frame.savedCallOp = op; frame.savedStackTop = stackTop; stack[stackTop] = fun.Call(cx, calleeScope, funThisObj, GetArgsArray(stack, sDbl, stackTop + 2, indexReg)); goto Loop_continue; } case Token.NEW: { if (instructionCounting) { cx.instructionCount += INVOCATION_COST; } // stack change: function arg0 .. argN -> newResult // indexReg: number of arguments stackTop -= indexReg; object lhs = stack[stackTop]; if (lhs is InterpretedFunction) { InterpretedFunction f = (InterpretedFunction)lhs; if (frame.fnOrScript.securityDomain == f.securityDomain) { Scriptable newInstance = f.CreateObject(cx, frame.scope); Interpreter.CallFrame calleeFrame = new Interpreter.CallFrame(); InitFrame(cx, frame.scope, newInstance, stack, sDbl, stackTop + 1, indexReg, f, frame, calleeFrame); stack[stackTop] = newInstance; frame.savedStackTop = stackTop; frame.savedCallOp = op; frame = calleeFrame; goto StateLoop_continue; } } if (!(lhs is Function)) { if (lhs == DBL_MRK) { lhs = ScriptRuntime.WrapNumber(sDbl[stackTop]); } throw ScriptRuntime.NotFunctionError(lhs); } Function fun = (Function)lhs; if (fun is IdFunctionObject) { IdFunctionObject ifun = (IdFunctionObject)fun; if (NativeContinuation.IsContinuationConstructor(ifun)) { frame.stack[stackTop] = CaptureContinuation(cx, frame.parentFrame, false); goto Loop_continue; } } object[] outArgs = GetArgsArray(stack, sDbl, stackTop + 1, indexReg); stack[stackTop] = fun.Construct(cx, frame.scope, outArgs); goto Loop_continue; } case Token.TYPEOF: { object lhs = stack[stackTop]; if (lhs == DBL_MRK) { lhs = ScriptRuntime.WrapNumber(sDbl[stackTop]); } stack[stackTop] = ScriptRuntime.Typeof(lhs); goto Loop_continue; } case Icode_TYPEOFNAME: { stack[++stackTop] = ScriptRuntime.TypeofName(frame.scope, stringReg); goto Loop_continue; } case Token.STRING: { stack[++stackTop] = stringReg; goto Loop_continue; } case Icode_SHORTNUMBER: { ++stackTop; stack[stackTop] = DBL_MRK; sDbl[stackTop] = GetShort(iCode, frame.pc); frame.pc += 2; goto Loop_continue; } case Icode_INTNUMBER: { ++stackTop; stack[stackTop] = DBL_MRK; sDbl[stackTop] = GetInt(iCode, frame.pc); frame.pc += 4; goto Loop_continue; } case Token.NUMBER: { ++stackTop; stack[stackTop] = DBL_MRK; sDbl[stackTop] = frame.idata.itsDoubleTable[indexReg]; goto Loop_continue; } case Token.NAME: { stack[++stackTop] = ScriptRuntime.Name(cx, frame.scope, stringReg); goto Loop_continue; } case Icode_NAME_INC_DEC: { stack[++stackTop] = ScriptRuntime.NameIncrDecr(frame.scope, stringReg, cx, iCode[frame.pc]); ++frame.pc; goto Loop_continue; } case Icode_SETCONSTVAR1: { indexReg = iCode[frame.pc++]; goto case Token.SETCONSTVAR; } case Token.SETCONSTVAR: { // fallthrough stackTop = DoSetConstVar(frame, stack, sDbl, stackTop, vars, varDbls, varAttributes, indexReg); goto Loop_continue; } case Icode_SETVAR1: { indexReg = iCode[frame.pc++]; goto case Token.SETVAR; } case Token.SETVAR: { // fallthrough stackTop = DoSetVar(frame, stack, sDbl, stackTop, vars, varDbls, varAttributes, indexReg); goto Loop_continue; } case Icode_GETVAR1: { indexReg = iCode[frame.pc++]; goto case Token.GETVAR; } case Token.GETVAR: { // fallthrough stackTop = DoGetVar(frame, stack, sDbl, stackTop, vars, varDbls, indexReg); goto Loop_continue; } case Icode_VAR_INC_DEC: { stackTop = DoVarIncDec(cx, frame, stack, sDbl, stackTop, vars, varDbls, indexReg); goto Loop_continue; } case Icode_ZERO: { ++stackTop; stack[stackTop] = DBL_MRK; sDbl[stackTop] = 0; goto Loop_continue; } case Icode_ONE: { ++stackTop; stack[stackTop] = DBL_MRK; sDbl[stackTop] = 1; goto Loop_continue; } case Token.NULL: { stack[++stackTop] = null; goto Loop_continue; } case Token.THIS: { stack[++stackTop] = frame.thisObj; goto Loop_continue; } case Token.THISFN: { stack[++stackTop] = frame.fnOrScript; goto Loop_continue; } case Token.FALSE: { stack[++stackTop] = false; goto Loop_continue; } case Token.TRUE: { stack[++stackTop] = true; goto Loop_continue; } case Icode_UNDEF: { stack[++stackTop] = undefined; goto Loop_continue; } case Token.ENTERWITH: { object lhs = stack[stackTop]; if (lhs == DBL_MRK) { lhs = ScriptRuntime.WrapNumber(sDbl[stackTop]); } --stackTop; frame.scope = ScriptRuntime.EnterWith(lhs, cx, frame.scope); goto Loop_continue; } case Token.LEAVEWITH: { frame.scope = ScriptRuntime.LeaveWith(frame.scope); goto Loop_continue; } case Token.CATCH_SCOPE: { // stack top: exception object // stringReg: name of exception variable // indexReg: local for exception scope --stackTop; indexReg += frame.localShift; bool afterFirstScope = (frame.idata.itsICode[frame.pc] != 0); Exception caughtException = (Exception)stack[stackTop + 1]; Scriptable lastCatchScope; if (!afterFirstScope) { lastCatchScope = null; } else { lastCatchScope = (Scriptable)stack[indexReg]; } stack[indexReg] = ScriptRuntime.NewCatchScope(caughtException, lastCatchScope, stringReg, cx, frame.scope); ++frame.pc; goto Loop_continue; } case Token.ENUM_INIT_KEYS: case Token.ENUM_INIT_VALUES: case Token.ENUM_INIT_ARRAY: { object lhs = stack[stackTop]; if (lhs == DBL_MRK) { lhs = ScriptRuntime.WrapNumber(sDbl[stackTop]); } --stackTop; indexReg += frame.localShift; int enumType = op == Token.ENUM_INIT_KEYS ? ScriptRuntime.ENUMERATE_KEYS : op == Token.ENUM_INIT_VALUES ? ScriptRuntime.ENUMERATE_VALUES : ScriptRuntime.ENUMERATE_ARRAY; stack[indexReg] = ScriptRuntime.EnumInit(lhs, cx, enumType); goto Loop_continue; } case Token.ENUM_NEXT: case Token.ENUM_ID: { indexReg += frame.localShift; object val = stack[indexReg]; ++stackTop; stack[stackTop] = (op == Token.ENUM_NEXT) ? (object)ScriptRuntime.EnumNext(val) : (object)ScriptRuntime.EnumId(val, cx); goto Loop_continue; } case Token.REF_SPECIAL: { //stringReg: name of special property object obj = stack[stackTop]; if (obj == DBL_MRK) { obj = ScriptRuntime.WrapNumber(sDbl[stackTop]); } stack[stackTop] = ScriptRuntime.SpecialRef(obj, stringReg, cx); goto Loop_continue; } case Token.REF_MEMBER: { //indexReg: flags stackTop = DoRefMember(cx, stack, sDbl, stackTop, indexReg); goto Loop_continue; } case Token.REF_NS_MEMBER: { //indexReg: flags stackTop = DoRefNsMember(cx, stack, sDbl, stackTop, indexReg); goto Loop_continue; } case Token.REF_NAME: { //indexReg: flags object name = stack[stackTop]; if (name == DBL_MRK) { name = ScriptRuntime.WrapNumber(sDbl[stackTop]); } stack[stackTop] = ScriptRuntime.NameRef(name, cx, frame.scope, indexReg); goto Loop_continue; } case Token.REF_NS_NAME: { //indexReg: flags stackTop = DoRefNsName(cx, frame, stack, sDbl, stackTop, indexReg); goto Loop_continue; } case Icode_SCOPE_LOAD: { indexReg += frame.localShift; frame.scope = (Scriptable)stack[indexReg]; goto Loop_continue; } case Icode_SCOPE_SAVE: { indexReg += frame.localShift; stack[indexReg] = frame.scope; goto Loop_continue; } case Icode_CLOSURE_EXPR: { stack[++stackTop] = InterpretedFunction.CreateFunction(cx, frame.scope, frame.fnOrScript, indexReg); goto Loop_continue; } case Icode_CLOSURE_STMT: { InitFunction(cx, frame.scope, frame.fnOrScript, indexReg); goto Loop_continue; } case Token.REGEXP: { object re = frame.idata.itsRegExpLiterals[indexReg]; stack[++stackTop] = ScriptRuntime.WrapRegExp(cx, frame.scope, re); goto Loop_continue; } case Icode_LITERAL_NEW: { // indexReg: number of values in the literal ++stackTop; stack[stackTop] = new int[indexReg]; ++stackTop; stack[stackTop] = new object[indexReg]; sDbl[stackTop] = 0; goto Loop_continue; } case Icode_LITERAL_SET: { object value = stack[stackTop]; if (value == DBL_MRK) { value = ScriptRuntime.WrapNumber(sDbl[stackTop]); } --stackTop; int i = (int)sDbl[stackTop]; ((object[])stack[stackTop])[i] = value; sDbl[stackTop] = i + 1; goto Loop_continue; } case Icode_LITERAL_GETTER: { object value = stack[stackTop]; --stackTop; int i = (int)sDbl[stackTop]; ((object[])stack[stackTop])[i] = value; ((int[])stack[stackTop - 1])[i] = -1; sDbl[stackTop] = i + 1; goto Loop_continue; } case Icode_LITERAL_SETTER: { object value = stack[stackTop]; --stackTop; int i = (int)sDbl[stackTop]; ((object[])stack[stackTop])[i] = value; ((int[])stack[stackTop - 1])[i] = +1; sDbl[stackTop] = i + 1; goto Loop_continue; } case Token.ARRAYLIT: case Icode_SPARE_ARRAYLIT: case Token.OBJECTLIT: { object[] data = (object[])stack[stackTop]; --stackTop; int[] getterSetters = (int[])stack[stackTop]; object val; if (op == Token.OBJECTLIT) { object[] ids = (object[])frame.idata.literalIds[indexReg]; val = ScriptRuntime.NewObjectLiteral(ids, data, getterSetters, cx, frame.scope); } else { int[] skipIndexces = null; if (op == Icode_SPARE_ARRAYLIT) { skipIndexces = (int[])frame.idata.literalIds[indexReg]; } val = ScriptRuntime.NewArrayLiteral(data, skipIndexces, cx, frame.scope); } stack[stackTop] = val; goto Loop_continue; } case Icode_ENTERDQ: { object lhs = stack[stackTop]; if (lhs == DBL_MRK) { lhs = ScriptRuntime.WrapNumber(sDbl[stackTop]); } --stackTop; frame.scope = ScriptRuntime.EnterDotQuery(lhs, frame.scope); goto Loop_continue; } case Icode_LEAVEDQ: { bool valBln = Stack_boolean(frame, stackTop); object x = ScriptRuntime.UpdateDotQuery(valBln, frame.scope); if (x != null) { stack[stackTop] = x; frame.scope = ScriptRuntime.LeaveDotQuery(frame.scope); frame.pc += 2; goto Loop_continue; } // reset stack and PC to code after ENTERDQ --stackTop; goto jumplessRun_break; } case Token.DEFAULTNAMESPACE: { object value = stack[stackTop]; if (value == DBL_MRK) { value = ScriptRuntime.WrapNumber(sDbl[stackTop]); } stack[stackTop] = ScriptRuntime.SetDefaultNamespace(value, cx); goto Loop_continue; } case Token.ESCXMLATTR: { object value = stack[stackTop]; if (value != DBL_MRK) { stack[stackTop] = ScriptRuntime.EscapeAttributeValue(value, cx); } goto Loop_continue; } case Token.ESCXMLTEXT: { object value = stack[stackTop]; if (value != DBL_MRK) { stack[stackTop] = ScriptRuntime.EscapeTextValue(value, cx); } goto Loop_continue; } case Icode_DEBUGGER: { if (frame.debuggerFrame != null) { frame.debuggerFrame.OnDebuggerStatement(cx); } goto Loop_continue; } case Icode_LINE: { frame.pcSourceLineStart = frame.pc; if (frame.debuggerFrame != null) { int line = GetIndex(iCode, frame.pc); frame.debuggerFrame.OnLineChange(cx, line); } frame.pc += 2; goto Loop_continue; } case Icode_REG_IND_C0: { indexReg = 0; goto Loop_continue; } case Icode_REG_IND_C1: { indexReg = 1; goto Loop_continue; } case Icode_REG_IND_C2: { indexReg = 2; goto Loop_continue; } case Icode_REG_IND_C3: { indexReg = 3; goto Loop_continue; } case Icode_REG_IND_C4: { indexReg = 4; goto Loop_continue; } case Icode_REG_IND_C5: { indexReg = 5; goto Loop_continue; } case Icode_REG_IND1: { indexReg = unchecked((int)(0xFF)) & iCode[frame.pc]; ++frame.pc; goto Loop_continue; } case Icode_REG_IND2: { indexReg = GetIndex(iCode, frame.pc); frame.pc += 2; goto Loop_continue; } case Icode_REG_IND4: { indexReg = GetInt(iCode, frame.pc); frame.pc += 4; goto Loop_continue; } case Icode_REG_STR_C0: { stringReg = strings[0]; goto Loop_continue; } case Icode_REG_STR_C1: { stringReg = strings[1]; goto Loop_continue; } case Icode_REG_STR_C2: { stringReg = strings[2]; goto Loop_continue; } case Icode_REG_STR_C3: { stringReg = strings[3]; goto Loop_continue; } case Icode_REG_STR1: { stringReg = strings[unchecked((int)(0xFF)) & iCode[frame.pc]]; ++frame.pc; goto Loop_continue; } case Icode_REG_STR2: { stringReg = strings[GetIndex(iCode, frame.pc)]; frame.pc += 2; goto Loop_continue; } case Icode_REG_STR4: { stringReg = strings[GetInt(iCode, frame.pc)]; frame.pc += 4; goto Loop_continue; } default: { DumpICode(frame.idata); throw new Exception("Unknown icode : " + op + " @ pc : " + (frame.pc - 1)); } } jumplessRun_break: ; // end of interpreter switch // end of jumplessRun label block // This should be reachable only for jump implementation // when pc points to encoded target offset if (instructionCounting) { AddInstructionCount(cx, frame, 2); } int offset = GetShort(iCode, frame.pc); if (offset != 0) { // -1 accounts for pc pointing to jump opcode + 1 frame.pc += offset - 1; } else { frame.pc = frame.idata.longJumps.GetExistingInt(frame.pc); } if (instructionCounting) { frame.pcPrevBranch = frame.pc; } goto Loop_continue; Loop_continue: ; } Loop_break: ; // end of Loop: for ExitFrame(cx, frame, null); interpreterResult = frame.result; interpreterResultDbl = frame.resultDbl; if (frame.parentFrame != null) { frame = frame.parentFrame; if (frame.frozen) { frame = frame.CloneFrozen(); } SetCallResult(frame, interpreterResult, interpreterResultDbl); interpreterResult = null; // Help GC goto StateLoop_continue; } goto StateLoop_break; } catch (Exception ex) { // end of interpreter withoutExceptions: try if (throwable != null) { // This is serious bug and it is better to track it ASAP Sharpen.Runtime.PrintStackTrace(ex, System.Console.Error); throw new InvalidOperationException(); } throwable = ex; } withoutExceptions_break: ; // This should be reachable only after above catch or from // finally when it needs to propagate exception or from // explicit throw if (throwable == null) { Kit.CodeBug(); } // Exception type int EX_CATCH_STATE = 2; // Can execute JS catch int EX_FINALLY_STATE = 1; // Can execute JS finally int EX_NO_JS_STATE = 0; // Terminate JS execution int exState; Interpreter.ContinuationJump cjump_1 = null; if (generatorState != null && generatorState.operation == NativeGenerator.GENERATOR_CLOSE && throwable == generatorState.value) { exState = EX_FINALLY_STATE; } else { if (throwable is JavaScriptException) { exState = EX_CATCH_STATE; } else { if (throwable is EcmaError) { // an offical ECMA error object, exState = EX_CATCH_STATE; } else { if (throwable is EvaluatorException) { exState = EX_CATCH_STATE; } else { if (throwable is ContinuationPending) { exState = EX_NO_JS_STATE; } else { if (throwable is Exception) { exState = cx.HasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) ? EX_CATCH_STATE : EX_FINALLY_STATE; } else { if (throwable is Exception) { exState = cx.HasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) ? EX_CATCH_STATE : EX_NO_JS_STATE; } else { if (throwable is Interpreter.ContinuationJump) { // It must be ContinuationJump exState = EX_FINALLY_STATE; cjump_1 = (Interpreter.ContinuationJump)throwable; } else { exState = cx.HasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) ? EX_CATCH_STATE : EX_FINALLY_STATE; } } } } } } } } if (instructionCounting) { try { AddInstructionCount(cx, frame, EXCEPTION_COST); } catch (Exception ex) { throwable = ex; exState = EX_FINALLY_STATE; } catch (Exception ex) { // Error from instruction counting // => unconditionally terminate JS throwable = ex; cjump_1 = null; exState = EX_NO_JS_STATE; } } if (frame.debuggerFrame != null && throwable is Exception) { // Call debugger only for RuntimeException Exception rex = (Exception)throwable; try { frame.debuggerFrame.OnExceptionThrown(cx, rex); } catch (Exception ex) { // Any exception from debugger // => unconditionally terminate JS throwable = ex; cjump_1 = null; exState = EX_NO_JS_STATE; } } for (; ; ) { if (exState != EX_NO_JS_STATE) { bool onlyFinally = (exState != EX_CATCH_STATE); indexReg = GetExceptionHandler(frame, onlyFinally); if (indexReg >= 0) { // We caught an exception, restart the loop // with exception pending the processing at the loop // start goto StateLoop_continue; } } // No allowed exception handlers in this frame, unwind // to parent and try to look there ExitFrame(cx, frame, throwable); frame = frame.parentFrame; if (frame == null) { break; } if (cjump_1 != null && cjump_1.branchFrame == frame) { // Continuation branch point was hit, // restart the state loop to reenter continuation indexReg = -1; goto StateLoop_continue; } } // No more frames, rethrow the exception or deal with continuation if (cjump_1 != null) { if (cjump_1.branchFrame != null) { // The above loop should locate the top frame Kit.CodeBug(); } if (cjump_1.capturedFrame != null) { // Restarting detached continuation indexReg = -1; goto StateLoop_continue; } // Return continuation result to the caller interpreterResult = cjump_1.result; interpreterResultDbl = cjump_1.resultDbl; throwable = null; } goto StateLoop_break; StateLoop_continue: ; } StateLoop_break: ; // end of StateLoop: for(;;) // Do cleanups/restorations before the final return or throw if (cx.previousInterpreterInvocations != null && cx.previousInterpreterInvocations.Size() != 0) { cx.lastInterpreterFrame = cx.previousInterpreterInvocations.Pop(); } else { // It was the last interpreter frame on the stack cx.lastInterpreterFrame = null; // Force GC of the value cx.previousInterpreterInvocations cx.previousInterpreterInvocations = null; } if (throwable != null) { if (throwable is Exception) { throw (Exception)throwable; } else { // Must be instance of Error or code bug throw (Exception)throwable; } } return (interpreterResult != DBL_MRK) ? interpreterResult : ScriptRuntime.WrapNumber(interpreterResultDbl); }
public void LogError(JavaScriptException error) { Output?.LogError(error); }
public async Task <GenerateResult> GenerateDocumentAsync(string code, object model, IResourceManager resourceManager = null, CancellationToken cancellationToken = default) { // Multiple contexts can share a runtime, but only one thread can access the runtime at a time var context = JavaScriptContext.CreateContext(_runtime); context.AddRef(); ModuleLease rootModuleLease = null; try { using var loader = new CustomLoader(context, _dispatcher, _resourceScriptFactory, resourceManager); var tcs = new TaskCompletionSource <JavaScriptValue>(TaskCreationOptions.RunContinuationsAsynchronously); _dispatcher.Invoke(() => { using (context.GetScope()) { Native.ThrowIfError(Native.JsSetPromiseContinuationCallback(_promiseContinuationCallback, IntPtr.Zero)); // Load polyfill's JavaScriptContext.RunScript("const globalThis = this;"); JavaScriptContext.RunScript(PolyfillScripts.Get("ImageData")); var rootModule = JavaScriptModuleRecord.Initialize(); rootModule.AddRef(); rootModule.HostUrl = "<host>"; // Only for debugging loader.RootModule = rootModule; rootModule.FetchImportedModuleCallBack = loader.LoadModule; rootModule.NotifyModuleReadyCallback = loader.ModuleLoaded; rootModuleLease = new ModuleLease(rootModule); loader.AddPreload("main", code); } }); // Add callback that will be run when the root module has been evaluated, // at which time its rootModule.Namespace becomes valid. loader.OnRootModuleEvaluated = () => { using (context.GetScope()) { var build = rootModuleLease.Module.Namespace.GetProperty("build"); build.AddRef(); var modelJson = JavaScriptValue.FromString(JsonSerializer.Serialize(model)); modelJson.AddRef(); var resultPromise = build.CallFunction(JavaScriptValue.GlobalObject, modelJson); resultPromise.AddRef(); FunctionLease resolve = default; FunctionLease reject = default; FunctionLease always = default; resolve = new FunctionLease((callee, isConstructCall, arguments, argumentCount, callbackState) => { var result = arguments[1]; result.AddRef(); tcs.SetResult(result); return(callee); }); reject = new FunctionLease((callee, isConstructCall, arguments, argumentCount, callbackState) => { JavaScriptException exception; if (arguments.Length >= 2) { var reason = arguments[1]; if (reason.ValueType == JavaScriptValueType.Error) { exception = new JavaScriptException(JavaScriptErrorCode.ScriptException, reason.GetProperty("message").ToString()); } else { exception = new JavaScriptException(JavaScriptErrorCode.ScriptException, reason.ConvertToString().ToString()); } } else { exception = new JavaScriptException(JavaScriptErrorCode.ScriptException); } tcs.SetException(exception); return(callee); }); always = new FunctionLease((callee, isConstructCall, arguments, argumentCount, callbackState) => { build.Release(); modelJson.Release(); resultPromise.Release(); resolve.Dispose(); reject.Dispose(); always.Dispose(); return(callee); }); resultPromise .GetProperty("then").CallFunction(resultPromise, resolve.Function) .GetProperty("catch").CallFunction(resultPromise, reject.Function) .GetProperty("finally").CallFunction(resultPromise, always.Function); } }; loader.OnResourceLoadError = e => tcs.SetException(e); _dispatcher.Invoke(() => { using (context.GetScope()) { rootModuleLease.Module.ParseSource(@" import Builder from 'main'; const builder = new Builder(); const build = async (modelJson) => { const model = JSON.parse(modelJson); const content = await Promise.resolve(builder.build(model)); try { const { contentType } = await import('main'); return { content, contentType }; } catch (error) { return { content }; } }; export { build }; "); } }); var result = await tcs.Task; return(_dispatcher.Invoke(() => { using (context.GetScope()) { _runtime.CollectGarbage(); var content = result.GetProperty("content"); var contentTypeValue = result.GetProperty("contentType"); var contentType = contentTypeValue.ValueType == JavaScriptValueType.String ? contentTypeValue.ToString() : null; switch (content.ValueType) { case JavaScriptValueType.String: return new GenerateResult() { Content = Encoding.UTF8.GetBytes(content.ToString()), ContentType = contentType ?? "text/plain" }; case JavaScriptValueType.TypedArray: { content.GetTypedArrayInfo(out var arrayType, out var buffer, out var byteOffset, out var byteLength); if (arrayType != JavaScriptTypedArrayType.Uint8) { throw new NotSupportedException("Typed array must be Uint8Array"); } var bufferPointer = buffer.GetArrayBufferStorage(out var bufferLength); var array = new byte[byteLength]; Marshal.Copy(IntPtr.Add(bufferPointer, (int)byteOffset), array, 0, (int)byteLength); return new GenerateResult() { Content = array, ContentType = contentType ?? "application/octet-stream" }; } case JavaScriptValueType.Array: { var list = content.ToList(); var array = new byte[list.Count]; for (var i = 0; i < list.Count; i++) { array[i] = (byte)list[i].ToInt32(); } return new GenerateResult() { Content = array, ContentType = contentType ?? "application/octet-stream" }; } default: throw new NotSupportedException("Build did not produce a supported result"); } } })); } finally { _dispatcher.Invoke(() => { using (context.GetScope()) { rootModuleLease?.Dispose(); } }); context.Release(); } }
private static readonly string[] _newLineSplitters = new[] { "\r\n", "\n", "\r" }; //TODO: check if Jint is using only \r\n static internal (string Message, bool Success) PrepareErrorMessageForJavaScriptIndexFuncException(string script, JavaScriptException jse) { var lines = script.Split(_newLineSplitters, StringSplitOptions.None); if (jse.Location.Start.Line > lines.Length || jse.Location.End.Line > lines.Length || jse.Location.Start.Line > jse.Location.End.Line) { return(null, false); } var sb = new StringBuilder(); //Location seems to be '1' based var start = Math.Max(jse.Location.Start.Line - 1, 1); if (start > 1) { sb.AppendLine("..."); } for (var i = start; i <= start + 2 && i <= lines.Length; i++) { var line = lines[i - 1]; sb.AppendLine(line); if (i == jse.Location.Start.Line) { sb.Append(new string('-', Math.Max(jse.Location.Start.Column - 1, 0))); sb.Append(new string('^', 3)); sb.AppendLine(new string('-', Math.Max(5, line.Length - jse.Location.Start.Column + 1))); } } if (start + 2 < lines.Length) { sb.AppendLine("..."); } var error = sb.ToString(); return(error, true); }
public JintJsException2(string moduleName, JavaScriptException jsException) : base(jsException) { Module = moduleName; }
/// <summary> /// https://tc39.es/ecma262/#sec-performeval /// </summary> public JsValue Call(JsValue thisObject, JsValue[] arguments, bool direct) { if (!(arguments.At(0) is JsString x)) { return(arguments.At(0)); } var parser = new JavaScriptParser(x.ToString(), ParserOptions); Script script; try { script = parser.ParseScript(StrictModeScope.IsStrictModeCode); } catch (ParserException e) { return(e.Description == Messages.InvalidLHSInAssignment ? ExceptionHelper.ThrowReferenceError <JsValue>(_engine) : ExceptionHelper.ThrowSyntaxError <JsValue>(_engine)); } var body = script.Body; if (body.Count == 0) { return(Undefined); } var strictEval = script.Strict || _engine._isStrict; var ctx = _engine.ExecutionContext; using (new StrictModeScope(strictEval)) { LexicalEnvironment lexEnv; LexicalEnvironment varEnv; if (direct) { lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment); varEnv = ctx.VariableEnvironment; } else { lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, Engine.GlobalEnvironment); varEnv = Engine.GlobalEnvironment; } if (strictEval) { varEnv = lexEnv; } // If ctx is not already suspended, suspend ctx. Engine.EnterExecutionContext(lexEnv, varEnv); try { Engine.EvalDeclarationInstantiation(script, varEnv, lexEnv, strictEval); var statement = new JintScript(_engine, script); var result = statement.Execute(); var value = result.GetValueOrDefault(); if (result.Type == CompletionType.Throw) { var ex = new JavaScriptException(value).SetCallstack(_engine, result.Location); throw ex; } else { return(value); } } finally { Engine.LeaveExecutionContext(); } } }
/// <summary> /// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.1 /// </summary> /// <param name="thisArg"></param> /// <param name="arguments"></param> /// <returns></returns> public override JsValue Call(JsValue thisArg, JsValue[] arguments) { using (new StrictModeScope(Strict, true)) { // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3 JsValue thisBinding; if (StrictModeScope.IsStrictModeCode) { thisBinding = thisArg; } else if (thisArg == Undefined.Instance || thisArg == Null.Instance) { thisBinding = Engine.Global; } else if (!thisArg.IsObject()) { thisBinding = TypeConverter.ToObject(Engine, thisArg); } else { thisBinding = thisArg; } var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(Engine, Scope); Engine.EnterExecutionContext(localEnv, localEnv, thisBinding); try { Engine.DeclarationBindingInstantiation( DeclarationBindingType.FunctionCode, _functionDeclaration.FunctionDeclarations, _functionDeclaration.VariableDeclarations, this, arguments); var result = Engine.ExecuteStatement(_functionDeclaration.Body); if (result.Type == Completion.Throw) { JavaScriptException ex = new JavaScriptException(result.GetValueOrDefault()); ex.Location = result.Location; throw ex; } if (result.Type == Completion.Return) { return result.GetValueOrDefault(); } } finally { Engine.LeaveExecutionContext(); } return Undefined.Instance; } }
/// <summary> /// https://tc39.es/ecma262/#sec-performeval /// </summary> public JsValue PerformEval(JsValue x, Realm callerRealm, bool strictCaller, bool direct) { if (!x.IsString()) { return(x); } var evalRealm = _realm; _engine._host.EnsureCanCompileStrings(callerRealm, evalRealm); var inFunction = false; var inMethod = false; var inDerivedConstructor = false; if (direct) { var thisEnvRec = _engine.ExecutionContext.GetThisEnvironment(); if (thisEnvRec is FunctionEnvironmentRecord functionEnvironmentRecord) { var F = functionEnvironmentRecord._functionObject; inFunction = true; inMethod = thisEnvRec.HasSuperBinding(); if (F._constructorKind == ConstructorKind.Derived) { inDerivedConstructor = true; } } } var parser = new JavaScriptParser(x.ToString(), ParserOptions); Script script = null; try { script = parser.ParseScript(strictCaller); } catch (ParserException e) { if (e.Description == Messages.InvalidLHSInAssignment) { ExceptionHelper.ThrowReferenceError(callerRealm, (string)null); } else { ExceptionHelper.ThrowSyntaxError(callerRealm, e.Message); } } var body = script.Body; if (body.Count == 0) { return(Undefined); } if (!inFunction) { // if body Contains NewTarget, throw a SyntaxError exception. } if (!inMethod) { // if body Contains SuperProperty, throw a SyntaxError exception. } if (!inDerivedConstructor) { // if body Contains SuperCall, throw a SyntaxError exception. } var strictEval = script.Strict || _engine._isStrict; var ctx = _engine.ExecutionContext; using (new StrictModeScope(strictEval)) { EnvironmentRecord lexEnv; EnvironmentRecord varEnv; PrivateEnvironmentRecord privateEnv; if (direct) { lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment); varEnv = ctx.VariableEnvironment; privateEnv = ctx.PrivateEnvironment; } else { lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, evalRealm.GlobalEnv); varEnv = evalRealm.GlobalEnv; privateEnv = null; } if (strictEval) { varEnv = lexEnv; } // If ctx is not already suspended, suspend ctx. Engine.EnterExecutionContext(lexEnv, varEnv, evalRealm, privateEnv); try { Engine.EvalDeclarationInstantiation(script, varEnv, lexEnv, privateEnv, strictEval); var statement = new JintScript(script); var result = statement.Execute(_engine._activeEvaluationContext); var value = result.GetValueOrDefault(); if (result.Type == CompletionType.Throw) { var ex = new JavaScriptException(value).SetCallstack(_engine, result.Location); throw ex; } else { return(value); } } finally { Engine.LeaveExecutionContext(); } } }
public virtual void UpdateResponseWithJavaScriptExceptionDetails(IScriptEngine engine, JavaScriptException exception, BrewResponse response) { if (exception == null) { throw new ArgumentNullException("exception"); } if (response == null) { throw new ArgumentNullException("response"); } string message; var stack = String.Empty; var rawStack = String.Empty; var javascriptExceptionMessage = JavaScriptExceptionMessage; if (TypeUtilities.IsString(exception.ErrorObject)) { message = TypeConverter.ToString(exception.ErrorObject); } else if (exception.ErrorObject is ObjectInstance) { var errorObject = exception.ErrorObject as ObjectInstance; message = errorObject.GetPropertyValue("message") as string; if (message == null || message.IsNullOrWhiteSpace()) { message = engine.Stringify(exception.ErrorObject, null, 4); } else { stack = errorObject.GetPropertyValue("stack") as string; rawStack = stack; if (stack != null && stack.IsNullOrWhiteSpace() == false) { stack = stack.Replace("at ", "at<br/>"); javascriptExceptionMessage = JavaScriptExceptionMessageWithStackTrace; } } } else { message = exception.ErrorObject.ToString(); } response.StatusCode = HttpStatusCode.BadRequest; response.StatusDescription = message; response.ContentType = "text/html"; string exceptionName = exception.Name; if (exceptionName.IsNullOrWhiteSpace()) { exceptionName = "JavaScript Error"; } var resultMessage = String.Format(javascriptExceptionMessage, exceptionName, message, exception.FunctionName, exception.LineNumber, exception.SourcePath, stack); response.Content = Encoding.UTF8.GetBytes(resultMessage); response.ExtendedProperties.Add("Exception_Message", message); response.ExtendedProperties.Add("Exception_Name", exceptionName); response.ExtendedProperties.Add("Exception_FunctionName", exception.FunctionName); response.ExtendedProperties.Add("Exception_LineNumber", exception.LineNumber.ToString(CultureInfo.InvariantCulture)); response.ExtendedProperties.Add("Exception_SourcePath", exception.SourcePath); response.ExtendedProperties.Add("Exception_StackTrace", rawStack); }
public FriendlyJavaScriptException(JavaScriptException ex) : base(ex.Message) { }
public JintJsException(string moduleName, JavaScriptException jsException) : base(jsException.Error) { Module = moduleName; _jsException = jsException; Location = jsException.Location; }
public void CallState(RuntimeState state) { CallArgs args = (CallArgs)state.arg; JsValue thisArg = args.thisObject; JsValue[] arguments = args.arguments; if (state.calleeReturned) { try { var result = (Completion)state.calleeReturnValue; var value = result.GetValueOrDefault(); var argumentInstanceRented = (bool)state.local; // we can safely release arguments if they don't escape the scope if (argumentInstanceRented && _engine.ExecutionContext.LexicalEnvironment?._record is DeclarativeEnvironmentRecord && !(result.Value is ArgumentsInstance)) { var der = _engine.ExecutionContext.LexicalEnvironment._record as DeclarativeEnvironmentRecord; der.ReleaseArguments(); } if (result.Type == CompletionType.Throw) { var ex = new JavaScriptException(value).SetCallstack(_engine, result.Location); throw ex; } if (result.Type == CompletionType.Return) { _engine.Return((JsValue)(value)); return; } } finally { _engine.LeaveExecutionContext(); } _engine.Return((JsValue)(Undefined)); return; } else { // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3 JsValue thisBinding; if (StrictModeScope.IsStrictModeCode) { thisBinding = thisArg; } else if (thisArg._type == Types.Undefined || thisArg._type == Types.Null) { thisBinding = _engine.Global; } else if (thisArg._type != Types.Object) { thisBinding = TypeConverter.ToObject(_engine, thisArg); } else { thisBinding = thisArg; } var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, _scope); _engine.EnterExecutionContext(localEnv, localEnv, thisBinding); state.local = _engine.DeclarationBindingInstantiation( DeclarationBindingType.FunctionCode, _functionDeclaration.HoistingScope.FunctionDeclarations, _functionDeclaration.HoistingScope.VariableDeclarations, this, arguments); _engine.Call(_engine.ExecuteStatement, _functionDeclaration.Body); return; } }