Skip to content

Commit f0f46f3

Browse files
andreabergia0xe
andcommitted
Implement super
Co-authored-by: Satish Srinivasan <satish.srinivasan@servicenow.com>
1 parent 8406632 commit f0f46f3

28 files changed

+2084
-205
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,17 @@ public class ArrowFunction extends BaseFunction {
1515

1616
private final Callable targetFunction;
1717
private final Scriptable boundThis;
18+
private final Scriptable boundHomeObject;
1819

1920
public ArrowFunction(
20-
Context cx, Scriptable scope, Callable targetFunction, Scriptable boundThis) {
21+
Context cx,
22+
Scriptable scope,
23+
Callable targetFunction,
24+
Scriptable boundThis,
25+
Scriptable boundHomeObject) {
2126
this.targetFunction = targetFunction;
2227
this.boundThis = boundThis;
28+
this.boundHomeObject = boundHomeObject;
2329

2430
ScriptRuntime.setFunctionProtoAndParent(this, cx, scope, false);
2531

@@ -80,6 +86,10 @@ Scriptable getCallThis(Context cx) {
8086
return boundThis != null ? boundThis : ScriptRuntime.getTopCallScope(cx);
8187
}
8288

89+
Scriptable getBoundHomeObject() {
90+
return this.boundHomeObject;
91+
}
92+
8393
Callable getTargetFunction() {
8494
return targetFunction;
8595
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,14 @@ protected int findPrototypeId(String s) {
656656
return id;
657657
}
658658

659+
public void setHomeObject(Scriptable homeObject) {
660+
this.homeObject = homeObject;
661+
}
662+
663+
public Scriptable getHomeObject() {
664+
return homeObject;
665+
}
666+
659667
private static final int Id_constructor = 1,
660668
Id_toString = 2,
661669
Id_toSource = 3,
@@ -668,6 +676,7 @@ protected int findPrototypeId(String s) {
668676
private Object argumentsObj = NOT_FOUND;
669677
private String nameValue = null;
670678
private boolean isGeneratorFunction = false;
679+
private Scriptable homeObject = null;
671680

672681
// For function object instances, attributes are
673682
// {configurable:false, enumerable:false};

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

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,9 @@ private void visitExpression(Node node, int contextFlags) {
566566
throw Kit.codeBug();
567567
}
568568
addIndexOp(Icode_CLOSURE_EXPR, fnIndex);
569+
if (fn.isMethodDefinition()) {
570+
addIcode(ICode_FN_STORE_HOME_OBJECT);
571+
}
569572
stackChange(1);
570573
}
571574
break;
@@ -626,6 +629,8 @@ private void visitExpression(Node node, int contextFlags) {
626629
addUint8(callType);
627630
addUint8(type == Token.NEW ? 1 : 0);
628631
addUint16(lineNumber & 0xFFFF);
632+
} else if (node.getIntProp(Node.SUPER_PROPERTY_ACCESS, 0) == 1) {
633+
addIndexOp(Icode_CALL_ON_SUPER, argCount);
629634
} else {
630635
// Only use the tail call optimization if we're not in a try
631636
// or we're not generating debug info (since the
@@ -718,6 +723,10 @@ private void visitExpression(Node node, int contextFlags) {
718723
addIcode(Icode_POP);
719724
addStringOp(Token.NAME, "undefined");
720725
resolveForwardGoto(afterLabel);
726+
} else if (node.getIntProp(Node.SUPER_PROPERTY_ACCESS, 0) == 1) {
727+
addStringOp(
728+
type == Token.GETPROP ? Token.GETPROP_SUPER : Token.GETPROPNOWARN_SUPER,
729+
child.getString());
721730
} else {
722731
addStringOp(type, child.getString());
723732
}
@@ -757,6 +766,10 @@ private void visitExpression(Node node, int contextFlags) {
757766
addIcode(Icode_POP);
758767
addStringOp(Token.NAME, "undefined");
759768
resolveForwardGoto(afterLabel);
769+
} else if (node.getIntProp(Node.SUPER_PROPERTY_ACCESS, 0) == 1) {
770+
visitExpression(child, 0);
771+
addToken(Token.GETELEM_SUPER);
772+
stackChange(-1);
760773
} else {
761774
finishGetElemGeneration(child);
762775
}
@@ -843,7 +856,11 @@ private void visitExpression(Node node, int contextFlags) {
843856
stackChange(-1);
844857
}
845858
visitExpression(child, 0);
846-
addStringOp(Token.SETPROP, property);
859+
addStringOp(
860+
node.getIntProp(Node.SUPER_PROPERTY_ACCESS, 0) == 1
861+
? Token.SETPROP_SUPER
862+
: Token.SETPROP,
863+
property);
847864
stackChange(-1);
848865
}
849866
break;
@@ -863,7 +880,10 @@ private void visitExpression(Node node, int contextFlags) {
863880
stackChange(-1);
864881
}
865882
visitExpression(child, 0);
866-
addToken(Token.SETELEM);
883+
addToken(
884+
node.getIntProp(Node.SUPER_PROPERTY_ACCESS, 0) == 1
885+
? Token.SETELEM_SUPER
886+
: Token.SETELEM);
867887
stackChange(-2);
868888
break;
869889

@@ -996,6 +1016,7 @@ private void visitExpression(Node node, int contextFlags) {
9961016

9971017
case Token.NULL:
9981018
case Token.THIS:
1019+
case Token.SUPER:
9991020
case Token.THISFN:
10001021
case Token.FALSE:
10011022
case Token.TRUE:

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2524,7 +2524,8 @@ private ScriptNode parse(
25242524
}
25252525
}
25262526

2527-
IRFactory irf = new IRFactory(compilerEnv, sourceString, compilationErrorReporter);
2527+
IRFactory irf =
2528+
new IRFactory(compilerEnv, sourceName, sourceString, compilationErrorReporter);
25282529
ScriptNode tree = irf.transformTree(ast);
25292530

25302531
if (compilerEnv.isGeneratingSource()) {

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

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,24 @@ public final class IRFactory {
9595
private AstNodePosition astNodePos;
9696

9797
public IRFactory(CompilerEnvirons env, String sourceString) {
98-
this(env, sourceString, env.getErrorReporter());
98+
this(env, null, sourceString, env.getErrorReporter());
9999
}
100100

101+
/** Use {@link #IRFactory(CompilerEnvirons, String, String, ErrorReporter)} */
102+
@Deprecated
101103
public IRFactory(CompilerEnvirons env, String sourceString, ErrorReporter errorReporter) {
104+
this(env, null, sourceString, errorReporter);
105+
}
106+
107+
public IRFactory(
108+
CompilerEnvirons env,
109+
String sourceName,
110+
String sourceString,
111+
ErrorReporter errorReporter) {
102112
parser = new Parser(env, errorReporter);
103113
astNodePos = new AstNodePosition(sourceString);
104114
parser.currentPos = astNodePos;
115+
parser.setSourceURI(sourceName);
105116
}
106117

107118
/** Transforms the tree into a lower-level IR suitable for codegen. */
@@ -180,7 +191,9 @@ private Node transform(AstNode node) {
180191
case Token.NULL:
181192
case Token.DEBUGGER:
182193
return transformLiteral(node);
183-
194+
case Token.SUPER:
195+
parser.setRequiresActivation();
196+
return transformLiteral(node);
184197
case Token.NAME:
185198
return transformName((Name) node);
186199
case Token.NUMBER:
@@ -533,6 +546,9 @@ private Node transformElementGet(ElementGet node) {
533546
if (node.type == Token.QUESTION_DOT) {
534547
getElem.putIntProp(Node.OPTIONAL_CHAINING, 1);
535548
}
549+
if (target.getType() == Token.SUPER) {
550+
getElem.putIntProp(Node.SUPER_PROPERTY_ACCESS, 1);
551+
}
536552
return getElem;
537553
}
538554

@@ -660,17 +676,26 @@ private Node transformFunction(FunctionNode fn) {
660676
}
661677

662678
private Node transformFunctionCall(FunctionCall node) {
663-
Node call = createCallOrNew(Token.CALL, transform(node.getTarget()));
664-
call.setLineColumnNumber(node.getLineno(), node.getColumn());
665-
List<AstNode> args = node.getArguments();
666-
for (int i = 0; i < args.size(); i++) {
667-
AstNode arg = args.get(i);
668-
call.addChildToBack(transform(arg));
669-
}
670-
if (node.isOptionalCall()) {
671-
call.putIntProp(Node.OPTIONAL_CHAINING, 1);
679+
astNodePos.push(node);
680+
try {
681+
Node transformedTarget = transform(node.getTarget());
682+
Node call = createCallOrNew(Token.CALL, transformedTarget);
683+
call.setLineColumnNumber(node.getLineno(), node.getColumn());
684+
List<AstNode> args = node.getArguments();
685+
for (int i = 0; i < args.size(); i++) {
686+
AstNode arg = args.get(i);
687+
call.addChildToBack(transform(arg));
688+
}
689+
if (node.isOptionalCall()) {
690+
call.putIntProp(Node.OPTIONAL_CHAINING, 1);
691+
}
692+
if (transformedTarget.getIntProp(Node.SUPER_PROPERTY_ACCESS, 0) == 1) {
693+
call.putIntProp(Node.SUPER_PROPERTY_ACCESS, 1);
694+
}
695+
return call;
696+
} finally {
697+
astNodePos.pop();
672698
}
673-
return call;
674699
}
675700

676701
private Node transformGenExpr(GeneratorExpression node) {
@@ -863,6 +888,11 @@ private Node transformLetNode(LetNode node) {
863888
}
864889

865890
private Node transformLiteral(AstNode node) {
891+
// Trying to call super as a function. See 15.4.2 Static Semantics: HasDirectSuper
892+
if (node.getParent() instanceof FunctionCall
893+
&& node.getType() == Token.SUPER
894+
&& parser.currentScriptOrFn.isMethodDefinition())
895+
parser.reportError("msg.super.shorthand.function");
866896
return node;
867897
}
868898

@@ -969,8 +999,12 @@ private Node transformTemplateLiteral(TemplateLiteral node) {
969999
}
9701000

9711001
private Node transformTemplateLiteralCall(TaggedTemplateLiteral node) {
972-
Node call = createCallOrNew(Token.CALL, transform(node.getTarget()));
1002+
Node transformedTarget = transform(node.getTarget());
1003+
Node call = createCallOrNew(Token.CALL, transformedTarget);
9731004
call.setLineColumnNumber(node.getLineno(), node.getColumn());
1005+
if (transformedTarget.getIntProp(Node.SUPER_PROPERTY_ACCESS, 0) == 1) {
1006+
call.putIntProp(Node.SUPER_PROPERTY_ACCESS, 1);
1007+
}
9741008
TemplateLiteral templateLiteral = (TemplateLiteral) node.getTemplateLiteral();
9751009
List<AstNode> elems = templateLiteral.getElements();
9761010
call.addChildToBack(templateLiteral);
@@ -1937,13 +1971,19 @@ private Node createPropertyGet(
19371971
ref.putIntProp(Node.OPTIONAL_CHAINING, 1);
19381972
getRef.putIntProp(Node.OPTIONAL_CHAINING, 1);
19391973
}
1974+
if (target.getType() == Token.SUPER) {
1975+
getRef.putIntProp(Node.SUPER_PROPERTY_ACCESS, 1);
1976+
}
19401977
return getRef;
19411978
}
19421979

19431980
Node node = new Node(Token.GETPROP, target, Node.newString(name));
19441981
if (type == Token.QUESTION_DOT) {
19451982
node.putIntProp(Node.OPTIONAL_CHAINING, 1);
19461983
}
1984+
if (target.getType() == Token.SUPER) {
1985+
node.putIntProp(Node.SUPER_PROPERTY_ACCESS, 1);
1986+
}
19471987
return node;
19481988
}
19491989
Node elem = Node.newString(name);
@@ -2147,7 +2187,9 @@ private Node createAssignment(int assignType, Node left, Node right) {
21472187
int assignOp;
21482188
switch (assignType) {
21492189
case Token.ASSIGN:
2150-
return parser.simpleAssignment(left, right);
2190+
{
2191+
return propagateSuperFromLhs(parser.simpleAssignment(left, right), left);
2192+
}
21512193
case Token.ASSIGN_BITOR:
21522194
assignOp = Token.BITOR;
21532195
break;
@@ -2203,7 +2245,7 @@ private Node createAssignment(int assignType, Node left, Node right) {
22032245
{
22042246
Node op = new Node(assignOp, left, right);
22052247
Node lvalueLeft = Node.newString(Token.BINDNAME, left.getString());
2206-
return new Node(Token.SETNAME, lvalueLeft, op);
2248+
return propagateSuperFromLhs(new Node(Token.SETNAME, lvalueLeft, op), left);
22072249
}
22082250
case Token.GETPROP:
22092251
case Token.GETELEM:
@@ -2215,21 +2257,28 @@ private Node createAssignment(int assignType, Node left, Node right) {
22152257

22162258
Node opLeft = new Node(Token.USE_STACK);
22172259
Node op = new Node(assignOp, opLeft, right);
2218-
return new Node(type, obj, id, op);
2260+
return propagateSuperFromLhs(new Node(type, obj, id, op), left);
22192261
}
22202262
case Token.GET_REF:
22212263
{
22222264
ref = left.getFirstChild();
22232265
parser.checkMutableReference(ref);
22242266
Node opLeft = new Node(Token.USE_STACK);
22252267
Node op = new Node(assignOp, opLeft, right);
2226-
return new Node(Token.SET_REF_OP, ref, op);
2268+
return propagateSuperFromLhs(new Node(Token.SET_REF_OP, ref, op), left);
22272269
}
22282270
}
22292271

22302272
throw Kit.codeBug();
22312273
}
22322274

2275+
private Node propagateSuperFromLhs(Node result, Node left) {
2276+
if (left.getIntProp(Node.SUPER_PROPERTY_ACCESS, 0) == 1) {
2277+
result.putIntProp(Node.SUPER_PROPERTY_ACCESS, 1);
2278+
}
2279+
return result;
2280+
}
2281+
22332282
private static Node createUseLocal(Node localBlock) {
22342283
if (Token.LOCAL_BLOCK != localBlock.getType()) throw Kit.codeBug();
22352284
Node result = new Node(Token.LOCAL_LOAD);

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,10 @@ abstract class Icode {
7878
Icode_LITERAL_NEW_OBJECT = Icode_INTNUMBER - 1,
7979
Icode_LITERAL_NEW_ARRAY = Icode_LITERAL_NEW_OBJECT - 1,
8080
Icode_LITERAL_SET = Icode_LITERAL_NEW_ARRAY - 1,
81+
ICode_FN_STORE_HOME_OBJECT = Icode_LITERAL_SET - 1,
8182

8283
// Array literal with skipped index like [1,,2]
83-
Icode_SPARE_ARRAYLIT = Icode_LITERAL_SET - 1,
84+
Icode_SPARE_ARRAYLIT = ICode_FN_STORE_HOME_OBJECT - 1,
8485

8586
// Load index register to prepare for the following index operation
8687
Icode_REG_IND_C0 = Icode_SPARE_ARRAYLIT - 1,
@@ -151,8 +152,12 @@ abstract class Icode {
151152
// Jump if stack head is null or undefined
152153
Icode_IF_NULL_UNDEF = Icode_LITERAL_KEY_SET - 1,
153154
Icode_IF_NOT_NULL_UNDEF = Icode_IF_NULL_UNDEF - 1,
155+
156+
// Call a method on the super object, i.e. super.foo()
157+
Icode_CALL_ON_SUPER = Icode_IF_NOT_NULL_UNDEF - 1,
158+
154159
// Last icode
155-
MIN_ICODE = Icode_IF_NOT_NULL_UNDEF;
160+
MIN_ICODE = Icode_CALL_ON_SUPER;
156161

157162
static String bytecodeName(int bytecode) {
158163
if (!validBytecode(bytecode)) {
@@ -240,6 +245,8 @@ static String bytecodeName(int bytecode) {
240245
return "LITERAL_NEW_ARRAY";
241246
case Icode_LITERAL_SET:
242247
return "LITERAL_SET";
248+
case ICode_FN_STORE_HOME_OBJECT:
249+
return "FN_STORE_HOME_OBJECT";
243250
case Icode_SPARE_ARRAYLIT:
244251
return "SPARE_ARRAYLIT";
245252
case Icode_REG_IND_C0:
@@ -334,6 +341,8 @@ static String bytecodeName(int bytecode) {
334341
return "IF_NULL_UNDEF";
335342
case Icode_IF_NOT_NULL_UNDEF:
336343
return "IF_NOT_NULL_UNDEF";
344+
case Icode_CALL_ON_SUPER:
345+
return "CALL_ON_SUPER";
337346
}
338347

339348
// icode without name

0 commit comments

Comments
 (0)