Skip to content

Commit

Permalink
Fail earlier
Browse files Browse the repository at this point in the history
  • Loading branch information
Julian Garn committed Sep 14, 2022
1 parent 44a648f commit 0aa647e
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 2 deletions.
Expand Up @@ -76,7 +76,7 @@ public void testFrom() {
Context.Builder builder = JSTest.newContextBuilder();
builder.option(JSContextOptions.ITERATOR_HELPERS_NAME, "true");
try (Context context = builder.build()) {
Value result = context.eval(JavaScriptLanguage.ID, "AsyncIterator.from({[Symbol.asyncIterator]: async () => ({next: () => ({done: true})})})");
Value result = context.eval(JavaScriptLanguage.ID, "AsyncIterator.from({[Symbol.asyncIterator]: () => ({next: () => ({done: true})})})");
Assert.assertTrue(result.hasMembers());
Assert.assertTrue(result.hasMember("next"));
Assert.assertTrue(result.getMember("next").canExecute());
Expand All @@ -99,6 +99,13 @@ public void testFrom() {

result = context.eval(JavaScriptLanguage.ID, "var x = (async function* test(){})(); AsyncIterator.from(x) === x");
Assert.assertTrue(result.asBoolean());

try {
context.eval(JavaScriptLanguage.ID, "AsyncIterator.from({[Symbol.asyncIterator]: async () => ({next: () => ({done: true})})})");
Assert.fail("No exception thrown");
} catch (PolyglotException e) {
Assert.assertTrue(e.getMessage().startsWith("TypeError: "));
}
}
}
}
Expand Up @@ -91,6 +91,13 @@ public void testFrom() {

result = context.eval(JavaScriptLanguage.ID, "var x = [].values(); Iterator.from(x) === x");
Assert.assertTrue(result.asBoolean());

try {
context.eval(JavaScriptLanguage.ID, "Iterator.from({[Symbol.iterator]: async () => ({next: () => ({done: true})})})");
Assert.fail("No exception thrown");
} catch (PolyglotException e) {
Assert.assertTrue(e.getMessage().startsWith("TypeError: "));
}
}
}
}
Expand Up @@ -42,13 +42,16 @@

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.js.nodes.access.GetIteratorDirectNode;
import com.oracle.truffle.js.nodes.access.GetIteratorNode;
import com.oracle.truffle.js.nodes.access.GetMethodNode;
import com.oracle.truffle.js.nodes.binary.InstanceofNode.OrdinaryHasInstanceNode;
import com.oracle.truffle.js.nodes.function.JSBuiltin;
import com.oracle.truffle.js.nodes.function.JSBuiltinNode;
import com.oracle.truffle.js.nodes.unary.IsCallableNode;
import com.oracle.truffle.js.runtime.Errors;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.Symbol;
import com.oracle.truffle.js.runtime.builtins.BuiltinEnum;
Expand Down Expand Up @@ -98,8 +101,10 @@ public abstract static class JSAsyncIteratorFromNode extends JSBuiltinNode {

@Child private OrdinaryHasInstanceNode ordinaryHasInstanceNode;
@Child private GetIteratorDirectNode getIteratorDirectNode;
@Child private IsCallableNode isCallableNode;

private final ConditionProfile usingIteratorProfile = ConditionProfile.createBinaryProfile();
private final BranchProfile errorProfile = BranchProfile.create();

public JSAsyncIteratorFromNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
Expand All @@ -120,6 +125,16 @@ protected JSDynamicObject asyncIteratorFrom(Object arg) {

iteratorRecord = getIteratorNode.execute(arg);

if (isCallableNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
isCallableNode = insert(IsCallableNode.create());
}

if (!isCallableNode.executeBoolean(iteratorRecord.getNextMethod())) {
errorProfile.enter();
throw Errors.createTypeErrorCallableExpected();
}

if (ordinaryHasInstanceNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
ordinaryHasInstanceNode = insert(OrdinaryHasInstanceNode.create(getContext()));
Expand Down
Expand Up @@ -41,6 +41,7 @@
package com.oracle.truffle.js.builtins;

import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.js.builtins.IteratorFunctionBuiltinsFactory.JSIteratorFromNodeGen;
import com.oracle.truffle.js.nodes.access.GetIteratorDirectNode;
Expand All @@ -49,6 +50,8 @@
import com.oracle.truffle.js.nodes.binary.InstanceofNode.OrdinaryHasInstanceNode;
import com.oracle.truffle.js.nodes.function.JSBuiltin;
import com.oracle.truffle.js.nodes.function.JSBuiltinNode;
import com.oracle.truffle.js.nodes.unary.IsCallableNode;
import com.oracle.truffle.js.runtime.Errors;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.Symbol;
import com.oracle.truffle.js.runtime.builtins.BuiltinEnum;
Expand Down Expand Up @@ -99,25 +102,33 @@ public abstract static class JSIteratorFromNode extends JSBuiltinNode {
@Child private GetIteratorNode getIteratorNode;
@Child private GetIteratorDirectNode getIteratorDirectNode;
@Child private OrdinaryHasInstanceNode ordinaryHasInstanceNode;
@Child private IsCallableNode isCallableNode;

private final ConditionProfile usingIteratorProfile = ConditionProfile.createBinaryProfile();
private final BranchProfile errorProfile = BranchProfile.create();

public JSIteratorFromNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
this.getIteratorMethodNode = GetMethodNode.create(context, Symbol.SYMBOL_ITERATOR);
this.getIteratorNode = GetIteratorNode.create(getContext());
this.ordinaryHasInstanceNode = OrdinaryHasInstanceNode.create(getContext());
this.getIteratorDirectNode = GetIteratorDirectNode.create(getContext());
this.isCallableNode = IsCallableNode.create();
}


@Specialization
protected JSDynamicObject iteratorFrom(Object arg) {
IteratorRecord iteratorRecord = null;
IteratorRecord iteratorRecord;

Object usingIterator = getIteratorMethodNode.executeWithTarget(arg);
if (usingIteratorProfile.profile(usingIterator != Undefined.instance)) {
iteratorRecord = getIteratorNode.execute(arg);
if (!isCallableNode.executeBoolean(iteratorRecord.getNextMethod())) {
errorProfile.enter();
throw Errors.createTypeErrorCallableExpected();
}

boolean hasInstance = ordinaryHasInstanceNode.executeBoolean(iteratorRecord.getIterator(), getRealm().getIteratorConstructor());
if (hasInstance) {
return iteratorRecord.getIterator();
Expand Down

0 comments on commit 0aa647e

Please sign in to comment.