/// <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)); }
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); }
/// <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); }