Skip to content

Commit 7db2823

Browse files
committed
[GR-52840] Backport to 24.0: Instanceof operator should check whether the left side is a (foreign) object.
PullRequest: js/3102
2 parents c103057 + 9894a42 commit 7db2823

File tree

4 files changed

+35
-11
lines changed

4 files changed

+35
-11
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl.
6+
*/
7+
8+
load("assert.js");
9+
10+
var javaNull = new java.util.ArrayDeque().peek();
11+
12+
assertFalse(javaNull instanceof Object);
13+
assertFalse(javaNull instanceof new Proxy(Object, {}));

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -41,8 +41,9 @@
4141
package com.oracle.truffle.js.test.interop;
4242

4343
import static com.oracle.truffle.js.lang.JavaScriptLanguage.ID;
44-
import static org.junit.Assert.assertTrue;
4544
import static org.junit.Assert.assertEquals;
45+
import static org.junit.Assert.assertFalse;
46+
import static org.junit.Assert.assertTrue;
4647

4748
import org.graalvm.polyglot.Context;
4849
import org.junit.Test;
@@ -62,6 +63,7 @@ public void testForeignNull() {
6263
assertTrue(context.eval(ID, "Object.getPrototypeOf(Object.create(obj)) === null").asBoolean());
6364
assertTrue(context.eval(ID, "try { obj.foo; false; } catch (e) { e instanceof TypeError }").asBoolean());
6465
assertTrue(context.eval(ID, "try { obj.foo(); false; } catch (e) { e instanceof TypeError }").asBoolean());
66+
assertFalse(context.eval(ID, "obj instanceof Object").asBoolean());
6567
}
6668
}
6769

@@ -76,6 +78,7 @@ public void testForeignBoxedString() {
7678
assertEquals("foo", context.eval(ID, "obj.valueOf()").asString());
7779
assertEquals("foo", context.eval(ID, "obj['valueOf']()").asString());
7880
assertTrue(context.eval(ID, "obj.includes('o')").asBoolean());
81+
assertFalse(context.eval(ID, "obj instanceof Object").asBoolean());
7982
}
8083
}
8184

@@ -95,6 +98,7 @@ public void testForeignBoxedNumber() {
9598
assertEquals("42", context.eval(ID, "obj.toString()").asString());
9699
assertEquals(42, context.eval(ID, "obj.valueOf()").asInt());
97100
assertEquals(42, context.eval(ID, "obj['valueOf']()").asInt());
101+
assertFalse(context.eval(ID, "obj instanceof Object").asBoolean());
98102
}
99103
}
100104

@@ -108,6 +112,7 @@ public void testForeignBoxedBoolean() {
108112
assertTrue(context.eval(ID, "obj.valueOf()").asBoolean());
109113
assertTrue(context.eval(ID, "obj['valueOf']()").asBoolean());
110114
assertEquals("true", context.eval(ID, "obj.toString()").asString());
115+
assertFalse(context.eval(ID, "obj instanceof Object").asBoolean());
111116
}
112117
}
113118

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -211,9 +211,9 @@ public void testForeignInstanceof() {
211211
Assert.assertTrue(testInstanceofIntl("Array", ProxyArray.fromArray("fun", "with", "proxy", "array")));
212212
Assert.assertTrue(testInstanceofIntl("Date", Instant.now()));
213213
Assert.assertTrue(testInstanceofIntl("Map", new TestTruffleHash()));
214-
Assert.assertTrue(testInstanceofIntl("String", new TestTruffleString()));
215-
Assert.assertTrue(testInstanceofIntl("Boolean", new TestTruffleBoolean()));
216-
Assert.assertTrue(testInstanceofIntl("Number", new TestTruffleNumber()));
214+
Assert.assertFalse(testInstanceofIntl("String", new TestTruffleString()));
215+
Assert.assertFalse(testInstanceofIntl("Boolean", new TestTruffleBoolean()));
216+
Assert.assertFalse(testInstanceofIntl("Number", new TestTruffleNumber()));
217217
Assert.assertTrue(testInstanceofIntl("Function", (ProxyExecutable) v -> true));
218218
Assert.assertTrue(testInstanceofIntl("Object", new Object()));
219219

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -67,6 +67,7 @@
6767
import com.oracle.truffle.js.nodes.access.GetMethodNode;
6868
import com.oracle.truffle.js.nodes.access.GetPrototypeNode;
6969
import com.oracle.truffle.js.nodes.access.IsJSObjectNode;
70+
import com.oracle.truffle.js.nodes.access.IsObjectNode;
7071
import com.oracle.truffle.js.nodes.access.PropertyGetNode;
7172
import com.oracle.truffle.js.nodes.binary.InstanceofNodeGen.IsBoundFunctionCacheNodeGen;
7273
import com.oracle.truffle.js.nodes.binary.InstanceofNodeGen.OrdinaryHasInstanceNodeGen;
@@ -249,18 +250,22 @@ protected boolean doIsBound(Object obj, JSDynamicObject check,
249250

250251
@Specialization(guards = {"!isJSObject(left)", "isForeignObject(left)", "isJSFunction(right)", "!isBoundFunction(right)"})
251252
protected boolean doForeignObject(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") JSDynamicObject right,
253+
@Cached @Shared IsObjectNode isAnyObjectNode,
252254
@Cached @Shared("foreignPrototypeNode") ForeignObjectPrototypeNode getForeignPrototypeNode,
253255
@Cached @Shared("invalidPrototypeBranch") InlinedBranchProfile invalidPrototypeBranch,
254256
@Cached("create(context)") @Shared("ordinaryHasInstance") OrdinaryHasInstanceNode ordinaryHasInstanceNode) {
255257
if (context.isOptionForeignObjectPrototype()) {
256-
return foreignObjectIntl(left, right, getForeignPrototypeNode, invalidPrototypeBranch, ordinaryHasInstanceNode);
258+
return foreignObjectIntl(left, right, isAnyObjectNode, getForeignPrototypeNode, invalidPrototypeBranch, ordinaryHasInstanceNode);
257259
} else {
258260
return false;
259261
}
260262
}
261263

262-
private boolean foreignObjectIntl(Object left, JSDynamicObject right, ForeignObjectPrototypeNode getForeignPrototypeNode, InlinedBranchProfile invalidPrototypeBranch,
263-
OrdinaryHasInstanceNode ordinaryHasInstanceNode) {
264+
private boolean foreignObjectIntl(Object left, JSDynamicObject right, IsObjectNode isObjectNode, ForeignObjectPrototypeNode getForeignPrototypeNode,
265+
InlinedBranchProfile invalidPrototypeBranch, OrdinaryHasInstanceNode ordinaryHasInstanceNode) {
266+
if (!isObjectNode.executeBoolean(left)) {
267+
return false;
268+
}
264269
Object rightProto = getConstructorPrototype(right, invalidPrototypeBranch);
265270
Object foreignProto = getForeignPrototypeNode.execute(left);
266271
if (foreignProto == rightProto) {
@@ -276,10 +281,11 @@ protected boolean doNotAnObject(@SuppressWarnings("unused") Object left, @Suppre
276281

277282
@Specialization(guards = {"!isJSObject(left)", "isForeignObject(left)", "isJSProxy(right)", "isCallableProxy(right)"})
278283
protected boolean doNotAnObjectProxyForeign(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") JSDynamicObject right,
284+
@Cached @Shared IsObjectNode isAnyObjectNode,
279285
@Cached @Shared("foreignPrototypeNode") ForeignObjectPrototypeNode getForeignPrototypeNode,
280286
@Cached @Shared("invalidPrototypeBranch") InlinedBranchProfile invalidPrototypeBranch,
281287
@Cached("create(context)") @Shared("ordinaryHasInstance") OrdinaryHasInstanceNode ordinaryHasInstanceNode) {
282-
return doForeignObject(left, right, getForeignPrototypeNode, invalidPrototypeBranch, ordinaryHasInstanceNode);
288+
return doForeignObject(left, right, isAnyObjectNode, getForeignPrototypeNode, invalidPrototypeBranch, ordinaryHasInstanceNode);
283289
}
284290

285291
@Specialization(guards = {"!isJSObject(left)", "!isForeignObject(left)", "isJSProxy(right)", "isCallableProxy(right)"})

0 commit comments

Comments
 (0)