Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/ast/G.zig
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub const Class = struct {
close_brace_loc: logger.Loc = logger.Loc.Empty,
properties: []Property = &([_]Property{}),
has_decorators: bool = false,
should_lower_standard_decorators: bool = false,

pub fn canBeMoved(this: *const Class) bool {
if (this.extends != null)
Expand Down Expand Up @@ -134,6 +135,7 @@ pub const Property = struct {
declare,
abstract,
class_static_block,
auto_accessor,

pub fn jsonStringify(self: @This(), writer: anytype) !void {
return try writer.write(@tagName(self));
Expand Down
21 changes: 19 additions & 2 deletions src/ast/P.zig
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ pub fn NewParser_(
pub const parseStmtsUpTo = parse_zig.parseStmtsUpTo;
pub const parseAsyncPrefixExpr = parse_zig.parseAsyncPrefixExpr;
pub const parseTypeScriptDecorators = parse_zig.parseTypeScriptDecorators;
pub const parseStandardDecorator = parse_zig.parseStandardDecorator;
pub const parseTypeScriptNamespaceStmt = parse_zig.parseTypeScriptNamespaceStmt;
pub const parseTypeScriptImportEqualsStmt = parse_zig.parseTypeScriptImportEqualsStmt;
pub const parseTypescriptEnumStmt = parse_zig.parseTypescriptEnumStmt;
Expand Down Expand Up @@ -136,6 +137,10 @@ pub fn NewParser_(
pub const findSymbol = symbols_zig.findSymbol;
pub const findSymbolWithRecordUsage = symbols_zig.findSymbolWithRecordUsage;

const lowerDecorators_zig = @import("./lowerDecorators.zig").LowerDecorators(parser_feature__typescript, parser_feature__jsx, parser_feature__scan_only);
pub const lowerStandardDecoratorsStmt = lowerDecorators_zig.lowerStandardDecoratorsStmt;
pub const lowerStandardDecoratorsExpr = lowerDecorators_zig.lowerStandardDecoratorsExpr;

macro: MacroState = undefined,
allocator: Allocator,
options: Parser.Options,
Expand Down Expand Up @@ -486,6 +491,10 @@ pub fn NewParser_(
/// Used for react refresh, it must be able to insert `const _s = $RefreshSig$();`
nearest_stmt_list: ?*ListManaged(Stmt) = null,

/// Name from assignment context for anonymous decorated class expressions.
/// Set before visitExpr, consumed by lowerStandardDecoratorsImpl.
decorator_class_name: ?[]const u8 = null,

Comment on lines +494 to +497

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider private field prefix if this is internal-only

If decorator_class_name isn’t part of the public parser state API, prefer #decorator_class_name and adjust accessors accordingly.

As per coding guidelines: Use the # prefix for private fields in Zig structs, e.g., struct { #foo: u32 };

🤖 Prompt for AI Agents
In `@src/ast/P.zig` around lines 494 - 497, The field decorator_class_name is
currently public but intended internal-only; rename it to `#decorator_class_name`
and update any direct references and accessor usage accordingly (e.g.,
reads/writes in visitExpr and lowerStandardDecoratorsImpl) to use the new
private-field name, and adjust any getters/setters or patterns that access it so
they compile with Zig's private field syntax.

const RecentlyVisitedTSNamespace = struct {
expr: Expr.Data = Expr.empty.data,
map: ?*js_ast.TSNamespaceMemberMap = null,
Expand Down Expand Up @@ -3759,7 +3768,10 @@ pub fn NewParser_(
}
},
else => {
Output.panic("Unexpected type in export default", .{});
// Standard decorator lowering can produce non-class
// statements as the export default value; conservatively
// assume they have side effects.
return false;
},
}
},
Expand Down Expand Up @@ -4857,6 +4869,11 @@ pub fn NewParser_(
) []Stmt {
switch (stmtorexpr) {
.stmt => |stmt| {
// Standard decorator lowering path (for both JS and TS files)
if (stmt.data.s_class.class.should_lower_standard_decorators) {
return p.lowerStandardDecoratorsStmt(stmt);
}
Comment on lines +4872 to +4875

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Please add/verify a regression for export default class with standard decorators.
A crash for this case was reported; ensure this path routes through lowerStandardDecoratorsStmt without panicking.

🤖 Prompt for AI Agents
In `@src/ast/P.zig` around lines 4872 - 4875, The code path for "export default
class" with standard decorators can panic instead of routing through the
standard decorator lowering; ensure that when a statement is an exported default
class whose should_lower_standard_decorators flag is set, it returns
p.lowerStandardDecoratorsStmt(stmt) (use the existing check of
stmt.data.s_class.class.should_lower_standard_decorators and the
lowerStandardDecoratorsStmt function) and does not take any alternative path
that can panic, and add/verify a regression test that parses/transforms an
`export default class` with at least one standard decorator to confirm the
lowering occurs without panic.


if (comptime !is_typescript_enabled) {
if (!stmt.data.s_class.class.has_decorators) {
var stmts = p.allocator.alloc(Stmt, 1) catch unreachable;
Expand Down Expand Up @@ -5007,7 +5024,7 @@ pub fn NewParser_(
}
}
},
.spread, .declare => {}, // not allowed in a class
.spread, .declare, .auto_accessor => {}, // not allowed in a class (auto_accessor is standard decorators only)
.class_static_block => {}, // not allowed to decorate this
}
}
Expand Down
Loading