Skip to content

Commit

Permalink
Implement Promise.try proposal.
Browse files Browse the repository at this point in the history
  • Loading branch information
woess committed Jun 12, 2024
1 parent 4814c88 commit e593be4
Showing 1 changed file with 50 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import com.oracle.truffle.api.exception.AbstractTruffleException;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.js.builtins.PromiseFunctionBuiltinsFactory.PromiseCombinatorNodeGen;
import com.oracle.truffle.js.builtins.PromiseFunctionBuiltinsFactory.PromiseTryNodeGen;
import com.oracle.truffle.js.builtins.PromiseFunctionBuiltinsFactory.RejectNodeGen;
import com.oracle.truffle.js.builtins.PromiseFunctionBuiltinsFactory.ResolveNodeGen;
import com.oracle.truffle.js.builtins.PromiseFunctionBuiltinsFactory.WithResolversNodeGen;
Expand Down Expand Up @@ -100,7 +101,9 @@ public enum PromiseFunction implements BuiltinEnum<PromiseFunction> {
allSettled(1),
any(1),

withResolvers(0);
withResolvers(0),

try_(1);

private final int length;

Expand All @@ -119,6 +122,7 @@ public int getECMAScriptVersion() {
case any -> JSConfig.ECMAScript2021;
case allSettled -> JSConfig.ECMAScript2020;
case withResolvers -> JSConfig.ECMAScript2024;
case try_ -> JSConfig.StagingECMAScriptVersion;
default -> JSConfig.ECMAScript2015;
};
}
Expand All @@ -141,6 +145,8 @@ protected Object createNode(JSContext context, JSBuiltin builtin, boolean constr
return ResolveNodeGen.create(context, builtin, args().withThis().fixedArgs(1).createArgumentNodes(context));
case withResolvers:
return WithResolversNodeGen.create(context, builtin, args().withThis().createArgumentNodes(context));
case try_:
return PromiseTryNodeGen.create(context, builtin, args().withThis().fixedArgs(1).varArgs().createArgumentNodes(context));
}
return null;
}
Expand Down Expand Up @@ -290,4 +296,47 @@ protected JSObject withResolvers(VirtualFrame frame, Object thiz) {
}

}

public abstract static class PromiseTryNode extends JSBuiltinNode {
@Child private NewPromiseCapabilityNode newPromiseCapabilityNode;
@Child private JSFunctionCallNode callCallbackFnNode;
@Child private JSFunctionCallNode callResolveNode;
@Child private JSFunctionCallNode callRejectNode;
@Child private TryCatchNode.GetErrorObjectNode getErrorObjectNode;

protected PromiseTryNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
this.newPromiseCapabilityNode = NewPromiseCapabilityNode.create(context);
this.callCallbackFnNode = JSFunctionCallNode.createCall();
this.callResolveNode = JSFunctionCallNode.createCall();
}

@Specialization
protected final Object doObject(JSObject constructor, Object callbackfn, Object[] args) {
PromiseCapabilityRecord promiseCapability = newPromiseCapabilityNode.execute(constructor);
try {
Object status = callCallbackFnNode.executeCall(JSArguments.create(Undefined.instance, callbackfn, args));
callResolveNode.executeCall(JSArguments.createOneArg(Undefined.instance, promiseCapability.getResolve(), status));
} catch (AbstractTruffleException ex) {
rejectPromise(ex, promiseCapability);
}
return promiseCapability.getPromise();
}

private void rejectPromise(AbstractTruffleException ex, PromiseCapabilityRecord promiseCapability) {
if (callRejectNode == null || getErrorObjectNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
callRejectNode = insert(JSFunctionCallNode.createCall());
getErrorObjectNode = insert(TryCatchNode.GetErrorObjectNode.create(getContext()));
}
Object error = getErrorObjectNode.execute(ex);
callRejectNode.executeCall(JSArguments.createOneArg(Undefined.instance, promiseCapability.getReject(), error));
}

@SuppressWarnings("unused")
@Specialization(guards = "!isJSObject(thisObj)")
protected static Object doNotObject(Object thisObj, Object callbackfn, Object[] args) {
throw Errors.createTypeError("Cannot create promise from this type");
}
}
}

0 comments on commit e593be4

Please sign in to comment.