Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        /// <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));
        }
Beispiel #4
0
        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);
                }
            }
        }