Resolves https://github.com/oxc-project/oxc/issues/22090
## Summary
Fixes Astro frontmatter parsing so it stops at the first valid closing
`---` fence, instead of the last `---` anywhere in the file. This
prevents `---` inside template/script content from being treated as a
frontmatter delimiter.
## Changes included
- Updated `AstroPartialLoader` frontmatter parsing to recognize only
standalone fence lines, require the opening fence at file start
(ignoring whitespace), and pair it with the next valid closing fence.
- Returned the frontmatter end offset from parsing so subsequent script
extraction starts after frontmatter.
- Added a regression test covering `.astro` content where later
JS/template strings include `---`.
LLM Disclosure: This was developed by an agent on this PR
https://github.com/shellscape/oxc/pull/1, but supervised by a human
(me).
---------
Co-authored-by: charliecreates[bot] <198680274+charliecreates[bot]@users.noreply.github.com>
Co-authored-by: CharlieHelps <charlie@charlielabs.ai>
Co-authored-by: Cameron <cameron.clark@hey.com>
fixes#21942
Astro script tags with non-JavaScript type values are now skipped by the partial loader, so import maps and JSON scripts are not parsed as TypeScript. The shared script attribute parser is reused with Svelte to avoid duplicating tag parsing logic.
## Summary
- parse Svelte <script> attributes instead of broad substring checks
- detect both module and context="module" scripts when creating partial
JS sources
- add unit and CLI coverage for module/instance scripts in both JS and
TS
## Validation
- mise x -- cargo test -p oxlint lint_svelte_
- mise x -- cargo test -p oxc_linter partial_loader::svelte
## AI usage disclosure
This PR was prepared with AI assistance (Codex). I reviewed and take
responsibility for the final changes.
---------
Co-authored-by: Cameron <cameron.clark@hey.com>
## Summary
- Implements speculative/unambiguous parsing for `.js`, `.jsx`, `.ts`, and `.tsx` files
- Instead of assuming module or script upfront, parses with `ModuleKind::Unambiguous` and upgrades to module mode when ESM syntax is detected
- ESM indicators: `import`, `export`, `import.meta` (NOT top-level await alone)
- Defers top-level await errors until module type is resolved
- Vue loader upgrades unambiguous scripts to module mode
- Updates linter tests to use explicit ESM extensions (`.mjs`/`.mts`) where needed
## Test plan
- [x] All parser tests pass
- [x] All linter tests pass
- [x] All semantic tests pass
- [x] Coverage conformance tests updated
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary
- Updates `SourceType::from_path()` to return `ModuleKind::CommonJS` for `.cjs`/`.cts` files (previously returned `ModuleKind::Script`)
- Fixes `eslint/no-eval` to check `!is_module()` instead of `is_script()` to handle both scripts and CommonJS (matching ESLint's `sourceType: "commonjs"` behavior)
- Fixes `eslint/no-redeclare` to run for both scripts and CommonJS files
- Updates tests to use proper CommonJS assertions
This follows up on #18089 which added `ModuleKind::CommonJS` support but didn't update the file extension mapping.
## Test plan
- [x] `cargo test -p oxc_span`
- [x] `cargo test -p oxc_linter`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Partial loader tries parsing the `<script>` tag in the code comment
incorrectly
For example, we have a `.vue` file
```vue
<!-- <script setup lang="tsx"> -->
<script setup lang="ts">
const count = ref(0)
</script>
```
And the loader will regard these as script part
```
-->
<script setup lang="ts">
const count = ref(0)
```
So this PR added some `Finder`s for code comment to ignore the
`<script>` in code comment, also works on `.svelte` and `.astro` files
Another approach to https://github.com/oxc-project/oxc/pull/12541 stack.
Because `vue/valid-define-emit` and other rules required the semantics of the other script block.
## The Goal:
`Linter.run` should run with the complete file context. In `vue` files and others, there can be multiple Semantics / Module Records.
Because `vue` requires some magic compiler rules, the linter should have access to the complete file.
This will also fix the offset bug in #12758. ~~**Don't** merge both stacks without rebasing.~~
I do not like the loop part. Maybe you guys have some better ideas.
---
<img width="1160" height="422" alt="benchmark results" src="https://github.com/user-attachments/assets/88702a01-eeb2-4a4f-8d80-c5236d3fa8cc" />
Same as #10230, but for linter.
Replace usages of `write!` macro with either `fmt.write_str(...)` for static strings or `Display::fmt` / `Debug::fmt` for other values, where it's not being used to concatenate multiple values.
`Formatter::write_str` is more performant, as it avoids various checks. `Display::fmt` / `Debug::fmt` may also perform a little better in some cases, and will be equivalent in others. But in all cases it should be better for compile times, due to avoiding macro expansion and trait resolution.
Previously, we were wasting some time creating a `Vec` at runtime with the lintable extensions, which is all of the JS/TS extensions plus other frameworks extensions like `.vue`. Now, we precompute this as a static string slice at compile time. This also ensures that we are using the same extensions list between `oxlint` and the language server too. Theoretically this is a very minor perf win possibly?
Replace `#[allow]` with `#[expect]` through the whole codebase.
This also surfaced many places where the `#[allow]` attributes were outdated/pointless and could be removed entirely.
Only places `#[allow]` remains are:
1. In generated code and macros, where lint errors may or may not be triggered depending on the generated code.
2. A few places where clippy malfunctions. These use e.g. `#[allow(unused, clippy::allow_attributes)]`.
Pure refactor. Re-order imports for clarity:
1. `std`
2. External crates
3. `oxc_*` crates
4. Current crate `use crate::...`
5. Super `use super::...`
6. Local modules
This order is from "furthest away" to "closest". This makes it clearer to see what is coming from where.
`cargo +nightly fmt` (#7877) did a lot of the work, but unfortunately `rustfmt` does not have an option to (a) put workspace crates in a separate block from external crates and (b) move `mod` statements to after `use` statements.
Previously, we reported the `source_text` of an Astro file correctly, but the `start` offset was incorrectly set to before the `---` of the frontmatter. The start value now correctly points to the end of the split.
# Human Description
Low on time, so this one is short.
- consolidate source file and partial loader logic into `loader` module. I have more plans for this.
- ~LSP no longer uses `VALID_EXTENSIONS`, so now `.d.ts` files (and the like) will be linted as well~ LSP does not respect `.gitignore` files, so this change was reverted.
# AI Description
## Refactor Loader and Partial Loader
This PR refactors the loader and partial loader functionality in the oxc_linter crate:
* Introduce a new `Loader` struct with methods for checking if a file can be loaded and loading file contents
* Move `partial_loader` module to `loader/partial_loader`
* Rename `JavaScriptSource` to `source.rs` and move it to the `loader` module
* Update `JavaScriptSource` to use `u32` for `start` offset instead of `usize`
* Refactor `IsolatedLintHandler` to use the new `Loader`
* Update imports and module references throughout the codebase
This change improves the organization of the loader-related code and provides a more unified interface for loading different file types.