@@ -6353,6 +6353,33 @@ func (p *parser) parseClass(classKeyword logger.Range, name *ast.LocRef, classOp
63536353
63546354 closeBraceLoc := p.saveExprCommentsHere()
63556355 p.lexer.Expect(js_lexer.TCloseBrace)
6356+
6357+ // TypeScript has legacy behavior that uses assignment semantics instead of
6358+ // define semantics for class fields when "useDefineForClassFields" is enabled
6359+ // (in which case TypeScript behaves differently than JavaScript, which is
6360+ // arguably "wrong").
6361+ //
6362+ // This legacy behavior exists because TypeScript added class fields to
6363+ // TypeScript before they were added to JavaScript. They decided to go with
6364+ // assignment semantics for whatever reason. Later on TC39 decided to go with
6365+ // define semantics for class fields instead. This behaves differently if the
6366+ // base class has a setter with the same name.
6367+ //
6368+ // The value of "useDefineForClassFields" defaults to false when it's not
6369+ // specified and the target is earlier than "ES2022" since the class field
6370+ // language feature was added in ES2022. However, TypeScript's "target"
6371+ // setting currently defaults to "ES3" which unfortunately means that the
6372+ // "useDefineForClassFields" setting defaults to false (i.e. to "wrong").
6373+ //
6374+ // We default "useDefineForClassFields" to true (i.e. to "correct") instead.
6375+ // This is partially because our target defaults to "esnext", and partially
6376+ // because this is a legacy behavior that no one should be using anymore.
6377+ // Users that want the wrong behavior can either set "useDefineForClassFields"
6378+ // to false in "tsconfig.json" explicitly, or set TypeScript's "target" to
6379+ // "ES2021" or earlier in their in "tsconfig.json" file.
6380+ useDefineForClassFields := !p.options.ts.Parse || p.options.ts.Config.UseDefineForClassFields == config.True ||
6381+ (p.options.ts.Config.UseDefineForClassFields == config.Unspecified && p.options.ts.Config.Target != config.TSTargetBelowES2022)
6382+
63566383 return js_ast.Class{
63576384 ClassKeyword: classKeyword,
63586385 Decorators: classOpts.decorators,
@@ -6362,31 +6389,15 @@ func (p *parser) parseClass(classKeyword logger.Range, name *ast.LocRef, classOp
63626389 Properties: properties,
63636390 CloseBraceLoc: closeBraceLoc,
63646391
6365- // TypeScript has legacy behavior that uses assignment semantics instead of
6366- // define semantics for class fields when "useDefineForClassFields" is enabled
6367- // (in which case TypeScript behaves differently than JavaScript, which is
6368- // arguably "wrong").
6369- //
6370- // This legacy behavior exists because TypeScript added class fields to
6371- // TypeScript before they were added to JavaScript. They decided to go with
6372- // assignment semantics for whatever reason. Later on TC39 decided to go with
6373- // define semantics for class fields instead. This behaves differently if the
6374- // base class has a setter with the same name.
6375- //
6376- // The value of "useDefineForClassFields" defaults to false when it's not
6377- // specified and the target is earlier than "ES2022" since the class field
6378- // language feature was added in ES2022. However, TypeScript's "target"
6379- // setting currently defaults to "ES3" which unfortunately means that the
6380- // "useDefineForClassFields" setting defaults to false (i.e. to "wrong").
6381- //
6382- // We default "useDefineForClassFields" to true (i.e. to "correct") instead.
6383- // This is partially because our target defaults to "esnext", and partially
6384- // because this is a legacy behavior that no one should be using anymore.
6385- // Users that want the wrong behavior can either set "useDefineForClassFields"
6386- // to false in "tsconfig.json" explicitly, or set TypeScript's "target" to
6387- // "ES2021" or earlier in their in "tsconfig.json" file.
6388- UseDefineForClassFields: !p.options.ts.Parse || p.options.ts.Config.UseDefineForClassFields == config.True ||
6389- (p.options.ts.Config.UseDefineForClassFields == config.Unspecified && p.options.ts.Config.Target != config.TSTargetBelowES2022),
6392+ // Always lower standard decorators if they are present and TypeScript's
6393+ // "useDefineForClassFields" setting is false even if the configured target
6394+ // environment supports decorators. This setting changes the behavior of
6395+ // class fields, and so we must lower decorators so they behave correctly.
6396+ ShouldLowerStandardDecorators: (!p.options.ts.Parse && p.options.unsupportedJSFeatures.Has(compat.Decorators)) ||
6397+ (p.options.ts.Parse && p.options.ts.Config.ExperimentalDecorators != config.True &&
6398+ (p.options.unsupportedJSFeatures.Has(compat.Decorators) || !useDefineForClassFields)),
6399+
6400+ UseDefineForClassFields: useDefineForClassFields,
63906401 }
63916402}
63926403
0 commit comments