/// <summary>True if a generic property is available at runtime.</summary> public static bool HasProperty(ScriptEngine engine, object thisObj, string property) { // Exists? if (thisObj == null) { throw new NullReferenceException("Attempted to read property '" + property + "' from a null reference."); } // Get the prototype: Prototype proto = engine.Prototypes.Get(thisObj.GetType()); // Get the property: return(proto.GetProperty(property) != null); }
/// <summary>Sets a generic property on the given object at runtime. Note that this can't create a property.</summary> public static void SetPropertyValue(ScriptEngine engine, object thisObj, string property, object value) { // Exists? if (thisObj == null) { throw new NullReferenceException("Attempted to set property '" + property + "' on a null reference."); } // Get the prototype: Prototype proto = engine.Prototypes.Get(thisObj.GetType()); // Get the property: PropertyVariable pv = proto.GetProperty(property); if (pv == null) { // Undefined: throw new JavaScriptException(engine, "TypeError", "Can't set dynamic properties on generic objects."); } // Set the value: pv.SetValue(thisObj, value); }
/// <summary>Pulls a generic property from the given object at runtime.</summary> public static object GetPropertyValue(ScriptEngine engine, object thisObj, string property) { // Exists? if (thisObj == null) { throw new NullReferenceException("Attempted to read property '" + property + "' from a null reference."); } // Get the prototype: Prototype proto = engine.Prototypes.Get(thisObj.GetType()); // Get the property: PropertyVariable pv = proto.GetProperty(property); if (pv == null) { // Undefined: return(Nitrassic.Undefined.Value); } // Get the value: return(pv.GetValue(thisObj)); }
internal override void ResolveVariables(OptimizationInfo optimizationInfo) { if (ResolvedProperty != null || propertyName != null) { // Already resolved. return; } // Resolve kids: base.ResolveVariables(optimizationInfo); // Right-hand-side can be a property name (a.b) if (this.OperatorType == OperatorType.MemberAccess) { var rhs = this.GetOperand(1) as NameExpression; if (rhs == null) { throw new JavaScriptException(optimizationInfo.Engine, "SyntaxError", "Invalid member access", 1, optimizationInfo.Source.Path, optimizationInfo.FunctionName); } propertyName = rhs.Name; } // Or a constant indexer (a['b']) if (this.OperatorType == OperatorType.Index) { var rhs = this.GetOperand(1); if (rhs != null) { Type rhsType = rhs.GetResultType(optimizationInfo); if (rhsType == typeof(string)) { // Try a literal: LiteralExpression literalStr = rhs as LiteralExpression; if (literalStr != null) { propertyName = TypeConverter.ToString(literalStr.Value); // Could actually be numeric, so try that: if (propertyName != null && Nitrassic.Library.Array.ParseArrayIndex(propertyName) != uint.MaxValue) { // Yep, it is! isArrayIndex = true; } } } else if (PrimitiveTypeUtilities.IsNumeric(rhsType)) { // array index (a[0]) isArrayIndex = true; } } } if (isArrayIndex == true) { // Array indexer // ------------- // xxx = object[index] // Load the left-hand side and convert to an object instance. var lhs = this.GetOperand(0); // Get the type of the LHS (the object being read from): Type lhsType = lhs.GetResultType(optimizationInfo); // Get the proto for it: Nitrassic.Library.Prototype proto = optimizationInfo.Engine.Prototypes.Get(lhsType); // Does that type have an indexer method on it? (this[uint]) ResolvedProperty = proto.Indexer(typeof(uint)); if (ResolvedProperty == null) { // Try [int] instead: ResolvedProperty = proto.Indexer(typeof(int)); } } if (ResolvedProperty == null && propertyName != null) { // Load the left-hand side and convert to an object instance. var lhs = this.GetOperand(0); Type lhsType = lhs.GetResultType(optimizationInfo); // Get the prototype: Nitrassic.Library.Prototype proto = optimizationInfo.Engine.Prototypes.Get(lhsType); // Get the property: ResolvedProperty = proto.GetProperty(propertyName); if (ResolvedProperty == null) { // Add it now (as undefined): ResolvedProperty = proto.AddProperty(propertyName, null, Nitrassic.Library.PropertyAttributes.FullAccess); } } }