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); }
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 */ }, }); }
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); }
/// <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); }
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); }
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); }
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); }
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); }
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);*/ }
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); }
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); }