示例#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;
    }
示例#2
0
        internal static void EvalString(string inputString, ref mdr.DValue result, mdr.DFunction callerFunction = null, mdr.DObject callerContext = null, mdr.DObject thisArg = null)
        {
            var funcMetadata = JSParser.ParseScript(inputString).Expression.Metadata;
            var func         = new mdr.DFunction(funcMetadata, null);

            var  tempCallFrame = new mdr.CallFrame();
            bool isDirectEval  = callerContext != null;

            if (isDirectEval)
            {
                //function will behave as if it was the caller
                Debug.Assert(thisArg != null && callerFunction != null && callerContext != null, "Invalid situation! Direct eval call must have thisArg, callerFunction, callerContext set");
                funcMetadata.Scope.IsProgram      = false;
                funcMetadata.Scope.IsEvalFunction = true;
                funcMetadata.ParentFunction       = (JSFunctionMetadata)callerFunction.Metadata;
                tempCallFrame.CallerContext       = callerContext;
                tempCallFrame.This = thisArg;
            }
            else
            {
                //This will behave just like a program code
                tempCallFrame.CallerContext = mdr.Runtime.Instance.GlobalContext;
                tempCallFrame.This          = (mdr.Runtime.Instance.GlobalContext);
            }

            //TODO: find a way to assign a name to this
            //funcMetadata.Name += "_eval"; //After we know the ParentFunction

            tempCallFrame.Function  = func;
            tempCallFrame.Signature = mdr.DFunctionSignature.EmptySignature;
            func.Call(ref tempCallFrame);
            result.Set(ref tempCallFrame.Return);
        }
示例#3
0
        //public static mdr.DValue IncDec(ref mdr.DValue i0, int i1)
        //{
        //    var result = new mdr.DValue();
        //    switch (i0.ValueType)
        //    {
        //        case mdr.ValueTypes.Int:
        //            {
        //                int oldValue = i0.IntValue;
        //                int newValue = oldValue + i1;
        //                result.Set(newValue);
        //                break;
        //            }
        //        case mdr.ValueTypes.Boolean:
        //            {
        //                int oldValue = i0.BoolValue ? 1 : 0;
        //                int newValue = oldValue + i1;
        //                result.Set(newValue);
        //                break;
        //            }
        //        default:
        //            {
        //                double oldValue = i0.ToDouble();
        //                double newValue = oldValue + i1;
        //                result.Set(newValue);
        //                break;
        //            }
        //    }
        //    return result;
        //}

        /// <summary>
        /// The following is used for inc/dec that involves DValue. To handle arrays and properties well, we will have a separate object for
        /// reading the value, and another for setting. To make the inc/dec and assign, etc. uniform, we should consider that on the stack
        /// we have all the paramertes always for all kinds of values (symbols, arrays, properties, ...)
        ///
        /// followings:
        ///     dest for writing
        ///     DObject  for setting (for array/property will be a member of the object itself)
        ///     DObject  for reading (for array/property may be a member of the object's prototype)
        /// </summary>
        /// <param name="result">for returing the value that is used in the next instruction.</param>
        /// <param name="dest">For updating the source itself</param>
        /// <param name="i0">the source for reading the value</param>
        /// <param name="i1">1 for inc and -1 for dec</param>
        /// <param name="isPostfix"></param>
        /// <returns></returns>
        public static void AddConst(ref mdr.DValue dest, /*const*/ ref mdr.DValue i0, int i1, bool isPostfix, ref mdr.DValue result)
        {
            switch (i0.ValueType)
            {
            case mdr.ValueTypes.Int32:
            {
                int oldValue = i0.IntValue;
                int newValue = oldValue + i1;
                dest.Set(newValue);
                result.Set(isPostfix ? oldValue : newValue);
                break;
            }

            case mdr.ValueTypes.Boolean:
            {
                int oldValue = i0.BooleanValue ? 1 : 0;
                int newValue = oldValue + i1;
                dest.Set(newValue);
                result.Set(isPostfix ? oldValue : newValue);
                break;
            }

            default:
            {
                double oldValue = i0.AsDouble();
                double newValue = oldValue + i1;
                dest.Set(newValue);
                result.Set(isPostfix ? oldValue : newValue);
                break;
            }
            }
        }
示例#4
0
        /// <summary>
        /// Parse a number. Intended to be used at runtime for string-to-number conversions.
        /// </summary>
        public static void ParseNumber(string number, ref mdr.DValue dValue)
        {
            var parser         = new JavaScriptParser.SequentialParser(number);
            var numericLiteral = parser.ParseNumber();

            // Convert to a DValue and return via the ref parameter.
            Debug.Assert(numericLiteral is IR.PrimitiveLiteral, "ParseNumber() should yield a PrimitiveLiteral.");
            (numericLiteral as IR.PrimitiveLiteral).SetAsDValue(ref dValue);
        }
示例#5
0
 // i0 ? i1 : i2
 public static void Run(ref mdr.DValue i0, ref mdr.DValue i1, ref mdr.DValue i2, ref mdr.DValue result)
 {
     if (Operations.Convert.ToBoolean.Run(ref i0))
     {
         result.Set(ref i1);
     }
     else
     {
         result.Set(ref i2);
     }
 }
示例#6
0
文件: ToUInt16.cs 项目: reshadi2/mcjs
 public static char Run(string i0) 
 {
   if (i0.Length == 1)
     return i0[0];
   else
   {
     var number = new mdr.DValue(); 
     Convert.ToNumber.Run(i0, ref number); 
     return Run(ref number);
   }
 }
示例#7
0
 public static char Run(string i0)
 {
     if (i0.Length == 1)
     {
         return(i0[0]);
     }
     else
     {
         var number = new mdr.DValue();
         Convert.ToNumber.Run(i0, ref number);
         return(Run(ref number));
     }
 }
示例#8
0
        public override void SetGlobalContext(mdr.DObject globalContext)
        {
            var timer = StartTimer(Configuration.ProfileInitTime, "JS/GlobalInit");

            try
            {
                base.SetGlobalContext(globalContext); //This will set the GlobalContext
                if (JSRuntime.Instance.Configuration.EnableRecursiveInterpreter && false)
                {
                    var result = new mdr.DValue();
                    Builtins.JSGlobalObject.EvalString(@"
Object.defineProperty(Array.prototype, 'pop', 
{
  enumerable: false,
  value: function() 
  {
    var n = (this.length);
    if (n == 0) {
      this.length = n;
      return;
    }
    n--;
    var value = this[n];
    delete this[n];
    this.length = n;
    return value;
  }
});

Object.defineProperty(Array.prototype, 'push', 
{
  enumerable: false,
  value: function() 
  {
    var n = this.length;
    var m = arguments.length;
    for (var i = 0; i < m; i++) {
      this[i+n] = arguments[i];
    }
    this.length = n + m;
    return this.length;
  }
});
", ref result);
                }
            }
            finally
            {
                StopTimer(timer);
            }
        }
示例#9
0
        public static void Run(ref mdr.DValue i0, int i1)
        {
            switch (i0.ValueType)
            {
            case mdr.ValueTypes.Double:
            {
                double oldValue = i0.DoubleValue;
                double newValue = oldValue + i1;
                i0.DoubleValue = newValue;
                //i0.Set(newValue);
                break;
            }

            case mdr.ValueTypes.Int32:
            {
                int oldValue = i0.IntValue;
                int newValue = oldValue + i1;
                i0.IntValue = newValue;
                //i0.Set(newValue);
                break;
            }

            case mdr.ValueTypes.Boolean:
            {
                int oldValue = i0.BooleanValue ? 1 : 0;
                int newValue = oldValue + i1;
                i0.Set(newValue);
                break;
            }

            default:
            {
                double oldValue = i0.AsDouble();
                double newValue = oldValue + i1;
                i0.Set(newValue);
                break;
            }
            }
        }
示例#10
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);
        }
示例#11
0
        public static string ToString(ref mdr.DValue arg)
        {
            //TODO: it seems eventually, this is the right implementation, but for now, we use the special implementation
            //mdr.DValue output;
            //if (Operations.Internals.CallToStringProperty(Operations.Convert.ToObject.Run(ref arg), out output))
            //  return output.AsString();
            //else
            //  return Operations.Convert.ToString.Run(ref arg);

            string s;

            if (!mdr.ValueTypesHelper.IsObject(arg.ValueType))
            {
                s = Operations.Convert.ToString.Run(ref arg);
            }
            else
            {
                var argObj   = arg.AsDObject(); //TODO: should we call ToObject(arg) here instead?!
                var toString = argObj.GetField("toString");
                if (toString.ValueType == mdr.ValueTypes.Function)
                {
                    var cf = new mdr.CallFrame();
                    cf.Function  = toString.AsDFunction();
                    cf.Signature = mdr.DFunctionSignature.EmptySignature;
                    cf.This      = argObj;
                    cf.Arguments = null;
                    cf.Function.Call(ref cf);
                    s = Operations.Convert.ToString.Run(ref cf.Return);
                }
                else
                {
                    s = arg.AsString();
                }
            }
            return(s);
        }
示例#12
0
 public abstract void SetAsDValue(ref mdr.DValue dValue);
示例#13
0
 public static void Run(mdr.DNull i0, ref mdr.DValue result)
 {
     result.Set(i0);
 }
示例#14
0
 public void Visit <T>(mdr.DValue <T> obj)
 {
     throw new NotImplementedException();
 }
示例#15
0
 private void RunBody(ref mdr.CallFrame callFrame)
 {
   //as tempting it might be, we cannot use the callFrame.Return here since function may not have a return statement at all.
   var result = new mdr.DValue();
   _currFuncMetadata.FunctionIR.Statement.Execute(ref result, ref callFrame, this);
 }
示例#16
0
    public override void Execute(ref mdr.DValue result, ref mdr.CallFrame callFrame, Interpreter interpreter)
    {
      interpreter.PushLocation(this);

      var tmpCallFrame = new mdr.CallFrame();

      Function.Execute(ref result, ref callFrame, interpreter);

      if (ThisArg != null)
      {
        var thisValue = new mdr.DValue();
        ThisArg.Execute(ref thisValue, ref callFrame, interpreter);
        tmpCallFrame.This = thisValue.AsDObject();
      }
      else if (IsDirectEvalCall)
      {
        tmpCallFrame.CallerFunction = callFrame.Function;
        tmpCallFrame.CallerContext = interpreter.Context;
        tmpCallFrame.This = callFrame.This;
      }
      else
      {
        tmpCallFrame.This = mdr.Runtime.Instance.GlobalContext;
      }

      interpreter.LoadArguments(this.Arguments, ref tmpCallFrame, ref callFrame);

      tmpCallFrame.Function = result.AsDFunction();
      JSRuntime.StopTimer(interpreter.Timer);
      tmpCallFrame.Function.Call(ref tmpCallFrame);
      JSRuntime.StartTimer(interpreter.Timer);
      result = tmpCallFrame.Return;

      interpreter.PopLocation(this, tmpCallFrame.Function);
    }
示例#17
0
    public override void Execute(ref mdr.DValue result, ref mdr.CallFrame callFrame, Interpreter interpreter)
    {
      interpreter.PushLocation(this);

      Container.Execute(ref result, ref callFrame, interpreter);
      var obj = result.AsDObject();
      var index = new mdr.DValue();
      Index.Execute(ref index, ref callFrame, interpreter);
      Value.Execute(ref result, ref callFrame, interpreter);
      obj.SetField(ref index, ref result);

      //interpreter.PopLocation(this, ref result, obj);
      interpreter.PopLocation(this, ref result);
    }
示例#18
0
        public static void WriteValueToContext(ref mdr.CallFrame callFrame, int valueIndex, int fieldId, ref mdr.DValue value)
        {
            var pd = GetPropertyDescriptor(ref callFrame, valueIndex, fieldId);

            if (pd.IsUndefined)
            {
                JSRuntime.Instance.GlobalContext.SetFieldByFieldId(fieldId, ref value);
            }
            else
            {
                var context = GetContext(ref callFrame);
                pd.Set(context, ref value);
            }
        }
示例#19
0
        /// <param name="input">Javascript value</param>
        /// <param name="output">Will have the primitive type of the input when the function returns</param>
        /// <param name="stringHint">Specifies whether the hint is string or number. Default is number.</param>

        //public static void Run(ref mdr.DValue input, out mdr.DValue output, bool stringHint = false)
        //{
        //  mdr.ValueTypes inputType = input.ValueType;
        //  if (mdr.ValueTypesHelper.IsObject(inputType))
        //    Internals.DefaultValue(ref input, out output, stringHint);
        //  else // type is a primitive type
        //    output = input;
        //}
        public static void Run(mdr.DObject input, ref mdr.DValue output, bool stringHint = false)
        {
            Internals.DefaultValue(input, out output, stringHint);
        }
示例#20
0
 public static void Run(double i0, ref mdr.DValue result)
 {
     result.Set(i0);
 }
示例#21
0
 public static void LoadDValue(ref mdr.DValue value, ref Stack stack)
 {
     stack.Items[stack.Sp++].Set(ref value);
 }
示例#22
0
 public JSException(ref mdr.DValue e) : this()
 {
     Value.Set(ref e);
 }
示例#23
0
 public static void Throw(ref mdr.DValue e)
 {
     throw new JSException(ref e);
 }
示例#24
0
 public static void Run(mdr.DFunction i0, ref mdr.DValue result)
 {
     result.Set(i0);
 }
示例#25
0
 public static void Run(mdr.DObject i0, ref mdr.DValue result)
 {
     result.Set(i0);
 }
示例#26
0
 public static void Run(mdr.DUndefined i0, ref mdr.DValue result)
 {
     result.Set(i0);
 }
示例#27
0
        public JSArray()
            : base(mdr.Runtime.Instance.DArrayPrototype, "Array")
        {
            JittedCode = (ref mdr.CallFrame callFrame) =>
            {
                mdr.DArray array;

                var argsCount = callFrame.PassedArgsCount;

                if (argsCount == 1)
                {
                    var len = Operations.Convert.ToInt32.Run(ref callFrame.Arg0);
                    array = new mdr.DArray(len);
                }
                else
                {
                    array = new mdr.DArray(argsCount);
                    switch (argsCount)
                    {
                    case 0: break;

                    case 1: break;

                    case 2:
                        array.Elements[1] = callFrame.Arg1;
                        array.Elements[0] = callFrame.Arg0;
                        break;

                    case 3:
                        array.Elements[2] = callFrame.Arg2;
                        goto case 2;

                    case 4:
                        array.Elements[3] = callFrame.Arg3;
                        goto case 3;

                    default:
                        Debug.Assert(argsCount > mdr.CallFrame.InlineArgsCount, "Code gen must be updated to support new CallFrame");
                        Array.Copy(callFrame.Arguments, 0, array.Elements, mdr.CallFrame.InlineArgsCount, argsCount - mdr.CallFrame.InlineArgsCount);
                        goto case 4;
                    }
                }
                if (IsConstrutor)
                {
                    callFrame.This = (array);
                }
                else
                {
                    callFrame.Return.Set(array);
                }
            };

            // ECMA-262 section 15.4.3.1
            this.DefineOwnProperty("isArray", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.isArray");
                if (callFrame.This.ValueType == mdr.ValueTypes.Array)
                {
                    callFrame.Return.Set(true);
                }
                else
                {
                    callFrame.Return.Set(false);
                }
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.2
            TargetPrototype.DefineOwnProperty("toString", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.toString");
                var join = callFrame.This.GetField("join");
                if (join.ValueType == mdr.ValueTypes.Function)// it is callable
                {
                    var joinFun = join.AsDFunction();
                    Debug.Assert(joinFun != null, "Invalid situation!");
                    callFrame.Function = joinFun;
                    //callFrame.This is already set
                    callFrame.Signature       = mdr.DFunctionSignature.EmptySignature;
                    callFrame.PassedArgsCount = 0;
                    callFrame.Arguments       = null;
                    joinFun.Call(ref callFrame);
                    callFrame.Return.Set(callFrame.Return.AsString());
                }
                else
                {
                    callFrame.Return.Set(callFrame.This.ToString());
                }
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.3
            TargetPrototype.DefineOwnProperty("toLocaleString", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                throw new NotImplementedException("Array.toLocaleString is not implemented");
                // TODO: callFrame.This is not an accurate implementation

                /*mdr.DObject array = callFrame.This;
                 * mdr.DFunction join = array.GetField("join").ToDObject() as mdr.DFunction;
                 * if (join != null) // it is callable
                 * {
                 *  callFrame.Function = join;
                 *  callFrame.Signature = mdr.DFunctionSignature.EmptySignature;
                 *  callFrame.Arguments = null;
                 *  join.Call(ref callFrame);
                 *  callFrame.Return.Set(callFrame.Return.ToString());    //TODO: is this the right implementation?
                 * }
                 * else
                 *  callFrame.Return.Set(array.ToString());*/
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.4
            TargetPrototype.DefineOwnProperty("concat", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.concat");
                //The most common case is calling .concat on array object with normal set of arguments
                mdr.DArray newArray;
                var destStartIndex = 0;

                var thisArray = callFrame.This as mdr.DArray;
                if (thisArray != null)
                {
                    newArray = new mdr.DArray(callFrame.PassedArgsCount + thisArray.Length);
                    Array.Copy(thisArray.Elements, 0, newArray.Elements, 0, thisArray.Length);
                    destStartIndex = thisArray.Length;
                }
                else
                {
                    newArray = new mdr.DArray(callFrame.PassedArgsCount + 1);
                    newArray.Elements[0].Set(callFrame.This);
                    destStartIndex = 1;
                }
                for (int i = 0; i < callFrame.PassedArgsCount; ++i)
                {
                    newArray.Elements[destStartIndex] = callFrame.Arg(i); //This is the common case
                    if (newArray.Elements[destStartIndex].ValueType == mdr.ValueTypes.Array)
                    {
                        var array = newArray.Elements[destStartIndex].AsDArray();
                        //We had already accounted 1 cell for this item, so, we add the missing remaining elements
                        newArray.Length += (array.Length - 1); //Extends newArray.Elements
                        Array.Copy(array.Elements, 0, newArray.Elements, destStartIndex, array.Length);
                        destStartIndex += array.Length;
                    }
                    else
                    {
                        ++destStartIndex;
                    }
                }
                //concat(newArray, ref callFrame.Arguments[i]);

                callFrame.Return.Set(newArray);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.5
            TargetPrototype.DefineOwnProperty("join", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.join");
                string separator = (callFrame.PassedArgsCount == 0 || callFrame.Arg0.ValueType == mdr.ValueTypes.Undefined)
                    ? ","
                    : callFrame.Arg0.AsString();

                callFrame.Return.Set(join(callFrame.This, separator).ToString());
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.6
            TargetPrototype.DefineOwnProperty("pop", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.pop");
                var This     = callFrame.This;
                var lenField = This.GetField("length");
                int len      = Operations.Convert.ToInt32.Run(ref lenField);
                if (len == 0)
                {
                    This.SetField("length", 0);
                    callFrame.Return.Set(mdr.Runtime.Instance.DefaultDUndefined);
                }
                else if (len > 0)
                {
                    var index          = len - 1;
                    mdr.DValue element = new mdr.DValue();
                    This.GetField(index, ref element);
                    This.DeletePropertyDescriptor(index.ToString());
                    This.SetField("length", index);
                    callFrame.Return.Set(ref element);
                }
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.7
            TargetPrototype.DefineOwnProperty("push", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.push");
                var This       = callFrame.This;
                var lenField   = This.GetField("length");
                int len        = Operations.Convert.ToInt32.Run(ref lenField);
                mdr.DValue arg = new mdr.DValue();
                for (int i = 0; i < callFrame.PassedArgsCount; ++i)
                {
                    arg = callFrame.Arg(i);
                    This.SetField(len, ref arg);
                    len++;
                }
                This.SetField("length", len);
                callFrame.Return.Set(len);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.8
            TargetPrototype.DefineOwnProperty("reverse", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.reverse");
                var This              = callFrame.This;
                var lenField          = This.GetField("length");
                int len               = Operations.Convert.ToInt32.Run(ref lenField);
                int middle            = len / 2;
                mdr.DValue lowerValue = new mdr.DValue();
                mdr.DValue upperValue = new mdr.DValue();
                bool lowerExists, upperExists;
                for (int lower = 0; lower != middle; lower++)
                {
                    int upper   = len - lower - 1;
                    lowerExists = This.HasProperty(lower);
                    upperExists = This.HasProperty(upper);
                    if (lowerExists && upperExists)
                    {
                        This.GetField(lower, ref lowerValue);
                        This.GetField(upper, ref upperValue);
                        This.SetField(lower, ref upperValue);
                        This.SetField(upper, ref lowerValue);
                    }
                    else if (!lowerExists && upperExists)
                    {
                        This.GetField(upper, ref upperValue);
                        This.SetField(lower, ref upperValue);
                        This.DeletePropertyDescriptor(upper.ToString());
                    }
                    else if (lowerExists && !upperExists)
                    {
                        This.GetField(lower, ref lowerValue);
                        This.SetField(upper, ref lowerValue);
                        This.DeletePropertyDescriptor(lower.ToString());
                    }
                }
                callFrame.Return.Set(This);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.9
            TargetPrototype.DefineOwnProperty("shift", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.shift");
                mdr.DArray array = callFrame.This.ToDArray();
                int len          = array.Length;
                if (array == null || array.Length == 0)
                {
                    //callFrame.Return.ValueType = mdr.ValueTypes.Undefined;
                    callFrame.Return.Set(mdr.Runtime.Instance.DefaultDUndefined);
                }
                else
                {
                    callFrame.Return.Set(ref array.Elements[0]);
                    for (int k = 1; k < len; k++)
                    {
                        array.Elements[k - 1].Set(ref array.Elements[k]);
                    }

                    array.Length--;
                }
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.10
            TargetPrototype.DefineOwnProperty("slice", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.slice");

                /*  TODO: This is the implementation for a case that "this" is a DArray. Use this faster implementation after adding PackedArray optimization.
                 * mdr.DArray array = callFrame.This.ToDArray();
                 * int len = array.Length;
                 * int relativeStart = callFrame.Arg0.ToInt32();
                 * int k = (relativeStart < 0) ? Math.Max(len + relativeStart, 0) : Math.Min(relativeStart, len);
                 * int relativeEnd = (callFrame.Arg1.ValueType == mdr.ValueTypes.Undefined) ? len : callFrame.Arg1.ToInt32();
                 * int final = (relativeEnd < 0) ? Math.Max(relativeEnd + len, 0) : Math.Min(relativeEnd, len);
                 * mdr.DArray newArray = new mdr.DArray((final - k > 0) ? (final - k) : 0);
                 * for (int n = 0; k < final; k++, n++)
                 *  newArray.Elements[n].Set(ref array.Elements[k]);
                 * callFrame.Return.Set(newArray);
                 */

                var This          = callFrame.This;
                var lenField      = This.GetField("length");
                int len           = Operations.Convert.ToInt32.Run(ref lenField);
                int relativeStart = 0;
                if (callFrame.PassedArgsCount > 0)
                {
                    relativeStart = Operations.Convert.ToInt32.Run(ref callFrame.Arg0);
                }
                int k               = (relativeStart < 0) ? Math.Max(len + relativeStart, 0) : Math.Min(relativeStart, len);
                int relativeEnd     = ((callFrame.Arg1.ValueType == mdr.ValueTypes.Undefined) || (callFrame.PassedArgsCount < 2)) ? len : Operations.Convert.ToInt32.Run(ref callFrame.Arg1);
                int final           = (relativeEnd < 0) ? Math.Max(relativeEnd + len, 0) : Math.Min(relativeEnd, len);
                mdr.DArray newArray = new mdr.DArray((final - k > 0) ? (final - k) : 0);
                mdr.DValue item     = new mdr.DValue();
                for (int n = 0; k < final; k++, n++)
                {
                    This.GetField(k, ref item);
                    newArray.Elements[n].Set(ref item);
                }
                callFrame.Return.Set(newArray);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.12
            //TODO: splice is generic and can be applied to other objects
            TargetPrototype.DefineOwnProperty("splice", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.splice");
                if (callFrame.PassedArgsCount < 2)
                {
                    callFrame.Return.Set(JSRuntime.Instance.DefaultDUndefined);
                    return;
                }
                var A    = new mdr.DArray();
                var This = callFrame.This as mdr.DArray;
                if (This == null)
                {
                    throw new Exception("Object is not an array, but splice must work with generic objects. Please fix it!");
                }
                int len               = This.Length;
                int relativeStart     = Operations.Convert.ToInt32.Run(ref callFrame.Arg0);
                int actualStart       = relativeStart < 0 ? Math.Max(len + relativeStart, 0) : Math.Min(relativeStart, len);
                int actualDeleteCount = Math.Min(Math.Max(Operations.Convert.ToInt32.Run(ref callFrame.Arg1), 0), len - actualStart);

                A.Length = actualDeleteCount;
                for (int k = 0; k < actualDeleteCount; k++)
                {
                    int from = relativeStart + k;
                    if (from < len)
                    {
                        A.Elements[k].Set(ref This.Elements[from]);
                    }
                }

                int itemCount = callFrame.PassedArgsCount - 2;
                if (itemCount < actualDeleteCount)
                {
                    for (int k = actualStart; k < len - actualDeleteCount; k++)
                    {
                        int from = k + actualDeleteCount;
                        int to   = k + itemCount;
                        // if (from < len) // This condition will always hold
                        This.Elements[to].Set(ref This.Elements[from]);
                        // from will always be less than less and therefore the element exists in the array
                        //TODO: can we assume any index less than Length exist? When an element is deleted from middle of the Elements, is Length adjusted?

                        /*
                         * else
                         * {
                         *  This.RemoveElements(to, len - actualDeleteCount - k);
                         *  break;
                         * }*/
                    }
                    This.RemoveElements(len - actualDeleteCount + itemCount, actualDeleteCount - itemCount);
                    This.Length = len - actualDeleteCount + itemCount;
                }
                else if (itemCount > actualDeleteCount)
                {
                    This.Length = len - actualDeleteCount + itemCount;
                    for (int k = len - actualDeleteCount; k > actualStart; k--)
                    {
                        int from = k + actualDeleteCount - 1;
                        int to   = k + itemCount - 1;
                        //if (from < len) //This condition will always hold
                        This.Elements[to].Set(ref This.Elements[from]);
                    }
                }

                for (int k = 0; k < itemCount; k++)
                {
                    This.Elements[k + actualStart] = callFrame.Arg(k + 2);
                }


                callFrame.Return.Set(A);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.11
            TargetPrototype.DefineOwnProperty("sort", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.sort");
                mdr.DArray array = callFrame.This.ToDArray();
                int len          = array.Length;
                if (len == 0)
                {
                    callFrame.Return.Set(array);
                }

                int argsCount       = callFrame.PassedArgsCount;
                mdr.DValue function = callFrame.Arg0;

                for (uint i = 0; i < len - 1; ++i)
                {
                    mdr.DValue iObj   = array.Elements[i];
                    uint themin       = i;
                    mdr.DValue minObj = iObj;
                    for (uint j = i + 1; j < len; ++j)
                    {
                        mdr.DValue jObj      = array.Elements[j];
                        double compareResult = 0;
                        if (jObj.ValueType == mdr.ValueTypes.Undefined)
                        {
                            compareResult = 1;
                        }
                        else if (minObj.ValueType == mdr.ValueTypes.Undefined)
                        {
                            compareResult = -1;
                        }
                        else if (argsCount == 1 && function.ValueType == mdr.ValueTypes.Function)
                        {
                            callFrame.Function = function.AsDFunction();
                            callFrame.SetArg(0, ref minObj);
                            callFrame.SetArg(1, ref jObj);
                            callFrame.PassedArgsCount = 2;
                            callFrame.Signature       = new mdr.DFunctionSignature(ref callFrame, 2);
                            callFrame.Function.Call(ref callFrame);
                            compareResult = Operations.Convert.ToInt32.Run(ref callFrame.Return) <= 0 ? 1 : -1;
                        }
                        else
                        {
                            mdr.DValue v1 = mdr.DValue.Create(jObj.AsString());
                            mdr.DValue v2 = mdr.DValue.Create(minObj.AsString());
                            compareResult = Operations.Binary.LessThan.Run(ref v1, ref v2) ? -1 : 1;
                        }

                        if (compareResult < 0)
                        {
                            themin = j;
                            minObj = jObj;
                        }
                    }
                    if (themin > i)
                    {
                        array.Elements[i]      = minObj;
                        array.Elements[themin] = iObj;
                    }
                }
                callFrame.Return.Set(array);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.13
            TargetPrototype.DefineOwnProperty("unshift", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.unshift");
                var thisObj      = callFrame.This;
                mdr.DArray array = thisObj.ToDArray();

                int len       = array.Length;
                int argsCount = callFrame.PassedArgsCount;
                array.ResizeElements(len + argsCount);
                array.Length = len + argsCount;
                if (argsCount != 0 && len != 0)
                {
                    mdr.DValue iObj;
                    for (int i = len; i > 0; --i)
                    {
                        iObj = array.Elements[i - 1];
                        array.Elements[i - 1].Set(0);
                        array.Elements[i + argsCount - 1] = iObj;
                    }
                }
                for (int k = 0; k < argsCount; ++k)
                {
                    array.Elements[k] = callFrame.Arg(k);
                }
                callFrame.Return.Set(array.Length);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.14
            TargetPrototype.DefineOwnProperty("indexOf", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.indexOf");
                mdr.DArray array = callFrame.This.ToDArray();
                int len          = array.Length;
                int index        = 0;
                if (callFrame.PassedArgsCount > 1)
                {
                    index = Operations.Convert.ToInt32.Run(ref callFrame.Arg1);
                }
                index = index < 0 ? Math.Max(len + index, 0) : Math.Min(index, len);
                mdr.DValue searchElem = callFrame.Arg0;
                for (; index < len; ++index)
                {
                    mdr.DValue indexElem = array.Elements[index];
                    if (indexElem.ValueType != mdr.ValueTypes.Undefined &&
                        Operations.Binary.Equal.Run(ref indexElem, ref searchElem))
                    {
                        callFrame.Return.Set(index);
                        return;
                    }
                }
                callFrame.Return.Set(-1);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.15
            TargetPrototype.DefineOwnProperty("lastIndexOf", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.lastIndexOf");
                mdr.DArray array = callFrame.This.ToDArray();
                int len          = array.Length;
                if (len == 0)
                {
                    callFrame.Return.Set(-1);
                    return;
                }
                int index = len - 1;
                if (callFrame.PassedArgsCount > 1)
                {
                    index = Operations.Convert.ToInt32.Run(ref callFrame.Arg1);
                }
                index = index < 0 ? len + index : Math.Min(index, len - 1);
                if (index < 0)
                {
                    callFrame.Return.Set(-1);
                    return;
                }
                mdr.DValue searchElem = callFrame.Arg0;
                do
                {
                    mdr.DValue indexElem = array.Elements[index];
                    if (indexElem.ValueType != mdr.ValueTypes.Undefined &&
                        Operations.Binary.Equal.Run(ref indexElem, ref searchElem))
                    {
                        callFrame.Return.Set(index);
                        return;
                    }
                } while (index-- > 0);
                callFrame.Return.Set(-1);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.16
            TargetPrototype.DefineOwnProperty("every", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.every");
                var thisObj      = callFrame.This;
                mdr.DArray array = thisObj.ToDArray();
                int len          = array.Length;
                if (len == 0)
                {
                    callFrame.Return.Set(array);
                }

                // TODO: Commented because argsCount is unused.
                /*int argsCount = callFrame.ArgsCount;*/
                mdr.DFunction function = callFrame.Arg0.AsDFunction();
                bool result            = true;

                for (int i = 0; i < len; ++i)
                {
                    if (array.Elements[i].ValueType != mdr.ValueTypes.Undefined)
                    {
                        callFrame.Function = function;
                        callFrame.SetArg(0, ref array.Elements[i]);
                        callFrame.SetArg(1, i);
                        callFrame.SetArg(2, thisObj);
                        callFrame.Signature = new mdr.DFunctionSignature(ref callFrame, 3);
                        callFrame.Function.Call(ref callFrame);
                        if (Operations.Convert.ToBoolean.Run(ref callFrame.Return) == false)
                        {
                            result = false;
                            break;
                        }
                    }
                }
                callFrame.Return.Set(result);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.17
            TargetPrototype.DefineOwnProperty("some", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.some");
                var thisObj      = callFrame.This;
                mdr.DArray array = thisObj.ToDArray();
                int len          = array.Length;
                if (len == 0)
                {
                    callFrame.Return.Set(array);
                }

                // TODO: Commented because argsCount is unused.
                /*int argsCount = callFrame.ArgsCount;*/
                mdr.DFunction function = callFrame.Arg0.AsDFunction();
                bool result            = false;

                for (int i = 0; i < len; ++i)
                {
                    if (array.Elements[i].ValueType != mdr.ValueTypes.Undefined)
                    {
                        callFrame.Function = function;
                        callFrame.SetArg(0, ref array.Elements[i]);
                        callFrame.SetArg(1, i);
                        callFrame.SetArg(2, thisObj);
                        callFrame.Signature = new mdr.DFunctionSignature(ref callFrame, 3);
                        callFrame.Function.Call(ref callFrame);
                        if (Operations.Convert.ToBoolean.Run(ref callFrame.Return) == true)
                        {
                            result = true;
                            break;
                        }
                    }
                }
                callFrame.Return.Set(result);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.18
            TargetPrototype.DefineOwnProperty("forEach", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.forEach");
                mdr.DArray array = callFrame.This.ToDArray();
                int len          = array.Length;
                if (len == 0)
                {
                    callFrame.Return.Set(array);
                }

                mdr.DFunction function = callFrame.Arg0.AsDFunction();

                // TODO: Commented because thisArg is unused.

                /*mdr.DValue thisArg;
                 * if (callFrame.ArgsCount > 1)
                 *  thisArg = callFrame.Arg1;
                 * else
                 *  thisArg = new mdr.DValue();*/

                for (int i = 0; i < len; ++i)
                {
                    if (array.Elements[i].ValueType != mdr.ValueTypes.Undefined)
                    {
                        callFrame.Function        = function;
                        callFrame.PassedArgsCount = 3;
                        callFrame.SetArg(0, ref array.Elements[i]);
                        callFrame.SetArg(1, i);
                        callFrame.SetArg(2, array);
                        callFrame.Signature = new mdr.DFunctionSignature(ref callFrame, 3);
                        callFrame.Function.Call(ref callFrame);
                    }
                }
                callFrame.Return.Set(mdr.Runtime.Instance.DefaultDUndefined);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.19
            TargetPrototype.DefineOwnProperty("map", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.map");
                mdr.DArray array = callFrame.This.ToDArray();
                int len          = array.Length;
                if (len == 0)
                {
                    callFrame.Return.Set(array);
                }

                mdr.DFunction function = callFrame.Arg0.AsDFunction();
                mdr.DObject thisArg;
                if (callFrame.PassedArgsCount > 1)
                {
                    thisArg = Operations.Convert.ToObject.Run(ref callFrame.Arg1);
                }
                else
                {
                    thisArg = mdr.Runtime.Instance.GlobalContext;
                }

                mdr.DArray newarray = new mdr.DArray(len);

                for (int i = 0; i < len; ++i)
                {
                    if (array.Elements[i].ValueType != mdr.ValueTypes.Undefined)
                    {
                        callFrame.Function        = function;
                        callFrame.This            = thisArg;
                        callFrame.PassedArgsCount = 3;
                        callFrame.SetArg(0, ref array.Elements[i]);
                        callFrame.SetArg(1, i);
                        callFrame.SetArg(2, array);
                        callFrame.Signature = new mdr.DFunctionSignature(ref callFrame, 3);
                        callFrame.Function.Call(ref callFrame);
                        newarray.Elements[i] = callFrame.Return;
                    }
                }
                callFrame.Return.Set(newarray);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("filter", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Trace.Fail("Unimplemented");
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("reduce", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Trace.Fail("Unimplemented");
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("reduceRight", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Trace.Fail("Unimplemented");
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
        }
示例#28
0
 public static void Run(/*const*/ ref mdr.DValue i0, ref mdr.DValue result)
 {
     result.Set(ref i0);
 }
示例#29
0
 public override void Execute(ref mdr.DValue result, ref mdr.CallFrame callFrame, Interpreter interpreter)
 {
   interpreter.PushLocation(this);
   var tmp = new mdr.DValue();
   Left.Execute(ref result, ref callFrame, interpreter);
   Right.Execute(ref tmp, ref callFrame, interpreter);
   result.Set(Operations.Binary.BitwiseXor.Run(ref result, ref tmp));
   interpreter.PopLocation(this, ref result);
 }
示例#30
0
 public override void SetAsDValue(ref mdr.DValue dValue)
 {
     dValue.Set(Value);
 }
示例#31
0
 public static void Run(ulong i0, ref mdr.DValue result)
 {
     result.Set(i0);
 }
示例#32
0
 public static void Run(/*const*/ ref mdr.DValue i0, bool i1, ref mdr.DValue result)
 {
     throw new NotImplementedException();
 }
示例#33
0
 public static void Run(mdr.DObject i0, /*const*/ ref mdr.DValue i1, ref mdr.DValue result)
 {
     throw new NotImplementedException();
 }
示例#34
0
文件: JSArray.cs 项目: reshadi2/mcjs
        public JSArray()
            : base(mdr.Runtime.Instance.DArrayPrototype, "Array")
        {
            JittedCode = (ref mdr.CallFrame callFrame) =>
            {
                mdr.DArray array;

                var argsCount = callFrame.PassedArgsCount;

                if (argsCount == 1)
                {
                    var len = Operations.Convert.ToInt32.Run(ref callFrame.Arg0);
                    array = new mdr.DArray(len);
                }
                else
                {
                    array = new mdr.DArray(argsCount);
                    switch (argsCount)
                    {
                        case 0: break;
                        case 1: break;
                        case 2:
                            array.Elements[1] = callFrame.Arg1;
                            array.Elements[0] = callFrame.Arg0;
                            break;
                        case 3:
                            array.Elements[2] = callFrame.Arg2;
                            goto case 2;
                        case 4:
                            array.Elements[3] = callFrame.Arg3;
                            goto case 3;
                        default:
                            Debug.Assert(argsCount > mdr.CallFrame.InlineArgsCount, "Code gen must be updated to support new CallFrame");
                            Array.Copy(callFrame.Arguments, 0, array.Elements, mdr.CallFrame.InlineArgsCount, argsCount - mdr.CallFrame.InlineArgsCount);
                            goto case 4;
                    }
                }
                if (IsConstrutor)
                    callFrame.This = (array);
                else
                    callFrame.Return.Set(array);
            };

            // ECMA-262 section 15.4.3.1
            this.DefineOwnProperty("isArray", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.isArray");
                if (callFrame.This.ValueType == mdr.ValueTypes.Array)
                    callFrame.Return.Set(true);
                else
                    callFrame.Return.Set(false);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.2
            TargetPrototype.DefineOwnProperty("toString", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.toString");
                var join = callFrame.This.GetField("join");
                if (join.ValueType == mdr.ValueTypes.Function)// it is callable
                {
                    var joinFun = join.AsDFunction();
                    Debug.Assert(joinFun != null, "Invalid situation!");
                    callFrame.Function = joinFun;
                    //callFrame.This is already set
                    callFrame.Signature = mdr.DFunctionSignature.EmptySignature;
                    callFrame.PassedArgsCount = 0;
                    callFrame.Arguments = null;
                    joinFun.Call(ref callFrame);
                    callFrame.Return.Set(callFrame.Return.AsString());
                }
                else
                    callFrame.Return.Set(callFrame.This.ToString());
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.3
            TargetPrototype.DefineOwnProperty("toLocaleString", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                throw new NotImplementedException("Array.toLocaleString is not implemented");
                // TODO: callFrame.This is not an accurate implementation
                /*mdr.DObject array = callFrame.This;
                mdr.DFunction join = array.GetField("join").ToDObject() as mdr.DFunction;
                if (join != null) // it is callable
                {
                    callFrame.Function = join;
                    callFrame.Signature = mdr.DFunctionSignature.EmptySignature;
                    callFrame.Arguments = null;
                    join.Call(ref callFrame);
                    callFrame.Return.Set(callFrame.Return.ToString());    //TODO: is this the right implementation?
                }
                else
                    callFrame.Return.Set(array.ToString());*/
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.4
            TargetPrototype.DefineOwnProperty("concat", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.concat");
                //The most common case is calling .concat on array object with normal set of arguments
                mdr.DArray newArray;
                var destStartIndex = 0;

                var thisArray = callFrame.This as mdr.DArray;
                if(thisArray != null)
                {
                  newArray = new mdr.DArray(callFrame.PassedArgsCount + thisArray.Length);
                  Array.Copy(thisArray.Elements, 0, newArray.Elements, 0, thisArray.Length);
                  destStartIndex = thisArray.Length;
                }
                else 
                {
                  newArray = new mdr.DArray(callFrame.PassedArgsCount + 1);
                  newArray.Elements[0].Set(callFrame.This);
                  destStartIndex = 1;
                }
                for (int i = 0; i < callFrame.PassedArgsCount; ++i)
                {
                  newArray.Elements[destStartIndex] = callFrame.Arg(i); //This is the common case
                  if (newArray.Elements[destStartIndex].ValueType == mdr.ValueTypes.Array)
                  {
                    var array = newArray.Elements[destStartIndex].AsDArray();
                    //We had already accounted 1 cell for this item, so, we add the missing remaining elements
                    newArray.Length += (array.Length - 1); //Extends newArray.Elements
                    Array.Copy(array.Elements, 0, newArray.Elements, destStartIndex, array.Length);
                    destStartIndex += array.Length;
                  }
                  else
                    ++destStartIndex;
                }
                //concat(newArray, ref callFrame.Arguments[i]);

                callFrame.Return.Set(newArray);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.5
            TargetPrototype.DefineOwnProperty("join", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.join");
                string separator = (callFrame.PassedArgsCount == 0 || callFrame.Arg0.ValueType == mdr.ValueTypes.Undefined)
                    ? ","
                    : callFrame.Arg0.AsString();

                callFrame.Return.Set(join(callFrame.This, separator).ToString());
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.6
            TargetPrototype.DefineOwnProperty("pop", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.pop");
                var This = callFrame.This;
                var lenField = This.GetField("length");
                int len = Operations.Convert.ToInt32.Run(ref lenField);
                if (len == 0)
                {
                    This.SetField("length", 0);
                    callFrame.Return.Set(mdr.Runtime.Instance.DefaultDUndefined);
                }
                else if (len > 0)
                {
                    var index = len - 1;
                    mdr.DValue element = new mdr.DValue();
                    This.GetField(index, ref element);
                    This.DeletePropertyDescriptor(index.ToString());
                    This.SetField("length", index);
                    callFrame.Return.Set(ref element);
                }
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.7
            TargetPrototype.DefineOwnProperty("push", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.push");
                var This = callFrame.This;
                var lenField = This.GetField("length");
                int len = Operations.Convert.ToInt32.Run(ref lenField);
                mdr.DValue arg = new mdr.DValue();
                for (int i = 0; i < callFrame.PassedArgsCount; ++i)
                {
                    arg = callFrame.Arg(i);
                    This.SetField(len, ref arg);
                    len++;
                }
                This.SetField("length", len);
                callFrame.Return.Set(len);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.8
            TargetPrototype.DefineOwnProperty("reverse", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.reverse");
                var This = callFrame.This;
                var lenField = This.GetField("length");
                int len = Operations.Convert.ToInt32.Run(ref lenField);
                int middle = len / 2;
                mdr.DValue lowerValue = new mdr.DValue();
                mdr.DValue upperValue = new mdr.DValue();
                bool lowerExists, upperExists;
                for (int lower = 0; lower != middle; lower++)
                {
                    int upper = len - lower - 1;
                    lowerExists = This.HasProperty(lower);
                    upperExists = This.HasProperty(upper);
                    if (lowerExists && upperExists)
                    {
                        This.GetField(lower, ref lowerValue);
                        This.GetField(upper, ref upperValue);
                        This.SetField(lower, ref upperValue);
                        This.SetField(upper, ref lowerValue);
                    }
                    else if (!lowerExists && upperExists)
                    {
                        This.GetField(upper, ref upperValue);
                        This.SetField(lower, ref upperValue);
                        This.DeletePropertyDescriptor(upper.ToString());
                    }
                    else if (lowerExists && !upperExists)
                    {
                        This.GetField(lower, ref lowerValue);
                        This.SetField(upper, ref lowerValue);
                        This.DeletePropertyDescriptor(lower.ToString());
                    }
                }
                callFrame.Return.Set(This);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.9
            TargetPrototype.DefineOwnProperty("shift", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.shift");
                mdr.DArray array = callFrame.This.ToDArray();
                int len = array.Length;
                if (array == null || array.Length == 0)
                    //callFrame.Return.ValueType = mdr.ValueTypes.Undefined;
                    callFrame.Return.Set(mdr.Runtime.Instance.DefaultDUndefined);
                else
                {
                    callFrame.Return.Set(ref array.Elements[0]);
                    for (int k = 1; k < len; k++)
                        array.Elements[k - 1].Set(ref array.Elements[k]);

                    array.Length--;
                }
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.10
            TargetPrototype.DefineOwnProperty("slice", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.slice");
                /*  TODO: This is the implementation for a case that "this" is a DArray. Use this faster implementation after adding PackedArray optimization.
                mdr.DArray array = callFrame.This.ToDArray();
                int len = array.Length;
                int relativeStart = callFrame.Arg0.ToInt32();
                int k = (relativeStart < 0) ? Math.Max(len + relativeStart, 0) : Math.Min(relativeStart, len);
                int relativeEnd = (callFrame.Arg1.ValueType == mdr.ValueTypes.Undefined) ? len : callFrame.Arg1.ToInt32();
                int final = (relativeEnd < 0) ? Math.Max(relativeEnd + len, 0) : Math.Min(relativeEnd, len);
                mdr.DArray newArray = new mdr.DArray((final - k > 0) ? (final - k) : 0);
                for (int n = 0; k < final; k++, n++)
                    newArray.Elements[n].Set(ref array.Elements[k]);
                callFrame.Return.Set(newArray);
                 */

                var This = callFrame.This;
                var lenField = This.GetField("length");
                int len = Operations.Convert.ToInt32.Run(ref lenField);
                int relativeStart = 0;
                if (callFrame.PassedArgsCount > 0 ) 
                  relativeStart = Operations.Convert.ToInt32.Run(ref callFrame.Arg0);
                int k = (relativeStart < 0) ? Math.Max(len + relativeStart, 0) : Math.Min(relativeStart, len);
                int relativeEnd = ((callFrame.Arg1.ValueType == mdr.ValueTypes.Undefined) || (callFrame.PassedArgsCount < 2)) ? len : Operations.Convert.ToInt32.Run(ref callFrame.Arg1 );
                int final = (relativeEnd < 0) ? Math.Max(relativeEnd + len, 0) : Math.Min(relativeEnd, len);
                mdr.DArray newArray = new mdr.DArray((final - k > 0) ? (final - k) : 0);
                mdr.DValue item = new mdr.DValue();
                for (int n = 0; k < final; k++, n++)
                {
                    This.GetField(k, ref item);
                    newArray.Elements[n].Set(ref item);
                }
                callFrame.Return.Set(newArray);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.12
            //TODO: splice is generic and can be applied to other objects
            TargetPrototype.DefineOwnProperty("splice", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.splice");
                if (callFrame.PassedArgsCount < 2)
                {
                    callFrame.Return.Set(JSRuntime.Instance.DefaultDUndefined);
                    return;
                }
                var A = new mdr.DArray();
                var This = callFrame.This as mdr.DArray;
                if (This == null)
                    throw new Exception("Object is not an array, but splice must work with generic objects. Please fix it!");
                int len = This.Length;
                int relativeStart = Operations.Convert.ToInt32.Run(ref callFrame.Arg0);
                int actualStart = relativeStart < 0 ? Math.Max(len + relativeStart, 0) : Math.Min(relativeStart, len);
                int actualDeleteCount = Math.Min(Math.Max(Operations.Convert.ToInt32.Run(ref callFrame.Arg1), 0), len - actualStart);

                A.Length = actualDeleteCount;
                for (int k = 0; k < actualDeleteCount; k++)
                {
                    int from = relativeStart + k;
                    if (from < len)
                        A.Elements[k].Set(ref This.Elements[from]);
                }

                int itemCount = callFrame.PassedArgsCount - 2;
                if (itemCount < actualDeleteCount)
                {
                    for (int k = actualStart; k < len - actualDeleteCount; k++)
                    {
                        int from = k + actualDeleteCount;
                        int to = k + itemCount;
                        // if (from < len) // This condition will always hold
                        This.Elements[to].Set(ref This.Elements[from]);
                        // from will always be less than less and therefore the element exists in the array 
                        //TODO: can we assume any index less than Length exist? When an element is deleted from middle of the Elements, is Length adjusted?
                        /*
                        else
                        {
                            This.RemoveElements(to, len - actualDeleteCount - k);
                            break;
                        }*/
                    }
                    This.RemoveElements(len - actualDeleteCount + itemCount, actualDeleteCount - itemCount);
                    This.Length = len - actualDeleteCount + itemCount;
                }
                else if (itemCount > actualDeleteCount)
                {
                    This.Length = len - actualDeleteCount + itemCount;
                    for (int k = len - actualDeleteCount; k > actualStart; k--)
                    {
                        int from = k + actualDeleteCount - 1;
                        int to = k + itemCount - 1;
                        //if (from < len) //This condition will always hold
                        This.Elements[to].Set(ref This.Elements[from]);
                    }
                }

                for (int k = 0; k < itemCount; k++)
                    This.Elements[k + actualStart] = callFrame.Arg(k + 2);

                
                callFrame.Return.Set(A);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.11
            TargetPrototype.DefineOwnProperty("sort", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.sort");
                mdr.DArray array = callFrame.This.ToDArray();
                int len = array.Length;
                if (len == 0)
                    callFrame.Return.Set(array);

                int argsCount = callFrame.PassedArgsCount;
                mdr.DValue function = callFrame.Arg0;

                for (uint i = 0; i < len - 1; ++i)
                {
                    mdr.DValue iObj = array.Elements[i];
                    uint themin = i;
                    mdr.DValue minObj = iObj;
                    for (uint j = i + 1; j < len; ++j)
                    {
                        mdr.DValue jObj = array.Elements[j];
                        double compareResult = 0;
                        if (jObj.ValueType == mdr.ValueTypes.Undefined)
                            compareResult = 1;
                        else if (minObj.ValueType == mdr.ValueTypes.Undefined)
                            compareResult = -1;
                        else if (argsCount == 1 && function.ValueType == mdr.ValueTypes.Function)
                        {
                            callFrame.Function = function.AsDFunction();
                            callFrame.SetArg(0, ref minObj);
                            callFrame.SetArg(1, ref jObj);
                            callFrame.PassedArgsCount = 2;
                            callFrame.Signature = new mdr.DFunctionSignature(ref callFrame, 2);
                            callFrame.Function.Call(ref callFrame);
                            compareResult = Operations.Convert.ToInt32.Run(ref callFrame.Return) <= 0 ? 1 : -1;
                        }
                        else
                        {
                            mdr.DValue v1 = mdr.DValue.Create(jObj.AsString());
                            mdr.DValue v2 = mdr.DValue.Create(minObj.AsString());
                            compareResult = Operations.Binary.LessThan.Run(ref v1, ref v2) ? -1 : 1;
                        }

                        if (compareResult < 0)
                        {
                            themin = j;
                            minObj = jObj;
                        }
                    }
                    if (themin > i)
                    {
                        array.Elements[i] = minObj;
                        array.Elements[themin] = iObj;
                    }
                }
                callFrame.Return.Set(array);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.13
            TargetPrototype.DefineOwnProperty("unshift", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.unshift");
                var thisObj = callFrame.This;
                mdr.DArray array = thisObj.ToDArray();

                int len = array.Length;
                int argsCount = callFrame.PassedArgsCount;
                array.ResizeElements(len + argsCount);
                array.Length = len + argsCount;
                if (argsCount != 0 && len != 0)
                {
                    mdr.DValue iObj;
                    for (int i = len; i > 0; --i)
                    {
                        iObj = array.Elements[i - 1];
                        array.Elements[i - 1].Set(0);
                        array.Elements[i + argsCount - 1] = iObj;

                    }
                }
                for (int k = 0; k < argsCount; ++k)
                {
                    array.Elements[k] = callFrame.Arg(k);
                }
                callFrame.Return.Set(array.Length);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.14
            TargetPrototype.DefineOwnProperty("indexOf", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.indexOf");
                mdr.DArray array = callFrame.This.ToDArray();
                int len = array.Length;
                int index = 0;
                if (callFrame.PassedArgsCount > 1)
                    index = Operations.Convert.ToInt32.Run(ref callFrame.Arg1);
                index = index < 0 ? Math.Max(len + index, 0) : Math.Min(index, len);
                mdr.DValue searchElem = callFrame.Arg0;
                for (; index < len; ++index)
                {
                    mdr.DValue indexElem = array.Elements[index];
                    if (indexElem.ValueType != mdr.ValueTypes.Undefined
                        && Operations.Binary.Equal.Run(ref indexElem, ref searchElem))
                    {
                        callFrame.Return.Set(index);
                        return;
                    }
                }
                callFrame.Return.Set(-1);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.15
            TargetPrototype.DefineOwnProperty("lastIndexOf", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.lastIndexOf");
                mdr.DArray array = callFrame.This.ToDArray();
                int len = array.Length;
                if (len == 0)
                {
                    callFrame.Return.Set(-1);
                    return;
                }
                int index = len - 1;
                if (callFrame.PassedArgsCount > 1)
                    index = Operations.Convert.ToInt32.Run(ref callFrame.Arg1);
                index = index < 0 ? len + index : Math.Min(index, len - 1);
                if (index < 0)
                {
                    callFrame.Return.Set(-1);
                    return;
                }
                mdr.DValue searchElem = callFrame.Arg0;
                do
                {
                    mdr.DValue indexElem = array.Elements[index];
                    if (indexElem.ValueType != mdr.ValueTypes.Undefined
                        && Operations.Binary.Equal.Run(ref indexElem, ref searchElem))
                    {
                        callFrame.Return.Set(index);
                        return;
                    }
                } while (index-- > 0);
                callFrame.Return.Set(-1);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.16
            TargetPrototype.DefineOwnProperty("every", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.every");
                var thisObj = callFrame.This;
                mdr.DArray array = thisObj.ToDArray();
                int len = array.Length;
                if (len == 0)
                    callFrame.Return.Set(array);

                // TODO: Commented because argsCount is unused.
                /*int argsCount = callFrame.ArgsCount;*/
                mdr.DFunction function = callFrame.Arg0.AsDFunction();
                bool result = true;

                for (int i = 0; i < len; ++i)
                {
                    if (array.Elements[i].ValueType != mdr.ValueTypes.Undefined)
                    {
                        callFrame.Function = function;
                        callFrame.SetArg(0, ref array.Elements[i]);
                        callFrame.SetArg(1, i);
                        callFrame.SetArg(2, thisObj);
                        callFrame.Signature = new mdr.DFunctionSignature(ref callFrame, 3);
                        callFrame.Function.Call(ref callFrame);
                        if (Operations.Convert.ToBoolean.Run(ref callFrame.Return) == false)
                        {
                            result = false;
                            break;
                        }
                    }
                }
                callFrame.Return.Set(result);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.17
            TargetPrototype.DefineOwnProperty("some", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.some");
                var thisObj = callFrame.This;
                mdr.DArray array = thisObj.ToDArray();
                int len = array.Length;
                if (len == 0)
                    callFrame.Return.Set(array);

                // TODO: Commented because argsCount is unused.
                /*int argsCount = callFrame.ArgsCount;*/
                mdr.DFunction function = callFrame.Arg0.AsDFunction();
                bool result = false;

                for (int i = 0; i < len; ++i)
                {
                    if (array.Elements[i].ValueType != mdr.ValueTypes.Undefined)
                    {
                        callFrame.Function = function;
                        callFrame.SetArg(0, ref array.Elements[i]);
                        callFrame.SetArg(1, i);
                        callFrame.SetArg(2, thisObj);
                        callFrame.Signature = new mdr.DFunctionSignature(ref callFrame, 3);
                        callFrame.Function.Call(ref callFrame);
                        if (Operations.Convert.ToBoolean.Run(ref callFrame.Return) == true)
                        {
                            result = true;
                            break;
                        }
                    }
                }
                callFrame.Return.Set(result);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.18
            TargetPrototype.DefineOwnProperty("forEach", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.forEach");
                mdr.DArray array = callFrame.This.ToDArray();
                int len = array.Length;
                if (len == 0)
                    callFrame.Return.Set(array);

                mdr.DFunction function = callFrame.Arg0.AsDFunction();
 
                // TODO: Commented because thisArg is unused.
                /*mdr.DValue thisArg;
                if (callFrame.ArgsCount > 1)
                    thisArg = callFrame.Arg1;
                else
                    thisArg = new mdr.DValue();*/

                for (int i = 0; i < len; ++i)
                {
                    if (array.Elements[i].ValueType != mdr.ValueTypes.Undefined)
                    {
                        callFrame.Function = function;
                        callFrame.PassedArgsCount = 3;
                        callFrame.SetArg(0, ref array.Elements[i]);
                        callFrame.SetArg(1, i);
                        callFrame.SetArg(2, array);
                        callFrame.Signature = new mdr.DFunctionSignature(ref callFrame, 3);
                        callFrame.Function.Call(ref callFrame);
                    }
                }
                callFrame.Return.Set(mdr.Runtime.Instance.DefaultDUndefined);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.4.4.19
            TargetPrototype.DefineOwnProperty("map", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("Calling JSArray.map");
                mdr.DArray array = callFrame.This.ToDArray();
                int len = array.Length;
                if (len == 0)
                    callFrame.Return.Set(array);

                mdr.DFunction function = callFrame.Arg0.AsDFunction();
                mdr.DObject thisArg;
                if (callFrame.PassedArgsCount > 1)
                    thisArg = Operations.Convert.ToObject.Run(ref callFrame.Arg1);
                else
                    thisArg = mdr.Runtime.Instance.GlobalContext;

                mdr.DArray newarray = new mdr.DArray(len);

                for (int i = 0; i < len; ++i)
                {
                    if (array.Elements[i].ValueType != mdr.ValueTypes.Undefined)
                    {
                        callFrame.Function = function;
                        callFrame.This = thisArg;
                        callFrame.PassedArgsCount = 3;
                        callFrame.SetArg(0, ref array.Elements[i]);
                        callFrame.SetArg(1, i);
                        callFrame.SetArg(2, array);
                        callFrame.Signature = new mdr.DFunctionSignature(ref callFrame, 3);
                        callFrame.Function.Call(ref callFrame);
                        newarray.Elements[i] = callFrame.Return;
                    }
                }
                callFrame.Return.Set(newarray);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("filter", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Trace.Fail("Unimplemented");
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("reduce", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Trace.Fail("Unimplemented");
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("reduceRight", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Trace.Fail("Unimplemented");
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

        }
示例#35
0
        public JSNumber()
            : base(mdr.Runtime.Instance.DNumberPrototype, "Number")
        {
            JittedCode = (ref mdr.CallFrame callFrame) =>
            {
                mdr.DValue number = new mdr.DValue();
                if (callFrame.PassedArgsCount > 0)
                {
                    Operations.Convert.ToNumber.Run(ref callFrame.Arg0, ref number);
                    //double arg = callFrame.Arg0.ToDouble();
                    ////if (Math.Floor(arg) == arg) //this is an int (FIXME: What if it is passed as 23.0? Should we still treat it as int?)
                    ////    number.Set((int)arg);
                    ////else
                    //number.Set(arg);
                }
                else
                {
                    number.Set(0);
                }

                if (IsConstrutor)
                {
                    mdr.DObject objNumber = new mdr.DObject(TargetPrototype);
                    objNumber.PrimitiveValue = number;
                    //objNumber.Class = "Number";
                    callFrame.This = (objNumber);
                }
                else
                {
                    callFrame.Return.Set(ref number);
                }
            };

            this.DefineOwnProperty("MAX_VALUE", 1.7976931348623157E308, mdr.PropertyDescriptor.Attributes.NotConfigurable | mdr.PropertyDescriptor.Attributes.NotWritable | mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("MIN_VALUE", 5E-324, mdr.PropertyDescriptor.Attributes.NotConfigurable | mdr.PropertyDescriptor.Attributes.NotWritable | mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("NaN", double.NaN, mdr.PropertyDescriptor.Attributes.NotConfigurable | mdr.PropertyDescriptor.Attributes.NotWritable | mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("NEGATIVE_INFINITY", double.NegativeInfinity, mdr.PropertyDescriptor.Attributes.NotConfigurable | mdr.PropertyDescriptor.Attributes.NotWritable | mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("POSITIVE_INFINITY", double.PositiveInfinity, mdr.PropertyDescriptor.Attributes.NotConfigurable | mdr.PropertyDescriptor.Attributes.NotWritable | mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("toString", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                int radix = 10;
                if (callFrame.PassedArgsCount > 0)
                {
                    radix = callFrame.Arg0.AsInt32();
                }
                var number = Operations.Convert.ToDouble.Run(callFrame.This);
                callFrame.Return.Set(ToStringImpl(number, radix));
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("toLocaleString", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                double number = callFrame.This.ToDouble();
                callFrame.Return.Set(ToStringImpl(number, 10));
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("valueOf", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                if (callFrame.This.ValueType == mdr.ValueTypes.Int32)
                {
                    callFrame.Return.Set(callFrame.This.ToInt32());
                }
                else
                {
                    callFrame.Return.Set(callFrame.This.ToDouble());
                }
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("toFixed", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                int numFractionDigits = 0;
                if (callFrame.PassedArgsCount > 0)
                {
                    numFractionDigits = callFrame.Arg0.AsInt32();
                    if (numFractionDigits < 0 || numFractionDigits > 20)
                    {
                        throw new ArgumentOutOfRangeException();
                    }
                }
                double number = callFrame.This.ToDouble();
                if (double.IsNaN(number))
                {
                    callFrame.Return.Set("NaN");
                }
                else
                {
                    callFrame.Return.Set(number.ToString("f" + numFractionDigits, CultureInfo.InvariantCulture));
                }
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("toExponential", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                int numFractionDigits = 0;
                if (callFrame.PassedArgsCount > 0)
                {
                    numFractionDigits = callFrame.Arg0.AsInt32();
                    if (numFractionDigits < 0 || numFractionDigits > 20)
                    {
                        throw new ArgumentOutOfRangeException();
                    }
                }
                double number = callFrame.This.ToDouble();
                if (double.IsNaN(number))
                {
                    callFrame.Return.Set("NaN");
                }
                else
                {
                    string format = String.Concat("#.", new String('0', numFractionDigits), "e+0");
                    callFrame.Return.Set(number.ToString(format, CultureInfo.InvariantCulture));
                }
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("toPrecision", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                if (callFrame.PassedArgsCount == 0)
                {
                    callFrame.Return.Set(callFrame.This.ToDouble().ToString());
                }
                else
                {
                    double number = callFrame.This.ToDouble();
                    if (double.IsNaN(number))
                    {
                        callFrame.Return.Set("NaN");
                    }
                    else if (double.IsPositiveInfinity(number))
                    {
                        callFrame.Return.Set("Infinity");
                    }
                    else if (double.IsNegativeInfinity(number))
                    {
                        callFrame.Return.Set("-Infinity");
                    }
                    else
                    {
                        int precision = 0;
                        precision     = callFrame.Arg0.AsInt32();
                        if (precision < 1 || precision > 21)
                        {
                            throw new ArgumentOutOfRangeException();
                        }

                        //TODO: make sure the following is correct implementation!
                        // Get the number of decimals
                        string str   = number.ToString("e23", CultureInfo.InvariantCulture);
                        int decimals = str.IndexOfAny(new char[] { '.', 'e' });
                        decimals     = decimals == -1 ? str.Length : decimals;
                        precision   -= decimals;
                        precision    = precision < 1 ? 1 : precision;
                        callFrame.Return.Set(number.ToString("f" + precision, CultureInfo.InvariantCulture));
                    }
                }
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
        }