package com.oracle.truffle.js.nodes.promise;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.js.nodes.JavaScriptBaseNode;
import com.oracle.truffle.js.nodes.access.PropertyGetNode;
import com.oracle.truffle.js.runtime.Errors;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.UserScriptException;
import com.oracle.truffle.js.runtime.builtins.JSPromise;
import com.oracle.truffle.js.runtime.objects.JSDynamicObject;
@ImportStatic(JSPromise.class)
public abstract class UnwrapPromiseNode extends JavaScriptBaseNode {
@Child private PropertyGetNode getPromiseResult;
private static final UnwrapPromiseNode UNCACHED = create(null);
protected UnwrapPromiseNode(JSContext context) {
if (context != null) {
this.getPromiseResult = PropertyGetNode.createGetHidden(JSPromise.PROMISE_RESULT, context);
}
}
public static UnwrapPromiseNode create(JSContext context) {
return UnwrapPromiseNodeGen.create(context);
}
public final Object execute(DynamicObject promise) {
if (getPromiseResult == null) {
return doUncached(promise);
}
int promiseState = JSPromise.getPromiseState(promise);
Object promiseResult = getPromiseResult.getValue(promise);
return execute(promise, promiseState, promiseResult);
}
@TruffleBoundary
private Object doUncached(DynamicObject promise) {
return execute(promise, JSPromise.getPromiseState(promise), JSDynamicObject.getOrNull(promise, JSPromise.PROMISE_RESULT));
}
protected abstract Object execute(DynamicObject promise, int promiseState, Object promiseResult);
@SuppressWarnings("unused")
@Specialization(guards = "promiseState == FULFILLED")
protected static Object fulfilled(DynamicObject promise, int promiseState, Object promiseResult) {
return promiseResult;
}
@SuppressWarnings("unused")
@Specialization(guards = "promiseState == REJECTED")
protected static Object rejected(DynamicObject promise, int promiseState, Object promiseResult) {
throw UserScriptException.create(promiseResult);
}
@SuppressWarnings("unused")
@Specialization(guards = "promiseState == PENDING")
protected static Object pending(DynamicObject promise, int promiseState, Object promiseResult) {
throw Errors.createTypeError("Attempt to unwrap pending promise");
}
public static UnwrapPromiseNode getUncached() {
return UNCACHED;
}
}