Repository navigation
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Essentials Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 10 included reviews per hour; 7 remain after this review. WalkthroughThe parser now propagates decorator names for anonymous named class expressions used with ChangesDecorator name propagation
Suggested reviewers: Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to The logical-assignment decorator naming change is covered for its intended operators and exclusions, with no actionable merge risk identified. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Comment |
|
Updated 7:48 PM PT - Sep 13th, 2026
✅ @robobun, your commit 92dcfe74af2739995025def4e17f56a6a7bbbbd6 passed in 🧪 To try this PR locally: bunx bun-pr 38924That installs a local version of the PR into your bun-38924 --bun |
There was a problem hiding this comment.
LGTM — extends the existing decorator_class_name propagation from = to the three logical assignment operators, matching the spec's NamedEvaluation rule.
What was reviewed:
- Confirmed
??=/||=/&&=perform NamedEvaluation per ECMA-262 §13.15.2 while arithmetic compound assigns do not — the operator set is exactly right. - The save/restore of
prev_decorator_class_nameat lines 121/182 already brackets all right-operand visits, so the new arms are covered without further changes. - Checked the sibling
decorator_class_namesites invisit/mod.rs,visit_stmt.rsandvisit_expr.rs— they cover declarators, destructuring defaults, property values andexport default, none of which can carry a logical operator, so this is the only site that needed changing. - Tests cover all three operators (method + class decorator paths), the chained
Outer = Inner ??= …case, and negative guards for named classes, member targets, nested classes, and+=.
Extended reasoning...
Overview
The PR extends one condition in src/js_parser/visit/visit_binary.rs: the block that records the assignment target's identifier name into p.decorator_class_name before visiting the right operand now fires for BinNullishCoalescingAssign, BinLogicalOrAssign and BinLogicalAndAssign in addition to BinAssign. Three new test.concurrent blocks are added to test/bundler/transpiler/es-decorators.test.ts.
Security risks
None. This is compile-time transpiler metadata (the .name given to a lowered anonymous class expression and the context.name seen by a class decorator). There is no user-input parsing, allocation sizing, or FFI change.
Level of scrutiny
Low-to-medium. The Rust change is a mechanical widening of an equality check into a four-arm matches!. Everything around it — the was_anonymous_named_expr gate, the EClass + should_lower_standard_decorators check, the EIdentifier left-side check, and the prev_decorator_class_name save/restore around the visit — is unchanged and already exercised by the existing BinAssign path. I verified that the restore at line 182 runs after every branch of the operator-dispatch match, so setting the name for the three new operators cannot leak into unrelated visits.
The spec claim checks out: ECMA-262 §13.15.2 defines the runtime semantics for &&=, ||= and ??= to call NamedEvaluation of the RHS with the LHS reference name when the RHS is an anonymous function/class definition, exactly as = does; the arithmetic/bitwise compound assignments do not. So the four-operator set is complete and does not over-apply.
Other factors
- The chained-assignment test (
Outer = Inner ??= class {…}→ nameInner) confirms the inner-most NamedEvaluation position wins, which is what the save/restore stacking already produces. - Negative guards prove the change doesn't over-apply: an explicit class name still wins (
is_anonymous_namedis false), a member-expression target is still excluded (EIdentifiergate), a class not directly on the RHS is still excluded (EClassgate), and+=is still excluded (operator gate). - I checked the other
decorator_class_namewrite sites (visit/mod.rsforlet x = …and destructuring/parameter defaults,visit_stmt.rsforexport default,visit_expr.rsfor object property values and array-pattern defaults). None of those grammatical positions accept a logical assignment operator, sovisit_binary.rsis indeed the only site that needed this change, as the PR description states. - Tests use
test.concurrentper repo convention for independent subprocess-spawning tests, assertstderrbeforeexitCode, and use exacttoEqualon structured JSON output.
There was a problem hiding this comment.
LGTM — extends the existing decorator_class_name propagation from = to ??=/||=/&&=, which are exactly the assignment operators the spec defines to perform NamedEvaluation.
What was reviewed:
- Confirmed the four-operator set matches the ECMAScript NamedEvaluation rule; compound arithmetic/bitwise assigns are correctly excluded.
- The save/restore of
prev_decorator_class_namewas already in place, so the chainedOuter = Inner ??= class {}case and nested visits behave the same as for=. - New tests cover all three operators (method + class decorator paths), plus negative guards for explicit names, member targets, nested classes, and
+=. - The comment-cop bot flag on line 124 looks like a false positive — the added line is a one-sentence spec citation, not a workaround justification.
Extended reasoning...
Overview
This PR widens a single condition in src/js_parser/visit/visit_binary.rs:124 so that p.decorator_class_name is recorded not only for BinAssign but also for BinNullishCoalescingAssign, BinLogicalOrAssign, and BinLogicalAndAssign. The rest of the block (anonymous-class check, should_lower_standard_decorators gate, identifier-only LHS, save/restore of the previous value) is unchanged. Three new test.concurrent blocks are added to test/bundler/transpiler/es-decorators.test.ts.
Security risks
None. This is a transpiler naming fix affecting the .name property and context.name of lowered decorated class expressions. No untrusted input parsing, no memory management, no FFI.
Level of scrutiny
Low-to-medium. The change is a mechanical widening of an existing, already-correct pattern to three sibling operators. I verified against the ECMAScript spec that exactly =, &&=, ||=, and ??= perform NamedEvaluation of an anonymous RHS with an identifier LHS — the arithmetic/bitwise compound assignments do not, and the code correctly excludes them. The consumer side in visit_expr.rs (decorator_name_from_context = p.decorator_class_name) reads the value the same way regardless of which operator set it, so no downstream change is needed.
Other factors
- Test coverage is thorough for a change this size: positive cases for each operator via both the method-decorator path (
.namewas_class) and the class-decorator path (context.namewas""), plus negative guards (explicitly named class, member-expression target, class nested inside the RHS,+=) that pass before and after — so the change is scoped precisely to the spec-mandated cases. - No CODEOWNERS entry covers these files.
- The github-actions "comment-cop" inline flag on the two-line comment appears to be a false positive: the added second line ("Only these four operators perform NamedEvaluation of the right side") is a concise spec citation explaining a non-obvious operator set, not a paragraph justifying a workaround. Per the repo's own guidance, that's exactly the kind of comment that belongs.
- No prior human review comments to address; the bug-hunting system found nothing.
There was a problem hiding this comment.
LGTM — small, spec-aligned extension of the existing = NamedEvaluation path to cover ??=, ||= and &&=.
What was reviewed:
- Verified the four operators listed are exactly the assignment operators the spec defines NamedEvaluation for;
+=and other compound ops are correctly excluded. - Confirmed the save/restore of
prev_decorator_class_nameand theEClass/should_lower_standard_decorators/EIdentifierguards are unchanged, so member targets and non-direct RHS classes stay excluded. - Checked the new tests cover method-decorator, class-decorator (
context.name), chained assignment, accessor-only lowering, and negative guards (explicit name, member target, nested class,+=). - The comment-cop bot's feedback was addressed in 659065b (comment is now one line).
Extended reasoning...
Overview
This PR extends the decorator_class_name propagation in visit_right_and_finish (src/js_parser/visit/visit_binary.rs) from BinAssign alone to also include the three logical assignment operators. This makes lowered anonymous decorated classes assigned via ??=/||=/&&= receive the correct .name and class-decorator context.name, matching what the engine would produce natively per the NamedEvaluation rule. Three new test.concurrent blocks in es-decorators.test.ts cover the positive cases and the negative guards.
Security risks
None. This is a transpiler correctness fix that only affects the name string threaded through the standard-decorator lowering. No parsing of untrusted lengths, no allocation changes, no new code paths.
Level of scrutiny
Low-to-medium. The Rust diff is a single condition change — replacing an equality check with a four-arm matches! — inside an existing well-guarded block. The surrounding save/restore of p.decorator_class_name and the inner EClass → should_lower_standard_decorators → EIdentifier gates are untouched, so the new operators inherit exactly the same restrictions as = already had. The spec claim (only = and the three logical assignments perform NamedEvaluation, not arithmetic/bitwise compound assignments) is accurate.
Other factors
- The github-actions comment-cop flagged a long comment on an earlier commit; commit 659065b shortened it to a single line, which is what the diff now shows.
- Test coverage is thorough: all three operators for both method and class decorators, the chained
Outer = Inner ??= class {}case (correctly namesInner), an accessor-only class (lowered without decorators), and four guard cases confirming explicit names, member targets, nested classes, and+=are still excluded. Tests usetest.concurrentand the existingrunDecoratorhelper, matching file conventions. - The PR description confirms cross-checking against Node's native behavior and passing the full decorator test suite plus clippy/fmt.
|
Status: rebased onto main. The former base, #38757, is closed because #40833 superseded it. Reproduced on a debug build of main (09bb546) with this file: const seen = [];
function dec(cls, ctx) { seen.push(ctx.name); }
let a; a ??= @dec class {};
let b = null; b ||= @dec class {};
let c = 1; c &&= @dec class {};
let d; d = @dec class {};
console.log(JSON.stringify([seen, [a.name, b.name, c.name, d.name]]));Main prints Tests: The reason for the stack no longer applies. The lowering on main passes the recorded name to Latest push (92dcfe7): |
659065b to
d33bb32
Compare
There was a problem hiding this comment.
LGTM — extends the existing decorator_class_name propagation from = to the three logical assignment operators, matching the spec's NamedEvaluation rule.
What was reviewed:
- Confirmed
=,??=,||=,&&=are exactly the assignment operators that perform NamedEvaluation per ECMA-262; compound arithmetic/bitwise ops are correctly excluded. - The save/restore of
prev_decorator_class_namearoundvisit_expris unchanged, so no leakage into unrelated right-hand expressions. - Traced
decorator_class_nameto its consumer invisit_expr.rs(e_class) — the new operators reach it via the samep.visit_expr(&mut e_.right)path asBinAssignalready did. - Tests cover the positive matrix,
context.namefor class decorators, negative guards (named class, member target, nested,+=), and that no class binding is introduced.
Extended reasoning...
Overview
The PR widens one condition in src/js_parser/visit/visit_binary.rs: the block that records p.decorator_class_name before visiting the right operand of an assignment now fires for BinNullishCoalescingAssign, BinLogicalOrAssign and BinLogicalAndAssign in addition to BinAssign. Everything else — the was_anonymous_named_expr guard, the EClass+should_lower_standard_decorators guard, the EIdentifier left-hand guard, and the save/restore of the previous value — is byte-identical to before. Four new test.concurrent blocks in test/bundler/transpiler/es-decorators.test.ts exercise the fix and pin the negative cases.
Security risks
None. This is a parser-visitor change that only affects what string is threaded through to the standard-decorator lowering as the class's inferred .name. No untrusted input handling, no memory management, no FFI/JSC surface.
Level of scrutiny
Low-to-medium. The Rust change is a one-condition widening at a site that already handled BinAssign; the mechanism (decorator_class_name → e_class → name_from_context in the lowering) is pre-existing and unchanged. I checked the spec claim: ECMA-262 gives =, &&=, ||= and ??= the NamedEvaluation step for an anonymous function/class RHS with an identifier LHS, and no other assignment operators do, so the operator list is exactly right. The consumer side in visit_expr.rs reads p.decorator_class_name and clears it before visiting the class body, so the existing scoping still holds.
Other factors
- The comment-cop bot flagged a paragraph-long comment on the first push; the author trimmed it to a single line in 659065b, which is what the current diff shows and which reads fine.
- No CODEOWNERS cover
src/js_parser/ortest/bundler/. - Tests follow the file's existing
runDecoratorharness pattern, usetest.concurrent, assert stderr/stdout/exitCode in the recommended order, and include both positive coverage (all three operators, chained assignment, accessor-only lowering, class-decoratorcontext.name) and negative guards (explicit name wins, member target, nested class,+=), plus a check that recording the name does not introduce a class binding that would shadow the outer variable. - The author reports the new tests fail on 1.4.0 and pass on the branch, and that the broader decorator/transpiler suites pass; the one red CI lane was an unrelated Windows bake test.
68a8a87 to
1ed1f67
Compare
d33bb32 to
b115ed8
Compare
There was a problem hiding this comment.
LGTM — extends the existing decorator_class_name propagation from = to the three logical assignment operators, matching the spec's NamedEvaluation rule.
What was reviewed:
- Confirmed ECMA-262 gives
??=/||=/&&=the same NamedEvaluation rule as=(identifier target only), and compound arithmetic operators do not — the operator list is exactly right. - The save/restore of
prev_decorator_class_nameand the inner guards (EClass,should_lower_standard_decorators,EIdentifierleft) are unchanged; only the operator predicate widened. - Checked the later
BinNullishCoalescingAssign | BinLogicalOrAssignarm (the{}.field ??= voptimization) — it requiresEDoton the left, disjoint from theEIdentifiercase here. - Tests cover the three operators (method + class decorators), negative guards (explicit name, member target, nested,
+=), and the scoping interaction with the base PR.
Extended reasoning...
Overview
One hunk in src/js_parser/visit/visit_binary.rs: the condition that sets p.decorator_class_name before visiting the right operand of an assignment is widened from e_.op == BinAssign to a matches! over BinAssign | BinNullishCoalescingAssign | BinLogicalOrAssign | BinLogicalAndAssign. Everything else in the block — the anonymous check, the EClass/should_lower_standard_decorators/EIdentifier guards, and the save/restore of the previous name — is unchanged. Four new test.concurrent cases in test/bundler/transpiler/es-decorators.test.ts exercise the fix and pin the negative cases.
Security risks
None. This is transpiler output correctness (the inferred .name of a lowered decorated class expression); no untrusted-input parsing, no allocation logic, no FFI/syscall/crypto surface.
Level of scrutiny
Low-to-medium. The change is a mechanical widening of an operator predicate at a single visitor site, and the spec is unambiguous that exactly these four assignment operators perform NamedEvaluation of an anonymous right-hand side against an identifier target. The existing = path already validates the mechanism; three sibling operators are being added to the same path with no new control flow. The PR is stacked on #38757, and the fourth test pins the scoping property that base PR provides (the recorded name must not shadow the outer variable inside the class body).
Other factors
- The comment-cop bot's feedback was addressed (comment trimmed to one line stating which operators perform NamedEvaluation).
- The tests include both positive coverage and negative guards (
+=, member target, nested class, explicit class name), and were cross-checked against Node per the description. - I checked the later match arm for
BinNullishCoalescingAssign | BinLogicalOrAssign(the{}.field ??= valueHMR optimization): it requirese_.leftto beEDot, so it cannot overlap with theEIdentifiercase that records the name. - The separate
maybe_keep_expr_symbol_namecall in theBinAssignarm (for--keep-names) is intentionally left as-is; the description notes #35307 handles keep-names for these operators separately, so this PR stays scoped to the decorator path.
b115ed8 to
b498dfe
Compare
…r &&= after the target Standard decorator lowering turns a class expression that has a class decorator into a comma expression, so the engine cannot name the class from its position. The parser records that name and the lowering passes it to `__decorateElement`. The binary visitor recorded it only for `=`. The logical assignment operators do the same NamedEvaluation of their right side when the target is an identifier, so `a ??= @dec class {}` had the name "" and the decorator got "" as `context.name`.
b498dfe to
a858c8e
Compare
|
The base of this PR is now main. The stacked branch it was based on is no longer needed since #40833 changed the lowering. The diff is one hunk in src/js_parser/visit/visit_binary.rs plus tests. The review threads on src/ast/ast_result.rs came from the stale base and are resolved. |
There was a problem hiding this comment.
LGTM — widening the decorator_class_name recording to the three logical-assignment operators matches the spec's NamedEvaluation set, and the negative cases (member LHS, +=, nested class, explicit name) confirm the guard stays tight.
What was reviewed:
- The operator set in
visit_binary.rs:124against ECMA-262 NamedEvaluation — only=/??=/||=/&&=name the RHS; arithmetic compounds correctly excluded. - That the existing guards (
is_anonymous_named,should_lower_standard_decorators,EIdentifierLHS) are unchanged, so member targets and named classes stay untouched. - The four new tests: they use the file's existing
runDecoratorhelper,test.concurrent, assert stderr/stdout before exitCode, and cover the operator matrix plus scoping (no class-body binding introduced). - The earlier
src/ast/ast_result.rsinline threads no longer apply — that file is not in the current diff after the rebase.
Extended reasoning...
Overview
The PR touches two files: src/js_parser/visit/visit_binary.rs (an 8-line condition widening) and test/bundler/transpiler/es-decorators.test.ts (four new test.concurrent cases in a new describe block). The Rust change extends the branch that records p.decorator_class_name — used by the standard-decorator lowering to give a lowered anonymous class its .name and decorator context.name — from BinAssign only to also include BinNullishCoalescingAssign, BinLogicalOrAssign, and BinLogicalAndAssign. The surrounding save/restore of prev_decorator_class_name and the inner guards (anonymous class, should_lower_standard_decorators, identifier LHS) are unchanged.
Security risks
None. This is a compile-time naming decision in the JS transpiler with no I/O, no untrusted-size arithmetic, and no memory-ownership changes. The tests spawn local subprocesses via the existing runDecorator helper and touch no network.
Level of scrutiny
Low-to-moderate. The change is spec-derived: ECMA-262 defines NamedEvaluation for exactly =, &&=, ||=, and ??= among the assignment operators, and not for arithmetic/bitwise compound assignments — the new matches! set is that exact list, and the one-line comment states the invariant. Per REVIEW.md's "fix the whole class" rule I checked for sibling sites: the PR description notes (and the code confirms) that logical-assignment operators are never lowered by the parser and the assignment-pattern default paths only see =, so visit_right_and_finish is the only visitor site involved. The maybe_keep_expr_symbol_name path further down handles the separate --keep-names concern and is out of scope here.
Other factors
Test coverage is thorough for the size of the fix: every operator, a chained Outer = Inner ??= …, an IIFE, member-decorator-only and accessor-only classes (engine-named path), explicit negative cases (Named, member LHS, nested-in-array, +=), and a scoping test proving the recorded name does not shadow the outer binding inside the class body. Tests follow repo conventions (existing file, existing runDecorator helper, test.concurrent, .toEqual on one object, stderr → stdout → exitCode ordering). CODEOWNERS does not cover either changed path. The branch was rebased since the last review round; the earlier inline threads on src/ast/ast_result.rs no longer correspond to any change in the current diff, and there are no outstanding CHANGES_REQUESTED reviews.
…lass names The emitted code for `x ??= @dec class {}` changes, so cached output from an older build must not be read back. Also drop the test for classes that have only member decorators. Such a class stays in place on main and the engine names it, so the test does not exercise the change.
There was a problem hiding this comment.
LGTM — the transpiler-cache version bump added in the latest push completes this.
What was reviewed:
- The
matches!extension invisit_right_and_finishcovers exactly the four assignment operators that spec NamedEvaluation on the RHS; compound arithmetic/bitwise ops and member-expression targets remain excluded, andprev_decorator_class_namesave/restore is unchanged. EXPECTED_VERSION32→33 invalidates cached transpiler output as required for a codegen change.- Tests cover the operator matrix, negative cases (
+=, named class, member target, nested), and confirm the recorded name does not become a class-body binding.
Extended reasoning...
Overview
The PR extends one condition in src/js_parser/visit/visit_binary.rs so that p.decorator_class_name is set for ??=, ||=, and &&= in addition to =, when the right operand is an anonymous class expression that will be lowered for standard decorators and the left operand is an identifier. It bumps EXPECTED_VERSION in src/jsc/RuntimeTranspilerCache.rs from 32 to 33, and adds three test.concurrent cases to the existing test/bundler/transpiler/es-decorators.test.ts describe block.
Security risks
None. This is a parser/lowering correctness fix affecting the .name and decorator context.name of anonymous class expressions. No untrusted-input parsing, no allocation/bounds arithmetic, no auth/crypto/permissions surface.
Level of scrutiny
Low-to-medium. The Rust change is a one-condition widening that mirrors the exact operator set the spec defines for NamedEvaluation of assignment RHS (only = and the three logical assignment operators; compound arithmetic/bitwise assignments do not). The surrounding save/restore of prev_decorator_class_name and the identifier-target / should_lower_standard_decorators guards are unchanged, so the blast radius is the four operators only. The cache bump satisfies the REVIEW.md rule that any cached-output change bumps the format version constant. No CODEOWNERS entries cover the touched paths.
Other factors
Since the previously reviewed push, commit 92dcfe7 added the transpiler-cache version bump and dropped one redundant member-decorator test case (its behavior — engine-named classes when only member decorators are present — is still pinned by the third test's Member case). Tests follow harness conventions (runDecorator uses tempDir/bunEnv/concurrent pipe drain, stderr asserted before exitCode, .toEqual on a single JSON object, test.concurrent). The negative test explicitly pins that +=, member targets, nested classes, and explicitly-named classes do not receive the target name. No outstanding human CHANGES_REQUESTED reviews; bot inline threads reference either this line or a file (src/ast/ast_result.rs) no longer in the diff. Bug-hunt exit reason was dry_streak.
Problem
a ??= @dec class {}(also||=,&&=) names the class""and passes""to the decorator ascontext.name.a = @dec class {}gives"a", as node does for all four operators without the decorator.visit_right_and_finish(src/js_parser/visit/visit_binary.rs:124). It records the assignment target as the class name only for=. Found by inspection, there is no user report.Fix
BinNullishCoalescingAssign,BinLogicalOrAssignandBinLogicalAndAssigntoo, under the same conditions: an anonymous class that will be lowered, and an identifier target. The emitted code changes, soEXPECTED_VERSIONinsrc/jsc/RuntimeTranspilerCache.rsgoes from 32 to 33.=.+=and member targets (o.p ??= class {}) have no such rule and stay excluded. esbuild 0.25.0 and tsc 6.0.2 give the same names.test/bundler/transpiler/es-decorators.test.ts, blockanonymous decorated class assigned with a logical assignment operator. 2 of its 3 tests fail on main without the change. Other suites: see Notes.Background
const a = class {},a ??= class {}). The expression must be directly in that position.p.decorator_class_name. The lowering passes it to__decorateElementas a string, for.nameandcontext.name. No class binding exists, so the class body still sees the assigned variable.Notes
Repro
["a","b","c","d"][["a","b","c","d"],["a","b","c","d"]]bun runandbun build[["","","","d"],["","","","d"]]bun runandbun build[["a","b","c","d"],["a","b","c","d"]]With
h.m ??= @dec class {}ands += @dec class {}added, esbuild, tsc and this PR all give""for those two.Emitted code for
a ??= @dec class {}(temporary names shortened)Before the change the third argument of
__decorateElementis"".Sites that this PR leaves alone on purpose
visit_right_and_finishhas a second arm that is specific to=, the keep-names arm atvisit_binary.rs:690. It callsmaybe_keep_expr_symbol_name, andkeep_expr_symbol_name(src/js_parser/p.rs:6159) returns its argument unchanged today. bundler: implement --keep-names with __name helper #40503 implements--keep-names. That arm stays as it is.visit_expr.rs([x = class {}] = ...,({ x = class {} } = ...)) only ever see=, because a pattern default cannot use a logical operator.forhead), js_parser: name lowered anonymous classes after numeric, non-ASCII and private property keys #38787 (numeric, non-ASCII and private property keys) and js_parser: name an anonymous decorated export default class "default" #38758 (export default class). One shared helper for all sites plus one matrix test is a possible follow-up. It is not part of this PR.Self-review
EXPECTED_VERSIONis now 33. Other open PRs also take 33, so the number can change at merge time.=-only keep-names arm. Addressed in Problem and in the list above.History
visit_binary.rshunk did not change._class = class a {}), which shadowed the assigned variable in the class body. That was the reason for the stack. The merged lowering has no such binding. The third test pins this.accessormembers stays in place on main, and the engine already names it for these operators. The failing cases in the tests therefore use class decorators.Tests in the new block
class decorator sees the target name as context.name: the three operators,=, a chainedOuter = Inner ??= @dec class {}(namedInner) and an assignment inside a function. It checkscontext.nameand.name. Fails on main without the change.the class body still refers to the variable being assigned: a static initializer reads the value that the variable had during definition (nullunder||=,1under&&=), a method sees a later reassignment, the body of a class that a decorator replaced sees the replacement, and a method can assign to the variable. Fails on main without the change (the names are"").the target name is only used for an anonymous class directly on the right: an explicit class name, a member target, a class nested in the right operand, and+=. Passes before and after..namevalues and the scoping results are what node prints for the same programs with the decorators removed.Suites run on the debug build of this branch
es-decorators.test.ts(421),es-decorators-esbuild.test.ts(147),decorators.test.ts(24),decorator-metadata.test.ts(5),transpiler.test.js(214),test/cli/run/transpiler-cache.test.tsandtest/regression/issue/30887.test.ts(25).cargo fmt --checkis clean forbun_js_parserandbun_jsc.[human-review] gate passed · iteration 2 · 3 files touched
fails on main (without fix)
passes on PR (with fix)
diff hotspot
gate history · 3 passed · 1 rejected · iteration 2
evidence per changed file
root cause · written by the author bot
The parser only set the decorator class name for anonymous class expressions on the right side of a plain
=assignment, so classes assigned via??=,||=, or&&=lost the inferred name when standard decorators were lowered. The fix widens the condition invisit_right_and_finishto cover those three logical assignment operators, matching the set for which the spec performs NamedEvaluation on the right operand, while leaving compound arithmetic operators and member-expression targets excluded. Because this changes generated output, the runtime transpiler cache version was bumped from…