Skip to content

Commit cf1a945

Browse files
committed
address remarks from review, add tests
1 parent 77034bc commit cf1a945

File tree

2 files changed

+67
-12
lines changed

2 files changed

+67
-12
lines changed

graal-js/src/com.oracle.truffle.js.test/src/com/oracle/truffle/js/test/interop/ForeignObjectPrototypeTest.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,46 @@ private static boolean testInstanceofIntl(String prototype, Object obj) {
235235
}
236236
}
237237

238+
@Test
239+
public void testForeignRightPrototype() {
240+
String code = "ForeignObjectPrototype = Object.getPrototypeOf(new java.lang.Object());\n" +
241+
"function f() {}; \n" +
242+
"f.prototype = ForeignObjectPrototype;\n" +
243+
"new java.lang.Object() instanceof f;";
244+
testTrue(code);
245+
}
246+
247+
private static void testTrue(String code) {
248+
Assert.assertTrue(testIntl(code));
249+
}
250+
251+
private static void testFalse(String code) {
252+
Assert.assertFalse(testIntl(code));
253+
}
254+
255+
private static boolean testIntl(String code) {
256+
try (Context context = JSTest.newContextBuilder(ID).allowAllAccess(true).allowHostAccess(HostAccess.ALL).build()) {
257+
Value result = context.eval(ID, code);
258+
return result.asBoolean();
259+
}
260+
}
261+
262+
@Test
263+
public void testCallableProxies() {
264+
String code = "new java.lang.Object instanceof new Proxy(Object, {});";
265+
testTrue(code);
266+
267+
code = "var handler = { get(target, prop, recv) { return (prop === 'prototype') ? Object.prototype : Reflect.get(target, prop, recv); } };\n" +
268+
"var proxy = new Proxy(function() {}, handler);\n" +
269+
"new java.lang.Object() instanceof proxy";
270+
testTrue(code);
271+
272+
code = "var handler = { get(target, prop, recv) { if (prop === 'prototype') { throw new Error() } else { return Reflect.get(target, prop, recv); } } };\n" +
273+
"var proxy = new Proxy(function() {}, handler);\n" +
274+
"42 instanceof proxy";
275+
testFalse(code);
276+
}
277+
238278
@ExportLibrary(InteropLibrary.class)
239279
public static class TestTruffleHash implements TruffleObject {
240280

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/binary/InstanceofNode.java

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -232,36 +232,51 @@ protected boolean doNotCallable(Object obj, Object check) {
232232

233233
@Specialization(guards = {"isJSFunction(check)", "isBoundFunction(check)"})
234234
protected boolean doIsBound(Object obj, JSDynamicObject check,
235-
@Cached("create(context)") @Shared("instanceofNode") InstanceofNode instanceofNode) {
235+
@Cached("create(context)") InstanceofNode instanceofNode) {
236236
JSDynamicObject boundTargetFunction = JSFunction.getBoundTargetFunction(check);
237237
return instanceofNode.executeBoolean(obj, boundTargetFunction);
238238
}
239239

240240
@Specialization(guards = {"!isJSObject(left)", "isForeignObject(left)", "isJSFunction(right)", "!isBoundFunction(right)"})
241241
protected boolean doForeignObject(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") JSDynamicObject right,
242-
@Cached ForeignObjectPrototypeNode getForeignPrototypeNode,
242+
@Cached @Shared("foreignPrototypeNode") ForeignObjectPrototypeNode getForeignPrototypeNode,
243243
@Cached @Shared("invalidPrototypeBranch") BranchProfile invalidPrototypeBranch,
244-
@Cached("create(context)") @Shared("instanceofNode") InstanceofNode instanceofNode) {
244+
@Cached("create(context)") @Shared("ordinaryHasInstance") OrdinaryHasInstanceNode ordinaryHasInstanceNode) {
245245
if (context.isOptionForeignObjectPrototype()) {
246-
Object rightProto = getConstructorPrototype(right, invalidPrototypeBranch);
247-
if (rightProto == getRealm().getDatePrototype()) {
248-
// necessary because of GR-39319
249-
return false;
250-
}
251-
Object foreignProto = getForeignPrototypeNode.execute(left);
252-
return instanceofNode.executeBoolean(foreignProto, right);
246+
return foreignObjectIntl(left, right, getForeignPrototypeNode, invalidPrototypeBranch, ordinaryHasInstanceNode);
253247
} else {
254248
return false;
255249
}
256250
}
257251

252+
private boolean foreignObjectIntl(Object left, JSDynamicObject right, ForeignObjectPrototypeNode getForeignPrototypeNode, BranchProfile invalidPrototypeBranch,
253+
OrdinaryHasInstanceNode ordinaryHasInstanceNode) {
254+
Object rightProto = getConstructorPrototype(right, invalidPrototypeBranch);
255+
if (rightProto == getRealm().getDatePrototype()) {
256+
// necessary because of GR-39319
257+
return false;
258+
}
259+
Object foreignProto = getForeignPrototypeNode.execute(left);
260+
if (foreignProto == rightProto) {
261+
return true;
262+
}
263+
return ordinaryHasInstanceNode.executeBoolean(foreignProto, right);
264+
}
265+
258266
@Specialization(guards = {"!isJSObject(left)", "!isForeignObject(left)", "isJSFunction(right)", "!isBoundFunction(right)"})
259267
protected boolean doNotAnObject(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") JSDynamicObject right) {
260268
return false;
261269
}
262270

263-
@Specialization(guards = {"!isJSObject(left)", "isJSProxy(right)", "isCallableProxy(right)"})
264-
protected boolean doNotAnObjectProxy(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") JSDynamicObject right) {
271+
@Specialization(guards = {"!isJSObject(left)", "isForeignObject(left)", "isJSProxy(right)", "isCallableProxy(right)"})
272+
protected boolean doNotAnObjectProxyForeign(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") JSDynamicObject right,
273+
@Cached @Shared("foreignPrototypeNode") ForeignObjectPrototypeNode getForeignPrototypeNode, @Cached @Shared("invalidPrototypeBranch") BranchProfile invalidPrototypeBranch,
274+
@Cached("create(context)") @Shared("ordinaryHasInstance") OrdinaryHasInstanceNode ordinaryHasInstanceNode) {
275+
return doForeignObject(left, right, getForeignPrototypeNode, invalidPrototypeBranch, ordinaryHasInstanceNode);
276+
}
277+
278+
@Specialization(guards = {"!isJSObject(left)", "!isForeignObject(left)", "isJSProxy(right)", "isCallableProxy(right)"})
279+
protected boolean doNotAnObjectProxyPrimitive(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") JSDynamicObject right) {
265280
return false;
266281
}
267282

0 commit comments

Comments
 (0)