Skip to content

refactor(oxc_parser): introduce ParserConfig#2

Closed
lilnasy wants to merge 114 commits intorustify-tokensfrom
refactor/parseconfig
Closed

refactor(oxc_parser): introduce ParserConfig#2
lilnasy wants to merge 114 commits intorustify-tokensfrom
refactor/parseconfig

Conversation

@lilnasy
Copy link
Owner

@lilnasy lilnasy commented Dec 11, 2025

  • Introduces ParserConfig, a generic interface that concretely does nothing for most compilation targets and will store tokens in an arena when compiled for oxlint.
  • Uses the code snippets from Linter plugins: Rustify token methods oxc-project/oxc#16207 as starting point.
  • At this point, the goal is to ensure there is no change in behavior or performance. The oxlint-exclusive storage of tokens is not implemented yet.

Comment on lines 24 to 49
type ByteHandler = unsafe fn(&mut Lexer<'_>) -> Kind;

/// Lookup table mapping any incoming byte to a handler function defined below.
/// <https://github.com/ratel-rust/ratel-core/blob/v0.7.0/ratel/src/lexer/mod.rs>
#[rustfmt::skip]
static BYTE_HANDLERS: [ByteHandler; 256] = [
// 0 1 2 3 4 5 6 7 8 9 A B C D E F //
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, SPS, LIN, ISP, ISP, LIN, ERR, ERR, // 0
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 1
SPS, EXL, QOD, HAS, IDT, PRC, AMP, QOS, PNO, PNC, ATR, PLS, COM, MIN, PRD, SLH, // 2
ZER, DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, COL, SEM, LSS, EQL, GTR, QST, // 3
AT_, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, // 4
IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, BTO, ESC, BTC, CRT, IDT, // 5
TPL, L_A, L_B, L_C, L_D, L_E, L_F, L_G, IDT, L_I, IDT, L_K, L_L, L_M, L_N, L_O, // 6
L_P, IDT, L_R, L_S, L_T, L_U, L_V, L_W, IDT, L_Y, IDT, BEO, PIP, BEC, TLD, ERR, // 7
UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, // 8
UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, // 9
UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, // A
UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, // B
UER, UER, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, // C
UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, // D
UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, // E
UNI, UNI, UNI, UNI, UNI, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, // F
];
// TODO: this should be a static array, not a function
const fn byte_handlers<Config: ParserConfig>() -> [for<'a> fn(&mut Lexer<'a, Config>) -> Kind; 256] {
[
// 0 1 2 3 4 5 6 7 8 9 A B C D E F //
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, SPS, LIN, ISP, ISP, LIN, ERR, ERR, // 0
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 1
SPS, EXL, QOD, HAS, IDT, PRC, AMP, QOS, PNO, PNC, ATR, PLS, COM, MIN, PRD, SLH, // 2
ZER, DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, COL, SEM, LSS, EQL, GTR, QST, // 3
AT_, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, // 4
IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, BTO, ESC, BTC, CRT, IDT, // 5
TPL, L_A, L_B, L_C, L_D, L_E, L_F, L_G, IDT, L_I, IDT, L_K, L_L, L_M, L_N, L_O, // 6
L_P, IDT, L_R, L_S, L_T, L_U, L_V, L_W, IDT, L_Y, IDT, BEO, PIP, BEC, TLD, ERR, // 7
UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, // 8
UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, // 9
UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, // A
UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, // B
UER, UER, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, // C
UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, // D
UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, // E
UNI, UNI, UNI, UNI, UNI, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, UER, // F
]
}
Copy link
Owner Author

Choose a reason for hiding this comment

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

I was running in circles trying to figure this out. This is what claude suggested but the function call probably has a cost (maybe #[inline] helps). I'll have to come back to this another time.

Copy link

@overlookmotel overlookmotel Dec 12, 2025

Choose a reason for hiding this comment

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

This is tricky. The reason we want a static is that statics are stored in the binary only once, whereas a const is inlined everywhere it's used. Lexer::handle_byte has 2 call sites, so the danger is that we end up with 2 copies of the table in the binary, which is wasteful. The table is 2 KiB (256 x 8 bytes).

There doesn't seem to be any way to do that, though. Rust doesn't allow statics to be generic.

Maybe this is slightly better:

/// Byte handler.
#[expect(type_alias_bounds)]
type ByteHandler<Config: ParserConfig> = unsafe fn(&mut Lexer<'_, Config>) -> Kind;

impl<Config: ParserConfig> Lexer<'_, Config> {
    /// Byte handlers for this `ParserConfig`.
    const BYTE_HANDLERS: [ByteHandler<Config>; 256] = byte_handlers();

    /// Handle next byte of source.
    ///
    /// # SAFETY
    ///
    /// * Lexer must not be at end of file.
    /// * `byte` must be next byte of source code, corresponding to current position of `lexer.source`.
    /// * Only `BYTE_HANDLERS` for ASCII characters may use the `ascii_byte_handler!()` macro.
    // `#[inline(always)]` to ensure is inlined into `read_next_token`
    #[expect(clippy::inline_always)]
    #[inline(always)]
    pub(super) unsafe fn handle_byte(&mut self, byte: u8) -> Kind {
        // SAFETY: Caller guarantees to uphold safety invariants
        unsafe { Self::BYTE_HANDLERS[byte as usize](self) }
    }
}

/// Lookup table mapping any incoming byte to a handler function defined below.
/// <https://github.com/ratel-rust/ratel-core/blob/v0.7.0/ratel/src/lexer/mod.rs>
#[rustfmt::skip]
const fn byte_handlers<Config: ParserConfig>() -> [ByteHandler<Config>; 256] {
    [
        // ....
    ]
}

At least then byte handlers table is a const, rather than stored in a local var.

(side benefit: this version also doesn't have the weird for<'a> syntax)

Maybe compiler is smart enough to de-duplicate the tables and store it only once. To find out, we'll need to build it, and then check the binary to see if it increases in size or not.

fn push(&mut self, token: Token);
fn checkpoint(&self) -> Self::Checkpoint;
fn rewind(&mut self, checkpoint: Self::Checkpoint);
// TODO: add another method that concretely returns a Vec of tokens
Copy link
Owner Author

Choose a reason for hiding this comment

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

We basically need a wrapper for std::mem::replace(&mut self.tokens, Vec::new_in(allocator)).

Choose a reason for hiding this comment

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

Maybe:

pub trait TokenStore<'a> {
    // ...
    fn into_tokens(self, allocator: &'a Allocator) -> ArenaVec<'a, Token>;
}

impl<'a> TokenStore<'a> for NoopTokenStore {
    // ...
    fn into_tokens(self, allocator: &'a Allocator) -> ArenaVec<'a, Token> {
        oxc_allocator::Vec::new_in(allocator)
    }
}

impl<'a> TokenStore<'a> for RealTokenStore<'a> {
    // ...
    fn into_tokens(self, _allocator: &'a Allocator) -> ArenaVec<'a, Token> {
        self.tokens
    }
}

Then in ParserImpl::parse:

let tokens = self.lexer.tokens.into_tokens(self.ast.allocator);

into_tokens consumes self, so no need for mem::replace.

Comment on lines 113 to 130
#[derive(Debug)]
pub struct LexerCheckpoint<'a, Config: ParserConfig> {
source_position: SourcePosition<'a>,
token: Token,
errors_snapshot: ErrorSnapshot,
token_checkpoint: <Config::Tokens<'a> as TokenStore<'a>>::Checkpoint,
}

impl<Config: ParserConfig> Clone for LexerCheckpoint<'_, Config> {
fn clone(&self) -> Self {
Self {
source_position: self.source_position,
token: self.token,
errors_snapshot: self.errors_snapshot.clone(),
token_checkpoint: self.token_checkpoint.clone(),
}
}
}
Copy link
Owner Author

Choose a reason for hiding this comment

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

Clone can simply be derived but that causes trait-satisfaction errors in ParserCheckpoint that I can't make sense of yet.

Copy link

@overlookmotel overlookmotel Dec 12, 2025

Choose a reason for hiding this comment

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

The auto-derived trait impl is this:

impl<Config: Clone> Clone for LexerCheckpoint<Config>
where
    Config: ParserConfig,
    Config::Tokens<'a>: Clone,
{
    fn clone(&self) -> Self {
        match self {
            LexerCheckpoint {
                source_position: source_position,
                token: token,
                errors_snapshot: errors_snapshot,
                token_checkpoint: token_checkpoint,
            } => LexerCheckpoint {
                source_position: source_position.clone(),
                token: token.clone(),
                errors_snapshot: errors_snapshot.clone(),
                token_checkpoint: token_checkpoint.clone(),
            },
        }
    }
}

This has bounds that both Config: Clone and Config::Tokens<'a>: Clone, and it doesn't implement Clone on LexerCheckpoint unless both those are satisfied.

Not sure why it includes those bounds, as they're not required. Probably it can't statically determine that they're not required - macros operate as text manipulators only - they don't have type information.

Neither Config nor Config::Tokens are Clone, and neither can be, because oxc_allocator::Vec isn't Clone.

So no way I can see to avoid manual implementation of Clone here. I'd suggest just adding a short comment saying why.

(If you use VS Code, you can see the expansion of any macro by putting cursor on the macro, and Command Palette -> "rust-analyser: Expand macro recursively at caret")

Comment on lines 177 to 196
@@ -99,6 +185,24 @@ impl<'a> Lexer<'a> {
source_type: SourceType,
unique: UniquePromise,
) -> Self {
Self::new_with_config(allocator, source_text, source_type, unique)
}
}

impl<'a, Config: ParserConfig> Lexer<'a, Config> {
/// Create new `Lexer`.
///
/// Requiring a `UniquePromise` to be provided guarantees only 1 `Lexer` can exist
/// on a single thread at one time.
Copy link
Owner Author

Choose a reason for hiding this comment

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

There is a separate impl block for StandardParserConfig to avoid having to add type annotations in the many places using Lexer::new. That usage remains unambiguous and continues to work as-is. It reduces the PR diff size and I imagine makes life slightly easier for non-oxc projects using our crates.

Parser and ParserImpl have similar refactors.

///
/// Filled only when the parser is being used by oxlint.
/// Empty when `ParserConfig` is the default one.
pub tokens: ArenaVec<'a, Token>,
Copy link
Owner Author

Choose a reason for hiding this comment

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

This is oxc_allocator::Vec.

renovate bot and others added 11 commits December 12, 2025 03:33
…#16765)

This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Adoption](https://docs.renovatebot.com/merge-confidence/) |
[Passing](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|
| [oxlint-tsgolint](https://github.com/oxc-project/tsgolint) |
[`0.8.5` ->
`0.8.6`](https://renovatebot.com/diffs/npm/oxlint-tsgolint/0.8.5/0.8.6)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/oxlint-tsgolint/0.8.6?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxlint-tsgolint/0.8.6?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxlint-tsgolint/0.8.5/0.8.6?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxlint-tsgolint/0.8.5/0.8.6?slim=true)
|

---

### Release Notes

<details>
<summary>oxc-project/tsgolint (oxlint-tsgolint)</summary>

###
[`v0.8.6`](https://github.com/oxc-project/tsgolint/releases/tag/v0.8.6)

[Compare
Source](https://github.com/oxc-project/tsgolint/compare/v0.8.5...v0.8.6)

##### What's Changed

- chore(deps): update typescript-go digest to
[`5ac8497`](https://github.com/oxc-project/tsgolint/commit/5ac8497)
by [@&oxc-project#8203;renovate](https://github.com/renovate)\[bot] in
[#&oxc-project#8203;500](https://github.com/oxc-project/tsgolint/pull/500)
- chore(deps): update typescript-go digest to
[`dcebe53`](https://github.com/oxc-project/tsgolint/commit/dcebe53)
by [@&oxc-project#8203;renovate](https://github.com/renovate)\[bot] in
[#&oxc-project#8203;503](https://github.com/oxc-project/tsgolint/pull/503)
- fix: nil interface type crash in getBaseTypes
([#&oxc-project#8203;502](https://github.com/oxc-project/tsgolint/issues/502))
by [@&oxc-project#8203;camc314](https://github.com/camc314) in
[#&oxc-project#8203;504](https://github.com/oxc-project/tsgolint/pull/504)
- chore(deps): update typescript-go digest to
[`cac2644`](https://github.com/oxc-project/tsgolint/commit/cac2644)
by [@&oxc-project#8203;renovate](https://github.com/renovate)\[bot] in
[#&oxc-project#8203;505](https://github.com/oxc-project/tsgolint/pull/505)

**Full Changelog**:
<oxc-project/tsgolint@v0.8.5...v0.8.6>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/oxc-project/oxc).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi40Mi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Adoption](https://docs.renovatebot.com/merge-confidence/) |
[Passing](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|
| [tsdown](http://tsdown.dev/)
([source](https://github.com/rolldown/tsdown)) | [`0.17.2` ->
`0.17.3`](https://renovatebot.com/diffs/npm/tsdown/0.17.2/0.17.3) |
![age](https://developer.mend.io/api/mc/badges/age/npm/tsdown/0.17.3?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/tsdown/0.17.3?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/tsdown/0.17.2/0.17.3?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/tsdown/0.17.2/0.17.3?slim=true)
|

---

### Release Notes

<details>
<summary>rolldown/tsdown (tsdown)</summary>

###
[`v0.17.3`](https://github.com/rolldown/tsdown/releases/tag/v0.17.3)

[Compare
Source](https://github.com/rolldown/tsdown/compare/v0.17.2...v0.17.3)

#####    🚀 Features

- **copy**: Support glob in `copy`  -  by
[@&oxc-project#8203;kricsleo](https://github.com/kricsleo) and
[@&oxc-project#8203;sxzz](https://github.com/sxzz) in
[#&oxc-project#8203;637](https://github.com/rolldown/tsdown/issues/637)
[<samp>(c1fd4)</samp>](https://github.com/rolldown/tsdown/commit/c1fd4f3)

#####    🐞 Bug Fixes

- Print error stack  -  by
[@&oxc-project#8203;sxzz](https://github.com/sxzz)
[<samp>(1c5b6)</samp>](https://github.com/rolldown/tsdown/commit/1c5b650)
- Add config name to rebuilt message  -  by
[@&oxc-project#8203;sxzz](https://github.com/sxzz)
[<samp>(bfdc6)</samp>](https://github.com/rolldown/tsdown/commit/bfdc67a)
- Call hooks for each format  -  by
[@&oxc-project#8203;sxzz](https://github.com/sxzz)
[<samp>(19bdd)</samp>](https://github.com/rolldown/tsdown/commit/19bdd0e)
- Merge input & output options  -  by
[@&oxc-project#8203;sxzz](https://github.com/sxzz)
[<samp>(14181)</samp>](https://github.com/rolldown/tsdown/commit/1418122)

#####     [View changes on
GitHub](https://github.com/rolldown/tsdown/compare/v0.17.2...v0.17.3)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/oxc-project/oxc).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi40Mi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
When adding new features primarily using JS via napi, to reduce future maintenance burdens such as missed implementations.
After giving it some thought, I decided to lean these features toward JS after all.

The reasons are:

- I want Rust side to focus on complex formatting tasks, while moving infrequently used commands elsewhere
- Code defining `napi` callbacks tends to become verbose

While `--init` itself worked on the Rust side, it will share some lines with upcoming `--migrate`, so I'm extracting this beforehand too.

Also, We were generating `.jsonc`, but I've switched to creating `.json` for now.

This is because running `oxfmt` immediately after generating `.jsonc` causes trailing comma diffs. 😨
I was hesitant to introduce a jsonc writer, so `.json` will enough for now.
Previously,

- `oxfmt(napi) not-exists.js` returns `exitCode: 1`
- `oxfmt(rust) not-exists.js` returns `exitCode: 2` = Expected

To fix this, I updated napi callback return value from `bool`.

Additionally, I realized that by returning the processing `Mode` simultaneously, Rust can handle the CLI arguments in better way. Like `--init --help`, which now shows help.

And finally changed napi binding name from `format()` to `runCli()` for the future Node API.
Simple addition but unfortunately untested: I locally fail tsgo related
tests, probably for reasons related to not having tsgo installed?

---------

Co-authored-by: Boshen <boshenc@gmail.com>
…age directly in conformance build (oxc-project#16774)

In build for conformance tests, use `@typescript-eslint/typescript-estree` package directly instead of the `ts_eslint.cjs`, to get stack traces for parsing failures.

Only affects conformance build - release and debug (tests) builds both use `ts_eslint.cjs` bundle, same as before.
Copy link

@overlookmotel overlookmotel left a comment

Choose a reason for hiding this comment

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

Wow this gets a bit complicated. I hadn't clocked that BYTE_HANDLERS would be impacted by the change.

A few broad comments on top of the smaller notes below:

No-op impl first

I suggest splitting this change into 2 parts:

  1. Introduce ParserConfig as an empty trait (no tokens code). Only add StandardParserConfig.
  2. Add all the tokens-related code.

Step (1) is pure refactor. After that PR alone, we can check that the changes to BYTE_HANDLERS aren't bloating the binary.

Once that's done, we'll be able to concentrate on the tokens-related code in isolation.

Shorten code

We have to add the generic in a lot of places. To make it less intrusive, I suggest:

// Before
use crate::ParserConfig;
impl<'a, Config: ParserConfig> ParserImpl<'a, Config> {
  // ...
}
// After
use crate::ParserConfig as Config;
impl<'a, C: Config> ParserImpl<'a, C> {
  // ...
}

ParserConfig future

FYI: I have other plans for ParserConfig aside from tokens.

I'd like to add more methods to ParserConfig, and make ParseOptions implement ParserConfig. Then you'll be able to set parser options at compile time instead of dynamically if you want. For instance:

trait ParserConfig {
  fn preserve_parens(&self) -> bool;
}

struct ParseOptions {
  preserve_parens: bool;
}

impl ParserConfig for ParseOptions {
  fn preserve_parens(&self) -> bool {
    self.preserve_parens
  }
}

This behaves exactly the same as at present, but for example in linter where preserve_parens is always true, we can implement a specialized ParserConfig which returns true from preserve_parens unconditionally. This will remove branches from the version of parser used in linter.

(I'm not suggesting we do that now - just to put you in the picture of what I have in mind)

Comment on lines 91 to 93
fn $id($lex: &mut Lexer) -> Kind {
fn $id<Config: ParserConfig>($lex: &mut Lexer<'_, Config>) -> Kind {

Choose a reason for hiding this comment

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

Please also update the comment above this showing what the macro expands to.

// TODO: better name
#[derive(Debug)]
pub struct RealTokenStore<'a> {
tokens: oxc_allocator::Vec<'a, Token>,

Choose a reason for hiding this comment

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

Please add use oxc_allocator::Vec as ArenaVec; at top of file and use ArenaVec here. Ditto other places where we have oxc_allocator::Vec.

Comment on lines 106 to 107
// TODO: better name
pub struct RealParserConfig;

Choose a reason for hiding this comment

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

Ha yes! How about:

  • RealParserConfig -> ParserConfigWithTokens
  • StandardParserConfig -> ParserConfigWithoutTokens
  • RealTokenStore -> ActiveTokenStore

?

Comment on lines 54 to 136
Full(Vec<OxcDiagnostic>),
Full(std::vec::Vec<OxcDiagnostic>),

Choose a reason for hiding this comment

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

Can leave this as it was (as we'll use ArenaVec for the other Vec).

Comment on lines 91 to 190
@@ -99,6 +185,24 @@ impl<'a> Lexer<'a> {
source_type: SourceType,
unique: UniquePromise,
) -> Self {
Self::new_with_config(allocator, source_text, source_type, unique)
}
}

Choose a reason for hiding this comment

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

I think this is only used in 1 test. Could:

  1. Convert that test to use new_with_config instead.
  2. Remove new.
  3. Rename new_with_config to new.

unique: UniquePromise,
) -> Self
where
Config: ParserConfig,

Choose a reason for hiding this comment

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

Is this where clause required? You already require this bound in impl<'a, Config: ParserConfig> Lexer<'a, Config> above.

pub mod lexer;

use oxc_allocator::{Allocator, Box as ArenaBox, Dummy};
use crate::lexer::{ParserConfig, StandardParserConfig};

Choose a reason for hiding this comment

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

Nit: Move this import down into the existing use crate::{ ... } block.

…xc-project#16780)

Pure refactor. In conformance tester, remove bunch of repeated `lines.push` calls to make report creation code easier to read.
…summary (oxc-project#16781)

Include percentages in summaries at top of conformance tester report.
tt-a1i and others added 13 commits December 12, 2025 23:48
…t#16779)

## Summary

Implements ESLint's `no-promise-executor-return` rule which disallows
returning values from Promise executor functions.

The return value of a Promise executor is ignored, so returning a value
is likely a mistake. This rule detects:
- Implicit returns from arrow function expression bodies (`new Promise(r
=> r(1))`)
- Explicit return statements with values (`return 1`, `return
resolve(1)`)
- Returns inside control flow (if, switch, loops, try-catch, etc.)

### Configuration

- `allowVoid` (default: `false`): When `true`, allows `return void expr`
pattern (both explicit and implicit returns)

### Design Notes

This rule only checks executors passed directly as arrow/function
expressions. It does not track references like `new Promise(executor)`
where `executor` is defined elsewhere — this is an intentional design
choice consistent with ESLint's implementation.

## Test Plan

- [x] Added 12 pass cases (empty return, no return, nested functions,
allowVoid, non-Promise)
- [x] Added 16 fail cases (implicit return, explicit return, control
flow, return resolve/reject)
- [x] `cargo test -p oxc_linter no_promise_executor_return` passes
- [x] `cargo clippy -p oxc_linter` passes
…ct#16790)

Update a few rules to use backticks in their diagnostic messages.
…hMap` (oxc-project#16666)

The language server wants to lint in the future multiple files at the same time.
These files could still be in memory, so extend `IsolatedLintHandlerFileSystem` to be a `FxHashMap`
…urce text (oxc-project#16667)

In the future, the language server wants to lint multiple files at the same time.
Refactored the code to accept the RuntimeFS (like the CLI tool) for reading the source text.
This test case is defunct since oxc-project#14401. It doesn't test what it's meant to.

From the comment in the plugin used in this test fixture:

```js
// Purpose of this test fixture is to ensure that source text and AST are available in `after` hook
// via `context.sourceCode` when the AST is not traversed
```

But the visitor returned by `createOnce` contains a visit function for `Program`, so the AST *is* traversed. On the other hand, if we remove that `Program` visit method, then it's an empty visitor, so the AST won't be traversed, but the `after` hook won't run either.

Therefore, the case which this fixture is designed to test is impossible. Delete the fixture.
…ct#16795)

Remove `// @ts-expect-error` and `// @ts-ignore` comments from test fixtures, and use assertions instead. This makes sure that the input to methods under test is what we intend it to be.

Note: Using `assert` rather than `expect`, because `assert` gives TypeScript information about types, which `expect` doesn't seem to be capable of.
…hich need fixing (oxc-project#16796)

Only alters comments.

* Make sure all `// @ts-expect-error` comments include "TODO" where it's an issue we need to fix.
* Format all the "TODO" comments consistently.
…#16798)

This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Adoption](https://docs.renovatebot.com/merge-confidence/) |
[Passing](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|
| [oxlint-tsgolint](https://github.com/oxc-project/tsgolint) |
[`0.8.6` ->
`0.9.0`](https://renovatebot.com/diffs/npm/oxlint-tsgolint/0.8.6/0.9.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/oxlint-tsgolint/0.9.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxlint-tsgolint/0.9.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxlint-tsgolint/0.8.6/0.9.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxlint-tsgolint/0.8.6/0.9.0?slim=true)
|

---

### Release Notes

<details>
<summary>oxc-project/tsgolint (oxlint-tsgolint)</summary>

###
[`v0.9.0`](https://github.com/oxc-project/tsgolint/compare/v0.8.6...3e44cb980edb576ad8b258ca939e14c3e29d84ce)

[Compare
Source](https://github.com/oxc-project/tsgolint/compare/v0.8.6...3e44cb980edb576ad8b258ca939e14c3e29d84ce)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/oxc-project/oxc).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi40Mi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…roject#16783)

> This PR refactors the LSP tool diagnostic API to allow tools to report diagnostics for multiple URIs, not just the file being analyzed. This enables cross-file analysis features like ts config deprecation detection.
…ysis (oxc-project#16706)

The constructor-super rule's DFS path analysis had exponential O(2^n)
complexity, causing oxlint to hang indefinitely on files with complex
control flow graphs (e.g., next.js compiled bundles with 59+ classes).

## Root Cause

The previous algorithm explored all possible paths through the CFG,
removing blocks from the visited set after each path to allow
re-exploration. With k branch points, this creates 2^k paths.

## Solution

Replaced the DFS path enumeration with iterative dataflow analysis:

- New `SuperCallState` enum tracks abstract states: Unreached, Never,
  Once, Multiple, Mixed
- Merge operation at CFG join points combines states from different paths
- Transfer function computes state after executing super() calls
- Worklist algorithm propagates states until fixpoint

## Complexity

- Before: O(2^n) where n = number of branch points
- After: O(n × m) where n = blocks, m = edges

The state lattice has finite height (5 states), guaranteeing termination.

## Performance

| File | Before | After |
|------|--------|-------|
| fetch.js (796KB, 59 classes) | hung indefinitely | 16ms |
| load.js (800KB, 59 classes) | hung indefinitely | 50ms |
| tar/index.js (98KB, 30 classes) | hung indefinitely | 6ms |
| Full next.js (19,535 files) | hung indefinitely | 1.2s |

🤖 generated with help from Claude Opus 4.5
connorshea and others added 27 commits December 15, 2025 09:27
This corrects the implementation of the empty-tags rule to not care about the `ignorePrivate` setting.

Fixes oxc-project#16871.

The doc comment for this setting actually explicitly says it should not be considered: https://github.com/oxc-project/oxc/blob/230e34c6eb36c4265fa8ae421375884182fd6926/crates/oxc_linter/src/config/settings/jsdoc.rs#L12-L14

This was missed when porting the tests because the settings shape was incorrect and silently failed. I only noticed it while attempting to enforce a stricter config schema.
## Summary

Implements the `eslint/no-sequences` rule that disallows the use of the comma operator.

The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand. However, this frequently obscures side effects, and its use is often an accident.

### Features

- Allows comma operator in for loop init and update expressions (standard JS pattern)
- `allowInParentheses` option (default: `true`) allows sequences wrapped in parentheses
- For grammar positions requiring parentheses (if, while, do-while, switch, with), double parentheses are needed to indicate intentionality

### Examples

**Incorrect:**
```javascript
foo = doSomething(), val;
0, eval("doSomething();");
do {} while ((doSomething(), !!test)); // needs double parens
```

**Correct:**
```javascript
foo = (doSomething(), val);
(0, eval)("doSomething();");
do {} while (((doSomething(), !!test))); // double parens
for (i = 0, j = 10; i < j; i++, j--) {} // for loop allowed
```

Closes oxc-project#481 (partially - adds
no-sequences)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Cameron Clark <cameron.clark@hey.com>
…rride struct. (oxc-project#16870)

Ensure that extra fields are not allowed inside overrides, to make it clear to users when they have added an invalid field.

Pulled out of oxc-project#16822 since I think it's worth including regardless of that PR.
…xc-project#16858)

Just ensuring they work correctly by checking that they get mapped to the correct enum variants.

- `readonly`/`readable`/`false` should map to Readonly
- `writable`/`writeable`/`true` should map to Writable
- `off` should map to Off
)

This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|
| [oxc-parser](https://oxc.rs) ([source](https://github.com/oxc-project/oxc/tree/HEAD/napi/parser)) | [`^0.102.0` -> `^0.103.0`](https://renovatebot.com/diffs/npm/oxc-parser/0.102.0/0.103.0) | ![age](https://developer.mend.io/api/mc/badges/age/npm/oxc-parser/0.103.0?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxc-parser/0.103.0?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxc-parser/0.102.0/0.103.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxc-parser/0.102.0/0.103.0?slim=true) |

---

### Release Notes

<details>
<summary>oxc-project/oxc (oxc-parser)</summary>

### [`v0.103.0`](https://github.com/oxc-project/oxc/blob/HEAD/napi/parser/CHANGELOG.md#01030---2025-12-15)

##### 🚀 Features

- [`30a9076`](https://github.com/oxc-project/oxc/commit/30a9076) ast, parser, codegen: Add `CommentKind::MultilineBlock` ([#&oxc-project#8203;16479](https://github.com/oxc-project/oxc/issues/16479)) (Dunqing)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi40Mi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
## Summary

Implement the ESLint `no-inline-comments` rule which disallows comments
on the same line as code.

### Features
- Detects inline comments (both line and block comments)
- Supports `ignorePattern` option for regex-based exceptions
- Exempts ESLint/OxLint directive comments (`eslint-disable`, `eslint `,
etc.)
- Exempts `global`, `globals`, and `exported` directive comments (block
comments only, matching ESLint behavior)
- Handles JSX empty expression comments (`{/* comment */}`)

### Performance optimizations
- Pre-collects `JSXEmptyExpression` spans to avoid repeated AST
traversal
- Returns `&str` slices instead of `String` allocations in comment
context detection

Closes oxc-project#2987

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Cameron Clark <cameron.clark@hey.com>
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|
| [oxlint](https://oxc.rs) ([source](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint)) | [`1.32.0` -> `1.33.0`](https://renovatebot.com/diffs/npm/oxlint/1.32.0/1.33.0) | ![age](https://developer.mend.io/api/mc/badges/age/npm/oxlint/1.33.0?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxlint/1.33.0?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxlint/1.32.0/1.33.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxlint/1.32.0/1.33.0?slim=true) |

---

### Release Notes

<details>
<summary>oxc-project/oxc (oxlint)</summary>

### [`v1.33.0`](https://github.com/oxc-project/oxc/compare/oxlint_v1.32.0...oxlint_v1.33.0)

[Compare Source](https://github.com/oxc-project/oxc/compare/oxlint_v1.32.0...oxlint_v1.33.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi40Mi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
Toml formatting is missing but there's only a few toml files, can wait
for oxfmt plugins.

- [x] Something is slow, can't figure out why, need oxc-project#16607
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|
| [tsdown](http://tsdown.dev/) ([source](https://github.com/rolldown/tsdown)) | [`0.17.4` -> `0.18.0`](https://renovatebot.com/diffs/npm/tsdown/0.17.4/0.18.0) | ![age](https://developer.mend.io/api/mc/badges/age/npm/tsdown/0.18.0?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/tsdown/0.18.0?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/tsdown/0.17.4/0.18.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/tsdown/0.17.4/0.18.0?slim=true) |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi40Mi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
… to internal language server (oxc-project#16784)

This PR refactors the VSCode extension to prefer using oxlint and oxfmt binaries from node_modules/.bin by default, with a fallback to the internal oxc_language_server when no binaries are found.
…xc-project#16898)

Add configuration support for the typescript/no-base-to-string rule with an ignoredTypeNames option that allows specifying types that are safe to call toString() on, even if they don't provide a custom implementation.

Default ignored types: Error, RegExp, URL, URLSearchParams

🤖 generated with help from Claude Opus 4.5

closes oxc-project/tsgolint#517
….ts` (oxc-project#16901)

Pure refactor. Move the type def for `RuleOptionsSchema` into `options.ts`, which is a more appropriate place for it.
…ble jest rule (oxc-project#16880)

Related to oxc-project#4656

# Sumarry
Add `require hook` as a vitest compatible rule.

Oxlint-migrate PR:
oxc-project/oxlint-migrate#288

# Changes made
I had to sligthy modify the implementation to be compatible with both
frameworks. The modifications were for 2 specific tests:

```javascripts
("describe.for([])('%s', (value) => {})", None),
(
  "describe('scoped', () => {
      test.scoped({ example: 'value' });
   });",
  None,
 ),
```

Both test cases must pass. The first test case failed because
`describe.for` [only exists in
vitest](https://vitest.dev/api/#describe-for) and this exact part of
`parse_jest_fn.rs` failed in the jest branch.


https://github.com/oxc-project/oxc/blob/eba07e6fd945069e7694e3880b36e4f0f8f78d6d/crates/oxc_linter/src/utils/jest/parse_jest_fn.rs#L109C1-L115C10

Second test failed because `test.scoped` doesn't exist neither
frameworks, `scoped` is a custom property made by a user. Reviewing the
Jest and Vitest eslint code they are only interested in the beginning,
not in the full chain.
Small improvement to type safety. Here we need to remove `Readonly` from a type, but do only that, rather than full type-casting.
…16899)

Ref: oxc-project#492 

This PR adds support for
[jest/prefer-to-have-been-called](https://github.com/jest-community/eslint-plugin-jest/blob/v29.5.0/docs/rules/prefer-to-have-been-called.md)

---------

Signed-off-by: Cameron <cameron.clark@hey.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
…#16906)

This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|
| [oxlint-tsgolint](https://github.com/oxc-project/tsgolint) | [`0.9.0` -> `0.9.1`](https://renovatebot.com/diffs/npm/oxlint-tsgolint/0.9.0/0.9.1) | ![age](https://developer.mend.io/api/mc/badges/age/npm/oxlint-tsgolint/0.9.1?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxlint-tsgolint/0.9.1?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxlint-tsgolint/0.9.0/0.9.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxlint-tsgolint/0.9.0/0.9.1?slim=true) |

---

### Release Notes

<details>
<summary>oxc-project/tsgolint (oxlint-tsgolint)</summary>

### [`v0.9.1`](https://github.com/oxc-project/tsgolint/releases/tag/v0.9.1)

[Compare Source](https://github.com/oxc-project/tsgolint/compare/v0.9.0...v0.9.1)

#### What's Changed

- chore(deps): update typescript-go digest to [`92c21db`](https://github.com/oxc-project/tsgolint/commit/92c21db) by [@&oxc-project#8203;renovate](https://github.com/renovate)\[bot] in [#&oxc-project#8203;509](https://github.com/oxc-project/tsgolint/pull/509)
- chore(deps): update typescript-go digest to [`2046634`](https://github.com/oxc-project/tsgolint/commit/2046634) by [@&oxc-project#8203;renovate](https://github.com/renovate)\[bot] in [#&oxc-project#8203;510](https://github.com/oxc-project/tsgolint/pull/510)
- chore(deps): update npm packages by [@&oxc-project#8203;renovate](https://github.com/renovate)\[bot] in [#&oxc-project#8203;512](https://github.com/oxc-project/tsgolint/pull/512)
- chore(deps): update taiki-e/install-action action to v2.63.1 by [@&oxc-project#8203;renovate](https://github.com/renovate)\[bot] in [#&oxc-project#8203;513](https://github.com/oxc-project/tsgolint/pull/513)
- chore(deps): update typescript-go digest to [`6c175a0`](https://github.com/oxc-project/tsgolint/commit/6c175a0) by [@&oxc-project#8203;renovate](https://github.com/renovate)\[bot] in [#&oxc-project#8203;511](https://github.com/oxc-project/tsgolint/pull/511)
- chore(deps): update github-actions (major) by [@&oxc-project#8203;renovate](https://github.com/renovate)\[bot] in [#&oxc-project#8203;515](https://github.com/oxc-project/tsgolint/pull/515)
- chore(deps): update taiki-e/install-action action to v2.63.2 by [@&oxc-project#8203;renovate](https://github.com/renovate)\[bot] in [#&oxc-project#8203;516](https://github.com/oxc-project/tsgolint/pull/516)
- fix(no-base-to-string): remove leading trivia from error message text by [@&oxc-project#8203;camc314](https://github.com/camc314) in [#&oxc-project#8203;519](https://github.com/oxc-project/tsgolint/pull/519)

**Full Changelog**: <oxc-project/tsgolint@v0.9.0...v0.9.1>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi41NC4yIiwidXBkYXRlZEluVmVyIjoiNDIuNTQuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
…ct#16909)

Updates submodule dependencies to their latest commits.

## Changes

- test262: `c0cf527` → `947fee3`
- babel: `3591b24` → `84d21e4`
- TypeScript: `c21f73f` → `0a07132`
- estree-conformance: `1f2816b` → `e0aa1b4`

This PR is automatically generated by the [update_submodules workflow](https://github.com/oxc-project/oxc/blob/main/.github/workflows/update_submodules.yml).
…c-project#16801)

Avoid heap allocation for the common case (0-2 default exports) by using
SmallVec with inline capacity of 2 instead of Vec.

🤖 generated with help from Claude Opus 4.5
… with single empty line (oxc-project#16012)

fixes oxc-project#15990

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
…y as default options (oxc-project#16913)

Small optimization to options merging. Treat rules which define `defaultOptions` as an empty array the same as those which provide no `defaultOptions` at all. This makes options merging take a faster path for these rules.
@lilnasy lilnasy force-pushed the refactor/parseconfig branch from 5f97c54 to 545d09b Compare December 15, 2025 18:49
@lilnasy lilnasy deleted the branch rustify-tokens December 16, 2025 19:33
@lilnasy lilnasy closed this Dec 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.