public static ObjectInstance Create(ScriptEngine engine, object prototype, [DefaultParameterValue(null)] object propertiesArg) { var properties = JurassicHelper.GetTypedArgumentValue <ObjectInstance>(engine, propertiesArg, null); if ((prototype is ObjectInstance) == false && prototype != Null.Value) { throw new JavaScriptException(engine, "TypeError", "object prototype must be an object or null"); } ObjectInstance result = prototype == Null.Value ? ObjectInstance.CreateRootObject(engine) : ObjectInstance.CreateRawObject((ObjectInstance)prototype); if (properties != null) { DefineProperties(result, properties); } return(result); }
/// <summary> /// /// </summary> /// <param name="engine"></param> /// <param name="name"></param> /// <param name="extends"></param> /// <param name="constructor"></param> /// <returns></returns> public static FunctionInstance ConstructClass(ScriptEngine engine, string name, object extends, UserDefinedFunction constructor) { if (extends is FunctionInstance extendsFunction) { // If extends doesn't have [[Construct]] then throw a TypeError. return(new ClassFunction(extendsFunction, name, ObjectInstance.CreateRawObject(extendsFunction.InstancePrototype), constructor)); } else if (extends == Null.Value) { return(new ClassFunction(engine.Function.InstancePrototype, name, ObjectInstance.CreateRootObject(engine), constructor)); } else { if (extends != null) { throw new JavaScriptException(ErrorType.TypeError, $"Class {name} cannot extend '{extends}' as it is not a constructor."); } return(new ClassFunction(engine.Function.InstancePrototype, name, engine.Object.Construct(), constructor)); } }
public ScriptEngine() { // Create the initial hidden class schema. This must be done first. this.emptySchema = HiddenClassSchema.CreateEmptySchema(); // Create the base of the prototype chain. var baseObject = ObjectInstance.CreateRootObject(this); // Create the global object. this.globalObject = new GlobalObject(baseObject); // Create the function object that second to last in the prototype chain. var baseFunction = UserDefinedFunction.CreateEmptyFunction(baseObject); // Object must be created first, then function. this.objectConstructor = new ObjectConstructor(baseFunction, baseObject); this.functionConstructor = new FunctionConstructor(baseFunction, baseFunction); // Create all the built-in objects. this.mathObject = new MathObject(baseObject); this.jsonObject = new JSONObject(baseObject); // Create all the built-in functions. this.arrayConstructor = new ArrayConstructor(baseFunction); this.booleanConstructor = new BooleanConstructor(baseFunction); this.dateConstructor = new DateConstructor(baseFunction); this.numberConstructor = new NumberConstructor(baseFunction); this.regExpConstructor = new RegExpConstructor(baseFunction); this.stringConstructor = new StringConstructor(baseFunction); // Create the error functions. this.errorConstructor = new ErrorConstructor(baseFunction, "Error"); this.rangeErrorConstructor = new ErrorConstructor(baseFunction, "RangeError"); this.typeErrorConstructor = new ErrorConstructor(baseFunction, "TypeError"); this.syntaxErrorConstructor = new ErrorConstructor(baseFunction, "SyntaxError"); this.uriErrorConstructor = new ErrorConstructor(baseFunction, "URIError"); this.evalErrorConstructor = new ErrorConstructor(baseFunction, "EvalError"); this.referenceErrorConstructor = new ErrorConstructor(baseFunction, "ReferenceError"); // Populate the instance prototypes (TODO: optimize this, currently takes about 15ms). this.globalObject.PopulateFunctions(); this.objectConstructor.PopulateFunctions(); this.objectConstructor.InstancePrototype.PopulateFunctions(); this.functionConstructor.InstancePrototype.PopulateFunctions(typeof(FunctionInstance)); this.mathObject.PopulateFunctions(); this.mathObject.PopulateFields(); this.jsonObject.PopulateFunctions(); this.arrayConstructor.PopulateFunctions(); this.arrayConstructor.InstancePrototype.PopulateFunctions(); this.booleanConstructor.InstancePrototype.PopulateFunctions(); this.dateConstructor.PopulateFunctions(); this.dateConstructor.InstancePrototype.PopulateFunctions(); this.numberConstructor.InstancePrototype.PopulateFunctions(); this.numberConstructor.PopulateFields(); this.regExpConstructor.InstancePrototype.PopulateFunctions(); this.stringConstructor.PopulateFunctions(); this.stringConstructor.InstancePrototype.PopulateFunctions(); this.errorConstructor.InstancePrototype.PopulateFunctions(); // Add them as JavaScript-accessible properties of the global instance. this.globalObject.FastSetProperty("Array", this.arrayConstructor, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("Boolean", this.booleanConstructor, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("Date", this.dateConstructor, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("Function", this.functionConstructor, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("JSON", this.jsonObject, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("Math", this.mathObject, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("Number", this.numberConstructor, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("Object", this.objectConstructor, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("RegExp", this.regExpConstructor, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("String", this.stringConstructor, PropertyAttributes.NonEnumerable); // And the errors. this.globalObject.FastSetProperty("Error", this.errorConstructor, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("RangeError", this.rangeErrorConstructor, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("TypeError", this.typeErrorConstructor, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("SyntaxError", this.syntaxErrorConstructor, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("URIError", this.uriErrorConstructor, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("EvalError", this.evalErrorConstructor, PropertyAttributes.NonEnumerable); this.globalObject.FastSetProperty("ReferenceError", this.referenceErrorConstructor, PropertyAttributes.NonEnumerable); }