Skip to content

Commit 0874113

Browse files
andreabergia0xe
andcommitted
Handle delete super.x by throwing an error
See spec 13.5.1.2 at https://tc39.es/ecma262/#sec-delete-operator-runtime-semantics-evaluation Co-authored-by: Satish Srinivasan <satish.srinivasan@servicenow.com>
1 parent b5a3170 commit 0874113

File tree

8 files changed

+96
-11
lines changed

8 files changed

+96
-11
lines changed

rhino/src/main/java/org/mozilla/javascript/CodeGenerator.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,9 @@ private void visitExpression(Node node, int contextFlags) {
737737
visitExpression(child, 0);
738738
child = child.getNext();
739739
visitExpression(child, 0);
740-
if (isName) {
740+
if (node.getIntProp(Node.SUPER_PROPERTY_ACCESS, 0) == 1) {
741+
addIcode(Icode_DELPROP_SUPER);
742+
} else if (isName) {
741743
// special handling for delete name
742744
addIcode(Icode_DELNAME);
743745
} else {

rhino/src/main/java/org/mozilla/javascript/IRFactory.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,6 +1864,9 @@ private static Node createUnary(int nodeType, Node child) {
18641864
// Always evaluate delete operand, see ES5 11.4.1 & bug #726121
18651865
n = new Node(nodeType, new Node(Token.TRUE), child);
18661866
}
1867+
if (child.getIntProp(Node.SUPER_PROPERTY_ACCESS, 0) == 1) {
1868+
n.putIntProp(Node.SUPER_PROPERTY_ACCESS, 1);
1869+
}
18671870
return n;
18681871
}
18691872
case Token.TYPEOF:

rhino/src/main/java/org/mozilla/javascript/Icode.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,11 @@ abstract class Icode {
156156
// Call a method on the super object, i.e. super.foo()
157157
Icode_CALL_ON_SUPER = Icode_IF_NOT_NULL_UNDEF - 1,
158158

159+
// delete super.prop
160+
Icode_DELPROP_SUPER = Icode_CALL_ON_SUPER - 1,
161+
159162
// Last icode
160-
MIN_ICODE = Icode_CALL_ON_SUPER;
163+
MIN_ICODE = Icode_DELPROP_SUPER;
161164

162165
static String bytecodeName(int bytecode) {
163166
if (!validBytecode(bytecode)) {
@@ -343,6 +346,8 @@ static String bytecodeName(int bytecode) {
343346
return "IF_NOT_NULL_UNDEF";
344347
case Icode_CALL_ON_SUPER:
345348
return "CALL_ON_SUPER";
349+
case Icode_DELPROP_SUPER:
350+
return "DELPROP_SUPER";
346351
}
347352

348353
// icode without name

rhino/src/main/java/org/mozilla/javascript/Interpreter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,6 +1643,11 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
16431643
stackTop = doDelName(cx, frame, op, stack, sDbl, stackTop);
16441644
continue Loop;
16451645
}
1646+
case Icode_DELPROP_SUPER:
1647+
stackTop -= 1;
1648+
stack[stackTop] = Boolean.FALSE;
1649+
ScriptRuntime.throwDeleteOnSuperPropertyNotAllowed();
1650+
continue Loop;
16461651
case Token.GETPROPNOWARN:
16471652
{
16481653
Object lhs = stack[stackTop];

rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5364,6 +5364,10 @@ public static EcmaError syntaxErrorById(String messageId, Object... args) {
53645364
return syntaxError(msg);
53655365
}
53665366

5367+
public static EcmaError referenceError(String message) {
5368+
return constructError("ReferenceError", message);
5369+
}
5370+
53675371
private static void warnAboutNonJSObject(Object nonJSObject) {
53685372
final String omitParam = ScriptRuntime.getMessageById("params.omit.non.js.object.warning");
53695373
if (!"true".equals(omitParam)) {
@@ -5592,6 +5596,11 @@ public static JavaScriptException throwCustomError(
55925596
return new JavaScriptException(error, filename, linep[0]);
55935597
}
55945598

5599+
/** Throws a ReferenceError "cannot delete a super property". See ECMAScript spec 13.5.1.2 */
5600+
public static void throwDeleteOnSuperPropertyNotAllowed() {
5601+
throw referenceError("msg.delete.super");
5602+
}
5603+
55955604
public static final Object[] emptyArgs = new Object[0];
55965605
public static final String[] emptyStrings = new String[0];
55975606
}

rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,14 +1555,27 @@ private void generateExpression(Node node, Node parent) {
15551555
generateExpression(child, node);
15561556
child = child.getNext();
15571557
generateExpression(child, node);
1558-
cfw.addALoad(contextLocal);
1559-
cfw.addPush(isName);
1560-
addScriptRuntimeInvoke(
1561-
"delete",
1562-
"(Ljava/lang/Object;"
1563-
+ "Ljava/lang/Object;"
1564-
+ "Lorg/mozilla/javascript/Context;"
1565-
+ "Z)Ljava/lang/Object;");
1558+
if (node.getIntProp(Node.SUPER_PROPERTY_ACCESS, 0) == 1) {
1559+
// We have pushed `super` and the expression, but we need to remove them because
1560+
// we actually are just going to throw an error. However, delete is supposed to
1561+
// put a boolean on the stack and the class file writer would complain if we
1562+
// don't have only popped here. So we pop and the push 0 (false). Anyway, this
1563+
// is code that will always fail, so honestly no one will ever write something
1564+
// like this (delete super[foo]), so... even if this is not the most efficient
1565+
// bytecode, it's fine.
1566+
cfw.add(ByteCode.POP2);
1567+
cfw.addLoadConstant(0);
1568+
addScriptRuntimeInvoke("throwDeleteOnSuperPropertyNotAllowed", "()V");
1569+
} else {
1570+
cfw.addALoad(contextLocal);
1571+
cfw.addPush(isName);
1572+
addScriptRuntimeInvoke(
1573+
"delete",
1574+
"(Ljava/lang/Object;"
1575+
+ "Ljava/lang/Object;"
1576+
+ "Lorg/mozilla/javascript/Context;"
1577+
+ "Z)Ljava/lang/Object;");
1578+
}
15661579
break;
15671580

15681581
case Token.BINDNAME:

rhino/src/main/resources/org/mozilla/javascript/resources/Messages.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,9 @@ msg.super.shorthand.function =\
459459
msg.optional.super =\
460460
super is not allowed in an optional chaining expression
461461

462+
msg.super.delete =\
463+
cannot delete a super property
464+
462465
msg.no.paren.catch =\
463466
missing ( before catch-block condition
464467

rhino/src/test/java/org/mozilla/javascript/SuperTest.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ void prototypeIsNull() {
414414
}
415415

416416
@Nested
417-
class PropertyWrite {
417+
class PropertyMutate {
418418
@Test
419419
void byName() {
420420
String script =
@@ -748,6 +748,51 @@ void modifyOperatorByName() {
748748
+ "object.x + ':' + proto.x";
749749
Utils.assertWithAllOptimizationLevelsES6("proto1:proto", script);
750750
}
751+
752+
@Test
753+
void deleteNotAllowed() {
754+
String script =
755+
""
756+
+ "var catchHit = false;\n"
757+
+ "var getterCalled = false;\n"
758+
+ "var proto = { get x() { getterCalled = true; } };"
759+
+ "var object = {\n"
760+
+ " f() {\n"
761+
+ " try {\n"
762+
+ " delete super.x;\n"
763+
+ " } catch (err) {\n"
764+
+ " catchHit = err instanceof ReferenceError;"
765+
+ " }\n"
766+
+ " }\n"
767+
+ "};\n"
768+
+ "Object.setPrototypeOf(object, proto);\n"
769+
+ "object.f();\n"
770+
+ "catchHit + ':' + getterCalled";
771+
Utils.assertWithAllOptimizationLevelsES6("true:false", script);
772+
}
773+
774+
@Test
775+
void deleteSuperFirstEvaluatesPropertyKey() {
776+
String script =
777+
""
778+
+ "var catchHit = false;\n"
779+
+ "var gCalled = false;\n"
780+
+ "var proto = { x: 1 };\n"
781+
+ "function g() { gCalled = true; return 'x'; }\n"
782+
+ " object = {\n"
783+
+ " f() {\n"
784+
+ " try {\n"
785+
+ " delete super[g()];\n"
786+
+ " } catch (err) {\n"
787+
+ " catchHit = err instanceof ReferenceError;"
788+
+ " }\n"
789+
+ " }\n"
790+
+ "};\n"
791+
+ "Object.setPrototypeOf(object, proto);\n"
792+
+ "object.f();\n"
793+
+ "catchHit + ':' + gCalled";
794+
Utils.assertWithAllOptimizationLevelsES6("true:true", script);
795+
}
751796
}
752797

753798
@Nested

0 commit comments

Comments
 (0)