diff --git a/packages/vscode/e2e/lint/suite-ancestor/ancestor.test.ts b/packages/vscode/e2e/lint/suite-ancestor/ancestor.test.ts index f5d91a3d..40b0fd18 100644 --- a/packages/vscode/e2e/lint/suite-ancestor/ancestor.test.ts +++ b/packages/vscode/e2e/lint/suite-ancestor/ancestor.test.ts @@ -46,6 +46,38 @@ suite('rslint config above the workspace folder', function () { diagnosticRuleIdIncludes(diagnostic, 'no-debugger'), ); + // On macOS, Node's directory `fs.watch` runs on one FSEventStream per + // process, and libuv destroys and recreates that stream (from + // `kFSEventStreamEventIdSinceNow`) whenever a directory watcher starts or + // stops. VS Code's non-recursive watchers share one watcher process, so an + // edit made while any other directory watcher starts can be lost by all of + // them. Startup still churns watchers right after the first diagnostics (Go + // registers its own ancestor watchers only once initialized), and macOS CI + // lost the first edit there: the diagnostics never changed. Writing the same + // content again, as a user saving twice would, re-signals the edit. The + // diagnostics must still follow the file within the overall timeout. + async function writeConfigUntilDiagnostics( + document: vscode.TextDocument, + filePath: string, + content: string, + predicate: (diagnostics: vscode.Diagnostic[]) => boolean, + ): Promise { + const deadline = Date.now() + 60_000; + for (;;) { + fs.writeFileSync(filePath, content); + try { + await waitForDiagnostics( + document, + predicate, + Math.max(0, Math.min(10_000, deadline - Date.now())), + ); + return; + } catch (error) { + if (Date.now() >= deadline) throw error; + } + } + } + teardown(async () => { fs.rmSync(nearerConfigPath(), { force: true }); fs.writeFileSync(rootConfigPath(), configWithNoDebugger('error')); @@ -56,14 +88,19 @@ suite('rslint config above the workspace folder', function () { const document = await openIndex(); await waitForDiagnostics(document, hasNoDebugger); - fs.writeFileSync(rootConfigPath(), configWithNoDebugger('off')); - await waitForDiagnostics( + await writeConfigUntilDiagnostics( document, + rootConfigPath(), + configWithNoDebugger('off'), (diagnostics) => !hasNoDebugger(diagnostics), ); - fs.writeFileSync(rootConfigPath(), configWithNoDebugger('error')); - await waitForDiagnostics(document, hasNoDebugger); + await writeConfigUntilDiagnostics( + document, + rootConfigPath(), + configWithNoDebugger('error'), + hasNoDebugger, + ); }); // The live runtime keeps its key; the extension's ancestor watchers send diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 1c096ff9..08e2ba3b 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -445,7 +445,7 @@ "@vscode/test-electron": "^3.1.0", "@vscode/vsce": "^3.9.2", "birpc": "^4.2.0", - "core-js-pure": "^3.50.0", + "core-js-pure": "^3.51.0", "mocha": "^11.8.0", "ovsx": "^1.3.0", "picomatch": "^4.0.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7f5a18a4..5adab70e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,8 +60,8 @@ importers: specifier: ^4.2.0 version: 4.2.0 core-js-pure: - specifier: ^3.50.0 - version: 3.50.0 + specifier: ^3.51.0 + version: 3.51.0 mocha: specifier: ^11.8.0 version: 11.8.0 @@ -1503,8 +1503,8 @@ packages: commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - core-js-pure@3.50.0: - resolution: {integrity: sha512-6GP3Pxz4IKyWjAfa747vIu/jilB5z29JWROLqH/b+pXVcpgh6tM06ZIBwSuglgVqzDYURhOK6oEzTrG0bCHitA==} + core-js-pure@3.51.0: + resolution: {integrity: sha512-NE4SFDJ+qzQeqHG2vVSNwopzS6zZNPYJ5kinIqs+OofTqGzOmICgT89E/yvS9XY7rwb3eU1utWXTJ9nVFqv74A==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -4233,7 +4233,7 @@ snapshots: commander@2.20.3: {} - core-js-pure@3.50.0: {} + core-js-pure@3.51.0: {} core-util-is@1.0.3: {}