From 2852f35f4d4433046eaedf06df06f00e6dbbbd74 Mon Sep 17 00:00:00 2001 From: "andrea.bergia" Date: Tue, 26 Nov 2024 10:20:57 +0100 Subject: [PATCH] Handle `super.__proto__`, which has a special implementation Co-authored-by: Satish Srinivasan --- .../org/mozilla/javascript/IRFactory.java | 19 +++++- .../org/mozilla/javascript/SuperTest.java | 59 +++++++++++++++++++ 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/rhino/src/main/java/org/mozilla/javascript/IRFactory.java b/rhino/src/main/java/org/mozilla/javascript/IRFactory.java index d358350245..1627a7751c 100644 --- a/rhino/src/main/java/org/mozilla/javascript/IRFactory.java +++ b/rhino/src/main/java/org/mozilla/javascript/IRFactory.java @@ -1964,6 +1964,22 @@ private Node createPropertyGet( } parser.checkActivationName(name, Token.GETPROP); if (ScriptRuntime.isSpecialProperty(name)) { + if (target.getType() == Token.SUPER) { + // We have an access to super.__proto__ or super.__parent__. + // This needs to behave in the same way as this.__proto__ - it really is not + // obvious why, but you can test it in v8 or any other engine. So, we just + // replace SUPER with THIS in the AST. It's a bit hacky, but it works - see the + // test cases in SuperTest! + if (!(target instanceof KeywordLiteral)) { + throw Kit.codeBug(); + } + KeywordLiteral oldTarget = (KeywordLiteral) target; + target = + new KeywordLiteral( + oldTarget.getPosition(), oldTarget.getLength(), Token.THIS); + target.setLineColumnNumber(oldTarget.getLineno(), oldTarget.getColumn()); + } + Node ref = new Node(Token.REF_SPECIAL, target); ref.putProp(Node.NAME_PROP, name); Node getRef = new Node(Token.GET_REF, ref); @@ -1971,9 +1987,6 @@ private Node createPropertyGet( ref.putIntProp(Node.OPTIONAL_CHAINING, 1); getRef.putIntProp(Node.OPTIONAL_CHAINING, 1); } - if (target.getType() == Token.SUPER) { - getRef.putIntProp(Node.SUPER_PROPERTY_ACCESS, 1); - } return getRef; } diff --git a/rhino/src/test/java/org/mozilla/javascript/SuperTest.java b/rhino/src/test/java/org/mozilla/javascript/SuperTest.java index 407f0d9cf2..411de94d2e 100644 --- a/rhino/src/test/java/org/mozilla/javascript/SuperTest.java +++ b/rhino/src/test/java/org/mozilla/javascript/SuperTest.java @@ -942,4 +942,63 @@ void doublyNestedLambdaCaptureSuper() { Utils.assertWithAllOptimizationLevelsES6("object", script); } } + + /** + * Test cases related to the special handling of REF in Rhino, which includes the special + * properties __proto__ and __parent__. It also includes XML stuff, but we do not support it for + * super. + */ + @Nested + class Ref { + @Test + void propertyGet() { + String script = + "" + + "var a = {x: 'a'};\n" + + "var b = {x: 'b'};\n" + + "var c = {x: 'c',\n" + + " f() {\n" + + " return super.__proto__.x;\n" + + " }\n" + + "};\n" + + "Object.setPrototypeOf(c, b);\n" + + "Object.setPrototypeOf(b, a);\n" + + "c.f();"; + Utils.assertWithAllOptimizationLevelsES6("b", script); + } + + @Test + void propertyGetter() { + String script = + "" + + "var a = {get x() { return 'a' + this.y }, y: 'a' };\n" + + "var b = {get x() { return 'b' + this.y }, y: 'b' };\n" + + "var c = {\n" + + " get x() { return 'c' + this.y }, y: 'c',\n" + + " f() { return super.__proto__.x }," + + "};\n" + + "Object.setPrototypeOf(c, b);\n" + + "Object.setPrototypeOf(b, a);\n" + + "c.f();"; + Utils.assertWithAllOptimizationLevelsES6("bb", script); + } + + @Test + void propertySet() { + String script = + "" + + "var a = {x: 'a'};\n" + + "var b = {x: 'b'};\n" + + "var c = {x: 'c',\n" + + " f() {\n" + + " super.__proto__ = a;\n" + + " return Object.getPrototypeOf(this).x;\n" + + " }\n" + + "};\n" + + "Object.setPrototypeOf(c, b);\n" + + "Object.setPrototypeOf(b, a);\n" + + "c.f();"; + Utils.assertWithAllOptimizationLevelsES6("a", script); + } + } }