Skip to content

Commit

Permalink
[GR-52840] Backport to 24.0: Instanceof operator should check whether…
Browse files Browse the repository at this point in the history
… the left side is a (foreign) object.

PullRequest: js/3102
  • Loading branch information
iamstolis committed Mar 20, 2024
2 parents c103057 + 9894a42 commit 7db2823
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 11 deletions.
13 changes: 13 additions & 0 deletions graal-js/src/com.oracle.truffle.js.test/js/GR-52824.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl.
*/

load("assert.js");

var javaNull = new java.util.ArrayDeque().peek();

assertFalse(javaNull instanceof Object);
assertFalse(javaNull instanceof new Proxy(Object, {}));
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -41,8 +41,9 @@
package com.oracle.truffle.js.test.interop;

import static com.oracle.truffle.js.lang.JavaScriptLanguage.ID;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

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

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

Expand All @@ -95,6 +98,7 @@ public void testForeignBoxedNumber() {
assertEquals("42", context.eval(ID, "obj.toString()").asString());
assertEquals(42, context.eval(ID, "obj.valueOf()").asInt());
assertEquals(42, context.eval(ID, "obj['valueOf']()").asInt());
assertFalse(context.eval(ID, "obj instanceof Object").asBoolean());
}
}

Expand All @@ -108,6 +112,7 @@ public void testForeignBoxedBoolean() {
assertTrue(context.eval(ID, "obj.valueOf()").asBoolean());
assertTrue(context.eval(ID, "obj['valueOf']()").asBoolean());
assertEquals("true", context.eval(ID, "obj.toString()").asString());
assertFalse(context.eval(ID, "obj instanceof Object").asBoolean());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -211,9 +211,9 @@ public void testForeignInstanceof() {
Assert.assertTrue(testInstanceofIntl("Array", ProxyArray.fromArray("fun", "with", "proxy", "array")));
Assert.assertTrue(testInstanceofIntl("Date", Instant.now()));
Assert.assertTrue(testInstanceofIntl("Map", new TestTruffleHash()));
Assert.assertTrue(testInstanceofIntl("String", new TestTruffleString()));
Assert.assertTrue(testInstanceofIntl("Boolean", new TestTruffleBoolean()));
Assert.assertTrue(testInstanceofIntl("Number", new TestTruffleNumber()));
Assert.assertFalse(testInstanceofIntl("String", new TestTruffleString()));
Assert.assertFalse(testInstanceofIntl("Boolean", new TestTruffleBoolean()));
Assert.assertFalse(testInstanceofIntl("Number", new TestTruffleNumber()));
Assert.assertTrue(testInstanceofIntl("Function", (ProxyExecutable) v -> true));
Assert.assertTrue(testInstanceofIntl("Object", new Object()));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -67,6 +67,7 @@
import com.oracle.truffle.js.nodes.access.GetMethodNode;
import com.oracle.truffle.js.nodes.access.GetPrototypeNode;
import com.oracle.truffle.js.nodes.access.IsJSObjectNode;
import com.oracle.truffle.js.nodes.access.IsObjectNode;
import com.oracle.truffle.js.nodes.access.PropertyGetNode;
import com.oracle.truffle.js.nodes.binary.InstanceofNodeGen.IsBoundFunctionCacheNodeGen;
import com.oracle.truffle.js.nodes.binary.InstanceofNodeGen.OrdinaryHasInstanceNodeGen;
Expand Down Expand Up @@ -249,18 +250,22 @@ protected boolean doIsBound(Object obj, JSDynamicObject check,

@Specialization(guards = {"!isJSObject(left)", "isForeignObject(left)", "isJSFunction(right)", "!isBoundFunction(right)"})
protected boolean doForeignObject(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") JSDynamicObject right,
@Cached @Shared IsObjectNode isAnyObjectNode,
@Cached @Shared("foreignPrototypeNode") ForeignObjectPrototypeNode getForeignPrototypeNode,
@Cached @Shared("invalidPrototypeBranch") InlinedBranchProfile invalidPrototypeBranch,
@Cached("create(context)") @Shared("ordinaryHasInstance") OrdinaryHasInstanceNode ordinaryHasInstanceNode) {
if (context.isOptionForeignObjectPrototype()) {
return foreignObjectIntl(left, right, getForeignPrototypeNode, invalidPrototypeBranch, ordinaryHasInstanceNode);
return foreignObjectIntl(left, right, isAnyObjectNode, getForeignPrototypeNode, invalidPrototypeBranch, ordinaryHasInstanceNode);
} else {
return false;
}
}

private boolean foreignObjectIntl(Object left, JSDynamicObject right, ForeignObjectPrototypeNode getForeignPrototypeNode, InlinedBranchProfile invalidPrototypeBranch,
OrdinaryHasInstanceNode ordinaryHasInstanceNode) {
private boolean foreignObjectIntl(Object left, JSDynamicObject right, IsObjectNode isObjectNode, ForeignObjectPrototypeNode getForeignPrototypeNode,
InlinedBranchProfile invalidPrototypeBranch, OrdinaryHasInstanceNode ordinaryHasInstanceNode) {
if (!isObjectNode.executeBoolean(left)) {
return false;
}
Object rightProto = getConstructorPrototype(right, invalidPrototypeBranch);
Object foreignProto = getForeignPrototypeNode.execute(left);
if (foreignProto == rightProto) {
Expand All @@ -276,10 +281,11 @@ protected boolean doNotAnObject(@SuppressWarnings("unused") Object left, @Suppre

@Specialization(guards = {"!isJSObject(left)", "isForeignObject(left)", "isJSProxy(right)", "isCallableProxy(right)"})
protected boolean doNotAnObjectProxyForeign(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") JSDynamicObject right,
@Cached @Shared IsObjectNode isAnyObjectNode,
@Cached @Shared("foreignPrototypeNode") ForeignObjectPrototypeNode getForeignPrototypeNode,
@Cached @Shared("invalidPrototypeBranch") InlinedBranchProfile invalidPrototypeBranch,
@Cached("create(context)") @Shared("ordinaryHasInstance") OrdinaryHasInstanceNode ordinaryHasInstanceNode) {
return doForeignObject(left, right, getForeignPrototypeNode, invalidPrototypeBranch, ordinaryHasInstanceNode);
return doForeignObject(left, right, isAnyObjectNode, getForeignPrototypeNode, invalidPrototypeBranch, ordinaryHasInstanceNode);
}

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

0 comments on commit 7db2823

Please sign in to comment.