Search in sources :

Example 1 with OrdinaryConstructorFunction

use of com.github.anba.es6draft.runtime.types.builtins.OrdinaryConstructorFunction in project es6draft by anba.

the class CodeGenerator method compile.

MethodName compile(MethodDefinitionsMethod node, boolean hasDecorators, CodeVisitor mv) {
    if (!isCompiled(node)) {
        MethodCode method = newMethod(node);
        MethodDefinitionsCodeVisitor body = new MethodDefinitionsCodeVisitor(node, method, mv);
        body.lineInfo(node);
        body.begin();
        Variable<OrdinaryConstructorFunction> function = body.getFunctionParameter();
        Variable<OrdinaryObject> proto = body.getPrototypeParameter();
        Variable<ArrayList<Object>> decorators = hasDecorators ? body.getDecoratorsParameter() : null;
        ClassPropertyEvaluation(this, node.getProperties(), function, proto, decorators, body);
        body._return();
        body.end();
    }
    return methodDesc(node);
}
Also used : OrdinaryConstructorFunction(com.github.anba.es6draft.runtime.types.builtins.OrdinaryConstructorFunction) OrdinaryObject(com.github.anba.es6draft.runtime.types.builtins.OrdinaryObject) ArrayList(java.util.ArrayList) MethodCode(com.github.anba.es6draft.compiler.assembler.Code.MethodCode)

Example 2 with OrdinaryConstructorFunction

use of com.github.anba.es6draft.runtime.types.builtins.OrdinaryConstructorFunction in project es6draft by anba.

the class ClassOperations method EvaluateConstructorMethod.

/**
 * 14.3 Method Definitions, 14.5 Class Definitions
 * <p>
 * 14.3.8 Runtime Semantics: DefineMethod<br>
 * 14.5.14 Runtime Semantics: ClassDefinitionEvaluation
 *
 * @param constructorParent
 *            the constructor prototype
 * @param proto
 *            the class prototype
 * @param fd
 *            the function runtime info object
 * @param isDerived
 *            {@code true} if evaluating the constructor of a derived class
 * @param cx
 *            the execution context
 * @return the new function instance
 */
public static OrdinaryConstructorFunction EvaluateConstructorMethod(ScriptObject constructorParent, OrdinaryObject proto, RuntimeInfo.Function fd, boolean isDerived, ExecutionContext cx) {
    // ClassDefinitionEvaluation - steps 12-14 (call DefineMethod)
    LexicalEnvironment<?> scope = cx.getLexicalEnvironment();
    ConstructorKind constructorKind = isDerived ? ConstructorKind.Derived : ConstructorKind.Base;
    OrdinaryConstructorFunction constructor = ConstructorFunctionCreate(cx, FunctionKind.ClassConstructor, constructorKind, fd, scope, constructorParent);
    MakeMethod(constructor, proto);
    // ClassDefinitionEvaluation - step 15 (not applicable, cf. ConstructorFunctionCreate)
    // ClassDefinitionEvaluation - step 16
    MakeConstructor(constructor, false, proto);
    // ClassDefinitionEvaluation - step 17
    MakeClassConstructor(constructor);
    // ClassDefinitionEvaluation - step 18
    proto.defineOwnProperty(cx, "constructor", new PropertyDescriptor(constructor, true, false, true));
    return constructor;
}
Also used : OrdinaryConstructorFunction(com.github.anba.es6draft.runtime.types.builtins.OrdinaryConstructorFunction) PropertyDescriptor(com.github.anba.es6draft.runtime.types.PropertyDescriptor) AccessorPropertyDescriptor(com.github.anba.es6draft.runtime.types.PropertyDescriptor.AccessorPropertyDescriptor) ConstructorKind(com.github.anba.es6draft.runtime.types.builtins.FunctionObject.ConstructorKind)

Example 3 with OrdinaryConstructorFunction

use of com.github.anba.es6draft.runtime.types.builtins.OrdinaryConstructorFunction in project es6draft by anba.

the class FunctionOperations method InstantiateFunctionObject.

/**
 * 14.1 Function Definitions
 * <p>
 * 14.1.20 Runtime Semantics: InstantiateFunctionObject
 *
 * @param scope
 *            the current lexical scope
 * @param cx
 *            the execution context
 * @param fd
 *            the function runtime info object
 * @return the new function instance
 */
public static OrdinaryConstructorFunction InstantiateFunctionObject(LexicalEnvironment<?> scope, ExecutionContext cx, RuntimeInfo.Function fd) {
    /* step 1 (not applicable) */
    /* step 2 */
    String name = fd.functionName();
    /* step 3 */
    OrdinaryConstructorFunction f = ConstructorFunctionCreate(cx, FunctionKind.Normal, fd, scope);
    /* step 4 */
    MakeConstructor(cx, f);
    /* step 4 */
    SetFunctionName(f, name);
    /* step 6 */
    return f;
}
Also used : OrdinaryConstructorFunction(com.github.anba.es6draft.runtime.types.builtins.OrdinaryConstructorFunction)

Example 4 with OrdinaryConstructorFunction

use of com.github.anba.es6draft.runtime.types.builtins.OrdinaryConstructorFunction in project es6draft by anba.

the class FunctionConstructor method CreateDynamicFunction.

/**
 * 19.2.1.1.1 RuntimeSemantics: CreateDynamicFunction(constructor, newTarget, kind, args)
 *
 * @param cx
 *            the execution context
 * @param kind
 *            the function kind
 * @param compiledFunction
 *            the compiled function
 * @param proto
 *            the function prototype
 * @return the new function object
 */
public static FunctionObject CreateDynamicFunction(ExecutionContext cx, SourceKind kind, CompiledFunction compiledFunction, ScriptObject proto) {
    RuntimeInfo.Function function = compiledFunction.getFunction();
    /* step 18 */
    boolean strict = function.isStrict();
    /* step 30 */
    ObjectAllocator<? extends FunctionObject> allocator;
    switch(kind) {
        case AsyncFunction:
            allocator = OrdinaryAsyncFunction::new;
            break;
        case AsyncGenerator:
            allocator = OrdinaryAsyncGenerator::new;
            break;
        case Function:
            if (function.is(RuntimeInfo.FunctionFlags.Legacy)) {
                assert !strict;
                allocator = LegacyConstructorFunction::new;
            } else {
                allocator = OrdinaryConstructorFunction::new;
            }
            break;
        case Generator:
            allocator = OrdinaryGenerator::new;
            break;
        default:
            throw new AssertionError();
    }
    FunctionObject f = FunctionAllocate(cx, allocator, proto, strict, FunctionKind.Normal);
    /* steps 31-32 */
    LexicalEnvironment<GlobalEnvironmentRecord> scope = f.getRealm().getGlobalEnv();
    /* step 33 */
    FunctionInitialize(f, FunctionKind.Normal, function, scope, compiledFunction);
    /* steps 34-36 */
    switch(kind) {
        case AsyncFunction:
            /* step 36 */
            break;
        case AsyncGenerator:
            {
                OrdinaryObject prototype = ObjectCreate(cx, Intrinsics.AsyncGeneratorPrototype);
                f.infallibleDefineOwnProperty("prototype", new Property(prototype, true, false, false));
                break;
            }
        case Function:
            /* step 35 */
            if (f instanceof LegacyConstructorFunction) {
                MakeConstructor(cx, (LegacyConstructorFunction) f);
            } else {
                MakeConstructor(cx, (OrdinaryConstructorFunction) f);
            }
            break;
        case Generator:
            {
                /* step 34 */
                OrdinaryObject prototype = ObjectCreate(cx, Intrinsics.GeneratorPrototype);
                f.infallibleDefineOwnProperty("prototype", new Property(prototype, true, false, false));
                break;
            }
        default:
            throw new AssertionError();
    }
    /* step 37 */
    SetFunctionName(f, "anonymous");
    /* step 38 */
    return f;
}
Also used : RuntimeInfo(com.github.anba.es6draft.runtime.internal.RuntimeInfo) GlobalEnvironmentRecord(com.github.anba.es6draft.runtime.GlobalEnvironmentRecord) FunctionObject(com.github.anba.es6draft.runtime.types.builtins.FunctionObject) OrdinaryConstructorFunction(com.github.anba.es6draft.runtime.types.builtins.OrdinaryConstructorFunction) OrdinaryAsyncGenerator(com.github.anba.es6draft.runtime.types.builtins.OrdinaryAsyncGenerator) OrdinaryGenerator(com.github.anba.es6draft.runtime.types.builtins.OrdinaryGenerator) OrdinaryObject(com.github.anba.es6draft.runtime.types.builtins.OrdinaryObject) OrdinaryAsyncFunction(com.github.anba.es6draft.runtime.types.builtins.OrdinaryAsyncFunction) Property(com.github.anba.es6draft.runtime.types.Property) LegacyConstructorFunction(com.github.anba.es6draft.runtime.types.builtins.LegacyConstructorFunction)

Example 5 with OrdinaryConstructorFunction

use of com.github.anba.es6draft.runtime.types.builtins.OrdinaryConstructorFunction in project es6draft by anba.

the class DefaultCodeGenerator method ClassDefinitionEvaluation.

/**
 * 14.5.14 Runtime Semantics: ClassDefinitionEvaluation
 *
 * @param def
 *            the class definition node
 * @param className
 *            the class name or {@code null} if not present
 * @param mv
 *            the code visitor
 */
protected final void ClassDefinitionEvaluation(ClassDefinition def, Name className, CodeVisitor mv) {
    mv.enterVariableScope();
    List<Expression> classDecoratorsList = def.getDecorators();
    Variable<Callable[]> classDecorators = null;
    if (!classDecoratorsList.isEmpty()) {
        classDecorators = mv.newVariable("classDecorators", Callable[].class);
        mv.anewarray(classDecoratorsList.size(), Types.Callable);
        mv.store(classDecorators);
        int index = 0;
        for (Expression decorator : classDecoratorsList) {
            mv.astore(classDecorators, index++, __ -> {
                expressionBoxed(decorator, mv);
                CheckCallable(decorator, mv);
            });
        }
    }
    mv.enterClassDefinition();
    // step 1 (not applicable)
    // steps 2-4
    BlockScope scope = def.getScope();
    Variable<DeclarativeEnvironmentRecord> classScopeEnvRec = null;
    if (scope != null) {
        assert scope.isPresent() == (className != null);
        if (scope.isPresent()) {
            // stack: [] -> [classScope]
            newDeclarativeEnvironment(scope, mv);
            classScopeEnvRec = mv.newVariable("classScopeEnvRec", DeclarativeEnvironmentRecord.class);
            getEnvRec(classScopeEnvRec, mv);
            if (className != null) {
                // stack: [classScope] -> [classScope]
                Name innerName = scope.resolveName(className);
                BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(classScopeEnvRec, innerName);
                op.createImmutableBinding(classScopeEnvRec, innerName, true, mv);
            }
            // stack: [classScope] -> []
            pushLexicalEnvironment(mv);
        }
        mv.enterScope(def);
    }
    // steps 5-7
    // stack: [] -> [<constructorParent,proto>]
    Expression classHeritage = def.getHeritage();
    if (classHeritage == null) {
        mv.loadExecutionContext();
        mv.invoke(Methods.ClassOperations_getDefaultClassProto);
    } else if (classHeritage instanceof NullLiteral) {
        mv.loadExecutionContext();
        mv.invoke(Methods.ClassOperations_getClassProto_Null);
    } else {
        expressionBoxed(classHeritage, mv);
        mv.loadExecutionContext();
        mv.lineInfo(def);
        mv.invoke(Methods.ClassOperations_getClassProto);
    }
    // stack: [<protoParent,constructorParent>] -> [<protoParent,constructorParent>]
    Variable<OrdinaryObject> proto = mv.newVariable("proto", OrdinaryObject.class);
    mv.dup();
    mv.aload(0, Types.ScriptObject);
    mv.loadExecutionContext();
    mv.invoke(Methods.ClassOperations_createProto);
    mv.store(proto);
    // stack: [<protoParent,constructorParent>] -> [constructorParent, proto]
    mv.aload(1, Types.ScriptObject);
    mv.load(proto);
    // Push the private-name environment to ensure private names are accessible in the constructor.
    BlockScope bodyScope = def.getBodyScope();
    if (bodyScope != null) {
        List<Name> privateBoundNames = PrivateBoundNames(def);
        assert bodyScope.isPresent() == !privateBoundNames.isEmpty();
        if (bodyScope.isPresent()) {
            // stack: [] -> [classPrivateEnv]
            newDeclarativeEnvironment(bodyScope, mv);
            Variable<DeclarativeEnvironmentRecord> classPrivateEnvRec = mv.newVariable("classPrivateEnvRec", DeclarativeEnvironmentRecord.class);
            getEnvRec(classPrivateEnvRec, mv);
            HashSet<Name> declaredPrivateNames = new HashSet<>();
            for (Name name : privateBoundNames) {
                // FIXME: spec bug - missing check for already declared private names for getter/setter pairs
                if (declaredPrivateNames.add(name)) {
                    BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(classPrivateEnvRec, name);
                    op.createImmutableBinding(classPrivateEnvRec, name, true, mv);
                }
            }
            // stack: [classPrivateEnv] -> []
            pushLexicalEnvironment(mv);
        }
        mv.enterScope(bodyScope);
    }
    // steps 8-9
    // stack: [constructorParent, proto] -> [constructorParent, proto, <rti>]
    MethodName method = mv.compile(def, codegen::classDefinition);
    // Runtime Semantics: Evaluation -> MethodDefinition
    mv.invoke(method);
    // step 10 (not applicable)
    // steps 11-18
    // stack: [constructorParent, proto, <rti>] -> [F]
    mv.iconst(classHeritage != null);
    mv.loadExecutionContext();
    mv.lineInfo(def);
    mv.invoke(Methods.ClassOperations_EvaluateConstructorMethod);
    // stack: [F] -> []
    Variable<OrdinaryConstructorFunction> F = mv.newVariable("F", OrdinaryConstructorFunction.class);
    mv.store(F);
    // steps 19-21
    ClassPropertyGenerator.Result result = ClassPropertyEvaluation(codegen, def, F, proto, mv);
    Variable<Object[]> methodDecorators = result.methodDecorators;
    if (!classDecoratorsList.isEmpty()) {
        int index = 0;
        for (Expression decorator : classDecoratorsList) {
            mv.aload(classDecorators, index++, Types.Callable);
            invokeDynamicCall(mv, decorator, mv.executionContext(), mv.undefinedValue(), F);
            mv.pop();
        }
    }
    if (methodDecorators != null) {
        LabelledHashKey hashKey = new LabelledHashKey(def, "decorators");
        MethodName decoratorsMethod = mv.compile(hashKey, () -> classMethodDecorators(def, mv));
        // 0 = hint for stacktraces to omit this frame
        mv.lineInfo(0);
        mv.invoke(decoratorsMethod, mv.executionContext(), F, proto, methodDecorators);
    }
    if (scope != null) {
        // steps 22-23 (moved)
        if (className != null) {
            // stack: [] -> []
            Name innerName = scope.resolveName(className);
            BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(classScopeEnvRec, innerName);
            op.initializeBinding(classScopeEnvRec, innerName, F, mv);
        }
    }
    if (result.instanceClassField != null || result.instanceClassMethods != null) {
        MethodName initializer = compileClassFieldInitializer(def, MethodDefinition.MethodAllocation.Prototype, mv);
        // stack: [] -> [F]
        mv.load(F);
        // stack: [F] -> [F, initializer]
        mv.load(proto);
        mv.invoke(initializer);
        if (result.instanceClassField != null) {
            mv.load(result.instanceClassField);
        } else {
            mv.anull();
        }
        if (result.instanceClassMethods != null) {
            mv.load(result.instanceClassMethods);
        } else {
            mv.anull();
        }
        mv.loadExecutionContext();
        mv.invoke(Methods.ClassOperations_CreateClassFieldInitializer);
        // stack: [F, initializer] -> []
        mv.invoke(Methods.ClassOperations_setInstanceFieldsInitializer);
    }
    // Class fields: Call InitializeStaticFields.
    if (result.staticClassField != null) {
        MethodName initializer = compileClassFieldInitializer(def, MethodDefinition.MethodAllocation.Class, mv);
        // stack: [] -> [staticInitializer]
        mv.load(F);
        mv.invoke(initializer);
        mv.load(result.staticClassField);
        mv.loadExecutionContext();
        mv.invoke(Methods.ClassOperations_CreateStaticClassFieldInitializer);
        // stack: [staticInitializer] -> []
        invokeDynamicCall(mv, def, mv.executionContext(), F);
        mv.pop(ValType.Any);
    }
    if (bodyScope != null) {
        mv.exitScope();
        if (bodyScope.isPresent()) {
            popLexicalEnvironment(mv);
        }
    }
    if (scope != null) {
        mv.exitScope();
        if (scope.isPresent()) {
            popLexicalEnvironment(mv);
        }
    }
    // stack: [] -> [F]
    mv.load(F);
    mv.exitVariableScope();
    // step 24 (return F)
    mv.exitClassDefinition();
}
Also used : Name(com.github.anba.es6draft.ast.scope.Name) OrdinaryConstructorFunction(com.github.anba.es6draft.runtime.types.builtins.OrdinaryConstructorFunction) BlockScope(com.github.anba.es6draft.ast.scope.BlockScope) OrdinaryObject(com.github.anba.es6draft.runtime.types.builtins.OrdinaryObject) LabelledHashKey(com.github.anba.es6draft.compiler.CodeVisitor.LabelledHashKey) DeclarativeEnvironmentRecord(com.github.anba.es6draft.runtime.DeclarativeEnvironmentRecord) HashSet(java.util.HashSet)

Aggregations

OrdinaryConstructorFunction (com.github.anba.es6draft.runtime.types.builtins.OrdinaryConstructorFunction)10 OrdinaryObject (com.github.anba.es6draft.runtime.types.builtins.OrdinaryObject)6 MethodCode (com.github.anba.es6draft.compiler.assembler.Code.MethodCode)3 DeclarativeEnvironmentRecord (com.github.anba.es6draft.runtime.DeclarativeEnvironmentRecord)2 PropertyDescriptor (com.github.anba.es6draft.runtime.types.PropertyDescriptor)2 AccessorPropertyDescriptor (com.github.anba.es6draft.runtime.types.PropertyDescriptor.AccessorPropertyDescriptor)2 ScriptObject (com.github.anba.es6draft.runtime.types.ScriptObject)2 FunctionObject (com.github.anba.es6draft.runtime.types.builtins.FunctionObject)2 BlockScope (com.github.anba.es6draft.ast.scope.BlockScope)1 Name (com.github.anba.es6draft.ast.scope.Name)1 LabelledHashKey (com.github.anba.es6draft.compiler.CodeVisitor.LabelledHashKey)1 MethodTypeDescriptor (com.github.anba.es6draft.compiler.assembler.MethodTypeDescriptor)1 EnvironmentRecord (com.github.anba.es6draft.runtime.EnvironmentRecord)1 ExecutionContext (com.github.anba.es6draft.runtime.ExecutionContext)1 FunctionEnvironmentRecord (com.github.anba.es6draft.runtime.FunctionEnvironmentRecord)1 GlobalEnvironmentRecord (com.github.anba.es6draft.runtime.GlobalEnvironmentRecord)1 RuntimeInfo (com.github.anba.es6draft.runtime.internal.RuntimeInfo)1 InstanceMethod (com.github.anba.es6draft.runtime.language.ClassOperations.InstanceMethod)1 Property (com.github.anba.es6draft.runtime.types.Property)1 BuiltinFunction (com.github.anba.es6draft.runtime.types.builtins.BuiltinFunction)1