/**
* Copyright (c) 2012-2016 André Bargull
* Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms.
*
* <https://github.com/anba/es6draft>
*/
package com.github.anba.es6draft.runtime.types.builtins;
import static com.github.anba.es6draft.runtime.types.builtins.OrdinaryFunction.FunctionInitialize;
import com.github.anba.es6draft.runtime.ExecutionContext;
import com.github.anba.es6draft.runtime.LexicalEnvironment;
import com.github.anba.es6draft.runtime.Realm;
import com.github.anba.es6draft.runtime.internal.RuntimeInfo;
import com.github.anba.es6draft.runtime.types.Constructor;
import com.github.anba.es6draft.runtime.types.Intrinsics;
import com.github.anba.es6draft.runtime.types.ScriptObject;
/**
* <h1>9 Ordinary and Exotic Objects Behaviours</h1>
* <ul>
* <li>9.2 ECMAScript Function Objects
* </ul>
*/
public final class OrdinaryConstructorFunction extends FunctionObject implements Constructor {
/**
* Constructs a new Constructor Function object.
*
* @param realm
* the realm object
*/
public OrdinaryConstructorFunction(Realm realm) {
super(realm);
}
@Override
protected OrdinaryConstructorFunction allocateNew() {
return FunctionAllocate(getRealm().defaultContext(), getPrototype(), isStrict(), getFunctionKind(),
getConstructorKind());
}
/**
* 9.2.1 [[Call]] (thisArgument, argumentsList)
*/
@Override
public Object call(ExecutionContext callerContext, Object thisValue, Object... argumentsList) {
try {
return getCallMethod().invokeExact(this, callerContext, thisValue, argumentsList);
} catch (Throwable e) {
throw FunctionObject.<RuntimeException> rethrow(e);
}
}
/**
* 9.2.1 [[Call]] (thisArgument, argumentsList)
*/
@Override
public Object tailCall(ExecutionContext callerContext, Object thisValue, Object... argumentsList) throws Throwable {
return getTailCallMethod().invokeExact(this, callerContext, thisValue, argumentsList);
}
/**
* 9.2.2 [[Construct]] (argumentsList)
*/
@Override
public ScriptObject construct(ExecutionContext callerContext, Constructor newTarget, Object... argumentsList) {
try {
return (ScriptObject) getConstructMethod().invokeExact(this, callerContext, newTarget, argumentsList);
} catch (Throwable e) {
throw FunctionObject.<RuntimeException> rethrow(e);
}
}
/* ***************************************************************************************** */
/**
* 9.2.3 FunctionAllocate (functionPrototype, strict [,functionKind] )
*
* @param cx
* the execution context
* @param functionPrototype
* the function prototype
* @param strict
* the strict mode flag
* @param functionKind
* the function kind
* @param constructorKind
* the constructor kind
* @return the new function object
*/
public static OrdinaryConstructorFunction FunctionAllocate(ExecutionContext cx, ScriptObject functionPrototype,
boolean strict, FunctionKind functionKind, ConstructorKind constructorKind) {
assert (functionKind == FunctionKind.Normal || functionKind == FunctionKind.ClassConstructor);
Realm realm = cx.getRealm();
/* steps 1-5 (implicit) */
/* steps 6-9 */
OrdinaryConstructorFunction f = new OrdinaryConstructorFunction(realm);
/* steps 10-14 */
f.allocate(realm, functionPrototype, strict, functionKind, constructorKind);
/* step 15 */
return f;
}
/**
* 9.2.5 FunctionCreate (kind, ParameterList, Body, Scope, Strict)
*
* @param cx
* the execution context
* @param kind
* the function kind
* @param function
* the function code
* @param scope
* the lexical environment
* @return the new function object
*/
public static OrdinaryConstructorFunction ConstructorFunctionCreate(ExecutionContext cx, FunctionKind kind,
RuntimeInfo.Function function, LexicalEnvironment<?> scope) {
/* step 1 */
ScriptObject prototype = cx.getIntrinsic(Intrinsics.FunctionPrototype);
/* steps 2-5 */
return ConstructorFunctionCreate(cx, kind, ConstructorKind.Base, function, scope, prototype);
}
/**
* 9.2.5 FunctionCreate (kind, ParameterList, Body, Scope, Strict, prototype)
*
* @param cx
* the execution context
* @param kind
* the function kind
* @param function
* the function code
* @param constructorKind
* the constructor kind
* @param scope
* the lexical environment
* @param prototype
* the function prototype
* @return the new function object
*/
public static OrdinaryConstructorFunction ConstructorFunctionCreate(ExecutionContext cx, FunctionKind kind,
ConstructorKind constructorKind, RuntimeInfo.Function function, LexicalEnvironment<?> scope,
ScriptObject prototype) {
assert !function.isGenerator() && !function.isAsync();
/* steps 1-3 (not applicable) */
/* step 4 */
OrdinaryConstructorFunction f = FunctionAllocate(cx, prototype, function.isStrict(), kind, constructorKind);
/* step 5 */
FunctionInitialize(f, kind, function, scope, cx.getCurrentExecutable());
return f;
}
}