package com.oracle.truffle.js.nodes.promise;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.js.nodes.JavaScriptBaseNode;
import com.oracle.truffle.js.nodes.access.PropertyGetNode;
import com.oracle.truffle.js.nodes.access.PropertySetNode;
import com.oracle.truffle.js.runtime.GraalJSException;
import com.oracle.truffle.js.runtime.JSConfig;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.builtins.JSError;
import com.oracle.truffle.js.runtime.builtins.JSPromise;
import com.oracle.truffle.js.runtime.objects.Undefined;
public class RejectPromiseNode extends JavaScriptBaseNode {
private final JSContext context;
@Child private PropertyGetNode getPromiseRejectReactions;
@Child private PropertySetNode setPromiseResult;
@Child private PropertySetNode setPromiseFulfillReactions;
@Child private PropertySetNode setPromiseRejectReactions;
@Child private PropertyGetNode getPromiseIsHandled;
@Child private TriggerPromiseReactionsNode triggerPromiseReactions;
private final ConditionProfile unhandledProf = ConditionProfile.createBinaryProfile();
protected RejectPromiseNode(JSContext context) {
this.context = context;
this.getPromiseRejectReactions = PropertyGetNode.createGetHidden(JSPromise.PROMISE_REJECT_REACTIONS, context);
this.setPromiseResult = PropertySetNode.createSetHidden(JSPromise.PROMISE_RESULT, context);
this.setPromiseFulfillReactions = PropertySetNode.createSetHidden(JSPromise.PROMISE_FULFILL_REACTIONS, context);
this.setPromiseRejectReactions = PropertySetNode.createSetHidden(JSPromise.PROMISE_REJECT_REACTIONS, context);
this.getPromiseIsHandled = PropertyGetNode.createGetHidden(JSPromise.PROMISE_IS_HANDLED, context);
this.triggerPromiseReactions = TriggerPromiseReactionsNode.create(context);
}
public static RejectPromiseNode create(JSContext context) {
return new RejectPromiseNode(context);
}
public Object execute(DynamicObject promise, Object reason) {
assert JSPromise.isPending(promise);
if (!JSConfig.EagerStackTrace && context.isOptionAsyncStackTraces() && JSError.isJSError(reason)) {
materializeLazyStackTrace((DynamicObject) reason);
}
Object reactions = getPromiseRejectReactions.getValue(promise);
setPromiseResult.setValue(promise, reason);
setPromiseFulfillReactions.setValue(promise, Undefined.instance);
setPromiseRejectReactions.setValue(promise, Undefined.instance);
JSPromise.setPromiseState(promise, JSPromise.REJECTED);
if (unhandledProf.profile(getPromiseIsHandled.getValue(promise) != Boolean.TRUE)) {
context.notifyPromiseRejectionTracker(promise, JSPromise.REJECTION_TRACKER_OPERATION_REJECT, reason);
}
return triggerPromiseReactions.execute(reactions, reason);
}
@TruffleBoundary
private static void materializeLazyStackTrace(DynamicObject error) {
assert JSError.isJSError(error);
GraalJSException exception = JSError.getException(error);
if (exception != null) {
exception.getJSStackTrace();
}
}
}