Example #1
0
    public static mdr.DArray CreateArgumentsObject(ref mdr.CallFrame callFrame, mdr.DObject context)
    {
      var metadata = (JSFunctionMetadata)callFrame.Function.Metadata;
      Debug.Assert(metadata.Scope.HasArgumentsSymbol, "Invalid situation, created arguments for the wrong scope!");
      mdr.DArray arguments = null;
      if (metadata.Scope.IsEvalFunction)
      {
        //Read from context
        var tmp = new mdr.DValue();
        context.GetField(JSFunctionArguments.Name, ref tmp);
        arguments = tmp.AsDArray();
      }
      else
      {
        arguments = CreateArgumentsObject(ref callFrame);
        var parameters = metadata.FunctionIR.Parameters;
        Debug.Assert(arguments.Length >= parameters.Count, "arguments array is not large enough to hold all arguments.");
        for (var i = parameters.Count - 1; i >= 0; --i)
        {
          var symbol = parameters[i].Symbol;
          var paramIndex = symbol.ParameterIndex;
          Debug.Assert(paramIndex == i, "Invalid situation!, Parameter indexes don't match!");

          if (symbol.SymbolType == JSSymbol.SymbolTypes.ClosedOnLocal)
          {
            var pd = context.AddOwnPropertyDescriptorByFieldId(symbol.FieldId, mdr.PropertyDescriptor.Attributes.Accessor | mdr.PropertyDescriptor.Attributes.NotConfigurable);
            context.Fields[pd.Index].Set(new ArgumentAccessor(arguments, paramIndex));
          }
        }
        if (metadata.Scope.HasEval)
          context.SetField(JSFunctionArguments.Name, arguments);
      }
      return arguments;
    }
Example #2
0
        private static void AddExtendedMethods(mdr.DObject obj)
        {
            #region Mozilla intrinsics
            obj.SetField("assertTrue", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                int argsLen = callFrame.PassedArgsCount;
                if (argsLen > 0)
                {
                    var b = Operations.Convert.ToBoolean.Run(ref callFrame.Arg0);
                    assert(b, argsLen > 1 ? callFrame.Arg1.AsString() : null);
                }
                else
                    Trace.Fail("Not enough arguments");
            }));

            obj.SetField("assertFalse", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                int argsLen = callFrame.PassedArgsCount;
                if (argsLen > 0)
                {
                    var b = Operations.Convert.ToBoolean.Run(ref callFrame.Arg0);
                    assert(!b, argsLen > 1 ? callFrame.Arg1.AsString() : null);
                }
                else
                    Trace.Fail("Not enough arguments");
            }));

            obj.SetField("assertEquals", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                int argsLen = callFrame.PassedArgsCount;
                if (argsLen > 1)
                {
                    bool b = Operations.Binary.Equal.Run(ref callFrame.Arg0, ref callFrame.Arg1);
                    assert(b, argsLen > 2 ? callFrame.Arg2.AsString() : null);
                }
                else
                    Trace.Fail("Not enough arguments");
            }));

            obj.SetField("assertArrayEquals", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                int argsLen = callFrame.PassedArgsCount;
                if (argsLen > 1)
                {
                    var arrayA = callFrame.Arg0.AsDArray();
                    var arrayB = callFrame.Arg1.AsDArray();
                    bool areEqual = true;
                    if (arrayA != null && arrayB != null && arrayA.Length == arrayB.Length)
                    {
                        for (int i = 0; i < arrayA.Length; i++)
                            if (Operations.Binary.Equal.Run(ref arrayA.Elements[i], ref arrayB.Elements[i]))
                            {
                                areEqual = false;
                                break;
                            }
                    }
                    else if (arrayA != arrayB)
                        areEqual = false;
                    assert(areEqual, argsLen > 2 ? callFrame.Arg2.AsString() : null);
                }
                else
                    Trace.Fail("Not enough arguments");
            }));
            #endregion

            // FIXME: The below causes an infinite recursion in CodeSourceGenerator. Commenting for now. - SF
            //SetField("global", this); //to enable access to global scope directly!
            obj.SetField("print", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                var l = callFrame.PassedArgsCount;
                for (var i = 0; i < l; ++i)
                {
                    var arg = callFrame.Arg(i);
                    string s = ToString(ref arg);
                    Console.Write("{0}{1}", s, (i < l - 1) ? " " : "");

                }
                Console.WriteLine();
            }));

            obj.SetField("load", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                var l = callFrame.PassedArgsCount;
                if (l < 1)
                    throw new Exception("load must have an argument");
                var filename = callFrame.Arg0.AsString();
                JSRuntime.Instance.RunScriptFile(filename);
            }));

            #region __mcjs__ object
            {
                var mcjs = new mdr.DObject(mdr.Runtime.Instance.EmptyPropertyMapMetadata.Root);
                obj.SetField("__mcjs__", mcjs);
                mcjs.SetField("SetSwitch", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
                {
                    var switchName = callFrame.Arg0.AsString();
                    var switchValue = Operations.Convert.ToBoolean.Run(ref callFrame.Arg1);
                    var prop = typeof(JSRuntimeConfiguration).GetProperty(switchName, CodeGen.Types.ClrSys.Boolean);
                    if (prop != null)
                        prop.GetSetMethod().Invoke(JSRuntime.Instance.Configuration, new object[] { switchValue });
                    else
                        Debug.WriteLine("JSRuntime.Instance.Configuration does not contain the switch '{0}'", switchName);
                }));

                mcjs.SetField("PrintDump", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
                {
                    var l = callFrame.PassedArgsCount;
                    if (l != 1)
                        throw new Exception("PrintDump must have one argument");
                    Debug.WriteLine("##JS: {0}", callFrame.Arg0.AsString());
#if DEBUG
                    //Check for android log directory
                    if (printOutFile == null)
                    {
                      printOutFile = System.IO.File.CreateText(System.IO.Path.Combine(JSRuntime.Instance.Configuration.OutputDir, "mcprint" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + ".out"));
                    }

                    printOutFile.Write("{0}", callFrame.Arg0.AsString());
                    printOutFile.Flush();
                    //Debug.WriteLine("MCPRINTVAR: {0}={1}", callFrame.Arg1.ToString(), s);
#endif
                }));

            }
            #endregion

        }
Example #3
0
        internal static void Init(mdr.DObject obj)
        {

            obj.SetField("global", obj);
            //obj.SetField("null", mdr.Runtime.Instance.DefaultDNull);
            obj.DefineOwnProperty("undefined", mdr.Runtime.Instance.DefaultDUndefined, mdr.PropertyDescriptor.Attributes.Data | mdr.PropertyDescriptor.Attributes.NotWritable | mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.NotConfigurable);
            obj.DefineOwnProperty("NaN", double.NaN, mdr.PropertyDescriptor.Attributes.Data | mdr.PropertyDescriptor.Attributes.NotWritable | mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.NotConfigurable);
            obj.DefineOwnProperty("Infinity", double.PositiveInfinity, mdr.PropertyDescriptor.Attributes.Data | mdr.PropertyDescriptor.Attributes.NotWritable | mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.NotConfigurable);

            obj.SetField("Object", new JSObject());
            obj.SetField("Function", new JSFunction());
            obj.SetField("Array", new JSArray());
            obj.SetField("ArrayBuffer", new JSArrayBuffer());
            obj.SetField("Int8Array", new JSInt8Array());
            obj.SetField("Uint8Array", new JSUint8Array());
            obj.SetField("Int16Array", new JSInt16Array());
            obj.SetField("Uint16Array", new JSUint16Array());
            obj.SetField("Int32Array", new JSInt32Array());
            obj.SetField("Uint32Array", new JSUint32Array());
            obj.SetField("Float32Array", new JSFloat32Array());
            obj.SetField("Float64Array", new JSFloat64Array());

            obj.SetField("Math", new JSMath());
            obj.SetField("String", new JSString());
            obj.SetField("Number", new JSNumber());
            obj.SetField("Date", new JSDate());
            obj.SetField("Boolean", new JSBoolean());
            obj.SetField("Error", new JSError());
            obj.SetField("RegExp", new JSRegExp());

            obj.SetField("eval", BuiltinEval);

            AddStandardMethods(obj);
            AddExtendedMethods(obj);
        }
Example #4
0
        // TODO: These are currently unused; can we remove them?
        /*private static char[] reservedEncoded = new char[] { ';', ',', '/', '?', ':', '@', '&', '=', '+', '$', '#' };
        private static char[] reservedEncodedComponent = new char[] { '-', '_', '.', '!', '~', '*', '\'', '(', ')', '[', ']' };*/

        private static void AddStandardMethods(mdr.DObject obj)
        {
            obj.SetField("ToNumber", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                if (callFrame.PassedArgsCount > 0)
                    callFrame.Return.Set(Operations.Convert.ToDouble.Run(ref callFrame.Arg0));
                else
                    callFrame.Return.Set(double.NaN);
            }));

            obj.SetField("isNaN", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                if (callFrame.PassedArgsCount > 0)
                    callFrame.Return.Set(double.IsNaN(Operations.Convert.ToDouble.Run(ref callFrame.Arg0)));
                else
                    callFrame.Return.Set(false);
            }));

            obj.SetField("isFinite", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                if (callFrame.PassedArgsCount > 0)
                {
                    double arg = Operations.Convert.ToDouble.Run(ref callFrame.Arg0);
                    callFrame.Return.Set(double.IsNaN(arg) || !double.IsInfinity(arg));
                }
                else
                    callFrame.Return.Set(false);
            }));

            obj.SetField("assert", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                for (int i = 0; i < callFrame.PassedArgsCount; ++i)
                {
                  var b = Operations.Convert.ToBoolean.Run(ref callFrame.Arg0);
                    if (!b)
                        throw new Exception("Error in script");
                }
            }));

            //ECMA-262: 15.1.2.2
            obj.SetField("parseInt", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
              if (callFrame.PassedArgsCount == 1 && mdr.ValueTypesHelper.IsNumber(callFrame.Arg0.ValueType))
                callFrame.Return.Set(Operations.Convert.ToInt32.Run(ref callFrame.Arg0));
              else
              {
                string stringArg = Operations.Convert.ToString.Run(ref callFrame.Arg0).TrimStart();
                int sign = 1;
                if (stringArg[0] == '-' || stringArg[0] == '+')
                {
                  if (stringArg[0] == '-')
                    sign = -1;
                  stringArg = stringArg.Remove(0, 1);
                }

                bool stripPrefix = true;
                int radix = 10;
                if (callFrame.PassedArgsCount > 1)
                {
                  radix = Operations.Convert.ToInt32.Run(ref callFrame.Arg1);
                  if (radix != 0)
                  {
                    if (radix < 2 || radix > 36)
                    {
                      callFrame.Return.Set(double.NaN);
                      return;
                    }
                    if (radix != 16)
                      stripPrefix = false;
                  }
                  else
                    radix = 10;
                }

                if (stripPrefix && (stringArg.StartsWith("0x") || stringArg.StartsWith("0X")))
                {
                  stringArg = stringArg.Remove(0, 2);
                  radix = 16;
                }

                callFrame.Return.Set(MathInt(stringArg, radix) * sign);
              }
            }));

            //ECMA-262: 15.1.2.3
            obj.SetField("parseFloat", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                string stringArg = (Operations.Convert.ToString.Run(ref callFrame.Arg0)).TrimStart();
                char[] charArg = stringArg.TrimEnd().ToCharArray();
                int len = charArg.Length;

                if (len == 0)
                {
                    callFrame.Return.Set(double.NaN);
                    return;
                }

                if (len == 1)
                {
                    if (char.IsDigit(charArg[0]))
                    {
                        callFrame.Return.Set((double)(charArg[0] - '0'));
                        return;
                    }
                }

                int i = 0;
                if (charArg[0] == '-' || charArg[0] == '+')
                    i = 1;

                bool punctation = false;
                for (; i < charArg.Length; ++i)
                {
                    if (!char.IsLetterOrDigit(charArg[i]) && charArg[i] != '.')
                        break;
                    if (charArg[i] == '-')
                        break;
                    if (punctation && charArg[i] == '.')
                        break;
                    if (charArg[i] == '.')
                        punctation = true;
                }

                stringArg = stringArg.Substring(0, i);

                double value = 0;
                if (Double.TryParse(stringArg, out value))
                {
                    callFrame.Return.Set(value);
                    return;
                }
                callFrame.Return.Set(double.NaN);
            }));

            //ECMA-262: 15.1.3.1
            obj.SetField("decodeURI", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSGlobalObject.decodeURI");
                string uri = callFrame.Arg0.AsString();
                callFrame.Return.Set(URIHandling.Decode(uri, URIHandling.uriReserved + "#"));
            }));

            //ECMA-262: 15.1.3.2
            obj.SetField("decodeURIComponent", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSGlobalObject.decodeURIComponent");
                if (callFrame.PassedArgsCount < 1 || callFrame.Arg0.ValueType == mdr.ValueTypes.Undefined)
                {
                    callFrame.Return.Set("");
                    return;
                }
                callFrame.Return.Set(URIHandling.Decode(callFrame.Arg0.AsString(), string.Empty));
            }));

            //ECMA-262: 15.1.3.3
            obj.SetField("encodeURI", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSGlobalObject.encodeURI");
                string uri = callFrame.Arg0.AsString();
                callFrame.Return.Set(URIHandling.Encode(uri, URIHandling.UriUnescaped + URIHandling.uriReserved + "#"));
            }));

            //ECMA-262: 15.1.3.4
            obj.SetField("encodeURIComponent", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSGlobalObject.encodeURIComponent");
                if (callFrame.PassedArgsCount < 1 || callFrame.Arg0.ValueType == mdr.ValueTypes.Undefined)
                {
                    callFrame.Return.Set("");
                    return;
                }
                callFrame.Return.Set(URIHandling.Encode(callFrame.Arg0.AsString(), URIHandling.UriUnescaped));
            }));

            obj.SetField("escape", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSGlobalObject.escape");              
                if (callFrame.PassedArgsCount == 1)
                {
                  string stringArg = callFrame.Arg0.AsString();
                  if (stringArg == null)
                  {
                    callFrame.Return.Set("");
                  }
                  else
                  {
                    string escArg = URIHandling.Escape(stringArg);
                    callFrame.Return.Set(escArg);
                  }
                }
                else
                {
                  callFrame.Return.Set("");
                }
            }));

            obj.SetField("unescape", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSGlobalObject.unescape");
                string stringArg = callFrame.Arg0.AsString();
                string unescArg = URIHandling.Unescape(stringArg);
                callFrame.Return.Set(unescArg);
            }));
        }