Skip to content

A shadowed variable is generated in a an async function with a default parameter declared as a static property of a class when targeting ES5.Β #57897

@iclanton

Description

@iclanton

πŸ”Ž Search Terms

"shadowed", "shadowed variable", "generator"

πŸ•— Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play?target=1&ts=5.4.3#code/MYGwhgzhAEAa0G8BQ1oAcCuAjEBLY0EALmEftGNALwUQCeAdgQBQQD2AtgKYBqYATgC5oWNmxBcwDatCL8MXAJTUAfIhSpo-LkQz9pYAO5hcROADoszRQG4NAXzsbMOcsVLksMyIxbKqasiaWjp60gBEAOIA8tEAIuF2qI5I9khIACZcoAJc0DlQ6PxswFyFQYQkZARcAB6mzMBsWcIMGBxYXPyKrVwAbl12aUiw5mDWGuZEABZcDI1sDOwS5iBsAOaKk8CkwNPM1qrqwU1L4lzmXcX8zOEAQgCCCbYaqGjFpVCX9UTMAIwvZIvIA

πŸ’» Code

class X {
  public static a = async (someVar: boolean = true) => {
    return await X.b();
  };

  public static b = async () => {
    return "GOOD";
  };
}

declare class process {
  static exit(code: number): never;
}

X.a()
  .then(console.log)
  .catch(() => {
    console.error("BAD");
    process.exit(1);
  });

πŸ™ Actual behavior

Between TS v5.4.2 and TS v5.3.3, the generated code from the above code sample changes to shadow the _a variable in the outer closure. See diff below:

var X = /** @class */ (function () {
    function X() {
    }
    var _a;
    _a = X;
-    X.a = function (someVar) {
-        if (someVar === void 0) { someVar = true; }
-        return __awaiter(_a, void 0, void 0, function () {
-            return __generator(_a, function (_b) {
-                switch (_b.label) {
+    X.a = function () {
+        var args_1 = [];
+        for (var _i = 0; _i < arguments.length; _i++) {
+            args_1[_i] = arguments[_i];
+        }
+        return __awaiter(_a, __spreadArray([], args_1, true), void 0, function (someVar) {
+            if (someVar === void 0) { someVar = true; }
+            return __generator(_a, function (_a) {
+                switch (_a.label) {
                     case 0: return [4 /*yield*/, _a.b()];
-                    case 1: return [2 /*return*/, _b.sent()];
+                    case 1: return [2 /*return*/, _a.sent()];
                }
            });
        });
    };
    X.b = function () { return __awaiter(_a, void 0, void 0, function () {
        return __generator(_a, function (_b) {
            return [2 /*return*/, "GOOD"];
        });
    }); };
    return X;
}());
X.a()
    .then(console.log)
    .catch(function () {
    console.error("BAD");
    process.exit(1);
});

Note that helpers have been omitted from this code sample.

Notice that in the context of the function, the class/function X is assigned to a variable _a in the "ambient" context of the class. In TS v5.3.3, the async state machine's state variable is declared as _b, but in TS v.5.4.2 is appears as if the context is lost when the state machine is generated, so the state is declared as _a, shadowing the earlier-declared _a.

πŸ™‚ Expected behavior

Expected that the async state machine's state variable does not shadow another variable.

Additional information about the issue

No response

This issue was found by @ipip2005.

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions