Example #1
0
        public JSObject()
            : base(mdr.Runtime.Instance.DObjectPrototype, "Object")
        {
            JittedCode = ctor;

            this.DefineOwnProperty("getPrototypeOf", new DFunction(getPrototypeOf), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("getOwnPropertyDescriptor", new DFunction(getOwnPropertyDescriptor), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("getOwnPropertyNames", new DFunction(getOwnPropertyNames), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("create", new DFunction(create), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("defineProperty", new DFunction(defineProperty), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("defineProperties", new DFunction(defineProperties), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("seal", new DFunction(seal), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("freeze", new DFunction(freeze), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("preventExtensions", new DFunction(preventExtensions), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("isSealed", new DFunction(isSealed), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("isFrozen", new DFunction(isFrozen), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("isExtensible", new DFunction(isExtensible), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            this.DefineOwnProperty("keys", new DFunction(keys), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("toString", new DFunction(toString), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("toLocaleString", new DFunction(toLocaleString), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("valueOf", new DFunction(valueOf), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("hasOwnProperty", new DFunction(hasOwnProperty), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("isPrototypeOf", new DFunction(isPrototypeOf), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("propertyIsEnumerable", new DFunction(propertyIsEnumerable), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
        }
Example #2
0
        public JSArrayBuffer()
            : base(new mdr.DObject(), "ArrayBuffer")
        {
            JittedCode = (ref mdr.CallFrame callFrame) =>
            {
                DArrayBuffer buffer;
                var          len       = 0;
                var          argsCount = callFrame.PassedArgsCount;
                if (argsCount > 0)
                {
                    len = Math.Max(0, callFrame.Arg0.AsInt32());
                }

                buffer = new DArrayBuffer(TargetPrototype, len);
                if (IsConstrutor)
                {
                    callFrame.This = (buffer);
                }
                else
                {
                    callFrame.Return.Set(buffer);
                }
            };

            TargetPrototype.DefineOwnProperty("byteLength", new mdr.DProperty()
            {
                OnGetDValue = (mdr.DObject This, ref mdr.DValue v) =>
                {
                    v.Set((This as DArrayBuffer).ByteLength);
                },
                OnSetDValue = (mdr.DObject This, ref mdr.DValue v) => { /* do nothing */ },
                OnSetInt    = (mdr.DObject This, int v) => { /* do nothing */ },
            });
        }
Example #3
0
        public JSTypedArrayBase(mdr.DObject prototype, string arrayname, int typesize)
            : base(prototype, arrayname)
        {
            TypeSize = typesize;

            TargetPrototype.DefineOwnProperty("length", new mdr.DProperty()
            {
                TargetValueType = mdr.ValueTypes.Int32,
                OnGetDValue     = (mdr.DObject This, ref mdr.DValue v) => {
                    v.Set((This as DTypedArray).ByteLength / TypeSize);
                },
                OnSetDValue = (mdr.DObject This, ref mdr.DValue v) => { /* do nothing */ },
                OnSetInt    = (mdr.DObject This, int v) => { /* do nothing */ },
            });

            TargetPrototype.DefineOwnProperty("byteLength", new mdr.DProperty()
            {
                TargetValueType = mdr.ValueTypes.Int32,
                OnGetDValue     = (mdr.DObject This, ref mdr.DValue v) => {
                    v.Set((This as DTypedArray).ByteLength);
                },
                OnSetDValue = (mdr.DObject This, ref mdr.DValue v) => { /* do nothing */ },
                OnSetInt    = (mdr.DObject This, int v) => { /* do nothing */ },
            });

            // Constants
            this.DefineOwnProperty("BYTES_PER_ELEMENT", TypeSize, mdr.PropertyDescriptor.Attributes.NotConfigurable | mdr.PropertyDescriptor.Attributes.NotWritable | mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("BYTES_PER_ELEMENT", TypeSize, mdr.PropertyDescriptor.Attributes.NotConfigurable | mdr.PropertyDescriptor.Attributes.NotWritable | mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
        }
Example #4
0
        /// <summary>
        /// JSRegExp constructor
        /// </summary>
        public JSRegExp()
            : base(mdr.Runtime.Instance.DRegExpPrototype, "RegExp")
        {
            JittedCode = ctor;

            TargetPrototype.DefineOwnProperty("exec", new mdr.DFunction(exec)
                                              , mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("test", new mdr.DFunction(test)
                                              , mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("toString", new mdr.DFunction(toString)
                                              , mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("global", new mdr.DProperty()
            {
                TargetValueType = mdr.ValueTypes.Boolean,
                //read only
                OnGetDValue = (mdr.DObject This, ref mdr.DValue v) =>
                {
                    var attval = This.FirstInPrototypeChainAs <DRegExp>().Global;
                    v.Set(attval);
                },
            }, mdr.PropertyDescriptor.Attributes.NotWritable | PropertyDescriptor.Attributes.NotEnumerable | PropertyDescriptor.Attributes.NotConfigurable);

            TargetPrototype.DefineOwnProperty("ignoreCase", new mdr.DProperty()
            {
                TargetValueType = mdr.ValueTypes.Boolean,
                //read only
                OnGetDValue = (mdr.DObject This, ref mdr.DValue v) =>
                {
                    var attval = This.FirstInPrototypeChainAs <DRegExp>().IgnoreCase;
                    v.Set(attval);
                },
            }, mdr.PropertyDescriptor.Attributes.NotWritable | PropertyDescriptor.Attributes.NotEnumerable | PropertyDescriptor.Attributes.NotConfigurable);

            TargetPrototype.DefineOwnProperty("multiline", new mdr.DProperty()
            {
                TargetValueType = mdr.ValueTypes.Boolean,
                //read only
                OnGetDValue = (mdr.DObject This, ref mdr.DValue v) =>
                {
                    var attval = This.FirstInPrototypeChainAs <DRegExp>().Multiline;
                    v.Set(attval);
                },
            }, mdr.PropertyDescriptor.Attributes.NotWritable | PropertyDescriptor.Attributes.NotEnumerable | PropertyDescriptor.Attributes.NotConfigurable);

            // ECMA 262 15.10.7.1
            TargetPrototype.DefineOwnProperty("source", new mdr.DProperty()
            {
                TargetValueType = mdr.ValueTypes.String,
                //read only
                OnGetDValue = (mdr.DObject This, ref mdr.DValue v) =>
                {
                    var attval = This.FirstInPrototypeChainAs <DRegExp>().Source;
                    v.Set(attval);
                },
            }, mdr.PropertyDescriptor.Attributes.NotWritable | PropertyDescriptor.Attributes.NotEnumerable | PropertyDescriptor.Attributes.NotConfigurable);
        }
Example #5
0
        public JSBoolean()
            : base(mdr.Runtime.Instance.DBooleanPrototype, "Boolean")
        {
            JittedCode = ctor;

            TargetPrototype.DefineOwnProperty("toString", new mdr.DFunction(toString)
                                              , mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("valueOf", new mdr.DFunction(valueOf)
                                              , mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
        }
Example #6
0
        public JSString()
            : base(mdr.Runtime.Instance.DStringPrototype, "String")
        {
            JittedCode = ctor;

            // ECMA-262 section 15.5.5.1
            // "length" is already added to the DStringPrototype in Runtime.cs

            // ECMA-262 section 15.5.3.2
            this.DefineOwnProperty("fromCharCode", new mdr.DFunction(fromCharCode), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            // ECMA-262 section 15.5.4.2
            TargetPrototype.DefineOwnProperty("toString", new mdr.DFunction(toString), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.3
            TargetPrototype.DefineOwnProperty("valueOf", new mdr.DFunction(valueOf), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262, section 15.5.4.4
            TargetPrototype.DefineOwnProperty("charAt", new mdr.DFunction(charAt), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.5
            TargetPrototype.DefineOwnProperty("charCodeAt", new mdr.DFunction(charCodeAt), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262, section 15.5.4.6
            TargetPrototype.DefineOwnProperty("concat", new mdr.DFunction(concat), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.7
            TargetPrototype.DefineOwnProperty("indexOf", new mdr.DFunction(indexOf), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.8
            TargetPrototype.DefineOwnProperty("lastIndexOf", new mdr.DFunction(lastIndexOf), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.9
            TargetPrototype.DefineOwnProperty("localeCompare", new mdr.DFunction(localeCompare), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.10
            TargetPrototype.DefineOwnProperty("match", new mdr.DFunction(match), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262, section 15.5.4.11
            TargetPrototype.DefineOwnProperty("replace", new mdr.DFunction(replace), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.12
            TargetPrototype.DefineOwnProperty("search", new mdr.DFunction(search), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.13
            TargetPrototype.DefineOwnProperty("slice", new mdr.DFunction(slice), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.14
            TargetPrototype.DefineOwnProperty("split", new mdr.DFunction(split), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.15
            TargetPrototype.DefineOwnProperty("substring", new mdr.DFunction(substring), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("substr", new mdr.DFunction(substr), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.16
            TargetPrototype.DefineOwnProperty("toLowerCase", new mdr.DFunction(toLowerCase), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.17
            TargetPrototype.DefineOwnProperty("toLocaleLowerCase", new mdr.DFunction(toLocaleLowerCase), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.18
            TargetPrototype.DefineOwnProperty("toUpperCase", new mdr.DFunction(toUpperCase), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.19
            TargetPrototype.DefineOwnProperty("toLocaleUpperCase", new mdr.DFunction(toLocaleUpperCase), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            // ECMA-262 section 15.5.4.20
            TargetPrototype.DefineOwnProperty("trim", new mdr.DFunction(trim), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
        }
Example #7
0
        public JSError() : base(new mdr.DObject(), "Error")
        {
            JittedCode = (ref mdr.CallFrame callFrame) =>
            {
                var error = new mdr.DObject(TargetPrototype);
                switch (callFrame.PassedArgsCount)
                {
                case 0:
                    break;

                case 1:
                    error.SetField("message", callFrame.Arg0.AsString());
                    goto case 0;

                case 2:
                    error.SetField("fileName", callFrame.Arg1.AsString());
                    goto case 1;

                case 3:
                    error.SetField("lineNumber", callFrame.Arg2.AsString());
                    goto case 2;
                }
                if (IsConstrutor)
                {
                    callFrame.This = (error);
                }
                else
                {
                    callFrame.Return.Set(error);
                }
            };

            TargetPrototype.DefineOwnProperty("message", "", mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("name", "Error", mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("toString", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                var name    = callFrame.This.GetField("name").AsString();
                var message = callFrame.This.GetField("message").AsString();
                callFrame.Return.Set(string.Format("{0}: {1}", name, message));
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
        }
Example #8
0
        public JSInt8Array()
            : base(new mdr.DObject(), "Int8Array", TypeSize)
        {
            JittedCode = (ref mdr.CallFrame callFrame) =>
            {
                DInt8Array int32array = new DInt8Array(TargetPrototype, 0, TypeSize);
                var        argsCount  = callFrame.PassedArgsCount;

                if (argsCount == 1)
                {
                    switch (callFrame.Arg0.ValueType)
                    {
                    case mdr.ValueTypes.Int32:
                        int32array = new DInt8Array(TargetPrototype, callFrame.Arg0.AsInt32() * TypeSize, TypeSize);
                        break;

                    case mdr.ValueTypes.Object:
                        int32array = createArrayFromObject(callFrame.Arg0.AsDObject());
                        break;

                    case mdr.ValueTypes.Array:
                        mdr.DArray array = callFrame.Arg0.AsDArray();
                        int32array = new DInt8Array(TargetPrototype, array.Length * TypeSize, TypeSize);
                        fillArray(int32array, array);
                        break;

                    default:
                        Trace.Fail("invalid Arguments");
                        break;
                    }
                }
                if (argsCount == 2)
                {
                    int byteoffset = callFrame.Arg1.AsInt32();
                    int32array = createArrayFromObject(callFrame.Arg0.AsDObject(), byteoffset);
                }
                if (argsCount == 3)
                {
                    var byteoffset = callFrame.Arg1.AsInt32();
                    var length     = callFrame.Arg2.AsInt32();
                    checkOffsetMemBoundary(byteoffset);
                    int32array = createArrayFromObject(callFrame.Arg0.AsDObject(), byteoffset, length * TypeSize);
                }

                if (IsConstrutor)
                {
                    callFrame.This = (int32array);
                }
                else
                {
                    callFrame.Return.Set(int32array);
                }
            };

            TargetPrototype.DefineOwnProperty("subarray", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                DInt8Array array = (callFrame.This as DInt8Array);
                var argsCount    = callFrame.PassedArgsCount;
                var begin        = (argsCount >= 1) ? callFrame.Arg0.AsInt32() : 0;
                var end          = array.ByteLength / array.TypeSize;
                end            = (argsCount >= 2) ? callFrame.Arg1.AsInt32() : end;
                begin          = begin < 0 ? begin += array.ByteLength / array.TypeSize : begin;
                end            = end < 0 ? end += array.ByteLength / array.TypeSize : end;
                var bytelength = Math.Max(0, (end - begin)) * array.TypeSize;
                end            = Math.Max(array.ByteLength, bytelength);
                var int32array = new DInt8Array(TargetPrototype, bytelength, array.TypeSize);
                int offset     = (begin <= 0) ? 0 : begin * array.TypeSize;
                for (int i = 0; i < int32array.ByteLength; ++i)
                {
                    int32array.Elements_[i] = array.Elements_[i + offset];
                }
                callFrame.Return.Set(int32array);
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
        }
Example #9
0
        public JSFunction()
            : base(mdr.Runtime.Instance.DFunctionPrototype, "Function")
        {
            JittedCode = (ref mdr.CallFrame callFrame) =>
            {
                //ECMA 15.3.2.1
                Debug.WriteLine("calling new Function");
                StringBuilder properFunctionDeclaration = new StringBuilder("return function ");
                int           argsCount = 0;
                string        body;
                if (callFrame.PassedArgsCount == 0)
                {
                    argsCount = 0;
                    body      = "";
                }
                else
                if (callFrame.PassedArgsCount == 1)
                {
                    argsCount = 0;
                    body      = callFrame.Arg(0).AsString();
                }
                else
                {
                    argsCount = callFrame.PassedArgsCount - 1;
                    body      = callFrame.Arg(callFrame.PassedArgsCount - 1).AsString();
                }

                properFunctionDeclaration.Append("(");
                for (int i = 0; i < argsCount; i++)
                {
                    properFunctionDeclaration.Append(callFrame.Arg(i).AsString());
                    if (i < argsCount - 1)
                    {
                        properFunctionDeclaration.Append(",");
                    }
                }
                properFunctionDeclaration.Append(")");

                properFunctionDeclaration.Append("{").Append(body).Append("}");
                string properFunctionDecString = properFunctionDeclaration.ToString();
                Debug.WriteLine("new Function: {0}", properFunctionDecString);
                JSGlobalObject.EvalString(properFunctionDecString, ref callFrame.Return);
                if (IsConstrutor)
                {
                    callFrame.This = callFrame.Return.AsDFunction();
                }
            };

            // toString is implementd in DObject
            //TargetPrototype.DefineOwnProperty("toString", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            //{
            //    Debug.WriteLine("calling JSFunction.toString");
            //    var function = callFrame.This as mdr.DFunction;
            //    if (function == null)
            //        Trace.Fail("TypeError");
            //    var funcStream = new System.IO.StringWriter();
            //    funcStream.WriteLine("{0} {{", Declaration(function));
            //    var astWriter = new mjr.Expressions.AstWriter(funcStream);
            //    astWriter.Execute((JSFunctionMetadata)function.Metadata);
            //    funcStream.WriteLine("}");
            //    callFrame.Return.Set(funcStream.ToString());
            //    //callFrame.Return.Set(function.ToString());
            //}), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);
            TargetPrototype.DefineOwnProperty("apply", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("calling JSFunction.apply");
                var tmpCallFrame      = new mdr.CallFrame();
                tmpCallFrame.Function = callFrame.This.ToDFunction();
                if (tmpCallFrame.Function == null)
                {
                    throw new InvalidOperationException(".apply should be called on a Function object");
                }
                if (mdr.ValueTypesHelper.IsDefined(callFrame.Arg0.ValueType))
                {
                    tmpCallFrame.This = Operations.Convert.ToObject.Run(ref callFrame.Arg0);
                }
                else
                {
                    tmpCallFrame.This = mdr.Runtime.Instance.GlobalContext;
                }
                if (callFrame.PassedArgsCount > 1)
                {
                    if (callFrame.Arg1.ValueType != mdr.ValueTypes.Array)
                    {
                        throw new InvalidOperationException("second argument of .apply should be an array");
                    }
                    var args = callFrame.Arg1.AsDArray();
                    tmpCallFrame.PassedArgsCount = args.Length;
                    switch (tmpCallFrame.PassedArgsCount)
                    {  //putting goto case x will crash the mono on linux
                    case 0:
                        break;

                    case 1:
                        tmpCallFrame.Arg0 = args.Elements[0];
                        break;

                    case 2:
                        tmpCallFrame.Arg1 = args.Elements[1];
                        goto case 1;

                    //tmpCallFrame.Arg0 = args.Elements[0];
                    //break;
                    case 3:
                        tmpCallFrame.Arg2 = args.Elements[2];
                        goto case 2;

                    //tmpCallFrame.Arg1 = args.Elements[1];
                    //tmpCallFrame.Arg0 = args.Elements[0];
                    //break;
                    case 4:
                        tmpCallFrame.Arg3 = args.Elements[3];
                        goto case 3;

                    //tmpCallFrame.Arg2 = args.Elements[2];
                    //tmpCallFrame.Arg1 = args.Elements[1];
                    //tmpCallFrame.Arg0 = args.Elements[0];
                    //break;
                    default:
                        tmpCallFrame.Arguments = JSFunctionArguments.Allocate(tmpCallFrame.PassedArgsCount - mdr.CallFrame.InlineArgsCount);
                        Array.Copy(args.Elements, mdr.CallFrame.InlineArgsCount, tmpCallFrame.Arguments, 0, tmpCallFrame.PassedArgsCount - mdr.CallFrame.InlineArgsCount);
                        goto case 4;
                        //tmpCallFrame.Arg3 = args.Elements[3];
                        //tmpCallFrame.Arg2 = args.Elements[2];
                        //tmpCallFrame.Arg1 = args.Elements[1];
                        //tmpCallFrame.Arg0 = args.Elements[0];
                        //break;
                    }
                    tmpCallFrame.Signature = new mdr.DFunctionSignature(args.Elements, tmpCallFrame.PassedArgsCount);
                }
                else
                {
                    tmpCallFrame.PassedArgsCount = 0;
                }
                tmpCallFrame.Function.Call(ref tmpCallFrame);
                if (tmpCallFrame.Arguments != null)
                {
                    JSFunctionArguments.Release(tmpCallFrame.Arguments);
                }

                callFrame.Return = tmpCallFrame.Return;
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            TargetPrototype.DefineOwnProperty("call", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
            {
                Debug.WriteLine("calling JSFunction.call");
                var tmpCallFrame      = new mdr.CallFrame();
                tmpCallFrame.Function = callFrame.This.ToDFunction();
                if (tmpCallFrame.Function == null)
                {
                    throw new InvalidOperationException(".call should be called on a Function object");
                }

                switch (callFrame.PassedArgsCount)
                {
                case 0:
                    tmpCallFrame.PassedArgsCount = 0;
                    tmpCallFrame.This            = mdr.Runtime.Instance.GlobalContext;
                    //throw new InvalidOperationException(".call should be called with at least one parameter");
                    break;

                case 1:
                    //tmpCallFrame.This = callFrame.Arg0;
                    if (mdr.ValueTypesHelper.IsDefined(callFrame.Arg0.ValueType))
                    {
                        tmpCallFrame.This = Operations.Convert.ToObject.Run(ref callFrame.Arg0);
                    }
                    else
                    {
                        tmpCallFrame.This = mdr.Runtime.Instance.GlobalContext;
                    }
                    tmpCallFrame.PassedArgsCount = callFrame.PassedArgsCount - 1;
                    break;

                case 2:
                    tmpCallFrame.Arg0 = callFrame.Arg1;
                    goto case 1;

                //tmpCallFrame.This = callFrame.Arg0;
                //tmpCallFrame.ArgsCount = callFrame.ArgsCount - 1;
                //break;
                case 3:
                    tmpCallFrame.Arg1 = callFrame.Arg2;
                    goto case 2;

                //tmpCallFrame.Arg0 = callFrame.Arg1;
                //tmpCallFrame.This = callFrame.Arg0;
                //tmpCallFrame.ArgsCount = callFrame.ArgsCount - 1;
                //break;
                case 4:
                    tmpCallFrame.Arg2 = callFrame.Arg3;
                    goto case 3;

                //tmpCallFrame.Arg1 = callFrame.Arg2;
                //tmpCallFrame.Arg0 = callFrame.Arg1;
                //tmpCallFrame.This = callFrame.Arg0;
                //tmpCallFrame.ArgsCount = callFrame.ArgsCount - 1;
                //break;
                case 5:
                    tmpCallFrame.Arg3 = callFrame.Arguments[0];
                    goto case 4;

                //tmpCallFrame.Arg2 = callFrame.Arg3;
                //tmpCallFrame.Arg1 = callFrame.Arg2;
                //tmpCallFrame.Arg0 = callFrame.Arg1;
                //tmpCallFrame.This = callFrame.Arg0;
                //tmpCallFrame.ArgsCount = callFrame.ArgsCount - 1;
                //break;
                default:
                    tmpCallFrame.Arguments = JSFunctionArguments.Allocate(tmpCallFrame.PassedArgsCount - mdr.CallFrame.InlineArgsCount);
                    Array.Copy(tmpCallFrame.Arguments, 0, callFrame.Arguments, 1, callFrame.PassedArgsCount - 1 - mdr.CallFrame.InlineArgsCount);
                    tmpCallFrame.Arg3 = callFrame.Arguments[0];
                    goto case 5;
                    //tmpCallFrame.Arg2 = callFrame.Arg3;
                    //tmpCallFrame.Arg1 = callFrame.Arg2;
                    //tmpCallFrame.Arg0 = callFrame.Arg1;
                    //tmpCallFrame.This = callFrame.Arg0;
                    //tmpCallFrame.ArgsCount = callFrame.ArgsCount - 1;
                    //break;
                }
                tmpCallFrame.Signature = new mdr.DFunctionSignature(ref tmpCallFrame, tmpCallFrame.PassedArgsCount);
                tmpCallFrame.Function.Call(ref tmpCallFrame);
                if (tmpCallFrame.Arguments != null)
                {
                    JSFunctionArguments.Release(tmpCallFrame.Arguments);
                }

                callFrame.Return = tmpCallFrame.Return;
            }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);

            /*TargetPrototype.DefineOwnProperty("bind", new mdr.DFunction((ref mdr.CallFrame callFrame) =>
             * {
             *  Debug.WriteLine("calling JSFunction.bind");
             *  Trace.Fail("Unimplemented");
             * }), mdr.PropertyDescriptor.Attributes.NotEnumerable | mdr.PropertyDescriptor.Attributes.Data);*/
        }
Example #10
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);
        }
Example #11
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);
        }