diff --git a/apps/oxlint/src-js/package/define.ts b/apps/oxlint/src-js/package/define.ts index bc68bbaabd635..4a7bb009507fd 100644 --- a/apps/oxlint/src-js/package/define.ts +++ b/apps/oxlint/src-js/package/define.ts @@ -101,13 +101,10 @@ export function defineRule(rule: Rule): Rule { return rule; } -// Cached current working directory -let cwd: string | null = null; - // File context object. Used as prototype for `Context` objects for each rule during `createOnce` call. // When running the rules, ESLint's `context` object is switching in as prototype for `Context` objects. // -// Only `cwd` property and `extends` method are available in `createOnce`, so only those are implemented here. +// Only `extends` method is available in `createOnce`, so only that is implemented here. // All other getters/methods throw, same as they do in main implementation. // // See `FILE_CONTEXT` in `plugins/context.ts` for details of all the getters/methods. @@ -129,14 +126,11 @@ const FILE_CONTEXT: FileContext = Object.freeze({ }, get cwd(): string { - // Note: We can allow accessing `cwd` in `createOnce`, as it's global - if (cwd === null) cwd = process.cwd(); - return cwd; + throw new Error("Cannot access `context.cwd` in `createOnce`"); }, getCwd(): string { - if (cwd === null) cwd = process.cwd(); - return cwd; + throw new Error("Cannot call `context.getCwd` in `createOnce`"); }, get sourceCode(): SourceCode { @@ -192,7 +186,7 @@ function createContextAndVisitor(rule: CreateOnceRule): { // Call `createOnce` with empty context object. // Really, accessing `options` or calling `report` should throw, because they're illegal in `createOnce`. // But any such bugs should have been caught when testing the rule in Oxlint, so should be OK to take this shortcut. - // `FILE_CONTEXT` prototype provides `cwd` property and `extends` method, which are available in `createOnce`. + // `FILE_CONTEXT` prototype provides `extends` method, which is available in `createOnce`. const context: Context = Object.create(FILE_CONTEXT, { id: { value: "", enumerable: true, configurable: true }, options: { value: null, enumerable: true, configurable: true }, diff --git a/apps/oxlint/src-js/plugins/context.ts b/apps/oxlint/src-js/plugins/context.ts index 963ea8fa96ba5..10a30f56da338 100644 --- a/apps/oxlint/src-js/plugins/context.ts +++ b/apps/oxlint/src-js/plugins/context.ts @@ -303,9 +303,8 @@ const FILE_CONTEXT = Object.freeze({ * Current working directory. */ get cwd(): string { - // Note: We can allow accessing `cwd` in `createOnce`, as it's global. - // Note: If we change this implementation, also change `getCwd` method below, - // and `cwd` getter + `getCwd` method in `index.ts` (`createOnce` shim for ESLint). + // Note: If we change this implementation, also change `getCwd` method below + if (filePath === null) throw new Error("Cannot access `context.cwd` in `createOnce`"); if (cwd === null) cwd = process.cwd(); return cwd; }, @@ -316,6 +315,7 @@ const FILE_CONTEXT = Object.freeze({ * @deprecated Use `context.cwd` property instead. */ getCwd(): string { + if (filePath === null) throw new Error("Cannot call `context.getCwd` in `createOnce`"); if (cwd === null) cwd = process.cwd(); return cwd; }, diff --git a/apps/oxlint/test/fixtures/createOnce/output.snap.md b/apps/oxlint/test/fixtures/createOnce/output.snap.md index 8a85de7635491..8f64a7d57d45f 100644 --- a/apps/oxlint/test/fixtures/createOnce/output.snap.md +++ b/apps/oxlint/test/fixtures/createOnce/output.snap.md @@ -21,7 +21,7 @@ : ^ `---- - x create-once-plugin(always-run): createOnce: cwd: + x create-once-plugin(always-run): createOnce: cwd error: Cannot access `context.cwd` in `createOnce` ,-[files/1.js:1:1] 1 | let x; : ^ @@ -45,7 +45,7 @@ : ^ `---- - x create-once-plugin(always-run): createOnce: getCwd(): + x create-once-plugin(always-run): createOnce: getCwd() error: Cannot call `context.getCwd` in `createOnce` ,-[files/1.js:1:1] 1 | let x; : ^ @@ -195,7 +195,7 @@ : ^ `---- - x create-once-plugin(always-run): createOnce: cwd: + x create-once-plugin(always-run): createOnce: cwd error: Cannot access `context.cwd` in `createOnce` ,-[files/2.js:1:1] 1 | let y; : ^ @@ -219,7 +219,7 @@ : ^ `---- - x create-once-plugin(always-run): createOnce: getCwd(): + x create-once-plugin(always-run): createOnce: getCwd() error: Cannot call `context.getCwd` in `createOnce` ,-[files/2.js:1:1] 1 | let y; : ^ diff --git a/apps/oxlint/test/fixtures/createOnce/plugin.ts b/apps/oxlint/test/fixtures/createOnce/plugin.ts index b806cf0973096..387556928412b 100644 --- a/apps/oxlint/test/fixtures/createOnce/plugin.ts +++ b/apps/oxlint/test/fixtures/createOnce/plugin.ts @@ -20,12 +20,10 @@ const alwaysRunRule: Rule = { // oxlint-disable-next-line typescript-eslint/no-this-alias const topLevelThis = this; - // Check that these APIs don't throw here - const { cwd } = context; - const getCwd = context.getCwd(); - // Check that these APIs throw here const idError = tryCatch(() => context.id); + const cwdError = tryCatch(() => context.cwd); + const getCwdError = tryCatch(() => context.getCwd()); const filenameError = tryCatch(() => context.filename); const getFilenameError = tryCatch(() => context.getFilename()); const physicalFilenameError = tryCatch(() => context.physicalFilename); @@ -44,8 +42,11 @@ const alwaysRunRule: Rule = { message: `createOnce: this === rule: ${topLevelThis === alwaysRunRule}`, node: SPAN, }); - context.report({ message: `createOnce: cwd: ${cwd}`, node: SPAN }); - context.report({ message: `createOnce: getCwd(): ${getCwd}`, node: SPAN }); + context.report({ message: `createOnce: cwd error: ${cwdError?.message}`, node: SPAN }); + context.report({ + message: `createOnce: getCwd() error: ${getCwdError?.message}`, + node: SPAN, + }); context.report({ message: `createOnce: id error: ${idError?.message}`, node: SPAN }); context.report({ message: `createOnce: filename error: ${filenameError?.message}`,