diff --git a/apps/oxlint/test/e2e.test.ts b/apps/oxlint/test/e2e.test.ts index ca1c1a5079491..277385f0c673f 100644 --- a/apps/oxlint/test/e2e.test.ts +++ b/apps/oxlint/test/e2e.test.ts @@ -250,4 +250,8 @@ describe('oxlint CLI', () => { it('should support UTF16 characters in source code and comments with correct spans', async () => { await testFixture('unicode-comments'); }); + + it('should report an error when a plugin wraps context and loses private #internal field', async () => { + await testFixture('oxc_issue_15325'); + }); }); diff --git a/apps/oxlint/test/fixtures/oxc_issue_15325/.oxlintrc.json b/apps/oxlint/test/fixtures/oxc_issue_15325/.oxlintrc.json new file mode 100644 index 0000000000000..a895c69b7e092 --- /dev/null +++ b/apps/oxlint/test/fixtures/oxc_issue_15325/.oxlintrc.json @@ -0,0 +1,9 @@ +{ + "jsPlugins": ["./plugin.ts"], + "categories": { + "correctness": "off" + }, + "rules": { + "wrapped-context/wrapped-rule": "error" + } +} diff --git a/apps/oxlint/test/fixtures/oxc_issue_15325/files/index.js b/apps/oxlint/test/fixtures/oxc_issue_15325/files/index.js new file mode 100644 index 0000000000000..a8141d3b18d34 --- /dev/null +++ b/apps/oxlint/test/fixtures/oxc_issue_15325/files/index.js @@ -0,0 +1 @@ +console.log("Hello, world!"); diff --git a/apps/oxlint/test/fixtures/oxc_issue_15325/output.snap.md b/apps/oxlint/test/fixtures/oxc_issue_15325/output.snap.md new file mode 100644 index 0000000000000..b0fb569a3ae2a --- /dev/null +++ b/apps/oxlint/test/fixtures/oxc_issue_15325/output.snap.md @@ -0,0 +1,20 @@ +# Exit code +1 + +# stdout +``` + x Error running JS plugin. + | File path: /apps/oxlint/test/fixtures/oxc_issue_15325/files/index.js + | TypeError: Cannot read private member #internal from an object whose class did not declare it + | at Object.create (/apps/oxlint/test/fixtures/oxc_issue_15325/plugin.ts:10:33) + | at Object.create (/apps/oxlint/test/fixtures/oxc_issue_15325/plugin.ts:36:25) + +Found 0 warnings and 1 error. +Finished in Xms on 1 file using X threads. +``` + +# stderr +``` +WARNING: JS plugins are experimental and not subject to semver. +Breaking changes are possible while JS plugins support is under development. +``` diff --git a/apps/oxlint/test/fixtures/oxc_issue_15325/plugin.ts b/apps/oxlint/test/fixtures/oxc_issue_15325/plugin.ts new file mode 100644 index 0000000000000..7efd7ab8a0a08 --- /dev/null +++ b/apps/oxlint/test/fixtures/oxc_issue_15325/plugin.ts @@ -0,0 +1,42 @@ +import type { Plugin } from "../../../dist/index.js"; + +function trapReport(_context: any) { + return function (_obj: any) {}; +} + +const baseRule = { + create(context: any) { + // Base rule tries to access sourceCode + const _sourceCode = context.sourceCode; + return { + Identifier(node: any) { + context.report({ + node, + message: "Base rule found identifier", + }); + }, + }; + }, +}; + +const plugin: Plugin = { + meta: { + name: "wrapped-context", + }, + rules: { + "wrapped-rule": { + create(context) { + const contextForBaseRule = Object.create(context, { + report: { + value: trapReport(context), + writable: false, + }, + }); + + return baseRule.create(contextForBaseRule); + }, + }, + }, +}; + +export default plugin;