static string FormatArgs(ref mdr.CallFrame callFrame) { var formatString = callFrame.Arg0.AsString(); StringBuilder str = new StringBuilder(); int escapeIdx = 0, nextEscapeIdx = 0; var nextArg = 1; while ((nextEscapeIdx = formatString.IndexOfAny(FormatChars, escapeIdx)) != -1) { // Append non-escape characters str.Append(formatString.Substring(escapeIdx, nextEscapeIdx - escapeIdx)); // If we're at the last character in the string, just break out of the loop if (nextEscapeIdx == formatString.Length - 1) { escapeIdx = nextEscapeIdx; break; } // Interpret escape character if (formatString[nextEscapeIdx] == '\\') { if (formatString[nextEscapeIdx + 1] == '%') str.Append('%'); else str.AppendFormat("\\{0}", formatString[nextEscapeIdx + 1]); } else if (formatString[nextEscapeIdx] == '%') { var arg = callFrame.Arg(nextArg++); if (formatString[nextEscapeIdx + 1] == 's') str.Append(mjr.Operations.Convert.ToString.Run(ref arg)); else if (formatString[nextEscapeIdx + 1] == 'd') str.Append(mjr.Operations.Convert.ToInt64.Run(ref arg)); else if (formatString[nextEscapeIdx + 1] == 'i') str.Append(mjr.Operations.Convert.ToInt64.Run(ref arg)); else if (formatString[nextEscapeIdx + 1] == 'f') str.Append(mjr.Operations.Convert.ToDouble.Run(ref arg)); else str.AppendFormat("[%{0}]", formatString[nextEscapeIdx + 1]); } // Advance past the escaped character escapeIdx = nextEscapeIdx + 2; } // Append any remaining characters str.Append(formatString.Substring(escapeIdx)); // Return the finished formatted string return str.ToString(); }
private static void SetTimer(ref mdr.CallFrame callFrame, bool isInterval) { mdr.DFunction handler = null; //TODO: We might need to do it better using sth like Callable property if (callFrame.Arg0.ValueType == mdr.ValueTypes.Function) { handler = callFrame.Arg0.AsDFunction(); } else if (callFrame.Arg0.ValueType == mdr.ValueTypes.String) { handler = HTMLRuntime.Instance.PrepareScript(callFrame.Arg0.AsString()); } else { Debug.WriteLine("Invalid argument type {0} for setInterval", callFrame.Arg0.ValueType); //Trace.Fail("Invalid argument type {0} for setInterval", callFrame.Arg0.ValueType); } //TODO: Consider the case in which it's nor function or string long times = (long)callFrame.Arg1.AsInt32(); int argCount = callFrame.PassedArgsCount; TimeoutEvent timeout = new TimeoutEvent(times, isInterval); timeout.CallFrame.Function = handler; Debug.WriteLineIf( handler == null , "The {0} handler function of timer {1} is null and arg0.ValueType={2} with value {3}" , (isInterval ? "setInterval" : "setTimeout") , timeout.Id , callFrame.Arg0.ValueType , mjr.Operations.Convert.ToString.Run(ref callFrame.Arg0) ); //TODO: we need the following ASSERT, but for some reason, this will cause strange problems with WrappedObject.cpp:85 gcGetWrapper(), so we're going to catch this again later in TimerQueue.ProcessEvents //Debug.Assert(timeout.CallFrame.Function != null, "The setTimeout handler function must not be null"); if (argCount > 2) { timeout.CallFrame.PassedArgsCount = argCount - 2; if (timeout.CallFrame.PassedArgsCount > 4) { timeout.CallFrame.Arguments = new mdr.DValue[timeout.CallFrame.PassedArgsCount - 4]; } for (int i = 0; i < argCount - 2; i++) { var arg = callFrame.Arg(i + 2); timeout.CallFrame.SetArg(i, ref arg); } } HTMLRuntime.Instance.TimerQueue.SetTimeoutOrInterval(timeout); callFrame.Return.Set(timeout.Id); }
public void LoadArguments(List<Expression> arguments, ref mdr.CallFrame calleeFrame, ref mdr.CallFrame callFrame) { calleeFrame.PassedArgsCount = arguments.Count; switch (arguments.Count) { case 0: break; case 1: arguments[0].Execute(ref calleeFrame.Arg0, ref callFrame, this); break; case 2: arguments[0].Execute(ref calleeFrame.Arg0, ref callFrame, this); arguments[1].Execute(ref calleeFrame.Arg1, ref callFrame, this); break; case 3: arguments[0].Execute(ref calleeFrame.Arg0, ref callFrame, this); arguments[1].Execute(ref calleeFrame.Arg1, ref callFrame, this); arguments[2].Execute(ref calleeFrame.Arg2, ref callFrame, this); break; case 4: arguments[0].Execute(ref calleeFrame.Arg0, ref callFrame, this); arguments[1].Execute(ref calleeFrame.Arg1, ref callFrame, this); arguments[2].Execute(ref calleeFrame.Arg2, ref callFrame, this); arguments[3].Execute(ref calleeFrame.Arg3, ref callFrame, this); break; default: arguments[0].Execute(ref calleeFrame.Arg0, ref callFrame, this); arguments[1].Execute(ref calleeFrame.Arg1, ref callFrame, this); arguments[2].Execute(ref calleeFrame.Arg2, ref callFrame, this); arguments[3].Execute(ref calleeFrame.Arg3, ref callFrame, this); calleeFrame.Arguments = new mdr.DValue[arguments.Count - mdr.CallFrame.InlineArgsCount]; for (var i = 4; i < arguments.Count; ++i) arguments[i].Execute(ref calleeFrame.Arguments[i - mdr.CallFrame.InlineArgsCount], ref callFrame, this); break; } //TODO: remove signature calculation and only do it if needed for (var i = calleeFrame.PassedArgsCount - 1; i >= 0; --i) calleeFrame.Signature.InitArgType(i, calleeFrame.Arg(i).ValueType); }
internal void ReadSymbol(JSSymbol symbol, ref mdr.DValue result, ref mdr.CallFrame callFrame) { switch (symbol.SymbolType) { case JSSymbol.SymbolTypes.Local: case JSSymbol.SymbolTypes.HiddenLocal: case JSSymbol.SymbolTypes.Arguments: { if (symbol.IsParameter) if (Arguments != null) //result = Arguments.Elements[symbol.ParameterIndex]; Arguments.GetField(symbol.ParameterIndex, ref result); //TODO: optimize this for faster access else result = callFrame.Arg(symbol.ParameterIndex); else result = SymbolValues[symbol.ValueIndex]; break; } case JSSymbol.SymbolTypes.ClosedOnLocal: case JSSymbol.SymbolTypes.ParentLocal: case JSSymbol.SymbolTypes.Global: { var pd = GetPropertyDescriptor(symbol); pd.Get(Context, ref result); break; } case JSSymbol.SymbolTypes.Unknown: { var pd = Context.GetPropertyDescriptorByFieldId(symbol.FieldId); pd.Get(Context, ref result); break; } case JSSymbol.SymbolTypes.OuterDuplicate: ReadSymbol(symbol.ResolvedSymbol, ref result, ref callFrame); break; default: Trace.Fail("Could not interpret symbol {0} with type {1}", symbol.Name, symbol.SymbolType); break; } }
private void DeclareParameterSymbols(ref mdr.CallFrame callFrame) { var parameters = _currFuncMetadata.FunctionIR.Parameters; //Extend missing arguments callFrame.SetExpectedArgsCount(parameters.Count); if (_currScope.HasArgumentsSymbol) { ///In this case, we already read/write from the arguments.Elements[i] for the symbol. ///however, we should always refer to the arguments variable itself since its .Elements ///may be resized and changed ///we cannot rely on the argument symbol's variable for this since the progremmer ///may write the arguments symbol and we can lose the value, so we keep our own separately Arguments = JSFunctionArguments.CreateArgumentsObject(ref callFrame, Context); var symbols = _currScope.Symbols; for (var i = parameters.Count; i < symbols.Count; ++i) //Hopefully "arguments" is the symbol almost immediately after the parameters { var symbol = symbols[i]; if (symbol.SymbolType == JSSymbol.SymbolTypes.Arguments) { SymbolValues[symbol.ValueIndex].Set(Arguments); break; } } } else { Arguments = null; var i = parameters.Count; if (i > callFrame.PassedArgsCount) i = callFrame.PassedArgsCount; for (i = i - 1; i >= 0; --i) { var symbol = parameters[i].Symbol; Debug.Assert(symbol.ParameterIndex == i, "Invalid situation!, symbol {0} should be paramter with parameter index {1} instead of {2}", symbol.Name, i, symbol.ParameterIndex); if (symbol.SymbolType == JSSymbol.SymbolTypes.ClosedOnLocal) { var pd = Context.Map.GetPropertyDescriptorByFieldId(symbol.FieldId); Debug.Assert( pd != null && !pd.HasAttributes(mdr.PropertyDescriptor.Attributes.Undefined | mdr.PropertyDescriptor.Attributes.Inherited | mdr.PropertyDescriptor.Attributes.Accessor) , "Invalid situation, symbol {0} is not properly added to context", symbol.Name); Context.Fields[pd.Index] = callFrame.Arg(i); SymbolValues[symbol.ValueIndex].Set(pd); } } } }
// ECMA-262 section 15.5.3.2 void fromCharCode(ref mdr.CallFrame callFrame) { Debug.WriteLine("Calling JSString.fromCharCode()"); var l = callFrame.PassedArgsCount; var str = new System.Text.StringBuilder(); for (var i = 0; i < l; i++) { var arg = callFrame.Arg(i); str.Append(Operations.Convert.ToChar.Run(Operations.Convert.ToUInt16.Run(ref arg))); } callFrame.Return.Set(str.ToString()); }
// ECMA-262, section 15.5.4.6 void concat(ref mdr.CallFrame callFrame) { Debug.WriteLine("Calling JSString.concat()"); var argLen = callFrame.PassedArgsCount; string thisString = callFrame.This.ToString(); if (argLen == 1) { callFrame.Return.Set(thisString + Operations.Convert.ToString.Run(ref callFrame.Arg0)); } string result = thisString; for (var i = 0; i < argLen; i++) { var tmp = callFrame.Arg(i); result += Operations.Convert.ToString.Run(ref tmp); } callFrame.Return.Set(result); }