} } // ObjectConstructorObj // Implementation for calling the Object constructor as a function. // "When Object is called as a function rather than as a constructor, it // performs a type conversion." private static object ObjectConstructorFunction(object this_, params object[] args) { if (args.Length == 0 || args[0] == null || args[0] is JUndefinedObject) return ObjectConstructor(null, args); return JConvert.ToObject(args[0]); } // ObjectConstructorFunction
} // ArrayConstructorFunction // Implementation for calling the Array constructor as a constructor. public static object ArrayConstructor(object this_, params object[] args) { JArrayObject arrayObj = new JArrayObject(); if (args.Length == 1 && JObject.Typeof(args[0]) == "number") { // Treat the one argument as a length, and create an array of // that length. UInt32 newLength = JConvert.ToUInt32(args[0]); if (newLength != JConvert.ToNumber(args[0])) throw new RangeError("array length in constructor is outside the UInt32 range"); arrayObj.arrayLength = newLength; } else { // Create an array with the entries specified in the args array. foreach (object curArg in args) arrayObj.entries.Add(curArg); arrayObj.arrayLength = (uint) args.Length; } return arrayObj; } // ArrayConstructor
} } // StringConstructorObj // Implementation for calling the String constructor as a function. // "When String is called as a function rather than as a constructor, // it performs a type conversion." private static object StringConstructorFunction(object this_, params object[] args) { if (args.Length == 0) return ""; else return JConvert.ToString(args[0]); } // StringConstructorFunction
} } // NumberConstructorObj // Implementation for calling the Number constructor as a function. // "When Number is called as a function rather than as a constructor, // it performs a type conversion." private static object NumberConstructorFunction(object this_, params object[] args) { if (args.Length == 0) return 0; else return JConvert.ToNumber(args[0]); } // NumberConstructorFunction
} } // BooleanConstructorObj // Implementation for calling the Boolean constructor as a function. // "When Boolean is called as a function rather than as a constructor, // it performs a type conversion." private static object BooleanConstructorFunction(object this_, params object[] args) { if (args.Length == 0) return 0; else return JConvert.ToBoolean(args[0]); } // BooleanConstructorFunction
} // StringConstructorFunction // Implementation for calling the String constructor as a constructor. // "When String is called as part of a new expression, it is a constructor: // it initialises the newly created object." public static object StringConstructor(object this_, params object[] args) { string strValue; if (args.Length == 0) strValue = ""; else strValue = JConvert.ToString(args[0]); return new JStringObject(strValue); } // StringConstructor
} // NumberConstructorFunction // Implementation for calling the Number constructor as a constructor. // "When Number is called as part of a new expression, it is a constructor: // it initialises the newly created object." public static object NumberConstructor(object this_, params object[] args) { double numValue; if (args.Length == 0) numValue = 0; else numValue = JConvert.ToNumber(args[0]); return new JNumberObject(numValue); } // NumberConstructor
} // BooleanConstructorFunction // Implementation for calling the Boolean constructor as a constructor. // "When Boolean is called as part of a new expression, it is a constructor: // it initialises the newly created object." public static object BooleanConstructor(object this_, params object[] args) { bool boolValue; if (args.Length == 0) boolValue = false; else boolValue = JConvert.ToBoolean(args[0]); return new JBooleanObject(boolValue); } // BooleanConstructor
} // ObjectConstructorFunction // Implementation for calling the Object constructor as a constructor. // "When Object is called as part of a new expression, it is a // constructor that may create an object." public static object ObjectConstructor(object this_, params object[] args) { if (args.Length == 0 || args[0] == null || args[0] is JUndefinedObject) return new JObject(ObjectPrototype, ObjectConstructorObj, "Object"); else { object v = args[0]; if (v is bool || IsNumber(v) || v is string) return JConvert.ToObject(v); else return v; } } // ObjectConstructor
} // IncrementLength // If the given string is an ECMAScript numerical array index, fill in // arrayIndex and return true. Otherwise set arrayIndex to 0 and return // false. public bool IsArrayIndex(string propName, out UInt32 arrayIndex) { arrayIndex = 0; // HACK snewman 10/3/01: need to implement the ECMAScript spec more // precisely. if (propName == "0") return true; foreach (char c in propName) if (c < '0' || c > '9') return false; double d = JConvert.ToNumber(propName); if (d > 0 && d <= 0xFFFFFFFE) { arrayIndex = (UInt32)d; return true; } return false; } // IsArrayIndex
} // LookupProperty // Store the given property under the given name, overwriting any // existing property of the same name. protected override void StoreProperty(string propName, JProperty prop) { Trace.Assert(prop.name == propName); UInt32 arrayIndex; if (propName == "length") { UInt32 newLength = JConvert.ToUInt32(prop.value); if (newLength != JConvert.ToNumber(prop.value)) throw new RangeError("array length set to a value outside the UInt32 range"); if (entries.Count > newLength) entries.RemoveRange((int)newLength, (int)(entries.Count - newLength)); if (newLength < arrayLength) for (uint i=newLength; i<=arrayLength && sparsePropertyCount > 0; i++) { string iAsString = ArrayIndexToString(i); if (props.ContainsKey(iAsString)) { sparsePropertyCount--; props.Remove(iAsString); } } arrayLength = newLength; } else if (IsArrayIndex(propName, out arrayIndex)) { Trace.Assert(prop.attributes == JProperty.AttrFlags.none); if (arrayIndex < entries.Count) { // This index is already in our entries array; update it. entries[(int)arrayIndex] = prop.value; } else if (arrayIndex == entries.Count) { // This index lands just after our entries array. Extend // the entries array to include it. entries.Add(prop.value); if (arrayIndex >= arrayLength) arrayLength = arrayIndex + 1; // Then, if there were any further adjacent entries being // stored in the hash table, move them to the entries array. while (sparsePropertyCount > 0) { string indexAsString = ArrayIndexToString((uint)(entries.Count)); if (props.ContainsKey(indexAsString)) { JProperty tempProp = (JProperty) (props[indexAsString]); entries.Add(tempProp.value); sparsePropertyCount--; props.Remove(indexAsString); } } } else { if (arrayIndex >= arrayLength) arrayLength = arrayIndex + 1; if (!props.ContainsKey(propName)) sparsePropertyCount++; base.StoreProperty(propName, prop); } } else base.StoreProperty(propName, prop); } // StoreProperty
} // Get (string propName) public virtual object Get(object propName) { return Get(JConvert.ToString(propName)); } // Get (object propName)