//ECMA-262 15.2.4.5 void hasOwnProperty(ref mdr.CallFrame callFrame) { var obj = callFrame.This; var prop = callFrame.Arg0.AsString(); callFrame.Return.Set(obj.HasOwnProperty(prop)); }
//ECMA-262 section 15.2.3.14 void keys(ref mdr.CallFrame callFrame) { Debug.WriteLine("calling JSObject.keys"); var O = callFrame.Arg0.AsDObject(); if (O == null) { Trace.Fail("TypeError"); } var retArray = new DArray(O.Map.Property.Index + 1); var i = 0; for (var m = O.Map; m.Property.Name != null; m = m.Parent) { if (!m.Property.IsNotEnumerable && !m.Property.IsInherited && (m.Property.IsDataDescriptor || m.Property.IsAccessorDescriptor)) { retArray.Elements[i++].Set(m.Property.Name); } } retArray.Length = i; //Debug.Assert(i == retArray.Length, "Array not populated correctly!"); callFrame.Return.Set(retArray); }
public virtual void Construct(ref CallFrame callFrame) { DValue proto = new DValue(); PrototypePropertyDescriptor.Get(this, ref proto); var protoObj = proto.AsDObject(); if (_prototypeMapMetadata == null || _prototypeMapMetadata.Prototype != protoObj) { _prototypeMapMetadata = Runtime.Instance.GetMapMetadataOfPrototype(protoObj); } callFrame.Function = this; if (Metadata != null) { callFrame.This = (new DObject(Metadata.TypicalConstructedFieldsLength, _prototypeMapMetadata.Root)); } else { callFrame.This = (new DObject(0, _prototypeMapMetadata.Root)); } JittedCode(ref callFrame); if (Metadata != null && Metadata.TypicalConstructedFieldsLength < callFrame.This.Fields.Length) { Metadata.TypicalConstructedFieldsLength = callFrame.This.Fields.Length; } if (ValueTypesHelper.IsObject(callFrame.Return.ValueType)) { callFrame.This = callFrame.Return.AsDObject(); } }
public static bool CheckSignature(ref mdr.CallFrame callFrame) { var func = callFrame.Function; var funcCode = func.Code; if (!func.EnableSignature || funcCode == null) { //If funcCode is null, that means this function was resolved at compile time and directly called in the code return(true); } Debug.Assert( ((JSFunctionMetadata)callFrame.Function.Metadata).ParametersCount > 0 && funcCode.Signature.Value != mdr.DFunctionSignature.EmptySignature.Value , "Invalid situaltion, we should not be checking signature for function {0}", callFrame.Function.Metadata.Declaration); if (funcCode.MatchSignature(ref callFrame.Signature)) { return(true); } else { callFrame.Function.Metadata.Execute(ref callFrame); return(false); } }
public static bool CallProperty(mdr.DObject input, string propName, out mdr.DValue output) { if (input != null) { var propDesc = input.GetPropertyDescriptor(propName); var prop = new mdr.DValue(); propDesc.Get(input, ref prop); mdr.DFunction func = null; if (prop.ValueType == mdr.ValueTypes.Function) { func = prop.AsDFunction(); //if (toString != null) //{ mdr.CallFrame callFrame = new mdr.CallFrame(); callFrame.This = (input); callFrame.Function = func; func.Call(ref callFrame); if (ValueTypesHelper.IsPrimitive(callFrame.Return.ValueType)) { output = callFrame.Return; return(true); } } } output = new mdr.DValue(); output.SetUndefined(); return(false); }
//public DFunctionSignature(int maxArgsCount) //{ // Value = GetMask(maxArgsCount); //} public DFunctionSignature(ref CallFrame callFrame, int maxArgsCount) { Value = EmptySignature.Value; if (callFrame.PassedArgsCount == 0) { return; } var argsCount = callFrame.PassedArgsCount; if (argsCount > maxArgsCount) { argsCount = maxArgsCount; } if (argsCount > TypesPerElement) { return; //throw new System.ArgumentOutOfRangeException("Too many arguments in the function signature!"); } for (var i = argsCount - 1; i >= 0; --i) { InitArgType(i, callFrame.Arg(i).ValueType); } //var tmp = Value; //for (var i = argsCount - 1; i >= 0; --i) // tmp = (tmp << BitsPerType) | (unchecked((uint)callFrame.Arg(i).ValueType) & TypeMask); ////for (var i = argsCount; i < TypesPerElement; ++i) //// tmp = (tmp << TypeBits) | (unchecked((uint)ValueTypes.Unknown) & 0x0F); //Value = tmp; }
public static bool CallProperty(mdr.DObject input, string propName, out mdr.DValue output) { if (input != null) { var propDesc = input.GetPropertyDescriptor(propName); var prop = new mdr.DValue(); propDesc.Get(input, ref prop); mdr.DFunction func = null; if (prop.ValueType == mdr.ValueTypes.Function) { func = prop.AsDFunction(); //if (toString != null) //{ mdr.CallFrame callFrame = new mdr.CallFrame(); callFrame.This = (input); callFrame.Function = func; func.Call(ref callFrame); if (ValueTypesHelper.IsPrimitive(callFrame.Return.ValueType)) { output = callFrame.Return; return true; } } } output = new mdr.DValue(); output.SetUndefined(); return false; }
// ECMA 262 - 15.10.4 private void ctor(ref mdr.CallFrame callFrame) { DRegExp regexp = null; string pattern; string flags; switch (callFrame.PassedArgsCount) { case 0: regexp = new DRegExp(""); break; case 1: if (callFrame.Arg0.ValueType == mdr.ValueTypes.Object && IsRegExp(callFrame.Arg0.AsDObject())) { regexp = callFrame.Arg0.AsDObject() as DRegExp; if (IsConstrutor) { //We have to create a new copy regexp = new DRegExp(regexp.Value.ToString()); } } else { pattern = Operations.Convert.ToString.Run(ref callFrame.Arg0); regexp = new DRegExp(pattern); } break; case 2: if (callFrame.Arg0.ValueType == mdr.ValueTypes.Object) { if (IsRegExp(callFrame.Arg0.AsDObject())) { RegExpError("TypeError"); } } else { pattern = Operations.Convert.ToString.Run(ref callFrame.Arg0); flags = Operations.Convert.ToString.Run(ref callFrame.Arg1); regexp = new DRegExp(pattern, flags); } break; default: RegExpError("Invalid arguments in RegExp constructor"); break; } if (IsConstrutor) { callFrame.This = (regexp); } else { callFrame.Return.Set(regexp); } }
// ECMA 262 - 15.10.6.2 private static void exec(ref mdr.CallFrame callFrame) { Debug.WriteLine("calling JSRegExp.exec S {0} \n R {1}", callFrame.Arg0, callFrame.This); string S = Operations.Convert.ToString.Run(ref callFrame.Arg0); DRegExp R = callFrame.This as DRegExp; callFrame.Return.Set(R.ExecImplementation(S)); }
//ECMA-262 section 15.2.2.1 void ctor(ref mdr.CallFrame callFrame) { if (IsConstrutor) { //var p = GetField("prototype"); //callFrame.This.Set(new mdr.DObject(p.DObjectValue)); callFrame.This = (new mdr.DObject(TargetPrototype)); } }
public static mdr.DObject CreateFunctionContext(ref mdr.CallFrame callFrame) { //this function will or may change its context, so create a new one; this is the safest option ///If callFrame.Function.ContextMap is null, it means it is the first time that function object is called ///in this case, we create a new PropertyMap and add all necessary fields to it. Then assign it to the .ContextMap. ///We don't add them one-by-one to the context itself to avoid resizing context.Fields several times. ///Also we first add all of them, so that we can use the reference of the context.Fields[i] //TODO: if we had the function object here, we could technically do the addition to map here and generate code that directly uses the indexes mdr.DObject context; var contextMap = callFrame.Function.Metadata.ContextMap; if (contextMap == null) { var outerContext = callFrame.Function.OuterContext; context = new mdr.DObject(outerContext); //We do this first to get the root of the map first contextMap = context.Map; var scope = ((JSFunctionMetadata)callFrame.Function.Metadata).Scope; if (scope.HasClosedOnSymbol) { var symbols = scope.Symbols; for (var i = symbols.Count - 1; i >= 0; --i) { var symbol = symbols[i]; if (symbol.SymbolType == JSSymbol.SymbolTypes.ClosedOnLocal) { if (scope.HasArgumentsSymbol && symbol.IsParameter) { contextMap = contextMap.AddOwnProperty(symbol.Name, symbol.FieldId, PropertyDescriptor.Attributes.Accessor | PropertyDescriptor.Attributes.NotConfigurable); } else { contextMap = contextMap.AddOwnProperty(symbol.Name, symbol.FieldId, PropertyDescriptor.Attributes.Data | PropertyDescriptor.Attributes.NotConfigurable); } } } } if (scope.HasEval) { //Eval may use the arguments Debug.Assert(scope.HasArgumentsSymbol, "Exected arguments in the context for a function with eval"); contextMap = contextMap.AddOwnProperty(JSFunctionArguments.Name, mdr.Runtime.Instance.GetFieldId(JSFunctionArguments.Name), PropertyDescriptor.Attributes.Data | PropertyDescriptor.Attributes.NotConfigurable); } context.Map = contextMap; //This will update the fields size callFrame.Function.Metadata.ContextMap = contextMap; } else { context = new mdr.DObject(contextMap); } return(context); }
public static mdr.DObject CreateConstantContext(ref mdr.CallFrame callFrame) { //return CreateFunctionContext(ref callFrame); //TODO: the following optimization requires proper support in the code generation as well! For now, we don't do much! //this function will not change its context, so we can just reuse the outer context Debug.Assert(((JSFunctionMetadata)callFrame.Function.Metadata).Scope.IsConstContext, "Function {0} will need its own context", ((JSFunctionMetadata)callFrame.Function.Metadata).Declaration); var context = callFrame.Function.OuterContext; return(context); }
//ECMA-262 section 15.2.3.2 void getPrototypeOf(ref mdr.CallFrame callFrame) { Debug.WriteLine("calling JSObject.getPrototypeOf"); var O = callFrame.Arg0.AsDObject(); if (O == null) { Trace.Fail("TypeError"); } callFrame.Return.Set(O.Prototype); }
public static mdr.DObject CreateProgramContext(ref mdr.CallFrame callFrame) { //this function should add everything to global context //since this is called once, it will also add all the symbols through a not so efficient loop var metadata = (JSFunctionMetadata)callFrame.Function.Metadata; Debug.Assert(metadata.Scope.IsProgram, "Function {0} is not a program", metadata.Declaration); var context = JSRuntime.Instance.GlobalContext; AddSymbolsToContext(metadata.Scope.Symbols, context); return(context); }
public static mdr.DObject CreateEvalContext(ref mdr.CallFrame callFrame) { //this function should add everything to its parent context //since we don't cache the generated code, it will also add all the symbols through a not so efficient loop var metadata = (JSFunctionMetadata)callFrame.Function.Metadata; Debug.Assert(metadata.Scope.IsEvalFunction, "Function {0} is not an eval", metadata.Declaration); Debug.Assert(callFrame.CallerContext != null, "Eval function {0} needs CallerContext in its call frame", metadata.Declaration); var context = callFrame.CallerContext; AddSymbolsToContext(metadata.Scope.Symbols, context); return(context); }
//#region ToX //public string ToString(DObject This) { return (OnGetString != null) ? OnGetString(This) : ToDValue().ToString(); }// base.ToString(); } //public double ToDouble(DObject This) { return (OnGetDouble != null) ? OnGetDouble(This) : ToDValue().ToDouble(); }// base.ToDouble(); } //public int ToInt(DObject This) { return (OnGetInt != null) ? OnGetInt(This) : ToDValue().ToInt32(); }// base.ToInt(); } //public bool ToBoolean(DObject This) { return (OnGetBoolean != null) ? OnGetBoolean(This) : ToDValue().ToBoolean(); }// base.ToBoolean(); } //public DObject ToDObject(DObject This) { return (OnGetDObject != null) ? OnGetDObject(This) : ToDValue().ToDObject(); }// base.ToDObject(); } //public DValue ToDValue(DObject This) //{ // if (OnGetDValue != null) // { // DValue temp = new DValue(); // OnGetDValue(This, ref temp); // return temp; // } // else // { // return base.ToDValue(); // } //} //#endregion #region Get public void Get(DObject This, ref DValue v) { if (OnGetDValue != null) OnGetDValue(This, ref v); else if (Getter != null) { var callFrame = new CallFrame(); callFrame.Function = Getter; callFrame.This = (This); Getter.Call(ref callFrame); v = callFrame.Return; } else v = base.ToDValue(); }
//ECMA-262 section 15.2.3.7 void defineProperties(ref mdr.CallFrame callFrame) { Debug.WriteLine("calling JSObject.defineProperties"); var O = callFrame.Arg0.AsDObject(); if (O == null) { Trace.Fail("TypeError"); } var props = callFrame.Arg1.AsDObject(); DefineProperties(O, props); callFrame.Return.Set(O); }
//ECMA-262 section 15.2.3.6 void defineProperty(ref mdr.CallFrame callFrame) { Debug.WriteLine("calling JSObject.defineProperty"); var O = callFrame.Arg0.AsDObject(); if (O == null) { Trace.Fail("TypeError"); } var name = callFrame.Arg1.AsString(); var desc = callFrame.Arg2.AsDObject(); DefineProperty(O, name, desc); callFrame.Return.Set(O); }
//ECMA-262 15.2.4.2 void toString(ref mdr.CallFrame callFrame) { DObject obj; if (!ValueTypesHelper.IsDefined(callFrame.This.ValueType)) { obj = Runtime.Instance.GlobalContext; } else { obj = callFrame.This; } //callFrame.Return.Set(obj.ToString()); callFrame.Return.Set(string.Format("[object {0}]", obj.Map.Metadata.Name)); }
//ECMA-262 section 15.2.3.3 void getOwnPropertyDescriptor(ref mdr.CallFrame callFrame) { Debug.WriteLine("calling JSObject.getPropertyDescriptor"); var O = callFrame.Arg0.AsDObject(); if (O == null) { Trace.Fail("TypeError"); } // TODO: Commented because name and desc are unused. /*var name = callFrame.Arg1.ToString(); * var desc = O.GetField(name); //FIXME: GetField must be GetOwnProperty*/ Trace.Fail("Unimplemented"); }
//#region ToX //public string ToString(DObject This) { return (OnGetString != null) ? OnGetString(This) : ToDValue().ToString(); }// base.ToString(); } //public double ToDouble(DObject This) { return (OnGetDouble != null) ? OnGetDouble(This) : ToDValue().ToDouble(); }// base.ToDouble(); } //public int ToInt(DObject This) { return (OnGetInt != null) ? OnGetInt(This) : ToDValue().ToInt32(); }// base.ToInt(); } //public bool ToBoolean(DObject This) { return (OnGetBoolean != null) ? OnGetBoolean(This) : ToDValue().ToBoolean(); }// base.ToBoolean(); } //public DObject ToDObject(DObject This) { return (OnGetDObject != null) ? OnGetDObject(This) : ToDValue().ToDObject(); }// base.ToDObject(); } //public DValue ToDValue(DObject This) //{ // if (OnGetDValue != null) // { // DValue temp = new DValue(); // OnGetDValue(This, ref temp); // return temp; // } // else // { // return base.ToDValue(); // } //} //#endregion #region Get public void Get(DObject This, ref DValue v) { if (OnGetDValue != null) { OnGetDValue(This, ref v); } else if (Getter != null) { var callFrame = new CallFrame(); callFrame.Function = Getter; callFrame.This = (This); Getter.Call(ref callFrame); v = callFrame.Return; } else { v = base.ToDValue(); } }
//ECMA-262 section 15.2.3.5 void create(ref mdr.CallFrame callFrame) { Debug.WriteLine("calling JSObject.create"); var O = callFrame.Arg0.AsDObject(); if (O == null) { Trace.Fail("TypeError"); } var obj = new DObject(O); var props = callFrame.Arg1.AsDObject(); if (!ValueTypesHelper.IsUndefined(props.ValueType)) { DefineProperties(obj, props); } callFrame.Return.Set(obj); }
//ECMA-262 15.2.4.7 void propertyIsEnumerable(ref mdr.CallFrame callFrame) { DObject obj; if (!ValueTypesHelper.IsDefined(callFrame.This.ValueType)) { obj = Runtime.Instance.GlobalContext; } else { obj = callFrame.This; } //callFrame.Return.Set(obj.ToString()); if (callFrame.PassedArgsCount == 1) { string toString; if (callFrame.Arg0.ValueType == ValueTypes.String) { toString = callFrame.Arg0.AsString(); } else { toString = callFrame.Arg0.AsDObject().GetField("toString").AsString(); } PropertyDescriptor pd = obj.GetPropertyDescriptor(toString); if (pd != null) { callFrame.Return.Set(!pd.IsNotEnumerable); } else { callFrame.Return.Set(false); } } else { callFrame.Return.Set(false); } }
public DObject Set(DObject This, ref DValue v) { if (OnSetDValue != null) { OnSetDValue(This, ref v); } else if (Setter != null) { var callFrame = new CallFrame(); callFrame.Function = Setter; callFrame.This = (This); callFrame.PassedArgsCount = 1; callFrame.Arg0 = v; callFrame.Signature.InitArgType(0, v.ValueType); Setter.Call(ref callFrame); } else { Trace.Fail(new NotSupportedException(string.Format("Cannot find setter for {0}:{1} on property {2}", v, typeof(DValue), base.ToString()))); } return(this); }
// ECMA 262 - 15.10.6.3 private void test(ref mdr.CallFrame callFrame) { Debug.WriteLine("calling JSRegExp.test"); string S = Operations.Convert.ToString.Run(ref callFrame.Arg0); DRegExp R = callFrame.This as DRegExp; LastDRegExp = R; if (R != null && R.MatchImplementation(S) != null) { if (R.MatchedGroups.Count > MaxMatchedGroupIndex) { for (var i = 0; i < (R.MatchedGroups.Count - MaxMatchedGroupIndex); i++) { AddNewMatchedGroup(); } } callFrame.Return.Set(true); } else { callFrame.Return.Set(false); } }
//ECMA-262 section 15.2.3.4 void getOwnPropertyNames(ref mdr.CallFrame callFrame) { Debug.WriteLine("calling JSObject.getOwnPropertyNames"); var O = callFrame.Arg0.AsDObject(); if (O == null) { Trace.Fail("TypeError"); } var retArray = new DArray(O.Map.Property.Index + 1); var i = 0; for (var m = O.Map; m.Property.Name != null; m = m.Parent) { retArray.Elements[i++].Set(m.Property.Name); } retArray.Length = i; //Debug.Assert(i == retArray.Length, "Array not populated correctly!"); callFrame.Return.Set(retArray); }
public void Call(ref CallFrame callFrame) { JittedCode(ref callFrame); }
//ECMA-262 15.2.4.6 void isPrototypeOf(ref mdr.CallFrame callFrame) { Trace.Fail("Unimplemented"); }
//This is used to setup callee signature within the body of the current function; //public DFunctionSignature CalleeSignature; ///We keep a pool of right sized Arguments for each call site here. ///As long as multiple DFunctionCode instances of a DFunctionMetadata don't run in parallel, we can share this pool with them. //public DValue[][] ArgumentsPool; public virtual void Execute(ref CallFrame callFrame) { Method(ref callFrame); }
//ECMA-262 15.2.4.4 void valueOf(ref mdr.CallFrame callFrame) { callFrame.Return.Set(callFrame.This); }
//ECMA-262 15.2.4.3 void toLocaleString(ref mdr.CallFrame callFrame) { Trace.Fail("Unimplemented"); }
//ECMA-262 15.2.4.1 void constructor(ref mdr.CallFrame callFramer) { }
//ECMA-262 section 15.2.3.13 void isExtensible(ref mdr.CallFrame callFrame) { Trace.Fail("Unimplemented"); }
//ECMA-262 section 15.2.3.12 void isFrozen(ref mdr.CallFrame callFrame) { Trace.Fail("Unimplemented"); }
public DObject Set(DObject This, ref DValue v) { if (OnSetDValue != null) OnSetDValue(This, ref v); else if (Setter != null) { var callFrame = new CallFrame(); callFrame.Function = Setter; callFrame.This = (This); callFrame.PassedArgsCount = 1; callFrame.Arg0 = v; callFrame.Signature.InitArgType(0, v.ValueType); Setter.Call(ref callFrame); } else Trace.Fail(new NotSupportedException(string.Format("Cannot find setter for {0}:{1} on property {2}", v, typeof(DValue), base.ToString()))); return this; }
//public DFunctionSignature(int maxArgsCount) //{ // Value = GetMask(maxArgsCount); //} public DFunctionSignature(ref CallFrame callFrame, int maxArgsCount) { Value = EmptySignature.Value; if (callFrame.PassedArgsCount == 0) return; var argsCount = callFrame.PassedArgsCount; if (argsCount > maxArgsCount) argsCount = maxArgsCount; if (argsCount > TypesPerElement) { return; //throw new System.ArgumentOutOfRangeException("Too many arguments in the function signature!"); } for (var i = argsCount - 1; i >= 0; --i) InitArgType(i, callFrame.Arg(i).ValueType); //var tmp = Value; //for (var i = argsCount - 1; i >= 0; --i) // tmp = (tmp << BitsPerType) | (unchecked((uint)callFrame.Arg(i).ValueType) & TypeMask); ////for (var i = argsCount; i < TypesPerElement; ++i) //// tmp = (tmp << TypeBits) | (unchecked((uint)ValueTypes.Unknown) & 0x0F); //Value = tmp; }
public virtual void Construct(ref CallFrame callFrame) { DValue proto = new DValue(); PrototypePropertyDescriptor.Get(this, ref proto); var protoObj = proto.AsDObject(); if (_prototypeMapMetadata == null || _prototypeMapMetadata.Prototype != protoObj) _prototypeMapMetadata = Runtime.Instance.GetMapMetadataOfPrototype(protoObj); callFrame.Function = this; if (Metadata != null) { callFrame.This = (new DObject(Metadata.TypicalConstructedFieldsLength, _prototypeMapMetadata.Root)); } else { callFrame.This = (new DObject(0, _prototypeMapMetadata.Root)); } JittedCode(ref callFrame); if (Metadata != null && Metadata.TypicalConstructedFieldsLength < callFrame.This.Fields.Length) Metadata.TypicalConstructedFieldsLength = callFrame.This.Fields.Length; if (ValueTypesHelper.IsObject(callFrame.Return.ValueType)) callFrame.This = callFrame.Return.AsDObject(); }