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 DValue Get(DObject obj) { DValue tmp = new DValue(); Get(obj, ref tmp); return(tmp); }
private PropertyMap DeleteOwnPropertyDescriptor(DObject obj, PropertyMap currMap, PropertyMap delMap) { Debug.Assert(delMap != null, "Invalid situation!"); ///In this function, we recursively add all the properties between the delMap, and this to the delMap.Parent ///currMap==this would be the end of recursion ///at the end we need to propagate the deletion to all objects whose prototype is obj var newMap = (delMap == currMap.Parent || delMap == currMap) ? delMap.Parent : DeleteOwnPropertyDescriptor(obj, currMap.Parent, delMap); if (delMap != this) { var currPropDesc = currMap.Property; newMap = newMap.AddOwnProperty(currPropDesc.Name, currPropDesc.NameId, currPropDesc.GetAttributes()); } if (currMap == this) { Debug.Assert(this.Property.Index == newMap.Property.Index + 1, "Invalid situation, we should delete on one field here!"); obj.Map = newMap; if (delMap != this) //otherwise it is just the last field so no need to copy { Array.Copy(obj.Fields, delMap.Property.Index + 1, obj.Fields, delMap.Property.Index, this.Property.Index - delMap.Property.Index); } var mapMetadata = Metadata.GetMapMetadataOfPrototype(obj, false); if (mapMetadata != null) { mapMetadata.PropagateDeletionDownPrototypeChain(obj, delMap.Property); } } return(newMap); }
public PropertyMapMetadata GetMapMetadataOfPrototype(DObject prototype) { if (prototype == null) { return(EmptyPropertyMapMetadata); } return(prototype.Map.Metadata.GetMapMetadataOfPrototype(prototype)); }
public virtual void SetGlobalContext(mdr.DObject globalContext) { Debug.Assert(globalContext != null, "Global Context cannot be null"); GlobalContext = globalContext; //if (globalContext == null) // GlobalContext = new mdr.DObject(); //GlobalContext = new mdr.DObject(GlobalDObject); }
public void CopyTo(DObject obj) { if (!DType.IsParentOf(obj.DType)) { throw new Exception(string.Format("Type {0} is not a parent of type {1} and so cannot be extended", DType, obj.DType)); } Array.Copy(Fields, obj.Fields, Fields.Length); }
public static bool Run(mdr.DObject i0, mdr.DFunction i1) { //var prototype = func.GetFieldByFieldIndex(mdr.DType.PrototypeIndex); var prototype = new mdr.DValue(); i1.PrototypePropertyDescriptor.Get(i1, ref prototype); return(i0.Prototype == prototype.AsDObject()); }
//#if __MonoCS__ // [MethodImplAttribute(MethodImplOptions.AggressiveInlining)] //#endif public void Get(DObject obj, ref DValue value) { /*if (mdr.Runtime.Instance.Configuration.ProfileStats) * { * mdr.Runtime.Instance.Counters.GetCounter("PD.GET").Count++; * mdr.Runtime.Instance.Counters.GetCounter("PD.GET[" + _flags + "]").Count++; * } */ _getter(this, obj, ref value); }
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 DFunction(DFunctionMetadata funcMetadata, DObject outerContext) : base(Runtime.Instance.DFunctionMap) { Metadata = funcMetadata; if (funcMetadata != null) { JittedCode = Metadata.Execute; } OuterContext = outerContext; }
public void Set(DObject v) { if (v == null) { Object = DObject.Undefined; } else { v.CopyTo(this); } }
public void Set(DObject obj, DObject value) { if (_setter == Own_Data_Set) //This is the most common case, and we can make it faster this way { obj.Fields[Index].Set(value); } else { var tmp = new DValue(); tmp.Set(value); Set(obj, ref tmp); } }
internal PropertyDescriptor AddOwnProperty(DObject obj, string field, int fieldId, PropertyDescriptor.Attributes attributes) { PropertyMap newMap = AddOwnProperty(field, fieldId, attributes); obj.Map = newMap; var mapMetadata = Metadata.GetMapMetadataOfPrototype(obj, false); if (mapMetadata != null) { mapMetadata.PropagateAdditionDownPrototypeChain(obj, newMap.Property); //obj is some other objects' prototype } return(newMap.Property); }
public void SetNullable(DObject v) { // XXX: Presumably the separation of Set(DObject) and CheckNull(DObject) existed because // sometimes we know for sure that the DObject is not null and we can elide the check. // If that's not true, this method should be merged into Set(DObject). if (v == null) { SetNull(); } else { Set(v); } }
public void Set(DObject obj, string value) { //if (IsDataDescriptor && !IsInherited) if (_setter == Own_Data_Set) //This is the most common case, and we can make it faster this way { obj.Fields[Index].Set(value); } else { var tmp = new DValue(); tmp.Set(value); Set(obj, ref tmp); } }
public DObject Set(DObject This, bool v) { if (OnSetBoolean == null) { var tmp = new DValue(); tmp.Set(v); return(Set(This, ref tmp)); } else { OnSetBoolean(This, v); return(this); } }
public DObject Set(DObject This, DObject v) { if (OnSetDObject == null) { var tmp = new DValue(); tmp.Set(v); return(Set(This, ref tmp)); } else { OnSetDObject(This, v); return(this); } }
public DForwardingProperty(DObject receiver, string field) { Receiver = receiver; ReceiverPD = Receiver.Map.GetPropertyDescriptor(field); Debug.Assert(ReceiverPD != null, "receiver field has null descriptor: " + field); OnGetDValue = (DObject This, ref DValue v) => { ReceiverPD.Get(Receiver, ref v); }; OnSetDValue = (DObject This, ref DValue v) => { ReceiverPD.Set(Receiver, ref v); }; }
public PropertyMapMetadata(DObject prototype) { Prototype = prototype; if (Prototype == null) { Level = 0; } else { Level = Prototype.Map.Metadata.Level + 1; } //We create an empty ProperyDescriptor to avoid checking for null all the time Root = new PropertyMap(this, null, new PropertyDescriptor(null, Runtime.InvalidFieldId, Runtime.InvalidFieldIndex, PropertyDescriptor.Attributes.NotEnumerable | PropertyDescriptor.Attributes.Undefined), null); }
public void SetArg(int i, DObject v) { switch (i) { case 0: Arg0.Set(v); break; case 1: Arg1.Set(v); break; case 2: Arg2.Set(v); break; case 3: Arg3.Set(v); break; default: Arguments[i - InlineArgsCount].Set(v); break; } //UpdateSignature(i); }
private static void AddSymbolsToContext(List <JSSymbol> symbols, mdr.DObject context) { //This is called when we are sharing the context, so should be careful not to add fields that are already there //Technically, this is the generic and safe way to do this. for (var i = symbols.Count - 1; i >= 0; --i) { var symbol = symbols[i]; if (symbol.SymbolType == JSSymbol.SymbolTypes.ClosedOnLocal) { var pd = context.Map.GetPropertyDescriptorByFieldId(symbol.FieldId); //TODO: can this be made faster? if (pd == null) { context.AddOwnPropertyDescriptorByFieldId(symbol.FieldId, PropertyDescriptor.Attributes.Data | PropertyDescriptor.Attributes.NotConfigurable); } } } }
internal void PropagateDeletionDownPrototypeChain(DObject obj, PropertyDescriptor propDesc) { //We should only find at most one matching element foreach (var p in _inheritedProperties) { if (p.NameId == propDesc.NameId) { Debug.Assert(p.IsInherited, "{0} has invalid descriptor type {1}", p.Name, p.GetAttributes()); if (p.Container.Map.Metadata.Level > obj.Map.Metadata.Level) { //this property is inherited from an object lower in the property chain. So no longer need to propogate return; } Debug.Assert(p.Container == obj, "Invalid situation!"); //We check to see if the property exists in higher parts of protoype chain var upperPropDesc = obj.Map.Metadata.GetInheritedPropertyDescriptorByFieldId(propDesc.NameId); if (upperPropDesc == null || upperPropDesc.IsUndefined) { p.Container = null; p.Index = propDesc.Index; p.ResetAttributes(PropertyDescriptor.Attributes.Undefined); } else { if (p.Container != upperPropDesc.Container) { if (p.ObjectCacheIndex != -1 && p.ObjectCacheIndex < Runtime._inheritPropertyObjectCache.Length) { Runtime._inheritPropertyObjectCache[p.ObjectCacheIndex] = null; } } p.Container = upperPropDesc.Container; p.Index = upperPropDesc.Index; p.ResetAttributes(upperPropDesc.GetAttributes() | PropertyDescriptor.Attributes.Inherited); } } } foreach (var child in _children) { if (child.IsAlive) { (child.Target as PropertyMapMetadata).PropagateDeletionDownPrototypeChain(obj, propDesc); } } }
public static Result Run(mdr.DObject i0, mdr.DObject i1, bool LeftFirst) { var pLeft = new mdr.DValue(); var pRight = new mdr.DValue(); if (LeftFirst) { Convert.ToPrimitive.Run(i0, ref pLeft, false); Convert.ToPrimitive.Run(i1, ref pRight, false); } else { Convert.ToPrimitive.Run(i1, ref pRight, false); Convert.ToPrimitive.Run(i0, ref pLeft, false); } return(Run(ref pLeft, ref pRight)); }
//#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(); } }
internal void PropagateAdditionDownPrototypeChain(DObject obj, PropertyDescriptor propDesc) { //We should only find at most one matching element foreach (var p in _inheritedProperties) { if (p.NameId == propDesc.NameId) { if (p.IsUndefined) { p.Container = obj; p.Index = propDesc.Index; p.ResetAttributes(propDesc.GetAttributes() | PropertyDescriptor.Attributes.Inherited); } else { Debug.Assert(p.IsInherited, "{0} has invalid descriptor type {1}", p.Name, p.GetAttributes()); if (p.Container.Map.Metadata.Level > obj.Map.Metadata.Level) { //this property is inherited from an object lower in the property chain. So no longer need to propogate return; } if (p.Container != obj && p.Container.Map.Metadata.Level < obj.Map.Metadata.Level) { p.Container = obj; p.Index = propDesc.Index; p.ResetAttributes(propDesc.GetAttributes() | PropertyDescriptor.Attributes.Inherited); if (p.ObjectCacheIndex != -1 && p.ObjectCacheIndex < Runtime._inheritPropertyObjectCache.Length) { Runtime._inheritPropertyObjectCache[p.ObjectCacheIndex] = null; } } } } } foreach (var child in _children) { if (child.IsAlive) { (child.Target as PropertyMapMetadata).PropagateAdditionDownPrototypeChain(obj, propDesc); } } }
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 DeleteStatus DeleteOwnPropertyDescriptor(DObject obj, string field) { Debug.Assert(obj.Map == this, "Invalid situation! this is the map of current object"); Debug.Assert(field != null, "Cannot remove null field from object"); for (var m = this; m != null; m = m.Parent) { if (m.Property.Name == field) { if (m.Property.IsNotConfigurable) { return(DeleteStatus.NotDeletable); } else { DeleteOwnPropertyDescriptor(obj, this, m); return(DeleteStatus.Deleted); } } } return(DeleteStatus.NotFound); }
public static void DefaultValue(mdr.DObject input, out mdr.DValue output, bool stringHint = false) { if (input.PrimitiveValue.ValueType != mdr.ValueTypes.Undefined) { output = input.PrimitiveValue; return; } if (stringHint) { if (!CallToStringProperty(input, out output) && !CallValueOfProperty(input, out output)) { Trace.Fail(new InvalidOperationException(string.Format("TypeError: DefaultValue for {0} is unknown", input.ValueType))); } } else //assume number hint { if (!CallValueOfProperty(input, out output) && !CallToStringProperty(input, out output)) { Trace.Fail(new InvalidOperationException(string.Format("TypeError: DefaultValue for {0} is unknown", input.ValueType))); } } }
public PropertyMap GetRootMapOfPrototype(DObject prototype) { return(GetMapMetadataOfPrototype(prototype).Root); }
protected Runtime(RuntimeConfiguration configuration) { _inheritPropertyObjectCacheMaxIndex = 0; //We need to first set the Instance since the following constructors may use it! Runtime.Instance = this; Configuration = configuration; configuration.ParseArgs();//Do this now before anyone tries to read any configuration value. if (configuration.EnableTimers) { Timers = new m.Util.Timers(); _timer = StartSimpleTimer(true, "MCJS"); } if (configuration.EnableCounters) { Counters = new m.Util.Counters(); } EmptyPropertyMapMetadata = new PropertyMapMetadata(null); ///We can initialize commong field Ids to save lookups later ValueOfFieldId = GetFieldId("valueOf"); ToStringFieldId = GetFieldId("toString"); PrototypeFieldId = GetFieldId("prototype"); LengthFieldId = GetFieldId("length"); ///In each instance of Runtime we need to first reset prototypes in case a program has changed them //DUndefinedPrototype = new DObject(root.Root); DObjectPrototype = new DObject(EmptyPropertyMapMetadata.Root); DObjectMap = GetRootMapOfPrototype(DObjectPrototype); DFunctionPrototype = new DObject(DObjectMap); DFunctionMap = GetRootMapOfPrototype(DFunctionPrototype); DNumberPrototype = new DObject(DObjectMap); DNumberMap = GetRootMapOfPrototype(DNumberPrototype); DStringPrototype = new DObject(DObjectMap); DStringMap = GetRootMapOfPrototype(DStringPrototype); DBooleanPrototype = new DObject(DObjectMap); DBooleanMap = GetRootMapOfPrototype(DBooleanPrototype); DArrayPrototype = new DObject(DObjectMap); DArrayMap = GetRootMapOfPrototype(DArrayPrototype); DRegExpPrototype = new DObject(DObjectMap); DRegExpMap = GetRootMapOfPrototype(DRegExpPrototype); //Now need to recreate default values based on fresh prototypes. DefaultDUndefined = new DUndefined(); DefaultDNull = new DNull(); //DefaultDObject = new DObject(); //DefaultDDouble = new DDouble(default(double)); //DefaultDString = new DString(default(string)); //DefaultDInt = new DInt(default(int)); //DefaultDBoolean = new DBoolean(default(bool)); //DefaultDFunction = new DFunction(null); //DefaultDArray = new DArray(); //DefaultDProperty = new DProperty(); ArrayItemAccessor = new PropertyDescriptor(null) { Getter = (mdr.PropertyDescriptor pd, mdr.DObject obj, ref mdr.DValue value) => { value = (obj as DArray).Elements[pd.Index]; /*if (mdr.Runtime.Instance.Configuration.ProfileStats) * { * mdr.Runtime.Instance.Counters.GetCounter("ArrayItemAccessor").Count++; * }*/ }, Setter = (mdr.PropertyDescriptor pd, mdr.DObject obj, ref mdr.DValue value) => { (obj as DArray).Elements[pd.Index] = value; }, }; StringItemAccessor = new PropertyDescriptor(null) { Getter = (mdr.PropertyDescriptor pd, mdr.DObject obj, ref mdr.DValue value) => { var strObj = obj.FirstInPrototypeChainAs <DString>(); value.Set(strObj.PrimitiveValue.AsString()[pd.Index]); }, Setter = (mdr.PropertyDescriptor pd, mdr.DObject obj, ref mdr.DValue value) => { var strObj = obj.FirstInPrototypeChainAs <DString>(); var chars = strObj.PrimitiveValue.AsString().ToCharArray(); chars[pd.Index] = value.AsChar(); strObj.PrimitiveValue.Set(new String(chars)); }, }; var lengthFieldName = GetFieldName(LengthFieldId); ProtoInitializer.InitDArrayPrototype(DArrayPrototype, lengthFieldName); ProtoInitializer.InitDStringPrototype(DStringPrototype, lengthFieldName); var protoFieldName = GetFieldName(PrototypeFieldId); ProtoInitializer.InitDFunctionPrototype(DFunctionPrototype, protoFieldName, PrototypeFieldId); }
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; }