Skip to content

Commit 5384ef4

Browse files
committed
[MERGE #4670 @sethbrenith] Return correct value from super(). Fixes #4663
Merge pull request #4670 from sethbrenith:user/sethb/super-return Return correct value from super(). Fixes #4663
2 parents 54caa27 + ca07e99 commit 5384ef4

File tree

2 files changed

+90
-4
lines changed

2 files changed

+90
-4
lines changed

lib/Runtime/ByteCode/ByteCodeEmitter.cpp

+11-4
Original file line numberDiff line numberDiff line change
@@ -2214,6 +2214,7 @@ void ByteCodeGenerator::LoadSuperObject(FuncInfo *funcInfo)
22142214
void ByteCodeGenerator::EmitSuperCall(FuncInfo* funcInfo, ParseNode* pnode, BOOL fReturnValue)
22152215
{
22162216
FuncInfo* nonLambdaFunc = funcInfo;
2217+
bool isResultUsed = pnode->isUsed;
22172218

22182219
if (funcInfo->IsLambda())
22192220
{
@@ -2226,11 +2227,11 @@ void ByteCodeGenerator::EmitSuperCall(FuncInfo* funcInfo, ParseNode* pnode, BOOL
22262227
this->Writer()->W1(Js::OpCode::RuntimeReferenceError, SCODE_CODE(JSERR_ClassSuperInBaseClass));
22272228
return;
22282229
}
2229-
else
2230-
{
2231-
pnode->isUsed = true;
2232-
}
22332230

2231+
pnode->isUsed = true;
2232+
2233+
// pnode->location refers to two things: the result of the inner function call (`temp` in the pseudocode below),
2234+
// and the result of the super() expression itself
22342235
funcInfo->AcquireLoc(pnode);
22352236

22362237
// We need to emit 'this' directly so we can skip throwing a reference error if 'this' is currently undecl (we want to get undecl if 'this' is undecl)
@@ -2302,6 +2303,12 @@ void ByteCodeGenerator::EmitSuperCall(FuncInfo* funcInfo, ParseNode* pnode, BOOL
23022303
this->Writer()->W1(Js::OpCode::RuntimeReferenceError, SCODE_CODE(JSERR_ClassThisAlreadyAssigned));
23032304
this->Writer()->MarkLabel(skipLabel);
23042305

2306+
// If calling code cares about the return value, then move the selected `this` value into the result register.
2307+
if (isResultUsed)
2308+
{
2309+
this->Writer()->Reg2(Js::OpCode::Ld_A, pnode->location, valueForThis);
2310+
}
2311+
23052312
Symbol* thisSym = pnode->sxSuperCall.pnodeThis->sxPid.sym;
23062313
this->Writer()->Reg2(Js::OpCode::StrictLdThis, pnode->sxSuperCall.pnodeThis->location, valueForThis);
23072314

test/es6/ES6Super.js

+79
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,85 @@ var tests = [
204204
assert.areEqual(6, count, "Side effects expected without SyntaxError");
205205
}
206206
},
207+
{
208+
name: "return value of super() should be this when super is plain function",
209+
body: function () {
210+
function A() { }
211+
212+
let s;
213+
class B extends A {
214+
constructor() {
215+
s = super();
216+
}
217+
}
218+
219+
const b = new B();
220+
assert.areEqual(b, s);
221+
}
222+
},
223+
{
224+
name: "return value of super() should be this when super is class",
225+
body: function () {
226+
class A { }
227+
228+
let s;
229+
class B extends A {
230+
constructor() {
231+
s = super();
232+
}
233+
}
234+
235+
const b = new B();
236+
assert.areEqual(b, s);
237+
}
238+
},
239+
{
240+
name: "return value of super() should be this when super is function with non-object return value",
241+
body: function () {
242+
function A() { return 4; }
243+
244+
let s;
245+
class B extends A {
246+
constructor() {
247+
s = super();
248+
}
249+
}
250+
251+
const b = new B();
252+
assert.areEqual(b, s);
253+
}
254+
},
255+
{
256+
name: "return value of super() should be this when super is function that returns an object",
257+
body: function () {
258+
function A() { return { a: 1 }; }
259+
260+
let s;
261+
class B extends A {
262+
constructor() {
263+
s = super();
264+
}
265+
}
266+
267+
const b = new B();
268+
assert.areEqual(b, s);
269+
assert.areEqual(1, b.a);
270+
}
271+
},
272+
{
273+
name: "return value of super() should be this when super is built-in type",
274+
body: function () {
275+
let s;
276+
class B extends Uint32Array {
277+
constructor() {
278+
s = super();
279+
}
280+
}
281+
282+
const b = new B();
283+
assert.areEqual(b, s);
284+
}
285+
},
207286
];
208287

209288
testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });

0 commit comments

Comments
 (0)