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);
        }
Ejemplo n.º 2
0
 /// <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));
     }
 }
Ejemplo n.º 3
0
        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);
        }