/** * 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 java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import com.github.anba.es6draft.runtime.ExecutionContext; import com.github.anba.es6draft.runtime.Realm; import com.github.anba.es6draft.runtime.types.Constructor; import com.github.anba.es6draft.runtime.types.ScriptObject; /** * <h1>9 Ordinary and Exotic Objects Behaviours</h1> * <ul> * <li>9.3 Built-in Function Objects * </ul> */ public final class NativeConstructor extends BuiltinConstructor { // (ExecutionContext, Object, Object[]) -> Object private final MethodHandle callMethod; // (ExecutionContext, Constructor, Object[]) -> Object private final MethodHandle constructMethod; /** * Constructs a new native constructor function. * * @param realm * the realm object * @param name * the function name * @param arity * the function arity * @param callMethod * the method handle to the function call code * @param constructMethod * the method handle to the function construct code */ public NativeConstructor(Realm realm, String name, int arity, MethodHandle callMethod, MethodHandle constructMethod) { super(realm, name, arity); this.callMethod = callMethod; this.constructMethod = constructMethod; createDefaultFunctionProperties(); } private NativeConstructor(NativeConstructor original) { super(original.getRealm(), original.getName(), original.getArity()); this.callMethod = original.callMethod; this.constructMethod = original.constructMethod; } @Override public NativeConstructor clone() { return new NativeConstructor(this); } @Override public MethodHandle getCallMethod() { return MethodHandles.dropArguments(callMethod, 0, NativeConstructor.class); } @Override public MethodHandle getConstructMethod() { return MethodHandles.dropArguments(callMethod, 0, NativeConstructor.class); } /** * 9.3.1 [[Call]] (thisArgument, argumentsList) */ @Override public Object call(ExecutionContext callerContext, Object thisValue, Object... args) { try { return callMethod.invokeExact(callerContext, thisValue, args); } catch (Throwable e) { throw NativeConstructor.<RuntimeException> rethrow(e); } } /** * 9.3.2 [[Construct]] (argumentsList, newTarget) */ @Override public ScriptObject construct(ExecutionContext callerContext, Constructor newTarget, Object... args) { try { return (ScriptObject) constructMethod.invokeExact(callerContext, newTarget, args); } catch (Throwable e) { throw NativeConstructor.<RuntimeException> rethrow(e); } } @SuppressWarnings("unchecked") private static <E extends Throwable> E rethrow(Throwable e) throws E { throw (E) e; } }