Example #1
0
        /// <summary>
        /// Sets the value of the global variable with the given name.  If the property does not
        /// exist, it will be created.
        /// </summary>
        /// <param name="variableName"> The name of the variable to set. </param>
        /// <param name="value"> The desired value of the variable. </param>
        /// <param name="attribs">The attributes of the value.</param>
        /// <exception cref="JavaScriptException"> The property is read-only or the property does
        /// not exist and the object is not extensible. </exception>
        public void SetGlobal(string variableName, object value, PropertyAttributes attribs)
        {
            if (value == null)
            {
                value = Null.Value;
            }

            // Try getting the property:
            PropertyVariable pv = GlobalPrototype[variableName];

            if (pv == null)
            {
                // Create it:
                pv = GlobalPrototype.AddProperty(variableName, value, attribs);
            }

            // Await/ set now:
            AwaitStart(new AwaitingStart(pv, value));
        }
Example #2
0
        internal override Variable AddVariable(string name, Type type, Expression valueAtTopOfScope)
        {
            // Get the property:
            PropertyVariable pv = ScopePrototype.GetProperty(name);

            if (pv != null)
            {
                // Already exists - try to change the type (may collapse it):
                pv.Type = type;

                return(pv);
            }

            // Add it now:
            pv = ScopePrototype.AddProperty(name, null, Nitrassic.Library.PropertyAttributes.FullAccess);

            // Set the type:
            pv.Type = type;

            return(pv);
        }
Example #3
0
        /// <summary>
        /// Gets or creates the prototype for the given type with an optional parent prototype.
        /// </summary>
        public Prototype Get(Type type, Prototype parentProto)
        {
            if (type == null)
            {
                return(null);
            }

            string name = type.Name;

            JSProperties attribute;

            if (type is System.Reflection.Emit.TypeBuilder)
            {
                attribute = null;
            }
            else
            {
                attribute = (JSProperties)Attribute.GetCustomAttribute(type, typeof(JSProperties), false);

                if (attribute != null && attribute.Name != null)
                {
                    name = attribute.Name;
                }
            }

            Prototype result;

            if (Lookup.TryGetValue(type, out result))
            {
                return(result);
            }

            // Get the parent proto (obj if none):
            if (parentProto == null)
            {
                Type baseType = type.BaseType;

                if (baseType == typeof(object) || baseType == null)
                {
                    // Get the very bottom of the proto stack:
                    parentProto = Engine.Prototypes.BasePrototype;
                }
                else
                {
                    parentProto = Get(type.BaseType);
                }
            }

            // Create and add it:
            result = new Prototype(Engine, name, parentProto, type);
            Lookup[result.Type] = result;

            // Does it declare PrototypeFor?
            FieldInfo protoFor = type.GetField("PrototypeFor");

            if (protoFor != null)
            {
                // Yes - get the type it's a prototype for:
                object value = protoFor.GetValue(null);

                // It can actually be a set, so check if it's just one first:
                Type protoForType = value as Type;

                if (protoForType != null)
                {
                    // It's just the one.
                    Lookup[protoForType] = result;
                }
                else
                {
                    // It's a set - add each one.
                    // For example, Function acts as the prototype for both MethodBase and MethodGroup.
                    Type[] set = value as Type[];

                    for (int i = 0; i < set.Length; i++)
                    {
                        Lookup[set[i]] = result;
                    }
                }
            }

            // Can this prototype be instanced?
            // - Not a static class
            // - Doesn't have "NoConstructors" set
            bool instanceable = (!type.IsAbstract && !(attribute != null && attribute.NoConstructors));

            if (instanceable)
            {
                if (type == typeof(object))
                {
                    name = "_base_object";
                }

                Prototype ctr = null;

                // Build the constructor prototype:
                ctr = new Prototype(Engine, name + "_ctor", null, false);
                ctr.PopulateConstructorPrototype(type);
                ctr.AddProperty("constructor", Function, Nitrassic.Library.PropertyAttributes.NonEnumerable);
                result.ConstructorPrototype = ctr;

                // ctr is a function instance, so set its base proto:
                ctr.BasePrototype = FunctionPrototype;

                // Generate an instance of the ctr (this also bakes the type):
                ctr.CtrInstance = ctr.Instance();

                // Add it to the lookup:
                Lookup[ctr.Type] = ctr;

                // Setup the instance proto:
                result.PopulateInstancePrototype(type);

                // Add the constructor property to the instance:
                result.AddProperty("constructor", ctr.CtrInstance, Nitrassic.Library.PropertyAttributes.NonEnumerable);
            }
            else
            {
                // Not instanceable - has no constructors or a constructor proto.
                // Init the single prototype now:
                result.PopulatePrototype(type, false);
            }

            return(result);
        }