From 88da5edebb4efb7d1639b707c9e3ae02b89e9a32 Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Wed, 4 Aug 2021 23:45:51 -0400 Subject: [PATCH] fix #1498: variable shadowing broke class lowering --- CHANGELOG.md | 22 +++++++++++++++++++ .../bundler/snapshots/snapshots_lower.txt | 12 +++++++++- internal/js_parser/js_parser_lower.go | 6 ++--- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 043ce49962..2d0716b2e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,28 @@ } ``` +* Fix lowering of static private methods in class expressions ([#1498](https://github.com/evanw/esbuild/issues/1498)) + + Previously static private methods were lowered incorrectly when present in class expressions. The class expression itself was missing in the output due to an oversight (variable shadowing). This issue has been fixed: + + ```js + // Original code + (class { + static #x() {} + }); + + // Old output (with --target=es6) + var _x, _a, x_fn; + __privateAdd(_a, _x), _x = new WeakSet(), x_fn = function() { + }, __privateAdd(_a, _x), _a; + + // New output (with --target=es6) + var _x, _a, x_fn; + _a = class { + }, _x = new WeakSet(), x_fn = function() { + }, __privateAdd(_a, _x), _a; + ``` + ## 0.12.17 * Fix a bug with private fields and logical assignment operators ([#1418](https://github.com/evanw/esbuild/issues/1418)) diff --git a/internal/bundler/snapshots/snapshots_lower.txt b/internal/bundler/snapshots/snapshots_lower.txt index f830367229..e0b34916a2 100644 --- a/internal/bundler/snapshots/snapshots_lower.txt +++ b/internal/bundler/snapshots/snapshots_lower.txt @@ -335,7 +335,17 @@ _foo = new WeakMap(); TestLowerPrivateClassExpr2020NoBundle ---------- /out.js ---------- var _field, _method, method_fn, _a, _staticField, _staticMethod, staticMethod_fn; -export let Foo = (__privateAdd(_a, _staticMethod), _field = new WeakMap(), _method = new WeakSet(), method_fn = function() { +export let Foo = (_a = class { + constructor() { + __privateAdd(this, _method); + __privateAdd(this, _field, void 0); + } + foo() { + var _a2; + __privateSet(this, _field, __privateMethod(this, _method, method_fn).call(this)); + __privateSet(Foo, _staticField, __privateMethod(_a2 = Foo, _staticMethod, staticMethod_fn).call(_a2)); + } +}, _field = new WeakMap(), _method = new WeakSet(), method_fn = function() { }, _staticField = new WeakMap(), _staticMethod = new WeakSet(), staticMethod_fn = function() { }, __privateAdd(_a, _staticMethod), __privateAdd(_a, _staticField, void 0), _a); diff --git a/internal/js_parser/js_parser_lower.go b/internal/js_parser/js_parser_lower.go index fd9d49d97c..d430deea8e 100644 --- a/internal/js_parser/js_parser_lower.go +++ b/internal/js_parser/js_parser_lower.go @@ -2269,7 +2269,7 @@ func (p *parser) lowerClass(stmt js_ast.Stmt, expr js_ast.Expr, shadowRef js_ast } // Add every newly-constructed instance into this map - expr = p.callRuntime(loc, "__privateAdd", []js_ast.Expr{ + methodExpr := p.callRuntime(loc, "__privateAdd", []js_ast.Expr{ target, {Loc: loc, Data: &js_ast.EIdentifier{Ref: ref}}, }) @@ -2285,10 +2285,10 @@ func (p *parser) lowerClass(stmt js_ast.Stmt, expr js_ast.Expr, shadowRef js_ast // if prop.IsStatic { // Move this property to an assignment after the class ends - staticPrivateMethods = append(staticPrivateMethods, expr) + staticPrivateMethods = append(staticPrivateMethods, methodExpr) } else { // Move this property to an assignment inside the class constructor - instancePrivateMethods = append(instancePrivateMethods, js_ast.Stmt{Loc: loc, Data: &js_ast.SExpr{Value: expr}}) + instancePrivateMethods = append(instancePrivateMethods, js_ast.Stmt{Loc: loc, Data: &js_ast.SExpr{Value: methodExpr}}) } }