diff --git a/lib/IRGen/ESTreeIRGen-expr.cpp b/lib/IRGen/ESTreeIRGen-expr.cpp index 7980cc50ba7..72a7f033765 100644 --- a/lib/IRGen/ESTreeIRGen-expr.cpp +++ b/lib/IRGen/ESTreeIRGen-expr.cpp @@ -551,6 +551,19 @@ Value *ESTreeIRGen::genCallExpr(ESTree::CallExpressionNode *call) { if (curFunction()->hasLegacyClassContext()) { return genLegacyDirectSuper(call); } + if (!curFunction()->superClassNode_) { + // This is a typed class, where super() is only supported as the first + // statement of the derived constructor itself; genClassDeclaration + // rejects a constructor which doesn't start with one. SemanticResolver + // has already verified that we are lexically inside a derived + // constructor, so the only way to get here is a super() nested in an + // arrow function, which has its own FunctionContext and therefore no + // superclass, 'this' or new.target of the constructor. + Mod->getContext().getSourceErrorManager().error( + call->getSourceRange(), + "super() is only supported as the first statement of a derived class constructor"); + return Builder.getLiteralUndefined(); + } if (curFunction()->calledSuperConstructor_) { // Found another super() call than the one that actually initializes the // base class. @@ -562,9 +575,6 @@ Value *ESTreeIRGen::genCallExpr(ESTree::CallExpressionNode *call) { // Check for a super() call. // Call with the passed-in 'this'. thisVal = curFunction()->jsParams[0]; - assert( - curFunction()->superClassNode_ && - "SemanticResolver must check super() is in a class with a superclass"); callee = genExpression(curFunction()->superClassNode_); newTarget = Builder.createGetNewTargetInst( curFunction()->function->getNewTargetParam()); diff --git a/test/IRGen/flow/super-in-arrow-error.js b/test/IRGen/flow/super-in-arrow-error.js new file mode 100644 index 00000000000..ee6d49ea981 --- /dev/null +++ b/test/IRGen/flow/super-in-arrow-error.js @@ -0,0 +1,45 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// RUN: (! %hermesc -typed -dump-ir %s 2>&1 ) | %FileCheck --match-full-lines %s + +// In a typed class, super() is only supported as the first statement of the +// derived constructor. A super() nested in an arrow function must report an +// error instead of crashing IRGen. + +class A { + x: number; + constructor() { + this.x = 1; + } +} + +class B extends A { + constructor() { + super(); + (() => { + super(); + })(); + } +} +// CHECK: {{.*}}super-in-arrow-error.js:25:7: error: super() is only supported as the first statement of a derived class constructor +// CHECK-NEXT: super(); +// CHECK-NEXT: ^~~~~~~ + +class C extends A { + constructor() { + super(); + var f = async () => { + super(); + }; + } +} +// CHECK: {{.*}}super-in-arrow-error.js:37:7: error: super() is only supported as the first statement of a derived class constructor +// CHECK-NEXT: super(); +// CHECK-NEXT: ^~~~~~~ + +// CHECK: Emitted 2 errors. exiting.