From 566f05f74ddc90bf6f89dd6135fdf77269503555 Mon Sep 17 00:00:00 2001
From: Josh Goldberg <josh@fullscreenmario.com>
Date: Mon, 9 Sep 2019 17:45:01 -0400
Subject: [PATCH 1/4] Corrected ES5 for-in destructuring binding emit

Although it's not permitted in the checker to use an array or object binding pattern ("destructuring") as the iterating variable in a `for..in` loop, TypeScript can still output the syntax. This corrects the emitter to correctly destructure the variables in the body of the loop. Previously they were incorrectly being bound in the iteration statement.

I'm not particularly satisfied with how this code shaped up. There's some duplication in the `convertForInStatementForLoop*` functions, but just small enough of it that I didn't extract into a shared function... does anyone see a cleaner approach?
---
 src/compiler/transformers/es2015.ts           | 117 +++++++++++++++---
 .../for-inStatementsDestructuring.errors.txt  |  38 +++++-
 .../for-inStatementsDestructuring.js          |  33 ++++-
 .../for-inStatementsDestructuring.symbols     |  26 +++-
 .../for-inStatementsDestructuring.types       |  31 +++++
 .../for-inStatementsDestructuring2.js         |   4 +-
 .../for-inStatementsDestructuring.ts          |  11 +-
 7 files changed, 232 insertions(+), 28 deletions(-)

diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts
index b86db73787901..2d963bab53d26 100644
--- a/src/compiler/transformers/es2015.ts
+++ b/src/compiler/transformers/es2015.ts
@@ -145,7 +145,15 @@ namespace ts {
         loopOutParameters: LoopOutParameter[];
     }
 
-    type LoopConverter = (node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convertedLoopBodyStatements: Statement[] | undefined, ancestorFacts: HierarchyFacts) => Statement;
+    type DirectLoopConverter = (node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convertedLoopBodyStatements: Statement[] | undefined, ancestorFacts: HierarchyFacts) => Statement;
+    type TransformedLoopConverter = (node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convertedLoopBodyStatements: Statement[] | undefined, ancestorFacts: HierarchyFacts, initializerFunction: IterationStatementPartFunction<VariableDeclarationList> | undefined, bodyFunction: IterationStatementPartFunction<Statement[]>) => Statement;
+
+    interface IterationStatementPartFunction<T> {
+        functionName: Identifier;
+        functionDeclaration: Statement;
+        containsYield: boolean;
+        part: T;
+    }
 
     // Facts we track as we traverse the tree
     const enum HierarchyFacts {
@@ -2226,9 +2234,9 @@ namespace ts {
             }
         }
 
-        function visitIterationStatementWithFacts(excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts, node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convert?: LoopConverter) {
+        function visitIterationStatementWithFacts(excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts, node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convertDirectly?: DirectLoopConverter, convertWithTransform?: TransformedLoopConverter) {
             const ancestorFacts = enterSubtree(excludeFacts, includeFacts);
-            const updated = convertIterationStatementBodyIfNecessary(node, outermostLabeledStatement, ancestorFacts, convert);
+            const updated = convertIterationStatementBodyIfNecessary(node, outermostLabeledStatement, ancestorFacts, convertDirectly, convertWithTransform);
             exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
             return updated;
         }
@@ -2254,19 +2262,23 @@ namespace ts {
                 HierarchyFacts.ForInOrForOfStatementExcludes,
                 HierarchyFacts.ForInOrForOfStatementIncludes,
                 node,
-                outermostLabeledStatement);
+                outermostLabeledStatement,
+                convertForInStatementForLoopDirectly,
+                convertForInStatementForLoopTransformed);
         }
 
         function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined): VisitResult<Statement> {
+            const convert = compilerOptions.downlevelIteration ? convertForOfStatementForIterable : convertForOfStatementForArray;
             return visitIterationStatementWithFacts(
                 HierarchyFacts.ForInOrForOfStatementExcludes,
                 HierarchyFacts.ForInOrForOfStatementIncludes,
                 node,
                 outermostLabeledStatement,
-                compilerOptions.downlevelIteration ? convertForOfStatementForIterable : convertForOfStatementForArray);
+                convert,
+                convert);
         }
 
-        function convertForOfStatementHead(node: ForOfStatement, boundValue: Expression, convertedLoopBodyStatements: Statement[]) {
+        function convertForStatementHead(node: ForInStatement | ForOfStatement, boundValue: Expression, convertedLoopBodyStatements: Statement[]) {
             const statements: Statement[] = [];
             const initializer = node.initializer;
             if (isVariableDeclarationList(initializer)) {
@@ -2364,6 +2376,78 @@ namespace ts {
                 EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps
             );
         }
+         
+        function convertForInStatementForLoopDirectly(node: ForInStatement, outermostLabeledStatement: LabeledStatement, convertedLoopBodyStatements: Statement[]): Statement {
+            // The following ES2015 code:
+            //
+            //    for (var [a, b] in expr) { }
+            //
+            // should be emitted as
+            //
+            //    for (var _a in expr) {
+            //        var a = _a[0], b = _a[1];
+            //    }
+            //
+            // where _a is a temp emitted to capture the LHS binding.
+            const initializerBinding = getForInInitializerBindingDeclaration(node);
+            if (initializerBinding) {
+                return convertForInStatementWithInitializerBinding(node, convertedLoopBodyStatements, initializerBinding);
+            }
+            
+            return restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement, convertedLoopState && resetLabel);
+        }
+         
+        function convertForInStatementForLoopTransformed(node: ForInStatement, outermostLabeledStatement: LabeledStatement, convertedLoopBodyStatements: Statement[], _ancestorFacts: HierarchyFacts, initializerFunction: IterationStatementPartFunction<VariableDeclarationList> | undefined, bodyFunction: IterationStatementPartFunction<Statement[]>): Statement {
+            // The following ES2015 code:
+            //
+            //    for (let [a, b] in expr) { ... }
+            //
+            // should be emitted as
+            //
+            //    var _loop_1 = function (_a) {
+            //      var a = _a[0], b = _a[1];
+            //      ...
+            //    }
+            //    for (var _a in expr) {
+            //        _loop_1(a);
+            //    }
+            //
+            // where _a is a temp emitted to capture the LHS binding.
+            const initializerBinding = getForInInitializerBindingDeclaration(node);
+            if (initializerBinding) {
+                return convertForInStatementWithInitializerBinding(node, convertedLoopBodyStatements, initializerBinding);
+            }
+
+            const clone = convertIterationStatementCore(node, initializerFunction, createBlock(bodyFunction.part, /*multiLine*/ true));
+            aggregateTransformFlags(clone);
+            return restoreEnclosingLabel(clone, outermostLabeledStatement, convertedLoopState && resetLabel);
+}
+
+        function convertForInStatementWithInitializerBinding(node: ForInStatement, convertedLoopBodyStatements: Statement[], _initializerBinding: VariableDeclaration) {
+            const tempInitializer = createTempVariable(/*recordTempVariable*/ undefined);
+
+            return ts.createForIn(
+                ts.createVariableDeclarationList([ts.createVariableDeclaration(tempInitializer)]),
+                node.expression,
+                convertForStatementHead(
+                    node,
+                    tempInitializer,
+                    convertedLoopBodyStatements,
+                )
+            );
+        }
+
+        function getForInInitializerBindingDeclaration(node: ForInStatement) {
+            if (!isVariableDeclarationList(node.initializer) || node.initializer.declarations.length === 0) {
+                return undefined;
+            }
+
+            const declaration = node.initializer.declarations[0];
+
+            return isArrayBindingPattern(declaration.name) || isObjectBindingPattern(declaration.name)
+                ? declaration
+                : undefined;
+        }
 
         function convertForOfStatementForArray(node: ForOfStatement, outermostLabeledStatement: LabeledStatement, convertedLoopBodyStatements: Statement[]): Statement {
             // The following ES6 code:
@@ -2420,7 +2504,7 @@ namespace ts {
                         node.expression
                     ),
                     /*incrementor*/ setTextRange(createPostfixIncrement(counter), node.expression),
-                    /*statement*/ convertForOfStatementHead(
+                    /*statement*/ convertForStatementHead(
                         node,
                         createElementAccess(rhsReference, counter),
                         convertedLoopBodyStatements
@@ -2468,7 +2552,7 @@ namespace ts {
                         ),
                         /*condition*/ createLogicalNot(createPropertyAccess(result, "done")),
                         /*incrementor*/ createAssignment(result, next),
-                        /*statement*/ convertForOfStatementHead(
+                        /*statement*/ convertForStatementHead(
                             node,
                             createPropertyAccess(result, "value"),
                             convertedLoopBodyStatements
@@ -2671,7 +2755,7 @@ namespace ts {
             }
         }
 
-        function convertIterationStatementBodyIfNecessary(node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, ancestorFacts: HierarchyFacts, convert?: LoopConverter): VisitResult<Statement> {
+        function convertIterationStatementBodyIfNecessary(node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, ancestorFacts: HierarchyFacts, convertDirectly?: DirectLoopConverter, convertWithTransform?: TransformedLoopConverter): VisitResult<Statement> {
             if (!shouldConvertIterationStatement(node)) {
                 let saveAllowedNonLabeledJumps: Jump | undefined;
                 if (convertedLoopState) {
@@ -2681,8 +2765,8 @@ namespace ts {
                     convertedLoopState.allowedNonLabeledJumps = Jump.Break | Jump.Continue;
                 }
 
-                const result = convert
-                    ? convert(node, outermostLabeledStatement, /*convertedLoopBodyStatements*/ undefined, ancestorFacts)
+                const result = convertDirectly
+                    ? convertDirectly(node, outermostLabeledStatement, /*convertedLoopBodyStatements*/ undefined, ancestorFacts)
                     : restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement, convertedLoopState && resetLabel);
 
                 if (convertedLoopState) {
@@ -2713,8 +2797,8 @@ namespace ts {
 
             let loop: Statement;
             if (bodyFunction) {
-                if (convert) {
-                    loop = convert(node, outermostLabeledStatement, bodyFunction.part, ancestorFacts);
+                if (convertWithTransform) {
+                    loop = convertWithTransform(node, outermostLabeledStatement, bodyFunction.part, ancestorFacts, initializerFunction, bodyFunction);
                 }
                 else {
                     const clone = convertIterationStatementCore(node, initializerFunction, createBlock(bodyFunction.part, /*multiLine*/ true));
@@ -2918,13 +3002,6 @@ namespace ts {
             }
         }
 
-        interface IterationStatementPartFunction<T> {
-            functionName: Identifier;
-            functionDeclaration: Statement;
-            containsYield: boolean;
-            part: T;
-        }
-
         function createOutVariable(p: LoopOutParameter) {
             return createVariableDeclaration(p.originalName, /*type*/ undefined, p.outParamName);
         }
diff --git a/tests/baselines/reference/for-inStatementsDestructuring.errors.txt b/tests/baselines/reference/for-inStatementsDestructuring.errors.txt
index e54f2c93272a3..f324d60738137 100644
--- a/tests/baselines/reference/for-inStatementsDestructuring.errors.txt
+++ b/tests/baselines/reference/for-inStatementsDestructuring.errors.txt
@@ -1,10 +1,44 @@
 tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts(1,10): error TS2461: Type 'string' is not an array type.
 tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts(1,10): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
+tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts(2,10): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
+tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts(2,12): error TS2339: Property 'a' does not exist on type 'String'.
+tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts(2,15): error TS2339: Property 'b' does not exist on type 'String'.
+tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts(4,10): error TS2461: Type 'string' is not an array type.
+tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts(4,10): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
+tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts(8,10): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
+tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts(8,12): error TS2339: Property 'a' does not exist on type 'String'.
+tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts(8,15): error TS2339: Property 'b' does not exist on type 'String'.
 
 
-==== tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts (2 errors) ====
+==== tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts (10 errors) ====
     for (var [a, b] in []) {}
              ~~~~~~
 !!! error TS2461: Type 'string' is not an array type.
              ~~~~~~
-!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
\ No newline at end of file
+!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
+    for (var { a, b } in []) {}
+             ~~~~~~~~
+!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
+               ~
+!!! error TS2339: Property 'a' does not exist on type 'String'.
+                  ~
+!!! error TS2339: Property 'b' does not exist on type 'String'.
+    
+    for (let [a, b] in []) {
+             ~~~~~~
+!!! error TS2461: Type 'string' is not an array type.
+             ~~~~~~
+!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
+        (() => a + b);
+    }
+    
+    for (let { a, b } in []) {
+             ~~~~~~~~
+!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern.
+               ~
+!!! error TS2339: Property 'a' does not exist on type 'String'.
+                  ~
+!!! error TS2339: Property 'b' does not exist on type 'String'.
+        (() => a + b);
+    }
+    
\ No newline at end of file
diff --git a/tests/baselines/reference/for-inStatementsDestructuring.js b/tests/baselines/reference/for-inStatementsDestructuring.js
index e5e00d5b3ab56..f490e787b22ec 100644
--- a/tests/baselines/reference/for-inStatementsDestructuring.js
+++ b/tests/baselines/reference/for-inStatementsDestructuring.js
@@ -1,5 +1,34 @@
 //// [for-inStatementsDestructuring.ts]
-for (var [a, b] in []) {}
+for (var [a, b] in []) {}
+for (var { a, b } in []) {}
+
+for (let [a, b] in []) {
+    (() => a + b);
+}
+
+for (let { a, b } in []) {
+    (() => a + b);
+}
+
 
 //// [for-inStatementsDestructuring.js]
-for (var _a = void 0, a = _a[0], b = _a[1] in []) { }
+for (var _a in []) {
+    var a = _a[0], b = _a[1];
+}
+for (var _b in []) {
+    var a = _b.a, b = _b.b;
+}
+var _loop_1 = function (a_1, b_1) {
+    (function () { return a_1 + b_1; });
+};
+for (var _c in []) {
+    var a_1 = _c[0], b_1 = _c[1];
+    _loop_1(a_1, b_1);
+}
+var _loop_2 = function (a_2, b_2) {
+    (function () { return a_2 + b_2; });
+};
+for (var _d in []) {
+    var a_2 = _d.a, b_2 = _d.b;
+    _loop_2(a_2, b_2);
+}
diff --git a/tests/baselines/reference/for-inStatementsDestructuring.symbols b/tests/baselines/reference/for-inStatementsDestructuring.symbols
index fff70d63bd353..04c3a07077349 100644
--- a/tests/baselines/reference/for-inStatementsDestructuring.symbols
+++ b/tests/baselines/reference/for-inStatementsDestructuring.symbols
@@ -1,5 +1,27 @@
 === tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts ===
 for (var [a, b] in []) {}
->a : Symbol(a, Decl(for-inStatementsDestructuring.ts, 0, 10))
->b : Symbol(b, Decl(for-inStatementsDestructuring.ts, 0, 12))
+>a : Symbol(a, Decl(for-inStatementsDestructuring.ts, 0, 10), Decl(for-inStatementsDestructuring.ts, 1, 10))
+>b : Symbol(b, Decl(for-inStatementsDestructuring.ts, 0, 12), Decl(for-inStatementsDestructuring.ts, 1, 13))
+
+for (var { a, b } in []) {}
+>a : Symbol(a, Decl(for-inStatementsDestructuring.ts, 0, 10), Decl(for-inStatementsDestructuring.ts, 1, 10))
+>b : Symbol(b, Decl(for-inStatementsDestructuring.ts, 0, 12), Decl(for-inStatementsDestructuring.ts, 1, 13))
+
+for (let [a, b] in []) {
+>a : Symbol(a, Decl(for-inStatementsDestructuring.ts, 3, 10))
+>b : Symbol(b, Decl(for-inStatementsDestructuring.ts, 3, 12))
+
+    (() => a + b);
+>a : Symbol(a, Decl(for-inStatementsDestructuring.ts, 3, 10))
+>b : Symbol(b, Decl(for-inStatementsDestructuring.ts, 3, 12))
+}
+
+for (let { a, b } in []) {
+>a : Symbol(a, Decl(for-inStatementsDestructuring.ts, 7, 10))
+>b : Symbol(b, Decl(for-inStatementsDestructuring.ts, 7, 13))
+
+    (() => a + b);
+>a : Symbol(a, Decl(for-inStatementsDestructuring.ts, 7, 10))
+>b : Symbol(b, Decl(for-inStatementsDestructuring.ts, 7, 13))
+}
 
diff --git a/tests/baselines/reference/for-inStatementsDestructuring.types b/tests/baselines/reference/for-inStatementsDestructuring.types
index 547e54a574195..ce8518fcb60fd 100644
--- a/tests/baselines/reference/for-inStatementsDestructuring.types
+++ b/tests/baselines/reference/for-inStatementsDestructuring.types
@@ -4,3 +4,34 @@ for (var [a, b] in []) {}
 >b : any
 >[] : undefined[]
 
+for (var { a, b } in []) {}
+>a : any
+>b : any
+>[] : undefined[]
+
+for (let [a, b] in []) {
+>a : any
+>b : any
+>[] : undefined[]
+
+    (() => a + b);
+>(() => a + b) : () => any
+>() => a + b : () => any
+>a + b : any
+>a : any
+>b : any
+}
+
+for (let { a, b } in []) {
+>a : any
+>b : any
+>[] : undefined[]
+
+    (() => a + b);
+>(() => a + b) : () => any
+>() => a + b : () => any
+>a + b : any
+>a : any
+>b : any
+}
+
diff --git a/tests/baselines/reference/for-inStatementsDestructuring2.js b/tests/baselines/reference/for-inStatementsDestructuring2.js
index 41a6d30919f50..5c384b1c9dfa9 100644
--- a/tests/baselines/reference/for-inStatementsDestructuring2.js
+++ b/tests/baselines/reference/for-inStatementsDestructuring2.js
@@ -2,4 +2,6 @@
 for (var {a, b} in []) {}
 
 //// [for-inStatementsDestructuring2.js]
-for (var _a = void 0, a = _a.a, b = _a.b in []) { }
+for (var _a in []) {
+    var a = _a.a, b = _a.b;
+}
diff --git a/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts
index 94868ef3bd62e..d73963a82b51e 100644
--- a/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts
+++ b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts
@@ -1 +1,10 @@
-for (var [a, b] in []) {}
\ No newline at end of file
+for (var [a, b] in []) {}
+for (var { a, b } in []) {}
+
+for (let [a, b] in []) {
+    (() => a + b);
+}
+
+for (let { a, b } in []) {
+    (() => a + b);
+}

From 7cc644701caebd555dea81d684a54c78a27aed32 Mon Sep 17 00:00:00 2001
From: Josh Goldberg <josh@fullscreenmario.com>
Date: Mon, 9 Sep 2019 22:41:49 -0400
Subject: [PATCH 2/4] TSLint corrections

---
 src/compiler/transformers/es2015.ts | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts
index 2d963bab53d26..f38726136f61d 100644
--- a/src/compiler/transformers/es2015.ts
+++ b/src/compiler/transformers/es2015.ts
@@ -2376,7 +2376,7 @@ namespace ts {
                 EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps
             );
         }
-         
+
         function convertForInStatementForLoopDirectly(node: ForInStatement, outermostLabeledStatement: LabeledStatement, convertedLoopBodyStatements: Statement[]): Statement {
             // The following ES2015 code:
             //
@@ -2393,10 +2393,10 @@ namespace ts {
             if (initializerBinding) {
                 return convertForInStatementWithInitializerBinding(node, convertedLoopBodyStatements, initializerBinding);
             }
-            
+
             return restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement, convertedLoopState && resetLabel);
         }
-         
+
         function convertForInStatementForLoopTransformed(node: ForInStatement, outermostLabeledStatement: LabeledStatement, convertedLoopBodyStatements: Statement[], _ancestorFacts: HierarchyFacts, initializerFunction: IterationStatementPartFunction<VariableDeclarationList> | undefined, bodyFunction: IterationStatementPartFunction<Statement[]>): Statement {
             // The following ES2015 code:
             //
@@ -2426,8 +2426,8 @@ namespace ts {
         function convertForInStatementWithInitializerBinding(node: ForInStatement, convertedLoopBodyStatements: Statement[], _initializerBinding: VariableDeclaration) {
             const tempInitializer = createTempVariable(/*recordTempVariable*/ undefined);
 
-            return ts.createForIn(
-                ts.createVariableDeclarationList([ts.createVariableDeclaration(tempInitializer)]),
+            return createForIn(
+                createVariableDeclarationList([createVariableDeclaration(tempInitializer)]),
                 node.expression,
                 convertForStatementHead(
                     node,

From d13e0e235d4dbfa80146dde091a871fa6bf0e1f8 Mon Sep 17 00:00:00 2001
From: Josh Goldberg <josh@codecademy.com>
Date: Wed, 2 Dec 2020 23:18:36 -0500
Subject: [PATCH 3/4] Remove unrelated baseline diff

---
 .../jsDeclarationsSubclassWithExplicitNoArgumentConstructor.js  | 2 --
 1 file changed, 2 deletions(-)

diff --git a/tests/baselines/reference/jsDeclarationsSubclassWithExplicitNoArgumentConstructor.js b/tests/baselines/reference/jsDeclarationsSubclassWithExplicitNoArgumentConstructor.js
index 8abe7764586b0..42cafa5e355a0 100644
--- a/tests/baselines/reference/jsDeclarationsSubclassWithExplicitNoArgumentConstructor.js
+++ b/tests/baselines/reference/jsDeclarationsSubclassWithExplicitNoArgumentConstructor.js
@@ -23,8 +23,6 @@ var __extends = (this && this.__extends) || (function () {
         return extendStatics(d, b);
     };
     return function (d, b) {
-        if (typeof b !== "function" && b !== null)
-            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
         extendStatics(d, b);
         function __() { this.constructor = d; }
         d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());

From 898ad4ade0314258c78b48ae4d8f35b8d66d9cce Mon Sep 17 00:00:00 2001
From: Josh Goldberg <josh@codecademy.com>
Date: Wed, 2 Dec 2020 23:36:15 -0500
Subject: [PATCH 4/4] Actually, that was incorrect; it's from one of my other
 PRs..

---
 .../jsDeclarationsSubclassWithExplicitNoArgumentConstructor.js  | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tests/baselines/reference/jsDeclarationsSubclassWithExplicitNoArgumentConstructor.js b/tests/baselines/reference/jsDeclarationsSubclassWithExplicitNoArgumentConstructor.js
index 42cafa5e355a0..8abe7764586b0 100644
--- a/tests/baselines/reference/jsDeclarationsSubclassWithExplicitNoArgumentConstructor.js
+++ b/tests/baselines/reference/jsDeclarationsSubclassWithExplicitNoArgumentConstructor.js
@@ -23,6 +23,8 @@ var __extends = (this && this.__extends) || (function () {
         return extendStatics(d, b);
     };
     return function (d, b) {
+        if (typeof b !== "function" && b !== null)
+            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
         extendStatics(d, b);
         function __() { this.constructor = d; }
         d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());