From 4a2ca5c068a2462212f2b7488705c0db44fc466f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 6 Oct 2026 13:36:35 +0100 Subject: [PATCH 001/174] Allow logging functions to accept `string[]` directly --- lib/entry-points.js | 20 ++++++++++++++++---- src/logging.test.ts | 17 +++++++++++++++++ src/logging.ts | 43 +++++++++++++++++++++++++++++++++++-------- src/testing-utils.ts | 14 +++++++------- 4 files changed, 75 insertions(+), 19 deletions(-) create mode 100644 src/logging.test.ts diff --git a/lib/entry-points.js b/lib/entry-points.js index 4bda956850..8de2effc4a 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -170510,12 +170510,24 @@ function fixCodeQualityCategory(logger2, category, env = getEnv()) { // src/logging.ts var core5 = __toESM(require_core()); +var joinMessageStrings = (message) => { + if (Array.isArray(message)) { + return message.join(" "); + } else { + return message; + } +}; +var autoJoinMessageStrings = (fn) => { + return (message) => { + return fn(joinMessageStrings(message)); + }; +}; function getActionsLogger() { return { - debug: core5.debug, - info: core5.info, - warning: core5.warning, - error: core5.error, + debug: autoJoinMessageStrings(core5.debug), + info: autoJoinMessageStrings(core5.info), + warning: autoJoinMessageStrings(core5.warning), + error: autoJoinMessageStrings(core5.error), isDebug: core5.isDebug, startGroup: core5.startGroup, endGroup: core5.endGroup diff --git a/src/logging.test.ts b/src/logging.test.ts new file mode 100644 index 0000000000..33f6f8c162 --- /dev/null +++ b/src/logging.test.ts @@ -0,0 +1,17 @@ +import test from "ava"; + +import { joinMessageStrings } from "./logging"; +import { setupTests } from "./testing-utils"; + +setupTests(test); + +test("joinMessageStrings", async (t) => { + // For strings and errors, it is the identity function. + t.deepEqual(joinMessageStrings("Hello"), "Hello"); + + const error = new Error("Some error"); + t.deepEqual(joinMessageStrings(error), error); + + // For arrays of strings, we get a join-ed string. + t.deepEqual(joinMessageStrings(["foo", "bar"]), "foo bar"); +}); diff --git a/src/logging.ts b/src/logging.ts index 2c34cb54d4..177aca6c7b 100644 --- a/src/logging.ts +++ b/src/logging.ts @@ -1,10 +1,16 @@ import * as core from "@actions/core"; +/** Types that all of our logging functions accept. */ +export type Loggable = string | string[]; + +/** Some logging functions also accept errors directly. */ +export type LoggableError = Loggable | Error; + export interface Logger { - debug: (message: string) => void; - info: (message: string) => void; - warning: (message: string | Error) => void; - error: (message: string | Error) => void; + debug: (message: Loggable) => void; + info: (message: Loggable) => void; + warning: (message: LoggableError) => void; + error: (message: LoggableError) => void; isDebug: () => boolean; @@ -12,12 +18,33 @@ export interface Logger { endGroup: () => void; } +/** If `message` is an array of strings, the array is `join`-ed into one string separated by spaces. */ +export const joinMessageStrings = ( + message: string[] | string | T, +): string | T => { + if (Array.isArray(message)) { + return message.join(" "); + } else { + return message; + } +}; + +/** + * Wraps a logging function so that `joinMessageStrings` is applied to the input before + * calling the wrapped logging function. + */ +const autoJoinMessageStrings = (fn: (msg: string | T) => void) => { + return (message: string[] | string | T) => { + return fn(joinMessageStrings(message)); + }; +}; + export function getActionsLogger(): Logger { return { - debug: core.debug, - info: core.info, - warning: core.warning, - error: core.error, + debug: autoJoinMessageStrings(core.debug), + info: autoJoinMessageStrings(core.info), + warning: autoJoinMessageStrings(core.warning), + error: autoJoinMessageStrings(core.error), isDebug: core.isDebug, startGroup: core.startGroup, endGroup: core.endGroup, diff --git a/src/testing-utils.ts b/src/testing-utils.ts index cd60318944..1318415a72 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -30,7 +30,7 @@ import { featureConfig, FeatureEnablement, } from "./feature-flags"; -import { Logger } from "./logging"; +import { joinMessageStrings, Loggable, LoggableError, Logger } from "./logging"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import { getBundlePlatform } from "./platform"; import { ActionName } from "./status-report"; @@ -618,8 +618,8 @@ export class RecordingLogger implements Logger { constructor(private readonly logToConsole: boolean = true) {} - private addMessage(level: LogLevel, message: string | Error): void { - this.messages.push({ type: level, message }); + private addMessage(level: LogLevel, message: LoggableError): void { + this.messages.push({ type: level, message: joinMessageStrings(message) }); if (this.logToConsole) { // eslint-disable-next-line no-console @@ -644,19 +644,19 @@ export class RecordingLogger implements Logger { return true; } - debug(message: string) { + debug(message: Loggable) { this.addMessage("debug", message); } - info(message: string) { + info(message: Loggable) { this.addMessage("info", message); } - warning(message: string | Error) { + warning(message: LoggableError) { this.addMessage("warning", message); } - error(message: string | Error) { + error(message: LoggableError) { this.addMessage("error", message); } From 924990a9c72b2fe575695534ab9db24dc3bbbc2a Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 14 Oct 2026 14:38:12 +0100 Subject: [PATCH 002/174] Move `getCodeQLForTesting` to `testing-utils.ts` --- src/codeql.test.ts | 7 ++++--- src/codeql.ts | 16 ++-------------- src/init-action-post-helper.test.ts | 5 +++-- src/testing-utils.ts | 20 +++++++++++++++++++- src/tracer-config.test.ts | 3 ++- src/workflow.test.ts | 3 ++- 6 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/codeql.test.ts b/src/codeql.test.ts index 3237d57723..643f6d9839 100644 --- a/src/codeql.test.ts +++ b/src/codeql.test.ts @@ -34,6 +34,7 @@ import { makeVersionInfo, createTestConfig, makeMacro, + getCodeQLForTesting, } from "./testing-utils"; import { ToolsDownloadStatusReport } from "./tools-download"; import * as util from "./util"; @@ -140,7 +141,7 @@ function mockApiDetails(apiDetails: GitHubApiDetails) { } async function stubCodeql(): Promise { - const codeqlObject = await codeql.getCodeQLForTesting(); + const codeqlObject = await getCodeQLForTesting(); sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6")); sinon .stub(codeqlObject, "isTracedLanguage") @@ -1039,7 +1040,7 @@ test.serial("runTool summarizes autobuilder errors", async (t) => { [2019-09-18 12:00:01] [autobuild] A non-error message `; stubToolRunnerConstructor(1, stderr); - const codeqlObject = await codeql.getCodeQLForTesting(); + const codeqlObject = await getCodeQLForTesting(); sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6")); sinon.stub(codeqlObject, "resolveExtractor").resolves("/path/to/extractor"); // io throws because of the test CodeQL object. @@ -1095,7 +1096,7 @@ test.serial("runTool recognizes fatal internal errors", async (t) => { com.semmle.util.exception.CatastrophicError: An error occurred while evaluating ControlFlowGraph::ControlFlow::Root.isRootOf/1#dispred#f610e6ed/2@86282cc8 Severe disk cache trouble (corruption or out of space) at /home/runner/work/_temp/codeql_databases/go/db-go/default/cache/pages/28/33.pack: Failed to write item to disk`; stubToolRunnerConstructor(1, stderr); - const codeqlObject = await codeql.getCodeQLForTesting(); + const codeqlObject = await getCodeQLForTesting(); sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6")); sinon.stub(codeqlObject, "resolveExtractor").resolves("/path/to/extractor"); // io throws because of the test CodeQL object. diff --git a/src/codeql.ts b/src/codeql.ts index 68273d27b5..fde35b171b 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -26,7 +26,7 @@ import { } from "./feature-flags"; import { isAnalyzingDefaultBranch } from "./git-utils"; import { Language } from "./languages"; -import { getRunnerLogger, Logger } from "./logging"; +import type { Logger } from "./logging"; import { writeBaseDatabaseOidsFile, writeOverlayChangesFile } from "./overlay"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import * as setupCodeql from "./setup-codeql"; @@ -486,18 +486,6 @@ export function createStubCodeQL(partialCodeql: Partial): CodeQL { }; } -/** - * Get a real, newly created CodeQL instance for testing. The instance refers to - * a non-existent placeholder codeql command, so tests that use this function - * should also stub the toolrunner.ToolRunner constructor. - */ -export async function getCodeQLForTesting( - cmd = "codeql-for-testing", - logger: Logger = getRunnerLogger(true), -): Promise { - return getCodeQLForCmd(logger, cmd, false); -} - /** * Return a CodeQL object for CodeQL CLI access. * @@ -506,7 +494,7 @@ export async function getCodeQLForTesting( * version requirement. Must be set to true outside tests. * @returns A new CodeQL object */ -async function getCodeQLForCmd( +export async function getCodeQLForCmd( logger: Logger, cmd: string, checkVersion: boolean, diff --git a/src/init-action-post-helper.test.ts b/src/init-action-post-helper.test.ts index fd1f489f7a..26b6ff4aba 100644 --- a/src/init-action-post-helper.test.ts +++ b/src/init-action-post-helper.test.ts @@ -20,6 +20,7 @@ import { createFeatures, createTestConfig, DEFAULT_ACTIONS_VARS, + getCodeQLForTesting, getTestEnv, makeMacro, makeVersionInfo, @@ -737,7 +738,7 @@ async function testFailedSarifUpload( .withArgs("matrix") .returns(JSON.stringify(matrix)); - const codeqlObject = await codeql.getCodeQLForTesting(); + const codeqlObject = await getCodeQLForTesting(); sinon.stub(codeql, "getCodeQL").resolves(codeqlObject); sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6")); const databaseExportDiagnosticsStub = sinon.stub( @@ -832,7 +833,7 @@ async function mockRiskAssessmentEnv(matrix: string) { .stub(apiClient, "getGitHubVersion") .resolves({ type: util.GitHubVariant.GHES, version: "3.0.0" }); - const codeqlObject = await codeql.getCodeQLForTesting(); + const codeqlObject = await getCodeQLForTesting(); const databaseExportDiagnostics = sinon .stub(codeqlObject, "databaseExportDiagnostics") .resolves(); diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 1318415a72..dfb08d9972 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -30,7 +30,13 @@ import { featureConfig, FeatureEnablement, } from "./feature-flags"; -import { joinMessageStrings, Loggable, LoggableError, Logger } from "./logging"; +import { + getRunnerLogger, + joinMessageStrings, + Loggable, + LoggableError, + Logger, +} from "./logging"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import { getBundlePlatform } from "./platform"; import { ActionName } from "./status-report"; @@ -1000,3 +1006,15 @@ export function makeTestToken(length: number = 36) { "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; return chars.repeat(Math.ceil(length / chars.length)).slice(0, length); } + +/** + * Get a real, newly created CodeQL instance for testing. The instance refers to + * a non-existent placeholder codeql command, so tests that use this function + * should also stub the toolrunner.ToolRunner constructor. + */ +export async function getCodeQLForTesting( + cmd = "codeql-for-testing", + logger: Logger = getRunnerLogger(true), +): Promise { + return codeql.getCodeQLForCmd(logger, cmd, false); +} diff --git a/src/tracer-config.test.ts b/src/tracer-config.test.ts index a3c42d668d..f410d47c16 100644 --- a/src/tracer-config.test.ts +++ b/src/tracer-config.test.ts @@ -4,11 +4,12 @@ import * as path from "path"; import test from "ava"; import * as sinon from "sinon"; -import { CodeQL, getCodeQLForTesting } from "./codeql"; +import type { CodeQL } from "./codeql"; import * as configUtils from "./config-utils"; import { BuiltInLanguage } from "./languages"; import { createTestConfig, + getCodeQLForTesting, makeVersionInfo, RecordingLogger, setupTests, diff --git a/src/workflow.test.ts b/src/workflow.test.ts index c7f168a9dc..5763430781 100644 --- a/src/workflow.test.ts +++ b/src/workflow.test.ts @@ -3,10 +3,11 @@ import * as yaml from "js-yaml"; import * as sinon from "sinon"; import * as actionsUtil from "./actions-util"; -import { createStubCodeQL, getCodeQLForTesting } from "./codeql"; +import { createStubCodeQL } from "./codeql"; import { EnvVar } from "./environment"; import { checkExpectedLogMessages, + getCodeQLForTesting, getRecordingLogger, LoggedMessage, setupTests, From 23d418cf2e0b4e2cfd4b455402bc9db48487e135 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 14 Oct 2026 14:50:54 +0100 Subject: [PATCH 003/174] Remove `getRunnerLogger` --- src/actions-util.test.ts | 3 +- src/analyses.test.ts | 11 ++-- src/analyze.test.ts | 4 +- src/artifact-scanner.test.ts | 4 +- src/cli/output-cache.test.ts | 5 +- src/codeql.test.ts | 24 ++++----- src/config-utils.test.ts | 32 ++++++------ src/config/db-config.test.ts | 7 ++- src/diff-informed-analysis-utils.test.ts | 14 +++--- src/feature-flags/properties.test.ts | 17 +++---- src/feature-flags/testing-util.ts | 5 +- src/fingerprints.test.ts | 9 ++-- src/init-action-post-helper.test.ts | 17 +++---- src/logging.ts | 16 ------ src/overlay/caching.test.ts | 20 ++++---- src/overlay/index.test.ts | 15 +++--- src/setup-codeql.test.ts | 64 ++++++++++++------------ src/start-proxy.test.ts | 40 +++++++-------- src/status-report.test.ts | 21 ++++---- src/tar.test.ts | 5 +- src/testing-utils.ts | 10 +--- src/tools-download.test.ts | 15 +++--- src/trap-caching.test.ts | 4 +- src/upload-lib.test.ts | 22 ++++---- src/upload-sarif.test.ts | 14 ++++-- src/util.test.ts | 17 +++---- 26 files changed, 195 insertions(+), 220 deletions(-) diff --git a/src/actions-util.test.ts b/src/actions-util.test.ts index 17cf96a4a5..175fdea966 100644 --- a/src/actions-util.test.ts +++ b/src/actions-util.test.ts @@ -11,7 +11,6 @@ import { } from "./actions-util"; import { computeAutomationID } from "./api-client"; import { EnvVar } from "./environment"; -import { getRunnerLogger } from "./logging"; import { RecordingLogger, setupTests } from "./testing-utils"; import { initializeEnvironment, withTmpDir } from "./util"; @@ -238,7 +237,7 @@ test.serial("fixCodeQualityCategory", (t) => { GITHUB_EVENT_NAME: "dynamic", }, () => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); // Categories that should get adjusted. t.is(fixCodeQualityCategory(logger, "/language:c#"), "/language:csharp"); diff --git a/src/analyses.test.ts b/src/analyses.test.ts index 9d0a9eb3e0..b9d182618a 100644 --- a/src/analyses.test.ts +++ b/src/analyses.test.ts @@ -15,7 +15,6 @@ import { supportedAnalysisKinds, } from "./analyses"; import { EnvVar } from "./environment"; -import { getRunnerLogger } from "./logging"; import { createFeatures, RecordingLogger, @@ -65,7 +64,7 @@ test.serial( .withArgs("analysis-kinds") .returns("code-scanning,code-quality"); const result = await getAnalysisKinds( - getRunnerLogger(true), + new RecordingLogger(), features, true, ); @@ -139,7 +138,7 @@ test.serial( const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput"); optionalInputStub.withArgs("quality-queries").returns("code-quality"); const result = await getAnalysisKinds( - getRunnerLogger(true), + new RecordingLogger(), features, true, ); @@ -155,7 +154,7 @@ test.serial( const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput"); requiredInputStub.withArgs("analysis-kinds").returns("no-such-thing"); await t.throwsAsync( - getAnalysisKinds(getRunnerLogger(true), features, true), + getAnalysisKinds(new RecordingLogger(), features, true), ); }, ); @@ -181,7 +180,7 @@ for (let i = 0; i < analysisKinds.length; i++) { .withArgs("analysis-kinds") .returns([analysisKind, otherAnalysis].join(",")); const result = await getAnalysisKinds( - getRunnerLogger(true), + new RecordingLogger(), features, true, ); @@ -199,7 +198,7 @@ for (let i = 0; i < analysisKinds.length; i++) { .withArgs("analysis-kinds") .returns([analysisKind, otherAnalysis].join(",")); await t.throwsAsync( - getAnalysisKinds(getRunnerLogger(true), features, true), + getAnalysisKinds(new RecordingLogger(), features, true), { instanceOf: ConfigurationError, message: `${analysisKind} and ${otherAnalysis} cannot be enabled at the same time`, diff --git a/src/analyze.test.ts b/src/analyze.test.ts index 80fc7a5474..e60bec7193 100644 --- a/src/analyze.test.ts +++ b/src/analyze.test.ts @@ -15,12 +15,12 @@ import { createStubCodeQL } from "./codeql"; import { defaultSuites } from "./config/db-config"; import { Feature } from "./feature-flags"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger } from "./logging"; import { setupTests, setupActionsVars, createFeatures, createTestConfig, + RecordingLogger, } from "./testing-utils"; import * as uploadLib from "./upload-lib"; import * as util from "./util"; @@ -107,7 +107,7 @@ test.serial("status report fields", async (t) => { undefined, codeql, config, - getRunnerLogger(true), + new RecordingLogger(), createFeatures([Feature.QaTelemetryEnabled]), ); t.deepEqual(Object.keys(statusReport).sort(), [ diff --git a/src/artifact-scanner.test.ts b/src/artifact-scanner.test.ts index 56f99e1138..50c0d3fd22 100644 --- a/src/artifact-scanner.test.ts +++ b/src/artifact-scanner.test.ts @@ -10,12 +10,12 @@ import { scanArtifactsForTokens, TokenType, } from "./artifact-scanner"; -import { getRunnerLogger } from "./logging"; import { checkExpectedLogMessages, getRecordingLogger, LoggedMessage, makeTestToken, + RecordingLogger, } from "./testing-utils"; test("makeTestToken", (t) => { @@ -121,7 +121,7 @@ for (const { type, value, checkPattern } of testTokens) { } test("scanArtifactsForTokens handles files without tokens", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "scanner-test-")); try { diff --git a/src/cli/output-cache.test.ts b/src/cli/output-cache.test.ts index 656cfd8201..ed49dab09d 100644 --- a/src/cli/output-cache.test.ts +++ b/src/cli/output-cache.test.ts @@ -3,15 +3,14 @@ import path from "path"; import test from "ava"; -import { getRunnerLogger } from "../logging"; -import { setupTests } from "../testing-utils"; +import { RecordingLogger, setupTests } from "../testing-utils"; import * as util from "../util"; import { getCachedCodeQlVersion } from "./output-cache"; setupTests(test); -const logger = getRunnerLogger(true); +const logger = new RecordingLogger(); test.serial( "getCachedCodeQlVersion reuses a version persisted by an earlier step", diff --git a/src/codeql.test.ts b/src/codeql.test.ts index 643f6d9839..4dcc3153e2 100644 --- a/src/codeql.test.ts +++ b/src/codeql.test.ts @@ -22,7 +22,6 @@ import type { Config } from "./config-utils"; import * as defaults from "./defaults.json"; import { DocUrl } from "./doc-url"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger } from "./logging"; import { ToolsSource } from "./setup-codeql"; import { setupTests, @@ -35,6 +34,7 @@ import { createTestConfig, makeMacro, getCodeQLForTesting, + RecordingLogger, } from "./testing-utils"; import { ToolsDownloadStatusReport } from "./tools-download"; import * as util from "./util"; @@ -103,7 +103,7 @@ async function installIntoToolcache({ undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([]), - getRunnerLogger(true), + new RecordingLogger(), false, ); } @@ -177,7 +177,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); @@ -213,7 +213,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); @@ -253,7 +253,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); t.assert(toolcache.find("CodeQL", "0.0.0-20200610")); @@ -363,7 +363,7 @@ for (const { undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); t.assert(toolcache.find("CodeQL", expectedToolcacheVersion)); @@ -406,7 +406,7 @@ for (const toolcacheVersion of [ undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); t.is( @@ -451,7 +451,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); t.deepEqual(result.toolsVersion, "0.0.0-20200601"); @@ -498,7 +498,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); t.deepEqual(result.toolsVersion, defaults.cliVersion); @@ -538,7 +538,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); t.deepEqual(result.toolsVersion, defaults.cliVersion); @@ -580,7 +580,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); @@ -665,7 +665,7 @@ const injectedConfigMacro = makeMacro({ tempDir, }; thisStubConfig.computedConfig = generateCodeScanningConfig( - getRunnerLogger(true), + new RecordingLogger(), thisStubConfig.originalUserInput, augmentationProperties, ); diff --git a/src/config-utils.test.ts b/src/config-utils.test.ts index b1f5f71343..254e86338a 100644 --- a/src/config-utils.test.ts +++ b/src/config-utils.test.ts @@ -21,7 +21,6 @@ import { RepositoryProperties } from "./feature-flags/properties"; import * as gitUtils from "./git-utils"; import { GitVersionInfo } from "./git-utils"; import { BuiltInLanguage, Language } from "./languages"; -import { getRunnerLogger } from "./logging"; import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay"; import * as overlayDiagnostics from "./overlay/diagnostics"; import { OverlayDisabledReason } from "./overlay/diagnostics"; @@ -42,6 +41,7 @@ import { callee, SAMPLE_DOTCOM_API_DETAILS, AssertableTarget, + RecordingLogger, } from "./testing-utils"; import { GitHubVariant, @@ -102,7 +102,7 @@ function createTestInitConfigInputs( features: createFeatures([]), repositoryProperties: {}, enableFileCoverageInformation: true, - logger: getRunnerLogger(true), + logger: new RecordingLogger(), } satisfies configUtils.InitConfigInputs, overrides, ); @@ -150,7 +150,7 @@ function mockListLanguages(languages: string[]) { test.serial("load empty config", async (t) => { return await withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const languages = "javascript,python"; setupActionsVars(tempDir, tempDir); @@ -194,7 +194,7 @@ test.serial("load empty config", async (t) => { test.serial("load code quality config", async (t) => { return await withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const languages = "actions"; setupActionsVars(tempDir, tempDir); @@ -249,7 +249,7 @@ test.serial( "initActionState doesn't throw if there are queries configured in the repository properties", async (t) => { return await withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const languages = "javascript"; setupActionsVars(tempDir, tempDir); @@ -311,7 +311,7 @@ test.serial( test.serial("loading a saved config produces the same config", async (t) => { return await withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = createStubCodeQL({ async resolveLanguages() { @@ -359,7 +359,7 @@ test.serial("loading a saved config produces the same config", async (t) => { test.serial("loading config with version mismatch throws", async (t) => { return await withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = createStubCodeQL({ async resolveLanguages() { @@ -782,12 +782,12 @@ test.serial("Unknown languages", async (t) => { }); }); -const mockLogger = getRunnerLogger(true); +const mockLogger = new RecordingLogger(); test.serial("no generateRegistries when registries is undefined", async (t) => { return await withTmpDir(async (tmpDir) => { const registriesInput = undefined; - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const { registriesAuthTokens, qlconfigFile } = await configUtils.generateRegistries(registriesInput, tmpDir, logger); @@ -808,7 +808,7 @@ test.serial( token: "not-a-token", }, ]); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const { registriesAuthTokens, qlconfigFile } = await configUtils.generateRegistries(registriesInput, tmpDir, logger); @@ -2245,7 +2245,7 @@ test("applyIncrementalAnalysisSettings: no-op when mode is not Overlay and diff const config = createTestConfig({}); config.overlayDatabaseMode = OverlayDatabaseMode.None; const codeql = createStubCodeQL({}); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); await configUtils.applyIncrementalAnalysisSettings( config, @@ -2263,7 +2263,7 @@ test("applyIncrementalAnalysisSettings: keeps overlay mode and adds exclusions w overlayDatabaseMode: OverlayDatabaseMode.Overlay, }); const codeql = createStubCodeQL({}); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); await configUtils.applyIncrementalAnalysisSettings( config, @@ -2286,7 +2286,7 @@ test.serial( }); config.useOverlayDatabaseCaching = true; const codeql = createStubCodeQL({}); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const addDiagnosticsStub = sinon .stub(overlayDiagnostics, "addOverlayDisablementDiagnostics") .resolves(); @@ -2318,7 +2318,7 @@ test.serial( config.useOverlayDatabaseCaching = false; config.overlayModeSetExplicitly = true; const codeql = createStubCodeQL({}); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const addDiagnosticsStub = sinon .stub(overlayDiagnostics, "addOverlayDisablementDiagnostics") .resolves(); @@ -2341,7 +2341,7 @@ test("applyIncrementalAnalysisSettings: adds exclusions for diff-informed-only r const config = createTestConfig({}); config.overlayDatabaseMode = OverlayDatabaseMode.None; const codeql = createStubCodeQL({}); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); await configUtils.applyIncrementalAnalysisSettings( config, @@ -2555,7 +2555,7 @@ test("determineUserConfig - merges configs if FF is enabled in Default Setup", a // also check whether loading the configuration from disk that was written // by `determineUserConfig` matches our expectations. const loadedFromDisk = configUtils.getLocalConfig( - getRunnerLogger(true), + new RecordingLogger(), expectedConfigPath, false, ); diff --git a/src/config/db-config.test.ts b/src/config/db-config.test.ts index 76fa918015..4a10a97017 100644 --- a/src/config/db-config.test.ts +++ b/src/config/db-config.test.ts @@ -2,7 +2,6 @@ import test, { ExecutionContext } from "ava"; import { RepositoryProperties } from "../feature-flags/properties"; import { BuiltInLanguage, Language } from "../languages"; -import { getRunnerLogger } from "../logging"; import { checkExpectedLogMessages, getRecordingLogger, @@ -384,7 +383,7 @@ calculateAugmentationErrorMacro( test("parseUserConfig - successfully parses valid YAML", (t) => { const result = dbConfig.parseUserConfig( - getRunnerLogger(true), + new RecordingLogger(), "test", ` paths-ignore: @@ -410,7 +409,7 @@ test("parseUserConfig - throws a ConfigurationError if the file is not valid YAM t.throws( () => dbConfig.parseUserConfig( - getRunnerLogger(true), + new RecordingLogger(), "test", ` paths-ignore: @@ -629,7 +628,7 @@ test("mergeDefaultSetupAndUserConfigs - warns about invalid keys from Default Se /** Parses `contents` as a configuration without validating it. */ function parseUnvalidatedConfig(contents: string): dbConfig.UserConfig { return dbConfig.parseUserConfig( - getRunnerLogger(true), + new RecordingLogger(), "test", contents, false, diff --git a/src/diff-informed-analysis-utils.test.ts b/src/diff-informed-analysis-utils.test.ts index e07240e322..76e5f33b4d 100644 --- a/src/diff-informed-analysis-utils.test.ts +++ b/src/diff-informed-analysis-utils.test.ts @@ -10,7 +10,6 @@ import { exportedForTesting, } from "./diff-informed-analysis-utils"; import { Feature, FeatureEnablement, initFeatures } from "./feature-flags"; -import { getRunnerLogger } from "./logging"; import { parseRepositoryNwo } from "./repository"; import { setupTests, @@ -19,6 +18,7 @@ import { mockFeatureFlagApiEndpoint, setupActionsVars, makeMacro, + RecordingLogger, } from "./testing-utils"; import { GitHubVariant, withTmpDir } from "./util"; import type { GitHubVersion } from "./util"; @@ -55,7 +55,7 @@ const testShouldPerformDiffInformedAnalysis = makeMacro({ setupActionsVars(tmpDir, tmpDir); const testCase = { ...defaultTestCase, ...partialTestCase }; - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = mockCodeQLVersion(testCase.codeQLVersion); if (testCase.diffInformedQueriesEnvVar !== undefined) { @@ -182,7 +182,7 @@ test.serial( async (t) => { await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = mockCodeQLVersion("2.21.0"); const features = createFeatures([Feature.DiffInformedQueries]); @@ -207,7 +207,7 @@ test.serial( async (t) => { await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = mockCodeQLVersion("2.21.0"); // A features implementation whose getValue rejects, simulating an // unexpected failure when determining whether diff-informed analysis @@ -237,7 +237,7 @@ test.serial( async (t) => { await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = mockCodeQLVersion("2.21.0"); const features = createFeatures([Feature.DiffInformedQueries]); @@ -274,7 +274,7 @@ test.serial( async (t) => { await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = mockCodeQLVersion("2.21.0"); const features = createFeatures([Feature.DiffInformedQueries]); @@ -313,7 +313,7 @@ function runGetDiffRanges(changes: number, patch: string[] | undefined): any { changes, patch: patch?.join("\n"), }, - getRunnerLogger(true), + new RecordingLogger(), ); } diff --git a/src/feature-flags/properties.test.ts b/src/feature-flags/properties.test.ts index d3094a8d1c..6544d15d35 100644 --- a/src/feature-flags/properties.test.ts +++ b/src/feature-flags/properties.test.ts @@ -2,7 +2,6 @@ import test from "ava"; import * as sinon from "sinon"; import * as api from "../api-client"; -import { getRunnerLogger } from "../logging"; import { parseRepositoryNwo } from "../repository"; import { RecordingLogger, setupTests } from "../testing-utils"; @@ -19,7 +18,7 @@ test.serial( url: "", data: {}, }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); await t.throwsAsync( properties.loadPropertiesFromApi(logger, mockRepositoryNwo), @@ -39,7 +38,7 @@ test.serial( url: "", data: [{}], }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); await t.throwsAsync( properties.loadPropertiesFromApi(logger, mockRepositoryNwo), @@ -63,7 +62,7 @@ test.serial( { property_name: "also-not-used-by-us", value: ["A", "B", "C"] }, ], }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); await t.notThrowsAsync( properties.loadPropertiesFromApi(logger, mockRepositoryNwo), @@ -86,7 +85,7 @@ test.serial("loadPropertiesFromApi loads known properties", async (t) => { { property_name: "unknown-property", value: "something" }, ] satisfies properties.GitHubPropertiesResponse, }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); const response = await properties.loadPropertiesFromApi( logger, @@ -113,7 +112,7 @@ test.serial("loadPropertiesFromApi parses true boolean property", async (t) => { { property_name: "github-codeql-extra-queries", value: "+queries" }, ] satisfies properties.GitHubPropertiesResponse, }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const warningSpy = sinon.spy(logger, "warning"); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); const response = await properties.loadPropertiesFromApi( @@ -141,7 +140,7 @@ test.serial( }, ] satisfies properties.GitHubPropertiesResponse, }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const warningSpy = sinon.spy(logger, "warning"); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); const response = await properties.loadPropertiesFromApi( @@ -164,7 +163,7 @@ test.serial( url: "", data: [{ property_name: "github-codeql-extra-queries", value: 123 }], }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); await t.throwsAsync( properties.loadPropertiesFromApi(logger, mockRepositoryNwo), @@ -190,7 +189,7 @@ test.serial( }, ] satisfies properties.GitHubPropertiesResponse, }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const warningSpy = sinon.spy(logger, "warning"); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); const response = await properties.loadPropertiesFromApi( diff --git a/src/feature-flags/testing-util.ts b/src/feature-flags/testing-util.ts index 202f2c97b1..46795bdf09 100644 --- a/src/feature-flags/testing-util.ts +++ b/src/feature-flags/testing-util.ts @@ -8,11 +8,12 @@ import { FeatureWithoutCLI, initFeatures, } from "../feature-flags"; -import { getRunnerLogger } from "../logging"; +import type { Logger } from "../logging"; import { parseRepositoryNwo } from "../repository"; import { LoggedMessage, mockCodeQLVersion, + RecordingLogger, setupActionsVars, } from "../testing-utils"; import { ToolsFeature } from "../tools-features"; @@ -51,7 +52,7 @@ export function assertAllFeaturesUndefinedInApi( export function setUpFeatureFlagTests( tmpDir: string, - logger = getRunnerLogger(true), + logger: Logger = new RecordingLogger(), gitHubVersion = { type: GitHubVariant.DOTCOM } as util.GitHubVersion, ): FeatureEnablement { setupActionsVars(tmpDir, tmpDir); diff --git a/src/fingerprints.test.ts b/src/fingerprints.test.ts index 6cb9b68617..6b480a777f 100644 --- a/src/fingerprints.test.ts +++ b/src/fingerprints.test.ts @@ -5,9 +5,8 @@ import * as ava from "ava"; import test from "ava"; import * as fingerprints from "./fingerprints"; -import { getRunnerLogger } from "./logging"; import * as sarif from "./sarif"; -import { setupTests } from "./testing-utils"; +import { RecordingLogger, setupTests } from "./testing-utils"; import * as util from "./util"; setupTests(test); @@ -131,7 +130,7 @@ function testResolveUriToFile(uri: any, index: any, artifactsURIs: any[]) { location, artifacts, process.cwd(), - getRunnerLogger(true), + new RecordingLogger(), ); } @@ -218,7 +217,7 @@ test("addFingerprints", async (t) => { await fingerprints.addFingerprints( input, sourceRoot, - getRunnerLogger(true), + new RecordingLogger(), ), expected, ); @@ -246,7 +245,7 @@ test("missingRegions", async (t) => { await fingerprints.addFingerprints( input, sourceRoot, - getRunnerLogger(true), + new RecordingLogger(), ), expected, ); diff --git a/src/init-action-post-helper.test.ts b/src/init-action-post-helper.test.ts index 26b6ff4aba..5fa691787c 100644 --- a/src/init-action-post-helper.test.ts +++ b/src/init-action-post-helper.test.ts @@ -11,7 +11,6 @@ import * as debugArtifacts from "./debug-artifacts"; import { EnvVar } from "./environment"; import { Feature } from "./feature-flags"; import * as initActionPostHelper from "./init-action-post-helper"; -import { getRunnerLogger } from "./logging"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import * as overlayStatus from "./overlay/status"; import { parseRepositoryNwo } from "./repository"; @@ -63,7 +62,7 @@ test.serial("init-post action with debug mode off", async (t) => { createFeatures([]), "success", getTestEnv(), - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(uploadAllAvailableDebugArtifactsSpy.notCalled); @@ -87,7 +86,7 @@ test.serial("init-post action with debug mode on", async (t) => { createFeatures([]), "success", getTestEnv(), - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(uploadAllAvailableDebugArtifactsSpy.called); @@ -384,7 +383,7 @@ test.serial( createFeatures([Feature.OverlayAnalysisStatusSave]), "success", getTestEnv(), - getRunnerLogger(true), + new RecordingLogger(), ); t.true( @@ -454,7 +453,7 @@ test.serial( createFeatures([]), "success", getTestEnv(), - getRunnerLogger(true), + new RecordingLogger(), ); t.true( @@ -498,7 +497,7 @@ test.serial("does not save overlay status when build successful", async (t) => { createFeatures([Feature.OverlayAnalysisStatusSave]), "success", env, - getRunnerLogger(true), + new RecordingLogger(), ); t.true( @@ -537,7 +536,7 @@ test.serial( createFeatures([]), "success", getTestEnv(), - getRunnerLogger(true), + new RecordingLogger(), ); t.true( @@ -590,7 +589,7 @@ async function runOverlayPostStep({ createFeatures([Feature.OverlayAnalysisStatusSave]), jobStatus, env, - getRunnerLogger(true), + new RecordingLogger(), ); return { saveOverlayStatusStub }; @@ -765,7 +764,7 @@ async function testFailedSarifUpload( config, parseRepositoryNwo("github/codeql-action"), createFeatures(features), - getRunnerLogger(true), + new RecordingLogger(), ); if (expectUpload) { t.deepEqual(result, { diff --git a/src/logging.ts b/src/logging.ts index 177aca6c7b..ffe4e6ccee 100644 --- a/src/logging.ts +++ b/src/logging.ts @@ -51,22 +51,6 @@ export function getActionsLogger(): Logger { }; } -export function getRunnerLogger(debugMode: boolean): Logger { - return { - // eslint-disable-next-line no-console - debug: debugMode ? console.debug : () => undefined, - // eslint-disable-next-line no-console - info: console.info, - // eslint-disable-next-line no-console - warning: console.warn, - // eslint-disable-next-line no-console - error: console.error, - isDebug: () => debugMode, - startGroup: () => undefined, - endGroup: () => undefined, - }; -} - export function withGroup(groupName: string, f: () => T): T { core.startGroup(groupName); try { diff --git a/src/overlay/caching.test.ts b/src/overlay/caching.test.ts index 364eeff9c4..e965b06a7f 100644 --- a/src/overlay/caching.test.ts +++ b/src/overlay/caching.test.ts @@ -11,11 +11,11 @@ import type { ResolveDatabaseOutput } from "../codeql"; import * as environment from "../environment"; import * as gitUtils from "../git-utils"; import { BuiltInLanguage } from "../languages"; -import { getRunnerLogger } from "../logging"; import { createTestConfig, makeMacro, mockCodeQLVersion, + RecordingLogger, setupTests, } from "../testing-utils"; import * as utils from "../util"; @@ -63,7 +63,7 @@ const testDownloadOverlayBaseDatabaseFromCache = makeMacro({ const dbLocation = path.join(tmpDir, "db"); await fs.promises.mkdir(dbLocation, { recursive: true }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const testCase = { ...defaultDownloadTestCase, ...partialTestCase }; const config = createTestConfig({ dbLocation, @@ -214,7 +214,7 @@ testDownloadOverlayBaseDatabaseFromCache.serial( ); test.serial("overlay-base database cache keys remain stable", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const config = createTestConfig({ languages: ["python", "javascript"] }); const codeQlVersion = "2.23.0"; const commitOid = "abc123def456"; @@ -261,7 +261,7 @@ test.serial("overlay-base database cache keys remain stable", async (t) => { test.serial( "getCodeQlVersionsForOverlayBaseDatabases returns unique versions sorted latest first", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); sinon.stub(apiClient, "listActionsCaches").resolves([ @@ -287,7 +287,7 @@ test.serial( test.serial( "getCodeQlVersionsForOverlayBaseDatabases returns empty list when no caches exist", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); sinon.stub(apiClient, "listActionsCaches").resolves([]); @@ -303,7 +303,7 @@ test.serial( test.serial( "getCodeQlVersionsForOverlayBaseDatabases returns empty list when cache keys are unparseable", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); sinon.stub(apiClient, "listActionsCaches").resolves([ @@ -324,7 +324,7 @@ test.serial( test.serial( "getCodeQlVersionsForOverlayBaseDatabases returns the single version when only one cache exists", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); sinon.stub(apiClient, "listActionsCaches").resolves([ @@ -344,7 +344,7 @@ test.serial( test.serial( "getCodeQlVersionsForOverlayBaseDatabases resolves language aliases", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); // The alias `c++` should be resolved to "cpp" and match cache entries keyed with "cpp" sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); @@ -365,7 +365,7 @@ test.serial( test.serial( "getCodeQlVersionsForOverlayBaseDatabases de-duplicates resolved language aliases", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); const listActionsCachesStub = sinon @@ -391,7 +391,7 @@ test.serial( test.serial( "getCodeQlVersionsForOverlayBaseDatabases ignores nightly versions with build metadata", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); sinon.stub(apiClient, "listActionsCaches").resolves([ diff --git a/src/overlay/index.test.ts b/src/overlay/index.test.ts index 967ccf3a7d..4534006f80 100644 --- a/src/overlay/index.test.ts +++ b/src/overlay/index.test.ts @@ -6,8 +6,11 @@ import * as sinon from "sinon"; import * as actionsUtil from "../actions-util"; import * as gitUtils from "../git-utils"; -import { getRunnerLogger } from "../logging"; -import { createTestConfig, setupTests } from "../testing-utils"; +import { + createTestConfig, + RecordingLogger, + setupTests, +} from "../testing-utils"; import { withTmpDir } from "../util"; import { writeBaseDatabaseOidsFile, writeOverlayChangesFile } from "."; @@ -27,7 +30,7 @@ test.serial( ), ); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const config = createTestConfig({ dbLocation }); // Mock the getFileOidsUnderPath function to return base OIDs @@ -91,7 +94,7 @@ test.serial( ), ); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const config = createTestConfig({ dbLocation }); // Mock the getFileOidsUnderPath function to return base OIDs @@ -169,7 +172,7 @@ test.serial( ), ); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const config = createTestConfig({ dbLocation }); // Mock the getFileOidsUnderPath function to return base OIDs @@ -232,7 +235,7 @@ test.serial( ), ); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const config = createTestConfig({ dbLocation }); // Base OIDs (sourceRoot-relative paths) diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 3fef11e63e..90c3c33098 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -14,7 +14,6 @@ import * as diagnostics from "./diagnostics"; import { ActionsEnvVars, Env, EnvVar, ReadOnlyEnv } from "./environment"; import { Feature } from "./feature-flags"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger } from "./logging"; import { getCacheRestoreKeyPrefix } from "./overlay/caching"; import { MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION } from "./per-language-bundles"; import * as setupCodeql from "./setup-codeql"; @@ -22,6 +21,7 @@ import * as tar from "./tar"; import { LINKED_CLI_VERSION, LoggedMessage, + RecordingLogger, SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DOTCOM_API_DETAILS, checkExpectedLogMessages, @@ -117,7 +117,7 @@ test.serial("convert to semver", (t) => { try { const parsedVersion = setupCodeql.convertToSemVer( version, - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(parsedVersion, expectedVersion); } catch (e) { @@ -127,7 +127,7 @@ test.serial("convert to semver", (t) => { }); test.serial("getCodeQLActionRepository", (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); initializeEnvironment("1.2.3"); @@ -163,7 +163,7 @@ test.serial( GitHubVariant.DOTCOM, false, features, - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(source, { @@ -249,7 +249,7 @@ for (const { GitHubVariant.DOTCOM, tarSupportsZstd, features, - getRunnerLogger(true), + new RecordingLogger(), ); t.is(source.toolsVersion, LINKED_CLI_VERSION.cliVersion); @@ -615,7 +615,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([Feature.CleanupToolcacheBundles]), - getRunnerLogger(true), + new RecordingLogger(), ); t.is(result.toolsVersion, "local"); @@ -652,7 +652,7 @@ for (const toolsInput of ["nightly", "nightly-latest"]) { GitHubVariant.DOTCOM, true, // tarSupportsZstd createFeatures([Feature.PerLanguageBundles]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(source, { @@ -712,7 +712,7 @@ test.serial( GitHubVariant.DOTCOM, true, // tarSupportsZstd features, - getRunnerLogger(true), + new RecordingLogger(), ); t.is(source.sourceType, "download"); @@ -751,7 +751,7 @@ for (const perLanguageBundles of [false, true]) { ? [Feature.ForceNightly, Feature.PerLanguageBundles] : [Feature.ForceNightly], ), - getRunnerLogger(true), + new RecordingLogger(), ); t.is(source.sourceType, "download"); @@ -866,7 +866,7 @@ test.serial( GitHubVariant.DOTCOM, true, createFeatures([]), - getRunnerLogger(true), + new RecordingLogger(), ), { message: @@ -1038,7 +1038,7 @@ test.serial( t.is( setupCodeql.tryGetTagNameFromUrl( "https://github.com/org/codeql-bundle-testing/releases/download/codeql-bundle-v2.19.0/codeql-bundle-linux64.tar.zst", - getRunnerLogger(true), + new RecordingLogger(), ), "codeql-bundle-v2.19.0", ); @@ -1050,7 +1050,7 @@ test.serial( (t) => { sinon.stub(toolcache, "findAllVersions").returns([]); t.is( - setupCodeql.getLatestToolcacheVersion(getRunnerLogger(true)), + setupCodeql.getLatestToolcacheVersion(new RecordingLogger()), undefined, ); }, @@ -1062,7 +1062,7 @@ test.serial( const testVersions = ["2.3.1", "3.2.1", "1.2.3"]; sinon.stub(toolcache, "findAllVersions").returns(testVersions); - t.is(setupCodeql.getLatestToolcacheVersion(getRunnerLogger(true)), "3.2.1"); + t.is(setupCodeql.getLatestToolcacheVersion(new RecordingLogger()), "3.2.1"); }, ); @@ -1116,7 +1116,7 @@ test.serial( GitHubVariant.DOTCOM, false, createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(listStub.calledOnce); @@ -1155,7 +1155,7 @@ test.serial( GitHubVariant.DOTCOM, false, createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(listStub.notCalled); @@ -1193,7 +1193,7 @@ test.serial( GitHubVariant.DOTCOM, true, // tarSupportsZstd createFeatures([Feature.PerLanguageBundles]), - getRunnerLogger(true), + new RecordingLogger(), ); t.is(source.sourceType, "download"); @@ -1244,7 +1244,7 @@ test.serial( GitHubVariant.DOTCOM, true, // tarSupportsZstd features, - getRunnerLogger(true), + new RecordingLogger(), ); t.is(source.sourceType, "download"); @@ -1314,7 +1314,7 @@ for (const fallback of [false, true]) { undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([Feature.PerLanguageBundles]), - getRunnerLogger(true), + new RecordingLogger(), ); t.true(fetchRelease.calledTwice); @@ -1582,7 +1582,7 @@ for (const error of [ undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([Feature.PerLanguageBundles]), - getRunnerLogger(true), + new RecordingLogger(), ), { is: error }, ); @@ -1618,7 +1618,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([]), - getRunnerLogger(true), + new RecordingLogger(), ), { is: error }, ); @@ -1651,7 +1651,7 @@ test.serial( overlayMatchEnabledVersions, ["javascript"], createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, [ { cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" }, @@ -1674,7 +1674,7 @@ test.serial( overlayMatchEnabledVersions, ["javascript"], createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, []); }, @@ -1691,7 +1691,7 @@ const noLanguagesMacro = makeMacro({ overlayMatchEnabledVersions, rawLanguages, createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, []); t.assert( @@ -1716,7 +1716,7 @@ test.serial( overlayMatchEnabledVersions, ["javascript"], createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, []); }, @@ -1736,7 +1736,7 @@ test.serial( overlayMatchEnabledVersions, ["javascript"], createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, [ { cliVersion: "2.20.2", tagName: "codeql-bundle-v2.20.2" }, @@ -1753,7 +1753,7 @@ test.serial( overlayMatchEnabledVersions, ["javascript"], createFeatures([]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, []); t.assert( @@ -1777,7 +1777,7 @@ test.serial( overlayMatchEnabledVersions, ["javascript"], createFeatures([Feature.OverlayAnalysisMatchCodeqlVersionDryRun]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual( result, @@ -1808,7 +1808,7 @@ test.serial( Feature.OverlayAnalysisMatchCodeqlVersion, Feature.OverlayAnalysisMatchCodeqlVersionDryRun, ]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, [ { cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" }, @@ -2138,7 +2138,7 @@ test.serial( env: new ReadOnlyEnv({ [ActionsEnvVars.RUNNER_TOOL_CACHE]: injectedRoot, }), - logger: getRunnerLogger(true), + logger: new RecordingLogger(), }); t.deepEqual(result, { @@ -2291,7 +2291,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([]), - getRunnerLogger(true), + new RecordingLogger(), ); t.is( @@ -2331,7 +2331,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([Feature.CleanupToolcacheBundles]), - getRunnerLogger(true), + new RecordingLogger(), ), { is: error }, ); @@ -2449,7 +2449,7 @@ test.serial( "isToolcacheOnWorkspaceFilesystem assumes a different filesystem when it cannot tell", async (t) => { await withTmpDir(async (tmpDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); setupActionsVars(tmpDir, tmpDir); t.true(toolsDownload.isToolcacheOnWorkspaceFilesystem(logger)); diff --git a/src/start-proxy.test.ts b/src/start-proxy.test.ts index bd24897136..692524e811 100644 --- a/src/start-proxy.test.ts +++ b/src/start-proxy.test.ts @@ -12,7 +12,7 @@ import { setUpFeatureFlagTests } from "./feature-flags/testing-util"; import { UnvalidatedObject, validateSchema } from "./json"; import { makeFromSchema } from "./json/testing-util"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger, Logger } from "./logging"; +import { Logger } from "./logging"; import { BundlePlatform, getBundlePlatform } from "./platform"; import * as startProxyExports from "./start-proxy"; import * as statusReport from "./status-report"; @@ -148,7 +148,7 @@ test("getCredentials prefers registriesCredentials over registrySecrets", async ]); const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), registrySecrets, registryCredentials, undefined, @@ -165,7 +165,7 @@ test("getCredentials throws an error when configurations are not an array", asyn t.throws( () => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, registryCredentials, undefined, @@ -184,7 +184,7 @@ test("getCredentials throws error when credential is not an object", async (t) = t.throws( () => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, testCredential, undefined, @@ -205,7 +205,7 @@ test("getCredentials throws error when credential is missing type", async (t) => t.throws( () => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, testCredential, undefined, @@ -228,7 +228,7 @@ test("getCredentials throws error when credential missing host and url", async ( t.throws( () => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, testCredential, undefined, @@ -242,7 +242,7 @@ test("getCredentials throws error when credential missing host and url", async ( test("getCredentials filters by language when specified", async (t) => { const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON(mixedCredentials), BuiltInLanguage.java, @@ -253,7 +253,7 @@ test("getCredentials filters by language when specified", async (t) => { test("getCredentials returns all for a language when specified", async (t) => { const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON([...mixedCredentials, gitSourceCredential]), BuiltInLanguage.go, @@ -273,7 +273,7 @@ test("getCredentials returns all goproxy_servers for Go when specified", async ( ]; const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON(multipleGoproxyServers), BuiltInLanguage.go, @@ -302,7 +302,7 @@ test("getCredentials returns all maven_repositories for Java when specified", as ]; const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON(multipleMavenRepositories), BuiltInLanguage.java, @@ -320,7 +320,7 @@ test("getCredentials returns all credentials when no language specified", async const credentialsInput = toEncodedJSON(mixedCredentials); const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, credentialsInput, undefined, @@ -350,7 +350,7 @@ test("getCredentials throws an error when non-printable characters are used", as t.throws( () => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, credentialsInput, undefined, @@ -381,7 +381,7 @@ for (const oidcSchemaInfo of startProxyExports.oidcSchemas) { t.throws( () => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, credentialsInput, undefined, @@ -405,7 +405,7 @@ test("getCredentials accepts OIDC configurations", (t) => { ); const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON(oidcConfigurations), BuiltInLanguage.csharp, @@ -595,7 +595,7 @@ test("getCredentials validates 'replaces-base' correctly", async (t) => { ]); const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, credentialsInput, BuiltInLanguage.java, @@ -614,7 +614,7 @@ test("getCredentials validates 'replaces-base' correctly", async (t) => { }; t.throws(() => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON([{ ...baseInvalid, "replaces-base": null }]), BuiltInLanguage.java, @@ -622,7 +622,7 @@ test("getCredentials validates 'replaces-base' correctly", async (t) => { ); t.throws(() => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON([{ ...baseInvalid, "replaces-base": 123 }]), BuiltInLanguage.java, @@ -630,7 +630,7 @@ test("getCredentials validates 'replaces-base' correctly", async (t) => { ); t.throws(() => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON([{ ...baseInvalid, "replaces-base": "true" }]), BuiltInLanguage.java, @@ -646,7 +646,7 @@ test("getCredentials returns only ALWAYS_ENABLED_REGISTRY_TYPE credentials for A ]); const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, credentialsInput, BuiltInLanguage.actions, @@ -678,7 +678,7 @@ test("getCredentials always returns ALWAYS_ENABLED_REGISTRY_TYPE credentials for // Test all languages. for (const language of Object.values(BuiltInLanguage)) { const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, credentialsInput, language, diff --git a/src/status-report.test.ts b/src/status-report.test.ts index 2b763da700..004161efac 100644 --- a/src/status-report.test.ts +++ b/src/status-report.test.ts @@ -6,7 +6,6 @@ import * as actionsUtil from "./actions-util"; import { Config } from "./config-utils"; import { EnvVar, RegistryProxyVars } from "./environment"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger } from "./logging"; import { ToolsSource } from "./setup-codeql"; import type { Registry } from "./start-proxy"; import { @@ -154,7 +153,7 @@ test.serial("createStatusReportBase", async (t) => { languages: [BuiltInLanguage.java, BuiltInLanguage.swift], }), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ); @@ -203,7 +202,7 @@ test.serial("createStatusReportBase - empty configuration", async (t) => { new Date("May 19, 2023 05:19:00"), {}, { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), ); if (t.truthy(statusReport)) { @@ -225,7 +224,7 @@ test.serial("createStatusReportBase - partial configuration", async (t) => { languages: ["go"], }, { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), ); if (t.truthy(statusReport)) { @@ -248,7 +247,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => { new Date("May 19, 2023 05:19:00"), createTestConfig({}), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ) @@ -264,7 +263,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => { new Date("May 19, 2023 05:19:00"), createTestConfig({}), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ) @@ -281,7 +280,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => { new Date("May 19, 2023 05:19:00"), createTestConfig({}), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ) @@ -297,7 +296,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => { new Date("May 19, 2023 05:19:00"), createTestConfig({}), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ) @@ -314,7 +313,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => { new Date("May 19, 2023 05:19:00"), createTestConfig({}), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ) @@ -330,7 +329,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => { new Date("May 19, 2023 05:19:00"), createTestConfig({}), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ) @@ -411,7 +410,7 @@ const testCreateInitWithConfigStatusReport = makeMacro({ new Date("May 19, 2023 05:19:00"), config, { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ); diff --git a/src/tar.test.ts b/src/tar.test.ts index 48f4e866d3..99d68b5317 100644 --- a/src/tar.test.ts +++ b/src/tar.test.ts @@ -3,9 +3,8 @@ import * as stream from "stream"; import test from "ava"; -import { getRunnerLogger } from "./logging"; import { extractTarZst } from "./tar"; -import { setupTests } from "./testing-utils"; +import { RecordingLogger, setupTests } from "./testing-utils"; import { withTmpDir } from "./util"; setupTests(test); @@ -17,7 +16,7 @@ test("extractTarZst rejects if the input stream errors", async (t) => { archive, path.join(tmpDir, "dest"), { type: "gnu", version: "1.34" }, - getRunnerLogger(true), + new RecordingLogger(), ); archive.destroy( diff --git a/src/testing-utils.ts b/src/testing-utils.ts index dfb08d9972..63f9533d29 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -30,13 +30,7 @@ import { featureConfig, FeatureEnablement, } from "./feature-flags"; -import { - getRunnerLogger, - joinMessageStrings, - Loggable, - LoggableError, - Logger, -} from "./logging"; +import { joinMessageStrings, Loggable, LoggableError, Logger } from "./logging"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import { getBundlePlatform } from "./platform"; import { ActionName } from "./status-report"; @@ -1014,7 +1008,7 @@ export function makeTestToken(length: number = 36) { */ export async function getCodeQLForTesting( cmd = "codeql-for-testing", - logger: Logger = getRunnerLogger(true), + logger: Logger = new RecordingLogger(), ): Promise { return codeql.getCodeQLForCmd(logger, cmd, false); } diff --git a/src/tools-download.test.ts b/src/tools-download.test.ts index 407e2ea489..1ba980bbe3 100644 --- a/src/tools-download.test.ts +++ b/src/tools-download.test.ts @@ -10,9 +10,8 @@ import { https } from "follow-redirects"; import nock from "nock"; import * as sinon from "sinon"; -import { getRunnerLogger } from "./logging"; import * as tar from "./tar"; -import { setupTests } from "./testing-utils"; +import { RecordingLogger, setupTests } from "./testing-utils"; import { downloadAndExtract } from "./tools-download"; import * as util from "./util"; @@ -34,7 +33,7 @@ test.serial( undefined, {}, undefined, - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(Number.isInteger(statusReport.downloadDurationMs)); @@ -72,7 +71,7 @@ test.serial( undefined, {}, { type: "gnu", version: "1.34" }, - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(Number.isInteger(statusReport.downloadDurationMs)); @@ -105,7 +104,7 @@ test.serial( undefined, {}, { type: "gnu", version: "1.34" }, - getRunnerLogger(true), + new RecordingLogger(), ), { instanceOf: util.HTTPError, @@ -149,7 +148,7 @@ test.serial( undefined, {}, { type: "gnu", version: "1.34" }, - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(Number.isInteger(statusReport.downloadDurationMs)); @@ -189,7 +188,7 @@ test.serial( undefined, {}, { type: "gnu", version: "1.34" }, - getRunnerLogger(true), + new RecordingLogger(), ); t.is( @@ -237,7 +236,7 @@ test.serial( undefined, {}, { type: "gnu", version: "1.34" }, - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(Number.isInteger(statusReport.totalDurationMs)); diff --git a/src/trap-caching.test.ts b/src/trap-caching.test.ts index 478305e577..efe93a13fd 100644 --- a/src/trap-caching.test.ts +++ b/src/trap-caching.test.ts @@ -16,12 +16,12 @@ import * as configUtils from "./config-utils"; import { Feature } from "./feature-flags"; import * as gitUtils from "./git-utils"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger } from "./logging"; import { createFeatures, createTestConfig, getRecordingLogger, makeVersionInfo, + RecordingLogger, setupTests, } from "./testing-utils"; import { @@ -264,7 +264,7 @@ test.serial("cleanup removes only old CodeQL TRAP caches", async (t) => { const statusReport = await cleanupTrapCaches( config, createFeatures([Feature.CleanupTrapCaches]), - getRunnerLogger(true), + new RecordingLogger(), ); t.is(listStub.callCount, 1); diff --git a/src/upload-lib.test.ts b/src/upload-lib.test.ts index 2c27d56c1c..ebfc5cd404 100644 --- a/src/upload-lib.test.ts +++ b/src/upload-lib.test.ts @@ -10,9 +10,9 @@ import * as analyses from "./analyses"; import { AnalysisKind, CodeQuality, CodeScanning } from "./analyses"; import * as api from "./api-client"; import * as diffUtils from "./diff-informed-analysis-utils"; -import { getRunnerLogger, Logger } from "./logging"; +import { Logger } from "./logging"; import * as sarif from "./sarif"; -import { setupTests } from "./testing-utils"; +import { RecordingLogger, setupTests } from "./testing-utils"; import * as uploadLib from "./upload-lib"; import { UploadPayload } from "./upload-lib/types"; import { GitHubVariant, initializeEnvironment, withTmpDir } from "./util"; @@ -29,7 +29,7 @@ test.serial("validateSarifFileSchema - valid", (t) => { uploadLib.validateSarifFileSchema( uploadLib.readSarifFileOrThrow(inputFile), inputFile, - getRunnerLogger(true), + new RecordingLogger(), ), ); }); @@ -40,7 +40,7 @@ test.serial("validateSarifFileSchema - invalid", (t) => { uploadLib.validateSarifFileSchema( uploadLib.readSarifFileOrThrow(inputFile), inputFile, - getRunnerLogger(true), + new RecordingLogger(), ), ); }); @@ -179,7 +179,7 @@ test.serial("finding SARIF files", async (t) => { } const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths( - getRunnerLogger(true), + new RecordingLogger(), tmpDir, ); @@ -200,7 +200,7 @@ test.serial("getGroupedSarifFilePaths - Risk Assessment files", async (t) => { fs.writeFileSync(sarifPath, ""); const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths( - getRunnerLogger(true), + new RecordingLogger(), sarifPath, ); @@ -218,7 +218,7 @@ test.serial("getGroupedSarifFilePaths - Code Quality file", async (t) => { fs.writeFileSync(sarifPath, ""); const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths( - getRunnerLogger(true), + new RecordingLogger(), sarifPath, ); @@ -236,7 +236,7 @@ test.serial("getGroupedSarifFilePaths - Code Scanning file", async (t) => { fs.writeFileSync(sarifPath, ""); const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths( - getRunnerLogger(true), + new RecordingLogger(), sarifPath, ); @@ -254,7 +254,7 @@ test.serial("getGroupedSarifFilePaths - Other file", async (t) => { fs.writeFileSync(sarifPath, ""); const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths( - getRunnerLogger(true), + new RecordingLogger(), sarifPath, ); @@ -932,7 +932,7 @@ function uploadPayloadFixtures(analysis: analyses.AnalysisConfig) { owner: mockData.owner, repo: mockData.repo, }, - getRunnerLogger(true), + new RecordingLogger(), analysis, ); @@ -1019,7 +1019,7 @@ function runFilterAlertsByDiffRange( diffRanges: diffUtils.DiffThunkRange[], ): Partial { sinon.stub(diffUtils, "readDiffRangesJsonFile").returns(diffRanges); - return uploadLib.filterAlertsByDiffRange(getRunnerLogger(true), input); + return uploadLib.filterAlertsByDiffRange(new RecordingLogger(), input); } test.serial( diff --git a/src/upload-sarif.test.ts b/src/upload-sarif.test.ts index d310bce92a..f9318b1966 100644 --- a/src/upload-sarif.test.ts +++ b/src/upload-sarif.test.ts @@ -5,8 +5,12 @@ import test, { ExecutionContext } from "ava"; import * as sinon from "sinon"; import { AnalysisKind, getAnalysisConfig } from "./analyses"; -import { getRunnerLogger } from "./logging"; -import { createFeatures, makeMacro, setupTests } from "./testing-utils"; +import { + createFeatures, + makeMacro, + RecordingLogger, + setupTests, +} from "./testing-utils"; import { UploadResult } from "./upload-lib"; import * as uploadLib from "./upload-lib"; import { postProcessAndUploadSarif } from "./upload-sarif"; @@ -51,7 +55,7 @@ const postProcessAndUploadSarifMacro = makeMacro({ expectedResult: Partial>, ) => { await util.withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const testPath = sarifPath(tempDir); const features = createFeatures([]); @@ -206,7 +210,7 @@ test.serial( "postProcessAndUploadSarif doesn't upload if upload is disabled", async (t) => { await util.withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const features = createFeatures([]); const toFullPath = (filename: string) => path.join(tempDir, filename); @@ -239,7 +243,7 @@ test.serial( "postProcessAndUploadSarif writes post-processed SARIF files if output directory is provided", async (t) => { await util.withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const features = createFeatures([]); const toFullPath = (filename: string) => path.join(tempDir, filename); diff --git a/src/util.test.ts b/src/util.test.ts index 074310279f..a4b7576b81 100644 --- a/src/util.test.ts +++ b/src/util.test.ts @@ -10,8 +10,7 @@ import * as sinon from "sinon"; import * as api from "./api-client"; import { EnvVar } from "./environment"; -import { getRunnerLogger } from "./logging"; -import { setupTests } from "./testing-utils"; +import { RecordingLogger, setupTests } from "./testing-utils"; import * as util from "./util"; setupTests(test); @@ -92,7 +91,7 @@ for (const { test("getMemoryFlag() throws if the ram input is < 0 or NaN", async (t) => { for (const input of ["-1", "hello!"]) { - t.throws(() => util.getMemoryFlag(input, getRunnerLogger(true))); + t.throws(() => util.getMemoryFlag(input, new RecordingLogger())); } }); @@ -109,13 +108,13 @@ test("getThreadsFlag() should return the correct --threads flag", (t) => { ]; for (const [input, expectedFlag] of tests) { - const flag = util.getThreadsFlag(input, getRunnerLogger(true)); + const flag = util.getThreadsFlag(input, new RecordingLogger()); t.deepEqual(flag, expectedFlag); } }); test("getThreadsFlag() throws if the threads input is not an integer", (t) => { - t.throws(() => util.getThreadsFlag("hello!", getRunnerLogger(true))); + t.throws(() => util.getThreadsFlag("hello!", new RecordingLogger())); }); test.serial( @@ -445,7 +444,7 @@ test("getCgroupCpuCountFromCpus calculates the number of CPUs correctly", async const testCpuFile = `${tmpDir}/cpus-file`; fs.writeFileSync(testCpuFile, "1, 9-10\n", "utf-8"); t.deepEqual( - util.getCgroupCpuCountFromCpus(testCpuFile, getRunnerLogger(true)), + util.getCgroupCpuCountFromCpus(testCpuFile, new RecordingLogger()), 3, ); }); @@ -456,7 +455,7 @@ test("getCgroupCpuCountFromCpus returns undefined if the CPU file doesn't exist" const testCpuFile = `${tmpDir}/cpus-file`; t.false(fs.existsSync(testCpuFile)); t.deepEqual( - util.getCgroupCpuCountFromCpus(testCpuFile, getRunnerLogger(true)), + util.getCgroupCpuCountFromCpus(testCpuFile, new RecordingLogger()), undefined, ); }); @@ -467,7 +466,7 @@ test("getCgroupCpuCountFromCpus returns undefined if the CPU file exists but is const testCpuFile = `${tmpDir}/cpus-file`; fs.writeFileSync(testCpuFile, "\n", "utf-8"); t.deepEqual( - util.getCgroupCpuCountFromCpus(testCpuFile, getRunnerLogger(true)), + util.getCgroupCpuCountFromCpus(testCpuFile, new RecordingLogger()), undefined, ); }); @@ -477,7 +476,7 @@ test.serial( "checkDiskUsage succeeds and produces positive numbers", async (t) => { process.env["GITHUB_WORKSPACE"] = os.tmpdir(); - const diskUsage = await util.checkDiskUsage(getRunnerLogger(true)); + const diskUsage = await util.checkDiskUsage(new RecordingLogger()); if (t.truthy(diskUsage)) { t.true(diskUsage.numAvailableBytes > 0); t.true(diskUsage.numTotalBytes > 0); From 7d7a550898448d564d08fbc23acaabecc105a70f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 14 Oct 2026 15:11:32 +0100 Subject: [PATCH 004/174] Ensure consistent output formatting in `addMessage` --- src/testing-utils.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 63f9533d29..04f0d17013 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -619,11 +619,12 @@ export class RecordingLogger implements Logger { constructor(private readonly logToConsole: boolean = true) {} private addMessage(level: LogLevel, message: LoggableError): void { - this.messages.push({ type: level, message: joinMessageStrings(message) }); + const joinedMessage = joinMessageStrings(message); + this.messages.push({ type: level, message: joinedMessage }); if (this.logToConsole) { // eslint-disable-next-line no-console - console.debug(message); + console.debug(joinedMessage); } } From 64e5c6243a4e038d230343674392b1e7166be75f Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Fri, 16 Oct 2026 13:59:52 +0100 Subject: [PATCH 005/174] Prepare per-language bundle graduation checks Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9f196d4-6d15-44ca-bd01-cd022d57d2cc --- .../__export-file-baseline-information.yml | 7 +++- .../__per-language-bundle-validation.yml | 33 +++++++++++------- .../export-file-baseline-information.yml | 10 +++--- .../checks/per-language-bundle-validation.yml | 34 +++++++++++-------- 4 files changed, 52 insertions(+), 32 deletions(-) diff --git a/.github/workflows/__export-file-baseline-information.yml b/.github/workflows/__export-file-baseline-information.yml index 597c7ce9b6..7badf827f1 100644 --- a/.github/workflows/__export-file-baseline-information.yml +++ b/.github/workflows/__export-file-baseline-information.yml @@ -91,6 +91,11 @@ jobs: with: languages: javascript tools: ${{ steps.prepare-test.outputs.tools-url }} + # To balance speed and coverage, analyze only JavaScript but use the combined bundle so + # baseline information is reported for every language in the multi-language repository. A + # no-op custom configuration selects that conservative path for custom configurations. + config: | + paths-ignore: [] - name: Build code run: ./build.sh - uses: ./../action/analyze @@ -124,5 +129,5 @@ jobs: env: CODEQL_ACTION_SKIP_FILE_COVERAGE_ON_PRS: false CODEQL_ACTION_SUBLANGUAGE_FILE_COVERAGE: true - CODEQL_ACTION_PER_LANGUAGE_BUNDLES: false + CODEQL_ACTION_PER_LANGUAGE_BUNDLES: true CODEQL_ACTION_TEST_MODE: true diff --git a/.github/workflows/__per-language-bundle-validation.yml b/.github/workflows/__per-language-bundle-validation.yml index ea900a9e09..07930b35ab 100644 --- a/.github/workflows/__per-language-bundle-validation.yml +++ b/.github/workflows/__per-language-bundle-validation.yml @@ -36,40 +36,40 @@ jobs: include: - language: actions os: ubuntu-latest - version: nightly-latest + version: linked expected-extractors: actions javascript - language: cpp os: ubuntu-latest - version: nightly-latest + version: linked build-mode: manual build-command: gcc -o main main.c - language: csharp os: ubuntu-latest - version: nightly-latest + version: linked build-mode: none - language: go os: ubuntu-latest - version: nightly-latest + version: linked build-mode: autobuild - language: java os: ubuntu-latest - version: nightly-latest + version: linked build-mode: none - language: javascript os: ubuntu-latest - version: nightly-latest + version: linked - language: python os: ubuntu-latest - version: nightly-latest + version: linked - language: ruby os: ubuntu-latest - version: nightly-latest + version: linked - language: rust os: ubuntu-latest - version: nightly-latest + version: linked - language: swift os: macos-latest-xlarge - version: nightly-latest + version: linked build-mode: autobuild name: Per-language bundles if: github.triggering_actor != 'dependabot[bot]' @@ -88,6 +88,14 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Remove CodeQL from toolcache + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const fs = require('fs'); + const path = require('path'); + const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL'); + fs.rmdirSync(codeqlPath, { recursive: true }); - uses: ./../action/init id: init with: @@ -128,9 +136,8 @@ jobs: CODEQL_PATH: ${{ steps.init.outputs.codeql-path }} run: | # A bundle that is missing most of its extractors must never be left in the toolcache, - # where a later job analyzing a different language could pick it up. The runner image - # ships with its own CodeQL in the toolcache, so check where this bundle was extracted to - # rather than whether the toolcache contains CodeQL at all. + # where a later job analyzing a different language could pick it up. Per-language bundles + # must instead be extracted under the runner's temporary directory. echo "CodeQL is at $CODEQL_PATH" if [[ "$CODEQL_PATH" == "$RUNNER_TOOL_CACHE"/* ]]; then echo "::error::The per-language bundle was added to the toolcache at $CODEQL_PATH." diff --git a/pr-checks/checks/export-file-baseline-information.yml b/pr-checks/checks/export-file-baseline-information.yml index da32372383..87c4b7609b 100644 --- a/pr-checks/checks/export-file-baseline-information.yml +++ b/pr-checks/checks/export-file-baseline-information.yml @@ -11,16 +11,18 @@ installDotNet: true env: CODEQL_ACTION_SKIP_FILE_COVERAGE_ON_PRS: false CODEQL_ACTION_SUBLANGUAGE_FILE_COVERAGE: true - # To balance speed and coverage, we analyze only a single language (JavaScript), but use the - # combined bundle so we can test that baseline information is reported for each language in the - # multi-language source directory. - CODEQL_ACTION_PER_LANGUAGE_BUNDLES: false + CODEQL_ACTION_PER_LANGUAGE_BUNDLES: true steps: - uses: ./../action/init id: init with: languages: javascript tools: ${{ steps.prepare-test.outputs.tools-url }} + # To balance speed and coverage, analyze only JavaScript but use the combined bundle so + # baseline information is reported for every language in the multi-language repository. A + # no-op custom configuration selects that conservative path for custom configurations. + config: | + paths-ignore: [] - name: Build code run: ./build.sh - uses: ./../action/analyze diff --git a/pr-checks/checks/per-language-bundle-validation.yml b/pr-checks/checks/per-language-bundle-validation.yml index 21fe33e757..ac22f67f50 100644 --- a/pr-checks/checks/per-language-bundle-validation.yml +++ b/pr-checks/checks/per-language-bundle-validation.yml @@ -1,49 +1,56 @@ name: Per-language bundles description: Validates extraction and analysis using each per-language CodeQL bundle. -# TODO: Use a released bundle once releases include per-language bundles. matrix: include: - language: actions os: ubuntu-latest - version: nightly-latest + version: linked # Actions also needs the JavaScript extractor. expected-extractors: actions javascript - language: cpp os: ubuntu-latest - version: nightly-latest + version: linked build-mode: manual build-command: gcc -o main main.c - language: csharp os: ubuntu-latest - version: nightly-latest + version: linked build-mode: none - language: go os: ubuntu-latest - version: nightly-latest + version: linked build-mode: autobuild - language: java os: ubuntu-latest - version: nightly-latest + version: linked build-mode: none - language: javascript os: ubuntu-latest - version: nightly-latest + version: linked - language: python os: ubuntu-latest - version: nightly-latest + version: linked - language: ruby os: ubuntu-latest - version: nightly-latest + version: linked - language: rust os: ubuntu-latest - version: nightly-latest + version: linked - language: swift os: macos-latest-xlarge - version: nightly-latest + version: linked build-mode: autobuild env: CODEQL_ACTION_PER_LANGUAGE_BUNDLES: true steps: + - name: Remove CodeQL from toolcache + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const fs = require('fs'); + const path = require('path'); + const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL'); + fs.rmdirSync(codeqlPath, { recursive: true }); - uses: ./../action/init id: init with: @@ -84,9 +91,8 @@ steps: CODEQL_PATH: ${{ steps.init.outputs.codeql-path }} run: | # A bundle that is missing most of its extractors must never be left in the toolcache, - # where a later job analyzing a different language could pick it up. The runner image - # ships with its own CodeQL in the toolcache, so check where this bundle was extracted to - # rather than whether the toolcache contains CodeQL at all. + # where a later job analyzing a different language could pick it up. Per-language bundles + # must instead be extracted under the runner's temporary directory. echo "CodeQL is at $CODEQL_PATH" if [[ "$CODEQL_PATH" == "$RUNNER_TOOL_CACHE"/* ]]; then echo "::error::The per-language bundle was added to the toolcache at $CODEQL_PATH." From 9bf78d13c9b17244340569e11ccfa22460cb1ca7 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Fri, 16 Oct 2026 14:00:12 +0100 Subject: [PATCH 006/174] Use per-language bundles by default Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9f196d4-6d15-44ca-bd01-cd022d57d2cc --- lib/entry-points.js | 32 +++----- src/per-language-bundles.test.ts | 28 ------- src/per-language-bundles.ts | 15 +--- src/setup-codeql.test.ts | 129 ++++++++++++++----------------- src/setup-codeql.ts | 25 +++--- 5 files changed, 83 insertions(+), 146 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 1a99a44427..dfa3adefcb 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -175692,11 +175692,7 @@ function getOtherLanguagePacksReason(inputs) { function findNonBuiltInQuery(queries) { return queries?.find((query) => !defaultSuites.has(query.uses))?.uses; } -async function getPerLanguageBundleLanguage({ - env, - features, - logger: logger2 -}, options) { +function getPerLanguageBundleLanguage({ env, logger: logger2 }, options) { const { rawLanguages, otherLanguagePacksReason, @@ -175710,9 +175706,6 @@ async function getPerLanguageBundleLanguage({ logger2.debug(`Not using a per-language CodeQL bundle since ${reason}.`); return void 0; }; - if (!await features.getValue("per_language_bundles_v2" /* PerLanguageBundles */)) { - return explain("the feature is disabled"); - } if (otherLanguagePacksReason !== void 0) { return explain(otherLanguagePacksReason); } @@ -176417,7 +176410,7 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, othe ); } bundle = await getLatestNightlyBundle( - { env: getEnv(), features, logger: logger2 }, + { env: getEnv(), logger: logger2 }, rawLanguages, otherLanguagePacksReason, variant @@ -176584,17 +176577,14 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, othe compressionMethod = cliVersion2 !== void 0 && await useZstdBundle(cliVersion2, tarSupportsZstd) ? "zstd" : "gzip"; const action = { env: getEnv(), logger: logger2 }; const platform2 = getBundlePlatform(); - const perLanguageBundleLanguage = await getPerLanguageBundleLanguage( - { ...action, features }, - { - rawLanguages, - otherLanguagePacksReason, - cliVersion: cliVersion2, - compressionMethod, - platform: platform2, - variant - } - ); + const perLanguageBundleLanguage = getPerLanguageBundleLanguage(action, { + rawLanguages, + otherLanguagePacksReason, + cliVersion: cliVersion2, + compressionMethod, + platform: platform2, + variant + }); const resolveBundleURL = (language) => getCodeQLAssetDownloadURL( action, apiDetails, @@ -176869,7 +176859,7 @@ async function getLatestNightlyBundle(action, rawLanguages, otherLanguagePacksRe zstdAvailability.available ) ? "zstd" : "gzip"; const platform2 = getBundlePlatform(); - const language = await getPerLanguageBundleLanguage(action, { + const language = getPerLanguageBundleLanguage(action, { rawLanguages, otherLanguagePacksReason, cliVersion: void 0, diff --git a/src/per-language-bundles.test.ts b/src/per-language-bundles.test.ts index 09500d2f77..6998892507 100644 --- a/src/per-language-bundles.test.ts +++ b/src/per-language-bundles.test.ts @@ -1,7 +1,6 @@ import test from "ava"; import { ActionsEnvVars } from "./environment"; -import { Feature } from "./feature-flags"; import { BuiltInLanguage } from "./languages"; import { getOtherLanguagePacksReason, @@ -12,7 +11,6 @@ import { } from "./per-language-bundles"; import { BundlePlatform } from "./platform"; import { - createFeatures, getRecordingLogger, getTestEnv, initAllState, @@ -40,7 +38,6 @@ async function checkEligibility( env: getTestEnv({ [ActionsEnvVars.RUNNER_ENVIRONMENT]: "github-hosted", }), - features: createFeatures([Feature.PerLanguageBundles]), ...stateOverrides, }), { ...ELIGIBLE_OPTIONS, ...overrides }, @@ -145,27 +142,6 @@ test("getPerLanguageBundleLanguage requires a supported release version", async t.is(await checkEligibility({ cliVersion: "2.27.1" }), BuiltInLanguage.java); }); -test("getPerLanguageBundleLanguage requires the feature flag", async (t) => { - t.is(await checkEligibility({}, { features: createFeatures([]) }), undefined); -}); - -test("getPerLanguageBundleLanguage explains a disabled feature before checking eligibility", async (t) => { - const messages: LoggedMessage[] = []; - const language = await getPerLanguageBundleLanguage( - initAllState({ - features: createFeatures([]), - logger: getRecordingLogger(messages, { logToConsole: false }), - }), - { ...ELIGIBLE_OPTIONS, rawLanguages: undefined, cliVersion: undefined }, - ); - - t.is(language, undefined); - t.deepEqual( - messages.map((message) => message.message), - ["Not using a per-language CodeQL bundle since the feature is disabled."], - ); -}); - test("getPerLanguageBundleLanguage skips only the release version check for the latest nightly", async (t) => { const nightly = { isLatestNightly: true, cliVersion: undefined }; t.is(await checkEligibility(nightly), BuiltInLanguage.java); @@ -181,10 +157,6 @@ test("getPerLanguageBundleLanguage skips only the release version check for the ]) { t.is(await checkEligibility({ ...nightly, ...overrides }), undefined); } - t.is( - await checkEligibility(nightly, { features: createFeatures([]) }), - undefined, - ); t.is( await checkEligibility(nightly, { env: getTestEnv({ [ActionsEnvVars.RUNNER_ENVIRONMENT]: "self-hosted" }), diff --git a/src/per-language-bundles.ts b/src/per-language-bundles.ts index d8fcca96dd..db70c808bc 100644 --- a/src/per-language-bundles.ts +++ b/src/per-language-bundles.ts @@ -9,7 +9,6 @@ import { QuerySpec, UserConfig, } from "./config/db-config"; -import { Feature } from "./feature-flags"; import { RepositoryPropertyName } from "./feature-flags/properties"; import { BuiltInLanguage, parseBuiltInLanguage } from "./languages"; import { BundlePlatform } from "./platform"; @@ -139,14 +138,10 @@ export interface PerLanguageBundleOptions { } /** Returns the eligible bundle language, or undefined for the combined bundle. */ -export async function getPerLanguageBundleLanguage( - { - env, - features, - logger, - }: ActionState<["Logger", "ReadOnlyEnv", "FeatureFlags"]>, +export function getPerLanguageBundleLanguage( + { env, logger }: ActionState<["Logger", "ReadOnlyEnv"]>, options: PerLanguageBundleOptions, -): Promise { +): BuiltInLanguage | undefined { const { rawLanguages, otherLanguagePacksReason, @@ -162,10 +157,6 @@ export async function getPerLanguageBundleLanguage( return undefined; }; - if (!(await features.getValue(Feature.PerLanguageBundles))) { - return explain("the feature is disabled"); - } - // A defined reason means the CodeQL CLI may need packs for other languages, for example because // of the configured queries. That applies whichever languages were requested, so check it first // to avoid suggesting that requesting a single language would be enough. diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 7dfac19148..780586ddf9 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -439,7 +439,7 @@ test.serial( tmpDir, GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, - ["javascript"], + undefined, // rawLanguages undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, @@ -633,7 +633,7 @@ for (const toolsInput of ["nightly", "nightly-latest"]) { SAMPLE_DOTCOM_API_DETAILS, GitHubVariant.DOTCOM, true, // tarSupportsZstd - createFeatures([Feature.PerLanguageBundles]), + createFeatures([]), getRunnerLogger(true), ); @@ -664,24 +664,16 @@ test.serial( await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); - for (const { languages, otherLanguagePacksReason, features } of [ - // The per-language feature is disabled. - { - languages: ["java"], - otherLanguagePacksReason: undefined, - features: createFeatures([]), - }, + for (const { languages, otherLanguagePacksReason } of [ // More than one language requires a combined bundle. { languages: ["java", "python"], otherLanguagePacksReason: undefined, - features: createFeatures([Feature.PerLanguageBundles]), }, // The configured queries may need library packs for other languages. { languages: ["java"], otherLanguagePacksReason: "an example reason", - features: createFeatures([Feature.PerLanguageBundles]), }, ]) { const source = await setupCodeql.getCodeQLSource( @@ -693,7 +685,7 @@ test.serial( SAMPLE_DOTCOM_API_DETAILS, GitHubVariant.DOTCOM, true, // tarSupportsZstd - features, + createFeatures([]), getRunnerLogger(true), ); @@ -709,58 +701,48 @@ test.serial( }, ); -for (const perLanguageBundles of [false, true]) { - test.serial( - `getCodeQLSource uses the latest ${perLanguageBundles ? "per-language" : "combined"} bundle for a forced nightly`, - async (t) => { - const expectedTag = "codeql-bundle-30260213"; - const baseURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}`; - const latestNightlyRequest = stubHostedNightly(expectedTag); +test.serial( + "getCodeQLSource uses the latest per-language bundle for a forced nightly", + async (t) => { + const expectedTag = "codeql-bundle-30260213"; + const baseURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}`; + const latestNightlyRequest = stubHostedNightly(expectedTag); - await withTmpDir(async (tmpDir) => { - setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "dynamic" }); - const source = await setupCodeql.getCodeQLSource( - undefined, // toolsInput: the nightly is selected by ForceNightly - SAMPLE_DEFAULT_CLI_VERSION, - ["java"], - undefined, // otherLanguagePacksReason - false, // useOverlayAwareDefaultCliVersion - SAMPLE_DOTCOM_API_DETAILS, - GitHubVariant.DOTCOM, - true, // tarSupportsZstd - createFeatures( - perLanguageBundles - ? [Feature.ForceNightly, Feature.PerLanguageBundles] - : [Feature.ForceNightly], - ), - getRunnerLogger(true), - ); + await withTmpDir(async (tmpDir) => { + setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "dynamic" }); + const source = await setupCodeql.getCodeQLSource( + undefined, // toolsInput: the nightly is selected by ForceNightly + SAMPLE_DEFAULT_CLI_VERSION, + ["java"], + undefined, // otherLanguagePacksReason + false, // useOverlayAwareDefaultCliVersion + SAMPLE_DOTCOM_API_DETAILS, + GitHubVariant.DOTCOM, + true, // tarSupportsZstd + createFeatures([Feature.ForceNightly]), + getRunnerLogger(true), + ); - t.is(source.sourceType, "download"); - t.true(latestNightlyRequest.calledOnce); - if (source.sourceType === "download") { - const combinedURL = `${baseURL}/codeql-bundle-linux64.tar.zst`; - t.deepEqual( - source.bundle, - perLanguageBundles - ? { - kind: "per-language", - language: BuiltInLanguage.java, - url: `${baseURL}/codeql-bundle-java-linux64.tar.zst`, - combinedBundleURL: combinedURL, - } - : { kind: "combined", url: combinedURL }, - ); - } - }); - }, - ); -} + t.is(source.sourceType, "download"); + t.true(latestNightlyRequest.calledOnce); + if (source.sourceType === "download") { + t.deepEqual(source.bundle, { + kind: "per-language", + language: BuiltInLanguage.java, + url: `${baseURL}/codeql-bundle-java-linux64.tar.zst`, + combinedBundleURL: `${baseURL}/codeql-bundle-linux64.tar.zst`, + }); + } + }); + }, +); for (const date of ["20200101", "30260213"]) { for (const bundle of ["combined", "per-language"] as const) { test.serial( - `getCodeQLSource preserves an explicit ${bundle} nightly URL for ${date}`, + `getCodeQLSource preserves an explicit ${bundle} nightly URL for ${date}${ + bundle === "per-language" ? " on GHES" : "" + }`, async (t) => { const latestNightlyRequest = stubHostedNightly( "codeql-bundle-30260213", @@ -770,7 +752,9 @@ for (const date of ["20200101", "30260213"]) { ? "codeql-bundle-linux64.tar.zst" : "codeql-bundle-java-linux64.tar.zst"; const url = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/codeql-bundle-${date}/${asset}`; - const features = createFeatures([Feature.PerLanguageBundles]); + const features = createFeatures([]); + const variant = + bundle === "per-language" ? GitHubVariant.GHES : GitHubVariant.DOTCOM; const logger = getRecordingLogger([], { logToConsole: false }); const error = new HTTPError("Not Found", 404); const extractStub = sinon @@ -786,7 +770,7 @@ for (const date of ["20200101", "30260213"]) { undefined, // otherLanguagePacksReason false, SAMPLE_DOTCOM_API_DETAILS, - GitHubVariant.DOTCOM, + variant, true, features, logger, @@ -808,7 +792,7 @@ for (const date of ["20200101", "30260213"]) { url, SAMPLE_DOTCOM_API_DETAILS, tmpDir, - GitHubVariant.DOTCOM, + variant, SAMPLE_DEFAULT_CLI_VERSION, ["java"], undefined, // otherLanguagePacksReason @@ -1174,7 +1158,7 @@ test.serial( SAMPLE_DOTCOM_API_DETAILS, GitHubVariant.DOTCOM, true, // tarSupportsZstd - createFeatures([Feature.PerLanguageBundles]), + createFeatures([]), getRunnerLogger(true), ); @@ -1207,13 +1191,16 @@ test.serial( await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); - for (const { otherLanguagePacksReason, features } of [ - // The per-language feature is disabled. - { otherLanguagePacksReason: undefined, features: createFeatures([]) }, + for (const { otherLanguagePacksReason, variant } of [ + // Automatic per-language selection is limited to GitHub.com. + { + otherLanguagePacksReason: undefined, + variant: GitHubVariant.GHES, + }, // The configured queries may need library packs for other languages. { otherLanguagePacksReason: "an example reason", - features: createFeatures([Feature.PerLanguageBundles]), + variant: GitHubVariant.DOTCOM, }, ]) { const source = await setupCodeql.getCodeQLSource( @@ -1223,9 +1210,9 @@ test.serial( otherLanguagePacksReason, false, // useOverlayAwareDefaultCliVersion SAMPLE_DOTCOM_API_DETAILS, - GitHubVariant.DOTCOM, + variant, true, // tarSupportsZstd - features, + createFeatures([]), getRunnerLogger(true), ); @@ -1295,7 +1282,7 @@ for (const fallback of [false, true]) { ["java"], undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion - createFeatures([Feature.PerLanguageBundles]), + createFeatures([]), getRunnerLogger(true), ); @@ -1375,7 +1362,7 @@ for (const bundle of ["per-language", "combined", "fallback"] as const) { }; }); const addDiagnostic = sinon.stub(diagnostics, "addNoLanguageDiagnostic"); - const features = createFeatures([Feature.PerLanguageBundles]); + const features = createFeatures([]); await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); @@ -1560,7 +1547,7 @@ for (const error of [ ["java"], undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion - createFeatures([Feature.PerLanguageBundles]), + createFeatures([]), getRunnerLogger(true), ), { is: error }, diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index b4d7416a17..ad17aaa380 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -408,7 +408,7 @@ export async function getCodeQLSource( ); } bundle = await getLatestNightlyBundle( - { env: getEnv(), features, logger }, + { env: getEnv(), logger }, rawLanguages, otherLanguagePacksReason, variant, @@ -651,17 +651,14 @@ export async function getCodeQLSource( const action = { env: getEnv(), logger }; const platform = getBundlePlatform(); - const perLanguageBundleLanguage = await getPerLanguageBundleLanguage( - { ...action, features }, - { - rawLanguages, - otherLanguagePacksReason, - cliVersion, - compressionMethod, - platform, - variant, - }, - ); + const perLanguageBundleLanguage = getPerLanguageBundleLanguage(action, { + rawLanguages, + otherLanguagePacksReason, + cliVersion, + compressionMethod, + platform, + variant, + }); // Resolves the combined or per-language bundle URL for the requested release. const resolveBundleURL = (language?: BuiltInLanguage) => @@ -1089,7 +1086,7 @@ function getTempExtractionDir(tempDir: string) { * Records the combined bundle URL from that release for use if the selected asset is missing. */ async function getLatestNightlyBundle( - action: ActionState<["Logger", "ReadOnlyEnv", "FeatureFlags"]>, + action: ActionState<["Logger", "ReadOnlyEnv"]>, rawLanguages: string[] | undefined, otherLanguagePacksReason: string | undefined, variant: util.GitHubVariant, @@ -1105,7 +1102,7 @@ async function getLatestNightlyBundle( : "gzip"; const platform = getBundlePlatform(); - const language = await getPerLanguageBundleLanguage(action, { + const language = getPerLanguageBundleLanguage(action, { rawLanguages, otherLanguagePacksReason, cliVersion: undefined, From 1a7b87e3d1ff559edb5823aad696a7b281d15f07 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 15 Oct 2026 21:45:10 +0100 Subject: [PATCH 007/174] Remove TRAP cache cleanup Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 103 +--------------------------------- src/analyze-action.ts | 21 +------ src/api-client.ts | 15 ----- src/doc-url.ts | 1 - src/feature-flags.ts | 6 -- src/trap-caching.test.ts | 86 ---------------------------- src/trap-caching.ts | 118 +-------------------------------------- 7 files changed, 3 insertions(+), 347 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 1a99a44427..fb4ca47368 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -170867,14 +170867,6 @@ async function listActionsCaches(keyPrefix, ref) { } ); } -async function deleteActionsCache(id) { - const repositoryNwo = getRepositoryNwo(); - await getApiClient().rest.actions.deleteActionsCacheById({ - owner: repositoryNwo.owner, - repo: repositoryNwo.repo, - cache_id: id - }); -} async function getRepositoryProperties(repositoryNwo) { return getApiClient().request("GET /repos/:owner/:repo/properties/values", { owner: repositoryNwo.owner, @@ -171932,11 +171924,6 @@ var featureConfig = { envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS", minimumVersion: void 0 }, - ["cleanup_trap_caches" /* CleanupTrapCaches */]: { - defaultValue: false, - envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", - minimumVersion: void 0 - }, ["config_file_repository_property" /* ConfigFileRepositoryProperty */]: { defaultValue: false, envVar: "CODEQL_ACTION_CONFIG_FILE_REPOSITORY_PROPERTY", @@ -174250,83 +174237,6 @@ async function uploadTrapCaches(codeql, config, logger2) { } return true; } -async function cleanupTrapCaches(config, features, logger2) { - const env = getEnv(); - if (!await features.getValue("cleanup_trap_caches" /* CleanupTrapCaches */)) { - return { - trap_cache_cleanup_skipped_because: "feature disabled" - }; - } - logger2.warning( - "TRAP cache cleanup is deprecated and will be removed in May 2026. We recommend instead disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action." - ); - if (!await isAnalyzingDefaultBranch(env, config.repositoryRoot)) { - return { - trap_cache_cleanup_skipped_because: "not analyzing default branch" - }; - } - try { - let totalBytesCleanedUp = 0; - const allCaches = await listActionsCaches( - CODEQL_TRAP_CACHE_PREFIX, - await getRef(env, config.repositoryRoot) - ); - for (const language of config.languages) { - if (config.trapCaches[language]) { - const cachesToRemove = await getTrapCachesForLanguage( - allCaches, - language, - logger2 - ); - cachesToRemove.sort((a, b) => a.created_at.localeCompare(b.created_at)); - const mostRecentCache = cachesToRemove.pop(); - logger2.debug( - `Keeping most recent TRAP cache (${JSON.stringify(mostRecentCache)})` - ); - if (cachesToRemove.length === 0) { - logger2.info(`No TRAP caches to clean up for ${language}.`); - continue; - } - for (const cache of cachesToRemove) { - logger2.debug(`Cleaning up TRAP cache (${JSON.stringify(cache)})`); - await deleteActionsCache(cache.id); - } - const bytesCleanedUp = cachesToRemove.reduce( - (acc, item) => acc + item.size_in_bytes, - 0 - ); - totalBytesCleanedUp += bytesCleanedUp; - const megabytesCleanedUp = (bytesCleanedUp / (1024 * 1024)).toFixed(2); - logger2.info( - `Cleaned up ${megabytesCleanedUp} MiB of old TRAP caches for ${language}.` - ); - } - } - return { trap_cache_cleanup_size_bytes: totalBytesCleanedUp }; - } catch (e) { - if (asHTTPError(e)?.status === 403) { - logger2.warning( - `Could not cleanup TRAP caches as the token did not have the required permissions. To clean up TRAP caches, ensure the token has the "actions:write" permission. See ${"https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs" /* ASSIGNING_PERMISSIONS_TO_JOBS */} for more information.` - ); - } else { - logger2.info(`Failed to cleanup TRAP caches, continuing. Details: ${e}`); - } - return { trap_cache_cleanup_error: getErrorMessage(e) }; - } -} -async function getTrapCachesForLanguage(allCaches, language, logger2) { - logger2.debug(`Listing TRAP caches for ${language}`); - for (const cache of allCaches) { - if (!cache.created_at || !cache.id || !cache.key || !cache.size_in_bytes) { - throw new Error( - `An unexpected cache item was returned from the API that was missing one or more required fields: ${JSON.stringify(cache)}` - ); - } - } - return allCaches.filter((cache) => { - return cache.key?.includes(`-${language}-`); - }); -} async function getLanguagesSupportingCaching(codeql, languages, logger2) { const result = []; const resolveResult = await codeql.resolveLanguages(); @@ -180651,7 +180561,7 @@ async function postProcessAndUploadSarif(logger2, features, uploadKind, checkout } // src/analyze-action.ts -async function sendStatusReport2(startedAt, config, stats, error3, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, trapCacheCleanup, dependencyCacheResults, databaseUploadResults, logger2) { +async function sendStatusReport2(startedAt, config, stats, error3, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, dependencyCacheResults, databaseUploadResults, logger2) { const status = getActionsStatus(error3, stats?.analyze_failure_language); const statusReportBase = await createStatusReportBase( "finish" /* Analyze */, @@ -180668,7 +180578,6 @@ async function sendStatusReport2(startedAt, config, stats, error3, trapCacheUplo ...statusReportBase, ...stats || {}, ...dbCreationTimings || {}, - ...trapCacheCleanup || {}, dependency_caching_upload_results: dependencyCacheResults, database_upload_results: databaseUploadResults }; @@ -180752,7 +180661,6 @@ async function run(action) { let uploadResults = void 0; let runStats = void 0; let config = void 0; - let trapCacheCleanupTelemetry = void 0; let trapCacheUploadTime = void 0; let dbCreationTimings = void 0; let didUploadTrapCaches = false; @@ -180896,11 +180804,6 @@ async function run(action) { const trapCacheUploadStartTime = import_perf_hooks6.performance.now(); didUploadTrapCaches = await uploadTrapCaches(codeql, config, logger2); trapCacheUploadTime = import_perf_hooks6.performance.now() - trapCacheUploadStartTime; - trapCacheCleanupTelemetry = await cleanupTrapCaches( - config, - features, - logger2 - ); if (shouldStoreCache(config.dependencyCachingEnabled)) { dependencyCacheResults = await uploadDependencyCaches( codeql, @@ -180937,7 +180840,6 @@ async function run(action) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger2 @@ -180956,7 +180858,6 @@ async function run(action) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger2 @@ -180970,7 +180871,6 @@ async function run(action) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger2 @@ -180984,7 +180884,6 @@ async function run(action) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger2 diff --git a/src/analyze-action.ts b/src/analyze-action.ts index 9efbb529b0..5478d818e2 100644 --- a/src/analyze-action.ts +++ b/src/analyze-action.ts @@ -49,11 +49,7 @@ import { getActionsStatus, StatusReportBase, } from "./status-report"; -import { - cleanupTrapCaches, - TrapCacheCleanupStatusReport, - uploadTrapCaches, -} from "./trap-caching"; +import { uploadTrapCaches } from "./trap-caching"; import * as uploadLib from "./upload-lib"; import { UploadResult } from "./upload-lib"; import { postProcessAndUploadSarif } from "./upload-sarif"; @@ -86,7 +82,6 @@ async function sendStatusReport( trapCacheUploadTime: number | undefined, dbCreationTimings: DatabaseCreationTimings | undefined, didUploadTrapCaches: boolean, - trapCacheCleanup: TrapCacheCleanupStatusReport | undefined, dependencyCacheResults: DependencyCacheUploadStatusReport | undefined, databaseUploadResults: DatabaseUploadResult[], logger: Logger, @@ -107,7 +102,6 @@ async function sendStatusReport( ...statusReportBase, ...(stats || {}), ...(dbCreationTimings || {}), - ...(trapCacheCleanup || {}), dependency_caching_upload_results: dependencyCacheResults, database_upload_results: databaseUploadResults, }; @@ -229,8 +223,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { | undefined = undefined; let runStats: QueriesStatusReport | undefined = undefined; let config: Config | undefined = undefined; - let trapCacheCleanupTelemetry: TrapCacheCleanupStatusReport | undefined = - undefined; let trapCacheUploadTime: number | undefined = undefined; let dbCreationTimings: DatabaseCreationTimings | undefined = undefined; let didUploadTrapCaches = false; @@ -415,13 +407,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { didUploadTrapCaches = await uploadTrapCaches(codeql, config, logger); trapCacheUploadTime = performance.now() - trapCacheUploadStartTime; - // Clean up TRAP caches - trapCacheCleanupTelemetry = await cleanupTrapCaches( - config, - features, - logger, - ); - // Store dependency cache(s) if dependency caching is enabled. if (shouldStoreCache(config.dependencyCachingEnabled)) { dependencyCacheResults = await uploadDependencyCaches( @@ -471,7 +456,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger, @@ -494,7 +478,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger, @@ -508,7 +491,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger, @@ -522,7 +504,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger, diff --git a/src/api-client.ts b/src/api-client.ts index 7aa4d61d75..8a456c1696 100644 --- a/src/api-client.ts +++ b/src/api-client.ts @@ -401,21 +401,6 @@ export async function listActionsCaches( ); } -/** - * Delete an Actions cache item by its ID. - * - * See https://docs.github.com/en/rest/actions/cache#delete-a-github-actions-cache-for-a-repository-using-a-cache-id. - */ -export async function deleteActionsCache(id: number) { - const repositoryNwo = getRepositoryNwo(); - - await getApiClient().rest.actions.deleteActionsCacheById({ - owner: repositoryNwo.owner, - repo: repositoryNwo.repo, - cache_id: id, - }); -} - /** * Retrieve all custom repository properties. * diff --git a/src/doc-url.ts b/src/doc-url.ts index c624817e90..97f5451d85 100644 --- a/src/doc-url.ts +++ b/src/doc-url.ts @@ -3,7 +3,6 @@ */ export enum DocUrl { - ASSIGNING_PERMISSIONS_TO_JOBS = "https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs", AUTOMATIC_BUILD_FAILED = "https://docs.github.com/en/code-security/code-scanning/troubleshooting-code-scanning/automatic-build-failed", CODEQL_BUILD_MODES = "https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#codeql-build-modes", DEFINE_ENV_VARIABLES = "https://docs.github.com/en/actions/learn-github-actions/variables#defining-environment-variables-for-a-single-workflow", diff --git a/src/feature-flags.ts b/src/feature-flags.ts index 5cf7c7414c..8b8e1027a1 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -74,7 +74,6 @@ export enum Feature { AllowMergeConfigFiles = "allow_merge_config_files", /** Controls whether we allow multiple values for the `analysis-kinds` input. */ AllowMultipleAnalysisKinds = "allow_multiple_analysis_kinds", - CleanupTrapCaches = "cleanup_trap_caches", /** Whether to allow the `config-file` input to be specified via a repository property. */ ConfigFileRepositoryProperty = "config_file_repository_property", CppDependencyInstallation = "cpp_dependency_installation_enabled", @@ -216,11 +215,6 @@ export const featureConfig = { envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS", minimumVersion: undefined, }, - [Feature.CleanupTrapCaches]: { - defaultValue: false, - envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", - minimumVersion: undefined, - }, [Feature.ConfigFileRepositoryProperty]: { defaultValue: false, envVar: "CODEQL_ACTION_CONFIG_FILE_REPOSITORY_PROPERTY", diff --git a/src/trap-caching.test.ts b/src/trap-caching.test.ts index 15ab494812..6ec3d5abaf 100644 --- a/src/trap-caching.test.ts +++ b/src/trap-caching.test.ts @@ -6,26 +6,21 @@ import test from "ava"; import * as sinon from "sinon"; import * as actionsUtil from "./actions-util"; -import * as apiClient from "./api-client"; import { getTrapCachingExtractorConfigArgs, getTrapCachingExtractorConfigArgsForLang, createStubCodeQL, } from "./codeql"; import * as configUtils from "./config-utils"; -import { Feature } from "./feature-flags"; import * as gitUtils from "./git-utils"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger } from "./logging"; import { - createFeatures, createTestConfig, getRecordingLogger, makeVersionInfo, setupTests, } from "./testing-utils"; import { - cleanupTrapCaches, downloadTrapCaches, getLanguagesSupportingCaching, uploadTrapCaches, @@ -199,84 +194,3 @@ test.serial( }); }, ); - -test.serial("cleanup removes only old CodeQL TRAP caches", async (t) => { - await util.withTmpDir(async (tmpDir) => { - // This config specifies that we are analyzing JavaScript and Ruby, but not Swift. - const config = getTestConfigWithTempDir(tmpDir); - - sinon.stub(gitUtils, "getRef").resolves("refs/heads/main"); - sinon.stub(gitUtils, "isAnalyzingDefaultBranch").resolves(true); - const listStub = sinon.stub(apiClient, "listActionsCaches").resolves([ - // Should be kept, since it's not relevant to CodeQL. In reality, the API shouldn't return - // this in the first place, but this is a defensive check. - { - id: 1, - key: "some-other-key", - created_at: "2024-05-23T14:25:00Z", - size_in_bytes: 100 * 1024 * 1024, - }, - // Should be kept, since it's the newest TRAP cache for JavaScript - { - id: 2, - key: "codeql-trap-1-2.0.0-javascript-newest", - created_at: "2024-04-23T14:25:00Z", - size_in_bytes: 50 * 1024 * 1024, - }, - // Should be cleaned up - { - id: 3, - key: "codeql-trap-1-2.0.0-javascript-older", - created_at: "2024-03-22T14:25:00Z", - size_in_bytes: 200 * 1024 * 1024, - }, - // Should be cleaned up - { - id: 4, - key: "codeql-trap-1-2.0.0-javascript-oldest", - created_at: "2024-02-21T14:25:00Z", - size_in_bytes: 300 * 1024 * 1024, - }, - // Should be kept, since it's the newest TRAP cache for Ruby - { - id: 5, - key: "codeql-trap-1-2.0.0-ruby-newest", - created_at: "2024-02-20T14:25:00Z", - size_in_bytes: 300 * 1024 * 1024, - }, - // Should be kept, since we aren't analyzing Swift - { - id: 6, - key: "codeql-trap-1-2.0.0-swift-newest", - created_at: "2024-02-22T14:25:00Z", - size_in_bytes: 300 * 1024 * 1024, - }, - // Should be kept, since we aren't analyzing Swift - { - id: 7, - key: "codeql-trap-1-2.0.0-swift-older", - created_at: "2024-02-21T14:25:00Z", - size_in_bytes: 300 * 1024 * 1024, - }, - ]); - - const deleteStub = sinon.stub(apiClient, "deleteActionsCache").resolves(); - - const statusReport = await cleanupTrapCaches( - config, - createFeatures([Feature.CleanupTrapCaches]), - getRunnerLogger(true), - ); - - t.is(listStub.callCount, 1); - t.assert(listStub.calledWithExactly("codeql-trap", "refs/heads/main")); - - t.deepEqual(statusReport, { - trap_cache_cleanup_size_bytes: 500 * 1024 * 1024, - }); - - t.is(deleteStub.callCount, 2); - t.assert(deleteStub.calledWithExactly(3)); - t.assert(deleteStub.calledWithExactly(4)); - }); -}); diff --git a/src/trap-caching.ts b/src/trap-caching.ts index d939368328..fd920600b9 100644 --- a/src/trap-caching.ts +++ b/src/trap-caching.ts @@ -4,21 +4,12 @@ import * as path from "path"; import * as actionsCache from "@actions/cache"; import * as actionsUtil from "./actions-util"; -import * as apiClient from "./api-client"; import { type CodeQL } from "./codeql"; import { type Config } from "./config-utils"; -import { DocUrl } from "./doc-url"; -import { Feature, FeatureEnablement } from "./feature-flags"; import * as gitUtils from "./git-utils"; import { Language } from "./languages"; import { Logger } from "./logging"; -import { - asHTTPError, - getEnv, - getErrorMessage, - tryGetFolderBytes, - waitForResultWithTimeLimit, -} from "./util"; +import { getEnv, tryGetFolderBytes, waitForResultWithTimeLimit } from "./util"; // This constant should be bumped if we make a breaking change // to how the CodeQL Action stores or retrieves the TRAP cache, @@ -178,113 +169,6 @@ export async function uploadTrapCaches( return true; } -export interface TrapCacheCleanupStatusReport { - trap_cache_cleanup_error?: string; - trap_cache_cleanup_size_bytes?: number; - trap_cache_cleanup_skipped_because?: string; -} - -export async function cleanupTrapCaches( - config: Config, - features: FeatureEnablement, - logger: Logger, -): Promise { - const env = getEnv(); - - if (!(await features.getValue(Feature.CleanupTrapCaches))) { - return { - trap_cache_cleanup_skipped_because: "feature disabled", - }; - } - logger.warning( - "TRAP cache cleanup is deprecated and will be removed in May 2026. " + - "We recommend instead disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action.", - ); - if (!(await gitUtils.isAnalyzingDefaultBranch(env, config.repositoryRoot))) { - return { - trap_cache_cleanup_skipped_because: "not analyzing default branch", - }; - } - - try { - let totalBytesCleanedUp = 0; - - const allCaches = await apiClient.listActionsCaches( - CODEQL_TRAP_CACHE_PREFIX, - await gitUtils.getRef(env, config.repositoryRoot), - ); - - for (const language of config.languages) { - if (config.trapCaches[language]) { - const cachesToRemove = await getTrapCachesForLanguage( - allCaches, - language, - logger, - ); - // Dates returned by the API are in ISO 8601 format, so we can sort them lexicographically - cachesToRemove.sort((a, b) => a.created_at.localeCompare(b.created_at)); - // Keep the most recent cache - const mostRecentCache = cachesToRemove.pop(); - logger.debug( - `Keeping most recent TRAP cache (${JSON.stringify(mostRecentCache)})`, - ); - - if (cachesToRemove.length === 0) { - logger.info(`No TRAP caches to clean up for ${language}.`); - continue; - } - - for (const cache of cachesToRemove) { - logger.debug(`Cleaning up TRAP cache (${JSON.stringify(cache)})`); - await apiClient.deleteActionsCache(cache.id); - } - const bytesCleanedUp = cachesToRemove.reduce( - (acc, item) => acc + item.size_in_bytes, - 0, - ); - totalBytesCleanedUp += bytesCleanedUp; - const megabytesCleanedUp = (bytesCleanedUp / (1024 * 1024)).toFixed(2); - logger.info( - `Cleaned up ${megabytesCleanedUp} MiB of old TRAP caches for ${language}.`, - ); - } - } - return { trap_cache_cleanup_size_bytes: totalBytesCleanedUp }; - } catch (e) { - if (asHTTPError(e)?.status === 403) { - logger.warning( - "Could not cleanup TRAP caches as the token did not have the required permissions. " + - 'To clean up TRAP caches, ensure the token has the "actions:write" permission. ' + - `See ${DocUrl.ASSIGNING_PERMISSIONS_TO_JOBS} for more information.`, - ); - } else { - logger.info(`Failed to cleanup TRAP caches, continuing. Details: ${e}`); - } - return { trap_cache_cleanup_error: getErrorMessage(e) }; - } -} - -async function getTrapCachesForLanguage( - allCaches: apiClient.ActionsCacheItem[], - language: Language, - logger: Logger, -): Promise>> { - logger.debug(`Listing TRAP caches for ${language}`); - - for (const cache of allCaches) { - if (!cache.created_at || !cache.id || !cache.key || !cache.size_in_bytes) { - throw new Error( - "An unexpected cache item was returned from the API that was missing one or " + - `more required fields: ${JSON.stringify(cache)}`, - ); - } - } - - return allCaches.filter((cache) => { - return cache.key?.includes(`-${language}-`); - }) as Array>; -} - export async function getLanguagesSupportingCaching( codeql: CodeQL, languages: Language[], From 2d688502143ec04609ef78940a0c57639b030d14 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Fri, 16 Oct 2026 14:00:39 +0100 Subject: [PATCH 008/174] Remove per-language bundle rollout flag Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9f196d4-6d15-44ca-bd01-cd022d57d2cc --- .../workflows/__export-file-baseline-information.yml | 1 - .github/workflows/__per-language-bundle-validation.yml | 1 - lib/entry-points.js | 5 ----- pr-checks/checks/export-file-baseline-information.yml | 1 - pr-checks/checks/per-language-bundle-validation.yml | 2 -- src/feature-flags.ts | 10 ---------- 6 files changed, 20 deletions(-) diff --git a/.github/workflows/__export-file-baseline-information.yml b/.github/workflows/__export-file-baseline-information.yml index 7badf827f1..13d15fb6d4 100644 --- a/.github/workflows/__export-file-baseline-information.yml +++ b/.github/workflows/__export-file-baseline-information.yml @@ -129,5 +129,4 @@ jobs: env: CODEQL_ACTION_SKIP_FILE_COVERAGE_ON_PRS: false CODEQL_ACTION_SUBLANGUAGE_FILE_COVERAGE: true - CODEQL_ACTION_PER_LANGUAGE_BUNDLES: true CODEQL_ACTION_TEST_MODE: true diff --git a/.github/workflows/__per-language-bundle-validation.yml b/.github/workflows/__per-language-bundle-validation.yml index 07930b35ab..c320f2199b 100644 --- a/.github/workflows/__per-language-bundle-validation.yml +++ b/.github/workflows/__per-language-bundle-validation.yml @@ -167,5 +167,4 @@ jobs: fi echo "Created a ${LANGUAGE} database at ${database}." env: - CODEQL_ACTION_PER_LANGUAGE_BUNDLES: true CODEQL_ACTION_TEST_MODE: true diff --git a/lib/entry-points.js b/lib/entry-points.js index dfa3adefcb..8d9d423bef 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -172145,11 +172145,6 @@ var featureConfig = { envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_SKIP_RESOURCE_CHECKS", minimumVersion: void 0 }, - ["per_language_bundles_v2" /* PerLanguageBundles */]: { - defaultValue: false, - envVar: "CODEQL_ACTION_PER_LANGUAGE_BUNDLES", - minimumVersion: void 0 - }, ["qa_telemetry_enabled" /* QaTelemetryEnabled */]: { defaultValue: false, envVar: "CODEQL_ACTION_QA_TELEMETRY", diff --git a/pr-checks/checks/export-file-baseline-information.yml b/pr-checks/checks/export-file-baseline-information.yml index 87c4b7609b..dd8325717b 100644 --- a/pr-checks/checks/export-file-baseline-information.yml +++ b/pr-checks/checks/export-file-baseline-information.yml @@ -11,7 +11,6 @@ installDotNet: true env: CODEQL_ACTION_SKIP_FILE_COVERAGE_ON_PRS: false CODEQL_ACTION_SUBLANGUAGE_FILE_COVERAGE: true - CODEQL_ACTION_PER_LANGUAGE_BUNDLES: true steps: - uses: ./../action/init id: init diff --git a/pr-checks/checks/per-language-bundle-validation.yml b/pr-checks/checks/per-language-bundle-validation.yml index ac22f67f50..fc9805af90 100644 --- a/pr-checks/checks/per-language-bundle-validation.yml +++ b/pr-checks/checks/per-language-bundle-validation.yml @@ -40,8 +40,6 @@ matrix: os: macos-latest-xlarge version: linked build-mode: autobuild -env: - CODEQL_ACTION_PER_LANGUAGE_BUNDLES: true steps: - name: Remove CodeQL from toolcache uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 diff --git a/src/feature-flags.ts b/src/feature-flags.ts index 5cf7c7414c..b43f23c5d4 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -159,11 +159,6 @@ export enum Feature { OverlayAnalysisStatusCheck = "overlay_analysis_status_check", /** Controls whether overlay build failures on the default branch are stored in the Actions cache. */ OverlayAnalysisStatusSave = "overlay_analysis_status_save", - /** - * Controls whether we may download a bundle containing only the single language being analysed, - * rather than the combined bundle that contains every language. - */ - PerLanguageBundles = "per_language_bundles_v2", QaTelemetryEnabled = "qa_telemetry_enabled", /** Routes (some) API requests through the registry proxy. */ ProxyApiRequests = "proxy_api_requests", @@ -429,11 +424,6 @@ export const featureConfig = { envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_SKIP_RESOURCE_CHECKS", minimumVersion: undefined, }, - [Feature.PerLanguageBundles]: { - defaultValue: false, - envVar: "CODEQL_ACTION_PER_LANGUAGE_BUNDLES", - minimumVersion: undefined, - }, [Feature.QaTelemetryEnabled]: { defaultValue: false, envVar: "CODEQL_ACTION_QA_TELEMETRY", From 9b5d335b995d625719d424b7041ad3331c3f4cf9 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 15 Oct 2026 21:48:34 +0100 Subject: [PATCH 009/174] Warn when `CODEQL_ACTION_CLEANUP_TRAP_CACHES` is set Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 11 +++++++++++ src/analyze-action.ts | 7 ++++++- src/trap-caching.test.ts | 27 +++++++++++++++++++++++++++ src/trap-caching.ts | 20 ++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index fb4ca47368..180ce0bff7 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -174237,6 +174237,16 @@ async function uploadTrapCaches(codeql, config, logger2) { } return true; } +function warnIfTrapCacheCleanupEnvVarIsSet({ + env, + logger: logger2 +}) { + if (env.getOptional("CODEQL_ACTION_CLEANUP_TRAP_CACHES") !== void 0) { + logger2.warning( + "TRAP cache cleanup has been removed, so the CODEQL_ACTION_CLEANUP_TRAP_CACHES environment variable no longer has any effect and can be removed from your workflow. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching instead by passing the `trap-caching: false` input to the `init` Action." + ); + } +} async function getLanguagesSupportingCaching(codeql, languages, logger2) { const result = []; const resolveResult = await codeql.resolveLanguages(); @@ -180697,6 +180707,7 @@ async function run(action) { "The 'cleanup-level' input is ignored since the CodeQL Action now automatically manages database cleanup. This input can safely be removed from your workflow." ); } + warnIfTrapCacheCleanupEnvVarIsSet(action); const apiDetails = getApiDetails(); const outputDir = getRequiredInput("output"); action.env.export("CODEQL_ACTION_SARIF_RESULTS_OUTPUT_DIR" /* SARIF_RESULTS_OUTPUT_DIR */, outputDir); diff --git a/src/analyze-action.ts b/src/analyze-action.ts index 5478d818e2..f273dbbd8c 100644 --- a/src/analyze-action.ts +++ b/src/analyze-action.ts @@ -49,7 +49,10 @@ import { getActionsStatus, StatusReportBase, } from "./status-report"; -import { uploadTrapCaches } from "./trap-caching"; +import { + uploadTrapCaches, + warnIfTrapCacheCleanupEnvVarIsSet, +} from "./trap-caching"; import * as uploadLib from "./upload-lib"; import { UploadResult } from "./upload-lib"; import { postProcessAndUploadSarif } from "./upload-sarif"; @@ -270,6 +273,8 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { ); } + warnIfTrapCacheCleanupEnvVarIsSet(action); + const apiDetails = getApiDetails(); const outputDir = actionsUtil.getRequiredInput("output"); action.env.export(EnvVar.SARIF_RESULTS_OUTPUT_DIR, outputDir); diff --git a/src/trap-caching.test.ts b/src/trap-caching.test.ts index 6ec3d5abaf..99dc59706e 100644 --- a/src/trap-caching.test.ts +++ b/src/trap-caching.test.ts @@ -15,6 +15,7 @@ import * as configUtils from "./config-utils"; import * as gitUtils from "./git-utils"; import { BuiltInLanguage } from "./languages"; import { + callee, createTestConfig, getRecordingLogger, makeVersionInfo, @@ -24,6 +25,7 @@ import { downloadTrapCaches, getLanguagesSupportingCaching, uploadTrapCaches, + warnIfTrapCacheCleanupEnvVarIsSet, } from "./trap-caching"; import * as util from "./util"; @@ -194,3 +196,28 @@ test.serial( }); }, ); + +// `CODEQL_ACTION_CLEANUP_TRAP_CACHES` has no effect with either value, so we warn even when it's +// set to `false`. +for (const value of ["true", "false"]) { + test(`warnIfTrapCacheCleanupEnvVarIsSet warns when CODEQL_ACTION_CLEANUP_TRAP_CACHES is '${value}'`, async (t) => { + const target = callee(warnIfTrapCacheCleanupEnvVarIsSet) + .withEnv((env) => env.set("CODEQL_ACTION_CLEANUP_TRAP_CACHES", value)) + .withArgs() + .logs( + t, + "CODEQL_ACTION_CLEANUP_TRAP_CACHES environment variable no longer has any effect", + ); + await target.passes(t.is, undefined); + t.deepEqual( + target.getLogger().messages.map((m) => m.type), + ["warning"], + ); + }); +} + +test("warnIfTrapCacheCleanupEnvVarIsSet doesn't warn when CODEQL_ACTION_CLEANUP_TRAP_CACHES is unset", async (t) => { + const target = callee(warnIfTrapCacheCleanupEnvVarIsSet).withArgs(); + await target.passes(t.is, undefined); + t.deepEqual(target.getLogger().messages, []); +}); diff --git a/src/trap-caching.ts b/src/trap-caching.ts index fd920600b9..58d96890f5 100644 --- a/src/trap-caching.ts +++ b/src/trap-caching.ts @@ -3,6 +3,7 @@ import * as path from "path"; import * as actionsCache from "@actions/cache"; +import { type ActionState } from "./action-common"; import * as actionsUtil from "./actions-util"; import { type CodeQL } from "./codeql"; import { type Config } from "./config-utils"; @@ -169,6 +170,25 @@ export async function uploadTrapCaches( return true; } +/** + * Warns if the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable is set to a non-empty + * value. That variable controlled the removed TRAP cache cleanup feature, so setting it has no + * effect. + */ +export function warnIfTrapCacheCleanupEnvVarIsSet({ + env, + logger, +}: ActionState<["Logger", "ReadOnlyEnv"]>): void { + if (env.getOptional("CODEQL_ACTION_CLEANUP_TRAP_CACHES") !== undefined) { + logger.warning( + "TRAP cache cleanup has been removed, so the CODEQL_ACTION_CLEANUP_TRAP_CACHES environment " + + "variable no longer has any effect and can be removed from your workflow. If you used TRAP " + + "cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching instead by " + + "passing the `trap-caching: false` input to the `init` Action.", + ); + } +} + export async function getLanguagesSupportingCaching( codeql: CodeQL, languages: Language[], From 0e72543776e866707b7ca718f668fc51e216ae8b Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 15 Oct 2026 14:51:51 +0100 Subject: [PATCH 010/174] Remove overlay version matching dry run Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 35 +----------------------- src/feature-flags.ts | 11 -------- src/setup-codeql.test.ts | 57 ++-------------------------------------- src/setup-codeql.ts | 43 +++--------------------------- 4 files changed, 6 insertions(+), 140 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index d5e64717a0..240eb82575 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -172089,11 +172089,6 @@ var featureConfig = { envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION", minimumVersion: void 0 }, - ["overlay_analysis_match_codeql_version_dry_run" /* OverlayAnalysisMatchCodeqlVersionDryRun */]: { - defaultValue: false, - envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION_DRY_RUN", - minimumVersion: void 0 - }, ["overlay_analysis_min_disk_8_gb" /* OverlayAnalysisMinDisk8Gb */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MIN_DISK_8_GB", @@ -176287,11 +176282,7 @@ async function getEnabledVersionsWithOverlayBaseDatabases(defaultCliVersion, raw if (rawLanguages === void 0 || rawLanguages.length === 0) { return []; } - const isEnabled = await features.getValue( - "overlay_analysis_match_codeql_version" /* OverlayAnalysisMatchCodeqlVersion */ - ); - const isDryRun = !isEnabled && await features.getValue("overlay_analysis_match_codeql_version_dry_run" /* OverlayAnalysisMatchCodeqlVersionDryRun */); - if (!isEnabled && !isDryRun) { + if (!await features.getValue("overlay_analysis_match_codeql_version" /* OverlayAnalysisMatchCodeqlVersion */)) { return []; } let cachedVersions; @@ -176316,30 +176307,6 @@ async function getEnabledVersionsWithOverlayBaseDatabases(defaultCliVersion, raw if (overlayVersions.length === 0) { return []; } - const isCachedVersionDifferent = overlayVersions[0].cliVersion !== defaultCliVersion.enabledVersions[0].cliVersion; - if (isCachedVersionDifferent) { - addNoLanguageDiagnostic( - void 0, - makeTelemetryDiagnostic( - "codeql-action/overlay-aware-default-codeql-version", - "Overlay-aware default CodeQL version selection", - { - cachedVersions, - enabledVersions: defaultCliVersion.enabledVersions.map( - (v) => v.cliVersion - ), - isDryRun, - overlayAwareVersion: overlayVersions[0].cliVersion - } - ) - ); - } - if (isDryRun) { - logger2.debug( - `Overlay-aware default CodeQL version selection is running in dry-run mode. Would have used version ${overlayVersions[0].cliVersion}.` - ); - return []; - } return overlayVersions; } async function resolveDefaultCliVersion(defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, features, logger2) { diff --git a/src/feature-flags.ts b/src/feature-flags.ts index f74d0bd250..d8cc4cd151 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -120,12 +120,6 @@ export enum Feature { * database exists in the cache. */ OverlayAnalysisMatchCodeqlVersion = "overlay_analysis_match_codeql_version", - /** - * Like `OverlayAnalysisMatchCodeqlVersion`, but only logs a diagnostic with the version that - * would have been chosen instead of actually changing the default CodeQL CLI version. - * `OverlayAnalysisMatchCodeqlVersion` overrides this flag. - */ - OverlayAnalysisMatchCodeqlVersionDryRun = "overlay_analysis_match_codeql_version_dry_run", /** * Lowers the overlay minimum available disk space to 8 GB. The lowest enabled limit wins; if * none are enabled, the default applies. @@ -389,11 +383,6 @@ export const featureConfig = { envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION", minimumVersion: undefined, }, - [Feature.OverlayAnalysisMatchCodeqlVersionDryRun]: { - defaultValue: false, - envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION_DRY_RUN", - minimumVersion: undefined, - }, [Feature.OverlayAnalysisMinDisk8Gb]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MIN_DISK_8_GB", diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 6bdb29f462..98633717de 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -1727,7 +1727,7 @@ test.serial( ); test.serial( - "getEnabledVersionsWithOverlayBaseDatabases does not list caches when both gates are off", + "getEnabledVersionsWithOverlayBaseDatabases does not list caches when the gate is off", async (t) => { const listStub = sinon.stub(api, "listActionsCaches").resolves([]); @@ -1740,64 +1740,11 @@ test.serial( t.deepEqual(result, []); t.assert( listStub.notCalled, - "Should not list Actions caches when both gating feature flags are off.", + "Should not list Actions caches when the gating feature flag is off.", ); }, ); -test.serial( - "getEnabledVersionsWithOverlayBaseDatabases dry-run returns empty but lists caches", - async (t) => { - sinon.stub(api, "getAutomationID").resolves("test/"); - const listStub = sinon.stub(api, "listActionsCaches").resolves([ - { - key: await fakeOverlayBaseCacheKey("javascript", "2.20.1", "abc-1-1"), - }, - ]); - - const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( - overlayMatchEnabledVersions, - ["javascript"], - createFeatures([Feature.OverlayAnalysisMatchCodeqlVersionDryRun]), - getRunnerLogger(true), - ); - t.deepEqual( - result, - [], - "Dry-run should return an empty list so the caller falls back.", - ); - t.assert( - listStub.calledOnce, - "Dry-run should still list Actions caches to populate the diagnostic.", - ); - }, -); - -test.serial( - "getEnabledVersionsWithOverlayBaseDatabases match flag wins over dry-run", - async (t) => { - sinon.stub(api, "getAutomationID").resolves("test/"); - sinon.stub(api, "listActionsCaches").resolves([ - { - key: await fakeOverlayBaseCacheKey("javascript", "2.20.1", "abc-1-1"), - }, - ]); - - const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( - overlayMatchEnabledVersions, - ["javascript"], - createFeatures([ - Feature.OverlayAnalysisMatchCodeqlVersion, - Feature.OverlayAnalysisMatchCodeqlVersionDryRun, - ]), - getRunnerLogger(true), - ); - t.deepEqual(result, [ - { cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" }, - ]); - }, -); - /** The CLI version that the toolcache cleanup tests download. */ const CLEANUP_CLI_VERSION = "2.21.0"; /** The bundle version that the toolcache cleanup tests download. */ diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index 07666d6302..9cd8ca470d 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -183,10 +183,8 @@ async function findOverridingToolsInCache( /** * Returns the sorted set of enabled versions that have cached overlay-base databases for the - * given languages, or an empty list if neither the `OverlayAnalysisMatchCodeqlVersion` nor the - * `OverlayAnalysisMatchCodeqlVersionDryRun` feature flag is enabled. When only the dry-run flag - * is enabled, this performs the lookup and emits a telemetry diagnostic with the version that - * would have been chosen, but still returns an empty list so the caller falls back. + * given languages, or an empty list if the `OverlayAnalysisMatchCodeqlVersion` feature flag is + * disabled. */ export async function getEnabledVersionsWithOverlayBaseDatabases( defaultCliVersion: CodeQLDefaultVersionInfo, @@ -197,13 +195,7 @@ export async function getEnabledVersionsWithOverlayBaseDatabases( if (rawLanguages === undefined || rawLanguages.length === 0) { return []; } - const isEnabled = await features.getValue( - Feature.OverlayAnalysisMatchCodeqlVersion, - ); - const isDryRun = - !isEnabled && - (await features.getValue(Feature.OverlayAnalysisMatchCodeqlVersionDryRun)); - if (!isEnabled && !isDryRun) { + if (!(await features.getValue(Feature.OverlayAnalysisMatchCodeqlVersion))) { return []; } @@ -234,35 +226,6 @@ export async function getEnabledVersionsWithOverlayBaseDatabases( return []; } - const isCachedVersionDifferent = - overlayVersions[0].cliVersion !== - defaultCliVersion.enabledVersions[0].cliVersion; - - if (isCachedVersionDifferent) { - addNoLanguageDiagnostic( - undefined, - makeTelemetryDiagnostic( - "codeql-action/overlay-aware-default-codeql-version", - "Overlay-aware default CodeQL version selection", - { - cachedVersions, - enabledVersions: defaultCliVersion.enabledVersions.map( - (v) => v.cliVersion, - ), - isDryRun, - overlayAwareVersion: overlayVersions[0].cliVersion, - }, - ), - ); - } - - if (isDryRun) { - logger.debug( - `Overlay-aware default CodeQL version selection is running in dry-run mode. Would have used version ${overlayVersions[0].cliVersion}.`, - ); - return []; - } - return overlayVersions; } From 6d82d4f44173c02171cc06acededab5d1b7d8085 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 15 Oct 2026 11:01:45 +0100 Subject: [PATCH 011/174] Use overlay-aware CodeQL versions by default Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 19 ++--- src/feature-flags.ts | 12 --- src/setup-codeql.test.ts | 177 +++++++++++++++++++++++++++++++-------- src/setup-codeql.ts | 27 +++--- 4 files changed, 162 insertions(+), 73 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 240eb82575..2982b8495d 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -172084,11 +172084,6 @@ var featureConfig = { envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_DISABLE_TRAP_CACHING", minimumVersion: void 0 }, - ["overlay_analysis_match_codeql_version" /* OverlayAnalysisMatchCodeqlVersion */]: { - defaultValue: false, - envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION", - minimumVersion: void 0 - }, ["overlay_analysis_min_disk_8_gb" /* OverlayAnalysisMinDisk8Gb */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MIN_DISK_8_GB", @@ -176278,13 +176273,10 @@ async function findOverridingToolsInCache(humanReadableVersion, logger2) { } return void 0; } -async function getEnabledVersionsWithOverlayBaseDatabases(defaultCliVersion, rawLanguages, features, logger2) { +async function getEnabledVersionsWithOverlayBaseDatabases(defaultCliVersion, rawLanguages, logger2) { if (rawLanguages === void 0 || rawLanguages.length === 0) { return []; } - if (!await features.getValue("overlay_analysis_match_codeql_version" /* OverlayAnalysisMatchCodeqlVersion */)) { - return []; - } let cachedVersions; try { cachedVersions = await getCodeQlVersionsForOverlayBaseDatabases( @@ -176309,14 +176301,13 @@ async function getEnabledVersionsWithOverlayBaseDatabases(defaultCliVersion, raw } return overlayVersions; } -async function resolveDefaultCliVersion(defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, features, logger2) { - if (!useOverlayAwareDefaultCliVersion || !isAnalyzingPullRequest()) { +async function resolveDefaultCliVersion(defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, variant, logger2) { + if (!useOverlayAwareDefaultCliVersion || variant !== "GitHub.com" /* DOTCOM */ && variant !== "GitHub Enterprise Cloud with data residency" /* GHEC_DR */ || defaultCliVersion.enabledVersions.length === 1 || !isAnalyzingPullRequest()) { return defaultCliVersion.enabledVersions[0]; } const overlayVersions = await getEnabledVersionsWithOverlayBaseDatabases( defaultCliVersion, rawLanguages, - features, logger2 ); if (overlayVersions.length > 0) { @@ -176423,7 +176414,7 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, othe defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, - features, + variant, logger2 ); cliVersion2 = version.cliVersion; @@ -176443,7 +176434,7 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, othe defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, - features, + variant, logger2 ); cliVersion2 = version.cliVersion; diff --git a/src/feature-flags.ts b/src/feature-flags.ts index d8cc4cd151..fcb2bbc9d3 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -113,13 +113,6 @@ export enum Feature { OverlayAnalysisGo = "overlay_analysis_go", OverlayAnalysisJava = "overlay_analysis_java", OverlayAnalysisJavascript = "overlay_analysis_javascript", - /** - * When set, chooses the default CodeQL CLI version as the highest version that is both enabled by - * feature flags and present as an overlay-base database in the Actions cache for the configured - * languages. Falls back to the highest feature flagged version if no intersecting overlay-base - * database exists in the cache. - */ - OverlayAnalysisMatchCodeqlVersion = "overlay_analysis_match_codeql_version", /** * Lowers the overlay minimum available disk space to 8 GB. The lowest enabled limit wins; if * none are enabled, the default applies. @@ -378,11 +371,6 @@ export const featureConfig = { envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_DISABLE_TRAP_CACHING", minimumVersion: undefined, }, - [Feature.OverlayAnalysisMatchCodeqlVersion]: { - defaultValue: false, - envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION", - minimumVersion: undefined, - }, [Feature.OverlayAnalysisMinDisk8Gb]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MIN_DISK_8_GB", diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 98633717de..a120d6ebd0 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -1069,14 +1069,147 @@ async function fakeOverlayBaseCacheKey( return `${prefix}${suffix}`; } +for (const variant of [GitHubVariant.DOTCOM, GitHubVariant.GHEC_DR]) { + test.serial( + `getCodeQLSource uses overlay-aware default version for a Code Scanning PR on ${variant}`, + async (t) => { + await withTmpDir(async (tmpDir) => { + setupActionsVars(tmpDir, tmpDir); + process.env[EnvVar.CODE_SCANNING_REF] = "refs/heads/feature-branch"; + process.env[EnvVar.CODE_SCANNING_BASE_BRANCH] = "main"; + + sinon.stub(api, "getAutomationID").resolves("test/"); + const listStub = sinon.stub(api, "listActionsCaches").resolves([ + { + key: await fakeOverlayBaseCacheKey( + "javascript", + "2.20.1", + "abc-1-1", + ), + }, + ]); + sinon + .stub(toolcache, "find") + .withArgs("CodeQL", "2.20.1") + .returns("/path/to/codeql-2.20.1"); + + const source = await setupCodeql.getCodeQLSource( + undefined, + overlayMatchEnabledVersions, + ["javascript"], + undefined, // otherLanguagePacksReason + true, + SAMPLE_DOTCOM_API_DETAILS, + variant, + false, + createFeatures([]), + getRunnerLogger(true), + ); + + t.assert(listStub.calledOnce); + t.is(source.sourceType, "toolcache"); + t.is(source.toolsVersion, "2.20.1"); + }); + }, + ); +} + +test.serial( + "getCodeQLSource skips overlay-aware default version for a Code Scanning PR on GHES", + async (t) => { + await withTmpDir(async (tmpDir) => { + setupActionsVars(tmpDir, tmpDir); + process.env[EnvVar.CODE_SCANNING_REF] = "refs/heads/feature-branch"; + process.env[EnvVar.CODE_SCANNING_BASE_BRANCH] = "main"; + + sinon.stub(api, "getAutomationID").resolves("test/"); + const listStub = sinon.stub(api, "listActionsCaches").resolves([ + { + key: await fakeOverlayBaseCacheKey("javascript", "2.20.1", "abc-1-1"), + }, + ]); + sinon + .stub(toolcache, "find") + .withArgs("CodeQL", "2.20.2") + .returns("/path/to/codeql-2.20.2"); + + const source = await setupCodeql.getCodeQLSource( + undefined, + overlayMatchEnabledVersions, + ["javascript"], + undefined, // otherLanguagePacksReason + true, + SAMPLE_DOTCOM_API_DETAILS, + GitHubVariant.GHES, + false, + createFeatures([]), + getRunnerLogger(true), + ); + + t.assert(listStub.notCalled); + t.is(source.sourceType, "toolcache"); + t.is(source.toolsVersion, "2.20.2"); + }); + }, +); + test.serial( - "getCodeQLSource uses overlay-aware default version when requested for a PR", + "getCodeQLSource skips the Actions cache when only one default version is enabled", async (t) => { await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); process.env[EnvVar.CODE_SCANNING_REF] = "refs/heads/feature-branch"; process.env[EnvVar.CODE_SCANNING_BASE_BRANCH] = "main"; + sinon.stub(api, "getAutomationID").resolves("test/"); + const listStub = sinon.stub(api, "listActionsCaches").resolves([ + { + key: await fakeOverlayBaseCacheKey( + "javascript", + SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion, + "abc-1-1", + ), + }, + ]); + sinon + .stub(toolcache, "find") + .withArgs( + "CodeQL", + SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion, + ) + .returns("/path/to/codeql"); + + const source = await setupCodeql.getCodeQLSource( + undefined, + SAMPLE_DEFAULT_CLI_VERSION, + ["javascript"], + undefined, // otherLanguagePacksReason + true, + SAMPLE_DOTCOM_API_DETAILS, + GitHubVariant.DOTCOM, + false, + createFeatures([]), + getRunnerLogger(true), + ); + + t.assert(listStub.notCalled); + t.is(source.sourceType, "toolcache"); + t.is( + source.toolsVersion, + SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion, + ); + }); + }, +); + +test.serial( + "getCodeQLSource skips overlay-aware default version outside pull request analysis", + async (t) => { + sinon.stub(actionsUtil, "isAnalyzingPullRequest").returns(false); + + await withTmpDir(async (tmpDir) => { + setupActionsVars(tmpDir, tmpDir); + sinon.stub(api, "getAutomationID").resolves("test/"); const listStub = sinon.stub(api, "listActionsCaches").resolves([ { @@ -1085,8 +1218,8 @@ test.serial( ]); sinon .stub(toolcache, "find") - .withArgs("CodeQL", "2.20.1") - .returns("/path/to/codeql-2.20.1"); + .withArgs("CodeQL", "2.20.2") + .returns("/path/to/codeql-2.20.2"); const source = await setupCodeql.getCodeQLSource( undefined, @@ -1097,19 +1230,19 @@ test.serial( SAMPLE_DOTCOM_API_DETAILS, GitHubVariant.DOTCOM, false, - createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), + createFeatures([]), getRunnerLogger(true), ); - t.assert(listStub.calledOnce); + t.assert(listStub.notCalled); t.is(source.sourceType, "toolcache"); - t.is(source.toolsVersion, "2.20.1"); + t.is(source.toolsVersion, "2.20.2"); }); }, ); test.serial( - "getCodeQLSource skips overlay-aware default version when not requested", + "getCodeQLSource skips overlay-aware default version when not requested for Code Scanning", async (t) => { await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); @@ -1136,7 +1269,7 @@ test.serial( SAMPLE_DOTCOM_API_DETAILS, GitHubVariant.DOTCOM, false, - createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), + createFeatures([]), getRunnerLogger(true), ); @@ -1611,7 +1744,7 @@ test.serial( ); test.serial( - "getEnabledVersionsWithOverlayBaseDatabases returns flag-enabled versions present in cache, sorted desc", + "getEnabledVersionsWithOverlayBaseDatabases returns enabled versions present in cache, sorted desc", async (t) => { sinon.stub(api, "getAutomationID").resolves("test/"); sinon.stub(api, "listActionsCaches").resolves([ @@ -1632,7 +1765,6 @@ test.serial( const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( overlayMatchEnabledVersions, ["javascript"], - createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), getRunnerLogger(true), ); t.deepEqual(result, [ @@ -1643,7 +1775,7 @@ test.serial( ); test.serial( - "getEnabledVersionsWithOverlayBaseDatabases returns empty when no cached version is flag-enabled", + "getEnabledVersionsWithOverlayBaseDatabases returns empty when no cached version is enabled", async (t) => { sinon.stub(api, "getAutomationID").resolves("test/"); sinon.stub(api, "listActionsCaches").resolves([ @@ -1655,7 +1787,6 @@ test.serial( const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( overlayMatchEnabledVersions, ["javascript"], - createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), getRunnerLogger(true), ); t.deepEqual(result, []); @@ -1672,7 +1803,6 @@ const noLanguagesMacro = makeMacro({ const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( overlayMatchEnabledVersions, rawLanguages, - createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), getRunnerLogger(true), ); t.deepEqual(result, []); @@ -1697,7 +1827,6 @@ test.serial( const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( overlayMatchEnabledVersions, ["javascript"], - createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), getRunnerLogger(true), ); t.deepEqual(result, []); @@ -1717,7 +1846,6 @@ test.serial( const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( overlayMatchEnabledVersions, ["javascript"], - createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), getRunnerLogger(true), ); t.deepEqual(result, [ @@ -1726,25 +1854,6 @@ test.serial( }, ); -test.serial( - "getEnabledVersionsWithOverlayBaseDatabases does not list caches when the gate is off", - async (t) => { - const listStub = sinon.stub(api, "listActionsCaches").resolves([]); - - const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( - overlayMatchEnabledVersions, - ["javascript"], - createFeatures([]), - getRunnerLogger(true), - ); - t.deepEqual(result, []); - t.assert( - listStub.notCalled, - "Should not list Actions caches when the gating feature flag is off.", - ); - }, -); - /** The CLI version that the toolcache cleanup tests download. */ const CLEANUP_CLI_VERSION = "2.21.0"; /** The bundle version that the toolcache cleanup tests download. */ diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index 9cd8ca470d..6932478bc1 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -183,21 +183,16 @@ async function findOverridingToolsInCache( /** * Returns the sorted set of enabled versions that have cached overlay-base databases for the - * given languages, or an empty list if the `OverlayAnalysisMatchCodeqlVersion` feature flag is - * disabled. + * given languages. */ export async function getEnabledVersionsWithOverlayBaseDatabases( defaultCliVersion: CodeQLDefaultVersionInfo, rawLanguages: string[] | undefined, - features: FeatureEnablement, logger: Logger, ): Promise { if (rawLanguages === undefined || rawLanguages.length === 0) { return []; } - if (!(await features.getValue(Feature.OverlayAnalysisMatchCodeqlVersion))) { - return []; - } let cachedVersions: string[] | undefined; try { @@ -231,24 +226,30 @@ export async function getEnabledVersionsWithOverlayBaseDatabases( /** * Resolves the newest enabled default CLI version that has a cached overlay-base database for the - * relevant languages, if running a Code Scanning analysis for a pull request and one exists. - * Otherwise, falls back to the newest enabled default CLI version. + * relevant languages, if running a Code Scanning analysis for a pull request with multiple enabled + * default versions in a supported environment and one exists. Otherwise, falls back to the newest + * enabled default CLI version. */ async function resolveDefaultCliVersion( defaultCliVersion: CodeQLDefaultVersionInfo, rawLanguages: string[] | undefined, useOverlayAwareDefaultCliVersion: boolean, - features: FeatureEnablement, + variant: util.GitHubVariant, logger: Logger, ): Promise { - if (!useOverlayAwareDefaultCliVersion || !isAnalyzingPullRequest()) { + if ( + !useOverlayAwareDefaultCliVersion || + (variant !== util.GitHubVariant.DOTCOM && + variant !== util.GitHubVariant.GHEC_DR) || + defaultCliVersion.enabledVersions.length === 1 || + !isAnalyzingPullRequest() + ) { return defaultCliVersion.enabledVersions[0]; } const overlayVersions = await getEnabledVersionsWithOverlayBaseDatabases( defaultCliVersion, rawLanguages, - features, logger, ); if (overlayVersions.length > 0) { @@ -445,7 +446,7 @@ export async function getCodeQLSource( defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, - features, + variant, logger, ); cliVersion = version.cliVersion; @@ -468,7 +469,7 @@ export async function getCodeQLSource( defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, - features, + variant, logger, ); cliVersion = version.cliVersion; From ba6f82195bbe4ce1dc3726b3b0fff7d82747452c Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Fri, 16 Oct 2026 14:02:16 +0100 Subject: [PATCH 012/174] Add change note Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- unreleased-change-notes/remove-trap-cache-cleanup.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 unreleased-change-notes/remove-trap-cache-cleanup.md diff --git a/unreleased-change-notes/remove-trap-cache-cleanup.md b/unreleased-change-notes/remove-trap-cache-cleanup.md new file mode 100644 index 0000000000..f63b7bebd8 --- /dev/null +++ b/unreleased-change-notes/remove-trap-cache-cleanup.md @@ -0,0 +1 @@ +- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable has been removed, as announced in CodeQL Action 4.35.2. The `analyze` Action now warns if this environment variable is set. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#4243](https://github.com/github/codeql-action/pull/4243) From 912708411bb42510370cb242ff6dd011cda4af78 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Fri, 16 Oct 2026 15:07:36 +0100 Subject: [PATCH 013/174] Remove redundant empty-list check Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 6 +----- src/setup-codeql.ts | 8 +------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 2982b8495d..b6728397f6 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -176293,13 +176293,9 @@ async function getEnabledVersionsWithOverlayBaseDatabases(defaultCliVersion, raw return []; } const cachedVersionsSet = new Set(cachedVersions); - const overlayVersions = defaultCliVersion.enabledVersions.filter( + return defaultCliVersion.enabledVersions.filter( (v) => cachedVersionsSet.has(v.cliVersion) ); - if (overlayVersions.length === 0) { - return []; - } - return overlayVersions; } async function resolveDefaultCliVersion(defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, variant, logger2) { if (!useOverlayAwareDefaultCliVersion || variant !== "GitHub.com" /* DOTCOM */ && variant !== "GitHub Enterprise Cloud with data residency" /* GHEC_DR */ || defaultCliVersion.enabledVersions.length === 1 || !isAnalyzingPullRequest()) { diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index 6932478bc1..cece0dcd22 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -213,15 +213,9 @@ export async function getEnabledVersionsWithOverlayBaseDatabases( } const cachedVersionsSet = new Set(cachedVersions); - const overlayVersions = defaultCliVersion.enabledVersions.filter((v) => + return defaultCliVersion.enabledVersions.filter((v) => cachedVersionsSet.has(v.cliVersion), ); - - if (overlayVersions.length === 0) { - return []; - } - - return overlayVersions; } /** From 734778abbe5ad6cffe44e04de30b0746864bddfc Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Fri, 16 Oct 2026 16:13:47 +0100 Subject: [PATCH 014/174] Improve changelog note Co-authored-by: Michael B. Gale --- unreleased-change-notes/remove-trap-cache-cleanup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unreleased-change-notes/remove-trap-cache-cleanup.md b/unreleased-change-notes/remove-trap-cache-cleanup.md index f63b7bebd8..b3cb822b86 100644 --- a/unreleased-change-notes/remove-trap-cache-cleanup.md +++ b/unreleased-change-notes/remove-trap-cache-cleanup.md @@ -1 +1 @@ -- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable has been removed, as announced in CodeQL Action 4.35.2. The `analyze` Action now warns if this environment variable is set. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#4243](https://github.com/github/codeql-action/pull/4243) +- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable has been removed, as announced in the release notes for CodeQL Action 4.35.2. The `analyze` Action now warns if this environment variable is set. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#4243](https://github.com/github/codeql-action/pull/4243) From 8bb7f8f14a657f1174b107dc5608f0965226a3f0 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 16:27:51 +0100 Subject: [PATCH 015/174] Add JSDocs for `Logger` logging functions --- src/logging.ts | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/logging.ts b/src/logging.ts index ffe4e6ccee..da67168725 100644 --- a/src/logging.ts +++ b/src/logging.ts @@ -7,11 +7,47 @@ export type Loggable = string | string[]; export type LoggableError = Loggable | Error; export interface Logger { + /** + * Logs {@link message} at debug-level. + * In Actions, this will only be output if workflow debugging is enabled. + * + * @param message + * A string or an array of strings. If an array of strings is provided, they are joined using + * space as the delimiter and printed as a single line. + */ debug: (message: Loggable) => void; + /** + * Logs {@link message} at info-level. + * In Actions, this will always be output. + * + * @param message + * A string or an array of strings. If an array of strings is provided, they are joined using + * space as the delimiter and printed as a single line. + */ info: (message: Loggable) => void; + /** + * Logs {@link message} at warning-level. + * In Actions, this will always be output and highlighted as a warning. It will additionally + * result in a warning-level workflow annotation. + * + * @param message + * A string or an array of strings. If an array of strings is provided, they are joined using + * space as the delimiter and printed as a single line. + */ warning: (message: LoggableError) => void; + /** + * Logs {@link message} at error-level. + * In Actions, this will always be output and highlighted as an error. It will additionally + * result in an error-level workflow annotation. + * + * @param message + * A string or an array of strings. If an array of strings is provided, they are joined using + * space as the delimiter and printed as a single line. + */ error: (message: LoggableError) => void; - + /** + * Gets a value indicating whether debugging is enabled. + */ isDebug: () => boolean; startGroup: (name: string) => void; From 8bdea824e2d904a190430615583a0f4cde99fd51 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 18:51:35 +0100 Subject: [PATCH 016/174] Move `ConfigurationError` out of `util.ts` --- lib/entry-points.js | 6 ++++-- src/errors/index.ts | 5 +++++ src/util.ts | 8 ++------ 3 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 src/errors/index.ts diff --git a/lib/entry-points.js b/lib/entry-points.js index 1a99a44427..3d3dc758fb 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -169373,6 +169373,10 @@ var semver = __toESM(require_semver2()); var maximumVersion = "3.23"; var minimumVersion = "3.18"; +// src/errors/index.ts +var ConfigurationError = class extends Error { +}; + // src/json/index.ts function parseString(data) { return JSON.parse(data); @@ -169830,8 +169834,6 @@ var HTTPError = class extends Error { this.status = status; } }; -var ConfigurationError = class extends Error { -}; function asHTTPError(arg) { if (!isObject2(arg) || !isString(arg.message)) { return void 0; diff --git a/src/errors/index.ts b/src/errors/index.ts new file mode 100644 index 0000000000..26bb63a9c7 --- /dev/null +++ b/src/errors/index.ts @@ -0,0 +1,5 @@ +/** + * An Error class that indicates an error that occurred due to + * a misconfiguration of the action or the CodeQL CLI. + */ +export class ConfigurationError extends Error {} diff --git a/src/util.ts b/src/util.ts index 02e105d577..f12059ced0 100644 --- a/src/util.ts +++ b/src/util.ts @@ -23,11 +23,13 @@ import { getEnv, type Env, } from "./environment"; +import { ConfigurationError } from "./errors"; import * as json from "./json"; import { Language } from "./languages"; import { Logger } from "./logging"; // Re-export for backwards compatibility to avoid updating a lot of imports elsewhere. +export { ConfigurationError } from "./errors"; export { getRequiredEnvParam, getOptionalEnvVar, @@ -573,12 +575,6 @@ export class HTTPError extends Error { } } -/** - * An Error class that indicates an error that occurred due to - * a misconfiguration of the action or the CodeQL CLI. - */ -export class ConfigurationError extends Error {} - export function asHTTPError(arg: any): HTTPError | undefined { if (!json.isObject(arg) || !json.isString(arg.message)) { return undefined; From 071544a67ac93f3feb1b157904250dc7ec0c23b7 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 19:02:10 +0100 Subject: [PATCH 017/174] Move `HTTPError` out of `util.ts` --- lib/entry-points.js | 46 +++++++++++++++++++------------------- src/errors/index.ts | 30 +++++++++++++++++++++++++ src/tools-download.test.ts | 3 ++- src/util.ts | 26 +-------------------- 4 files changed, 56 insertions(+), 49 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 3d3dc758fb..89234fdf37 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -169373,10 +169373,6 @@ var semver = __toESM(require_semver2()); var maximumVersion = "3.23"; var minimumVersion = "3.18"; -// src/errors/index.ts -var ConfigurationError = class extends Error { -}; - // src/json/index.ts function parseString(data) { return JSON.parse(data); @@ -169559,6 +169555,29 @@ function checkSchema(schema, obj, options = {}, path30 = "") { return result; } +// src/errors/index.ts +var ConfigurationError = class extends Error { +}; +var HTTPError = class extends Error { + status; + constructor(message, status) { + super(message); + this.status = status; + } +}; +function asHTTPError(arg) { + if (!isObject2(arg) || !isString(arg.message)) { + return void 0; + } + if (Number.isInteger(arg.status)) { + return new HTTPError(arg.message, arg.status); + } + if (Number.isInteger(arg.httpStatusCode)) { + return new HTTPError(arg.message, arg.httpStatusCode); + } + return void 0; +} + // src/util.ts var BASE_DATABASE_OIDS_FILE_NAME = "base-database-oids.json"; var BROKEN_VERSIONS = ["0.0.0-20211207"]; @@ -169827,25 +169846,6 @@ function initializeEnvironment(version, env = getEnv()) { env.export("CODEQL_ACTION_FEATURE_WILL_UPLOAD" /* FEATURE_WILL_UPLOAD */, "true"); env.export("CODEQL_ACTION_VERSION" /* VERSION */, version); } -var HTTPError = class extends Error { - status; - constructor(message, status) { - super(message); - this.status = status; - } -}; -function asHTTPError(arg) { - if (!isObject2(arg) || !isString(arg.message)) { - return void 0; - } - if (Number.isInteger(arg.status)) { - return new HTTPError(arg.message, arg.status); - } - if (Number.isInteger(arg.httpStatusCode)) { - return new HTTPError(arg.message, arg.httpStatusCode); - } - return void 0; -} async function codeQlVersionAtLeast(codeql, requiredVersion) { return semver.gte((await codeql.getVersion()).version, requiredVersion); } diff --git a/src/errors/index.ts b/src/errors/index.ts index 26bb63a9c7..a8887c8ea0 100644 --- a/src/errors/index.ts +++ b/src/errors/index.ts @@ -1,5 +1,35 @@ +import * as json from "../json"; + /** * An Error class that indicates an error that occurred due to * a misconfiguration of the action or the CodeQL CLI. */ export class ConfigurationError extends Error {} + +/** Minimal representation of errors resulting from HTTP requests. */ +export class HTTPError extends Error { + public status: number; + + constructor(message: string, status: number) { + super(message); + this.status = status; + } +} + +/** + * Tries to convert {@link arg} to a {@link HTTPError}, but returns `undefined` if + * {@link arg} is not like a {@link HTTPError}. + */ +export function asHTTPError(arg: any): HTTPError | undefined { + if (!json.isObject(arg) || !json.isString(arg.message)) { + return undefined; + } + if (Number.isInteger(arg.status)) { + return new HTTPError(arg.message, arg.status as number); + } + // See https://github.com/actions/toolkit/blob/acb230b99a46ed33a3f04a758cd68b47b9a82908/packages/tool-cache/src/tool-cache.ts#L19 + if (Number.isInteger(arg.httpStatusCode)) { + return new HTTPError(arg.message, arg.httpStatusCode as number); + } + return undefined; +} diff --git a/src/tools-download.test.ts b/src/tools-download.test.ts index 407e2ea489..fd11c1801e 100644 --- a/src/tools-download.test.ts +++ b/src/tools-download.test.ts @@ -10,6 +10,7 @@ import { https } from "follow-redirects"; import nock from "nock"; import * as sinon from "sinon"; +import * as errors from "./errors"; import { getRunnerLogger } from "./logging"; import * as tar from "./tar"; import { setupTests } from "./testing-utils"; @@ -164,7 +165,7 @@ test.serial( test.serial( "downloadAndExtract handles an unknown status as a non-HTTP error", async (t) => { - const asHTTPError = sinon.spy(util, "asHTTPError"); + const asHTTPError = sinon.spy(errors, "asHTTPError"); await util.withTmpDir(async (tmpDir) => { sinon.stub(process, "platform").value("linux"); const archivePath = path.join(tmpDir, "codeql-bundle.tar.zst"); diff --git a/src/util.ts b/src/util.ts index f12059ced0..bff332ba3e 100644 --- a/src/util.ts +++ b/src/util.ts @@ -24,12 +24,11 @@ import { type Env, } from "./environment"; import { ConfigurationError } from "./errors"; -import * as json from "./json"; import { Language } from "./languages"; import { Logger } from "./logging"; // Re-export for backwards compatibility to avoid updating a lot of imports elsewhere. -export { ConfigurationError } from "./errors"; +export { ConfigurationError, HTTPError, asHTTPError } from "./errors"; export { getRequiredEnvParam, getOptionalEnvVar, @@ -566,29 +565,6 @@ export function initializeEnvironment(version: string, env: Env = getEnv()) { env.export(EnvVar.VERSION, version); } -export class HTTPError extends Error { - public status: number; - - constructor(message: string, status: number) { - super(message); - this.status = status; - } -} - -export function asHTTPError(arg: any): HTTPError | undefined { - if (!json.isObject(arg) || !json.isString(arg.message)) { - return undefined; - } - if (Number.isInteger(arg.status)) { - return new HTTPError(arg.message, arg.status as number); - } - // See https://github.com/actions/toolkit/blob/acb230b99a46ed33a3f04a758cd68b47b9a82908/packages/tool-cache/src/tool-cache.ts#L19 - if (Number.isInteger(arg.httpStatusCode)) { - return new HTTPError(arg.message, arg.httpStatusCode as number); - } - return undefined; -} - export async function codeQlVersionAtLeast( codeql: CodeQL, requiredVersion: string, From a76419a63223cc025c5d660e8d487ebcd7442cc8 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 21:46:16 +0100 Subject: [PATCH 018/174] Move `wrapError` and `getErrorMessage` out of `util.ts` --- lib/entry-points.js | 12 ++++++------ src/errors/index.ts | 18 ++++++++++++++++++ src/util.ts | 18 ++---------------- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 89234fdf37..c79607d1cf 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -169556,6 +169556,12 @@ function checkSchema(schema, obj, options = {}, path30 = "") { } // src/errors/index.ts +function wrapError(error3) { + return error3 instanceof Error ? error3 : new Error(String(error3)); +} +function getErrorMessage(error3) { + return error3 instanceof Error ? error3.message : String(error3); +} var ConfigurationError = class extends Error { }; var HTTPError = class extends Error { @@ -169983,12 +169989,6 @@ function parseMatrixInput(matrixInput) { ); } } -function wrapError(error3) { - return error3 instanceof Error ? error3 : new Error(String(error3)); -} -function getErrorMessage(error3) { - return error3 instanceof Error ? error3.message : String(error3); -} function prettyPrintPack(pack) { return `${pack.name}${pack.version ? `@${pack.version}` : ""}${pack.path ? `:${pack.path}` : ""}`; } diff --git a/src/errors/index.ts b/src/errors/index.ts index a8887c8ea0..b1281f3af8 100644 --- a/src/errors/index.ts +++ b/src/errors/index.ts @@ -1,5 +1,23 @@ import * as json from "../json"; +/** + * If {@link error} is not already an instance of {@link Error}, then this function constructs + * an {@link Error} with a string representation of {@link error} as the message. + */ +export function wrapError(error: unknown): Error { + return error instanceof Error ? error : new Error(String(error)); +} + +/** + * Returns an appropriate message for the error. + * + * If the error is an {@link Error} instance, this returns the error message without + * an `Error: ` prefix. + */ +export function getErrorMessage(error: unknown): string { + return error instanceof Error ? error.message : String(error); +} + /** * An Error class that indicates an error that occurred due to * a misconfiguration of the action or the CodeQL CLI. diff --git a/src/util.ts b/src/util.ts index bff332ba3e..8761cacb23 100644 --- a/src/util.ts +++ b/src/util.ts @@ -23,12 +23,12 @@ import { getEnv, type Env, } from "./environment"; -import { ConfigurationError } from "./errors"; +import { ConfigurationError, getErrorMessage, wrapError } from "./errors"; import { Language } from "./languages"; import { Logger } from "./logging"; // Re-export for backwards compatibility to avoid updating a lot of imports elsewhere. -export { ConfigurationError, HTTPError, asHTTPError } from "./errors"; +export * from "./errors"; export { getRequiredEnvParam, getOptionalEnvVar, @@ -839,20 +839,6 @@ export function parseMatrixInput( } } -export function wrapError(error: unknown): Error { - return error instanceof Error ? error : new Error(String(error)); -} - -/** - * Returns an appropriate message for the error. - * - * If the error is an `Error` instance, this returns the error message without - * an `Error: ` prefix. - */ -export function getErrorMessage(error: unknown): string { - return error instanceof Error ? error.message : String(error); -} - export function prettyPrintPack(pack: Pack) { return `${pack.name}${pack.version ? `@${pack.version}` : ""}${ pack.path ? `:${pack.path}` : "" From 929f5c0db4911649e069de2df00230b5066ad203 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 21:50:09 +0100 Subject: [PATCH 019/174] Move `isDiskConfigurationError` out of `codeql.ts` --- lib/entry-points.js | 20 ++++++++++---------- src/codeql.ts | 25 ++++--------------------- src/errors/index.ts | 20 ++++++++++++++++++++ 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index c79607d1cf..7fdec233b7 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -169562,6 +169562,16 @@ function wrapError(error3) { function getErrorMessage(error3) { return error3 instanceof Error ? error3.message : String(error3); } +function isDiskConfigurationError(e) { + if (!(e instanceof Error)) { + return false; + } + return ( + // out of disk space + e.message.includes("ENOSPC") || // access denied + e.message.includes("EACCES") + ); +} var ConfigurationError = class extends Error { }; var HTTPError = class extends Error { @@ -177004,16 +177014,6 @@ var CODEQL_NEXT_MINIMUM_VERSION = "2.21.3"; var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.17"; var GHES_MOST_RECENT_DEPRECATION_DATE = "2026-09-24"; var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; -function isDiskConfigurationError(e) { - if (!(e instanceof Error)) { - return false; - } - return ( - // out of disk space - e.message.includes("ENOSPC") || // access denied - e.message.includes("EACCES") - ); -} async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, rawLanguages, otherLanguagePacksReason, useOverlayAwareDefaultCliVersion, features, logger2, checkVersion) { try { const { diff --git a/src/codeql.ts b/src/codeql.ts index a76e29727a..706ca32106 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -19,6 +19,7 @@ import type { ActionConfig } from "./config/action-config"; import { appendExtraQueryExclusions, type Config } from "./config-utils"; import { DocUrl } from "./doc-url"; import { EnvVar, getEnv, exportEnvVar } from "./environment"; +import { getErrorMessage, isDiskConfigurationError } from "./errors"; import { CodeQLDefaultVersionInfo, Feature, @@ -34,7 +35,9 @@ import { ToolsDownloadStatusReport } from "./tools-download"; import { ToolsFeature, isSupportedToolsFeature } from "./tools-features"; import { shouldEnableIndirectTracing } from "./tracer-config"; import * as util from "./util"; -import { BuildMode, CleanupLevel, getErrorMessage } from "./util"; +import { BuildMode, CleanupLevel } from "./util"; + +export { isDiskConfigurationError } from "./errors"; type Options = Array; @@ -274,26 +277,6 @@ const GHES_MOST_RECENT_DEPRECATION_DATE = "2026-09-24"; /** The CLI verbosity level to use for extraction in debug mode. */ const EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; -/** - * Decides whether `e` is a disk-related error outside of our control - * that should be classified as a `ConfigurationError`. - * - * @param e The error to check. - * @returns True if the error should be treated as a `ConfigurationError` or false if not. - */ -export function isDiskConfigurationError(e: unknown): boolean { - if (!(e instanceof Error)) { - return false; - } - - return ( - // out of disk space - e.message.includes("ENOSPC") || - // access denied - e.message.includes("EACCES") - ); -} - /** * Set up CodeQL CLI access. * diff --git a/src/errors/index.ts b/src/errors/index.ts index b1281f3af8..24ce40d189 100644 --- a/src/errors/index.ts +++ b/src/errors/index.ts @@ -18,6 +18,26 @@ export function getErrorMessage(error: unknown): string { return error instanceof Error ? error.message : String(error); } +/** + * Decides whether `e` is a disk-related error outside of our control + * that should be classified as a `ConfigurationError`. + * + * @param e The error to check. + * @returns True if the error should be treated as a `ConfigurationError` or false if not. + */ +export function isDiskConfigurationError(e: unknown): boolean { + if (!(e instanceof Error)) { + return false; + } + + return ( + // out of disk space + e.message.includes("ENOSPC") || + // access denied + e.message.includes("EACCES") + ); +} + /** * An Error class that indicates an error that occurred due to * a misconfiguration of the action or the CodeQL CLI. From 9c72af5b2b5de7f083fe72969eda020adf36d6d6 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 19:12:19 +0100 Subject: [PATCH 020/174] Move `codeQlVersionAtLeast` out of `util.ts` and into `CodeQL` --- lib/entry-points.js | 56 +++++++++++++++++++++----------------------- src/codeql.ts | 26 ++++++++++++++++++-- src/config-utils.ts | 8 ++----- src/feature-flags.ts | 2 +- src/init-action.ts | 3 +-- src/util.ts | 7 ------ 6 files changed, 55 insertions(+), 47 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 7fdec233b7..f5cb6b25c9 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -34719,7 +34719,7 @@ var require_cacheUtils = __commonJS({ var crypto3 = __importStar2(require("crypto")); var fs32 = __importStar2(require("fs")); var path30 = __importStar2(require("path")); - var semver11 = __importStar2(require_semver3()); + var semver12 = __importStar2(require_semver3()); var util4 = __importStar2(require("util")); var constants_1 = require_constants7(); var versionSalt = "1.0"; @@ -34812,7 +34812,7 @@ var require_cacheUtils = __commonJS({ function getCompressionMethod() { return __awaiter2(this, void 0, void 0, function* () { const versionOutput = yield getVersion("zstd", ["--quiet"]); - const version = semver11.clean(versionOutput); + const version = semver12.clean(versionOutput); core29.debug(`zstd version: ${version}`); if (versionOutput === "") { return constants_1.CompressionMethod.Gzip; @@ -106361,7 +106361,7 @@ var require_manifest = __commonJS({ exports2._findMatch = _findMatch; exports2._getOsVersion = _getOsVersion; exports2._readLinuxVersionFile = _readLinuxVersionFile; - var semver11 = __importStar2(require_semver2()); + var semver12 = __importStar2(require_semver2()); var core_1 = require_core(); var os7 = require("os"); var cp = require("child_process"); @@ -106375,7 +106375,7 @@ var require_manifest = __commonJS({ for (const candidate of candidates) { const version = candidate.version; (0, core_1.debug)(`check ${version} satisfies ${versionSpec}`); - if (semver11.satisfies(version, versionSpec) && (!stable || candidate.stable === stable)) { + if (semver12.satisfies(version, versionSpec) && (!stable || candidate.stable === stable)) { file = candidate.files.find((item) => { (0, core_1.debug)(`${item.arch}===${archFilter} && ${item.platform}===${platFilter}`); let chk = item.arch === archFilter && item.platform === platFilter; @@ -106384,7 +106384,7 @@ var require_manifest = __commonJS({ if (osVersion === item.platform_version) { chk = true; } else { - chk = semver11.satisfies(osVersion, item.platform_version); + chk = semver12.satisfies(osVersion, item.platform_version); } } return chk; @@ -106644,7 +106644,7 @@ var require_tool_cache = __commonJS({ var os7 = __importStar2(require("os")); var path30 = __importStar2(require("path")); var httpm = __importStar2(require_lib()); - var semver11 = __importStar2(require_semver2()); + var semver12 = __importStar2(require_semver2()); var stream2 = __importStar2(require("stream")); var util4 = __importStar2(require("util")); var assert_1 = require("assert"); @@ -106917,7 +106917,7 @@ var require_tool_cache = __commonJS({ } function cacheDir2(sourceDir, tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { - version = semver11.clean(version) || version; + version = semver12.clean(version) || version; arch2 = arch2 || os7.arch(); core29.debug(`Caching tool ${tool} ${version} ${arch2}`); core29.debug(`source dir: ${sourceDir}`); @@ -106935,7 +106935,7 @@ var require_tool_cache = __commonJS({ } function cacheFile(sourceFile, targetFile, tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { - version = semver11.clean(version) || version; + version = semver12.clean(version) || version; arch2 = arch2 || os7.arch(); core29.debug(`Caching tool ${tool} ${version} ${arch2}`); core29.debug(`source file: ${sourceFile}`); @@ -106965,7 +106965,7 @@ var require_tool_cache = __commonJS({ } let toolPath = ""; if (versionSpec) { - versionSpec = semver11.clean(versionSpec) || ""; + versionSpec = semver12.clean(versionSpec) || ""; const cachePath = path30.join(_getCacheDirectory(), toolName, versionSpec, arch2); core29.debug(`checking cache: ${cachePath}`); if (fs32.existsSync(cachePath) && fs32.existsSync(`${cachePath}.complete`)) { @@ -107045,7 +107045,7 @@ var require_tool_cache = __commonJS({ } function _createToolPath(tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { - const folderPath = path30.join(_getCacheDirectory(), tool, semver11.clean(version) || version, arch2 || ""); + const folderPath = path30.join(_getCacheDirectory(), tool, semver12.clean(version) || version, arch2 || ""); core29.debug(`destination ${folderPath}`); const markerPath = `${folderPath}.complete`; yield io9.rmRF(folderPath); @@ -107055,15 +107055,15 @@ var require_tool_cache = __commonJS({ }); } function _completeToolPath(tool, version, arch2) { - const folderPath = path30.join(_getCacheDirectory(), tool, semver11.clean(version) || version, arch2 || ""); + const folderPath = path30.join(_getCacheDirectory(), tool, semver12.clean(version) || version, arch2 || ""); const markerPath = `${folderPath}.complete`; fs32.writeFileSync(markerPath, ""); core29.debug("finished caching tool"); } function isExplicitVersion(versionSpec) { - const c = semver11.clean(versionSpec) || ""; + const c = semver12.clean(versionSpec) || ""; core29.debug(`isExplicit: ${c}`); - const valid4 = semver11.valid(c) != null; + const valid4 = semver12.valid(c) != null; core29.debug(`explicit? ${valid4}`); return valid4; } @@ -107071,14 +107071,14 @@ var require_tool_cache = __commonJS({ let version = ""; core29.debug(`evaluating ${versions.length} versions`); versions = versions.sort((a, b) => { - if (semver11.gt(a, b)) { + if (semver12.gt(a, b)) { return 1; } return -1; }); for (let i = versions.length - 1; i >= 0; i--) { const potential = versions[i]; - const satisfied = semver11.satisfies(potential, versionSpec); + const satisfied = semver12.satisfies(potential, versionSpec); if (satisfied) { version = potential; break; @@ -169862,9 +169862,6 @@ function initializeEnvironment(version, env = getEnv()) { env.export("CODEQL_ACTION_FEATURE_WILL_UPLOAD" /* FEATURE_WILL_UPLOAD */, "true"); env.export("CODEQL_ACTION_VERSION" /* VERSION */, version); } -async function codeQlVersionAtLeast(codeql, requiredVersion) { - return semver.gte((await codeql.getVersion()).version, requiredVersion); -} function getBaseDatabaseOidsFilePath(config) { return path.join(config.dbLocation, BASE_DATABASE_OIDS_FILE_NAME); } @@ -172262,7 +172259,7 @@ var OfflineFeatures = class { } const minimumVersion2 = config.minimumVersion; if (codeql && minimumVersion2) { - if (!await codeQlVersionAtLeast(codeql, minimumVersion2)) { + if (!await codeql.isVersionAtLeast(minimumVersion2)) { this.logger.debug( `Feature ${feature} is disabled because the CodeQL CLI version is older than the minimum version ${minimumVersion2}.` ); @@ -172685,6 +172682,7 @@ var fs16 = __toESM(require("fs")); var path15 = __toESM(require("path")); var core12 = __toESM(require_core()); var toolrunner3 = __toESM(require_toolrunner()); +var semver10 = __toESM(require_semver2()); // src/cli-errors.ts var SUPPORTED_PLATFORMS = [ @@ -174673,10 +174671,7 @@ function runnerHasSufficientDiskSpace(diskUsage, logger2, minimumDiskSpaceMb) { return true; } async function runnerHasSufficientMemory(codeql, ramInput, logger2) { - if (await codeQlVersionAtLeast( - codeql, - CODEQL_VERSION_REDUCED_OVERLAY_MEMORY_USAGE - )) { + if (await codeql.isVersionAtLeast(CODEQL_VERSION_REDUCED_OVERLAY_MEMORY_USAGE)) { logger2.debug( `Skipping memory check for overlay analysis because CodeQL version is at least ${CODEQL_VERSION_REDUCED_OVERLAY_MEMORY_USAGE}.` ); @@ -174814,7 +174809,7 @@ async function validateOverlayDatabaseMode(overlayDatabaseMode, useOverlayDataba ); return new Failure("incompatible-build-mode" /* IncompatibleBuildMode */); } - if (!await codeQlVersionAtLeast(codeql, CODEQL_OVERLAY_MINIMUM_VERSION)) { + if (!await codeql.isVersionAtLeast(CODEQL_OVERLAY_MINIMUM_VERSION)) { logger2.warning( `Cannot build an ${overlayDatabaseMode} database because the CodeQL CLI is older than ${CODEQL_OVERLAY_MINIMUM_VERSION}. Falling back to creating a normal full database instead.` ); @@ -177088,6 +177083,9 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion) { } return result; }, + async isVersionAtLeast(requiredVersion) { + return semver10.gte((await this.getVersion()).version, requiredVersion); + }, async printVersion() { core12.info(JSON.stringify(await this.getVersion(), null, 2)); }, @@ -177476,11 +177474,11 @@ Output was: ${extractorPath}` await runCli(cmd, args); } }; - if (checkVersion && !await codeQlVersionAtLeast(codeql, CODEQL_MINIMUM_VERSION)) { + if (checkVersion && !await codeql.isVersionAtLeast(CODEQL_MINIMUM_VERSION)) { throw new ConfigurationError( `Expected a CodeQL CLI with version at least ${CODEQL_MINIMUM_VERSION} but got version ${(await codeql.getVersion()).version}` ); - } else if (checkVersion && process.env["CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */] !== "true" && !await codeQlVersionAtLeast(codeql, CODEQL_NEXT_MINIMUM_VERSION)) { + } else if (checkVersion && process.env["CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */] !== "true" && !await codeql.isVersionAtLeast(CODEQL_NEXT_MINIMUM_VERSION)) { const result = await codeql.getVersion(); core12.warning( `CodeQL CLI version ${result.version} was discontinued on ${GHES_MOST_RECENT_DEPRECATION_DATE} alongside GitHub Enterprise Server ${GHES_VERSION_MOST_RECENTLY_DEPRECATED} and will not be supported by the next minor release of the CodeQL Action. Please update to CodeQL CLI version ${CODEQL_NEXT_MINIMUM_VERSION} or later. For instance, if you have specified a custom version of the CLI using the 'tools' input to the 'init' Action, you can remove this input to use the default version. @@ -186038,7 +186036,7 @@ var fs29 = __toESM(require("fs")); var path25 = __toESM(require("path")); var core19 = __toESM(require_core()); var io7 = __toESM(require_io()); -var semver10 = __toESM(require_semver2()); +var semver11 = __toESM(require_semver2()); // src/config/inputs.ts async function getToolsInput(action, repositoryProperties) { @@ -186548,7 +186546,7 @@ async function run3(actionState) { ) { const publicPreview = "2.22.1"; const actualVer = (await codeql.getVersion()).version; - if (semver10.lt(actualVer, publicPreview)) { + if (semver11.lt(actualVer, publicPreview)) { actionState.env.export("CODEQL_ENABLE_EXPERIMENTAL_FEATURES" /* EXPERIMENTAL_FEATURES */, "true"); logger2.info("Experimental Rust analysis enabled"); } @@ -186781,7 +186779,7 @@ exec ${goBinaryPath} "$@"` logger2.debug( `${"CODEQL_EXTRACTOR_JAVA_OPTION_MINIMIZE_DEPENDENCY_JARS" /* JAVA_EXTRACTOR_MINIMIZE_DEPENDENCY_JARS */} is already set to '${process.env["CODEQL_EXTRACTOR_JAVA_OPTION_MINIMIZE_DEPENDENCY_JARS" /* JAVA_EXTRACTOR_MINIMIZE_DEPENDENCY_JARS */]}', so the Action will not override it.` ); - } else if (await codeQlVersionAtLeast(codeql, CODEQL_VERSION_JAR_MINIMIZATION) && config.dependencyCachingEnabled && config.buildMode === "none" /* None */ && config.languages.includes("java" /* java */)) { + } else if (await codeql.isVersionAtLeast(CODEQL_VERSION_JAR_MINIMIZATION) && config.dependencyCachingEnabled && config.buildMode === "none" /* None */ && config.languages.includes("java" /* java */)) { actionState.env.export( "CODEQL_EXTRACTOR_JAVA_OPTION_MINIMIZE_DEPENDENCY_JARS" /* JAVA_EXTRACTOR_MINIMIZE_DEPENDENCY_JARS */, "true" diff --git a/src/codeql.ts b/src/codeql.ts index 706ca32106..07153a7499 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -4,6 +4,7 @@ import * as path from "path"; import * as core from "@actions/core"; import * as toolrunner from "@actions/exec/lib/toolrunner"; import * as yaml from "js-yaml"; +import * as semver from "semver"; import { CommandInvocationError, @@ -73,6 +74,11 @@ export interface CodeQL { * Get a string containing the semver version of the CodeQL executable. */ getVersion(): Promise; + /** + * Determines whether the CLI installation represented by this {@link CodeQL} instance + * has at least the {@link requiredVersion}. + */ + isVersionAtLeast(requiredVersion: string): Promise; /** * Print version information about CodeQL. */ @@ -414,6 +420,19 @@ export function createStubCodeQL(partialCodeql: Partial): CodeQL { getVersion: resolveFunction(partialCodeql, "getVersion", async () => ({ version: "1.0.0", })), + isVersionAtLeast: resolveFunction( + partialCodeql, + "codeQlVersionAtLeast", + async (requiredVersion) => { + return ( + !!partialCodeql.getVersion && + semver.gte( + (await partialCodeql.getVersion()).version, + requiredVersion, + ) + ); + }, + ), printVersion: resolveFunction(partialCodeql, "printVersion"), supportsFeature: resolveFunction( partialCodeql, @@ -517,6 +536,9 @@ async function getCodeQLForCmd( } return result; }, + async isVersionAtLeast(requiredVersion: string) { + return semver.gte((await this.getVersion()).version, requiredVersion); + }, async printVersion() { // Reuse the cached version information rather than invoking the CLI again. core.info(JSON.stringify(await this.getVersion(), null, 2)); @@ -1011,7 +1033,7 @@ async function getCodeQLForCmd( // CodeQL object is created. if ( checkVersion && - !(await util.codeQlVersionAtLeast(codeql, CODEQL_MINIMUM_VERSION)) + !(await codeql.isVersionAtLeast(CODEQL_MINIMUM_VERSION)) ) { throw new util.ConfigurationError( `Expected a CodeQL CLI with version at least ${CODEQL_MINIMUM_VERSION} but got version ${ @@ -1021,7 +1043,7 @@ async function getCodeQLForCmd( } else if ( checkVersion && process.env[EnvVar.SUPPRESS_DEPRECATED_SOON_WARNING] !== "true" && - !(await util.codeQlVersionAtLeast(codeql, CODEQL_NEXT_MINIMUM_VERSION)) + !(await codeql.isVersionAtLeast(CODEQL_NEXT_MINIMUM_VERSION)) ) { const result = await codeql.getVersion(); core.warning( diff --git a/src/config-utils.ts b/src/config-utils.ts index de506aac05..5c2a89776d 100644 --- a/src/config-utils.ts +++ b/src/config-utils.ts @@ -82,7 +82,6 @@ import { GitHubVersion, ConfigurationError, BuildMode, - codeQlVersionAtLeast, cloneObject, isDefined, checkDiskUsage, @@ -652,10 +651,7 @@ async function runnerHasSufficientMemory( logger: Logger, ): Promise { if ( - await codeQlVersionAtLeast( - codeql, - CODEQL_VERSION_REDUCED_OVERLAY_MEMORY_USAGE, - ) + await codeql.isVersionAtLeast(CODEQL_VERSION_REDUCED_OVERLAY_MEMORY_USAGE) ) { logger.debug( `Skipping memory check for overlay analysis because CodeQL version is at least ${CODEQL_VERSION_REDUCED_OVERLAY_MEMORY_USAGE}.`, @@ -899,7 +895,7 @@ async function validateOverlayDatabaseMode( ); return new Failure(OverlayDisabledReason.IncompatibleBuildMode); } - if (!(await codeQlVersionAtLeast(codeql, CODEQL_OVERLAY_MINIMUM_VERSION))) { + if (!(await codeql.isVersionAtLeast(CODEQL_OVERLAY_MINIMUM_VERSION))) { logger.warning( `Cannot build an ${overlayDatabaseMode} database because ` + `the CodeQL CLI is older than ${CODEQL_OVERLAY_MINIMUM_VERSION}. ` + diff --git a/src/feature-flags.ts b/src/feature-flags.ts index 5cf7c7414c..e64b69eabe 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -589,7 +589,7 @@ class OfflineFeatures implements FeatureEnablement { // Never use this feature if the CLI version explicitly can't support it. const minimumVersion = config.minimumVersion; if (codeql && minimumVersion) { - if (!(await util.codeQlVersionAtLeast(codeql, minimumVersion))) { + if (!(await codeql.isVersionAtLeast(minimumVersion))) { this.logger.debug( `Feature ${feature} is disabled because the CodeQL CLI version is older than the minimum ` + `version ${minimumVersion}.`, diff --git a/src/init-action.ts b/src/init-action.ts index f58d4ccca7..7f9178304c 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -88,7 +88,6 @@ import { checkDiskUsage, checkForTimeout, checkGitHubVersionInRange, - codeQlVersionAtLeast, DEFAULT_DEBUG_ARTIFACT_NAME, DEFAULT_DEBUG_DATABASE_NAME, getCodeQLMemoryLimit, @@ -686,7 +685,7 @@ async function run( `${EnvVar.JAVA_EXTRACTOR_MINIMIZE_DEPENDENCY_JARS} is already set to '${process.env[EnvVar.JAVA_EXTRACTOR_MINIMIZE_DEPENDENCY_JARS]}', so the Action will not override it.`, ); } else if ( - (await codeQlVersionAtLeast(codeql, CODEQL_VERSION_JAR_MINIMIZATION)) && + (await codeql.isVersionAtLeast(CODEQL_VERSION_JAR_MINIMIZATION)) && config.dependencyCachingEnabled && config.buildMode === BuildMode.None && config.languages.includes(BuiltInLanguage.java) diff --git a/src/util.ts b/src/util.ts index 8761cacb23..19fbc4368b 100644 --- a/src/util.ts +++ b/src/util.ts @@ -565,13 +565,6 @@ export function initializeEnvironment(version: string, env: Env = getEnv()) { env.export(EnvVar.VERSION, version); } -export async function codeQlVersionAtLeast( - codeql: CodeQL, - requiredVersion: string, -): Promise { - return semver.gte((await codeql.getVersion()).version, requiredVersion); -} - export function getBaseDatabaseOidsFilePath( config: ActionConfig<"dbLocation">, ): string { From 86bc4448d3cac2bb3a975703685964f56bd3d48c Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 21:52:19 +0100 Subject: [PATCH 021/174] Mark additional imports in `util.ts` as `type`-only --- src/util.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util.ts b/src/util.ts index 19fbc4368b..d1729acdc1 100644 --- a/src/util.ts +++ b/src/util.ts @@ -24,8 +24,8 @@ import { type Env, } from "./environment"; import { ConfigurationError, getErrorMessage, wrapError } from "./errors"; -import { Language } from "./languages"; -import { Logger } from "./logging"; +import type { Language } from "./languages"; +import type { Logger } from "./logging"; // Re-export for backwards compatibility to avoid updating a lot of imports elsewhere. export * from "./errors"; From 02283e954255a3bcc4667da340f00d031edeba00 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 18:55:59 +0100 Subject: [PATCH 022/174] Move more GitHub-related definitions from `util.ts` to `github.ts` --- lib/entry-points.js | 104 ++++++++++++++++++++++---------------------- src/github.ts | 16 ++++++- src/util.ts | 16 +------ 3 files changed, 69 insertions(+), 67 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index f5cb6b25c9..841bb36a12 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -42967,11 +42967,11 @@ var require_tracingPolicy = __commonJS({ var import_log = require_log3(); var import_core_util = require_commonjs4(); var import_restError = require_restError3(); - var import_util59 = require_internal3(); + var import_util58 = require_internal3(); var tracingPolicyName2 = "tracingPolicy"; function tracingPolicy2(options = {}) { const userAgentPromise = (0, import_userAgent.getUserAgentValue)(options.userAgentPrefix); - const sanitizer = new import_util59.Sanitizer({ + const sanitizer = new import_util58.Sanitizer({ additionalAllowedQueryParameters: options.additionalAllowedQueryParameters }); const tracingClient = tryCreateTracingClient(); @@ -46597,11 +46597,11 @@ var require_response2 = __commonJS({ }); module2.exports = __toCommonJS2(response_exports); var import_core_rest_pipeline = require_commonjs6(); - var import_util59 = require_util9(); + var import_util58 = require_util9(); var originalResponse = /* @__PURE__ */ Symbol("Original FullOperationResponse"); function toCompatResponse2(response, options) { - let request3 = (0, import_util59.toWebResourceLike)(response.request); - let headers = (0, import_util59.toHttpHeadersLike)(response.headers); + let request3 = (0, import_util58.toWebResourceLike)(response.request); + let headers = (0, import_util58.toHttpHeadersLike)(response.headers); if (options?.createProxy) { return new Proxy(response, { get(target, prop, receiver) { @@ -46642,7 +46642,7 @@ var require_response2 = __commonJS({ return { ...compatResponse, headers, - request: (0, import_util59.toPipelineRequest)(compatResponse.request) + request: (0, import_util58.toPipelineRequest)(compatResponse.request) }; } } @@ -46749,7 +46749,7 @@ var require_requestPolicyFactoryPolicy = __commonJS({ requestPolicyFactoryPolicyName: () => requestPolicyFactoryPolicyName2 }); module2.exports = __toCommonJS2(requestPolicyFactoryPolicy_exports); - var import_util59 = require_util9(); + var import_util58 = require_util9(); var import_response = require_response2(); var HttpPipelineLogLevel2 = /* @__PURE__ */ ((HttpPipelineLogLevel22) => { HttpPipelineLogLevel22[HttpPipelineLogLevel22["ERROR"] = 1] = "ERROR"; @@ -46773,14 +46773,14 @@ var require_requestPolicyFactoryPolicy = __commonJS({ async sendRequest(request3, next) { let httpPipeline = { async sendRequest(httpRequest) { - const response2 = await next((0, import_util59.toPipelineRequest)(httpRequest)); + const response2 = await next((0, import_util58.toPipelineRequest)(httpRequest)); return (0, import_response.toCompatResponse)(response2, { createProxy: true }); } }; for (const factory of orderedFactories) { httpPipeline = factory.create(httpPipeline, mockRequestPolicyOptions); } - const webResourceLike = (0, import_util59.toWebResourceLike)(request3, { createProxy: true }); + const webResourceLike = (0, import_util58.toWebResourceLike)(request3, { createProxy: true }); const response = await httpPipeline.sendRequest(webResourceLike); return (0, import_response.toPipelineResponse)(response); } @@ -46815,12 +46815,12 @@ var require_httpClientAdapter = __commonJS({ }); module2.exports = __toCommonJS2(httpClientAdapter_exports); var import_response = require_response2(); - var import_util59 = require_util9(); + var import_util58 = require_util9(); function convertHttpClient2(requestPolicyClient) { return { sendRequest: async (request3) => { const response = await requestPolicyClient.sendRequest( - (0, import_util59.toWebResourceLike)(request3, { createProxy: true }) + (0, import_util58.toWebResourceLike)(request3, { createProxy: true }) ); return (0, import_response.toPipelineResponse)(response); } @@ -46858,7 +46858,7 @@ var require_commonjs9 = __commonJS({ disableKeepAlivePolicyName: () => import_disableKeepAlivePolicy.disableKeepAlivePolicyName, requestPolicyFactoryPolicyName: () => import_requestPolicyFactoryPolicy.requestPolicyFactoryPolicyName, toCompatResponse: () => import_response.toCompatResponse, - toHttpHeadersLike: () => import_util59.toHttpHeadersLike + toHttpHeadersLike: () => import_util58.toHttpHeadersLike }); module2.exports = __toCommonJS2(src_exports); var import_extendedClient = require_extendedClient(); @@ -46866,7 +46866,7 @@ var require_commonjs9 = __commonJS({ var import_requestPolicyFactoryPolicy = require_requestPolicyFactoryPolicy(); var import_disableKeepAlivePolicy = require_disableKeepAlivePolicy(); var import_httpClientAdapter = require_httpClientAdapter(); - var import_util59 = require_util9(); + var import_util58 = require_util9(); } }); @@ -169594,6 +169594,43 @@ function asHTTPError(arg) { return void 0; } +// src/github.ts +var GITHUB_DOTCOM_URL = "https://github.com"; +function parseGitHubUrl(inputUrl) { + const originalUrl = inputUrl; + if (inputUrl.indexOf("://") === -1) { + inputUrl = `https://${inputUrl}`; + } + if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) { + throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`); + } + let url2; + try { + url2 = new URL(inputUrl); + } catch { + throw new ConfigurationError(`"${originalUrl}" is not a valid URL`); + } + if (url2.hostname === "github.com" || url2.hostname === "api.github.com") { + return GITHUB_DOTCOM_URL; + } + if (url2.pathname.indexOf("/api/v3") !== -1) { + url2.pathname = url2.pathname.substring(0, url2.pathname.indexOf("/api/v3")); + } + if (url2.hostname.startsWith("api.")) { + url2.hostname = url2.hostname.substring(4); + } + if (!url2.pathname.endsWith("/")) { + url2.pathname = `${url2.pathname}/`; + } + return url2.toString(); +} +function getCurrentInstance(env) { + return { + url: env.getRequired("GITHUB_SERVER_URL" /* GITHUB_SERVER_URL */), + apiURL: env.getRequired("GITHUB_API_URL" /* GITHUB_API_URL */) + }; +} + // src/util.ts var BASE_DATABASE_OIDS_FILE_NAME = "base-database-oids.json"; var BROKEN_VERSIONS = ["0.0.0-20211207"]; @@ -170639,43 +170676,6 @@ retry.VERSION = VERSION7; // src/api-client.ts var import_undici = __toESM(require_undici()); -// src/github.ts -var GITHUB_DOTCOM_URL = "https://github.com"; -function parseGitHubUrl(inputUrl) { - const originalUrl = inputUrl; - if (inputUrl.indexOf("://") === -1) { - inputUrl = `https://${inputUrl}`; - } - if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) { - throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`); - } - let url2; - try { - url2 = new URL(inputUrl); - } catch { - throw new ConfigurationError(`"${originalUrl}" is not a valid URL`); - } - if (url2.hostname === "github.com" || url2.hostname === "api.github.com") { - return GITHUB_DOTCOM_URL; - } - if (url2.pathname.indexOf("/api/v3") !== -1) { - url2.pathname = url2.pathname.substring(0, url2.pathname.indexOf("/api/v3")); - } - if (url2.hostname.startsWith("api.")) { - url2.hostname = url2.hostname.substring(4); - } - if (!url2.pathname.endsWith("/")) { - url2.pathname = `${url2.pathname}/`; - } - return url2.toString(); -} -function getCurrentInstance(env) { - return { - url: env.getRequired("GITHUB_SERVER_URL" /* GITHUB_SERVER_URL */), - apiURL: env.getRequired("GITHUB_API_URL" /* GITHUB_API_URL */) - }; -} - // src/repository.ts function isRepositoryNwoStr(val) { return val.includes("/"); @@ -183090,7 +183090,7 @@ var import_async = __toESM(require_async(), 1); var import_path7 = require("path"); // node_modules/archiver/lib/error.js -var import_util37 = __toESM(require("util"), 1); +var import_util36 = __toESM(require("util"), 1); var ERROR_CODES = { ABORTED: "archive was aborted", DIRECTORYDIRPATHREQUIRED: "diretory dirpath argument must be a non-empty string value", @@ -183115,7 +183115,7 @@ function ArchiverError(code, data) { this.code = code; this.data = data; } -import_util37.default.inherits(ArchiverError, Error); +import_util36.default.inherits(ArchiverError, Error); // node_modules/archiver/lib/core.js var import_readable_stream2 = __toESM(require_ours(), 1); diff --git a/src/github.ts b/src/github.ts index 6350fb3f30..e39cddfb05 100644 --- a/src/github.ts +++ b/src/github.ts @@ -1,5 +1,19 @@ import { ActionsEnvVars, type ReadOnlyEnv } from "./environment"; -import { ConfigurationError } from "./util"; +import { ConfigurationError } from "./errors"; + +export enum GitHubVariant { + /** [GitHub.com](https://github.com) */ + DOTCOM = "GitHub.com", + /** [GitHub Enterprise Server](https://docs.github.com/en/enterprise-server@latest/admin/overview/about-github-enterprise-server) */ + GHES = "GitHub Enterprise Server", + /** [GitHub Enterprise Cloud with data residency](https://docs.github.com/en/enterprise-cloud@latest/admin/data-residency/about-github-enterprise-cloud-with-data-residency) */ + GHEC_DR = "GitHub Enterprise Cloud with data residency", +} + +export type GitHubVersion = + | { type: GitHubVariant.DOTCOM } + | { type: GitHubVariant.GHEC_DR } + | { type: GitHubVariant.GHES; version: string }; /** A string representing a GitHub instance address. */ export type InstanceURL = string; diff --git a/src/util.ts b/src/util.ts index d1729acdc1..032c158f45 100644 --- a/src/util.ts +++ b/src/util.ts @@ -24,6 +24,7 @@ import { type Env, } from "./environment"; import { ConfigurationError, getErrorMessage, wrapError } from "./errors"; +import { GitHubVariant, type GitHubVersion } from "./github"; import type { Language } from "./languages"; import type { Logger } from "./logging"; @@ -35,6 +36,7 @@ export { getEnv, isInTestMode, } from "./environment"; +export { GitHubVariant, type GitHubVersion } from "./github"; /** * The name of the file containing the base database OIDs, as stored in the @@ -471,20 +473,6 @@ const CODEQL_ACTION_WARNED_ABOUT_VERSION_ENV_VAR = let hasBeenWarnedAboutVersion = false; -export enum GitHubVariant { - /** [GitHub.com](https://github.com) */ - DOTCOM = "GitHub.com", - /** [GitHub Enterprise Server](https://docs.github.com/en/enterprise-server@latest/admin/overview/about-github-enterprise-server) */ - GHES = "GitHub Enterprise Server", - /** [GitHub Enterprise Cloud with data residency](https://docs.github.com/en/enterprise-cloud@latest/admin/data-residency/about-github-enterprise-cloud-with-data-residency) */ - GHEC_DR = "GitHub Enterprise Cloud with data residency", -} - -export type GitHubVersion = - | { type: GitHubVariant.DOTCOM } - | { type: GitHubVariant.GHEC_DR } - | { type: GitHubVariant.GHES; version: string }; - export function checkGitHubVersionInRange( version: GitHubVersion, logger: Logger, From dc2ed81cc7467eab39dd4658e8047f18c8048bf2 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 22:04:05 +0100 Subject: [PATCH 023/174] Remove `InstanceURL` from `util.ts` --- src/setup/repository.ts | 3 +-- src/util.ts | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/setup/repository.ts b/src/setup/repository.ts index 341a278755..ff02a1560b 100644 --- a/src/setup/repository.ts +++ b/src/setup/repository.ts @@ -2,13 +2,12 @@ import { ActionState } from "../action-common"; import { isRunningLocalAction } from "../actions-util"; import * as api from "../api-client"; import { ActionsEnvVars } from "../environment"; -import { GITHUB_DOTCOM_URL } from "../github"; +import { GITHUB_DOTCOM_URL, type InstanceURL } from "../github"; import { isRepositoryNwoStr, parseRepositoryNwo, type RepositoryNwoStr, } from "../repository"; -import { type InstanceURL } from "../util"; /** The NWO of the standard CodeQL Action repository. */ export const CODEQL_DEFAULT_ACTION_REPOSITORY = "github/codeql-action"; diff --git a/src/util.ts b/src/util.ts index 032c158f45..7ba59c6751 100644 --- a/src/util.ts +++ b/src/util.ts @@ -50,9 +50,6 @@ const BASE_DATABASE_OIDS_FILE_NAME = "base-database-oids.json"; */ const BROKEN_VERSIONS = ["0.0.0-20211207"]; -/** A string representing a GitHub instance. */ -export type InstanceURL = string; - /** * Default name of the debugging artifact. */ From 297dec926f76a5869199314e02c7a0b346913007 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 20 Oct 2026 13:48:22 +0100 Subject: [PATCH 024/174] Add `toolcache.ts` script for `bundle-toolcache.yml` --- .github/workflows/__bundle-toolcache.yml | 52 ++++++------- pr-checks/checks/bundle-toolcache.yml | 44 ++++------- pr-checks/toolcache.ts | 94 ++++++++++++++++++++++++ 3 files changed, 130 insertions(+), 60 deletions(-) create mode 100755 pr-checks/toolcache.ts diff --git a/.github/workflows/__bundle-toolcache.yml b/.github/workflows/__bundle-toolcache.yml index 0055f94705..96a901cf34 100644 --- a/.github/workflows/__bundle-toolcache.yml +++ b/.github/workflows/__bundle-toolcache.yml @@ -50,6 +50,15 @@ jobs: steps: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Install Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: 20.x + cache: npm + - name: Install newer npm + run: npm install -g npm@11.19.1 + - name: Install dependencies + run: npm ci - name: Prepare test id: prepare-test uses: ./.github/actions/prepare-test @@ -58,47 +67,30 @@ jobs: use-all-platform-bundle: 'false' setup-kotlin: 'true' - name: Remove CodeQL from toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const fs = require('fs'); - const path = require('path'); - const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL'); - fs.rmdirSync(codeqlPath, { recursive: true }); - - name: Install @actions/tool-cache - run: npm install @actions/tool-cache@3 + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts clear + - name: Check toolcache does not contain CodeQL - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - if (allCodeqlVersions.length !== 0) { - throw new Error(`CodeQL should not be found in the toolcache, but found ${allCodeqlVersions}`); - } - console.log('No versions of CodeQL found in the toolcache'); + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts absent + - id: init uses: ./../action/init with: # Request multiple languages so this check uses the combined bundle. languages: javascript,python tools: ${{ steps.prepare-test.outputs.tools-url }} + - uses: ./../action/analyze with: output: ${{ runner.temp }}/results upload-database: false + - name: Check CodeQL is installed within the toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - console.log(`Found CodeQL versions: ${allCodeqlVersions}`); - if (allCodeqlVersions.length === 0) { - throw new Error('CodeQL not found in toolcache'); - } - if (allCodeqlVersions.length > 1) { - throw new Error('Multiple CodeQL versions found in toolcache'); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed -n 1 env: CODEQL_ACTION_TEST_MODE: true diff --git a/pr-checks/checks/bundle-toolcache.yml b/pr-checks/checks/bundle-toolcache.yml index f74c6af75c..3317a45f40 100644 --- a/pr-checks/checks/bundle-toolcache.yml +++ b/pr-checks/checks/bundle-toolcache.yml @@ -6,47 +6,31 @@ operatingSystems: - ubuntu - macos - windows +installNode: true steps: - name: Remove CodeQL from toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const fs = require('fs'); - const path = require('path'); - const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL'); - fs.rmdirSync(codeqlPath, { recursive: true }); - - name: Install @actions/tool-cache - run: npm install @actions/tool-cache@3 + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts clear + - name: Check toolcache does not contain CodeQL - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - if (allCodeqlVersions.length !== 0) { - throw new Error(`CodeQL should not be found in the toolcache, but found ${allCodeqlVersions}`); - } - console.log('No versions of CodeQL found in the toolcache'); + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts absent + - id: init uses: ./../action/init with: # Request multiple languages so this check uses the combined bundle. languages: javascript,python tools: ${{ steps.prepare-test.outputs.tools-url }} + - uses: ./../action/analyze with: output: ${{ runner.temp }}/results upload-database: false + - name: Check CodeQL is installed within the toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - console.log(`Found CodeQL versions: ${allCodeqlVersions}`); - if (allCodeqlVersions.length === 0) { - throw new Error('CodeQL not found in toolcache'); - } - if (allCodeqlVersions.length > 1) { - throw new Error('Multiple CodeQL versions found in toolcache'); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed -n 1 diff --git a/pr-checks/toolcache.ts b/pr-checks/toolcache.ts new file mode 100755 index 0000000000..a14605e38e --- /dev/null +++ b/pr-checks/toolcache.ts @@ -0,0 +1,94 @@ +#!/usr/bin/env npx tsx + +/** + * Provides utility commands for working with the Actions toolcache in PR checks. + */ + +import fs from "fs"; +import { parseArgs } from "node:util"; +import path from "path"; + +import * as core from "@actions/core"; +import * as toolcache from "@actions/tool-cache"; + +function removeCodeQLFromToolcache() { + const toolcachePath = process.env["RUNNER_TOOL_CACHE"]; + + if (toolcachePath === undefined) { + throw new Error("Expected RUNNER_TOOL_CACHE to be defined"); + } + + const codeqlPath = path.join(toolcachePath, "CodeQL"); + fs.rmdirSync(codeqlPath, { recursive: true }); + + core.info(`Removed '${codeqlPath}' from the toolcache.`); +} + +function findCodeQL() { + return toolcache.findAllVersions("CodeQL"); +} + +function noCodeQLInToolcache() { + const allCodeqlVersions = findCodeQL(); + if (allCodeqlVersions.length !== 0) { + throw new Error( + `CodeQL should not be found in the toolcache, but found ${allCodeqlVersions}`, + ); + } + core.info("No versions of CodeQL found in the toolcache"); +} + +function hasCodeQLInToolcache(expectedNumber?: string) { + const expected = + expectedNumber !== undefined + ? Number.parseInt(expectedNumber, 10) + : undefined; + + const allCodeqlVersions = findCodeQL(); + core.info(`Found CodeQL versions: ${allCodeqlVersions}`); + + if (allCodeqlVersions.length === 0) { + throw new Error("CodeQL not found in toolcache"); + } + if (expected !== undefined && allCodeqlVersions.length > expected) { + throw new Error( + `Expected ${expected} versions of CodeQL in the toolcache, but found ${allCodeqlVersions.length}`, + ); + } +} + +function main() { + const { positionals, values } = parseArgs({ + options: { + // The *number* of expected versions in the toolcache. + expectedVersions: { type: "string", short: "n" }, + }, + allowPositionals: true, + }); + + if (positionals.length < 1) { + throw new Error("Command not specified."); + } + + const cmd = positionals[0]; + + switch (cmd.trim().toLowerCase()) { + case "clear": + removeCodeQLFromToolcache(); + return; + case "absent": + noCodeQLInToolcache(); + return; + case "installed": + hasCodeQLInToolcache(values.expectedVersions); + return; + default: + throw new Error(`Unknown command '${cmd}'.`); + } +} + +try { + main(); +} catch (err) { + core.setFailed(err instanceof Error ? err.message : String(err)); +} From 24408cc688e9f8de459b9077a0990a6762587831 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 20 Oct 2026 13:49:30 +0100 Subject: [PATCH 025/174] Use `toolcache.ts` in `bundle-from-toolcache.yml` --- .github/workflows/__bundle-from-toolcache.yml | 36 +++++++++---------- pr-checks/checks/bundle-from-toolcache.yml | 28 +++++---------- 2 files changed, 26 insertions(+), 38 deletions(-) diff --git a/.github/workflows/__bundle-from-toolcache.yml b/.github/workflows/__bundle-from-toolcache.yml index a1c1fade09..1a307ba2ee 100644 --- a/.github/workflows/__bundle-from-toolcache.yml +++ b/.github/workflows/__bundle-from-toolcache.yml @@ -46,6 +46,15 @@ jobs: steps: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Install Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: 20.x + cache: npm + - name: Install newer npm + run: npm install -g npm@11.19.1 + - name: Install dependencies + run: npm ci - name: Prepare test id: prepare-test uses: ./.github/actions/prepare-test @@ -53,31 +62,20 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' - - name: Install @actions/tool-cache - run: npm install @actions/tool-cache@3 - name: Check toolcache contains CodeQL continue-on-error: true - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - if (allCodeqlVersions.length === 0) { - throw new Error(`CodeQL could not be found in the toolcache`); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed + - id: setup-codeql uses: ./../action/setup-codeql with: tools: ${{ steps.prepare-test.outputs.tools-url }} + - name: Check CodeQL is installed within the toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - console.log(`Found CodeQL versions: ${allCodeqlVersions}`); - if (allCodeqlVersions.length === 0) { - throw new Error('CodeQL not found in toolcache'); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed env: CODEQL_ACTION_TEST_MODE: true diff --git a/pr-checks/checks/bundle-from-toolcache.yml b/pr-checks/checks/bundle-from-toolcache.yml index 0e51e2e12b..947b273903 100644 --- a/pr-checks/checks/bundle-from-toolcache.yml +++ b/pr-checks/checks/bundle-from-toolcache.yml @@ -2,30 +2,20 @@ name: "Bundle: From toolcache" description: "The CodeQL bundle should be cached within the toolcache" versions: - toolcache +installNode: true steps: - - name: Install @actions/tool-cache - run: npm install @actions/tool-cache@3 - name: Check toolcache contains CodeQL continue-on-error: true - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - if (allCodeqlVersions.length === 0) { - throw new Error(`CodeQL could not be found in the toolcache`); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed + - id: setup-codeql uses: ./../action/setup-codeql with: tools: ${{ steps.prepare-test.outputs.tools-url }} + - name: Check CodeQL is installed within the toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - console.log(`Found CodeQL versions: ${allCodeqlVersions}`); - if (allCodeqlVersions.length === 0) { - throw new Error('CodeQL not found in toolcache'); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed From 57804e978e65c0e15d620179b2c60df7bcf0f6ec Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 20 Oct 2026 14:24:12 +0100 Subject: [PATCH 026/174] Add `@actions/tool-cache` as an explicit dependency --- package-lock.json | 1 + pr-checks/package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/package-lock.json b/package-lock.json index d702b0f6f5..71a06c5d95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10484,6 +10484,7 @@ "dependencies": { "@actions/core": "^2.0.3", "@actions/github": "^8.0.1", + "@actions/tool-cache": "^3.0.1", "@octokit/core": "^7.0.8", "@octokit/plugin-paginate-rest": ">=16.0.0", "@octokit/plugin-rest-endpoint-methods": "^18.0.0", diff --git a/pr-checks/package.json b/pr-checks/package.json index 3f20d119da..343f943814 100644 --- a/pr-checks/package.json +++ b/pr-checks/package.json @@ -5,6 +5,7 @@ "dependencies": { "@actions/core": "^2.0.3", "@actions/github": "^8.0.1", + "@actions/tool-cache": "^3.0.1", "@octokit/core": "^7.0.8", "@octokit/plugin-paginate-rest": ">=16.0.0", "@octokit/plugin-rest-endpoint-methods": "^18.0.0", From d0ab717e67eec1c39f68f404715b32ea3d9bcdbe Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 20 Oct 2026 17:45:21 +0100 Subject: [PATCH 027/174] Replace `rmdir` with `rmSync` --- pr-checks/toolcache.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr-checks/toolcache.ts b/pr-checks/toolcache.ts index a14605e38e..8ec7e80b5e 100755 --- a/pr-checks/toolcache.ts +++ b/pr-checks/toolcache.ts @@ -19,7 +19,7 @@ function removeCodeQLFromToolcache() { } const codeqlPath = path.join(toolcachePath, "CodeQL"); - fs.rmdirSync(codeqlPath, { recursive: true }); + fs.rmSync(codeqlPath, { recursive: true }); core.info(`Removed '${codeqlPath}' from the toolcache.`); } From 596ae5c8cf042b08e1010164da813fdfd11a6e48 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 20 Oct 2026 18:12:38 +0100 Subject: [PATCH 028/174] Make comparison strict --- pr-checks/toolcache.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr-checks/toolcache.ts b/pr-checks/toolcache.ts index 8ec7e80b5e..459ecb068a 100755 --- a/pr-checks/toolcache.ts +++ b/pr-checks/toolcache.ts @@ -50,7 +50,7 @@ function hasCodeQLInToolcache(expectedNumber?: string) { if (allCodeqlVersions.length === 0) { throw new Error("CodeQL not found in toolcache"); } - if (expected !== undefined && allCodeqlVersions.length > expected) { + if (expected !== undefined && allCodeqlVersions.length !== expected) { throw new Error( `Expected ${expected} versions of CodeQL in the toolcache, but found ${allCodeqlVersions.length}`, ); From 56e0d42f6883e74367a0e168af4fc698e811f7f3 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 18:56:55 +0100 Subject: [PATCH 029/174] Refactor `writeDiagnosticFile` out of `writeDiagnostic` --- lib/entry-points.js | 25 +++++++++++++----------- src/diagnostics.ts | 46 +++++++++++++++++++++++++++------------------ 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index f70631437a..905dcde2fa 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -173028,6 +173028,19 @@ function addNoLanguageDiagnostic(config, diagnostic) { unwrittenDefaultLanguageDiagnostics.push(diagnostic); } } +function writeDiagnosticFile(diagnosticsPath, diagnostic) { + (0, import_fs.mkdirSync)(diagnosticsPath, { recursive: true }); + const uniqueSuffix = (diagnosticCounter++).toString(); + const sanitizedTimestamp = diagnostic.timestamp.replace( + /[^a-zA-Z0-9.-]/g, + "" + ); + const jsonPath = import_path2.default.resolve( + diagnosticsPath, + `codeql-action-${sanitizedTimestamp}-${uniqueSuffix}.json` + ); + (0, import_fs.writeFileSync)(jsonPath, JSON.stringify(diagnostic)); +} function writeDiagnostic(config, language, diagnostic) { const logger2 = getActionsLogger(); const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; @@ -173037,17 +173050,7 @@ function writeDiagnostic(config, language, diagnostic) { "codeql-action" ); try { - (0, import_fs.mkdirSync)(diagnosticsPath, { recursive: true }); - const uniqueSuffix = (diagnosticCounter++).toString(); - const sanitizedTimestamp = diagnostic.timestamp.replace( - /[^a-zA-Z0-9.-]/g, - "" - ); - const jsonPath = import_path2.default.resolve( - diagnosticsPath, - `codeql-action-${sanitizedTimestamp}-${uniqueSuffix}.json` - ); - (0, import_fs.writeFileSync)(jsonPath, JSON.stringify(diagnostic)); + writeDiagnosticFile(diagnosticsPath, diagnostic); } catch (err) { logger2.warning(`Unable to write diagnostic message to database: ${err}`); logger2.debug(JSON.stringify(diagnostic)); diff --git a/src/diagnostics.ts b/src/diagnostics.ts index fa0e87c046..caab84934e 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -177,6 +177,33 @@ export function addNoLanguageDiagnostic( } } +/** + * Writes {@link diagnostic} to a file in {@link diagnosticsPath}. + */ +function writeDiagnosticFile( + diagnosticsPath: string, + diagnostic: DiagnosticMessage, +) { + // Create the directory if it doesn't exist yet. + mkdirSync(diagnosticsPath, { recursive: true }); + + // Include a monotonically increasing suffix to avoid filename collisions + // between diagnostics produced within the same millisecond. + const uniqueSuffix = (diagnosticCounter++).toString(); + // We should only need to remove colons, but to be defensive, only allow a restricted set of + // characters. + const sanitizedTimestamp = diagnostic.timestamp.replace( + /[^a-zA-Z0-9.-]/g, + "", + ); + const jsonPath = path.resolve( + diagnosticsPath, + `codeql-action-${sanitizedTimestamp}-${uniqueSuffix}.json`, + ); + + writeFileSync(jsonPath, JSON.stringify(diagnostic)); +} + /** * Writes the given diagnostic to the database. * @@ -200,24 +227,7 @@ function writeDiagnostic( ); try { - // Create the directory if it doesn't exist yet. - mkdirSync(diagnosticsPath, { recursive: true }); - - // Include a monotonically increasing suffix to avoid filename collisions - // between diagnostics produced within the same millisecond. - const uniqueSuffix = (diagnosticCounter++).toString(); - // We should only need to remove colons, but to be defensive, only allow a restricted set of - // characters. - const sanitizedTimestamp = diagnostic.timestamp.replace( - /[^a-zA-Z0-9.-]/g, - "", - ); - const jsonPath = path.resolve( - diagnosticsPath, - `codeql-action-${sanitizedTimestamp}-${uniqueSuffix}.json`, - ); - - writeFileSync(jsonPath, JSON.stringify(diagnostic)); + writeDiagnosticFile(diagnosticsPath, diagnostic); } catch (err) { logger.warning(`Unable to write diagnostic message to database: ${err}`); logger.debug(JSON.stringify(diagnostic)); From f422d8a87420c3165a94b7c414f607689f171b1e Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 19:29:16 +0100 Subject: [PATCH 030/174] Write diagnostics to temporary location when database isn't ready --- lib/entry-points.js | 65 ++++++++++------- src/config/db-config.test.ts | 134 ++++++++++++++++++++--------------- src/diagnostics.ts | 130 ++++++++++++++++++++++----------- src/init-action.ts | 9 +-- src/setup-codeql.test.ts | 86 ++++++++++++---------- 5 files changed, 257 insertions(+), 167 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 905dcde2fa..ee275be44d 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -172993,8 +172993,7 @@ var semver4 = __toESM(require_semver2()); // src/diagnostics.ts var import_fs = require("fs"); var import_path2 = __toESM(require("path")); -var unwrittenDiagnostics = []; -var unwrittenDefaultLanguageDiagnostics = []; +var temporaryDiagnostics = []; var diagnosticCounter = 0; function makeDiagnostic(id, name, data = void 0) { return { @@ -173003,6 +173002,16 @@ function makeDiagnostic(id, name, data = void 0) { source: { ...data?.source, id, name } }; } +function getTempDiagnosticPath(tmpDir, language) { + const root = import_path2.default.join(tmpDir, "codeql-action-temp-diagnostics"); + return getDiagnosticsPath(root, language); +} +function getDiagnosticsPath(basePath, language) { + if (language !== void 0) { + return import_path2.default.resolve(basePath, language, "diagnostic", "codeql-action"); + } + return basePath; +} function addDiagnostic(config, language, diagnostic) { const logger2 = getActionsLogger(); const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; @@ -173012,7 +173021,9 @@ function addDiagnostic(config, language, diagnostic) { logger2.debug( `Writing a diagnostic for ${language}, but the database at ${databasePath} does not exist yet.` ); - unwrittenDiagnostics.push({ diagnostic, language }); + const tempDiagnosticsPath = getTempDiagnosticPath(config.tempDir, language); + const diagnosticPath = writeDiagnosticFile(tempDiagnosticsPath, diagnostic); + temporaryDiagnostics.push({ path: diagnosticPath, language }); } } function addNoLanguageDiagnostic(config, diagnostic) { @@ -173025,7 +173036,9 @@ function addNoLanguageDiagnostic(config, diagnostic) { diagnostic ); } else { - unwrittenDefaultLanguageDiagnostics.push(diagnostic); + const tempDiagnosticsPath = getTempDiagnosticPath(getTemporaryDirectory()); + const diagnosticPath = writeDiagnosticFile(tempDiagnosticsPath, diagnostic); + temporaryDiagnostics.push({ path: diagnosticPath }); } } function writeDiagnosticFile(diagnosticsPath, diagnostic) { @@ -173040,15 +173053,14 @@ function writeDiagnosticFile(diagnosticsPath, diagnostic) { `codeql-action-${sanitizedTimestamp}-${uniqueSuffix}.json` ); (0, import_fs.writeFileSync)(jsonPath, JSON.stringify(diagnostic)); + return jsonPath; +} +function getDatabaseDiagnosticsPath(config, language) { + return getDiagnosticsPath(config.dbLocation, language); } function writeDiagnostic(config, language, diagnostic) { const logger2 = getActionsLogger(); - const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; - const diagnosticsPath = import_path2.default.resolve( - databasePath, - "diagnostic", - "codeql-action" - ); + const diagnosticsPath = getDatabaseDiagnosticsPath(config, language); try { writeDiagnosticFile(diagnosticsPath, diagnostic); } catch (err) { @@ -173056,30 +173068,34 @@ function writeDiagnostic(config, language, diagnostic) { logger2.debug(JSON.stringify(diagnostic)); } } -function logUnwrittenDiagnostics() { +function logTemporaryDiagnostics() { const logger2 = getActionsLogger(); - const num = unwrittenDiagnostics.length; + const num = temporaryDiagnostics.length; if (num > 0) { logger2.warning( `${num} diagnostic(s) could not be written to the database and will not appear on the Tool Status Page.` ); - for (const unwritten of unwrittenDiagnostics) { - logger2.debug(JSON.stringify(unwritten.diagnostic)); + for (const temporary of temporaryDiagnostics) { + logger2.debug((0, import_fs.readFileSync)(temporary.path, "utf-8")); } } } function flushDiagnostics(config) { const logger2 = getActionsLogger(); - const diagnosticsCount = unwrittenDiagnostics.length + unwrittenDefaultLanguageDiagnostics.length; - logger2.debug(`Writing ${diagnosticsCount} diagnostic(s) to database.`); - for (const unwritten of unwrittenDiagnostics) { - writeDiagnostic(config, unwritten.language, unwritten.diagnostic); - } - for (const unwritten of unwrittenDefaultLanguageDiagnostics) { - addNoLanguageDiagnostic(config, unwritten); + const diagnosticsCount = temporaryDiagnostics.length; + logger2.debug( + `Moving ${diagnosticsCount} diagnostic(s) to their respective databases.` + ); + for (const temporary of temporaryDiagnostics) { + const directory = getDatabaseDiagnosticsPath( + config, + temporary.language ?? config.languages[0] + ); + const filename = import_path2.default.basename(temporary.path); + const destination = import_path2.default.join(directory, filename); + (0, import_fs.renameSync)(temporary.path, destination); } - unwrittenDiagnostics = []; - unwrittenDefaultLanguageDiagnostics = []; + temporaryDiagnostics = []; } function makeTelemetryDiagnostic(id, name, attributes, tags) { return makeDiagnostic(id, name, { @@ -186673,6 +186689,7 @@ async function run3(actionState) { if (statusReportBase !== void 0) { await sendStatusReport(statusReportBase); } + logTemporaryDiagnostics(); return; } let overlayBaseDatabaseStats; @@ -186882,7 +186899,7 @@ exec ${goBinaryPath} "$@"` ); return; } finally { - logUnwrittenDiagnostics(); + logTemporaryDiagnostics(); } await sendCompletedStatusReport2( startedAt, diff --git a/src/config/db-config.test.ts b/src/config/db-config.test.ts index 76fa918015..386556f3d3 100644 --- a/src/config/db-config.test.ts +++ b/src/config/db-config.test.ts @@ -9,8 +9,9 @@ import { LoggedMessage, makeMacro, RecordingLogger, + setupActionsVars, } from "../testing-utils"; -import { ConfigurationError, prettyPrintPack } from "../util"; +import { ConfigurationError, prettyPrintPack, withTmpDir } from "../util"; import * as dbConfig from "./db-config"; @@ -562,69 +563,84 @@ test("mergeDefaultSetupAndUserConfigs - keeps other properties from user-supplie t.deepEqual(result, configFile); }); -test("mergeDefaultSetupAndUserConfigs - ignores, but warns about, unknown keys from Default Setup", async (t) => { - const logger = new RecordingLogger(); - const configFile: dbConfig.UserConfig = { - "query-filters": [{ exclude: { a: "b" } }], - "paths-ignore": ["path"], - }; - - const result = dbConfig.mergeDefaultSetupAndUserConfigs( - logger, - { - "default-setup": { - borg: [], - org: { - unknown: "foo", - "model-packs": [], +test.serial( + "mergeDefaultSetupAndUserConfigs - ignores, but warns about, unknown keys from Default Setup", + async (t) => { + const logger = new RecordingLogger(); + const configFile: dbConfig.UserConfig = { + "query-filters": [{ exclude: { a: "b" } }], + "paths-ignore": ["path"], + }; + + await withTmpDir(async (tmpDir) => { + setupActionsVars(tmpDir, tmpDir); + const result = dbConfig.mergeDefaultSetupAndUserConfigs( + logger, + { + "default-setup": { + borg: [], + org: { + unknown: "foo", + "model-packs": [], + }, + } as unknown as dbConfig.DefaultSetupConfig, + "paths-ignore": ["other-path"], }, - } as unknown as dbConfig.DefaultSetupConfig, - "paths-ignore": ["other-path"], - }, - configFile, - ); + configFile, + ); + + t.deepEqual(result, { + ...configFile, + "default-setup": { org: { "model-packs": [] } }, + }); + + const expectedUnrecognisedKeys = [ + ".default-setup.org.unknown", + ".default-setup.borg", + ".paths-ignore", + ].join(", "); + checkExpectedLogMessages(t, logger.messages, [ + `Unrecognised keys in Default Setup configuration: ${expectedUnrecognisedKeys}`, + ]); + }); + }, +); - t.deepEqual(result, { - ...configFile, - "default-setup": { org: { "model-packs": [] } }, - }); - - const expectedUnrecognisedKeys = [ - ".default-setup.org.unknown", - ".default-setup.borg", - ".paths-ignore", - ].join(", "); - checkExpectedLogMessages(t, logger.messages, [ - `Unrecognised keys in Default Setup configuration: ${expectedUnrecognisedKeys}`, - ]); -}); +test.serial( + "mergeDefaultSetupAndUserConfigs - warns about invalid keys from Default Setup", + async (t) => { + const logger = new RecordingLogger(); + const configFile: dbConfig.UserConfig = {}; -test("mergeDefaultSetupAndUserConfigs - warns about invalid keys from Default Setup", async (t) => { - const logger = new RecordingLogger(); - const configFile: dbConfig.UserConfig = {}; + await withTmpDir(async (tmpDir) => { + setupActionsVars(tmpDir, tmpDir); - const result = dbConfig.mergeDefaultSetupAndUserConfigs( - logger, - { - "default-setup": { - org: { - "model-packs": [123], + const result = dbConfig.mergeDefaultSetupAndUserConfigs( + logger, + { + "default-setup": { + org: { + "model-packs": [123], + }, + } as unknown as dbConfig.DefaultSetupConfig, }, - } as unknown as dbConfig.DefaultSetupConfig, - }, - configFile, - ); - - t.deepEqual(result, { - ...configFile, - "default-setup": { org: { "model-packs": [123] } }, - }); - - const expectedInvalidKeys = [".default-setup.org.model-packs[0]"].join(", "); - checkExpectedLogMessages(t, logger.messages, [ - `Invalid keys in Default Setup configuration: ${expectedInvalidKeys}`, - ]); -}); + configFile, + ); + + t.deepEqual(result, { + ...configFile, + "default-setup": { org: { "model-packs": [123] } }, + }); + + const expectedInvalidKeys = [".default-setup.org.model-packs[0]"].join( + ", ", + ); + checkExpectedLogMessages(t, logger.messages, [ + `Invalid keys in Default Setup configuration: ${expectedInvalidKeys}`, + ]); + }); + }, +); /** Parses `contents` as a configuration without validating it. */ function parseUnvalidatedConfig(contents: string): dbConfig.UserConfig { diff --git a/src/diagnostics.ts b/src/diagnostics.ts index caab84934e..f08c83c420 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -1,6 +1,13 @@ -import { existsSync, mkdirSync, writeFileSync } from "fs"; +import { + existsSync, + mkdirSync, + readFileSync, + renameSync, + writeFileSync, +} from "fs"; import path from "path"; +import { getTemporaryDirectory } from "./actions-util"; import type { Config } from "./config-utils"; import { Language } from "./languages"; import { getActionsLogger } from "./logging"; @@ -84,22 +91,16 @@ export type DiagnosticMessage = DiagnosticMessageOptions & { source: DiagnosticSource; }; -/** Represents a diagnostic message that has not yet been written to the database. */ -interface UnwrittenDiagnostic { - /** The diagnostic message that has not yet been written. */ - diagnostic: DiagnosticMessage; - /** The language the diagnostic is for. */ - language: Language; +/** Represents a diagnostic message that has not yet been saved to the database. */ +interface TemporaryDiagnostic { + /** The path to which the diagnostic has temporarily been written to. */ + path: string; + /** The language the diagnostic is for, if any. */ + language?: Language; } -/** A list of diagnostics which have not yet been written to disk. */ -let unwrittenDiagnostics: UnwrittenDiagnostic[] = []; - -/** - * A list of diagnostics which have not yet been written to disk, - * and where the language does not matter. - */ -let unwrittenDefaultLanguageDiagnostics: DiagnosticMessage[] = []; +/** A list of diagnostics which have not yet been saved to the database. */ +let temporaryDiagnostics: TemporaryDiagnostic[] = []; /** * Counter used to generate a unique suffix for each diagnostic filename, so that @@ -128,6 +129,29 @@ export function makeDiagnostic( }; } +/** + * Gets a path relative to {@link tmpDir} where diagnostics for {@link language} + * can temporarily be stored at before the database is initialised. If {@link language} + * is `undefined`, then the common base path for all languages relative to {@link tmpDir} + * is returned. + */ +export function getTempDiagnosticPath(tmpDir: string, language?: Language) { + const root = path.join(tmpDir, "codeql-action-temp-diagnostics"); + return getDiagnosticsPath(root, language); +} + +/** + * Gets a path relative to {@link basePath} where diagnostics for {@link language} + * should be stored at. If {@link language} is `undefined`, then {@link baseBath} + * is returned instead. + */ +export function getDiagnosticsPath(basePath: string, language?: Language) { + if (language !== undefined) { + return path.resolve(basePath, language, "diagnostic", "codeql-action"); + } + return basePath; +} + /** * Adds the given diagnostic to the database. If the database does not yet exist, * the diagnostic will be written to it once it has been created. @@ -155,7 +179,12 @@ export function addDiagnostic( `Writing a diagnostic for ${language}, but the database at ${databasePath} does not exist yet.`, ); - unwrittenDiagnostics.push({ diagnostic, language }); + // Write the diagnostic to a temporary location. + const tempDiagnosticsPath = getTempDiagnosticPath(config.tempDir, language); + const diagnosticPath = writeDiagnosticFile(tempDiagnosticsPath, diagnostic); + + // Track the temporary file. + temporaryDiagnostics.push({ path: diagnosticPath, language }); } } @@ -173,7 +202,11 @@ export function addNoLanguageDiagnostic( diagnostic, ); } else { - unwrittenDefaultLanguageDiagnostics.push(diagnostic); + const tempDiagnosticsPath = getTempDiagnosticPath(getTemporaryDirectory()); + const diagnosticPath = writeDiagnosticFile(tempDiagnosticsPath, diagnostic); + + // Track the temporary file. + temporaryDiagnostics.push({ path: diagnosticPath }); } } @@ -183,7 +216,7 @@ export function addNoLanguageDiagnostic( function writeDiagnosticFile( diagnosticsPath: string, diagnostic: DiagnosticMessage, -) { +): string { // Create the directory if it doesn't exist yet. mkdirSync(diagnosticsPath, { recursive: true }); @@ -202,6 +235,16 @@ function writeDiagnosticFile( ); writeFileSync(jsonPath, JSON.stringify(diagnostic)); + + return jsonPath; +} + +/** Gets the path where diagnostics for {@link language} should be stored in the database. */ +export function getDatabaseDiagnosticsPath( + config: Config, + language: Language | undefined, +) { + return getDiagnosticsPath(config.dbLocation, language); } /** @@ -217,14 +260,7 @@ function writeDiagnostic( diagnostic: DiagnosticMessage, ) { const logger = getActionsLogger(); - const databasePath = language - ? getCodeQLDatabasePath(config, language) - : config.dbLocation; - const diagnosticsPath = path.resolve( - databasePath, - "diagnostic", - "codeql-action", - ); + const diagnosticsPath = getDatabaseDiagnosticsPath(config, language); try { writeDiagnosticFile(diagnosticsPath, diagnostic); @@ -234,39 +270,47 @@ function writeDiagnostic( } } -/** Report if there are unwritten diagnostics and write them to the log. */ -export function logUnwrittenDiagnostics() { +/** Report if there are temporary diagnostics and write them to the log. */ +export function logTemporaryDiagnostics() { const logger = getActionsLogger(); - const num = unwrittenDiagnostics.length; + const num = temporaryDiagnostics.length; + if (num > 0) { logger.warning( `${num} diagnostic(s) could not be written to the database and will not appear on the Tool Status Page.`, ); - for (const unwritten of unwrittenDiagnostics) { - logger.debug(JSON.stringify(unwritten.diagnostic)); + for (const temporary of temporaryDiagnostics) { + logger.debug(readFileSync(temporary.path, "utf-8")); } } } -/** Writes all unwritten diagnostics to disk. */ +/** Relocates all temporary diagnostics to the respective databases. */ export function flushDiagnostics(config: Config) { const logger = getActionsLogger(); - const diagnosticsCount = - unwrittenDiagnostics.length + unwrittenDefaultLanguageDiagnostics.length; - logger.debug(`Writing ${diagnosticsCount} diagnostic(s) to database.`); + const diagnosticsCount = temporaryDiagnostics.length; + logger.debug( + `Moving ${diagnosticsCount} diagnostic(s) to their respective databases.`, + ); - for (const unwritten of unwrittenDiagnostics) { - writeDiagnostic(config, unwritten.language, unwritten.diagnostic); - } - for (const unwritten of unwrittenDefaultLanguageDiagnostics) { - addNoLanguageDiagnostic(config, unwritten); + for (const temporary of temporaryDiagnostics) { + // If `temporary.language` is `undefined`, then we didn't have a `config` at the time that + // `addNoLanguageDiagnostic` was called. In that case, we arbitrarily choose the first + // configured language here like we would have done in `addNoLanguageDiagnostic`. + const directory = getDatabaseDiagnosticsPath( + config, + temporary.language ?? config.languages[0], + ); + const filename = path.basename(temporary.path); + const destination = path.join(directory, filename); + + renameSync(temporary.path, destination); } - // Reset the unwritten diagnostics arrays. - unwrittenDiagnostics = []; - unwrittenDefaultLanguageDiagnostics = []; + // Reset the temporary diagnostics arrays. + temporaryDiagnostics = []; } /** diff --git a/src/init-action.ts b/src/init-action.ts index f58d4ccca7..99d8e06663 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -40,7 +40,7 @@ import { addDiagnostic, addNoLanguageDiagnostic, flushDiagnostics, - logUnwrittenDiagnostics, + logTemporaryDiagnostics, makeDiagnostic, makeTelemetryDiagnostic, } from "./diagnostics"; @@ -484,6 +484,7 @@ async function run( if (statusReportBase !== undefined) { await sendStatusReport(statusReportBase); } + logTemporaryDiagnostics(); return; } @@ -766,8 +767,8 @@ async function run( ); } - // Write diagnostics to the database that we previously stored in memory because the database - // did not exist until now. + // Move diagnostics to the database that we previously kept in a temporary location + // because the database did not exist until now flushDiagnostics(config); // We save the config here instead of at the end of `initConfig` because we @@ -797,7 +798,7 @@ async function run( ); return; } finally { - logUnwrittenDiagnostics(); + logTemporaryDiagnostics(); } await sendCompletedStatusReport( startedAt, diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 7dfac19148..bad5cb35fc 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -1626,16 +1626,20 @@ test.serial( }, ]); - const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( - overlayMatchEnabledVersions, - ["javascript"], - createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), - ); - t.deepEqual(result, [ - { cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" }, - { cliVersion: "2.20.0", tagName: "codeql-bundle-v2.20.0" }, - ]); + await withTmpDir(async (tmpDir) => { + setupActionsVars(tmpDir, tmpDir); + const result = + await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( + overlayMatchEnabledVersions, + ["javascript"], + createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), + getRunnerLogger(true), + ); + t.deepEqual(result, [ + { cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" }, + { cliVersion: "2.20.0", tagName: "codeql-bundle-v2.20.0" }, + ]); + }); }, ); @@ -1752,21 +1756,25 @@ test.serial( }, ]); - const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( - overlayMatchEnabledVersions, - ["javascript"], - createFeatures([Feature.OverlayAnalysisMatchCodeqlVersionDryRun]), - getRunnerLogger(true), - ); - t.deepEqual( - result, - [], - "Dry-run should return an empty list so the caller falls back.", - ); - t.assert( - listStub.calledOnce, - "Dry-run should still list Actions caches to populate the diagnostic.", - ); + await withTmpDir(async (tmpDir) => { + setupActionsVars(tmpDir, tmpDir); + const result = + await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( + overlayMatchEnabledVersions, + ["javascript"], + createFeatures([Feature.OverlayAnalysisMatchCodeqlVersionDryRun]), + getRunnerLogger(true), + ); + t.deepEqual( + result, + [], + "Dry-run should return an empty list so the caller falls back.", + ); + t.assert( + listStub.calledOnce, + "Dry-run should still list Actions caches to populate the diagnostic.", + ); + }); }, ); @@ -1780,18 +1788,22 @@ test.serial( }, ]); - const result = await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( - overlayMatchEnabledVersions, - ["javascript"], - createFeatures([ - Feature.OverlayAnalysisMatchCodeqlVersion, - Feature.OverlayAnalysisMatchCodeqlVersionDryRun, - ]), - getRunnerLogger(true), - ); - t.deepEqual(result, [ - { cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" }, - ]); + await withTmpDir(async (tmpDir) => { + setupActionsVars(tmpDir, tmpDir); + const result = + await setupCodeql.getEnabledVersionsWithOverlayBaseDatabases( + overlayMatchEnabledVersions, + ["javascript"], + createFeatures([ + Feature.OverlayAnalysisMatchCodeqlVersion, + Feature.OverlayAnalysisMatchCodeqlVersionDryRun, + ]), + getRunnerLogger(true), + ); + t.deepEqual(result, [ + { cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" }, + ]); + }); }, ); From 67f25913cb2ea1d22dc93c6cf9169b570387c15b Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 21:59:55 +0100 Subject: [PATCH 031/174] Make diagnostics less dependent on global state Add limited test coverage --- lib/entry-points.js | 820 ++++++++++++++++++++-------------------- src/diagnostics.test.ts | 111 ++++++ src/diagnostics.ts | 78 ++-- src/init-action.ts | 6 +- src/util.ts | 15 + 5 files changed, 598 insertions(+), 432 deletions(-) create mode 100644 src/diagnostics.test.ts diff --git a/lib/entry-points.js b/lib/entry-points.js index ee275be44d..674e6425f6 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -213,7 +213,7 @@ var require_file_command = __commonJS({ exports2.issueFileCommand = issueFileCommand; exports2.prepareKeyValueMessage = prepareKeyValueMessage; var crypto3 = __importStar2(require("crypto")); - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var os7 = __importStar2(require("os")); var utils_1 = require_utils(); function issueFileCommand(command, message) { @@ -221,10 +221,10 @@ var require_file_command = __commonJS({ if (!filePath) { throw new Error(`Unable to find environment variable for file command ${command}`); } - if (!fs32.existsSync(filePath)) { + if (!fs33.existsSync(filePath)) { throw new Error(`Missing file at path: ${filePath}`); } - fs32.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os7.EOL}`, { + fs33.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os7.EOL}`, { encoding: "utf8" }); } @@ -20443,13 +20443,13 @@ var require_io_util = __commonJS({ exports2.isRooted = isRooted; exports2.tryGetExecutablePath = tryGetExecutablePath; exports2.getCmdPath = getCmdPath; - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var path30 = __importStar2(require("path")); - _a6 = fs32.promises, exports2.chmod = _a6.chmod, exports2.copyFile = _a6.copyFile, exports2.lstat = _a6.lstat, exports2.mkdir = _a6.mkdir, exports2.open = _a6.open, exports2.readdir = _a6.readdir, exports2.rename = _a6.rename, exports2.rm = _a6.rm, exports2.rmdir = _a6.rmdir, exports2.stat = _a6.stat, exports2.symlink = _a6.symlink, exports2.unlink = _a6.unlink; + _a6 = fs33.promises, exports2.chmod = _a6.chmod, exports2.copyFile = _a6.copyFile, exports2.lstat = _a6.lstat, exports2.mkdir = _a6.mkdir, exports2.open = _a6.open, exports2.readdir = _a6.readdir, exports2.rename = _a6.rename, exports2.rm = _a6.rm, exports2.rmdir = _a6.rmdir, exports2.stat = _a6.stat, exports2.symlink = _a6.symlink, exports2.unlink = _a6.unlink; exports2.IS_WINDOWS = process.platform === "win32"; function readlink(fsPath) { return __awaiter2(this, void 0, void 0, function* () { - const result = yield fs32.promises.readlink(fsPath); + const result = yield fs33.promises.readlink(fsPath); if (exports2.IS_WINDOWS && !result.endsWith("\\")) { return `${result}\\`; } @@ -20457,7 +20457,7 @@ var require_io_util = __commonJS({ }); } exports2.UV_FS_O_EXLOCK = 268435456; - exports2.READONLY = fs32.constants.O_RDONLY; + exports2.READONLY = fs33.constants.O_RDONLY; function exists(fsPath) { return __awaiter2(this, void 0, void 0, function* () { try { @@ -33065,7 +33065,7 @@ var require_internal_globber = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.DefaultGlobber = void 0; var core29 = __importStar2(require_core()); - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var globOptionsHelper = __importStar2(require_internal_glob_options_helper()); var path30 = __importStar2(require("path")); var patternHelper = __importStar2(require_internal_pattern_helper()); @@ -33119,7 +33119,7 @@ var require_internal_globber = __commonJS({ for (const searchPath of patternHelper.getSearchPaths(patterns)) { core29.debug(`Search path '${searchPath}'`); try { - yield __await2(fs32.promises.lstat(searchPath)); + yield __await2(fs33.promises.lstat(searchPath)); } catch (err) { if (err.code === "ENOENT") { continue; @@ -33153,7 +33153,7 @@ var require_internal_globber = __commonJS({ continue; } const childLevel = item.level + 1; - const childItems = (yield __await2(fs32.promises.readdir(item.path))).map((x) => new internal_search_state_1.SearchState(path30.join(item.path, x), childLevel)); + const childItems = (yield __await2(fs33.promises.readdir(item.path))).map((x) => new internal_search_state_1.SearchState(path30.join(item.path, x), childLevel)); stack.push(...childItems.reverse()); } else if (match2 & internal_match_kind_1.MatchKind.File) { yield yield __await2(item.path); @@ -33188,7 +33188,7 @@ var require_internal_globber = __commonJS({ let stats; if (options.followSymbolicLinks) { try { - stats = yield fs32.promises.stat(item.path); + stats = yield fs33.promises.stat(item.path); } catch (err) { if (err.code === "ENOENT") { if (options.omitBrokenSymbolicLinks) { @@ -33200,10 +33200,10 @@ var require_internal_globber = __commonJS({ throw err; } } else { - stats = yield fs32.promises.lstat(item.path); + stats = yield fs33.promises.lstat(item.path); } if (stats.isDirectory() && options.followSymbolicLinks) { - const realPath = yield fs32.promises.realpath(item.path); + const realPath = yield fs33.promises.realpath(item.path); while (traversalChain.length >= item.level) { traversalChain.pop(); } @@ -33312,7 +33312,7 @@ var require_internal_hash_files = __commonJS({ exports2.hashFiles = hashFiles2; var crypto3 = __importStar2(require("crypto")); var core29 = __importStar2(require_core()); - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var stream2 = __importStar2(require("stream")); var util4 = __importStar2(require("util")); var path30 = __importStar2(require("path")); @@ -33335,13 +33335,13 @@ var require_internal_hash_files = __commonJS({ writeDelegate(`Ignore '${file}' since it is not under GITHUB_WORKSPACE.`); continue; } - if (fs32.statSync(file).isDirectory()) { + if (fs33.statSync(file).isDirectory()) { writeDelegate(`Skip directory '${file}'.`); continue; } const hash2 = crypto3.createHash("sha256"); const pipeline2 = util4.promisify(stream2.pipeline); - yield pipeline2(fs32.createReadStream(file), hash2); + yield pipeline2(fs33.createReadStream(file), hash2); result.write(hash2.digest()); count++; if (!hasMatch) { @@ -34717,7 +34717,7 @@ var require_cacheUtils = __commonJS({ var glob2 = __importStar2(require_glob()); var io9 = __importStar2(require_io()); var crypto3 = __importStar2(require("crypto")); - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var path30 = __importStar2(require("path")); var semver11 = __importStar2(require_semver3()); var util4 = __importStar2(require("util")); @@ -34746,7 +34746,7 @@ var require_cacheUtils = __commonJS({ }); } function getArchiveFileSizeInBytes(filePath) { - return fs32.statSync(filePath).size; + return fs33.statSync(filePath).size; } function resolvePaths(patterns) { return __awaiter2(this, void 0, void 0, function* () { @@ -34784,7 +34784,7 @@ var require_cacheUtils = __commonJS({ } function unlinkFile(filePath) { return __awaiter2(this, void 0, void 0, function* () { - return util4.promisify(fs32.unlink)(filePath); + return util4.promisify(fs33.unlink)(filePath); }); } function getVersion(app_1) { @@ -34826,7 +34826,7 @@ var require_cacheUtils = __commonJS({ } function getGnuTarPathOnWindows() { return __awaiter2(this, void 0, void 0, function* () { - if (fs32.existsSync(constants_1.GnuTarPathOnWindows)) { + if (fs33.existsSync(constants_1.GnuTarPathOnWindows)) { return constants_1.GnuTarPathOnWindows; } const versionOutput = yield getVersion("tar"); @@ -99550,7 +99550,7 @@ var require_downloadUtils = __commonJS({ var http_client_1 = require_lib(); var storage_blob_1 = require_commonjs15(); var buffer = __importStar2(require("buffer")); - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var stream2 = __importStar2(require("stream")); var util4 = __importStar2(require("util")); var utils = __importStar2(require_cacheUtils()); @@ -99661,7 +99661,7 @@ var require_downloadUtils = __commonJS({ exports2.DownloadProgress = DownloadProgress; function downloadCacheHttpClient(archiveLocation, archivePath) { return __awaiter2(this, void 0, void 0, function* () { - const writeStream = fs32.createWriteStream(archivePath); + const writeStream = fs33.createWriteStream(archivePath); const httpClient = new http_client_1.HttpClient("actions/cache"); const downloadResponse = yield (0, requestUtils_1.retryHttpClientResponse)("downloadCache", () => __awaiter2(this, void 0, void 0, function* () { return httpClient.get(archiveLocation); @@ -99686,7 +99686,7 @@ var require_downloadUtils = __commonJS({ function downloadCacheHttpClientConcurrent(archiveLocation, archivePath, options) { return __awaiter2(this, void 0, void 0, function* () { var _a6; - const archiveDescriptor = yield fs32.promises.open(archivePath, "w"); + const archiveDescriptor = yield fs33.promises.open(archivePath, "w"); const httpClient = new http_client_1.HttpClient("actions/cache", void 0, { socketTimeout: options.timeoutInMs, keepAlive: true @@ -99802,7 +99802,7 @@ var require_downloadUtils = __commonJS({ } else { const maxSegmentSize = Math.min(134217728, buffer.constants.MAX_LENGTH); const downloadProgress = new DownloadProgress(contentLength); - const fd = fs32.openSync(archivePath, "w"); + const fd = fs33.openSync(archivePath, "w"); try { downloadProgress.startDisplayTimer(); const controller = new abort_controller_1.AbortController(); @@ -99820,12 +99820,12 @@ var require_downloadUtils = __commonJS({ controller.abort(); throw new Error("Aborting cache download as the download time exceeded the timeout."); } else if (Buffer.isBuffer(result)) { - fs32.writeFileSync(fd, result); + fs33.writeFileSync(fd, result); } } } finally { downloadProgress.stopDisplayTimer(); - fs32.closeSync(fd); + fs33.closeSync(fd); } } }); @@ -100164,7 +100164,7 @@ var require_cacheHttpClient = __commonJS({ var core29 = __importStar2(require_core()); var http_client_1 = require_lib(); var auth_1 = require_auth(); - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var url_1 = require("url"); var utils = __importStar2(require_cacheUtils()); var uploadUtils_1 = require_uploadUtils(); @@ -100305,7 +100305,7 @@ Other caches with similar key:`); return __awaiter2(this, void 0, void 0, function* () { const fileSize = utils.getArchiveFileSizeInBytes(archivePath); const resourceUrl = getCacheApiUrl(`caches/${cacheId.toString()}`); - const fd = fs32.openSync(archivePath, "r"); + const fd = fs33.openSync(archivePath, "r"); const uploadOptions = (0, options_1.getUploadOptions)(options); const concurrency = utils.assertDefined("uploadConcurrency", uploadOptions.uploadConcurrency); const maxChunkSize = utils.assertDefined("uploadChunkSize", uploadOptions.uploadChunkSize); @@ -100319,7 +100319,7 @@ Other caches with similar key:`); const start = offset; const end = offset + chunkSize - 1; offset += maxChunkSize; - yield uploadChunk(httpClient, resourceUrl, () => fs32.createReadStream(archivePath, { + yield uploadChunk(httpClient, resourceUrl, () => fs33.createReadStream(archivePath, { fd, start, end, @@ -100330,7 +100330,7 @@ Other caches with similar key:`); } }))); } finally { - fs32.closeSync(fd); + fs33.closeSync(fd); } return; }); @@ -106365,7 +106365,7 @@ var require_manifest = __commonJS({ var core_1 = require_core(); var os7 = require("os"); var cp = require("child_process"); - var fs32 = require("fs"); + var fs33 = require("fs"); function _findMatch(versionSpec, stable, candidates, archFilter) { return __awaiter2(this, void 0, void 0, function* () { const platFilter = os7.platform(); @@ -106427,10 +106427,10 @@ var require_manifest = __commonJS({ const lsbReleaseFile = "/etc/lsb-release"; const osReleaseFile = "/etc/os-release"; let contents = ""; - if (fs32.existsSync(lsbReleaseFile)) { - contents = fs32.readFileSync(lsbReleaseFile).toString(); - } else if (fs32.existsSync(osReleaseFile)) { - contents = fs32.readFileSync(osReleaseFile).toString(); + if (fs33.existsSync(lsbReleaseFile)) { + contents = fs33.readFileSync(lsbReleaseFile).toString(); + } else if (fs33.existsSync(osReleaseFile)) { + contents = fs33.readFileSync(osReleaseFile).toString(); } return contents; } @@ -106639,7 +106639,7 @@ var require_tool_cache = __commonJS({ var core29 = __importStar2(require_core()); var io9 = __importStar2(require_io()); var crypto3 = __importStar2(require("crypto")); - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var mm = __importStar2(require_manifest()); var os7 = __importStar2(require("os")); var path30 = __importStar2(require("path")); @@ -106685,7 +106685,7 @@ var require_tool_cache = __commonJS({ } function downloadToolAttempt(url2, dest, auth2, headers) { return __awaiter2(this, void 0, void 0, function* () { - if (fs32.existsSync(dest)) { + if (fs33.existsSync(dest)) { throw new Error(`Destination file path ${dest} already exists`); } const http = new httpm.HttpClient(userAgent2, [], { @@ -106709,7 +106709,7 @@ var require_tool_cache = __commonJS({ const readStream = responseMessageFactory(); let succeeded = false; try { - yield pipeline2(readStream, fs32.createWriteStream(dest)); + yield pipeline2(readStream, fs33.createWriteStream(dest)); core29.debug("download complete"); succeeded = true; return dest; @@ -106921,11 +106921,11 @@ var require_tool_cache = __commonJS({ arch2 = arch2 || os7.arch(); core29.debug(`Caching tool ${tool} ${version} ${arch2}`); core29.debug(`source dir: ${sourceDir}`); - if (!fs32.statSync(sourceDir).isDirectory()) { + if (!fs33.statSync(sourceDir).isDirectory()) { throw new Error("sourceDir is not a directory"); } const destPath = yield _createToolPath(tool, version, arch2); - for (const itemName of fs32.readdirSync(sourceDir)) { + for (const itemName of fs33.readdirSync(sourceDir)) { const s = path30.join(sourceDir, itemName); yield io9.cp(s, destPath, { recursive: true }); } @@ -106939,7 +106939,7 @@ var require_tool_cache = __commonJS({ arch2 = arch2 || os7.arch(); core29.debug(`Caching tool ${tool} ${version} ${arch2}`); core29.debug(`source file: ${sourceFile}`); - if (!fs32.statSync(sourceFile).isFile()) { + if (!fs33.statSync(sourceFile).isFile()) { throw new Error("sourceFile is not a file"); } const destFolder = yield _createToolPath(tool, version, arch2); @@ -106968,7 +106968,7 @@ var require_tool_cache = __commonJS({ versionSpec = semver11.clean(versionSpec) || ""; const cachePath = path30.join(_getCacheDirectory(), toolName, versionSpec, arch2); core29.debug(`checking cache: ${cachePath}`); - if (fs32.existsSync(cachePath) && fs32.existsSync(`${cachePath}.complete`)) { + if (fs33.existsSync(cachePath) && fs33.existsSync(`${cachePath}.complete`)) { core29.debug(`Found tool in cache ${toolName} ${versionSpec} ${arch2}`); toolPath = cachePath; } else { @@ -106981,12 +106981,12 @@ var require_tool_cache = __commonJS({ const versions = []; arch2 = arch2 || os7.arch(); const toolPath = path30.join(_getCacheDirectory(), toolName); - if (fs32.existsSync(toolPath)) { - const children = fs32.readdirSync(toolPath); + if (fs33.existsSync(toolPath)) { + const children = fs33.readdirSync(toolPath); for (const child of children) { if (isExplicitVersion(child)) { const fullPath = path30.join(toolPath, child, arch2 || ""); - if (fs32.existsSync(fullPath) && fs32.existsSync(`${fullPath}.complete`)) { + if (fs33.existsSync(fullPath) && fs33.existsSync(`${fullPath}.complete`)) { versions.push(child); } } @@ -107057,7 +107057,7 @@ var require_tool_cache = __commonJS({ function _completeToolPath(tool, version, arch2) { const folderPath = path30.join(_getCacheDirectory(), tool, semver11.clean(version) || version, arch2 || ""); const markerPath = `${folderPath}.complete`; - fs32.writeFileSync(markerPath, ""); + fs33.writeFileSync(markerPath, ""); core29.debug("finished caching tool"); } function isExplicitVersion(versionSpec) { @@ -113270,15 +113270,15 @@ var require_upload_zip_specification = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.getUploadZipSpecification = exports2.validateRootDirectory = void 0; - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var core_1 = require_core(); var path_1 = require("path"); var path_and_artifact_name_validation_1 = require_path_and_artifact_name_validation(); function validateRootDirectory(rootDirectory) { - if (!fs32.existsSync(rootDirectory)) { + if (!fs33.existsSync(rootDirectory)) { throw new Error(`The provided rootDirectory ${rootDirectory} does not exist`); } - if (!fs32.statSync(rootDirectory).isDirectory()) { + if (!fs33.statSync(rootDirectory).isDirectory()) { throw new Error(`The provided rootDirectory ${rootDirectory} is not a valid directory`); } (0, core_1.info)(`Root directory input is valid!`); @@ -113289,7 +113289,7 @@ var require_upload_zip_specification = __commonJS({ rootDirectory = (0, path_1.normalize)(rootDirectory); rootDirectory = (0, path_1.resolve)(rootDirectory); for (let file of filesToZip) { - const stats = fs32.lstatSync(file, { throwIfNoEntry: false }); + const stats = fs33.lstatSync(file, { throwIfNoEntry: false }); if (!stats) { throw new Error(`File ${file} does not exist`); } @@ -114364,13 +114364,13 @@ var require_minimatch2 = __commonJS({ var require_readdir_glob = __commonJS({ "node_modules/@actions/artifact/node_modules/readdir-glob/index.js"(exports2, module2) { module2.exports = readdirGlob2; - var fs32 = require("fs"); + var fs33 = require("fs"); var { EventEmitter: EventEmitter2 } = require("events"); var { Minimatch: Minimatch2 } = require_minimatch2(); var { resolve: resolve15 } = require("path"); function readdir3(dir, strict) { return new Promise((resolve16, reject) => { - fs32.readdir(dir, { withFileTypes: true }, (err, files) => { + fs33.readdir(dir, { withFileTypes: true }, (err, files) => { if (err) { switch (err.code) { case "ENOTDIR": @@ -114403,7 +114403,7 @@ var require_readdir_glob = __commonJS({ } function stat2(file, followSymlinks) { return new Promise((resolve16, reject) => { - const statFunc = followSymlinks ? fs32.stat : fs32.lstat; + const statFunc = followSymlinks ? fs33.stat : fs33.lstat; statFunc(file, (err, stats) => { if (err) { switch (err.code) { @@ -116468,54 +116468,54 @@ var require_polyfills = __commonJS({ } var chdir; module2.exports = patch; - function patch(fs32) { + function patch(fs33) { if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { - patchLchmod(fs32); - } - if (!fs32.lutimes) { - patchLutimes(fs32); - } - fs32.chown = chownFix(fs32.chown); - fs32.fchown = chownFix(fs32.fchown); - fs32.lchown = chownFix(fs32.lchown); - fs32.chmod = chmodFix(fs32.chmod); - fs32.fchmod = chmodFix(fs32.fchmod); - fs32.lchmod = chmodFix(fs32.lchmod); - fs32.chownSync = chownFixSync(fs32.chownSync); - fs32.fchownSync = chownFixSync(fs32.fchownSync); - fs32.lchownSync = chownFixSync(fs32.lchownSync); - fs32.chmodSync = chmodFixSync(fs32.chmodSync); - fs32.fchmodSync = chmodFixSync(fs32.fchmodSync); - fs32.lchmodSync = chmodFixSync(fs32.lchmodSync); - fs32.stat = statFix(fs32.stat); - fs32.fstat = statFix(fs32.fstat); - fs32.lstat = statFix(fs32.lstat); - fs32.statSync = statFixSync(fs32.statSync); - fs32.fstatSync = statFixSync(fs32.fstatSync); - fs32.lstatSync = statFixSync(fs32.lstatSync); - if (fs32.chmod && !fs32.lchmod) { - fs32.lchmod = function(path30, mode, cb) { + patchLchmod(fs33); + } + if (!fs33.lutimes) { + patchLutimes(fs33); + } + fs33.chown = chownFix(fs33.chown); + fs33.fchown = chownFix(fs33.fchown); + fs33.lchown = chownFix(fs33.lchown); + fs33.chmod = chmodFix(fs33.chmod); + fs33.fchmod = chmodFix(fs33.fchmod); + fs33.lchmod = chmodFix(fs33.lchmod); + fs33.chownSync = chownFixSync(fs33.chownSync); + fs33.fchownSync = chownFixSync(fs33.fchownSync); + fs33.lchownSync = chownFixSync(fs33.lchownSync); + fs33.chmodSync = chmodFixSync(fs33.chmodSync); + fs33.fchmodSync = chmodFixSync(fs33.fchmodSync); + fs33.lchmodSync = chmodFixSync(fs33.lchmodSync); + fs33.stat = statFix(fs33.stat); + fs33.fstat = statFix(fs33.fstat); + fs33.lstat = statFix(fs33.lstat); + fs33.statSync = statFixSync(fs33.statSync); + fs33.fstatSync = statFixSync(fs33.fstatSync); + fs33.lstatSync = statFixSync(fs33.lstatSync); + if (fs33.chmod && !fs33.lchmod) { + fs33.lchmod = function(path30, mode, cb) { if (cb) process.nextTick(cb); }; - fs32.lchmodSync = function() { + fs33.lchmodSync = function() { }; } - if (fs32.chown && !fs32.lchown) { - fs32.lchown = function(path30, uid, gid, cb) { + if (fs33.chown && !fs33.lchown) { + fs33.lchown = function(path30, uid, gid, cb) { if (cb) process.nextTick(cb); }; - fs32.lchownSync = function() { + fs33.lchownSync = function() { }; } if (platform2 === "win32") { - fs32.rename = typeof fs32.rename !== "function" ? fs32.rename : (function(fs$rename) { + fs33.rename = typeof fs33.rename !== "function" ? fs33.rename : (function(fs$rename) { function rename(from, to, cb) { var start = Date.now(); var backoff = 0; fs$rename(from, to, function CB(er) { if (er && (er.code === "EACCES" || er.code === "EPERM") && Date.now() - start < 6e4) { setTimeout(function() { - fs32.stat(to, function(stater, st) { + fs33.stat(to, function(stater, st) { if (stater && stater.code === "ENOENT") fs$rename(from, to, CB); else @@ -116531,9 +116531,9 @@ var require_polyfills = __commonJS({ } if (Object.setPrototypeOf) Object.setPrototypeOf(rename, fs$rename); return rename; - })(fs32.rename); + })(fs33.rename); } - fs32.read = typeof fs32.read !== "function" ? fs32.read : (function(fs$read) { + fs33.read = typeof fs33.read !== "function" ? fs33.read : (function(fs$read) { function read(fd, buffer, offset, length, position, callback_) { var callback; if (callback_ && typeof callback_ === "function") { @@ -116541,22 +116541,22 @@ var require_polyfills = __commonJS({ callback = function(er, _2, __) { if (er && er.code === "EAGAIN" && eagCounter < 10) { eagCounter++; - return fs$read.call(fs32, fd, buffer, offset, length, position, callback); + return fs$read.call(fs33, fd, buffer, offset, length, position, callback); } callback_.apply(this, arguments); }; } - return fs$read.call(fs32, fd, buffer, offset, length, position, callback); + return fs$read.call(fs33, fd, buffer, offset, length, position, callback); } if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read); return read; - })(fs32.read); - fs32.readSync = typeof fs32.readSync !== "function" ? fs32.readSync : /* @__PURE__ */ (function(fs$readSync) { + })(fs33.read); + fs33.readSync = typeof fs33.readSync !== "function" ? fs33.readSync : /* @__PURE__ */ (function(fs$readSync) { return function(fd, buffer, offset, length, position) { var eagCounter = 0; while (true) { try { - return fs$readSync.call(fs32, fd, buffer, offset, length, position); + return fs$readSync.call(fs33, fd, buffer, offset, length, position); } catch (er) { if (er.code === "EAGAIN" && eagCounter < 10) { eagCounter++; @@ -116566,10 +116566,10 @@ var require_polyfills = __commonJS({ } } }; - })(fs32.readSync); - function patchLchmod(fs33) { - fs33.lchmod = function(path30, mode, callback) { - fs33.open( + })(fs33.readSync); + function patchLchmod(fs34) { + fs34.lchmod = function(path30, mode, callback) { + fs34.open( path30, constants.O_WRONLY | constants.O_SYMLINK, mode, @@ -116578,80 +116578,80 @@ var require_polyfills = __commonJS({ if (callback) callback(err); return; } - fs33.fchmod(fd, mode, function(err2) { - fs33.close(fd, function(err22) { + fs34.fchmod(fd, mode, function(err2) { + fs34.close(fd, function(err22) { if (callback) callback(err2 || err22); }); }); } ); }; - fs33.lchmodSync = function(path30, mode) { - var fd = fs33.openSync(path30, constants.O_WRONLY | constants.O_SYMLINK, mode); + fs34.lchmodSync = function(path30, mode) { + var fd = fs34.openSync(path30, constants.O_WRONLY | constants.O_SYMLINK, mode); var threw = true; var ret; try { - ret = fs33.fchmodSync(fd, mode); + ret = fs34.fchmodSync(fd, mode); threw = false; } finally { if (threw) { try { - fs33.closeSync(fd); + fs34.closeSync(fd); } catch (er) { } } else { - fs33.closeSync(fd); + fs34.closeSync(fd); } } return ret; }; } - function patchLutimes(fs33) { - if (constants.hasOwnProperty("O_SYMLINK") && fs33.futimes) { - fs33.lutimes = function(path30, at, mt, cb) { - fs33.open(path30, constants.O_SYMLINK, function(er, fd) { + function patchLutimes(fs34) { + if (constants.hasOwnProperty("O_SYMLINK") && fs34.futimes) { + fs34.lutimes = function(path30, at, mt, cb) { + fs34.open(path30, constants.O_SYMLINK, function(er, fd) { if (er) { if (cb) cb(er); return; } - fs33.futimes(fd, at, mt, function(er2) { - fs33.close(fd, function(er22) { + fs34.futimes(fd, at, mt, function(er2) { + fs34.close(fd, function(er22) { if (cb) cb(er2 || er22); }); }); }); }; - fs33.lutimesSync = function(path30, at, mt) { - var fd = fs33.openSync(path30, constants.O_SYMLINK); + fs34.lutimesSync = function(path30, at, mt) { + var fd = fs34.openSync(path30, constants.O_SYMLINK); var ret; var threw = true; try { - ret = fs33.futimesSync(fd, at, mt); + ret = fs34.futimesSync(fd, at, mt); threw = false; } finally { if (threw) { try { - fs33.closeSync(fd); + fs34.closeSync(fd); } catch (er) { } } else { - fs33.closeSync(fd); + fs34.closeSync(fd); } } return ret; }; - } else if (fs33.futimes) { - fs33.lutimes = function(_a6, _b2, _c2, cb) { + } else if (fs34.futimes) { + fs34.lutimes = function(_a6, _b2, _c2, cb) { if (cb) process.nextTick(cb); }; - fs33.lutimesSync = function() { + fs34.lutimesSync = function() { }; } } function chmodFix(orig) { if (!orig) return orig; return function(target, mode, cb) { - return orig.call(fs32, target, mode, function(er) { + return orig.call(fs33, target, mode, function(er) { if (chownErOk(er)) er = null; if (cb) cb.apply(this, arguments); }); @@ -116661,7 +116661,7 @@ var require_polyfills = __commonJS({ if (!orig) return orig; return function(target, mode) { try { - return orig.call(fs32, target, mode); + return orig.call(fs33, target, mode); } catch (er) { if (!chownErOk(er)) throw er; } @@ -116670,7 +116670,7 @@ var require_polyfills = __commonJS({ function chownFix(orig) { if (!orig) return orig; return function(target, uid, gid, cb) { - return orig.call(fs32, target, uid, gid, function(er) { + return orig.call(fs33, target, uid, gid, function(er) { if (chownErOk(er)) er = null; if (cb) cb.apply(this, arguments); }); @@ -116680,7 +116680,7 @@ var require_polyfills = __commonJS({ if (!orig) return orig; return function(target, uid, gid) { try { - return orig.call(fs32, target, uid, gid); + return orig.call(fs33, target, uid, gid); } catch (er) { if (!chownErOk(er)) throw er; } @@ -116700,13 +116700,13 @@ var require_polyfills = __commonJS({ } if (cb) cb.apply(this, arguments); } - return options ? orig.call(fs32, target, options, callback) : orig.call(fs32, target, callback); + return options ? orig.call(fs33, target, options, callback) : orig.call(fs33, target, callback); }; } function statFixSync(orig) { if (!orig) return orig; return function(target, options) { - var stats = options ? orig.call(fs32, target, options) : orig.call(fs32, target); + var stats = options ? orig.call(fs33, target, options) : orig.call(fs33, target); if (stats) { if (stats.uid < 0) stats.uid += 4294967296; if (stats.gid < 0) stats.gid += 4294967296; @@ -116735,7 +116735,7 @@ var require_legacy_streams = __commonJS({ "node_modules/graceful-fs/legacy-streams.js"(exports2, module2) { var Stream = require("stream").Stream; module2.exports = legacy; - function legacy(fs32) { + function legacy(fs33) { return { ReadStream, WriteStream @@ -116778,7 +116778,7 @@ var require_legacy_streams = __commonJS({ }); return; } - fs32.open(this.path, this.flags, this.mode, function(err, fd) { + fs33.open(this.path, this.flags, this.mode, function(err, fd) { if (err) { self2.emit("error", err); self2.readable = false; @@ -116817,7 +116817,7 @@ var require_legacy_streams = __commonJS({ this.busy = false; this._queue = []; if (this.fd === null) { - this._open = fs32.open; + this._open = fs33.open; this._queue.push([this._open, this.path, this.flags, this.mode, void 0]); this.flush(); } @@ -116852,7 +116852,7 @@ var require_clone = __commonJS({ // node_modules/graceful-fs/graceful-fs.js var require_graceful_fs = __commonJS({ "node_modules/graceful-fs/graceful-fs.js"(exports2, module2) { - var fs32 = require("fs"); + var fs33 = require("fs"); var polyfills = require_polyfills(); var legacy = require_legacy_streams(); var clone = require_clone(); @@ -116884,12 +116884,12 @@ var require_graceful_fs = __commonJS({ m = "GFS4: " + m.split(/\n/).join("\nGFS4: "); console.error(m); }; - if (!fs32[gracefulQueue]) { + if (!fs33[gracefulQueue]) { queue2 = global[gracefulQueue] || []; - publishQueue(fs32, queue2); - fs32.close = (function(fs$close) { + publishQueue(fs33, queue2); + fs33.close = (function(fs$close) { function close(fd, cb) { - return fs$close.call(fs32, fd, function(err) { + return fs$close.call(fs33, fd, function(err) { if (!err) { resetQueue(); } @@ -116901,40 +116901,40 @@ var require_graceful_fs = __commonJS({ value: fs$close }); return close; - })(fs32.close); - fs32.closeSync = (function(fs$closeSync) { + })(fs33.close); + fs33.closeSync = (function(fs$closeSync) { function closeSync(fd) { - fs$closeSync.apply(fs32, arguments); + fs$closeSync.apply(fs33, arguments); resetQueue(); } Object.defineProperty(closeSync, previousSymbol, { value: fs$closeSync }); return closeSync; - })(fs32.closeSync); + })(fs33.closeSync); if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) { process.on("exit", function() { - debug6(fs32[gracefulQueue]); - require("assert").equal(fs32[gracefulQueue].length, 0); + debug6(fs33[gracefulQueue]); + require("assert").equal(fs33[gracefulQueue].length, 0); }); } } var queue2; if (!global[gracefulQueue]) { - publishQueue(global, fs32[gracefulQueue]); - } - module2.exports = patch(clone(fs32)); - if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs32.__patched) { - module2.exports = patch(fs32); - fs32.__patched = true; - } - function patch(fs33) { - polyfills(fs33); - fs33.gracefulify = patch; - fs33.createReadStream = createReadStream4; - fs33.createWriteStream = createWriteStream3; - var fs$readFile = fs33.readFile; - fs33.readFile = readFile; + publishQueue(global, fs33[gracefulQueue]); + } + module2.exports = patch(clone(fs33)); + if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs33.__patched) { + module2.exports = patch(fs33); + fs33.__patched = true; + } + function patch(fs34) { + polyfills(fs34); + fs34.gracefulify = patch; + fs34.createReadStream = createReadStream4; + fs34.createWriteStream = createWriteStream3; + var fs$readFile = fs34.readFile; + fs34.readFile = readFile; function readFile(path30, options, cb) { if (typeof options === "function") cb = options, options = null; @@ -116950,8 +116950,8 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$writeFile = fs33.writeFile; - fs33.writeFile = writeFile; + var fs$writeFile = fs34.writeFile; + fs34.writeFile = writeFile; function writeFile(path30, data, options, cb) { if (typeof options === "function") cb = options, options = null; @@ -116967,9 +116967,9 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$appendFile = fs33.appendFile; + var fs$appendFile = fs34.appendFile; if (fs$appendFile) - fs33.appendFile = appendFile; + fs34.appendFile = appendFile; function appendFile(path30, data, options, cb) { if (typeof options === "function") cb = options, options = null; @@ -116985,9 +116985,9 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$copyFile = fs33.copyFile; + var fs$copyFile = fs34.copyFile; if (fs$copyFile) - fs33.copyFile = copyFile2; + fs34.copyFile = copyFile2; function copyFile2(src, dest, flags, cb) { if (typeof flags === "function") { cb = flags; @@ -117005,8 +117005,8 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$readdir = fs33.readdir; - fs33.readdir = readdir3; + var fs$readdir = fs34.readdir; + fs34.readdir = readdir3; var noReaddirOptionVersions = /^v[0-5]\./; function readdir3(path30, options, cb) { if (typeof options === "function") @@ -117047,21 +117047,21 @@ var require_graceful_fs = __commonJS({ } } if (process.version.substr(0, 4) === "v0.8") { - var legStreams = legacy(fs33); + var legStreams = legacy(fs34); ReadStream = legStreams.ReadStream; WriteStream = legStreams.WriteStream; } - var fs$ReadStream = fs33.ReadStream; + var fs$ReadStream = fs34.ReadStream; if (fs$ReadStream) { ReadStream.prototype = Object.create(fs$ReadStream.prototype); ReadStream.prototype.open = ReadStream$open; } - var fs$WriteStream = fs33.WriteStream; + var fs$WriteStream = fs34.WriteStream; if (fs$WriteStream) { WriteStream.prototype = Object.create(fs$WriteStream.prototype); WriteStream.prototype.open = WriteStream$open; } - Object.defineProperty(fs33, "ReadStream", { + Object.defineProperty(fs34, "ReadStream", { get: function() { return ReadStream; }, @@ -117071,7 +117071,7 @@ var require_graceful_fs = __commonJS({ enumerable: true, configurable: true }); - Object.defineProperty(fs33, "WriteStream", { + Object.defineProperty(fs34, "WriteStream", { get: function() { return WriteStream; }, @@ -117082,7 +117082,7 @@ var require_graceful_fs = __commonJS({ configurable: true }); var FileReadStream = ReadStream; - Object.defineProperty(fs33, "FileReadStream", { + Object.defineProperty(fs34, "FileReadStream", { get: function() { return FileReadStream; }, @@ -117093,7 +117093,7 @@ var require_graceful_fs = __commonJS({ configurable: true }); var FileWriteStream = WriteStream; - Object.defineProperty(fs33, "FileWriteStream", { + Object.defineProperty(fs34, "FileWriteStream", { get: function() { return FileWriteStream; }, @@ -117142,13 +117142,13 @@ var require_graceful_fs = __commonJS({ }); } function createReadStream4(path30, options) { - return new fs33.ReadStream(path30, options); + return new fs34.ReadStream(path30, options); } function createWriteStream3(path30, options) { - return new fs33.WriteStream(path30, options); + return new fs34.WriteStream(path30, options); } - var fs$open = fs33.open; - fs33.open = open; + var fs$open = fs34.open; + fs34.open = open; function open(path30, flags, mode, cb) { if (typeof mode === "function") cb = mode, mode = null; @@ -117164,20 +117164,20 @@ var require_graceful_fs = __commonJS({ }); } } - return fs33; + return fs34; } function enqueue(elem) { debug6("ENQUEUE", elem[0].name, elem[1]); - fs32[gracefulQueue].push(elem); + fs33[gracefulQueue].push(elem); retry2(); } var retryTimer; function resetQueue() { var now = Date.now(); - for (var i = 0; i < fs32[gracefulQueue].length; ++i) { - if (fs32[gracefulQueue][i].length > 2) { - fs32[gracefulQueue][i][3] = now; - fs32[gracefulQueue][i][4] = now; + for (var i = 0; i < fs33[gracefulQueue].length; ++i) { + if (fs33[gracefulQueue][i].length > 2) { + fs33[gracefulQueue][i][3] = now; + fs33[gracefulQueue][i][4] = now; } } retry2(); @@ -117185,9 +117185,9 @@ var require_graceful_fs = __commonJS({ function retry2() { clearTimeout(retryTimer); retryTimer = void 0; - if (fs32[gracefulQueue].length === 0) + if (fs33[gracefulQueue].length === 0) return; - var elem = fs32[gracefulQueue].shift(); + var elem = fs33[gracefulQueue].shift(); var fn = elem[0]; var args = elem[1]; var err = elem[2]; @@ -117209,7 +117209,7 @@ var require_graceful_fs = __commonJS({ debug6("RETRY", fn.name, args); fn.apply(null, args.concat([startTime])); } else { - fs32[gracefulQueue].push(elem); + fs33[gracefulQueue].push(elem); } } if (retryTimer === void 0) { @@ -128032,7 +128032,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s)) retur g.minimatch.escape = vi.escape; g.minimatch.unescape = Ei.unescape; }); - var fs32 = R((Wt) => { + var fs33 = R((Wt) => { "use strict"; Object.defineProperty(Wt, "__esModule", { value: true }); Wt.LRUCache = void 0; @@ -128901,7 +128901,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s)) retur }; Object.defineProperty(_2, "__esModule", { value: true }); _2.PathScurry = _2.Path = _2.PathScurryDarwin = _2.PathScurryPosix = _2.PathScurryWin32 = _2.PathScurryBase = _2.PathPosix = _2.PathWin32 = _2.PathBase = _2.ChildrenCache = _2.ResolveCache = void 0; - var Qt = fs32(), Yt = require("node:path"), yr = require("node:url"), pt = require("fs"), Sr = br(require("node:fs")), vr = pt.realpathSync.native, Ht = require("node:fs/promises"), bs = Oe(), mt = { lstatSync: pt.lstatSync, readdir: pt.readdir, readdirSync: pt.readdirSync, readlinkSync: pt.readlinkSync, realpathSync: vr, promises: { lstat: Ht.lstat, readdir: Ht.readdir, readlink: Ht.readlink, realpath: Ht.realpath } }, _s2 = (n) => !n || n === mt || n === Sr ? mt : { ...mt, ...n, promises: { ...mt.promises, ...n.promises || {} } }, Os = /^\\\\\?\\([a-z]:)\\?$/i, Er = (n) => n.replace(/\//g, "\\").replace(Os, "$1\\"), _r2 = /[\\\/]/, N = 0, xs = 1, Ts = 2, G = 4, Cs = 6, Rs = 8, Q = 10, As = 12, j = 15, dt = ~j, xe = 16, ys = 32, gt = 64, W = 128, Vt = 256, Xt = 512, Ss = gt | W | Xt, Or = 1023, Te = (n) => n.isFile() ? Rs : n.isDirectory() ? G : n.isSymbolicLink() ? Q : n.isCharacterDevice() ? Ts : n.isBlockDevice() ? Cs : n.isSocket() ? As : n.isFIFO() ? xs : N, vs = new Qt.LRUCache({ max: 2 ** 12 }), wt = (n) => { + var Qt = fs33(), Yt = require("node:path"), yr = require("node:url"), pt = require("fs"), Sr = br(require("node:fs")), vr = pt.realpathSync.native, Ht = require("node:fs/promises"), bs = Oe(), mt = { lstatSync: pt.lstatSync, readdir: pt.readdir, readdirSync: pt.readdirSync, readlinkSync: pt.readlinkSync, realpathSync: vr, promises: { lstat: Ht.lstat, readdir: Ht.readdir, readlink: Ht.readlink, realpath: Ht.realpath } }, _s2 = (n) => !n || n === mt || n === Sr ? mt : { ...mt, ...n, promises: { ...mt.promises, ...n.promises || {} } }, Os = /^\\\\\?\\([a-z]:)\\?$/i, Er = (n) => n.replace(/\//g, "\\").replace(Os, "$1\\"), _r2 = /[\\\/]/, N = 0, xs = 1, Ts = 2, G = 4, Cs = 6, Rs = 8, Q = 10, As = 12, j = 15, dt = ~j, xe = 16, ys = 32, gt = 64, W = 128, Vt = 256, Xt = 512, Ss = gt | W | Xt, Or = 1023, Te = (n) => n.isFile() ? Rs : n.isDirectory() ? G : n.isSymbolicLink() ? Q : n.isCharacterDevice() ? Ts : n.isBlockDevice() ? Cs : n.isSocket() ? As : n.isFIFO() ? xs : N, vs = new Qt.LRUCache({ max: 2 ** 12 }), wt = (n) => { let t = vs.get(n); if (t) return t; let e = n.normalize("NFKD"); @@ -130279,7 +130279,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s)) retur // node_modules/archiver-utils/file.js var require_file3 = __commonJS({ "node_modules/archiver-utils/file.js"(exports2, module2) { - var fs32 = require_graceful_fs(); + var fs33 = require_graceful_fs(); var path30 = require("path"); var flatten = require_flatten(); var difference = require_difference(); @@ -130306,7 +130306,7 @@ var require_file3 = __commonJS({ }; file.exists = function() { var filepath = path30.join.apply(path30, arguments); - return fs32.existsSync(filepath); + return fs33.existsSync(filepath); }; file.expand = function(...args) { var options = isPlainObject4(args[0]) ? args.shift() : {}; @@ -130324,7 +130324,7 @@ var require_file3 = __commonJS({ if (typeof options.filter === "function") { return options.filter(filepath); } else { - return fs32.statSync(filepath)[options.filter](); + return fs33.statSync(filepath)[options.filter](); } } catch (e) { return false; @@ -130432,7 +130432,7 @@ var require_file3 = __commonJS({ // node_modules/archiver-utils/index.js var require_archiver_utils = __commonJS({ "node_modules/archiver-utils/index.js"(exports2, module2) { - var fs32 = require_graceful_fs(); + var fs33 = require_graceful_fs(); var path30 = require("path"); var isStream2 = require_is_stream(); var lazystream = require_lazystream(); @@ -130481,7 +130481,7 @@ var require_archiver_utils = __commonJS({ }; utils.lazyReadStream = function(filepath) { return new lazystream.Readable(function() { - return fs32.createReadStream(filepath); + return fs33.createReadStream(filepath); }); }; utils.normalizeInputSource = function(source) { @@ -130509,7 +130509,7 @@ var require_archiver_utils = __commonJS({ callback = base; base = dirpath; } - fs32.readdir(dirpath, function(err, list) { + fs33.readdir(dirpath, function(err, list) { var i = 0; var file; var filepath; @@ -130522,7 +130522,7 @@ var require_archiver_utils = __commonJS({ return callback(null, results); } filepath = path30.join(dirpath, file); - fs32.stat(filepath, function(err2, stats) { + fs33.stat(filepath, function(err2, stats) { results.push({ path: filepath, relative: path30.relative(base, filepath).replace(/\\/g, "/"), @@ -130584,7 +130584,7 @@ var require_error3 = __commonJS({ // node_modules/@actions/artifact/node_modules/archiver/lib/core.js var require_core2 = __commonJS({ "node_modules/@actions/artifact/node_modules/archiver/lib/core.js"(exports2, module2) { - var fs32 = require("fs"); + var fs33 = require("fs"); var glob2 = require_readdir_glob(); var async = require_async(); var path30 = require("path"); @@ -130648,7 +130648,7 @@ var require_core2 = __commonJS({ data.sourcePath = filepath; task.data = data; this._entriesCount++; - if (data.stats && data.stats instanceof fs32.Stats) { + if (data.stats && data.stats instanceof fs33.Stats) { task = this._updateQueueTaskWithStats(task, data.stats); if (task) { if (data.stats.size) { @@ -130819,7 +130819,7 @@ var require_core2 = __commonJS({ callback(); return; } - fs32.lstat(task.filepath, function(err, stats) { + fs33.lstat(task.filepath, function(err, stats) { if (this._state.aborted) { setImmediate(callback); return; @@ -130862,7 +130862,7 @@ var require_core2 = __commonJS({ task.data.sourceType = "buffer"; task.source = Buffer.concat([]); } else if (stats.isSymbolicLink() && this._moduleSupports("symlink")) { - var linkPath = fs32.readlinkSync(task.filepath); + var linkPath = fs33.readlinkSync(task.filepath); var dirName = path30.dirname(task.filepath); task.data.type = "symlink"; task.data.linkname = path30.relative(dirName, path30.resolve(dirName, linkPath)); @@ -141764,7 +141764,7 @@ var require_parser_stream = __commonJS({ var require_mkdirp = __commonJS({ "node_modules/mkdirp/index.js"(exports2, module2) { var path30 = require("path"); - var fs32 = require("fs"); + var fs33 = require("fs"); var _0777 = parseInt("0777", 8); module2.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; function mkdirP(p, opts, f, made) { @@ -141775,7 +141775,7 @@ var require_mkdirp = __commonJS({ opts = { mode: opts }; } var mode = opts.mode; - var xfs = opts.fs || fs32; + var xfs = opts.fs || fs33; if (mode === void 0) { mode = _0777; } @@ -141814,7 +141814,7 @@ var require_mkdirp = __commonJS({ opts = { mode: opts }; } var mode = opts.mode; - var xfs = opts.fs || fs32; + var xfs = opts.fs || fs33; if (mode === void 0) { mode = _0777; } @@ -141851,7 +141851,7 @@ var require_mkdirp = __commonJS({ // node_modules/unzip-stream/lib/extract.js var require_extract2 = __commonJS({ "node_modules/unzip-stream/lib/extract.js"(exports2, module2) { - var fs32 = require("fs"); + var fs33 = require("fs"); var path30 = require("path"); var util4 = require("util"); var mkdirp = require_mkdirp(); @@ -141898,7 +141898,7 @@ var require_extract2 = __commonJS({ var directory = entry.isDirectory ? destPath : path30.dirname(destPath); this.unfinishedEntries++; var writeFileFn = function() { - var pipedStream = fs32.createWriteStream(destPath); + var pipedStream = fs33.createWriteStream(destPath); pipedStream.on("close", function() { self2.unfinishedEntries--; self2._notifyAwaiter(); @@ -143096,7 +143096,7 @@ var require_file_command2 = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.prepareKeyValueMessage = exports2.issueFileCommand = void 0; var crypto3 = __importStar2(require("crypto")); - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var os7 = __importStar2(require("os")); var utils_1 = require_utils11(); function issueFileCommand(command, message) { @@ -143104,10 +143104,10 @@ var require_file_command2 = __commonJS({ if (!filePath) { throw new Error(`Unable to find environment variable for file command ${command}`); } - if (!fs32.existsSync(filePath)) { + if (!fs33.existsSync(filePath)) { throw new Error(`Missing file at path: ${filePath}`); } - fs32.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os7.EOL}`, { + fs33.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os7.EOL}`, { encoding: "utf8" }); } @@ -144430,12 +144430,12 @@ var require_io_util2 = __commonJS({ var _a6; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.getCmdPath = exports2.tryGetExecutablePath = exports2.isRooted = exports2.isDirectory = exports2.exists = exports2.READONLY = exports2.UV_FS_O_EXLOCK = exports2.IS_WINDOWS = exports2.unlink = exports2.symlink = exports2.stat = exports2.rmdir = exports2.rm = exports2.rename = exports2.readlink = exports2.readdir = exports2.open = exports2.mkdir = exports2.lstat = exports2.copyFile = exports2.chmod = void 0; - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var path30 = __importStar2(require("path")); - _a6 = fs32.promises, exports2.chmod = _a6.chmod, exports2.copyFile = _a6.copyFile, exports2.lstat = _a6.lstat, exports2.mkdir = _a6.mkdir, exports2.open = _a6.open, exports2.readdir = _a6.readdir, exports2.readlink = _a6.readlink, exports2.rename = _a6.rename, exports2.rm = _a6.rm, exports2.rmdir = _a6.rmdir, exports2.stat = _a6.stat, exports2.symlink = _a6.symlink, exports2.unlink = _a6.unlink; + _a6 = fs33.promises, exports2.chmod = _a6.chmod, exports2.copyFile = _a6.copyFile, exports2.lstat = _a6.lstat, exports2.mkdir = _a6.mkdir, exports2.open = _a6.open, exports2.readdir = _a6.readdir, exports2.readlink = _a6.readlink, exports2.rename = _a6.rename, exports2.rm = _a6.rm, exports2.rmdir = _a6.rmdir, exports2.stat = _a6.stat, exports2.symlink = _a6.symlink, exports2.unlink = _a6.unlink; exports2.IS_WINDOWS = process.platform === "win32"; exports2.UV_FS_O_EXLOCK = 268435456; - exports2.READONLY = fs32.constants.O_RDONLY; + exports2.READONLY = fs33.constants.O_RDONLY; function exists(fsPath) { return __awaiter2(this, void 0, void 0, function* () { try { @@ -145824,25 +145824,25 @@ var require_upload_specification = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.getUploadSpecification = void 0; - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var core_1 = require_core3(); var path_1 = require("path"); var path_and_artifact_name_validation_1 = require_path_and_artifact_name_validation2(); function getUploadSpecification(artifactName, rootDirectory, artifactFiles) { const specifications = []; - if (!fs32.existsSync(rootDirectory)) { + if (!fs33.existsSync(rootDirectory)) { throw new Error(`Provided rootDirectory ${rootDirectory} does not exist`); } - if (!fs32.statSync(rootDirectory).isDirectory()) { + if (!fs33.statSync(rootDirectory).isDirectory()) { throw new Error(`Provided rootDirectory ${rootDirectory} is not a valid directory`); } rootDirectory = (0, path_1.normalize)(rootDirectory); rootDirectory = (0, path_1.resolve)(rootDirectory); for (let file of artifactFiles) { - if (!fs32.existsSync(file)) { + if (!fs33.existsSync(file)) { throw new Error(`File ${file} does not exist`); } - if (!fs32.statSync(file).isDirectory()) { + if (!fs33.statSync(file).isDirectory()) { file = (0, path_1.normalize)(file); file = (0, path_1.resolve)(file); if (!file.startsWith(rootDirectory)) { @@ -145867,11 +145867,11 @@ var require_upload_specification = __commonJS({ // node_modules/tmp/lib/tmp.js var require_tmp = __commonJS({ "node_modules/tmp/lib/tmp.js"(exports2, module2) { - var fs32 = require("fs"); + var fs33 = require("fs"); var os7 = require("os"); var path30 = require("path"); var crypto3 = require("crypto"); - var _c2 = { fs: fs32.constants, os: os7.constants }; + var _c2 = { fs: fs33.constants, os: os7.constants }; var RANDOM_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; var TEMPLATE_PATTERN = /XXXXXX/; var DEFAULT_TRIES = 3; @@ -145883,13 +145883,13 @@ var require_tmp = __commonJS({ var FILE_MODE = 384; var EXIT = "exit"; var _removeObjects = []; - var FN_RMDIR_SYNC = fs32.rmdirSync.bind(fs32); + var FN_RMDIR_SYNC = fs33.rmdirSync.bind(fs33); var _gracefulCleanup = false; function rimraf(dirPath, callback) { - return fs32.rm(dirPath, { recursive: true }, callback); + return fs33.rm(dirPath, { recursive: true }, callback); } function FN_RIMRAF_SYNC(dirPath) { - return fs32.rmSync(dirPath, { recursive: true }); + return fs33.rmSync(dirPath, { recursive: true }); } function tmpName(options, callback) { const args = _parseArguments(options, callback), opts = args[0], cb = args[1]; @@ -145899,7 +145899,7 @@ var require_tmp = __commonJS({ (function _getUniqueName() { try { const name = _generateTmpName(sanitizedOptions); - fs32.stat(name, function(err2) { + fs33.stat(name, function(err2) { if (!err2) { if (tries-- > 0) return _getUniqueName(); return cb(new Error("Could not get a unique tmp filename, max tries reached " + name)); @@ -145919,7 +145919,7 @@ var require_tmp = __commonJS({ do { const name = _generateTmpName(sanitizedOptions); try { - fs32.statSync(name); + fs33.statSync(name); } catch (e) { return name; } @@ -145930,10 +145930,10 @@ var require_tmp = __commonJS({ const args = _parseArguments(options, callback), opts = args[0], cb = args[1]; tmpName(opts, function _tmpNameCreated(err, name) { if (err) return cb(err); - fs32.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) { + fs33.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) { if (err2) return cb(err2); if (opts.discardDescriptor) { - return fs32.close(fd, function _discardCallback(possibleErr) { + return fs33.close(fd, function _discardCallback(possibleErr) { return cb(possibleErr, name, void 0, _prepareTmpFileRemoveCallback(name, -1, opts, false)); }); } else { @@ -145947,9 +145947,9 @@ var require_tmp = __commonJS({ const args = _parseArguments(options), opts = args[0]; const discardOrDetachDescriptor = opts.discardDescriptor || opts.detachDescriptor; const name = tmpNameSync(opts); - let fd = fs32.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE); + let fd = fs33.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE); if (opts.discardDescriptor) { - fs32.closeSync(fd); + fs33.closeSync(fd); fd = void 0; } return { @@ -145962,7 +145962,7 @@ var require_tmp = __commonJS({ const args = _parseArguments(options, callback), opts = args[0], cb = args[1]; tmpName(opts, function _tmpNameCreated(err, name) { if (err) return cb(err); - fs32.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) { + fs33.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) { if (err2) return cb(err2); cb(null, name, _prepareTmpDirRemoveCallback(name, opts, false)); }); @@ -145971,7 +145971,7 @@ var require_tmp = __commonJS({ function dirSync(options) { const args = _parseArguments(options), opts = args[0]; const name = tmpNameSync(opts); - fs32.mkdirSync(name, opts.mode || DIR_MODE); + fs33.mkdirSync(name, opts.mode || DIR_MODE); return { name, removeCallback: _prepareTmpDirRemoveCallback(name, opts, true) @@ -145985,20 +145985,20 @@ var require_tmp = __commonJS({ next(); }; if (0 <= fdPath[0]) - fs32.close(fdPath[0], function() { - fs32.unlink(fdPath[1], _handler); + fs33.close(fdPath[0], function() { + fs33.unlink(fdPath[1], _handler); }); - else fs32.unlink(fdPath[1], _handler); + else fs33.unlink(fdPath[1], _handler); } function _removeFileSync(fdPath) { let rethrownException = null; try { - if (0 <= fdPath[0]) fs32.closeSync(fdPath[0]); + if (0 <= fdPath[0]) fs33.closeSync(fdPath[0]); } catch (e) { if (!_isEBADF(e) && !_isENOENT(e)) throw e; } finally { try { - fs32.unlinkSync(fdPath[1]); + fs33.unlinkSync(fdPath[1]); } catch (e) { if (!_isENOENT(e)) rethrownException = e; } @@ -146014,7 +146014,7 @@ var require_tmp = __commonJS({ return sync ? removeCallbackSync : removeCallback; } function _prepareTmpDirRemoveCallback(name, opts, sync) { - const removeFunction = opts.unsafeCleanup ? rimraf : fs32.rmdir.bind(fs32); + const removeFunction = opts.unsafeCleanup ? rimraf : fs33.rmdir.bind(fs33); const removeFunctionSync = opts.unsafeCleanup ? FN_RIMRAF_SYNC : FN_RMDIR_SYNC; const removeCallbackSync = _prepareRemoveCallback(removeFunctionSync, name, sync); const removeCallback = _prepareRemoveCallback(removeFunction, name, sync, removeCallbackSync); @@ -146077,24 +146077,24 @@ var require_tmp = __commonJS({ } function _resolvePath(name, tmpDir, cb) { const pathToResolve = path30.isAbsolute(name) ? name : path30.join(tmpDir, name); - fs32.stat(pathToResolve, function(err) { + fs33.stat(pathToResolve, function(err) { if (err) { - fs32.realpath(path30.dirname(pathToResolve), function(err2, parentDir) { + fs33.realpath(path30.dirname(pathToResolve), function(err2, parentDir) { if (err2) return cb(err2); cb(null, path30.join(parentDir, path30.basename(pathToResolve))); }); } else { - fs32.realpath(pathToResolve, cb); + fs33.realpath(pathToResolve, cb); } }); } function _resolvePathSync(name, tmpDir) { const pathToResolve = path30.isAbsolute(name) ? name : path30.join(tmpDir, name); try { - fs32.statSync(pathToResolve); - return fs32.realpathSync(pathToResolve); + fs33.statSync(pathToResolve); + return fs33.realpathSync(pathToResolve); } catch (_err) { - const parentDir = fs32.realpathSync(path30.dirname(pathToResolve)); + const parentDir = fs33.realpathSync(path30.dirname(pathToResolve)); return path30.join(parentDir, path30.basename(pathToResolve)); } } @@ -146215,10 +146215,10 @@ var require_tmp = __commonJS({ _gracefulCleanup = true; } function _getTmpDir(options, cb) { - return fs32.realpath(options && options.tmpdir || os7.tmpdir(), cb); + return fs33.realpath(options && options.tmpdir || os7.tmpdir(), cb); } function _getTmpDirSync(options) { - return fs32.realpathSync(options && options.tmpdir || os7.tmpdir()); + return fs33.realpathSync(options && options.tmpdir || os7.tmpdir()); } process.addListener(EXIT, _garbageCollector); Object.defineProperty(module2.exports, "tmpdir", { @@ -147072,10 +147072,10 @@ var require_upload_gzip = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.createGZipFileInBuffer = exports2.createGZipFileOnDisk = void 0; - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var zlib3 = __importStar2(require("zlib")); var util_1 = require("util"); - var stat2 = (0, util_1.promisify)(fs32.stat); + var stat2 = (0, util_1.promisify)(fs33.stat); var gzipExemptFileExtensions = [ ".gz", ".gzip", @@ -147108,9 +147108,9 @@ var require_upload_gzip = __commonJS({ } } return new Promise((resolve15, reject) => { - const inputStream = fs32.createReadStream(originalFilePath); + const inputStream = fs33.createReadStream(originalFilePath); const gzip = zlib3.createGzip(); - const outputStream = fs32.createWriteStream(tempFilePath); + const outputStream = fs33.createWriteStream(tempFilePath); inputStream.pipe(gzip).pipe(outputStream); outputStream.on("finish", () => __awaiter2(this, void 0, void 0, function* () { const size = (yield stat2(tempFilePath)).size; @@ -147128,7 +147128,7 @@ var require_upload_gzip = __commonJS({ return __awaiter2(this, void 0, void 0, function* () { return new Promise((resolve15) => __awaiter2(this, void 0, void 0, function* () { var _a6, e_1, _b2, _c2; - const inputStream = fs32.createReadStream(originalFilePath); + const inputStream = fs33.createReadStream(originalFilePath); const gzip = zlib3.createGzip(); inputStream.pipe(gzip); const chunks = []; @@ -147337,7 +147337,7 @@ var require_upload_http_client = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.UploadHttpClient = void 0; - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var core29 = __importStar2(require_core3()); var tmp2 = __importStar2(require_tmp_promise()); var stream2 = __importStar2(require("stream")); @@ -147351,7 +147351,7 @@ var require_upload_http_client = __commonJS({ var http_manager_1 = require_http_manager(); var upload_gzip_1 = require_upload_gzip(); var requestUtils_1 = require_requestUtils2(); - var stat2 = (0, util_1.promisify)(fs32.stat); + var stat2 = (0, util_1.promisify)(fs33.stat); var UploadHttpClient = class { constructor() { this.uploadHttpManager = new http_manager_1.HttpManager((0, config_variables_1.getUploadFileConcurrency)(), "@actions/artifact-upload"); @@ -147488,7 +147488,7 @@ var require_upload_http_client = __commonJS({ let openUploadStream; if (totalFileSize < buffer.byteLength) { core29.debug(`The gzip file created for ${parameters.file} did not help with reducing the size of the file. The original file will be uploaded as-is`); - openUploadStream = () => fs32.createReadStream(parameters.file); + openUploadStream = () => fs33.createReadStream(parameters.file); isGzip = false; uploadFileSize = totalFileSize; } else { @@ -147534,7 +147534,7 @@ var require_upload_http_client = __commonJS({ failedChunkSizes += chunkSize; continue; } - const result = yield this.uploadChunk(httpClientIndex, parameters.resourceUrl, () => fs32.createReadStream(uploadFilePath, { + const result = yield this.uploadChunk(httpClientIndex, parameters.resourceUrl, () => fs33.createReadStream(uploadFilePath, { start: startChunkIndex, end: endChunkIndex, autoClose: false @@ -147729,7 +147729,7 @@ var require_download_http_client = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.DownloadHttpClient = void 0; - var fs32 = __importStar2(require("fs")); + var fs33 = __importStar2(require("fs")); var core29 = __importStar2(require_core3()); var zlib3 = __importStar2(require("zlib")); var utils_1 = require_utils12(); @@ -147820,7 +147820,7 @@ var require_download_http_client = __commonJS({ return __awaiter2(this, void 0, void 0, function* () { let retryCount = 0; const retryLimit = (0, config_variables_1.getRetryLimit)(); - let destinationStream = fs32.createWriteStream(downloadPath); + let destinationStream = fs33.createWriteStream(downloadPath); const headers = (0, utils_1.getDownloadHeaders)("application/json", true, true); const makeDownloadRequest = () => __awaiter2(this, void 0, void 0, function* () { const client = this.downloadHttpManager.getClient(httpClientIndex); @@ -147862,7 +147862,7 @@ var require_download_http_client = __commonJS({ } }); yield (0, utils_1.rmFile)(fileDownloadPath); - destinationStream = fs32.createWriteStream(fileDownloadPath); + destinationStream = fs33.createWriteStream(fileDownloadPath); }); while (retryCount <= retryLimit) { let response; @@ -166068,7 +166068,7 @@ __export(entry_points_exports, { module.exports = __toCommonJS(entry_points_exports); // src/analyze-action.ts -var fs23 = __toESM(require("fs")); +var fs24 = __toESM(require("fs")); var import_path5 = __toESM(require("path")); var import_perf_hooks6 = require("perf_hooks"); var core14 = __toESM(require_core()); @@ -166219,21 +166219,21 @@ async function getFolderSize(itemPath, options) { getFolderSize.loose = async (itemPath, options) => await core2(itemPath, options); getFolderSize.strict = async (itemPath, options) => await core2(itemPath, options, { strict: true }); async function core2(rootItemPath, options = {}, returnType = {}) { - const fs32 = options.fs || await import("node:fs/promises"); + const fs33 = options.fs || await import("node:fs/promises"); let folderSize = 0n; const foundInos = /* @__PURE__ */ new Set(); const errors = []; await processItem(rootItemPath); async function processItem(itemPath) { if (options.ignore?.test(itemPath)) return; - const stats = returnType.strict ? await fs32.lstat(itemPath, { bigint: true }) : await fs32.lstat(itemPath, { bigint: true }).catch((error3) => errors.push(error3)); + const stats = returnType.strict ? await fs33.lstat(itemPath, { bigint: true }) : await fs33.lstat(itemPath, { bigint: true }).catch((error3) => errors.push(error3)); if (typeof stats !== "object") return; if (!foundInos.has(stats.ino)) { foundInos.add(stats.ino); folderSize += stats.size; } if (stats.isDirectory()) { - const directoryItems = returnType.strict ? await fs32.readdir(itemPath) : await fs32.readdir(itemPath).catch((error3) => errors.push(error3)); + const directoryItems = returnType.strict ? await fs33.readdir(itemPath) : await fs33.readdir(itemPath).catch((error3) => errors.push(error3)); if (typeof directoryItems !== "object") return; await Promise.all( directoryItems.map( @@ -169994,6 +169994,9 @@ function wrapError(error3) { function getErrorMessage(error3) { return error3 instanceof Error ? error3.message : String(error3); } +function isErrnoException(error3) { + return typeof error3 === "object" && error3 !== null && "code" in error3 && typeof error3.code === "string"; +} function prettyPrintPack(pack) { return `${pack.name}${pack.version ? `@${pack.version}` : ""}${pack.path ? `:${pack.path}` : ""}`; } @@ -172670,13 +172673,13 @@ var SarifScanOrder = [ ]; // src/analyze.ts -var fs17 = __toESM(require("fs")); +var fs18 = __toESM(require("fs")); var path16 = __toESM(require("path")); var import_perf_hooks5 = require("perf_hooks"); var io5 = __toESM(require_io()); // src/codeql.ts -var fs16 = __toESM(require("fs")); +var fs17 = __toESM(require("fs")); var path15 = __toESM(require("path")); var core12 = __toESM(require_core()); var toolrunner3 = __toESM(require_toolrunner()); @@ -172931,7 +172934,7 @@ function wrapCliConfigurationError(cliError) { } // src/config-utils.ts -var fs10 = __toESM(require("fs")); +var fs11 = __toESM(require("fs")); var path11 = __toESM(require("path")); var import_perf_hooks2 = require("perf_hooks"); @@ -172991,7 +172994,7 @@ var jsonschema = __toESM(require_lib2()); var semver4 = __toESM(require_semver2()); // src/diagnostics.ts -var import_fs = require("fs"); +var fs7 = __toESM(require("fs")); var import_path2 = __toESM(require("path")); var temporaryDiagnostics = []; var diagnosticCounter = 0; @@ -173012,11 +173015,10 @@ function getDiagnosticsPath(basePath, language) { } return basePath; } -function addDiagnostic(config, language, diagnostic) { - const logger2 = getActionsLogger(); +function addDiagnostic(config, language, diagnostic, logger2 = getActionsLogger()) { const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; - if ((0, import_fs.existsSync)(databasePath)) { - writeDiagnostic(config, language, diagnostic); + if (fs7.existsSync(databasePath)) { + writeDiagnostic({ logger: logger2 }, config, language, diagnostic); } else { logger2.debug( `Writing a diagnostic for ${language}, but the database at ${databasePath} does not exist yet.` @@ -173042,7 +173044,7 @@ function addNoLanguageDiagnostic(config, diagnostic) { } } function writeDiagnosticFile(diagnosticsPath, diagnostic) { - (0, import_fs.mkdirSync)(diagnosticsPath, { recursive: true }); + fs7.mkdirSync(diagnosticsPath, { recursive: true }); const uniqueSuffix = (diagnosticCounter++).toString(); const sanitizedTimestamp = diagnostic.timestamp.replace( /[^a-zA-Z0-9.-]/g, @@ -173052,40 +173054,40 @@ function writeDiagnosticFile(diagnosticsPath, diagnostic) { diagnosticsPath, `codeql-action-${sanitizedTimestamp}-${uniqueSuffix}.json` ); - (0, import_fs.writeFileSync)(jsonPath, JSON.stringify(diagnostic)); + fs7.writeFileSync(jsonPath, JSON.stringify(diagnostic)); return jsonPath; } function getDatabaseDiagnosticsPath(config, language) { return getDiagnosticsPath(config.dbLocation, language); } -function writeDiagnostic(config, language, diagnostic) { - const logger2 = getActionsLogger(); +function writeDiagnostic(action, config, language, diagnostic) { const diagnosticsPath = getDatabaseDiagnosticsPath(config, language); try { writeDiagnosticFile(diagnosticsPath, diagnostic); } catch (err) { - logger2.warning(`Unable to write diagnostic message to database: ${err}`); - logger2.debug(JSON.stringify(diagnostic)); + action.logger.warning( + `Unable to write diagnostic message to database: ${err}` + ); + action.logger.debug(JSON.stringify(diagnostic)); } } -function logTemporaryDiagnostics() { - const logger2 = getActionsLogger(); +function logTemporaryDiagnostics(action) { const num = temporaryDiagnostics.length; if (num > 0) { - logger2.warning( + action.logger.warning( `${num} diagnostic(s) could not be written to the database and will not appear on the Tool Status Page.` ); for (const temporary of temporaryDiagnostics) { - logger2.debug((0, import_fs.readFileSync)(temporary.path, "utf-8")); + action.logger.debug(fs7.readFileSync(temporary.path, "utf-8")); } } } -function flushDiagnostics(config) { - const logger2 = getActionsLogger(); +function flushDiagnostics(action, config) { const diagnosticsCount = temporaryDiagnostics.length; - logger2.debug( + action.logger.debug( `Moving ${diagnosticsCount} diagnostic(s) to their respective databases.` ); + const failedFlushDiagnostics = []; for (const temporary of temporaryDiagnostics) { const directory = getDatabaseDiagnosticsPath( config, @@ -173093,9 +173095,25 @@ function flushDiagnostics(config) { ); const filename = import_path2.default.basename(temporary.path); const destination = import_path2.default.join(directory, filename); - (0, import_fs.renameSync)(temporary.path, destination); + try { + fs7.mkdirSync(directory, { recursive: true }); + try { + fs7.renameSync(temporary.path, destination); + } catch (renameErr) { + if (!isErrnoException(renameErr) || renameErr.code !== "EXDEV") { + throw renameErr; + } + fs7.copyFileSync(temporary.path, destination); + fs7.unlinkSync(temporary.path); + } + } catch (err) { + action.logger.warning( + `Failed to relocate '${temporary.path}' to '${destination}': ${getErrorMessage(err)}` + ); + failedFlushDiagnostics.push(temporary); + } } - temporaryDiagnostics = []; + temporaryDiagnostics = failedFlushDiagnostics; } function makeTelemetryDiagnostic(id, name, attributes, tags) { return makeDiagnostic(id, name, { @@ -173757,7 +173775,7 @@ async function getRemoteConfig(actionState, configFile, apiDetails) { } // src/diff-informed-analysis-utils.ts -var fs7 = __toESM(require("fs")); +var fs8 = __toESM(require("fs")); async function getDiffInformedAnalysisBranches(codeql, features, logger2) { if (!await features.getValue("diff_informed_queries" /* DiffInformedQueries */, codeql)) { return void 0; @@ -173799,7 +173817,7 @@ async function prepareDiffInformedAnalysis(codeql, features, logger2) { function writeDiffRangesJsonFile(logger2, ranges) { const jsonContents = JSON.stringify(ranges, null, 2); const jsonFilePath = getDiffRangesJsonFilePath(); - fs7.writeFileSync(jsonFilePath, jsonContents); + fs8.writeFileSync(jsonFilePath, jsonContents); logger2.debug( `Wrote pr-diff-range JSON file to ${jsonFilePath}: ${jsonContents}` @@ -173807,11 +173825,11 @@ ${jsonContents}` } function readDiffRangesJsonFile(logger2) { const jsonFilePath = getDiffRangesJsonFilePath(); - if (!fs7.existsSync(jsonFilePath)) { + if (!fs8.existsSync(jsonFilePath)) { logger2.debug(`Diff ranges JSON file does not exist at ${jsonFilePath}`); return void 0; } - const jsonContents = fs7.readFileSync(jsonFilePath, "utf8"); + const jsonContents = fs8.readFileSync(jsonFilePath, "utf8"); logger2.debug( `Read pr-diff-range JSON file from ${jsonFilePath}: ${jsonContents}` @@ -174062,7 +174080,7 @@ Improved incremental analysis will be automatically retried when the next versio } // src/overlay/status.ts -var fs8 = __toESM(require("fs")); +var fs9 = __toESM(require("fs")); var path9 = __toESM(require("path")); var actionsCache = __toESM(require_cache4()); var MAX_CACHE_OPERATION_MS = 3e4; @@ -174107,7 +174125,7 @@ async function getOverlayStatus(codeql, languages, diskUsage, logger2) { const cacheKey3 = await getCacheKey(codeql, languages, diskUsage); const statusFile = getStatusFilePath(languages); try { - await fs8.promises.mkdir(path9.dirname(statusFile), { recursive: true }); + await fs9.promises.mkdir(path9.dirname(statusFile), { recursive: true }); const foundKey = await waitForResultWithTimeLimit( MAX_CACHE_OPERATION_MS, actionsCache.restoreCache([statusFile], cacheKey3, [cacheKey3]), @@ -174119,13 +174137,13 @@ async function getOverlayStatus(codeql, languages, diskUsage, logger2) { logger2.debug("No overlay status found in Actions cache."); return void 0; } - if (!fs8.existsSync(statusFile)) { + if (!fs9.existsSync(statusFile)) { logger2.debug( "Overlay status cache entry found but status file is missing." ); return void 0; } - const contents = await fs8.promises.readFile(statusFile, "utf-8"); + const contents = await fs9.promises.readFile(statusFile, "utf-8"); const parsed = JSON.parse(contents); if (!isObject2(parsed) || typeof parsed["attemptedToBuildOverlayBaseDatabase"] !== "boolean" || typeof parsed["builtOverlayBaseDatabase"] !== "boolean") { logger2.debug( @@ -174145,8 +174163,8 @@ async function saveOverlayStatus(codeql, languages, diskUsage, status, logger2) const cacheKey3 = await getCacheKey(codeql, languages, diskUsage); const statusFile = getStatusFilePath(languages); try { - await fs8.promises.mkdir(path9.dirname(statusFile), { recursive: true }); - await fs8.promises.writeFile(statusFile, JSON.stringify(status)); + await fs9.promises.mkdir(path9.dirname(statusFile), { recursive: true }); + await fs9.promises.writeFile(statusFile, JSON.stringify(status)); const cacheId = await waitForResultWithTimeLimit( MAX_CACHE_OPERATION_MS, actionsCache.saveCache([statusFile], cacheKey3), @@ -174172,7 +174190,7 @@ async function getCacheKey(codeql, languages, diskUsage) { } // src/trap-caching.ts -var fs9 = __toESM(require("fs")); +var fs10 = __toESM(require("fs")); var path10 = __toESM(require("path")); var actionsCache2 = __toESM(require_cache4()); var CACHE_VERSION = 1; @@ -174196,7 +174214,7 @@ async function downloadTrapCaches(codeql, languages, logger2, repositoryRoot) { ); for (const language of languagesSupportingCaching) { const cacheDir2 = path10.join(cachesDir, language); - fs9.mkdirSync(cacheDir2, { recursive: true }); + fs10.mkdirSync(cacheDir2, { recursive: true }); result[language] = cacheDir2; } if (await isAnalyzingDefaultBranch(getEnv(), repositoryRoot)) { @@ -174208,7 +174226,7 @@ async function downloadTrapCaches(codeql, languages, logger2, repositoryRoot) { let baseSha = "unknown"; const eventPath = process.env.GITHUB_EVENT_PATH; if (getWorkflowEventName() === "pull_request" && eventPath !== void 0) { - const event = JSON.parse(fs9.readFileSync(path10.resolve(eventPath), "utf-8")); + const event = JSON.parse(fs10.readFileSync(path10.resolve(eventPath), "utf-8")); baseSha = event.pull_request?.base?.sha || baseSha; } for (const language of languages) { @@ -174437,8 +174455,8 @@ async function getSupportedLanguageMap(codeql, logger2) { var baseWorkflowsPath = ".github/workflows"; function hasActionsWorkflows(sourceRoot) { const workflowsPath = path11.resolve(sourceRoot, baseWorkflowsPath); - const stats = fs10.lstatSync(workflowsPath, { throwIfNoEntry: false }); - return stats !== void 0 && stats.isDirectory() && fs10.readdirSync(workflowsPath).length > 0; + const stats = fs11.lstatSync(workflowsPath, { throwIfNoEntry: false }); + return stats !== void 0 && stats.isDirectory() && fs11.readdirSync(workflowsPath).length > 0; } async function getRawLanguagesInRepo(repository, sourceRoot, logger2) { logger2.debug( @@ -174930,7 +174948,7 @@ async function determineUserConfig(action, tempDir, inputs) { inputs.configInput, fromConfigFile ); - fs10.writeFileSync(computedConfigPath, dump(mergedConfig)); + fs11.writeFileSync(computedConfigPath, dump(mergedConfig)); action.logger.debug( `Using merged configurations from 'config' input with configuration from '${inputs.configFile}': ${computedConfigPath}` ); @@ -174942,7 +174960,7 @@ async function determineUserConfig(action, tempDir, inputs) { `Both a config file and config input were provided. Ignoring config file.` ); } - fs10.writeFileSync(computedConfigPath, dump(inputs.configInput)); + fs11.writeFileSync(computedConfigPath, dump(inputs.configInput)); inputs.configFile = computedConfigPath; action.logger.debug( `Using config from action input: ${inputs.configFile}` @@ -175099,7 +175117,7 @@ function isLocal(configPath) { return !containsAtRef(configPath); } function getLocalConfig(logger2, configFile, validateConfig) { - if (!fs10.existsSync(configFile)) { + if (!fs11.existsSync(configFile)) { throw new ConfigurationError( getConfigFileDoesNotExistErrorMessage(configFile) ); @@ -175107,7 +175125,7 @@ function getLocalConfig(logger2, configFile, validateConfig) { return parseUserConfig( logger2, configFile, - fs10.readFileSync(configFile, "utf-8"), + fs11.readFileSync(configFile, "utf-8"), validateConfig ); } @@ -175119,8 +175137,8 @@ function getPathToFailedConfigFile(tempDir) { } function saveConfigFile(logger2, configFilePath, config) { const configString = JSON.stringify(config); - fs10.mkdirSync(path11.dirname(configFilePath), { recursive: true }); - fs10.writeFileSync(configFilePath, configString, "utf8"); + fs11.mkdirSync(path11.dirname(configFilePath), { recursive: true }); + fs11.writeFileSync(configFilePath, configString, "utf8"); logger2.debug("Saved config:"); logger2.debug(configString); } @@ -175151,10 +175169,10 @@ function saveAbortedInitConfig(action, config) { ); } function readConfigFile(logger2, configFilePath) { - if (!fs10.existsSync(configFilePath)) { + if (!fs11.existsSync(configFilePath)) { return void 0; } - const configString = fs10.readFileSync(configFilePath, "utf8"); + const configString = fs11.readFileSync(configFilePath, "utf8"); logger2.debug("Loaded config:"); logger2.debug(configString); const config = JSON.parse(configString); @@ -175195,7 +175213,7 @@ async function generateRegistries(registriesInput, tempDir, logger2) { const qlconfig = createRegistriesBlock(registries); qlconfigFile = path11.join(tempDir, "qlconfig.yml"); const qlconfigContents = dump(qlconfig); - fs10.writeFileSync(qlconfigFile, qlconfigContents, "utf8"); + fs11.writeFileSync(qlconfigFile, qlconfigContents, "utf8"); logger2.debug("Generated qlconfig.yml:"); logger2.debug(qlconfigContents); registriesAuthTokens = registries.map((registry) => `${registry.url}=${registry.token}`).join(","); @@ -175324,7 +175342,7 @@ async function logGeneratedFilesTelemetry(config, duration, generatedFilesCount) } // src/setup-codeql.ts -var fs14 = __toESM(require("fs")); +var fs15 = __toESM(require("fs")); var path13 = __toESM(require("path")); var import_perf_hooks4 = require("perf_hooks"); var toolcache3 = __toESM(require_tool_cache()); @@ -175360,7 +175378,7 @@ function getCodeQLBundleFromUrl(url2) { } // src/overlay/caching.ts -var fs11 = __toESM(require("fs")); +var fs12 = __toESM(require("fs")); var actionsCache3 = __toESM(require_cache4()); var semver5 = __toESM(require_semver2()); var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; @@ -175370,7 +175388,7 @@ var CACHE_PREFIX = "codeql-overlay-base-database"; var MAX_CACHE_OPERATION_MS3 = 6e5; async function checkOverlayBaseDatabase(codeql, config, logger2, warningPrefix) { const baseDatabaseOidsFilePath = getBaseDatabaseOidsFilePath(config); - if (!fs11.existsSync(baseDatabaseOidsFilePath)) { + if (!fs12.existsSync(baseDatabaseOidsFilePath)) { logger2.warning( `${warningPrefix}: ${baseDatabaseOidsFilePath} does not exist` ); @@ -175857,7 +175875,7 @@ async function getCodeQLAssetDownloadURL(action, apiDetails, tagName, assetName, // src/tar.ts var import_child_process = require("child_process"); -var fs12 = __toESM(require("fs")); +var fs13 = __toESM(require("fs")); var stream = __toESM(require("stream")); var import_toolrunner = __toESM(require_toolrunner()); var io4 = __toESM(require_io()); @@ -175930,7 +175948,7 @@ async function isZstdAvailable(logger2) { } } async function extract(tarPath, dest, compressionMethod, tarVersion, logger2) { - fs12.mkdirSync(dest, { recursive: true }); + fs13.mkdirSync(dest, { recursive: true }); switch (compressionMethod) { case "gzip": return await toolcache.extractTar(tarPath, dest); @@ -176016,7 +176034,7 @@ function inferCompressionMethod(tarPath) { } // src/tools-download.ts -var fs13 = __toESM(require("fs")); +var fs14 = __toESM(require("fs")); var os4 = __toESM(require("os")); var path12 = __toESM(require("path")); var import_perf_hooks3 = require("perf_hooks"); @@ -176102,7 +176120,7 @@ async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorizat }; } async function downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorization, headers, tarVersion, logger2) { - fs13.mkdirSync(dest, { recursive: true }); + fs14.mkdirSync(dest, { recursive: true }); const agent = new import_http_client.HttpClient().getAgent(codeqlURL); headers = Object.assign( { "User-Agent": "CodeQL Action" }, @@ -176161,7 +176179,7 @@ function getToolcacheDirectory(version) { } function isToolcacheOnWorkspaceFilesystem(logger2) { try { - return fs13.statSync(getRequiredEnvParam("RUNNER_TOOL_CACHE")).dev === fs13.statSync(getRequiredEnvParam("GITHUB_WORKSPACE")).dev; + return fs14.statSync(getRequiredEnvParam("RUNNER_TOOL_CACHE")).dev === fs14.statSync(getRequiredEnvParam("GITHUB_WORKSPACE")).dev; } catch (e) { logger2.debug( `Could not determine whether the toolcache is on the same filesystem as the workspace: ${getErrorMessage(e)}` @@ -176183,7 +176201,7 @@ async function deleteToolcacheBundles({ return { deletedVersions: [], failed: true }; } try { - if ((await fs13.promises.lstat(toolDirectory)).isSymbolicLink()) { + if ((await fs14.promises.lstat(toolDirectory)).isSymbolicLink()) { logger2.info( `Not deleting the CodeQL tools from the toolcache since '${toolDirectory}' is a symlink.` ); @@ -176202,7 +176220,7 @@ async function deleteToolcacheBundles({ return { deletedVersions: [], failed: true }; } try { - const entries = await fs13.promises.readdir(toolDirectory, { + const entries = await fs14.promises.readdir(toolDirectory, { withFileTypes: true }); const deletedVersions = []; @@ -176216,7 +176234,7 @@ async function deleteToolcacheBundles({ } const versionDirectory = path12.join(toolDirectory, entry.name); try { - await fs13.promises.rm(versionDirectory, { + await fs14.promises.rm(versionDirectory, { force: true, recursive: true }); @@ -176241,7 +176259,7 @@ async function deleteToolcacheBundles({ } function writeToolcacheMarkerFile(extractedPath, logger2) { const markerFilePath = `${extractedPath}.complete`; - fs13.writeFileSync(markerFilePath, ""); + fs14.writeFileSync(markerFilePath, ""); logger2.info(`Created toolcache marker file ${markerFilePath}`); } @@ -176293,7 +176311,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger2) { const candidates = toolcache3.findAllVersions("CodeQL").filter(isGoodVersion).map((version) => ({ folder: toolcache3.find("CodeQL", version), version - })).filter(({ folder }) => fs14.existsSync(path13.join(folder, "pinned-version"))); + })).filter(({ folder }) => fs15.existsSync(path13.join(folder, "pinned-version"))); if (candidates.length === 1) { const candidate = candidates[0]; logger2.debug( @@ -176955,7 +176973,7 @@ function isReservedToolsValue(tools) { } // src/tracer-config.ts -var fs15 = __toESM(require("fs")); +var fs16 = __toESM(require("fs")); var path14 = __toESM(require("path")); async function shouldEnableIndirectTracing(codeql, config) { if (config.buildMode === "none" /* None */) { @@ -176975,14 +176993,14 @@ async function endTracingForCluster(codeql, config, logger2) { config.dbLocation, "temp/tracingEnvironment/end-tracing.json" ); - if (!fs15.existsSync(envVariablesFile)) { + if (!fs16.existsSync(envVariablesFile)) { throw new Error( `Environment file for ending tracing not found: ${envVariablesFile}` ); } try { const endTracingEnvVariables = JSON.parse( - fs15.readFileSync(envVariablesFile, "utf8") + fs16.readFileSync(envVariablesFile, "utf8") ); for (const [key, value] of Object.entries(endTracingEnvVariables)) { if (value !== null) { @@ -177003,7 +177021,7 @@ async function getTracerConfigForCluster(logger2, config) { "temp/tracingEnvironment/start-tracing.json" ); try { - const tracingEnvVariables = JSON.parse(fs15.readFileSync(filePath, "utf8")); + const tracingEnvVariables = JSON.parse(fs16.readFileSync(filePath, "utf8")); return { env: tracingEnvVariables }; @@ -177125,7 +177143,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion) { "tools", "tracing-config.lua" ); - return fs16.existsSync(tracingConfigPath); + return fs17.existsSync(tracingConfigPath); }, async isScannedLanguage(language) { return !await this.isTracedLanguage(language); @@ -177583,7 +177601,7 @@ async function writeCodeScanningConfigFile(config, logger2) { logger2.startGroup("Augmented user configuration file contents"); logger2.info(dump(augmentedConfig)); logger2.endGroup(); - fs16.writeFileSync(codeScanningConfigFile, dump(augmentedConfig)); + fs17.writeFileSync(codeScanningConfigFile, dump(augmentedConfig)); return codeScanningConfigFile; } var TRAP_CACHE_SIZE_MB = 1024; @@ -178076,7 +178094,7 @@ function dbIsFinalized(config, language, logger2) { const dbPath = getCodeQLDatabasePath(config, language); try { const dbInfo = load( - fs17.readFileSync(path16.resolve(dbPath, "codeql-database.yml"), "utf8") + fs18.readFileSync(path16.resolve(dbPath, "codeql-database.yml"), "utf8") ); return !("inProgress" in dbInfo); } catch { @@ -178160,8 +178178,8 @@ function writeDiffRangeDataExtensionPack(logger2, ranges, checkoutPath) { ranges = [{ path: "", startLine: 0, endLine: 0 }]; } const diffRangeDir = path16.join(getTemporaryDirectory(), "pr-diff-range"); - fs17.mkdirSync(diffRangeDir, { recursive: true }); - fs17.writeFileSync( + fs18.mkdirSync(diffRangeDir, { recursive: true }); + fs18.writeFileSync( path16.join(diffRangeDir, "qlpack.yml"), ` name: codeql-action/pr-diff-range @@ -178178,7 +178196,7 @@ dataExtensions: checkoutPath ); const extensionFilePath = path16.join(diffRangeDir, "pr-diff-range.yml"); - fs17.writeFileSync(extensionFilePath, extensionContents); + fs18.writeFileSync(extensionFilePath, extensionContents); logger2.debug( `Wrote pr-diff-range extension pack to ${extensionFilePath}: ${extensionContents}` @@ -178323,7 +178341,7 @@ async function runQueries(sarifFolder, memoryFlag, threadsFlag, diffRangePackDir } function getPerQueryAlertCounts(sarifPath) { const sarifObject = JSON.parse( - fs17.readFileSync(sarifPath, "utf8") + fs18.readFileSync(sarifPath, "utf8") ); const perQueryAlertCounts = {}; for (const sarifRun of sarifObject.runs) { @@ -178341,13 +178359,13 @@ async function runQueries(sarifFolder, memoryFlag, threadsFlag, diffRangePackDir } async function runFinalize(features, outputDir, threadsFlag, memoryFlag, codeql, config, logger2) { try { - await fs17.promises.rm(outputDir, { force: true, recursive: true }); + await fs18.promises.rm(outputDir, { force: true, recursive: true }); } catch (error3) { if (error3?.code !== "ENOENT") { throw error3; } } - await fs17.promises.mkdir(outputDir, { recursive: true }); + await fs18.promises.mkdir(outputDir, { recursive: true }); const timings = await finalizeDatabaseCreation( codeql, features, @@ -178391,7 +178409,7 @@ async function warnIfGoInstalledAfterInit(config, logger2) { } // src/database-upload.ts -var fs18 = __toESM(require("fs")); +var fs19 = __toESM(require("fs")); async function cleanupAndUploadDatabases(action, repositoryNwo, codeql, config, apiDetails, checkoutPath) { const logger2 = action.logger; if (getRequiredInput("upload-database") !== "true") { @@ -178428,7 +178446,7 @@ async function cleanupAndUploadDatabases(action, repositoryNwo, codeql, config, const bundledDb = await bundleDb(config, language, codeql, language, { includeDiagnostics: false }); - bundledDbSize = fs18.statSync(bundledDb).size; + bundledDbSize = fs19.statSync(bundledDb).size; const commitOid = await getCommitOid(action.env, checkoutPath); const maxAttempts = 4; let uploadDurationMs; @@ -178506,7 +178524,7 @@ async function recordClearCleanupSizes(codeql, config, reports, logger2) { const bundledDb = await bundleDb(config, language, codeql, language, { includeDiagnostics: false }); - report.clear_cleanup_zipped_size_bytes = fs18.statSync(bundledDb).size; + report.clear_cleanup_zipped_size_bytes = fs19.statSync(bundledDb).size; logger2.debug( `Database for ${language} is ${report.clear_cleanup_zipped_size_bytes} bytes zipped at the '${"clear" /* Clear */}' cleanup level (vs. ${report.zipped_upload_size_bytes ?? "unknown"} bytes at the '${"overlay" /* Overlay */}' level).` ); @@ -178529,7 +178547,7 @@ async function uploadBundledDatabase(repositoryNwo, language, commitOid, bundled if (uploadsBaseUrl.endsWith("/")) { uploadsBaseUrl = uploadsBaseUrl.slice(0, -1); } - const bundledDbReadStream = fs18.createReadStream(bundledDb); + const bundledDbReadStream = fs19.createReadStream(bundledDb); try { const startTime = performance.now(); await client.request( @@ -178581,7 +178599,7 @@ __export(upload_lib_exports, { waitForProcessing: () => waitForProcessing, writePostProcessedFiles: () => writePostProcessedFiles }); -var fs22 = __toESM(require("fs")); +var fs23 = __toESM(require("fs")); var path19 = __toESM(require("path")); var url = __toESM(require("url")); var import_zlib = __toESM(require("zlib")); @@ -178589,7 +178607,7 @@ var core13 = __toESM(require_core()); var jsonschema2 = __toESM(require_lib2()); // src/fingerprints.ts -var fs19 = __toESM(require("fs")); +var fs20 = __toESM(require("fs")); var import_path4 = __toESM(require("path")); // node_modules/long/index.js @@ -179577,7 +179595,7 @@ async function hash(callback, filepath) { } updateHash(current); }; - const readStream = fs19.createReadStream(filepath, "utf8"); + const readStream = fs20.createReadStream(filepath, "utf8"); for await (const data of readStream) { for (let i = 0; i < data.length; ++i) { processCharacter(data.charCodeAt(i)); @@ -179652,11 +179670,11 @@ function resolveUriToFile(location, artifacts, sourceRoot, logger2) { if (!import_path4.default.isAbsolute(uri)) { uri = srcRootPrefix + uri; } - if (!fs19.existsSync(uri)) { + if (!fs20.existsSync(uri)) { logger2.debug(`Unable to compute fingerprint for non-existent file: ${uri}`); return void 0; } - if (fs19.statSync(uri).isDirectory()) { + if (fs20.statSync(uri).isDirectory()) { logger2.debug(`Unable to compute fingerprint for directory: ${uri}`); return void 0; } @@ -179711,7 +179729,7 @@ async function addFingerprints(sarifLog, sourceRoot, logger2) { } // src/init.ts -var fs20 = __toESM(require("fs")); +var fs21 = __toESM(require("fs")); var path18 = __toESM(require("path")); var toolrunner4 = __toESM(require_toolrunner()); var github3 = __toESM(require_github()); @@ -179746,7 +179764,7 @@ async function initConfig2(actionState, inputs) { }); } async function runDatabaseInitCluster(databaseInitEnvironment, codeql, config, sourceRoot, processName, qlconfigFile) { - fs20.mkdirSync(config.dbLocation, { recursive: true }); + fs21.mkdirSync(config.dbLocation, { recursive: true }); await wrapEnvironment( databaseInitEnvironment, async () => await codeql.databaseInitCluster( @@ -179781,24 +179799,24 @@ async function checkPacksForOverlayCompatibility(codeql, config, logger2) { function checkPackForOverlayCompatibility(packDir, codeQlOverlayVersion, logger2) { try { let qlpackPath = path18.join(packDir, "qlpack.yml"); - if (!fs20.existsSync(qlpackPath)) { + if (!fs21.existsSync(qlpackPath)) { qlpackPath = path18.join(packDir, "codeql-pack.yml"); } const qlpackContents = load( - fs20.readFileSync(qlpackPath, "utf8") + fs21.readFileSync(qlpackPath, "utf8") ); if (!qlpackContents.buildMetadata) { return true; } const packInfoPath = path18.join(packDir, ".packinfo"); - if (!fs20.existsSync(packInfoPath)) { + if (!fs21.existsSync(packInfoPath)) { logger2.warning( `The query pack at ${packDir} does not have a .packinfo file, so it cannot support overlay analysis. Recompiling the query pack with the latest CodeQL CLI should solve this problem.` ); return false; } const packInfoFileContents = JSON.parse( - fs20.readFileSync(packInfoPath, "utf8") + fs21.readFileSync(packInfoPath, "utf8") ); const packOverlayVersion = packInfoFileContents.overlayVersion; if (typeof packOverlayVersion !== "number") { @@ -179833,8 +179851,8 @@ async function checkInstallPython311(languages, codeql) { ]).exec(); } } -function cleanupDatabaseClusterDirectory(config, logger2, options = {}, rmSync5 = fs20.rmSync) { - if (fs20.existsSync(config.dbLocation) && (fs20.statSync(config.dbLocation).isFile() || fs20.readdirSync(config.dbLocation).length > 0)) { +function cleanupDatabaseClusterDirectory(config, logger2, options = {}, rmSync5 = fs21.rmSync) { + if (fs21.existsSync(config.dbLocation) && (fs21.statSync(config.dbLocation).isFile() || fs21.readdirSync(config.dbLocation).length > 0)) { if (!options.disableExistingDirectoryWarning) { logger2.warning( `The database cluster directory ${config.dbLocation} must be empty. Attempting to clean it up.` @@ -179939,7 +179957,7 @@ To opt out of this change, ${envVarOptOut}`; } // src/sarif/index.ts -var fs21 = __toESM(require("fs")); +var fs22 = __toESM(require("fs")); var InvalidSarifUploadError = class extends Error { }; function getToolNames(sarifFile) { @@ -179955,7 +179973,7 @@ function getToolNames(sarifFile) { } function readSarifFile(sarifFilePath) { try { - return JSON.parse(fs21.readFileSync(sarifFilePath, "utf8")); + return JSON.parse(fs22.readFileSync(sarifFilePath, "utf8")); } catch (err) { throw new Error( `Parsing SARIF file at '${sarifFilePath}' failed: ${getErrorMessage(err)}` @@ -180096,8 +180114,8 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo codeQL = initCodeQLResult.codeql; } const baseTempDir = path19.resolve(tempDir, "combined-sarif"); - fs22.mkdirSync(baseTempDir, { recursive: true }); - const outputDirectory = fs22.mkdtempSync(path19.resolve(baseTempDir, "output-")); + fs23.mkdirSync(baseTempDir, { recursive: true }); + const outputDirectory = fs23.mkdtempSync(path19.resolve(baseTempDir, "output-")); const outputFile = path19.resolve(outputDirectory, "combined-sarif.sarif"); await codeQL.mergeResults(sarifFiles, outputFile, { mergeRunsFromEqualCategory: true @@ -180142,7 +180160,7 @@ async function uploadPayload(payload, repositoryNwo, logger2, analysis) { `SARIF upload disabled by an environment variable. Saving to ${payloadSaveFile}` ); logger2.info(`Payload: ${JSON.stringify(payload, null, 2)}`); - fs22.writeFileSync(payloadSaveFile, JSON.stringify(payload, null, 2)); + fs23.writeFileSync(payloadSaveFile, JSON.stringify(payload, null, 2)); return "dummy-sarif-id"; } const client = getApiClient(); @@ -180176,7 +180194,7 @@ async function uploadPayload(payload, repositoryNwo, logger2, analysis) { function findSarifFilesInDir(sarifPath, isSarif) { const sarifFiles = []; const walkSarifFiles = (dir) => { - const entries = fs22.readdirSync(dir, { withFileTypes: true }); + const entries = fs23.readdirSync(dir, { withFileTypes: true }); for (const entry of entries) { if (entry.isFile() && isSarif(entry.name)) { sarifFiles.push(path19.resolve(dir, entry.name)); @@ -180189,11 +180207,11 @@ function findSarifFilesInDir(sarifPath, isSarif) { return sarifFiles; } function getSarifFilePaths(sarifPath, isSarif) { - if (!fs22.existsSync(sarifPath)) { + if (!fs23.existsSync(sarifPath)) { throw new ConfigurationError(`Path does not exist: ${sarifPath}`); } let sarifFiles; - if (fs22.lstatSync(sarifPath).isDirectory()) { + if (fs23.lstatSync(sarifPath).isDirectory()) { sarifFiles = findSarifFilesInDir(sarifPath, isSarif); if (sarifFiles.length === 0) { throw new ConfigurationError( @@ -180206,7 +180224,7 @@ function getSarifFilePaths(sarifPath, isSarif) { return sarifFiles; } async function getGroupedSarifFilePaths(logger2, sarifPath) { - const stats = fs22.statSync(sarifPath, { throwIfNoEntry: false }); + const stats = fs23.statSync(sarifPath, { throwIfNoEntry: false }); if (stats === void 0) { throw new ConfigurationError(`Path does not exist: ${sarifPath}`); } @@ -180341,7 +180359,7 @@ function buildPayload(commitOid, ref, analysisKey, analysisName, zippedSarif, wo payloadObj.base_sha = mergeBaseCommitOid; } else if (process.env.GITHUB_EVENT_PATH) { const githubEvent = JSON.parse( - fs22.readFileSync(process.env.GITHUB_EVENT_PATH, "utf8") + fs23.readFileSync(process.env.GITHUB_EVENT_PATH, "utf8") ); payloadObj.base_ref = `refs/heads/${githubEvent.pull_request.base.ref}`; payloadObj.base_sha = githubEvent.pull_request.base.sha; @@ -180479,9 +180497,9 @@ async function uploadPostProcessedFiles(logger2, checkoutPath, uploadTarget, pos }; } function dumpSarifFile(sarifPayload, outputDir, logger2, uploadTarget) { - if (!fs22.existsSync(outputDir)) { - fs22.mkdirSync(outputDir, { recursive: true }); - } else if (!fs22.lstatSync(outputDir).isDirectory()) { + if (!fs23.existsSync(outputDir)) { + fs23.mkdirSync(outputDir, { recursive: true }); + } else if (!fs23.lstatSync(outputDir).isDirectory()) { throw new ConfigurationError( `The path that processed SARIF files should be written to exists, but is not a directory: ${outputDir}` ); @@ -180491,7 +180509,7 @@ function dumpSarifFile(sarifPayload, outputDir, logger2, uploadTarget) { `upload${uploadTarget.sarifExtension}` ); logger2.info(`Writing processed SARIF file to ${outputFile}`); - fs22.writeFileSync(outputFile, sarifPayload); + fs23.writeFileSync(outputFile, sarifPayload); } var STATUS_CHECK_INITIAL_BACKOFF_MILLISECONDS = 5 * 1e3; var STATUS_CHECK_BACKOFF_MULTIPLIER = 2; @@ -180738,7 +180756,7 @@ function doesGoExtractionOutputExist(config) { "trap", "go" /* go */ ); - return fs23.existsSync(trapDirectory) && fs23.readdirSync(trapDirectory).some( + return fs24.existsSync(trapDirectory) && fs24.readdirSync(trapDirectory).some( (fileName) => [ ".trap", ".trap.gz", @@ -181043,18 +181061,18 @@ async function runWrapper() { } // src/analyze-action-post.ts -var fs27 = __toESM(require("fs")); +var fs28 = __toESM(require("fs")); var core16 = __toESM(require_core()); // src/debug-artifacts.ts -var fs26 = __toESM(require("fs")); +var fs27 = __toESM(require("fs")); var path23 = __toESM(require("path")); var artifact = __toESM(require_artifact2()); var artifactLegacy = __toESM(require_artifact_client2()); var core15 = __toESM(require_core()); // node_modules/archiver/lib/core.js -var import_fs2 = require("fs"); +var import_fs = require("fs"); // node_modules/is-stream/index.js function isStream(stream2, { checkOpen = true } = {}) { @@ -181062,7 +181080,7 @@ function isStream(stream2, { checkOpen = true } = {}) { } // node_modules/readdir-glob/dist/index.mjs -var fs24 = __toESM(require("fs"), 1); +var fs25 = __toESM(require("fs"), 1); var import_events = require("events"); // node_modules/readdir-glob/node_modules/balanced-match/dist/esm/index.js @@ -182939,7 +182957,7 @@ minimatch.unescape = unescape2; var import_path6 = require("path"); function readdir2(dir, strict) { return new Promise((resolve$1, reject) => { - fs24.readdir(dir, { withFileTypes: true }, (err, files) => { + fs25.readdir(dir, { withFileTypes: true }, (err, files) => { if (err) switch (err.code) { case "ENOTDIR": if (strict) reject(err); @@ -182962,7 +182980,7 @@ function readdir2(dir, strict) { } function getStat(file, followSymlinks) { return new Promise((resolve$1) => { - const statFunc = followSymlinks ? fs24.stat : fs24.lstat; + const statFunc = followSymlinks ? fs25.stat : fs25.lstat; statFunc(file, (err, stats) => { if (err) switch (err.code) { case "ENOENT": @@ -183270,7 +183288,7 @@ var Archiver = class extends import_readable_stream2.Transform { data.sourcePath = filepath; task.data = data; this._entriesCount++; - if (data.stats && data.stats instanceof import_fs2.Stats) { + if (data.stats && data.stats instanceof import_fs.Stats) { task = this._updateQueueTaskWithStats(task, data.stats); if (task) { if (data.stats.size) { @@ -183518,7 +183536,7 @@ var Archiver = class extends import_readable_stream2.Transform { callback(); return; } - (0, import_fs2.lstat)( + (0, import_fs.lstat)( task.filepath, function(err, stats) { if (this._state.aborted) { @@ -183580,7 +183598,7 @@ var Archiver = class extends import_readable_stream2.Transform { task.data.type = "file"; task.data.sourceType = "stream"; task.source = new import_lazystream.Readable(function() { - return (0, import_fs2.createReadStream)(task.filepath); + return (0, import_fs.createReadStream)(task.filepath); }); } else if (stats.isDirectory() && this._supportsDirectory) { task.data.name = trailingSlashIt(task.data.name); @@ -183589,7 +183607,7 @@ var Archiver = class extends import_readable_stream2.Transform { task.data.sourceType = "buffer"; task.source = Buffer.concat([]); } else if (stats.isSymbolicLink() && this._supportsSymlink) { - const linkPath = (0, import_fs2.readlinkSync)(task.filepath); + const linkPath = (0, import_fs.readlinkSync)(task.filepath); const dirName = (0, import_path7.dirname)(task.filepath); task.data.type = "symlink"; task.data.linkname = (0, import_path7.relative)( @@ -185432,7 +185450,7 @@ var ZipArchive = class extends Archiver { }; // src/artifact-scanner.ts -var fs25 = __toESM(require("fs")); +var fs26 = __toESM(require("fs")); var os6 = __toESM(require("os")); var path22 = __toESM(require("path")); var exec = __toESM(require_exec()); @@ -185479,7 +185497,7 @@ function isAuthToken(value, patterns = GITHUB_TOKEN_PATTERNS) { function scanFileForTokens(filePath, relativePath2, logger2) { const findings = []; try { - const content = fs25.readFileSync(filePath, "utf8"); + const content = fs26.readFileSync(filePath, "utf8"); for (const { type, pattern } of GITHUB_TOKEN_PATTERNS) { const matches = content.match(pattern); if (matches) { @@ -185512,7 +185530,7 @@ async function scanArchiveFile(archivePath, relativeArchivePath, extractDir, log findings: [] }; try { - const tempExtractDir = fs25.mkdtempSync( + const tempExtractDir = fs26.mkdtempSync( path22.join(extractDir, `extract-${depth}-`) ); const fileName = path22.basename(archivePath).toLowerCase(); @@ -185546,7 +185564,7 @@ async function scanArchiveFile(archivePath, relativeArchivePath, extractDir, log path22.basename(archivePath, ".gz") ); await exec.exec("gunzip", ["-c", archivePath], { - outStream: fs25.createWriteStream(outputFile), + outStream: fs26.createWriteStream(outputFile), silent: true }); } else if (fileName.endsWith(".zip")) { @@ -185567,7 +185585,7 @@ async function scanArchiveFile(archivePath, relativeArchivePath, extractDir, log ); result.scannedFiles += scanResult.scannedFiles; result.findings.push(...scanResult.findings); - fs25.rmSync(tempExtractDir, { recursive: true, force: true }); + fs26.rmSync(tempExtractDir, { recursive: true, force: true }); } catch (e) { logger2.debug( `Could not extract or scan archive file ${archivePath}: ${getErrorMessage(e)}` @@ -185602,7 +185620,7 @@ async function scanDirectory(dirPath, baseRelativePath, logger2, depth = 0) { scannedFiles: 0, findings: [] }; - const entries = fs25.readdirSync(dirPath, { withFileTypes: true }); + const entries = fs26.readdirSync(dirPath, { withFileTypes: true }); for (const entry of entries) { const fullPath = path22.join(dirPath, entry.name); const relativePath2 = path22.join(baseRelativePath, entry.name); @@ -185637,10 +185655,10 @@ async function scanArtifactsForTokens(filesToScan, logger2) { scannedFiles: 0, findings: [] }; - const tempScanDir = fs25.mkdtempSync(path22.join(os6.tmpdir(), "artifact-scan-")); + const tempScanDir = fs26.mkdtempSync(path22.join(os6.tmpdir(), "artifact-scan-")); try { for (const filePath of filesToScan) { - const stats = fs25.statSync(filePath); + const stats = fs26.statSync(filePath); const fileName = path22.basename(filePath); if (stats.isDirectory()) { const dirResult = await scanDirectory(filePath, fileName, logger2); @@ -185678,7 +185696,7 @@ async function scanArtifactsForTokens(filesToScan, logger2) { } } finally { try { - fs25.rmSync(tempScanDir, { recursive: true, force: true }); + fs26.rmSync(tempScanDir, { recursive: true, force: true }); } catch (e) { logger2.debug( `Could not clean up temporary scan directory: ${getErrorMessage(e)}` @@ -185700,10 +185718,10 @@ async function uploadCombinedSarifArtifacts(logger2, gitHubVariant) { ); const baseTempDir = path23.resolve(tempDir, "combined-sarif"); const toUpload = []; - if (fs26.existsSync(baseTempDir)) { - const outputDirs = fs26.readdirSync(baseTempDir); + if (fs27.existsSync(baseTempDir)) { + const outputDirs = fs27.readdirSync(baseTempDir); for (const outputDir of outputDirs) { - const sarifFiles = fs26.readdirSync(path23.resolve(baseTempDir, outputDir)).filter((f) => path23.extname(f) === ".sarif"); + const sarifFiles = fs27.readdirSync(path23.resolve(baseTempDir, outputDir)).filter((f) => path23.extname(f) === ".sarif"); for (const sarifFile of sarifFiles) { toUpload.push(path23.resolve(baseTempDir, outputDir, sarifFile)); } @@ -185730,17 +185748,17 @@ async function uploadCombinedSarifArtifacts(logger2, gitHubVariant) { function tryPrepareSarifDebugArtifact(config, language, logger2) { try { const analyzeActionOutputDir = process.env["CODEQL_ACTION_SARIF_RESULTS_OUTPUT_DIR" /* SARIF_RESULTS_OUTPUT_DIR */]; - if (analyzeActionOutputDir !== void 0 && fs26.existsSync(analyzeActionOutputDir) && fs26.lstatSync(analyzeActionOutputDir).isDirectory()) { + if (analyzeActionOutputDir !== void 0 && fs27.existsSync(analyzeActionOutputDir) && fs27.lstatSync(analyzeActionOutputDir).isDirectory()) { const sarifFile = path23.resolve( analyzeActionOutputDir, `${language}.sarif` ); - if (fs26.existsSync(sarifFile)) { + if (fs27.existsSync(sarifFile)) { const sarifInDbLocation = path23.resolve( config.dbLocation, `${language}.sarif` ); - fs26.copyFileSync(sarifFile, sarifInDbLocation); + fs27.copyFileSync(sarifFile, sarifInDbLocation); return sarifInDbLocation; } } @@ -185908,10 +185926,10 @@ async function createPartialDatabaseBundle(config, language) { core15.info( `${config.debugDatabaseName}-${language} is not finalized. Uploading partial database bundle at ${databaseBundlePath}...` ); - if (fs26.existsSync(databaseBundlePath)) { - await fs26.promises.rm(databaseBundlePath, { force: true }); + if (fs27.existsSync(databaseBundlePath)) { + await fs27.promises.rm(databaseBundlePath, { force: true }); } - const output = fs26.createWriteStream(databaseBundlePath); + const output = fs27.createWriteStream(databaseBundlePath); const zip = new ZipArchive(); zip.on("error", (err) => { throw err; @@ -185961,9 +185979,9 @@ async function runWrapper2() { getCsharpTempDependencyDir() ]; for (const tempDependencyDir of tempDependencyDirs) { - if (fs27.existsSync(tempDependencyDir)) { + if (fs28.existsSync(tempDependencyDir)) { try { - fs27.rmSync(tempDependencyDir, { recursive: true }); + fs28.rmSync(tempDependencyDir, { recursive: true }); } catch (error3) { logger2.info( `Failed to remove temporary dependencies directory: ${getErrorMessage(error3)}` @@ -186074,7 +186092,7 @@ async function runWrapper3() { } // src/init-action.ts -var fs29 = __toESM(require("fs")); +var fs30 = __toESM(require("fs")); var path25 = __toESM(require("path")); var core19 = __toESM(require_core()); var io7 = __toESM(require_io()); @@ -186133,7 +186151,7 @@ function createInitToolsDownloadFields(report, toolsFeatureFlagsValid) { } // src/workflow.ts -var fs28 = __toESM(require("fs")); +var fs29 = __toESM(require("fs")); var path24 = __toESM(require("path")); var import_zlib3 = __toESM(require("zlib")); var core18 = __toESM(require_core()); @@ -186285,7 +186303,7 @@ async function getWorkflow(logger2) { ); } const workflowPath = await getWorkflowAbsolutePath(logger2); - return load(fs28.readFileSync(workflowPath, "utf-8")); + return load(fs29.readFileSync(workflowPath, "utf-8")); } async function getWorkflowAbsolutePath(logger2) { const relativePath2 = await getWorkflowRelativePath(); @@ -186293,7 +186311,7 @@ async function getWorkflowAbsolutePath(logger2) { getRequiredEnvParam("GITHUB_WORKSPACE"), relativePath2 ); - if (fs28.existsSync(absolutePath)) { + if (fs29.existsSync(absolutePath)) { logger2.debug( `Derived the following absolute path for the currently executing workflow: ${absolutePath}.` ); @@ -186689,7 +186707,7 @@ async function run3(actionState) { if (statusReportBase !== void 0) { await sendStatusReport(statusReportBase); } - logTemporaryDiagnostics(); + logTemporaryDiagnostics(actionState); return; } let overlayBaseDatabaseStats; @@ -186737,16 +186755,16 @@ async function run3(actionState) { "codeql-action-go-tracing", "bin" ); - fs29.mkdirSync(tempBinPath, { recursive: true }); + fs30.mkdirSync(tempBinPath, { recursive: true }); core19.addPath(tempBinPath); const goWrapperPath = path25.resolve(tempBinPath, "go"); - fs29.writeFileSync( + fs30.writeFileSync( goWrapperPath, `#!/bin/bash exec ${goBinaryPath} "$@"` ); - fs29.chmodSync(goWrapperPath, "755"); + fs30.chmodSync(goWrapperPath, "755"); actionState.env.export("CODEQL_ACTION_GO_BINARY" /* GO_BINARY_LOCATION */, goWrapperPath); } catch (e) { logger2.warning( @@ -186875,7 +186893,7 @@ exec ${goBinaryPath} "$@"` `${existingJavaToolOptions} -Djavax.net.debug=all` ); } - flushDiagnostics(config); + flushDiagnostics(actionState, config); await saveConfig(config, logger2); core19.setOutput("codeql-path", config.codeQLCmd); core19.setOutput("codeql-version", (await codeql.getVersion()).version); @@ -186899,7 +186917,7 @@ exec ${goBinaryPath} "$@"` ); return; } finally { - logTemporaryDiagnostics(); + logTemporaryDiagnostics(actionState); } await sendCompletedStatusReport2( startedAt, @@ -186928,7 +186946,7 @@ async function runWrapper4() { var core20 = __toESM(require_core()); // src/init-action-post-helper.ts -var fs30 = __toESM(require("fs")); +var fs31 = __toESM(require("fs")); var import_path8 = __toESM(require("path")); var github4 = __toESM(require_github()); function createFailedUploadFailedSarifResult(error3) { @@ -187127,7 +187145,7 @@ async function uploadFailureInfo(uploadAllAvailableDebugArtifacts, printDebugLog } if (isSelfHostedRunner() && config.dbLocation) { try { - fs30.rmSync(config.dbLocation, { + fs31.rmSync(config.dbLocation, { recursive: true, force: true, maxRetries: 3 @@ -188067,7 +188085,7 @@ function generateCertificateAuthority() { } // src/start-proxy/environment.ts -var fs31 = __toESM(require("fs")); +var fs32 = __toESM(require("fs")); var path28 = __toESM(require("path")); var toolrunner5 = __toESM(require_toolrunner()); var io8 = __toESM(require_io()); @@ -188140,9 +188158,9 @@ function checkJdkSettings(logger2, jdkHome) { for (const fileToCheck of filesToCheck) { const file = path28.join(jdkHome, fileToCheck); try { - if (fs31.existsSync(file)) { + if (fs32.existsSync(file)) { logger2.debug(`Found '${file}'.`); - const lines = String(fs31.readFileSync(file)).split("\n"); + const lines = String(fs32.readFileSync(file)).split("\n"); for (const line of lines) { for (const property of javaProperties) { if (line.startsWith(`${property}=`)) { diff --git a/src/diagnostics.test.ts b/src/diagnostics.test.ts new file mode 100644 index 0000000000..2ba98da606 --- /dev/null +++ b/src/diagnostics.test.ts @@ -0,0 +1,111 @@ +import * as fs from "fs"; +import path from "path"; + +import test, { type ExecutionContext } from "ava"; + +import * as diagnostics from "./diagnostics"; +import { BuiltInLanguage } from "./languages"; +import { + checkExpectedLogMessages, + createTestConfig, + initAllState, + RecordingLogger, + setupTests, +} from "./testing-utils"; +import { withTmpDir } from "./util"; + +setupTests(test); + +const id = "codeql-action/test-diagnostic"; +const name = "Test title"; + +test("makeDiagnostic - adds expected properties", (t) => { + const diagnostic = diagnostics.makeDiagnostic(id, name, {}); + + t.truthy(diagnostic.timestamp); + t.is(diagnostic.source.id, id); + t.is(diagnostic.source.name, name); +}); + +/** + * Diagnostic files that are written to disk don't have deterministic names. + * This function recursively finds all `.json` files at {@link rootPath}, + * asserts that there is exactly one, and that it matches {@link expected}. + * + * @param rootPath The path to start searching from. + */ +function assertSingleDiagnosticIn( + t: ExecutionContext, + rootPath: string, + expected: diagnostics.DiagnosticMessage, +) { + // Find all `.json` files in `rootPath` and check that there is exactly one. + const filePaths = fs + .readdirSync(rootPath, { + recursive: true, + encoding: "utf-8", + }) + .filter((p) => p.endsWith(".json")); + + t.is(filePaths.length, 1); + + // Check that the written diagnostic matches the one we added. + const contents = fs.readFileSync( + path.resolve(rootPath, filePaths[0]), + "utf-8", + ); + + const readDiagnostic = JSON.parse(contents) as diagnostics.DiagnosticMessage; + t.deepEqual(readDiagnostic, expected); +} + +test("addDiagnostic writes temporary diagnostics and flushDiagnostics moves them to the database", async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + + const tempDiagDir = path.resolve(tmpDir, "temp"); + const testDbDir = path.resolve(tmpDir, "test", "database"); + const diagnostic = diagnostics.makeDiagnostic(id, name, {}); + + // Write the diagnostic. The path provided for `dbLocation` doesn't exist, + // so the diagnostic will be written to a temporary location. + t.notThrows(() => { + diagnostics.addDiagnostic( + createTestConfig({ tempDir: tempDiagDir, dbLocation: testDbDir }), + BuiltInLanguage.actions, + diagnostic, + logger, + ); + }); + + // Check that `tempDiagDir` was created. + t.true(fs.existsSync(tempDiagDir)); + + // Check that the diagnostic exists under `tempDiagDir`. + assertSingleDiagnosticIn(t, tempDiagDir, diagnostic); + + // Flush the diagnostics. This will cause the diagnostic we wrote previously to + // be moved to a location under `dbLocation`. + t.notThrows(() => { + diagnostics.flushDiagnostics( + initAllState({ logger }), + createTestConfig({ + tempDir: tempDiagDir, + dbLocation: testDbDir, + }), + ); + }); + + // Check that `testDbDir` was created. + t.true(fs.existsSync(testDbDir)); + + // Check that the diagnostic exists under `testDbDir`. + assertSingleDiagnosticIn(t, testDbDir, diagnostic); + + // Check that we logged that the database directory doesn't exist yet + // and that we moved one diagnostic. + checkExpectedLogMessages(t, logger.messages, [ + `but the database at ${path.join(testDbDir, "actions")} does not exist yet`, + "Moving 1 diagnostic(s) to their respective databases.", + ]); + })); diff --git a/src/diagnostics.ts b/src/diagnostics.ts index f08c83c420..1e74f52525 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -1,17 +1,16 @@ -import { - existsSync, - mkdirSync, - readFileSync, - renameSync, - writeFileSync, -} from "fs"; +import * as fs from "fs"; import path from "path"; +import type { ActionState } from "./action-common"; import { getTemporaryDirectory } from "./actions-util"; import type { Config } from "./config-utils"; import { Language } from "./languages"; -import { getActionsLogger } from "./logging"; -import { getCodeQLDatabasePath } from "./util"; +import { getActionsLogger, type Logger } from "./logging"; +import { + getCodeQLDatabasePath, + getErrorMessage, + isErrnoException, +} from "./util"; /** * Known tags for diagnostics. There is currently only "internal-error", @@ -142,7 +141,7 @@ export function getTempDiagnosticPath(tmpDir: string, language?: Language) { /** * Gets a path relative to {@link basePath} where diagnostics for {@link language} - * should be stored at. If {@link language} is `undefined`, then {@link baseBath} + * should be stored at. If {@link language} is `undefined`, then {@link basePath} * is returned instead. */ export function getDiagnosticsPath(basePath: string, language?: Language) { @@ -164,16 +163,16 @@ export function addDiagnostic( config: Config, language: Language, diagnostic: DiagnosticMessage, + logger: Logger = getActionsLogger(), ) { - const logger = getActionsLogger(); const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; // Check that the database exists before writing to it. If the database does not yet exist, // store the diagnostic in memory and write it later. - if (existsSync(databasePath)) { - writeDiagnostic(config, language, diagnostic); + if (fs.existsSync(databasePath)) { + writeDiagnostic({ logger }, config, language, diagnostic); } else { logger.debug( `Writing a diagnostic for ${language}, but the database at ${databasePath} does not exist yet.`, @@ -218,7 +217,7 @@ function writeDiagnosticFile( diagnostic: DiagnosticMessage, ): string { // Create the directory if it doesn't exist yet. - mkdirSync(diagnosticsPath, { recursive: true }); + fs.mkdirSync(diagnosticsPath, { recursive: true }); // Include a monotonically increasing suffix to avoid filename collisions // between diagnostics produced within the same millisecond. @@ -234,7 +233,7 @@ function writeDiagnosticFile( `codeql-action-${sanitizedTimestamp}-${uniqueSuffix}.json`, ); - writeFileSync(jsonPath, JSON.stringify(diagnostic)); + fs.writeFileSync(jsonPath, JSON.stringify(diagnostic)); return jsonPath; } @@ -255,46 +254,49 @@ export function getDatabaseDiagnosticsPath( * @param diagnostic The diagnostic message to add to the database. */ function writeDiagnostic( + action: ActionState<["Logger"]>, config: Config, language: Language | undefined, diagnostic: DiagnosticMessage, ) { - const logger = getActionsLogger(); const diagnosticsPath = getDatabaseDiagnosticsPath(config, language); try { writeDiagnosticFile(diagnosticsPath, diagnostic); } catch (err) { - logger.warning(`Unable to write diagnostic message to database: ${err}`); - logger.debug(JSON.stringify(diagnostic)); + action.logger.warning( + `Unable to write diagnostic message to database: ${err}`, + ); + action.logger.debug(JSON.stringify(diagnostic)); } } /** Report if there are temporary diagnostics and write them to the log. */ -export function logTemporaryDiagnostics() { - const logger = getActionsLogger(); +export function logTemporaryDiagnostics(action: ActionState<["Logger"]>) { const num = temporaryDiagnostics.length; if (num > 0) { - logger.warning( + action.logger.warning( `${num} diagnostic(s) could not be written to the database and will not appear on the Tool Status Page.`, ); for (const temporary of temporaryDiagnostics) { - logger.debug(readFileSync(temporary.path, "utf-8")); + action.logger.debug(fs.readFileSync(temporary.path, "utf-8")); } } } /** Relocates all temporary diagnostics to the respective databases. */ -export function flushDiagnostics(config: Config) { - const logger = getActionsLogger(); - +export function flushDiagnostics( + action: ActionState<["Logger"]>, + config: Config, +) { const diagnosticsCount = temporaryDiagnostics.length; - logger.debug( + action.logger.debug( `Moving ${diagnosticsCount} diagnostic(s) to their respective databases.`, ); + const failedFlushDiagnostics: TemporaryDiagnostic[] = []; for (const temporary of temporaryDiagnostics) { // If `temporary.language` is `undefined`, then we didn't have a `config` at the time that // `addNoLanguageDiagnostic` was called. In that case, we arbitrarily choose the first @@ -306,11 +308,31 @@ export function flushDiagnostics(config: Config) { const filename = path.basename(temporary.path); const destination = path.join(directory, filename); - renameSync(temporary.path, destination); + try { + fs.mkdirSync(directory, { recursive: true }); + try { + fs.renameSync(temporary.path, destination); + } catch (renameErr: unknown) { + // Rethrow the error if it isn't an EXDEV one. + if (!isErrnoException(renameErr) || renameErr.code !== "EXDEV") { + throw renameErr; + } + + // The error was an EXDEV one: try to copy the file and delete the temporary one. + fs.copyFileSync(temporary.path, destination); + fs.unlinkSync(temporary.path); + } + } catch (err) { + action.logger.warning( + `Failed to relocate '${temporary.path}' to '${destination}': ${getErrorMessage(err)}`, + ); + + failedFlushDiagnostics.push(temporary); + } } // Reset the temporary diagnostics arrays. - temporaryDiagnostics = []; + temporaryDiagnostics = failedFlushDiagnostics; } /** diff --git a/src/init-action.ts b/src/init-action.ts index 99d8e06663..bd5ed3395a 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -484,7 +484,7 @@ async function run( if (statusReportBase !== undefined) { await sendStatusReport(statusReportBase); } - logTemporaryDiagnostics(); + logTemporaryDiagnostics(actionState); return; } @@ -769,7 +769,7 @@ async function run( // Move diagnostics to the database that we previously kept in a temporary location // because the database did not exist until now - flushDiagnostics(config); + flushDiagnostics(actionState, config); // We save the config here instead of at the end of `initConfig` because we // may have updated the config returned from `initConfig`, e.g. to revert to @@ -798,7 +798,7 @@ async function run( ); return; } finally { - logTemporaryDiagnostics(); + logTemporaryDiagnostics(actionState); } await sendCompletedStatusReport( startedAt, diff --git a/src/util.ts b/src/util.ts index ba0c3c7d46..b68824d6e9 100644 --- a/src/util.ts +++ b/src/util.ts @@ -900,6 +900,21 @@ export function getErrorMessage(error: unknown): string { return error instanceof Error ? error.message : String(error); } +/** + * Approximates whether {@link error} is like a {@link NodeJS.ErrnoException}. + * We only typically care about the `code` property, so that's what we check for here. + */ +export function isErrnoException( + error: unknown, +): error is NodeJS.ErrnoException { + return ( + typeof error === "object" && + error !== null && + "code" in error && + typeof error.code === "string" + ); +} + export function prettyPrintPack(pack: Pack) { return `${pack.name}${pack.version ? `@${pack.version}` : ""}${ pack.path ? `:${pack.path}` : "" From 64723df932ef37cffa7dab62abf807484a079d07 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 22:40:36 +0100 Subject: [PATCH 032/174] Use temporary diagnostic dir in `generateFailedSarif` --- lib/entry-points.js | 11 +++++-- src/codeql.ts | 5 ++++ src/init-action-post-helper.test.ts | 45 +++++++++++++++++++++++++++++ src/init-action-post-helper.ts | 26 +++++++++++++++-- 4 files changed, 83 insertions(+), 4 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 674e6425f6..629ee5b6b0 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -177425,7 +177425,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion) { } await new toolrunner3.ToolRunner(cmd, args).exec(); }, - async diagnosticsExport(sarifFile, automationDetailsId, config) { + async diagnosticsExport(sarifFile, automationDetailsId, config, diagnosticDir) { const args = [ "diagnostics", "export", @@ -177434,6 +177434,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion) { `--sarif-codescanning-config=${getGeneratedCodeScanningConfigPath( config )}`, + ...diagnosticDir !== void 0 ? [`--diagnostic-dir=${diagnosticDir}`] : [], ...getExtraOptionsFromEnv(["diagnostics", "export"]) ]; if (automationDetailsId !== void 0) { @@ -187021,7 +187022,13 @@ async function generateFailedSarif(logger2, features, config, category, checkout sarifFile = "../codeql-failed-run.sarif"; } if (databasePath === void 0 || !await features.getValue("export_diagnostics_enabled" /* ExportDiagnosticsEnabled */, codeql)) { - await codeql.diagnosticsExport(sarifFile, category, config); + let diagnosticDir = getTempDiagnosticPath( + config.tempDir + ); + if (!fs31.existsSync(diagnosticDir)) { + diagnosticDir = void 0; + } + await codeql.diagnosticsExport(sarifFile, category, config, diagnosticDir); } else { await codeql.databaseExportDiagnostics(databasePath, sarifFile, category); } diff --git a/src/codeql.ts b/src/codeql.ts index a76e29727a..5981929c13 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -199,6 +199,7 @@ export interface CodeQL { sarifFile: string, automationDetailsId: string | undefined, config: ActionConfig<"tempDir">, + diagnosticDir: string | undefined, ): Promise; /** Get the location of an extractor for the specified language. */ resolveExtractor(language: Language): Promise; @@ -915,6 +916,7 @@ async function getCodeQLForCmd( sarifFile: string, automationDetailsId: string | undefined, config: ActionConfig<"tempDir">, + diagnosticDir: string | undefined, ): Promise { const args = [ "diagnostics", @@ -924,6 +926,9 @@ async function getCodeQLForCmd( `--sarif-codescanning-config=${getGeneratedCodeScanningConfigPath( config, )}`, + ...(diagnosticDir !== undefined + ? [`--diagnostic-dir=${diagnosticDir}`] + : []), ...getExtraOptionsFromEnv(["diagnostics", "export"]), ]; if (automationDetailsId !== undefined) { diff --git a/src/init-action-post-helper.test.ts b/src/init-action-post-helper.test.ts index 554add71fc..b90ad3047a 100644 --- a/src/init-action-post-helper.test.ts +++ b/src/init-action-post-helper.test.ts @@ -1,3 +1,6 @@ +import * as fs from "fs"; +import * as path from "path"; + import * as core from "@actions/core"; import test, { ExecutionContext } from "ava"; import * as sinon from "sinon"; @@ -8,6 +11,7 @@ import * as apiClient from "./api-client"; import * as codeql from "./codeql"; import * as configUtils from "./config-utils"; import * as debugArtifacts from "./debug-artifacts"; +import { getTempDiagnosticPath } from "./diagnostics"; import { EnvVar } from "./environment"; import { Feature } from "./feature-flags"; import * as initActionPostHelper from "./init-action-post-helper"; @@ -35,6 +39,47 @@ const NUM_BYTES_PER_GIB = 1024 * 1024 * 1024; setupTests(test); +test.serial("generateFailedSarif picks up unwritten diagnostics", async (t) => + util.withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + + const tempDiagDir = getTempDiagnosticPath(tmpDir); + fs.mkdirSync(tempDiagDir); + + const codeqlObject = await codeql.getCodeQLForTesting(); + const diagnosticsExport = sinon + .stub(codeqlObject, "diagnosticsExport") + .resolves(); + + sinon.stub(codeql, "getCodeQL").resolves(codeqlObject); + + const sarifFile = path.join(tmpDir, "failed.sarif"); + const result = await initActionPostHelper.generateFailedSarif( + logger, + createFeatures([]), + createTestConfig({ + tempDir: tmpDir, + // Explicitly undefined to ensure we get the "no database" path. + dbLocation: undefined, + }), + "category", + "", + sarifFile, + ); + + t.truthy(result); + t.is(diagnosticsExport.callCount, 1); + t.true( + diagnosticsExport.calledOnceWith( + sarifFile, + "category", + sinon.match.any, + tempDiagDir, + ), + ); + }), +); + test.serial("init-post action with debug mode off", async (t) => { return await util.withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); diff --git a/src/init-action-post-helper.ts b/src/init-action-post-helper.ts index cfaab312fb..83c2aec9fc 100644 --- a/src/init-action-post-helper.ts +++ b/src/init-action-post-helper.ts @@ -24,6 +24,7 @@ import { type UploadDebugArtifactsConfig, } from "./debug-artifacts"; import * as dependencyCaching from "./dependency-caching"; +import { getTempDiagnosticPath } from "./diagnostics"; import { EnvVar, ReadOnlyEnv } from "./environment"; import { Feature, FeatureEnablement } from "./feature-flags"; import { Logger } from "./logging"; @@ -177,7 +178,16 @@ async function prepareFailedSarif( } } -async function generateFailedSarif( +/** + * Generates a SARIF file for a failed run, i.e. an analysis where no SARIF was produced as a result of the analysis. + * + * Not intended to be called directly, other than by `prepareFailedSarif`. + * + * @param category The analysis category to include in the SARIF. + * @param checkoutPath The path where the repository was checked out at. + * @param sarifFile The SARIF file to produce. + */ +export async function generateFailedSarif( logger: Logger, features: FeatureEnablement, config: ActionConfig<"codeQLCmd" | "tempDir">, @@ -198,7 +208,19 @@ async function generateFailedSarif( databasePath === undefined || !(await features.getValue(Feature.ExportDiagnosticsEnabled, codeql)) ) { - await codeql.diagnosticsExport(sarifFile, category, config); + // If we don't have a database path, then we may have diagnostics that were written to a + // temporary location. Get the path that they would have been written to and check whether + // it exists. If so, pass it on to the CLI. The CLI will not complain if we give it a + // path that doesn't exist, so we are just being extra defensive here. + let diagnosticDir: string | undefined = getTempDiagnosticPath( + config.tempDir, + ); + + if (!fs.existsSync(diagnosticDir)) { + diagnosticDir = undefined; + } + + await codeql.diagnosticsExport(sarifFile, category, config, diagnosticDir); } else { // We call 'database export-diagnostics' to find any per-database diagnostics. await codeql.databaseExportDiagnostics(databasePath, sarifFile, category); From 581a0e148ec5728a67211b30328c100a6e28894d Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 12 Oct 2026 16:15:55 +0100 Subject: [PATCH 033/174] Refactor `writeTemporaryDiagnosticFile` out of `add[NoLanguage]Diagnostic` --- lib/entry-points.js | 29 +++++++++++++++++++++++------ src/diagnostics.ts | 42 +++++++++++++++++++++++++++++++++++------- 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 629ee5b6b0..e2fac0cfbf 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -173023,12 +173023,10 @@ function addDiagnostic(config, language, diagnostic, logger2 = getActionsLogger( logger2.debug( `Writing a diagnostic for ${language}, but the database at ${databasePath} does not exist yet.` ); - const tempDiagnosticsPath = getTempDiagnosticPath(config.tempDir, language); - const diagnosticPath = writeDiagnosticFile(tempDiagnosticsPath, diagnostic); - temporaryDiagnostics.push({ path: diagnosticPath, language }); + writeTemporaryDiagnosticFile(logger2, config.tempDir, language, diagnostic); } } -function addNoLanguageDiagnostic(config, diagnostic) { +function addNoLanguageDiagnostic(config, diagnostic, logger2 = getActionsLogger()) { if (config !== void 0) { addDiagnostic( config, @@ -173038,9 +173036,28 @@ function addNoLanguageDiagnostic(config, diagnostic) { diagnostic ); } else { - const tempDiagnosticsPath = getTempDiagnosticPath(getTemporaryDirectory()); + logger2.debug( + `Writing a diagnostic not associated with any language, but we have no configuration to tell us where the database is yet.` + ); + writeTemporaryDiagnosticFile( + logger2, + getTemporaryDirectory(), + void 0, + diagnostic + ); + } +} +function writeTemporaryDiagnosticFile(logger2, tempDir, language, diagnostic) { + const tempDiagnosticsPath = getTempDiagnosticPath(tempDir, language); + try { const diagnosticPath = writeDiagnosticFile(tempDiagnosticsPath, diagnostic); - temporaryDiagnostics.push({ path: diagnosticPath }); + temporaryDiagnostics.push({ path: diagnosticPath, language }); + } catch (err) { + logger2.warning( + `Unable to write temporary diagnostic to '${tempDiagnosticsPath}': ${getErrorMessage(err)} + +${JSON.stringify(diagnostic)}` + ); } } function writeDiagnosticFile(diagnosticsPath, diagnostic) { diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 1e74f52525..a3b44fd760 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -179,11 +179,7 @@ export function addDiagnostic( ); // Write the diagnostic to a temporary location. - const tempDiagnosticsPath = getTempDiagnosticPath(config.tempDir, language); - const diagnosticPath = writeDiagnosticFile(tempDiagnosticsPath, diagnostic); - - // Track the temporary file. - temporaryDiagnostics.push({ path: diagnosticPath, language }); + writeTemporaryDiagnosticFile(logger, config.tempDir, language, diagnostic); } } @@ -191,6 +187,7 @@ export function addDiagnostic( export function addNoLanguageDiagnostic( config: Config | undefined, diagnostic: DiagnosticMessage, + logger: Logger = getActionsLogger(), ) { if (config !== undefined) { addDiagnostic( @@ -201,11 +198,42 @@ export function addNoLanguageDiagnostic( diagnostic, ); } else { - const tempDiagnosticsPath = getTempDiagnosticPath(getTemporaryDirectory()); + logger.debug( + `Writing a diagnostic not associated with any language, but we have no configuration to tell us where the database is yet.`, + ); + + // Write the diagnostic to a temporary location. + writeTemporaryDiagnosticFile( + logger, + getTemporaryDirectory(), + undefined, + diagnostic, + ); + } +} + +/** + * Writes {@link diagnostic} for an optional {@link language} to a subdirectory of {@link tempDir} + * and tracks it as a diagnostic that was written to a temporary location. + */ +function writeTemporaryDiagnosticFile( + logger: Logger, + tempDir: string, + language: Language | undefined, + diagnostic: DiagnosticMessage, +) { + const tempDiagnosticsPath = getTempDiagnosticPath(tempDir, language); + + try { + // Write the diagnostic to a temporary location. const diagnosticPath = writeDiagnosticFile(tempDiagnosticsPath, diagnostic); // Track the temporary file. - temporaryDiagnostics.push({ path: diagnosticPath }); + temporaryDiagnostics.push({ path: diagnosticPath, language }); + } catch (err) { + logger.warning( + `Unable to write temporary diagnostic to '${tempDiagnosticsPath}': ${getErrorMessage(err)}\n\n${JSON.stringify(diagnostic)}`, + ); } } From ba569ac626d7a9c07b266134ee00281f678593ab Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 12:23:00 +0100 Subject: [PATCH 034/174] Omit `--sarif-codescanning-config` if the config file doesn't exist --- lib/entry-points.js | 8 +++++--- src/codeql.ts | 19 ++++++++++++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index e2fac0cfbf..089961508c 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -177443,14 +177443,16 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion) { await new toolrunner3.ToolRunner(cmd, args).exec(); }, async diagnosticsExport(sarifFile, automationDetailsId, config, diagnosticDir) { + let configPath = getGeneratedCodeScanningConfigPath(config); + if (diagnosticDir !== void 0 && !fs17.existsSync(configPath)) { + configPath = void 0; + } const args = [ "diagnostics", "export", "--format=sarif-latest", `--output=${sarifFile}`, - `--sarif-codescanning-config=${getGeneratedCodeScanningConfigPath( - config - )}`, + ...configPath !== void 0 ? [`--sarif-codescanning-config=${configPath}`] : [], ...diagnosticDir !== void 0 ? [`--diagnostic-dir=${diagnosticDir}`] : [], ...getExtraOptionsFromEnv(["diagnostics", "export"]) ]; diff --git a/src/codeql.ts b/src/codeql.ts index 5981929c13..7595e604a6 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -918,14 +918,27 @@ async function getCodeQLForCmd( config: ActionConfig<"tempDir">, diagnosticDir: string | undefined, ): Promise { + // We may be exporting diagnostics for a failed SARIF, in which case the configuration + // file may not have been written to disk and there may not be a database. The CLI + // will produce a SARIF for diagnostics from `diagnosticDir` without it. Therefore, + // if `diagnosticDir` is set, we check whether `configPath` exists and only provide + // it to the CLI if it does. Although not needed, the CLI will produce an error if it + // is provided with an argument to `--sarif-codescanning-config` that does not exist. + let configPath: string | undefined = + getGeneratedCodeScanningConfigPath(config); + + if (diagnosticDir !== undefined && !fs.existsSync(configPath)) { + configPath = undefined; + } + const args = [ "diagnostics", "export", "--format=sarif-latest", `--output=${sarifFile}`, - `--sarif-codescanning-config=${getGeneratedCodeScanningConfigPath( - config, - )}`, + ...(configPath !== undefined + ? [`--sarif-codescanning-config=${configPath}`] + : []), ...(diagnosticDir !== undefined ? [`--diagnostic-dir=${diagnosticDir}`] : []), From b963054f39f4598d33d386cb17f34bb786778400 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 12 Oct 2026 13:58:12 +0100 Subject: [PATCH 035/174] Add e2e test --- .../workflows/__diagnostics-without-db.yml | 138 ++++++++++++++++++ pr-checks/check-diagnostics.ts | 41 ++++-- pr-checks/checks/diagnostics-without-db.yml | 67 +++++++++ pr-checks/diagnostics-without-db.ts | 48 ++++++ pr-checks/sync.ts | 38 +++-- 5 files changed, 307 insertions(+), 25 deletions(-) create mode 100644 .github/workflows/__diagnostics-without-db.yml create mode 100644 pr-checks/checks/diagnostics-without-db.yml create mode 100644 pr-checks/diagnostics-without-db.ts diff --git a/.github/workflows/__diagnostics-without-db.yml b/.github/workflows/__diagnostics-without-db.yml new file mode 100644 index 0000000000..27200f181a --- /dev/null +++ b/.github/workflows/__diagnostics-without-db.yml @@ -0,0 +1,138 @@ +# Warning: This file is generated automatically, and should not be modified. +# Instead, please modify the template in the pr-checks directory and run: +# pr-checks/sync.sh +# to regenerate this file. + +name: PR Check - Diagnostic export without database +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GO111MODULE: auto +on: + push: + branches: + - main + - releases/v* + pull_request: {} + merge_group: + types: + - checks_requested + schedule: + - cron: '0 5 * * *' + workflow_dispatch: + inputs: {} + workflow_call: + inputs: {} +defaults: + run: + shell: bash +concurrency: + cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} + group: diagnostics-without-db-${{github.ref}} +jobs: + diagnostics-without-db: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + version: linked + name: Diagnostic export without database + if: github.triggering_actor != 'dependabot[bot]' + permissions: + contents: read + security-events: read + timeout-minutes: 45 + runs-on: ${{ matrix.os }} + steps: + # We deliberately need to make this step fail before the database is initialised, but after + # some diagnostic has been produced. The simplest way to do that right now is to force the + # use of a nightly release and then fail because we are attempting to analyse Swift on + # a non-macOS runner. + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Install Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: 20.x + cache: npm + - name: Install newer npm + run: npm install -g npm@11.19.1 + - name: Install dependencies + run: npm ci + - name: Prepare test + id: prepare-test + uses: ./.github/actions/prepare-test + with: + version: ${{ matrix.version }} + use-all-platform-bundle: 'false' + setup-kotlin: 'true' + - name: Initialise failing analysis + id: init + uses: ./../action/init + continue-on-error: true + env: + CODEQL_ACTION_FORCE_NIGHTLY: true + with: + languages: swift + tools: ${{ steps.prepare-test.outputs.tools-url }} + + - name: Analyze + uses: ./analyze + # In a real workflow, this step wouldn't run. Since we used `continue-on-error` + # above, we manually disable it with an `if` condition. + if: false + with: + category: '/test-codeql-version:${{ matrix.version }}' + + - name: Check diagnostics appear on disk + env: + SARIF_PATH: '${{ runner.temp }}/codeql-action-temp-diagnostics/' + run: | + cd ../action + npx tsx ./pr-checks/diagnostics-without-db.ts + env: + CODEQL_ACTION_SKIP_GENERATE_FAILED_SARIF: false + CODEQL_ACTION_SKIP_SARIF_UPLOAD: true + CODEQL_ACTION_TESTING_ENVIRONMENT: codeql-action-pr-checks + CODEQL_ACTION_TEST_MODE: true + diagnostics-without-db-validation: + if: github.triggering_actor != 'dependabot[bot]' + needs: + - diagnostics-without-db + permissions: + contents: read + security-events: read + timeout-minutes: 5 + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Install Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: 20.x + cache: npm + - name: Install newer npm + run: npm install -g npm@11.19.1 + - name: Install dependencies + run: npm ci + - name: Download workflow artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: test-mode-sarif-* + path: sarif + + - name: List artifact contents + run: ls -laR ./sarif + + - name: Check diagnostics appear in SARIF + env: + SARIF_PATH: "./sarif/codeql-failed-run.sarif" + DIAGNOSTIC_ID: "codeql-action/forced-nightly-cli" + DIAGNOSTIC_NAME: "A nightly release of CodeQL was used" + EXPECTED_LOCATIONS: "0" + EXPECTED_MESSAGE: | + GitHub configured this analysis to use a nightly release of CodeQL to allow you to preview changes from an upcoming release. + run: npx tsx ./pr-checks/check-diagnostics.ts + env: + CODEQL_ACTION_TEST_MODE: true diff --git a/pr-checks/check-diagnostics.ts b/pr-checks/check-diagnostics.ts index 0a35ac28b8..6e9d0ba82c 100644 --- a/pr-checks/check-diagnostics.ts +++ b/pr-checks/check-diagnostics.ts @@ -4,16 +4,32 @@ import * as core from "@actions/core"; import * as sarif from "../src/sarif"; -function checkStatusPageNotification(n) { - const expectedMessage = "Plaintext message"; - if (n.message.text !== expectedMessage) { - core.setFailed( - `Expected the status page diagnostic to have the message '${expectedMessage}', but found '${n.message.text}'.`, - ); +const DIAGNOSTIC_ID = + process.env["DIAGNOSTIC_ID"] ?? "lang/diagnostics/example"; +const DIAGNOSTIC_NAME = process.env["DIAGNOSTIC_NAME"] ?? "Diagnostic name"; +const EXPECTED_MESSAGE = process.env["EXPECTED_MESSAGE"] ?? "Plaintext message"; +const EXPECTED_LOCATIONS = Number.parseInt( + process.env["EXPECTED_LOCATIONS"] ?? "1", +); + +function checkStatusPageNotification(n: sarif.Notification) { + const expectedMessage = EXPECTED_MESSAGE.trim(); + if (!n.message.text?.includes(expectedMessage)) { + if (n.message.text !== undefined) { + core.setFailed( + `Expected the status page diagnostic to contain the message '${expectedMessage}', but found '${n.message.text.replaceAll("\n", "\\n")}'.`, + ); + } else { + core.setFailed( + `Expected the status page diagnostic to contain the message '${expectedMessage}', but found nothing.`, + ); + } } - if (n.locations.length !== 1) { + + const locationCount = n.locations?.length ?? 0; + if (locationCount !== EXPECTED_LOCATIONS) { core.setFailed( - `Expected the status page diagnostic to have exactly 1 location, but found ${n.locations.length}.`, + `Expected the status page diagnostic to have exactly ${EXPECTED_LOCATIONS} location(s), but found ${locationCount}.`, ); } } @@ -40,8 +56,7 @@ if (toolExecutionNotifications === undefined) { const statusPageNotifications = toolExecutionNotifications.filter( (n) => - n.descriptor?.id === "lang/diagnostics/example" && - n.properties?.visibility?.statusPage, + n.descriptor?.id === DIAGNOSTIC_ID && n.properties?.visibility?.statusPage, ); if (statusPageNotifications.length !== 1) { core.setFailed( @@ -61,9 +76,9 @@ if (notifications === undefined) { const diagnosticNotification = notifications.filter( (n) => - n.id === "lang/diagnostics/example" && - n.name === "lang/diagnostics/example" && - n.fullDescription?.text === "Diagnostic name", + n.id === DIAGNOSTIC_ID && + n.name === DIAGNOSTIC_ID && + n.fullDescription?.text === DIAGNOSTIC_NAME, ); if (diagnosticNotification.length !== 1) { core.setFailed( diff --git a/pr-checks/checks/diagnostics-without-db.yml b/pr-checks/checks/diagnostics-without-db.yml new file mode 100644 index 0000000000..f4bdfc4510 --- /dev/null +++ b/pr-checks/checks/diagnostics-without-db.yml @@ -0,0 +1,67 @@ +name: "Diagnostic export without database" +description: "Tests that temporary diagnostics are correctly included in the failed SARIF." +versions: + # Overridden by the FF below. + - linked +installNode: true + +env: + # Allow the failed SARIF file to be generated. + CODEQL_ACTION_SKIP_GENERATE_FAILED_SARIF: false + # But don't actually upload it. + CODEQL_ACTION_SKIP_SARIF_UPLOAD: true + # Mark telemetry for this workflow so it can be treated separately. + CODEQL_ACTION_TESTING_ENVIRONMENT: codeql-action-pr-checks + +steps: + # We deliberately need to make this step fail before the database is initialised, but after + # some diagnostic has been produced. The simplest way to do that right now is to force the + # use of a nightly release and then fail because we are attempting to analyse Swift on + # a non-macOS runner. + - name: Initialise failing analysis + id: init + uses: ./../action/init + continue-on-error: true + env: + CODEQL_ACTION_FORCE_NIGHTLY: true + with: + languages: swift + tools: ${{ steps.prepare-test.outputs.tools-url }} + + - name: Analyze + uses: ./analyze + # In a real workflow, this step wouldn't run. Since we used `continue-on-error` + # above, we manually disable it with an `if` condition. + if: false + with: + category: "/test-codeql-version:${{ matrix.version }}" + + - name: Check diagnostics appear on disk + env: + SARIF_PATH: "${{ runner.temp }}/codeql-action-temp-diagnostics/" + run: | + cd ../action + npx tsx ./pr-checks/diagnostics-without-db.ts +validationJobs: + diagnostics-without-db-validation: + checkout: true + installNode: true + steps: + - name: Download workflow artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: test-mode-sarif-* + path: sarif + + - name: List artifact contents + run: ls -laR ./sarif + + - name: Check diagnostics appear in SARIF + env: + SARIF_PATH: "./sarif/codeql-failed-run.sarif" + DIAGNOSTIC_ID: "codeql-action/forced-nightly-cli" + DIAGNOSTIC_NAME: "A nightly release of CodeQL was used" + EXPECTED_LOCATIONS: "0" + EXPECTED_MESSAGE: | + GitHub configured this analysis to use a nightly release of CodeQL to allow you to preview changes from an upcoming release. + run: npx tsx ./pr-checks/check-diagnostics.ts diff --git a/pr-checks/diagnostics-without-db.ts b/pr-checks/diagnostics-without-db.ts new file mode 100644 index 0000000000..b742c10d68 --- /dev/null +++ b/pr-checks/diagnostics-without-db.ts @@ -0,0 +1,48 @@ +import * as fs from "fs"; +import * as path from "path"; + +import * as core from "@actions/core"; + +import type * as diagnostics from "../src/diagnostics"; + +const DIAGNOSTIC_ID = "codeql-action/forced-nightly-cli"; +const sarifDirectory = process.env["SARIF_PATH"]; + +if (sarifDirectory === undefined) { + throw new Error("SARIF_PATH is undefined."); +} + +const paths = fs + .readdirSync(sarifDirectory, { + recursive: true, + encoding: "utf-8", + }) + .filter((p) => p.endsWith(".json")); + +core.info(`Found ${paths.length} paths in '${sarifDirectory}'.`); +core.info(`Searching for a diagnostic with id '${DIAGNOSTIC_ID}'...`); + +let found = false; +for (const diagnosticPath of paths) { + if (path.extname(diagnosticPath) !== ".json") { + core.info(`Skipping ${diagnosticPath}.`); + continue; + } + core.info(`Found ${diagnosticPath}.`); + + const contents = JSON.parse( + fs.readFileSync(path.resolve(sarifDirectory, diagnosticPath), "utf-8"), + ) as diagnostics.DiagnosticMessage; + + if (contents.source.id === DIAGNOSTIC_ID) { + core.info( + `Found '${DIAGNOSTIC_ID}' in '${diagnosticPath}'. Skipping remaining files.`, + ); + found = true; + break; + } +} + +if (!found) { + throw new Error(`Didn't find '${DIAGNOSTIC_ID}' diagnostic.`); +} diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index d6382786c3..57fa3cab3d 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -90,7 +90,7 @@ interface Specification extends JobSpecification { services?: any; /** Additional jobs to run after the main PR check job. */ - validationJobs?: Record; + validationJobs?: Record; /** If set, this check is part of a named collection that gets its own caller workflow. */ collection?: string; @@ -122,6 +122,10 @@ interface JobSpecification { installYq?: boolean; } +type ValidationJobSpecification = JobSpecification & { + checkout?: boolean; +}; + /** Describes language/framework-specific steps and inputs. */ interface LanguageSetup { specProperty: keyof JobSpecification; @@ -462,6 +466,20 @@ function generateJobMatrix( return matrix; } +/** + * Gets the `actions/checkout` step. + */ +function getCheckoutStep(): Step { + return { + name: "Check out repository", + uses: pinnedUses( + "actions/checkout", + "3d3c42e5aac5ba805825da76410c181273ba90b1", + "v7.0.1", + ), + }; +} + /** * Retrieves setup steps and additional input definitions based on specific languages or frameworks * that are requested by the `checkSpecification`. @@ -531,14 +549,7 @@ function generateJob( // Construct the workflow steps needed for this check. const steps: Step[] = [ - { - name: "Check out repository", - uses: pinnedUses( - "actions/checkout", - "3d3c42e5aac5ba805825da76410c181273ba90b1", - "v7.0.1", - ), - }, + getCheckoutStep(), ...setupInfo.steps, { name: "Prepare test", @@ -609,13 +620,16 @@ function generateJob( /** Generates a validation job. */ function generateValidationJob( specDocument: yaml.Document, - jobSpecification: JobSpecification, + jobSpecification: ValidationJobSpecification, checkName: string, name: string, ) { // Determine which languages or frameworks have to be installed. const { inputs, steps } = getSetupSteps(jobSpecification); + // Construct a checkout step if requested. + const checkoutStep = jobSpecification.checkout ? [getCheckoutStep()] : []; + // Extract the sequence of steps from the YAML document to persist as much formatting as possible. const specSteps = specDocument.getIn([ "validationJobs", @@ -624,7 +638,7 @@ function generateValidationJob( ]) as yaml.YAMLSeq; // Add the generated steps in front of the ones from the specification. - specSteps.items.unshift(...steps); + specSteps.items.unshift(...checkoutStep, ...steps); const validationJob: Record = { name: jobSpecification.name, @@ -635,7 +649,7 @@ function generateValidationJob( "security-events": "read", }, "timeout-minutes": 5, - "runs-on": "ubuntu-slim", + "runs-on": "ubuntu-latest", steps: specSteps, }; From 8357829c18a93705759e3a6bbe5d787615081e87 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 12:22:44 +0100 Subject: [PATCH 036/174] Use same sub-path in `getDiagnosticsPath` for no language case --- lib/entry-points.js | 2 +- src/diagnostics.ts | 2 +- src/init-action-post-helper.test.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 089961508c..ea3097da7c 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -173013,7 +173013,7 @@ function getDiagnosticsPath(basePath, language) { if (language !== void 0) { return import_path2.default.resolve(basePath, language, "diagnostic", "codeql-action"); } - return basePath; + return import_path2.default.resolve(basePath, "diagnostic", "codeql-action"); } function addDiagnostic(config, language, diagnostic, logger2 = getActionsLogger()) { const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; diff --git a/src/diagnostics.ts b/src/diagnostics.ts index a3b44fd760..272706c4e4 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -148,7 +148,7 @@ export function getDiagnosticsPath(basePath: string, language?: Language) { if (language !== undefined) { return path.resolve(basePath, language, "diagnostic", "codeql-action"); } - return basePath; + return path.resolve(basePath, "diagnostic", "codeql-action"); } /** diff --git a/src/init-action-post-helper.test.ts b/src/init-action-post-helper.test.ts index b90ad3047a..aaee9c33f6 100644 --- a/src/init-action-post-helper.test.ts +++ b/src/init-action-post-helper.test.ts @@ -44,7 +44,7 @@ test.serial("generateFailedSarif picks up unwritten diagnostics", async (t) => const logger = new RecordingLogger(); const tempDiagDir = getTempDiagnosticPath(tmpDir); - fs.mkdirSync(tempDiagDir); + fs.mkdirSync(tempDiagDir, { recursive: true }); const codeqlObject = await codeql.getCodeQLForTesting(); const diagnosticsExport = sinon From 98b8e51380c9bb16f7d21a67486a64d853b3544f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 12:28:26 +0100 Subject: [PATCH 037/174] Always check whether config file exists And emit a warning if it doesn't --- lib/entry-points.js | 8 +++++++- src/codeql.ts | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index aeb99eb43d..5ab2e57fe9 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -177439,7 +177439,13 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion) { }, async diagnosticsExport(sarifFile, automationDetailsId, config, diagnosticDir) { let configPath = getGeneratedCodeScanningConfigPath(config); - if (diagnosticDir !== void 0 && !fs17.existsSync(configPath)) { + if (!fs17.existsSync(configPath)) { + logger2.warning( + [ + `Expected a configuration file at '${configPath}', which does not exist.`, + "Continuing with diagnostics export anyway, without a configuration file." + ].join(" ") + ); configPath = void 0; } const args = [ diff --git a/src/codeql.ts b/src/codeql.ts index 7595e604a6..b88144a253 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -927,7 +927,13 @@ async function getCodeQLForCmd( let configPath: string | undefined = getGeneratedCodeScanningConfigPath(config); - if (diagnosticDir !== undefined && !fs.existsSync(configPath)) { + if (!fs.existsSync(configPath)) { + logger.warning( + [ + `Expected a configuration file at '${configPath}', which does not exist.`, + "Continuing with diagnostics export anyway, without a configuration file.", + ].join(" "), + ); configPath = undefined; } From 4707994e6e9979b210fcf8fc655fac8b5665b670 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 13:03:37 +0100 Subject: [PATCH 038/174] Don't include diagnostics if FF is off --- lib/entry-points.js | 8 ++++++-- src/init-action-post-helper.test.ts | 2 +- src/init-action-post-helper.ts | 13 ++++++++----- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 5ab2e57fe9..6128fe3b4c 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -187041,11 +187041,15 @@ async function generateFailedSarif(logger2, features, config, category, checkout if (sarifFile === void 0) { sarifFile = "../codeql-failed-run.sarif"; } - if (databasePath === void 0 || !await features.getValue("export_diagnostics_enabled" /* ExportDiagnosticsEnabled */, codeql)) { + const exportDiagnosticsEnabled = await features.getValue( + "export_diagnostics_enabled" /* ExportDiagnosticsEnabled */, + codeql + ); + if (databasePath === void 0 || !exportDiagnosticsEnabled) { let diagnosticDir = getTempDiagnosticPath( config.tempDir ); - if (!fs31.existsSync(diagnosticDir)) { + if (!exportDiagnosticsEnabled || !fs31.existsSync(diagnosticDir)) { diagnosticDir = void 0; } await codeql.diagnosticsExport(sarifFile, category, config, diagnosticDir); diff --git a/src/init-action-post-helper.test.ts b/src/init-action-post-helper.test.ts index aaee9c33f6..0458dbf52b 100644 --- a/src/init-action-post-helper.test.ts +++ b/src/init-action-post-helper.test.ts @@ -56,7 +56,7 @@ test.serial("generateFailedSarif picks up unwritten diagnostics", async (t) => const sarifFile = path.join(tmpDir, "failed.sarif"); const result = await initActionPostHelper.generateFailedSarif( logger, - createFeatures([]), + createFeatures([Feature.ExportDiagnosticsEnabled]), createTestConfig({ tempDir: tmpDir, // Explicitly undefined to ensure we get the "no database" path. diff --git a/src/init-action-post-helper.ts b/src/init-action-post-helper.ts index 83c2aec9fc..b86ed9dbb7 100644 --- a/src/init-action-post-helper.ts +++ b/src/init-action-post-helper.ts @@ -204,19 +204,22 @@ export async function generateFailedSarif( } // If there is no database or the feature flag is off, we run 'export diagnostics' - if ( - databasePath === undefined || - !(await features.getValue(Feature.ExportDiagnosticsEnabled, codeql)) - ) { + const exportDiagnosticsEnabled = await features.getValue( + Feature.ExportDiagnosticsEnabled, + codeql, + ); + if (databasePath === undefined || !exportDiagnosticsEnabled) { // If we don't have a database path, then we may have diagnostics that were written to a // temporary location. Get the path that they would have been written to and check whether // it exists. If so, pass it on to the CLI. The CLI will not complain if we give it a // path that doesn't exist, so we are just being extra defensive here. + // We also don't pass the path to the CLI if `exportDiagnosticsEnabled` is not enabled, to preserve + // its intended behaviour of controlling whether diagnostics are included in the SARIF or not. let diagnosticDir: string | undefined = getTempDiagnosticPath( config.tempDir, ); - if (!fs.existsSync(diagnosticDir)) { + if (!exportDiagnosticsEnabled || !fs.existsSync(diagnosticDir)) { diagnosticDir = undefined; } From 67cd8c12d4e80909882f0c440b46b9a4dcf0dd17 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 15:15:17 +0100 Subject: [PATCH 039/174] Rename env var to `DIAGNOSTICS_DIR` --- .github/workflows/__diagnostics-without-db.yml | 2 +- pr-checks/checks/diagnostics-without-db.yml | 2 +- pr-checks/diagnostics-without-db.ts | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/__diagnostics-without-db.yml b/.github/workflows/__diagnostics-without-db.yml index 27200f181a..71c597d744 100644 --- a/.github/workflows/__diagnostics-without-db.yml +++ b/.github/workflows/__diagnostics-without-db.yml @@ -86,7 +86,7 @@ jobs: - name: Check diagnostics appear on disk env: - SARIF_PATH: '${{ runner.temp }}/codeql-action-temp-diagnostics/' + DIAGNOSTICS_DIR: '${{ runner.temp }}/codeql-action-temp-diagnostics/' run: | cd ../action npx tsx ./pr-checks/diagnostics-without-db.ts diff --git a/pr-checks/checks/diagnostics-without-db.yml b/pr-checks/checks/diagnostics-without-db.yml index f4bdfc4510..e346a1cabd 100644 --- a/pr-checks/checks/diagnostics-without-db.yml +++ b/pr-checks/checks/diagnostics-without-db.yml @@ -38,7 +38,7 @@ steps: - name: Check diagnostics appear on disk env: - SARIF_PATH: "${{ runner.temp }}/codeql-action-temp-diagnostics/" + DIAGNOSTICS_DIR: "${{ runner.temp }}/codeql-action-temp-diagnostics/" run: | cd ../action npx tsx ./pr-checks/diagnostics-without-db.ts diff --git a/pr-checks/diagnostics-without-db.ts b/pr-checks/diagnostics-without-db.ts index b742c10d68..b276260f9d 100644 --- a/pr-checks/diagnostics-without-db.ts +++ b/pr-checks/diagnostics-without-db.ts @@ -6,20 +6,20 @@ import * as core from "@actions/core"; import type * as diagnostics from "../src/diagnostics"; const DIAGNOSTIC_ID = "codeql-action/forced-nightly-cli"; -const sarifDirectory = process.env["SARIF_PATH"]; +const diagnosticDirectory = process.env["DIAGNOSTICS_DIR"]; -if (sarifDirectory === undefined) { - throw new Error("SARIF_PATH is undefined."); +if (diagnosticDirectory === undefined) { + throw new Error("DIAGNOSTICS_DIR is undefined."); } const paths = fs - .readdirSync(sarifDirectory, { + .readdirSync(diagnosticDirectory, { recursive: true, encoding: "utf-8", }) .filter((p) => p.endsWith(".json")); -core.info(`Found ${paths.length} paths in '${sarifDirectory}'.`); +core.info(`Found ${paths.length} paths in '${diagnosticDirectory}'.`); core.info(`Searching for a diagnostic with id '${DIAGNOSTIC_ID}'...`); let found = false; @@ -31,7 +31,7 @@ for (const diagnosticPath of paths) { core.info(`Found ${diagnosticPath}.`); const contents = JSON.parse( - fs.readFileSync(path.resolve(sarifDirectory, diagnosticPath), "utf-8"), + fs.readFileSync(path.resolve(diagnosticDirectory, diagnosticPath), "utf-8"), ) as diagnostics.DiagnosticMessage; if (contents.source.id === DIAGNOSTIC_ID) { From a83f6f50cda0c5daf29cd4fb6020a4078972db51 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 15:17:33 +0100 Subject: [PATCH 040/174] Update skipped `analyze` step comment --- .github/workflows/__diagnostics-without-db.yml | 4 +++- .github/workflows/__submit-sarif-failure.yml | 4 +++- pr-checks/checks/diagnostics-without-db.yml | 4 +++- pr-checks/checks/submit-sarif-failure.yml | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/__diagnostics-without-db.yml b/.github/workflows/__diagnostics-without-db.yml index 71c597d744..2122225a25 100644 --- a/.github/workflows/__diagnostics-without-db.yml +++ b/.github/workflows/__diagnostics-without-db.yml @@ -79,7 +79,9 @@ jobs: - name: Analyze uses: ./analyze # In a real workflow, this step wouldn't run. Since we used `continue-on-error` - # above, we manually disable it with an `if` condition. + # above, we manually disable it with an `if` condition. Having this step is required + # for the init post-action because it checks the workflow definition for e.g. the + # `category` input. Without this step, that part of the init post-action would fail. if: false with: category: '/test-codeql-version:${{ matrix.version }}' diff --git a/.github/workflows/__submit-sarif-failure.yml b/.github/workflows/__submit-sarif-failure.yml index 099e93001f..36f7be4eb6 100644 --- a/.github/workflows/__submit-sarif-failure.yml +++ b/.github/workflows/__submit-sarif-failure.yml @@ -71,7 +71,9 @@ jobs: run: exit 1 - uses: ./analyze # In a real workflow, this step wouldn't run. Since we used `continue-on-error` - # above, we manually disable it with an `if` condition. + # above, we manually disable it with an `if` condition. Having this step is required + # for the init post-action because it checks the workflow definition for e.g. the + # `category` input. Without this step, that part of the init post-action would fail. if: false with: category: '/test-codeql-version:${{ matrix.version }}' diff --git a/pr-checks/checks/diagnostics-without-db.yml b/pr-checks/checks/diagnostics-without-db.yml index e346a1cabd..d15878cfcb 100644 --- a/pr-checks/checks/diagnostics-without-db.yml +++ b/pr-checks/checks/diagnostics-without-db.yml @@ -31,7 +31,9 @@ steps: - name: Analyze uses: ./analyze # In a real workflow, this step wouldn't run. Since we used `continue-on-error` - # above, we manually disable it with an `if` condition. + # above, we manually disable it with an `if` condition. Having this step is required + # for the init post-action because it checks the workflow definition for e.g. the + # `category` input. Without this step, that part of the init post-action would fail. if: false with: category: "/test-codeql-version:${{ matrix.version }}" diff --git a/pr-checks/checks/submit-sarif-failure.yml b/pr-checks/checks/submit-sarif-failure.yml index c33e1322f7..ea156ca931 100644 --- a/pr-checks/checks/submit-sarif-failure.yml +++ b/pr-checks/checks/submit-sarif-failure.yml @@ -35,7 +35,9 @@ steps: run: exit 1 - uses: ./analyze # In a real workflow, this step wouldn't run. Since we used `continue-on-error` - # above, we manually disable it with an `if` condition. + # above, we manually disable it with an `if` condition. Having this step is required + # for the init post-action because it checks the workflow definition for e.g. the + # `category` input. Without this step, that part of the init post-action would fail. if: false with: category: "/test-codeql-version:${{ matrix.version }}" From c3f2a34e23c03c1251cdf0b53376c626a69582de Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 15:31:30 +0100 Subject: [PATCH 041/174] Clarify comment that explains how the test works --- .github/workflows/__diagnostics-without-db.yml | 9 ++++++--- pr-checks/checks/diagnostics-without-db.yml | 11 +++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/workflows/__diagnostics-without-db.yml b/.github/workflows/__diagnostics-without-db.yml index 2122225a25..28472c95a7 100644 --- a/.github/workflows/__diagnostics-without-db.yml +++ b/.github/workflows/__diagnostics-without-db.yml @@ -45,9 +45,12 @@ jobs: runs-on: ${{ matrix.os }} steps: # We deliberately need to make this step fail before the database is initialised, but after - # some diagnostic has been produced. The simplest way to do that right now is to force the - # use of a nightly release and then fail because we are attempting to analyse Swift on - # a non-macOS runner. + # some diagnostic has been produced. The simplest way to do that right now is to: + # + # - Produce a diagnostic before the db is initialised by forcing the use of a nightly release + # with the `CODEQL_ACTION_FORCE_NIGHTLY` feature flag. + # - Cause `init` to abort because we are attempting to analyse Swift on a non-macOS runner. + # - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install Node.js diff --git a/pr-checks/checks/diagnostics-without-db.yml b/pr-checks/checks/diagnostics-without-db.yml index d15878cfcb..0d43f1c628 100644 --- a/pr-checks/checks/diagnostics-without-db.yml +++ b/pr-checks/checks/diagnostics-without-db.yml @@ -1,7 +1,7 @@ name: "Diagnostic export without database" description: "Tests that temporary diagnostics are correctly included in the failed SARIF." versions: - # Overridden by the FF below. + # Overridden by the FF in the `init` step below. - linked installNode: true @@ -15,9 +15,12 @@ env: steps: # We deliberately need to make this step fail before the database is initialised, but after - # some diagnostic has been produced. The simplest way to do that right now is to force the - # use of a nightly release and then fail because we are attempting to analyse Swift on - # a non-macOS runner. + # some diagnostic has been produced. The simplest way to do that right now is to: + # + # - Produce a diagnostic before the db is initialised by forcing the use of a nightly release + # with the `CODEQL_ACTION_FORCE_NIGHTLY` feature flag. + # - Cause `init` to abort because we are attempting to analyse Swift on a non-macOS runner. + # - name: Initialise failing analysis id: init uses: ./../action/init From 33f58aa90d0a355774a25beaff09a8c0ec561ba9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 15:48:42 +0000 Subject: [PATCH 042/174] Update changelog and version after v4.39.1 --- CHANGELOG.md | 4 ++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec85da14e3..8a96e0a9c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. +## [UNRELEASED] + +No user facing changes. + ## 4.39.1 - 21 Oct 2026 - Update default CodeQL bundle version to [2.27.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.3). [#4256](https://github.com/github/codeql-action/pull/4256) diff --git a/package-lock.json b/package-lock.json index d702b0f6f5..cfc9b231f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codeql", - "version": "4.39.1", + "version": "4.39.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codeql", - "version": "4.39.1", + "version": "4.39.2", "license": "MIT", "workspaces": [ "pr-checks" diff --git a/package.json b/package.json index 209ded6797..9bfd792221 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codeql", - "version": "4.39.1", + "version": "4.39.2", "private": true, "description": "CodeQL action", "scripts": { From 4cf32242898ad79d69aed5bc5bca8d94f1a902ae Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 15:48:52 +0000 Subject: [PATCH 043/174] Rebuild --- lib/entry-points.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 98c7f0488d..0b7e6c4e38 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -170161,7 +170161,7 @@ function getDiffRangesJsonFilePath(env = getEnv()) { return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME); } function getActionVersion() { - return "4.39.1"; + return "4.39.2"; } function getWorkflowEventName(env = getEnv()) { return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */); From 774bc191bf9b1c77dbbb2b95785ed3677330409d Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 22:04:24 +0100 Subject: [PATCH 044/174] Remove unused type parameters from `Env` classes --- src/environment.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/environment.ts b/src/environment.ts index 9f61070257..9867b27319 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -281,8 +281,8 @@ export function getOptionalEnvVar(paramName: string): string | undefined { * in tests, while clearly signalling in regular code that the consumer of the `ReadOnlyEnv` instance * will only read from it. */ -export class ReadOnlyEnv { - constructor(protected readonly vars: Record) {} +export class ReadOnlyEnv { + constructor(protected readonly vars: Record) {} /** Clones the object while detaching the underlying environment from the original. */ public clone(): this { @@ -290,7 +290,7 @@ export class ReadOnlyEnv { } /** Gets a copy of the underlying environment. */ - public get(): Record { + public get(): Record { return { ...this.vars }; } @@ -305,7 +305,7 @@ export class ReadOnlyEnv { } /** Gets the entries of the underlying `ProcessEnv`. */ - public entries(): Array<[string, T]> { + public entries(): Array<[string, string | undefined]> { return Object.entries(this.vars); } @@ -335,19 +335,17 @@ export class ReadOnlyEnv { * Use `ReadOnlyEnv` instead if you only plan to read from the environment. * This type allows writing to the environment. */ -export class Env< - T extends string | undefined = string | undefined, -> extends ReadOnlyEnv { +export class Env extends ReadOnlyEnv { private changed: boolean = false; /** Sets an environment variable. */ - public set(name: string, value: T): void { + public set(name: string, value: string | undefined): void { this.vars[name] = value; this.changed = true; } /** Sets all environment variables given by `vars`. */ - public setAll(vars: Record): void { + public setAll(vars: Record): void { for (const [key, val] of Object.entries(vars)) { this.set(key, val); } @@ -361,7 +359,7 @@ export class Env< * @param name The name of the environment variable to set and export. * @param val The value to set and export for the environment variable. */ - public export(name: string, val: T): void { + public export(name: string, val: string): void { // Setting the environment variable for this instance is always OK, including // in tests, since we use fresh `Env` instances whenever needed. This allows // tests to pass that rely on that part of the `core.exportVariable` behaviour. From 7def52843a117d3fab1270b95249abf351d46d5f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 22:15:06 +0100 Subject: [PATCH 045/174] Move `initializeEnvironment` out of `util.ts` --- lib/entry-points.js | 48 ++++++++++++++-------- src/actions-util.test.ts | 9 ++-- src/analyze-action.ts | 2 +- src/api-client.test.ts | 4 +- src/autobuild-action.ts | 15 +++++-- src/codeql.test.ts | 4 +- src/database-upload.test.ts | 11 ++--- src/environment.ts | 12 ++++++ src/feature-flags.test.ts | 5 ++- src/feature-flags/offline-features.test.ts | 4 +- src/init-action.ts | 3 +- src/setup-codeql-action.ts | 3 +- src/setup-codeql.test.ts | 18 ++++---- src/setup/repository.test.ts | 3 +- src/upload-lib.test.ts | 5 ++- src/upload-sarif-action.ts | 13 +++--- src/util.ts | 14 ------- 17 files changed, 93 insertions(+), 80 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 841bb36a12..9e674a2c1c 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -166182,6 +166182,17 @@ var Env = class extends ReadOnlyEnv { core.exportVariable(name, val); } } + /** + * Set some initial environment variables that we can set even without + * knowing what version of CodeQL we're running. + */ + initialise(version) { + this.export("CODEQL_ACTION_FEATURE_MULTI_LANGUAGE" /* FEATURE_MULTI_LANGUAGE */, "false"); + this.export("CODEQL_ACTION_FEATURE_SANDWICH" /* FEATURE_SANDWICH */, "false"); + this.export("CODEQL_ACTION_FEATURE_SARIF_COMBINE" /* FEATURE_SARIF_COMBINE */, "true"); + this.export("CODEQL_ACTION_FEATURE_WILL_UPLOAD" /* FEATURE_WILL_UPLOAD */, "true"); + this.export("CODEQL_ACTION_VERSION" /* VERSION */, version); + } /** Gets a value indicating whether `set` was called at least once. */ hasChanged() { return this.changed; @@ -169892,13 +169903,6 @@ var ExhaustivityCheckingError = class extends Error { function assertNever(value) { throw new ExhaustivityCheckingError(value); } -function initializeEnvironment(version, env = getEnv()) { - env.export("CODEQL_ACTION_FEATURE_MULTI_LANGUAGE" /* FEATURE_MULTI_LANGUAGE */, "false"); - env.export("CODEQL_ACTION_FEATURE_SANDWICH" /* FEATURE_SANDWICH */, "false"); - env.export("CODEQL_ACTION_FEATURE_SARIF_COMBINE" /* FEATURE_SARIF_COMBINE */, "true"); - env.export("CODEQL_ACTION_FEATURE_WILL_UPLOAD" /* FEATURE_WILL_UPLOAD */, "true"); - env.export("CODEQL_ACTION_VERSION" /* VERSION */, version); -} function getBaseDatabaseOidsFilePath(config) { return path.join(config.dbLocation, BASE_DATABASE_OIDS_FILE_NAME); } @@ -180759,7 +180763,7 @@ async function run(action) { let dependencyCacheResults; let databaseUploadResults = []; try { - initializeEnvironment(getActionVersion()); + action.env.initialise(getActionVersion()); persistInputs(); const statusReportBase = await createStatusReportBase( "finish" /* Analyze */, @@ -185938,8 +185942,8 @@ async function runWrapper2() { // src/autobuild-action.ts var core17 = __toESM(require_core()); -async function sendCompletedStatusReport(config, logger2, startedAt, allLanguages, failingLanguage, cause) { - initializeEnvironment(getActionVersion()); +async function sendCompletedStatusReport(env, config, logger2, startedAt, allLanguages, failingLanguage, cause) { + env.initialise(getActionVersion()); const status = getActionsStatus(cause, failingLanguage); const statusReportBase = await createStatusReportBase( "autobuild" /* Autobuild */, @@ -186011,6 +186015,7 @@ async function run2({ `We were unable to automatically build your code. Please replace the call to the autobuild action with your custom build steps. ${error3.message}` ); await sendCompletedStatusReport( + env, config, logger2, startedAt, @@ -186021,7 +186026,13 @@ async function run2({ return; } env.export("CODEQL_ACTION_AUTOBUILD_DID_COMPLETE_SUCCESSFULLY" /* AUTOBUILD_DID_COMPLETE_SUCCESSFULLY */, "true"); - await sendCompletedStatusReport(config, logger2, startedAt, languages ?? []); + await sendCompletedStatusReport( + env, + config, + logger2, + startedAt, + languages ?? [] + ); } var autobuild = { name: "autobuild" /* Autobuild */, @@ -186449,7 +186460,7 @@ async function run3(actionState) { let toolsSource; let toolsVersion; try { - initializeEnvironment(getActionVersion()); + actionState.env.initialise(getActionVersion()); persistInputs(); apiDetails = { auth: getRequiredInput("token"), @@ -187492,7 +187503,7 @@ async function run6(actionState) { let toolsSource; let toolsVersion; try { - initializeEnvironment(getActionVersion()); + actionState.env.initialise(getActionVersion()); const apiDetails = { auth: getRequiredInput("token"), externalRepoAuth: getOptionalInput("external-repository-token"), @@ -188444,9 +188455,10 @@ async function sendSuccessStatusReport2(startedAt, uploadStats, logger2) { await sendStatusReport(statusReport); } } -async function run8({ startedAt, logger: logger2 }) { +async function run8(action) { + const logger2 = action.logger; try { - initializeEnvironment(getActionVersion()); + action.env.initialise(getActionVersion()); const gitHubVersion = await getGitHubVersion(); checkActionVersion(getActionVersion(), gitHubVersion); persistInputs(); @@ -188460,7 +188472,7 @@ async function run8({ startedAt, logger: logger2 }) { const startingStatusReportBase = await createStatusReportBase( "upload-sarif" /* UploadSarif */, "starting", - startedAt, + action.startedAt, void 0, await checkDiskUsage(logger2), logger2 @@ -188503,7 +188515,7 @@ async function run8({ startedAt, logger: logger2 }) { } } await sendSuccessStatusReport2( - startedAt, + action.startedAt, codeScanningResult?.statusReport || {}, logger2 ); @@ -188514,7 +188526,7 @@ async function run8({ startedAt, logger: logger2 }) { const errorStatusReportBase = await createStatusReportBase( "upload-sarif" /* UploadSarif */, getActionsStatus(error3), - startedAt, + action.startedAt, void 0, await checkDiskUsage(logger2), logger2, diff --git a/src/actions-util.test.ts b/src/actions-util.test.ts index 17cf96a4a5..8ef947cdc2 100644 --- a/src/actions-util.test.ts +++ b/src/actions-util.test.ts @@ -12,8 +12,8 @@ import { import { computeAutomationID } from "./api-client"; import { EnvVar } from "./environment"; import { getRunnerLogger } from "./logging"; -import { RecordingLogger, setupTests } from "./testing-utils"; -import { initializeEnvironment, withTmpDir } from "./util"; +import { getTestEnv, RecordingLogger, setupTests } from "./testing-utils"; +import { withTmpDir } from "./util"; setupTests(test); @@ -228,8 +228,9 @@ test.serial( ); test.serial("initializeEnvironment", (t) => { - initializeEnvironment("1.2.3"); - t.deepEqual(process.env[EnvVar.VERSION], "1.2.3"); + const env = getTestEnv(); + env.initialise("1.2.3"); + t.deepEqual(env.getOptional(EnvVar.VERSION), "1.2.3"); }); test.serial("fixCodeQualityCategory", (t) => { diff --git a/src/analyze-action.ts b/src/analyze-action.ts index 9efbb529b0..f7cad45f39 100644 --- a/src/analyze-action.ts +++ b/src/analyze-action.ts @@ -238,7 +238,7 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { let databaseUploadResults: DatabaseUploadResult[] = []; try { - util.initializeEnvironment(actionsUtil.getActionVersion()); + action.env.initialise(actionsUtil.getActionVersion()); // Make inputs accessible in the `post` step, details at // https://github.com/github/codeql-action/issues/2553 diff --git a/src/api-client.test.ts b/src/api-client.test.ts index 2bb878f3b7..34ebd52e9d 100644 --- a/src/api-client.test.ts +++ b/src/api-client.test.ts @@ -7,7 +7,7 @@ import { ProxyAgent } from "undici"; import * as actionsUtil from "./actions-util"; import * as api from "./api-client"; import { DO_NOT_RETRY_STATUSES } from "./api-client"; -import { ActionsEnvVars, RegistryProxyVars } from "./environment"; +import { ActionsEnvVars, RegistryProxyVars, getEnv } from "./environment"; import { GITHUB_DOTCOM_API_URL, GITHUB_DOTCOM_URL } from "./github"; import { callee, @@ -21,7 +21,7 @@ import * as util from "./util"; setupTests(test); test.beforeEach(() => { - util.initializeEnvironment(actionsUtil.getActionVersion()); + getEnv().initialise(actionsUtil.getActionVersion()); }); test.serial("getApiClient", async (t) => { diff --git a/src/autobuild-action.ts b/src/autobuild-action.ts index 18aad11855..3e2eb1a3f2 100644 --- a/src/autobuild-action.ts +++ b/src/autobuild-action.ts @@ -10,7 +10,7 @@ import { getGitHubVersion } from "./api-client"; import { determineAutobuildLanguages, runAutobuild } from "./autobuild"; import { getCodeQL } from "./codeql"; import { Config, getConfig } from "./config-utils"; -import { EnvVar } from "./environment"; +import { EnvVar, type Env } from "./environment"; import { Language } from "./languages"; import { Logger } from "./logging"; import { @@ -26,7 +26,6 @@ import { checkDiskUsage, checkGitHubVersionInRange, ConfigurationError, - initializeEnvironment, wrapError, } from "./util"; @@ -38,6 +37,7 @@ interface AutobuildStatusReport extends StatusReportBase { } async function sendCompletedStatusReport( + env: Env, config: Config | undefined, logger: Logger, startedAt: Date, @@ -45,7 +45,7 @@ async function sendCompletedStatusReport( failingLanguage?: string, cause?: Error, ) { - initializeEnvironment(getActionVersion()); + env.initialise(getActionVersion()); const status = getActionsStatus(cause, failingLanguage); const statusReportBase = await createStatusReportBase( @@ -129,6 +129,7 @@ async function run({ `We were unable to automatically build your code. Please replace the call to the autobuild action with your custom build steps. ${error.message}`, ); await sendCompletedStatusReport( + env, config, logger, startedAt, @@ -141,7 +142,13 @@ async function run({ env.export(EnvVar.AUTOBUILD_DID_COMPLETE_SUCCESSFULLY, "true"); - await sendCompletedStatusReport(config, logger, startedAt, languages ?? []); + await sendCompletedStatusReport( + env, + config, + logger, + startedAt, + languages ?? [], + ); } /** Defines the `autobuild` Action. */ diff --git a/src/codeql.test.ts b/src/codeql.test.ts index e70dcd99f9..e07d1b811d 100644 --- a/src/codeql.test.ts +++ b/src/codeql.test.ts @@ -21,6 +21,7 @@ import { import type { Config } from "./config-utils"; import * as defaults from "./defaults.json"; import { DocUrl } from "./doc-url"; +import { getEnv } from "./environment"; import { BuiltInLanguage } from "./languages"; import { getRunnerLogger } from "./logging"; import { ToolsSource } from "./setup-codeql"; @@ -37,14 +38,13 @@ import { } from "./testing-utils"; import { ToolsDownloadStatusReport } from "./tools-download"; import * as util from "./util"; -import { initializeEnvironment } from "./util"; setupTests(test); let stubConfig: Config; test.beforeEach(() => { - initializeEnvironment("1.2.3"); + getEnv().initialise("1.2.3"); stubConfig = createTestConfig({ languages: [BuiltInLanguage.cpp], diff --git a/src/database-upload.test.ts b/src/database-upload.test.ts index 908994112e..7d7145dd36 100644 --- a/src/database-upload.test.ts +++ b/src/database-upload.test.ts @@ -15,6 +15,7 @@ import { cleanupAndUploadDatabases, uploadBundledDatabase, } from "./database-upload"; +import { getEnv } from "./environment"; import { Feature } from "./feature-flags"; import * as gitUtils from "./git-utils"; import { BuiltInLanguage } from "./languages"; @@ -31,18 +32,12 @@ import { setupActionsVars, setupTests, } from "./testing-utils"; -import { - CleanupLevel, - GitHubVariant, - HTTPError, - initializeEnvironment, - withTmpDir, -} from "./util"; +import { CleanupLevel, GitHubVariant, HTTPError, withTmpDir } from "./util"; setupTests(test); test.beforeEach(() => { - initializeEnvironment("1.2.3"); + getEnv().initialise("1.2.3"); }); const testRepoName: RepositoryNwo = { owner: "github", repo: "example" }; diff --git a/src/environment.ts b/src/environment.ts index 9867b27319..7acff8e99d 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -371,6 +371,18 @@ export class Env extends ReadOnlyEnv { } } + /** + * Set some initial environment variables that we can set even without + * knowing what version of CodeQL we're running. + */ + public initialise(version: string) { + this.export(EnvVar.FEATURE_MULTI_LANGUAGE, "false"); + this.export(EnvVar.FEATURE_SANDWICH, "false"); + this.export(EnvVar.FEATURE_SARIF_COMBINE, "true"); + this.export(EnvVar.FEATURE_WILL_UPLOAD, "true"); + this.export(EnvVar.VERSION, version); + } + /** Gets a value indicating whether `set` was called at least once. */ public hasChanged(): boolean { return this.changed; diff --git a/src/feature-flags.test.ts b/src/feature-flags.test.ts index d8b5eea04d..7b1c1ef3e5 100644 --- a/src/feature-flags.test.ts +++ b/src/feature-flags.test.ts @@ -4,6 +4,7 @@ import * as path from "path"; import test from "ava"; import * as defaults from "./defaults.json"; +import { getEnv } from "./environment"; import { Feature, featureConfig, @@ -26,12 +27,12 @@ import { setupTests, stubFeatureFlagApiEndpoint, } from "./testing-utils"; -import { GitHubVariant, initializeEnvironment, withTmpDir } from "./util"; +import { GitHubVariant, withTmpDir } from "./util"; setupTests(test); test.beforeEach(() => { - initializeEnvironment("1.2.3"); + getEnv().initialise("1.2.3"); }); test.serial( diff --git a/src/feature-flags/offline-features.test.ts b/src/feature-flags/offline-features.test.ts index 2870ef3b8a..1c3d2a8c1b 100644 --- a/src/feature-flags/offline-features.test.ts +++ b/src/feature-flags/offline-features.test.ts @@ -8,7 +8,7 @@ import { LoggedMessage, setupTests, } from "../testing-utils"; -import { GitHubVariant, initializeEnvironment, withTmpDir } from "../util"; +import { getEnv, GitHubVariant, withTmpDir } from "../util"; import { assertAllFeaturesHaveDefaultValues, @@ -18,7 +18,7 @@ import { setupTests(test); test.beforeEach(() => { - initializeEnvironment("1.2.3"); + getEnv().initialise("1.2.3"); }); test("OfflineFeatures makes no API requests", async (t) => { diff --git a/src/init-action.ts b/src/init-action.ts index 7f9178304c..b5749e9c8d 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -92,7 +92,6 @@ import { DEFAULT_DEBUG_DATABASE_NAME, getCodeQLMemoryLimit, getThreadsFlagValue, - initializeEnvironment, ConfigurationError, wrapError, checkActionVersion, @@ -225,7 +224,7 @@ async function run( let toolsVersion: string; try { - initializeEnvironment(getActionVersion()); + actionState.env.initialise(getActionVersion()); // Make inputs accessible in the `post` step. persistInputs(); diff --git a/src/setup-codeql-action.ts b/src/setup-codeql-action.ts index 757b26fac5..1bbfdacecc 100644 --- a/src/setup-codeql-action.ts +++ b/src/setup-codeql-action.ts @@ -38,7 +38,6 @@ import { checkDiskUsage, checkForTimeout, checkGitHubVersionInRange, - initializeEnvironment, ConfigurationError, wrapError, checkActionVersion, @@ -108,7 +107,7 @@ async function run( let toolsVersion: string; try { - initializeEnvironment(getActionVersion()); + actionState.env.initialise(getActionVersion()); const apiDetails = { auth: getRequiredInput("token"), diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 7dfac19148..319729acd7 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -11,7 +11,13 @@ import * as sinon from "sinon"; import * as actionsUtil from "./actions-util"; import * as api from "./api-client"; import * as diagnostics from "./diagnostics"; -import { ActionsEnvVars, Env, EnvVar, ReadOnlyEnv } from "./environment"; +import { + ActionsEnvVars, + Env, + EnvVar, + getEnv, + ReadOnlyEnv, +} from "./environment"; import { Feature } from "./feature-flags"; import { BuiltInLanguage } from "./languages"; import { getRunnerLogger } from "./logging"; @@ -37,18 +43,12 @@ import { setupTests, } from "./testing-utils"; import * as toolsDownload from "./tools-download"; -import { - getErrorMessage, - GitHubVariant, - HTTPError, - initializeEnvironment, - withTmpDir, -} from "./util"; +import { getErrorMessage, GitHubVariant, HTTPError, withTmpDir } from "./util"; setupTests(test); test.beforeEach(() => { - initializeEnvironment("1.2.3"); + getEnv().initialise("1.2.3"); }); function stubDownloadAndExtract() { diff --git a/src/setup/repository.test.ts b/src/setup/repository.test.ts index d1c6d034c0..9fabd84884 100644 --- a/src/setup/repository.test.ts +++ b/src/setup/repository.test.ts @@ -6,7 +6,6 @@ import * as sinon from "sinon"; import * as actionsUtil from "../actions-util"; import { ActionsEnvVars } from "../environment"; import { callee, getTestEnv, setupTests } from "../testing-utils"; -import { initializeEnvironment } from "../util"; import { getCodeQLActionRepository } from "./repository"; @@ -16,7 +15,7 @@ test.serial("getCodeQLActionRepository", async (t) => { const initialEnv = getTestEnv({ [ActionsEnvVars.RUNNER_TEMP]: path.dirname(__dirname), }); - initializeEnvironment("1.2.3", initialEnv); + initialEnv.initialise("1.2.3"); const target = callee(getCodeQLActionRepository) .withArgs() diff --git a/src/upload-lib.test.ts b/src/upload-lib.test.ts index 2c27d56c1c..393e3720d6 100644 --- a/src/upload-lib.test.ts +++ b/src/upload-lib.test.ts @@ -10,17 +10,18 @@ import * as analyses from "./analyses"; import { AnalysisKind, CodeQuality, CodeScanning } from "./analyses"; import * as api from "./api-client"; import * as diffUtils from "./diff-informed-analysis-utils"; +import { getEnv } from "./environment"; import { getRunnerLogger, Logger } from "./logging"; import * as sarif from "./sarif"; import { setupTests } from "./testing-utils"; import * as uploadLib from "./upload-lib"; import { UploadPayload } from "./upload-lib/types"; -import { GitHubVariant, initializeEnvironment, withTmpDir } from "./util"; +import { GitHubVariant, withTmpDir } from "./util"; setupTests(test); test.beforeEach(() => { - initializeEnvironment("1.2.3"); + getEnv().initialise("1.2.3"); }); test.serial("validateSarifFileSchema - valid", (t) => { diff --git a/src/upload-sarif-action.ts b/src/upload-sarif-action.ts index d3437510ce..7d67c55675 100644 --- a/src/upload-sarif-action.ts +++ b/src/upload-sarif-action.ts @@ -23,7 +23,6 @@ import { ConfigurationError, checkActionVersion, checkDiskUsage, - initializeEnvironment, shouldSkipSarifUpload, wrapError, } from "./util"; @@ -54,11 +53,13 @@ async function sendSuccessStatusReport( } } -async function run({ startedAt, logger }: ActionState<["Base", "Logger"]>) { +async function run(action: ActionState<["Base", "Env", "Logger"]>) { // To capture errors appropriately, keep as much code within the try-catch as // possible, and only use safe functions outside. + const logger = action.logger; + try { - initializeEnvironment(getActionVersion()); + action.env.initialise(getActionVersion()); const gitHubVersion = await getGitHubVersion(); checkActionVersion(getActionVersion(), gitHubVersion); @@ -77,7 +78,7 @@ async function run({ startedAt, logger }: ActionState<["Base", "Logger"]>) { const startingStatusReportBase = await createStatusReportBase( ActionName.UploadSarif, "starting", - startedAt, + action.startedAt, undefined, await checkDiskUsage(logger), logger, @@ -131,7 +132,7 @@ async function run({ startedAt, logger }: ActionState<["Base", "Logger"]>) { // so we can't wait for that here. } await sendSuccessStatusReport( - startedAt, + action.startedAt, codeScanningResult?.statusReport || {}, logger, ); @@ -147,7 +148,7 @@ async function run({ startedAt, logger }: ActionState<["Base", "Logger"]>) { const errorStatusReportBase = await createStatusReportBase( ActionName.UploadSarif, getActionsStatus(error), - startedAt, + action.startedAt, undefined, await checkDiskUsage(logger), logger, diff --git a/src/util.ts b/src/util.ts index 7ba59c6751..b9f51011eb 100644 --- a/src/util.ts +++ b/src/util.ts @@ -20,8 +20,6 @@ import { getRequiredEnvParam, isInTestMode, exportEnvVar, - getEnv, - type Env, } from "./environment"; import { ConfigurationError, getErrorMessage, wrapError } from "./errors"; import { GitHubVariant, type GitHubVersion } from "./github"; @@ -538,18 +536,6 @@ export function assertNever(value: never): never { throw new ExhaustivityCheckingError(value); } -/** - * Set some initial environment variables that we can set even without - * knowing what version of CodeQL we're running. - */ -export function initializeEnvironment(version: string, env: Env = getEnv()) { - env.export(EnvVar.FEATURE_MULTI_LANGUAGE, "false"); - env.export(EnvVar.FEATURE_SANDWICH, "false"); - env.export(EnvVar.FEATURE_SARIF_COMBINE, "true"); - env.export(EnvVar.FEATURE_WILL_UPLOAD, "true"); - env.export(EnvVar.VERSION, version); -} - export function getBaseDatabaseOidsFilePath( config: ActionConfig<"dbLocation">, ): string { From 44f1c73c5609b278c28193ea174602d95e2f1475 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 19 Oct 2026 17:35:16 +0100 Subject: [PATCH 046/174] Fix `resolveFunction` call --- src/codeql.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codeql.ts b/src/codeql.ts index 07153a7499..512d4eaf05 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -422,7 +422,7 @@ export function createStubCodeQL(partialCodeql: Partial): CodeQL { })), isVersionAtLeast: resolveFunction( partialCodeql, - "codeQlVersionAtLeast", + "isVersionAtLeast", async (requiredVersion) => { return ( !!partialCodeql.getVersion && From c29909a87f2dcda415ec11ffcb097377ed8f18dd Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 19 Oct 2026 17:40:29 +0100 Subject: [PATCH 047/174] Improve typing of `resolveFunction` --- src/codeql.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/codeql.ts b/src/codeql.ts index 512d4eaf05..ef6d4c6629 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -391,9 +391,9 @@ export function setCodeQL(codeql: Partial): void { cachedCodeQL = createStubCodeQL(codeql); } -function resolveFunction( +function resolveFunction( partialCodeql: Partial, - methodName: string, + methodName: K, defaultImplementation?: T, ): T { if (typeof partialCodeql[methodName] !== "function") { @@ -403,7 +403,7 @@ function resolveFunction( const dummyMethod = () => { throw new Error(`CodeQL ${methodName} method not correctly defined`); }; - return dummyMethod as T; + return dummyMethod as unknown as T; } return partialCodeql[methodName] as T; } From 0fcd0abe85818a2728c270830d8d51c86241810c Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Wed, 21 Oct 2026 11:10:30 -0500 Subject: [PATCH 048/174] Trigger workflows From d1db36d3020dba2af0937a898accb5b0c9d8bdbd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 17:54:13 +0000 Subject: [PATCH 049/174] Bump the npm-minor group across 1 directory with 3 updates Bumps the npm-minor group with 3 updates in the / directory: [uuid](https://github.com/uuidjs/uuid), [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint). Updates `uuid` from 14.0.2 to 14.0.3 - [Release notes](https://github.com/uuidjs/uuid/releases) - [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md) - [Commits](https://github.com/uuidjs/uuid/compare/v14.0.2...v14.0.3) Updates `eslint-plugin-jsdoc` from 65.2.0 to 65.3.4 - [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases) - [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v65.2.0...v65.3.4) Updates `typescript-eslint` from 8.71.1 to 8.71.2 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.71.2/packages/typescript-eslint) --- updated-dependencies: - dependency-name: uuid dependency-version: 14.0.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: npm-minor - dependency-name: eslint-plugin-jsdoc dependency-version: 65.3.4 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-minor - dependency-name: typescript-eslint dependency-version: 8.71.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 140 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 73 insertions(+), 73 deletions(-) diff --git a/package-lock.json b/package-lock.json index cfc9b231f4..8f37440fe2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,7 @@ "node-forge": "^1.4.0", "semver": "^7.8.5", "undici": "^6.28.0", - "uuid": "^14.0.2" + "uuid": "^14.0.3" }, "devDependencies": { "@ava/typescript": "6.0.0", @@ -57,14 +57,14 @@ "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-github": "^6.1.2", "eslint-plugin-import-x": "^4.17.1", - "eslint-plugin-jsdoc": "^65.2.0", + "eslint-plugin-jsdoc": "^65.3.4", "eslint-plugin-no-async-foreach": "^0.1.1", "glob": "^13.0.6", "globals": "^17.13.0", "nock": "^14.0.17", "sinon": "^22.1.0", "typescript": "^6.0.3", - "typescript-eslint": "^8.71.1" + "typescript-eslint": "^8.71.2" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -2702,17 +2702,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.1.tgz", - "integrity": "sha512-nNlBf6HuotqMgZvSkWD5hNdemiBIxQ2NmrlgfcUIeZRs+BbakjscCQRq/Hb74EFVnFiSWWdL12JruqwBy3ERDw==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.2.tgz", + "integrity": "sha512-K72/pvT7qpm8q3k8G5u93NCSN1RcLxX5h7Gw0bQpbMXviBHeY6Nx1WEwmk9wP+eKTSQ8ecxvcgt/ZX/rB938xQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.71.1", - "@typescript-eslint/type-utils": "8.71.1", - "@typescript-eslint/utils": "8.71.1", - "@typescript-eslint/visitor-keys": "8.71.1", + "@typescript-eslint/scope-manager": "8.71.2", + "@typescript-eslint/type-utils": "8.71.2", + "@typescript-eslint/utils": "8.71.2", + "@typescript-eslint/visitor-keys": "8.71.2", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -2725,7 +2725,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.71.1", + "@typescript-eslint/parser": "^8.71.2", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } @@ -2741,16 +2741,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.1.tgz", - "integrity": "sha512-oM/5sAqz/l1v/zYK1qTOPrn2+JIrBGC1V6uNYucRO5gh6eT9vWJ/RhPbGE59byvZEUQ4VP6XkLBaS5Jti5jpvw==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.2.tgz", + "integrity": "sha512-aTtmZjp/x3gsGHkDs04/1I8kNogBJkpQaeGaN0PfiG43NzDEmW2n+OP5im9wfsvyX0yP1UZWBrAGtDBfH9jEVw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.71.1", - "@typescript-eslint/types": "8.71.1", - "@typescript-eslint/typescript-estree": "8.71.1", - "@typescript-eslint/visitor-keys": "8.71.1", + "@typescript-eslint/scope-manager": "8.71.2", + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/typescript-estree": "8.71.2", + "@typescript-eslint/visitor-keys": "8.71.2", "debug": "^4.4.3" }, "engines": { @@ -2784,14 +2784,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.1.tgz", - "integrity": "sha512-Oijc9RUsohHjncg6iGi7gCtjnEjYt9FWv9u6ygK8uKcHK5eLjLAkqERQ9BaytbpceOFdk6kifPCS/zAZE+A99g==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.2.tgz", + "integrity": "sha512-Pd68GsLVh5ZXlcEccFPdhSOvtHZ/2WU0XsA8zmXOS3F158lVlcTLhfQ6qvtL1RzbMie0Kp8xtbVwAg4nejKPHw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.71.1", - "@typescript-eslint/types": "^8.71.1", + "@typescript-eslint/tsconfig-utils": "^8.71.2", + "@typescript-eslint/types": "^8.71.2", "debug": "^4.4.3" }, "engines": { @@ -2824,14 +2824,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.1.tgz", - "integrity": "sha512-1YUDZXdTnXLlob03SFHBipdyMBsDVm7zoSz0ytTJ39dk5J1TgsTK03VlR/dLXG/RLLUrPcYbD4rp23BmHxHP0w==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.2.tgz", + "integrity": "sha512-YF4wgg5iUX5Obywoac27B56FhozMNFhdJSbh11H5GBAwmBtfyRhmgTQqW9tRNNmHDvsZ2CX6UGzoz+YfYn2Leg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.1", - "@typescript-eslint/visitor-keys": "8.71.1" + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/visitor-keys": "8.71.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2842,9 +2842,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.1.tgz", - "integrity": "sha512-oTvkml5SxXhgg+WWKhod5qWQICDXtOB+/Hi9VdPKFAANJ2b7YOgMffgvzXuqog7R6A/JtrzRf128dsxummyWhg==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.2.tgz", + "integrity": "sha512-jz49TAWokm/7yWD9/o837nYax9DyALxIPOImdImvVzo6canBCZYzin8zJyqNR5k1j9K1DE0bVvr0XYB+99uAdg==", "dev": true, "license": "MIT", "engines": { @@ -2859,15 +2859,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.1.tgz", - "integrity": "sha512-kH3t3jZCYv2PZSBEWPKTariLrCaoF1CLoPitYFBJOhAGEwWnSRAtGEifrfrpBa4K9JlwWNZotgA5w3/wLSk/FQ==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.2.tgz", + "integrity": "sha512-cC8UaalCViJkb3rH/xLIvidEwoFRtMZMUqDjjJMGEKaTFwYRHYBcoczlEGHuvkHEO8svRDrgZ0yQgOArFmwang==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.1", - "@typescript-eslint/typescript-estree": "8.71.1", - "@typescript-eslint/utils": "8.71.1", + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/typescript-estree": "8.71.2", + "@typescript-eslint/utils": "8.71.2", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -2902,9 +2902,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.1.tgz", - "integrity": "sha512-ybYnPTUwg3VQQOFEiBPLs8Jxl1ry2vXdn1kVKguomBbvxpetdu3MKTNDqFNUrlG8ylP9MpZosmXMFYlGQHk1oQ==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.2.tgz", + "integrity": "sha512-y5Ukl3oVp7e/VGxqIoEXoeb/Roj71PAJ4WG/N/RGj+eeDvKRLM15kGr9MijLbN0i03S52zxu31Z98E5gWChJKw==", "dev": true, "license": "MIT", "engines": { @@ -2916,16 +2916,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.1.tgz", - "integrity": "sha512-pSKSEK1JJpHs6KiKVtABCE4iJK5d7FLFzDXQNBQ2oRY7LEd3UwOt3TZemTgu9syTIf56dJWlTn/pdmrO9oKUXQ==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.2.tgz", + "integrity": "sha512-DgNOEsl4pdYzwSL+N/Cl33tX1Hlw3FvId73LnKXfq7jnrF2viOEn7X+P7RBkkSWCVm92gnWd28GIC5vJuLREeA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.71.1", - "@typescript-eslint/tsconfig-utils": "8.71.1", - "@typescript-eslint/types": "8.71.1", - "@typescript-eslint/visitor-keys": "8.71.1", + "@typescript-eslint/project-service": "8.71.2", + "@typescript-eslint/tsconfig-utils": "8.71.2", + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/visitor-keys": "8.71.2", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -3001,16 +3001,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.1.tgz", - "integrity": "sha512-CBjT6gfAz3DW2j9Q4moFnqt208Aq+506sVGXfpRcyAeqn0EpayL0mjdWoCO2t3RC7GewNrFxdeehuEaPg6DMzQ==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.2.tgz", + "integrity": "sha512-RyKa1G1M9rKHDhrk+HJtiF1MvLD5Ux2JW3TSkzw+02pRALdpJb+QzG1Y5em+LvCgzGwgg8H7mBRFKljNz7ImPw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.71.1", - "@typescript-eslint/types": "8.71.1", - "@typescript-eslint/typescript-estree": "8.71.1" + "@typescript-eslint/scope-manager": "8.71.2", + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/typescript-estree": "8.71.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3025,13 +3025,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.1.tgz", - "integrity": "sha512-0GxiUGqMU0qXJt58cBsiG3DP8lUmBaFo2vChtUX+CT7PnR3v/VGLLrzVP4K9r1lNiZXjHYefMBbPunplr09v6w==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.2.tgz", + "integrity": "sha512-zozlN0UA32bSG2zkKAgQyRYSbEISVoyU6vvkKYo2aSny74D8Jh4e+POkJ6Lk0dlezZi5x7TtD+88Xb06IB8nhg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.1", + "@typescript-eslint/types": "8.71.2", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -5365,9 +5365,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "65.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-65.2.0.tgz", - "integrity": "sha512-IMZaNwdDa5otUQYGWN1pzywZLsGKswitvFFNhcO8IOsBfaWpWIDXYuZh2sYhe9MNyKN9hz0YryOFaKdpbTP5Bw==", + "version": "65.3.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-65.3.4.tgz", + "integrity": "sha512-Z3/ro8sZPqnXKhyAzCNa3F7KCZ3js5xVx/q9BEvTjUGzN6OIQfdb+q3Sc9lJ3zCfyPnN0tI524ulZjYRxAwnAw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -9981,16 +9981,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.71.1.tgz", - "integrity": "sha512-oiNVPC3/NbV1FpaHU07l8O6ynqG9v4PAiW2WvTrAmZdR0f2HI/gE668ElMLCK7Xbsu5k2fK5C4fXNiq05j7/nQ==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.71.2.tgz", + "integrity": "sha512-Rz4effbMy2g9wnvOJZG6SbVavX313Lap1vNEbk1RUochzickvzP8P4HB+bkNg5e50eVz1hQGjh9K1omI1xB4Bw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.71.1", - "@typescript-eslint/parser": "8.71.1", - "@typescript-eslint/typescript-estree": "8.71.1", - "@typescript-eslint/utils": "8.71.1" + "@typescript-eslint/eslint-plugin": "8.71.2", + "@typescript-eslint/parser": "8.71.2", + "@typescript-eslint/typescript-estree": "8.71.2", + "@typescript-eslint/utils": "8.71.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10167,9 +10167,9 @@ "license": "MIT" }, "node_modules/uuid": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.2.tgz", - "integrity": "sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.3.tgz", + "integrity": "sha512-Sc5u1VVln93y1Xnz4R+CunOZc7R9LUcTmhj7Rc7Eg3HVcf7rVn2FOoa812fe0W8p3jD7xeoGSYbfqCGGH2B6xw==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" diff --git a/package.json b/package.json index 9bfd792221..76ac14cf2d 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "node-forge": "^1.4.0", "semver": "^7.8.5", "undici": "^6.28.0", - "uuid": "^14.0.2" + "uuid": "^14.0.3" }, "devDependencies": { "@ava/typescript": "6.0.0", @@ -65,14 +65,14 @@ "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-github": "^6.1.2", "eslint-plugin-import-x": "^4.17.1", - "eslint-plugin-jsdoc": "^65.2.0", + "eslint-plugin-jsdoc": "^65.3.4", "eslint-plugin-no-async-foreach": "^0.1.1", "glob": "^13.0.6", "globals": "^17.13.0", "nock": "^14.0.17", "sinon": "^22.1.0", "typescript": "^6.0.3", - "typescript-eslint": "^8.71.1" + "typescript-eslint": "^8.71.2" }, "overrides": { "@actions/tool-cache": { From ec3f8658b6956d81e8d3947e0199d9b2a5ee5e44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 17:56:03 +0000 Subject: [PATCH 050/174] Bump the actions-minor group across 1 directory with 3 updates Bumps the actions-minor group with 3 updates in the /.github/workflows directory: [actions/setup-java](https://github.com/actions/setup-java), [ruby/setup-ruby](https://github.com/ruby/setup-ruby) and [actions/create-github-app-token](https://github.com/actions/create-github-app-token). Updates `actions/setup-java` from 6.0.1 to 6.1.0 - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/de7274f081f381c8f8158605e0321c36c376e2e6...b843ebf9b913146b38da2eaa7aeddf76074ae1ad) Updates `ruby/setup-ruby` from 1.327.0 to 1.329.0 - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb) - [Commits](https://github.com/ruby/setup-ruby/compare/14594264cd68ce8a2345dd349bc3d138a4ef85c8...651ff0d62c5c79bed6d53ec518387aae20e72c1a) Updates `actions/create-github-app-token` from 3.2.0 to 3.3.0 - [Release notes](https://github.com/actions/create-github-app-token/releases) - [Changelog](https://github.com/actions/create-github-app-token/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/create-github-app-token/compare/bcd2ba49218906704ab6c1aa796996da409d3eb1...64ab729a6294000f5aa4a4bc0b73d1f32bc45510) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-minor - dependency-name: ruby/setup-ruby dependency-version: 1.329.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-minor - dependency-name: actions/create-github-app-token dependency-version: 3.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-minor ... Signed-off-by: dependabot[bot] --- .../workflows/__autobuild-direct-tracing-with-working-dir.yml | 2 +- .github/workflows/__build-mode-autobuild.yml | 2 +- .github/workflows/__rubocop-multi-language.yml | 2 +- .github/workflows/post-release-mergeback.yml | 2 +- .github/workflows/rollback-release.yml | 2 +- .github/workflows/update-release-branch.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml b/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml index e0ff968bdc..bad4921eb8 100644 --- a/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml +++ b/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml @@ -63,7 +63,7 @@ jobs: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install Java - uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 + uses: actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0 with: java-version: ${{ inputs.java-version || '17' }} distribution: temurin diff --git a/.github/workflows/__build-mode-autobuild.yml b/.github/workflows/__build-mode-autobuild.yml index edc1d505db..76e3f348ad 100644 --- a/.github/workflows/__build-mode-autobuild.yml +++ b/.github/workflows/__build-mode-autobuild.yml @@ -63,7 +63,7 @@ jobs: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install Java - uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 + uses: actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0 with: java-version: ${{ inputs.java-version || '17' }} distribution: temurin diff --git a/.github/workflows/__rubocop-multi-language.yml b/.github/workflows/__rubocop-multi-language.yml index 7bda6ce9fd..c3348db6cf 100644 --- a/.github/workflows/__rubocop-multi-language.yml +++ b/.github/workflows/__rubocop-multi-language.yml @@ -54,7 +54,7 @@ jobs: use-all-platform-bundle: 'false' setup-kotlin: 'true' - name: Set up Ruby - uses: ruby/setup-ruby@14594264cd68ce8a2345dd349bc3d138a4ef85c8 # v1.327.0 + uses: ruby/setup-ruby@651ff0d62c5c79bed6d53ec518387aae20e72c1a # v1.329.0 with: ruby-version: 2.6 - name: Install Code Scanning integration diff --git a/.github/workflows/post-release-mergeback.yml b/.github/workflows/post-release-mergeback.yml index 354da0afde..76ef6e555f 100644 --- a/.github/workflows/post-release-mergeback.yml +++ b/.github/workflows/post-release-mergeback.yml @@ -134,7 +134,7 @@ jobs: echo "::endgroup::" - name: Generate token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0 id: app-token with: app-id: ${{ vars.AUTOMATION_APP_ID }} diff --git a/.github/workflows/rollback-release.yml b/.github/workflows/rollback-release.yml index 01651796ea..14a8490b8c 100644 --- a/.github/workflows/rollback-release.yml +++ b/.github/workflows/rollback-release.yml @@ -139,7 +139,7 @@ jobs: - name: Generate token if: github.event_name == 'workflow_dispatch' - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0 id: app-token with: app-id: ${{ vars.AUTOMATION_APP_ID }} diff --git a/.github/workflows/update-release-branch.yml b/.github/workflows/update-release-branch.yml index a506b87ce4..981a38eaca 100644 --- a/.github/workflows/update-release-branch.yml +++ b/.github/workflows/update-release-branch.yml @@ -95,7 +95,7 @@ jobs: pull-requests: write # needed to create pull request steps: - name: Generate token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0 id: app-token with: app-id: ${{ vars.AUTOMATION_APP_ID }} From fb5d8688b9288d836fcfe44a6ea1f42cb1a47bca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 17:58:09 +0000 Subject: [PATCH 051/174] Rebuild --- pr-checks/checks/rubocop-multi-language.yml | 2 +- pr-checks/sync.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pr-checks/checks/rubocop-multi-language.yml b/pr-checks/checks/rubocop-multi-language.yml index 633c2a3795..eec3aa8335 100644 --- a/pr-checks/checks/rubocop-multi-language.yml +++ b/pr-checks/checks/rubocop-multi-language.yml @@ -5,7 +5,7 @@ versions: - default steps: - name: Set up Ruby - uses: ruby/setup-ruby@14594264cd68ce8a2345dd349bc3d138a4ef85c8 # v1.327.0 + uses: ruby/setup-ruby@651ff0d62c5c79bed6d53ec518387aae20e72c1a # v1.329.0 with: ruby-version: 2.6 - name: Install Code Scanning integration diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index d6382786c3..08b514adfa 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -263,8 +263,8 @@ const languageSetups: LanguageSetups = { name: "Install Java", uses: pinnedUses( "actions/setup-java", - "de7274f081f381c8f8158605e0321c36c376e2e6", - "v6.0.1", + "b843ebf9b913146b38da2eaa7aeddf76074ae1ad", + "v6.1.0", ), with: { "java-version": `\${{ inputs.java-version || '${defaultLanguageVersions.java}' }}`, From 34f75b50e724c177539ba21befb43ab2a8b1c897 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 19:34:35 +0100 Subject: [PATCH 052/174] Rename argument --- pr-checks/toolcache.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pr-checks/toolcache.ts b/pr-checks/toolcache.ts index 459ecb068a..7339bf8989 100755 --- a/pr-checks/toolcache.ts +++ b/pr-checks/toolcache.ts @@ -60,8 +60,8 @@ function hasCodeQLInToolcache(expectedNumber?: string) { function main() { const { positionals, values } = parseArgs({ options: { - // The *number* of expected versions in the toolcache. - expectedVersions: { type: "string", short: "n" }, + // The number of expected versions in the toolcache. + "expected-version-count": { type: "string", short: "n" }, }, allowPositionals: true, }); @@ -80,7 +80,7 @@ function main() { noCodeQLInToolcache(); return; case "installed": - hasCodeQLInToolcache(values.expectedVersions); + hasCodeQLInToolcache(values["expected-version-count"]); return; default: throw new Error(`Unknown command '${cmd}'.`); From 6b344309f73a7460b93a7affee262a21e60a88f0 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 19:36:06 +0100 Subject: [PATCH 053/174] Log versions if there are some --- pr-checks/toolcache.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pr-checks/toolcache.ts b/pr-checks/toolcache.ts index 7339bf8989..6d734a2e7e 100755 --- a/pr-checks/toolcache.ts +++ b/pr-checks/toolcache.ts @@ -45,11 +45,11 @@ function hasCodeQLInToolcache(expectedNumber?: string) { : undefined; const allCodeqlVersions = findCodeQL(); - core.info(`Found CodeQL versions: ${allCodeqlVersions}`); - if (allCodeqlVersions.length === 0) { throw new Error("CodeQL not found in toolcache"); } + + core.info(`Found CodeQL versions: ${allCodeqlVersions.join(", ")}`); if (expected !== undefined && allCodeqlVersions.length !== expected) { throw new Error( `Expected ${expected} versions of CodeQL in the toolcache, but found ${allCodeqlVersions.length}`, From 0a00d0c14ffb44f643486c0dfcf11dfe5f09effd Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 19:36:54 +0100 Subject: [PATCH 054/174] Rename `noCodeQLInToolcache` --- pr-checks/toolcache.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pr-checks/toolcache.ts b/pr-checks/toolcache.ts index 6d734a2e7e..aa7d9afc19 100755 --- a/pr-checks/toolcache.ts +++ b/pr-checks/toolcache.ts @@ -28,7 +28,7 @@ function findCodeQL() { return toolcache.findAllVersions("CodeQL"); } -function noCodeQLInToolcache() { +function checkNoCodeQLInToolcache() { const allCodeqlVersions = findCodeQL(); if (allCodeqlVersions.length !== 0) { throw new Error( @@ -77,7 +77,7 @@ function main() { removeCodeQLFromToolcache(); return; case "absent": - noCodeQLInToolcache(); + checkNoCodeQLInToolcache(); return; case "installed": hasCodeQLInToolcache(values["expected-version-count"]); From c758339759af8b8eaa99b7db1d25882a5d1bef9f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 22 Oct 2026 10:17:07 +0100 Subject: [PATCH 055/174] Trigger workflows From 347d5ce5d59a46d1719e8b2f20356db6ed01c040 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 22 Oct 2026 10:17:39 +0100 Subject: [PATCH 056/174] Trigger workflows From 26f5c5e4e0aaac24bf3f31e064343e3229fbbec6 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 22 Oct 2026 10:30:34 +0100 Subject: [PATCH 057/174] Improve logging and error handling in `logTemporaryDiagnostics` --- lib/entry-points.js | 16 ++++++++++++---- src/diagnostics.ts | 17 +++++++++++++---- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 6128fe3b4c..5fde8a09ab 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -173085,13 +173085,21 @@ function writeDiagnostic(action, config, language, diagnostic) { } function logTemporaryDiagnostics(action) { const num = temporaryDiagnostics.length; - if (num > 0) { - action.logger.warning( - `${num} diagnostic(s) could not be written to the database and will not appear on the Tool Status Page.` + if (num > 0 && action.logger.isDebug()) { + action.logger.startGroup("Diagnostics in temporary location"); + action.logger.debug( + `${num} diagnostic(s) were not moved to the database and remain in the temporary directory.` ); for (const temporary of temporaryDiagnostics) { - action.logger.debug(fs7.readFileSync(temporary.path, "utf-8")); + try { + action.logger.debug(fs7.readFileSync(temporary.path, "utf-8")); + } catch (err) { + action.logger.debug( + `Failed to read diagnostics from temporary location at '${temporary.path}': ${getErrorMessage(err)}` + ); + } } + action.logger.endGroup(); } } function flushDiagnostics(action, config) { diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 272706c4e4..2c5fe909d8 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -303,14 +303,23 @@ function writeDiagnostic( export function logTemporaryDiagnostics(action: ActionState<["Logger"]>) { const num = temporaryDiagnostics.length; - if (num > 0) { - action.logger.warning( - `${num} diagnostic(s) could not be written to the database and will not appear on the Tool Status Page.`, + if (num > 0 && action.logger.isDebug()) { + action.logger.startGroup("Diagnostics in temporary location"); + action.logger.debug( + `${num} diagnostic(s) were not moved to the database and remain in the temporary directory.`, ); for (const temporary of temporaryDiagnostics) { - action.logger.debug(fs.readFileSync(temporary.path, "utf-8")); + try { + action.logger.debug(fs.readFileSync(temporary.path, "utf-8")); + } catch (err) { + action.logger.debug( + `Failed to read diagnostics from temporary location at '${temporary.path}': ${getErrorMessage(err)}`, + ); + } } + + action.logger.endGroup(); } } From 308d941317ce1303e8645e9ede2606deedcdc825 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 22 Oct 2026 10:37:37 +0100 Subject: [PATCH 058/174] Only warn for missing config if `init` was successful --- lib/entry-points.js | 19 ++++++++++++------- src/codeql.ts | 17 +++++++++++------ src/config-utils.ts | 2 ++ src/config/action-config.ts | 3 +++ src/init-action.ts | 1 + src/testing-utils.ts | 1 + 6 files changed, 30 insertions(+), 13 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 5fde8a09ab..de7255217d 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -174622,7 +174622,9 @@ async function initActionState({ useOverlayDatabaseCaching: false, overlayModeSetExplicitly: false, repositoryProperties, - enableFileCoverageInformation + enableFileCoverageInformation, + // We don't set this to `true` until `init` is successful. + successfullyInitialised: false }; } async function downloadCacheWithTime(codeQL, languages, logger2, repositoryRoot) { @@ -177448,12 +177450,14 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion) { async diagnosticsExport(sarifFile, automationDetailsId, config, diagnosticDir) { let configPath = getGeneratedCodeScanningConfigPath(config); if (!fs17.existsSync(configPath)) { - logger2.warning( - [ - `Expected a configuration file at '${configPath}', which does not exist.`, - "Continuing with diagnostics export anyway, without a configuration file." - ].join(" ") - ); + if (config.successfullyInitialised) { + logger2.warning( + [ + `Expected a configuration file at '${configPath}', which does not exist.`, + "Continuing with diagnostics export anyway, without a configuration file." + ].join(" ") + ); + } configPath = void 0; } const args = [ @@ -186923,6 +186927,7 @@ exec ${goBinaryPath} "$@"` ); } flushDiagnostics(actionState, config); + config.successfullyInitialised = true; await saveConfig(config, logger2); core19.setOutput("codeql-path", config.codeQLCmd); core19.setOutput("codeql-version", (await codeql.getVersion()).version); diff --git a/src/codeql.ts b/src/codeql.ts index b88144a253..9824b7e4fa 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -928,12 +928,17 @@ async function getCodeQLForCmd( getGeneratedCodeScanningConfigPath(config); if (!fs.existsSync(configPath)) { - logger.warning( - [ - `Expected a configuration file at '${configPath}', which does not exist.`, - "Continuing with diagnostics export anyway, without a configuration file.", - ].join(" "), - ); + // Warn if there is no configuration file, even though `config` claims that `init` + // was successful. This shouldn't be happening. + if (config.successfullyInitialised) { + logger.warning( + [ + `Expected a configuration file at '${configPath}', which does not exist.`, + "Continuing with diagnostics export anyway, without a configuration file.", + ].join(" "), + ); + } + configPath = undefined; } diff --git a/src/config-utils.ts b/src/config-utils.ts index 7bb7a37c02..12c1024f87 100644 --- a/src/config-utils.ts +++ b/src/config-utils.ts @@ -465,6 +465,8 @@ export async function initActionState( overlayModeSetExplicitly: false, repositoryProperties, enableFileCoverageInformation, + // We don't set this to `true` until `init` is successful. + successfullyInitialised: false, }; } diff --git a/src/config/action-config.ts b/src/config/action-config.ts index 4990ba6754..9daf966eec 100644 --- a/src/config/action-config.ts +++ b/src/config/action-config.ts @@ -130,6 +130,9 @@ export interface Config { * Whether to enable file coverage information. */ enableFileCoverageInformation: boolean; + + /** Whether the analysis was successfully initialised using the configuration. */ + successfullyInitialised: boolean; } /** Properties available in `Config`. */ diff --git a/src/init-action.ts b/src/init-action.ts index bd5ed3395a..ceffe9d6e3 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -775,6 +775,7 @@ async function run( // may have updated the config returned from `initConfig`, e.g. to revert to // `OverlayDatabaseMode.None` if we failed to download an overlay-base // database. + config.successfullyInitialised = true; await configUtils.saveConfig(config, logger); core.setOutput("codeql-path", config.codeQLCmd); diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 8c38187c4e..adcdfe3e4a 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -1031,6 +1031,7 @@ export function createTestConfig(overrides: Partial): Config { overlayModeSetExplicitly: false, repositoryProperties: {}, enableFileCoverageInformation: true, + successfullyInitialised: false, } satisfies Config, overrides, ); From 54af742a29bcb8826f1e5770122d631f23dbc169 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 22 Oct 2026 10:58:51 +0100 Subject: [PATCH 059/174] Simplify the condition for overlay-aware version selection Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 7 +++-- src/setup-codeql.test.ts | 57 +++++----------------------------------- src/setup-codeql.ts | 12 +++------ 3 files changed, 13 insertions(+), 63 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 4c3d9ac8aa..0c08cab1b9 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -176305,8 +176305,9 @@ async function getEnabledVersionsWithOverlayBaseDatabases(defaultCliVersion, raw (v) => cachedVersionsSet.has(v.cliVersion) ); } -async function resolveDefaultCliVersion(defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, variant, logger2) { - if (!useOverlayAwareDefaultCliVersion || variant !== "GitHub.com" /* DOTCOM */ && variant !== "GitHub Enterprise Cloud with data residency" /* GHEC_DR */ || defaultCliVersion.enabledVersions.length === 1 || !isAnalyzingPullRequest()) { +async function resolveDefaultCliVersion(defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, logger2) { + if (!useOverlayAwareDefaultCliVersion || // Listing the Actions cache can't change which version we use if only one version is enabled. + defaultCliVersion.enabledVersions.length === 1 || !isAnalyzingPullRequest()) { return defaultCliVersion.enabledVersions[0]; } const overlayVersions = await getEnabledVersionsWithOverlayBaseDatabases( @@ -176418,7 +176419,6 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, othe defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, - variant, logger2 ); cliVersion2 = version.cliVersion; @@ -176438,7 +176438,6 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, othe defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, - variant, logger2 ); cliVersion2 = version.cliVersion; diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 5ee914c1e3..5bbbf18718 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -1069,53 +1069,8 @@ async function fakeOverlayBaseCacheKey( return `${prefix}${suffix}`; } -for (const variant of [GitHubVariant.DOTCOM, GitHubVariant.GHEC_DR]) { - test.serial( - `getCodeQLSource uses overlay-aware default version for a Code Scanning PR on ${variant}`, - async (t) => { - await withTmpDir(async (tmpDir) => { - setupActionsVars(tmpDir, tmpDir); - process.env[EnvVar.CODE_SCANNING_REF] = "refs/heads/feature-branch"; - process.env[EnvVar.CODE_SCANNING_BASE_BRANCH] = "main"; - - sinon.stub(api, "getAutomationID").resolves("test/"); - const listStub = sinon.stub(api, "listActionsCaches").resolves([ - { - key: await fakeOverlayBaseCacheKey( - "javascript", - "2.20.1", - "abc-1-1", - ), - }, - ]); - sinon - .stub(toolcache, "find") - .withArgs("CodeQL", "2.20.1") - .returns("/path/to/codeql-2.20.1"); - - const source = await setupCodeql.getCodeQLSource( - undefined, - overlayMatchEnabledVersions, - ["javascript"], - undefined, // otherLanguagePacksReason - true, - SAMPLE_DOTCOM_API_DETAILS, - variant, - false, - createFeatures([]), - getRunnerLogger(true), - ); - - t.assert(listStub.calledOnce); - t.is(source.sourceType, "toolcache"); - t.is(source.toolsVersion, "2.20.1"); - }); - }, - ); -} - test.serial( - "getCodeQLSource skips overlay-aware default version for a Code Scanning PR on GHES", + "getCodeQLSource uses overlay-aware default version for a Code Scanning PR", async (t) => { await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); @@ -1130,8 +1085,8 @@ test.serial( ]); sinon .stub(toolcache, "find") - .withArgs("CodeQL", "2.20.2") - .returns("/path/to/codeql-2.20.2"); + .withArgs("CodeQL", "2.20.1") + .returns("/path/to/codeql-2.20.1"); const source = await setupCodeql.getCodeQLSource( undefined, @@ -1140,15 +1095,15 @@ test.serial( undefined, // otherLanguagePacksReason true, SAMPLE_DOTCOM_API_DETAILS, - GitHubVariant.GHES, + GitHubVariant.DOTCOM, false, createFeatures([]), getRunnerLogger(true), ); - t.assert(listStub.notCalled); + t.assert(listStub.calledOnce); t.is(source.sourceType, "toolcache"); - t.is(source.toolsVersion, "2.20.2"); + t.is(source.toolsVersion, "2.20.1"); }); }, ); diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index eb7c93be63..c895f57f77 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -220,21 +220,19 @@ export async function getEnabledVersionsWithOverlayBaseDatabases( /** * Resolves the newest enabled default CLI version that has a cached overlay-base database for the - * relevant languages, if running a Code Scanning analysis for a pull request with multiple enabled - * default versions in a supported environment and one exists. Otherwise, falls back to the newest - * enabled default CLI version. + * relevant languages, if this is a Code Scanning analysis of a pull request, multiple default + * versions are enabled, and such a version exists. Otherwise, falls back to the newest enabled + * default CLI version. */ async function resolveDefaultCliVersion( defaultCliVersion: CodeQLDefaultVersionInfo, rawLanguages: string[] | undefined, useOverlayAwareDefaultCliVersion: boolean, - variant: util.GitHubVariant, logger: Logger, ): Promise { if ( !useOverlayAwareDefaultCliVersion || - (variant !== util.GitHubVariant.DOTCOM && - variant !== util.GitHubVariant.GHEC_DR) || + // Listing the Actions cache can't change which version we use if only one version is enabled. defaultCliVersion.enabledVersions.length === 1 || !isAnalyzingPullRequest() ) { @@ -440,7 +438,6 @@ export async function getCodeQLSource( defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, - variant, logger, ); cliVersion = version.cliVersion; @@ -463,7 +460,6 @@ export async function getCodeQLSource( defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, - variant, logger, ); cliVersion = version.cliVersion; From b79966a8eed1b74372dee8aeba5d983c4e29f2d2 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 22 Oct 2026 11:32:04 +0100 Subject: [PATCH 060/174] Clean up path functions in `diagnostics.ts` and add some tests --- lib/entry-points.js | 34 ++++++++++----- src/diagnostics.test.ts | 54 +++++++++++++++++++++++ src/diagnostics.ts | 68 +++++++++++++++++++---------- src/init-action-post-helper.test.ts | 4 +- src/init-action-post-helper.ts | 4 +- 5 files changed, 126 insertions(+), 38 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index de7255217d..c04fd4a7e4 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -172991,6 +172991,11 @@ var semver4 = __toESM(require_semver2()); // src/diagnostics.ts var fs7 = __toESM(require("fs")); var import_path2 = __toESM(require("path")); +var TEMP_DIAGNOSTIC_DIR_NAME = "codeql-action-temp-diagnostics"; +var CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS = [ + "diagnostic", + "codeql-action" +]; var temporaryDiagnostics = []; var diagnosticCounter = 0; function makeDiagnostic(id, name, data = void 0) { @@ -173000,15 +173005,25 @@ function makeDiagnostic(id, name, data = void 0) { source: { ...data?.source, id, name } }; } -function getTempDiagnosticPath(tmpDir, language) { - const root = import_path2.default.join(tmpDir, "codeql-action-temp-diagnostics"); - return getDiagnosticsPath(root, language); +function getLanguageDiagnosticsPath(basePath, language) { + return import_path2.default.resolve( + basePath, + language, + ...CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS + ); +} +function getTempDiagnosticsRoot(tmpDir) { + return import_path2.default.resolve(tmpDir, TEMP_DIAGNOSTIC_DIR_NAME); } -function getDiagnosticsPath(basePath, language) { +function getTempLanguageDiagnosticsPath(tmpDir, language) { + const root = getTempDiagnosticsRoot(tmpDir); if (language !== void 0) { - return import_path2.default.resolve(basePath, language, "diagnostic", "codeql-action"); + return getLanguageDiagnosticsPath(root, language); } - return import_path2.default.resolve(basePath, "diagnostic", "codeql-action"); + return import_path2.default.resolve(root, ...CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS); +} +function getDatabaseDiagnosticsPath(config, language) { + return getLanguageDiagnosticsPath(config.dbLocation, language); } function addDiagnostic(config, language, diagnostic, logger2 = getActionsLogger()) { const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; @@ -173043,7 +173058,7 @@ function addNoLanguageDiagnostic(config, diagnostic, logger2 = getActionsLogger( } } function writeTemporaryDiagnosticFile(logger2, tempDir, language, diagnostic) { - const tempDiagnosticsPath = getTempDiagnosticPath(tempDir, language); + const tempDiagnosticsPath = getTempLanguageDiagnosticsPath(tempDir, language); try { const diagnosticPath = writeDiagnosticFile(tempDiagnosticsPath, diagnostic); temporaryDiagnostics.push({ path: diagnosticPath, language }); @@ -173069,9 +173084,6 @@ function writeDiagnosticFile(diagnosticsPath, diagnostic) { fs7.writeFileSync(jsonPath, JSON.stringify(diagnostic)); return jsonPath; } -function getDatabaseDiagnosticsPath(config, language) { - return getDiagnosticsPath(config.dbLocation, language); -} function writeDiagnostic(action, config, language, diagnostic) { const diagnosticsPath = getDatabaseDiagnosticsPath(config, language); try { @@ -187059,7 +187071,7 @@ async function generateFailedSarif(logger2, features, config, category, checkout codeql ); if (databasePath === void 0 || !exportDiagnosticsEnabled) { - let diagnosticDir = getTempDiagnosticPath( + let diagnosticDir = getTempDiagnosticsRoot( config.tempDir ); if (!exportDiagnosticsEnabled || !fs31.existsSync(diagnosticDir)) { diff --git a/src/diagnostics.test.ts b/src/diagnostics.test.ts index 2ba98da606..0d9af674d2 100644 --- a/src/diagnostics.test.ts +++ b/src/diagnostics.test.ts @@ -27,6 +27,60 @@ test("makeDiagnostic - adds expected properties", (t) => { t.is(diagnostic.source.name, name); }); +test("getLanguageDiagnosticsPath gets language-specific path", async (t) => + withTmpDir(async (tmpDir) => { + for (const language of Object.values(BuiltInLanguage)) { + t.is( + diagnostics.getLanguageDiagnosticsPath(tmpDir, language), + path.resolve( + tmpDir, + language, + ...diagnostics.CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS, + ), + ); + } + })); + +test("getTempLanguageDiagnosticsPath returns path without language", async (t) => + withTmpDir(async (tmpDir) => { + t.is( + diagnostics.getTempLanguageDiagnosticsPath(tmpDir), + path.resolve( + tmpDir, + diagnostics.TEMP_DIAGNOSTIC_DIR_NAME, + ...diagnostics.CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS, + ), + ); + })); + +test("getTempLanguageDiagnosticsPath returns language-specific path if a language is provided", async (t) => + withTmpDir(async (tmpDir) => { + t.is( + diagnostics.getTempLanguageDiagnosticsPath(tmpDir, BuiltInLanguage.swift), + path.resolve( + tmpDir, + diagnostics.TEMP_DIAGNOSTIC_DIR_NAME, + BuiltInLanguage.swift, + ...diagnostics.CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS, + ), + ); + })); + +test("getDatabaseDiagnosticsPath returns language-specific path if a language is provided", async (t) => + withTmpDir(async (tmpDir) => { + t.is( + diagnostics.getDatabaseDiagnosticsPath( + createTestConfig({ dbLocation: tmpDir }), + BuiltInLanguage.swift, + ), + path.resolve( + tmpDir, + BuiltInLanguage.swift, + ...diagnostics.CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS, + ), + ); + })); + /** * Diagnostic files that are written to disk don't have deterministic names. * This function recursively finds all `.json` files at {@link rootPath}, diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 2c5fe909d8..5e5bf21562 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -12,6 +12,14 @@ import { isErrnoException, } from "./util"; +/** The name of the directory we use to temporarily store diagnostics. */ +export const TEMP_DIAGNOSTIC_DIR_NAME = "codeql-action-temp-diagnostics"; + +export const CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS = [ + "diagnostic", + "codeql-action", +]; + /** * Known tags for diagnostics. There is currently only "internal-error", * but others may be added in the future. @@ -129,26 +137,48 @@ export function makeDiagnostic( } /** - * Gets a path relative to {@link tmpDir} where diagnostics for {@link language} - * can temporarily be stored at before the database is initialised. If {@link language} - * is `undefined`, then the common base path for all languages relative to {@link tmpDir} - * is returned. + * Gets a path relative to {@link basePath} where diagnostics for to {@link language} should be stored at. + */ +export function getLanguageDiagnosticsPath( + basePath: string, + language: Language, +) { + return path.resolve( + basePath, + language, + ...CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS, + ); +} + +/** + * Gets a path relative to {@link tmpDir} where diagnostics should temporarily be stored + * until they can be moved to the database. */ -export function getTempDiagnosticPath(tmpDir: string, language?: Language) { - const root = path.join(tmpDir, "codeql-action-temp-diagnostics"); - return getDiagnosticsPath(root, language); +export function getTempDiagnosticsRoot(tmpDir: string): string { + return path.resolve(tmpDir, TEMP_DIAGNOSTIC_DIR_NAME); } /** - * Gets a path relative to {@link basePath} where diagnostics for {@link language} - * should be stored at. If {@link language} is `undefined`, then {@link basePath} - * is returned instead. + * Gets a path relative to {@link tmpDir} where diagnostics for {@link language} + * can temporarily be stored at before the database is initialised. If {@link language} + * is `undefined`, then a non-language-specific path is returned. */ -export function getDiagnosticsPath(basePath: string, language?: Language) { +export function getTempLanguageDiagnosticsPath( + tmpDir: string, + language?: Language, +) { + const root = getTempDiagnosticsRoot(tmpDir); + if (language !== undefined) { - return path.resolve(basePath, language, "diagnostic", "codeql-action"); + return getLanguageDiagnosticsPath(root, language); } - return path.resolve(basePath, "diagnostic", "codeql-action"); + + return path.resolve(root, ...CODEQL_ACTION_DIAGNOSTIC_SUBDIR_PARTS); +} + +/** Gets the path where diagnostics for {@link language} should be stored in the database. */ +export function getDatabaseDiagnosticsPath(config: Config, language: Language) { + return getLanguageDiagnosticsPath(config.dbLocation, language); } /** @@ -222,7 +252,7 @@ function writeTemporaryDiagnosticFile( language: Language | undefined, diagnostic: DiagnosticMessage, ) { - const tempDiagnosticsPath = getTempDiagnosticPath(tempDir, language); + const tempDiagnosticsPath = getTempLanguageDiagnosticsPath(tempDir, language); try { // Write the diagnostic to a temporary location. @@ -266,14 +296,6 @@ function writeDiagnosticFile( return jsonPath; } -/** Gets the path where diagnostics for {@link language} should be stored in the database. */ -export function getDatabaseDiagnosticsPath( - config: Config, - language: Language | undefined, -) { - return getDiagnosticsPath(config.dbLocation, language); -} - /** * Writes the given diagnostic to the database. * @@ -284,7 +306,7 @@ export function getDatabaseDiagnosticsPath( function writeDiagnostic( action: ActionState<["Logger"]>, config: Config, - language: Language | undefined, + language: Language, diagnostic: DiagnosticMessage, ) { const diagnosticsPath = getDatabaseDiagnosticsPath(config, language); diff --git a/src/init-action-post-helper.test.ts b/src/init-action-post-helper.test.ts index 0458dbf52b..01dfbe0cea 100644 --- a/src/init-action-post-helper.test.ts +++ b/src/init-action-post-helper.test.ts @@ -11,7 +11,7 @@ import * as apiClient from "./api-client"; import * as codeql from "./codeql"; import * as configUtils from "./config-utils"; import * as debugArtifacts from "./debug-artifacts"; -import { getTempDiagnosticPath } from "./diagnostics"; +import { getTempDiagnosticsRoot } from "./diagnostics"; import { EnvVar } from "./environment"; import { Feature } from "./feature-flags"; import * as initActionPostHelper from "./init-action-post-helper"; @@ -43,7 +43,7 @@ test.serial("generateFailedSarif picks up unwritten diagnostics", async (t) => util.withTmpDir(async (tmpDir) => { const logger = new RecordingLogger(); - const tempDiagDir = getTempDiagnosticPath(tmpDir); + const tempDiagDir = getTempDiagnosticsRoot(tmpDir); fs.mkdirSync(tempDiagDir, { recursive: true }); const codeqlObject = await codeql.getCodeQLForTesting(); diff --git a/src/init-action-post-helper.ts b/src/init-action-post-helper.ts index b86ed9dbb7..060592cac2 100644 --- a/src/init-action-post-helper.ts +++ b/src/init-action-post-helper.ts @@ -24,7 +24,7 @@ import { type UploadDebugArtifactsConfig, } from "./debug-artifacts"; import * as dependencyCaching from "./dependency-caching"; -import { getTempDiagnosticPath } from "./diagnostics"; +import { getTempDiagnosticsRoot } from "./diagnostics"; import { EnvVar, ReadOnlyEnv } from "./environment"; import { Feature, FeatureEnablement } from "./feature-flags"; import { Logger } from "./logging"; @@ -215,7 +215,7 @@ export async function generateFailedSarif( // path that doesn't exist, so we are just being extra defensive here. // We also don't pass the path to the CLI if `exportDiagnosticsEnabled` is not enabled, to preserve // its intended behaviour of controlling whether diagnostics are included in the SARIF or not. - let diagnosticDir: string | undefined = getTempDiagnosticPath( + let diagnosticDir: string | undefined = getTempDiagnosticsRoot( config.tempDir, ); From 626d8b93644b56b6246ce3ef2b1de864b65389b2 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 22 Oct 2026 11:49:39 +0100 Subject: [PATCH 061/174] Use `toolcache.ts` in `per-language-bundle-validation.yml` Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../__per-language-bundle-validation.yml | 19 ++++++++++++------- .../checks/per-language-bundle-validation.yml | 11 ++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/.github/workflows/__per-language-bundle-validation.yml b/.github/workflows/__per-language-bundle-validation.yml index c320f2199b..ee779ab40b 100644 --- a/.github/workflows/__per-language-bundle-validation.yml +++ b/.github/workflows/__per-language-bundle-validation.yml @@ -81,6 +81,15 @@ jobs: steps: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Install Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: 20.x + cache: npm + - name: Install newer npm + run: npm install -g npm@11.19.1 + - name: Install dependencies + run: npm ci - name: Prepare test id: prepare-test uses: ./.github/actions/prepare-test @@ -89,13 +98,9 @@ jobs: use-all-platform-bundle: 'false' setup-kotlin: 'true' - name: Remove CodeQL from toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const fs = require('fs'); - const path = require('path'); - const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL'); - fs.rmdirSync(codeqlPath, { recursive: true }); + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts clear - uses: ./../action/init id: init with: diff --git a/pr-checks/checks/per-language-bundle-validation.yml b/pr-checks/checks/per-language-bundle-validation.yml index fc9805af90..ad18736739 100644 --- a/pr-checks/checks/per-language-bundle-validation.yml +++ b/pr-checks/checks/per-language-bundle-validation.yml @@ -40,15 +40,12 @@ matrix: os: macos-latest-xlarge version: linked build-mode: autobuild +installNode: true steps: - name: Remove CodeQL from toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const fs = require('fs'); - const path = require('path'); - const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL'); - fs.rmdirSync(codeqlPath, { recursive: true }); + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts clear - uses: ./../action/init id: init with: From 0171a2b52fed2a437381fe5f92b53dbf4eba6b83 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 22 Oct 2026 12:04:37 +0100 Subject: [PATCH 062/174] Take a single `ActionState` parameter in `getPerLanguageBundleLanguage` Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 8 +++++--- src/per-language-bundles.ts | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index e9741ef55e..adf101eaab 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -175621,7 +175621,7 @@ function getOtherLanguagePacksReason(inputs) { function findNonBuiltInQuery(queries) { return queries?.find((query) => !defaultSuites.has(query.uses))?.uses; } -function getPerLanguageBundleLanguage({ env, logger: logger2 }, options) { +function getPerLanguageBundleLanguage(action, options) { const { rawLanguages, otherLanguagePacksReason, @@ -175632,7 +175632,9 @@ function getPerLanguageBundleLanguage({ env, logger: logger2 }, options) { isLatestNightly } = options; const explain = (reason) => { - logger2.debug(`Not using a per-language CodeQL bundle since ${reason}.`); + action.logger.debug( + `Not using a per-language CodeQL bundle since ${reason}.` + ); return void 0; }; if (otherLanguagePacksReason !== void 0) { @@ -175653,7 +175655,7 @@ function getPerLanguageBundleLanguage({ env, logger: logger2 }, options) { if (variant !== "GitHub.com" /* DOTCOM */) { return explain(`we are running against ${variant}`); } - if (!isGitHubHostedRunner(env)) { + if (!isGitHubHostedRunner(action.env)) { return explain("the job is not running on a GitHub-hosted runner"); } if (!isLatestNightly) { diff --git a/src/per-language-bundles.ts b/src/per-language-bundles.ts index db70c808bc..14c8830203 100644 --- a/src/per-language-bundles.ts +++ b/src/per-language-bundles.ts @@ -139,7 +139,7 @@ export interface PerLanguageBundleOptions { /** Returns the eligible bundle language, or undefined for the combined bundle. */ export function getPerLanguageBundleLanguage( - { env, logger }: ActionState<["Logger", "ReadOnlyEnv"]>, + action: ActionState<["Logger", "ReadOnlyEnv"]>, options: PerLanguageBundleOptions, ): BuiltInLanguage | undefined { const { @@ -153,7 +153,9 @@ export function getPerLanguageBundleLanguage( } = options; const explain = (reason: string) => { - logger.debug(`Not using a per-language CodeQL bundle since ${reason}.`); + action.logger.debug( + `Not using a per-language CodeQL bundle since ${reason}.`, + ); return undefined; }; @@ -188,7 +190,7 @@ export function getPerLanguageBundleLanguage( return explain(`we are running against ${variant}`); } - if (!isGitHubHostedRunner(env)) { + if (!isGitHubHostedRunner(action.env)) { // Per-language installs stay out of the toolcache; self-hosted runners should retain // the reusable combined bundle instead. return explain("the job is not running on a GitHub-hosted runner"); From f033e23010ed0ec7f126990ec8c7182da9978c38 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 22 Oct 2026 12:04:37 +0100 Subject: [PATCH 063/174] Clarify why the file baseline check uses a custom configuration Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/__export-file-baseline-information.yml | 2 +- pr-checks/checks/export-file-baseline-information.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/__export-file-baseline-information.yml b/.github/workflows/__export-file-baseline-information.yml index 13d15fb6d4..a3b68dbb25 100644 --- a/.github/workflows/__export-file-baseline-information.yml +++ b/.github/workflows/__export-file-baseline-information.yml @@ -93,7 +93,7 @@ jobs: tools: ${{ steps.prepare-test.outputs.tools-url }} # To balance speed and coverage, analyze only JavaScript but use the combined bundle so # baseline information is reported for every language in the multi-language repository. A - # no-op custom configuration selects that conservative path for custom configurations. + # custom configuration prevents per-language bundles from being used. config: | paths-ignore: [] - name: Build code diff --git a/pr-checks/checks/export-file-baseline-information.yml b/pr-checks/checks/export-file-baseline-information.yml index dd8325717b..c83c3626e8 100644 --- a/pr-checks/checks/export-file-baseline-information.yml +++ b/pr-checks/checks/export-file-baseline-information.yml @@ -19,7 +19,7 @@ steps: tools: ${{ steps.prepare-test.outputs.tools-url }} # To balance speed and coverage, analyze only JavaScript but use the combined bundle so # baseline information is reported for every language in the multi-language repository. A - # no-op custom configuration selects that conservative path for custom configurations. + # custom configuration prevents per-language bundles from being used. config: | paths-ignore: [] - name: Build code From 87da5f37e5ca8a74af34c39cfd0558dd4fdc5eb9 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 22 Oct 2026 13:48:48 +0100 Subject: [PATCH 064/174] Improve wording to address review feedback --- src/codeql.ts | 4 ++-- src/diagnostics.test.ts | 2 +- src/diagnostics.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/codeql.ts b/src/codeql.ts index b4fa4c3952..28ba2243e9 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -909,8 +909,8 @@ export async function getCodeQLForCmd( // We may be exporting diagnostics for a failed SARIF, in which case the configuration // file may not have been written to disk and there may not be a database. The CLI // will produce a SARIF for diagnostics from `diagnosticDir` without it. Therefore, - // if `diagnosticDir` is set, we check whether `configPath` exists and only provide - // it to the CLI if it does. Although not needed, the CLI will produce an error if it + // we check whether `configPath` exists and only provide it to the CLI if it does. + // Although not needed, the CLI will produce an error if it // is provided with an argument to `--sarif-codescanning-config` that does not exist. let configPath: string | undefined = getGeneratedCodeScanningConfigPath(config); diff --git a/src/diagnostics.test.ts b/src/diagnostics.test.ts index 0d9af674d2..39ed95b209 100644 --- a/src/diagnostics.test.ts +++ b/src/diagnostics.test.ts @@ -66,7 +66,7 @@ test("getTempLanguageDiagnosticsPath returns language-specific path if a languag ); })); -test("getDatabaseDiagnosticsPath returns language-specific path if a language is provided", async (t) => +test("getDatabaseDiagnosticsPath returns language-specific path", async (t) => withTmpDir(async (tmpDir) => { t.is( diagnostics.getDatabaseDiagnosticsPath( diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 5e5bf21562..bec1d28abf 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -137,7 +137,7 @@ export function makeDiagnostic( } /** - * Gets a path relative to {@link basePath} where diagnostics for to {@link language} should be stored at. + * Gets a path relative to {@link basePath} where diagnostics for {@link language} should be stored at. */ export function getLanguageDiagnosticsPath( basePath: string, @@ -200,7 +200,7 @@ export function addDiagnostic( : config.dbLocation; // Check that the database exists before writing to it. If the database does not yet exist, - // store the diagnostic in memory and write it later. + // store the diagnostic in a temporary location and move it to the database later. if (fs.existsSync(databasePath)) { writeDiagnostic({ logger }, config, language, diagnostic); } else { From 7e3e4f23b1cdb077a39cbc110cd4330b60852e61 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 15:13:16 +0100 Subject: [PATCH 065/174] Make `getCodeQLForCmd` use `Env` --- lib/entry-points.js | 38 ++++++++++++++++++++++---------------- src/actions-util.ts | 2 +- src/cli/output-cache.ts | 4 ++-- src/codeql.ts | 41 ++++++++++++++++++++++++----------------- src/testing-utils.ts | 3 ++- 5 files changed, 51 insertions(+), 37 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index cb7ef17ffb..01be23317e 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -177025,13 +177025,13 @@ async function getCodeQL(logger2, cmd) { } return cachedCodeQL; } -async function getCodeQLForCmd(logger2, cmd, checkVersion) { +async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { const codeql = { getPath() { return cmd; }, async getVersion() { - const cacheFilePath = getCommandCacheFilePath(getEnv()); + const cacheFilePath = getCommandCacheFilePath(env); let result = getCachedCodeQlVersion( logger2, cacheFilePath, @@ -177141,14 +177141,17 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion) { } }, async runAutobuild(config, language) { - applyAutobuildAzurePipelinesTimeoutFix(); + applyAutobuildAzurePipelinesTimeoutFix(env); const autobuildCmd = path15.join( await this.resolveExtractor(language), "tools", process.platform === "win32" ? "autobuild.cmd" : "autobuild.sh" ); if (config.debugMode) { - process.env["CODEQL_VERBOSITY" /* CLI_VERBOSITY */] = process.env["CODEQL_VERBOSITY" /* CLI_VERBOSITY */] || EXTRACTION_DEBUG_MODE_VERBOSITY; + env.set( + "CODEQL_VERBOSITY" /* CLI_VERBOSITY */, + env.getOptional("CODEQL_VERBOSITY" /* CLI_VERBOSITY */) ?? EXTRACTION_DEBUG_MODE_VERBOSITY + ); } await runCli(autobuildCmd); }, @@ -177165,7 +177168,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion) { }, async extractUsingBuildMode(config, language) { if (config.buildMode === "autobuild" /* Autobuild */) { - applyAutobuildAzurePipelinesTimeoutFix(); + applyAutobuildAzurePipelinesTimeoutFix(env); } try { await runCli(cmd, [ @@ -177267,7 +177270,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion) { "--sarif-group-rules-by-pack", "--sarif-include-query-help=always", "--sublanguage-file-coverage", - ...await getJobRunUuidSarifOptions(), + ...await getJobRunUuidSarifOptions(env), ...getExtraOptionsFromEnv(["database", "interpret-results"]) ]; if (sarifRunPropertyFlag !== void 0) { @@ -177452,7 +177455,7 @@ Output was: ${extractorPath}` throw new ConfigurationError( `Expected a CodeQL CLI with version at least ${CODEQL_MINIMUM_VERSION} but got version ${(await codeql.getVersion()).version}` ); - } else if (checkVersion && process.env["CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */] !== "true" && !await codeQlVersionAtLeast(codeql, CODEQL_NEXT_MINIMUM_VERSION)) { + } else if (checkVersion && env.getOptional("CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */) !== "true" && !await codeQlVersionAtLeast(codeql, CODEQL_NEXT_MINIMUM_VERSION)) { const result = await codeql.getVersion(); core12.warning( `CodeQL CLI version ${result.version} was discontinued on ${GHES_MOST_RECENT_DEPRECATION_DATE} alongside GitHub Enterprise Server ${GHES_VERSION_MOST_RECENTLY_DEPRECATED} and will not be supported by the next minor release of the CodeQL Action. Please update to CodeQL CLI version ${CODEQL_NEXT_MINIMUM_VERSION} or later. For instance, if you have specified a custom version of the CLI using the 'tools' input to the 'init' Action, you can remove this input to use the default version. @@ -177559,16 +177562,19 @@ function getGeneratedCodeScanningConfigPath(config) { function getExtractionVerbosityArguments(enableDebugLogging) { return enableDebugLogging ? [`--verbosity=${EXTRACTION_DEBUG_MODE_VERBOSITY}`] : []; } -function applyAutobuildAzurePipelinesTimeoutFix() { - const javaToolOptions = process.env["JAVA_TOOL_OPTIONS"] || ""; - process.env["JAVA_TOOL_OPTIONS"] = [ - ...javaToolOptions.split(/\s+/), - "-Dhttp.keepAlive=false", - "-Dmaven.wagon.http.pool=false" - ].join(" "); +function applyAutobuildAzurePipelinesTimeoutFix(env) { + const javaToolOptions = env.getOptional("JAVA_TOOL_OPTIONS") ?? ""; + env.set( + "JAVA_TOOL_OPTIONS", + [ + ...javaToolOptions.split(/\s+/), + "-Dhttp.keepAlive=false", + "-Dmaven.wagon.http.pool=false" + ].join(" ") + ); } -async function getJobRunUuidSarifOptions() { - const jobRunUuid = process.env["CODEQL_ACTION_JOB_RUN_UUID" /* JOB_RUN_UUID */]; +async function getJobRunUuidSarifOptions(env) { + const jobRunUuid = env.getOptional("CODEQL_ACTION_JOB_RUN_UUID" /* JOB_RUN_UUID */); return jobRunUuid ? [`--sarif-run-property=jobRunUuid=${jobRunUuid}`] : []; } diff --git a/src/actions-util.ts b/src/actions-util.ts index 13e33a8e9d..997b8ee90a 100644 --- a/src/actions-util.ts +++ b/src/actions-util.ts @@ -72,7 +72,7 @@ export const getOptionalInput = function (name: string): string | undefined { * directory that has been set in `CODEQL_ACTION_TEMP` by e.g. a previous step, or the * value of `RUNNER_TEMP` otherwise. */ -export function getTemporaryDirectory(env: Env = getEnv()): string { +export function getTemporaryDirectory(env: ReadOnlyEnv = getEnv()): string { return ( env.getOptional(EnvVar.TEMP) ?? env.getRequired(ActionsEnvVars.RUNNER_TEMP) ); diff --git a/src/cli/output-cache.ts b/src/cli/output-cache.ts index fb5deb1ad6..209df575db 100644 --- a/src/cli/output-cache.ts +++ b/src/cli/output-cache.ts @@ -2,7 +2,7 @@ import * as fs from "fs"; import path from "path"; import { getTemporaryDirectory } from "../actions-util"; -import { Env } from "../environment"; +import { ReadOnlyEnv } from "../environment"; import * as json from "../json"; import { Logger } from "../logging"; @@ -51,7 +51,7 @@ export function resetCachedCodeQlVersion(): void { * Returns the path to the temporary file that backs the * on-disk cache of CLI responses between workflow steps. */ -export function getCommandCacheFilePath(env: Env): string { +export function getCommandCacheFilePath(env: ReadOnlyEnv): string { return path.join(getTemporaryDirectory(env), COMMAND_CACHE_FILENAME); } diff --git a/src/codeql.ts b/src/codeql.ts index 28ba2243e9..973ebafd28 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -18,7 +18,7 @@ import { CliError, wrapCliConfigurationError } from "./cli-errors"; import type { ActionConfig } from "./config/action-config"; import { appendExtraQueryExclusions, type Config } from "./config-utils"; import { DocUrl } from "./doc-url"; -import { EnvVar, getEnv, exportEnvVar } from "./environment"; +import { EnvVar, getEnv, exportEnvVar, Env, ReadOnlyEnv } from "./environment"; import { CodeQLDefaultVersionInfo, Feature, @@ -499,13 +499,14 @@ export async function getCodeQLForCmd( logger: Logger, cmd: string, checkVersion: boolean, + env: Env = getEnv(), ): Promise { const codeql: CodeQL = { getPath() { return cmd; }, async getVersion() { - const cacheFilePath = outputCache.getCommandCacheFilePath(getEnv()); + const cacheFilePath = outputCache.getCommandCacheFilePath(env); let result = outputCache.getCachedCodeQlVersion( logger, cacheFilePath, @@ -631,7 +632,7 @@ export async function getCodeQLForCmd( } }, async runAutobuild(config: Config, language: Language) { - applyAutobuildAzurePipelinesTimeoutFix(); + applyAutobuildAzurePipelinesTimeoutFix(env); const autobuildCmd = path.join( await this.resolveExtractor(language), @@ -641,8 +642,11 @@ export async function getCodeQLForCmd( // Bump the verbosity of the autobuild command if we're in debug mode if (config.debugMode) { - process.env[EnvVar.CLI_VERBOSITY] = - process.env[EnvVar.CLI_VERBOSITY] || EXTRACTION_DEBUG_MODE_VERBOSITY; + env.set( + EnvVar.CLI_VERBOSITY, + env.getOptional(EnvVar.CLI_VERBOSITY) ?? + EXTRACTION_DEBUG_MODE_VERBOSITY, + ); } // On macOS, System Integrity Protection (SIP) typically interferes with @@ -674,7 +678,7 @@ export async function getCodeQLForCmd( }, async extractUsingBuildMode(config: Config, language: Language) { if (config.buildMode === BuildMode.Autobuild) { - applyAutobuildAzurePipelinesTimeoutFix(); + applyAutobuildAzurePipelinesTimeoutFix(env); } try { await runCli(cmd, [ @@ -806,7 +810,7 @@ export async function getCodeQLForCmd( "--sarif-group-rules-by-pack", "--sarif-include-query-help=always", "--sublanguage-file-coverage", - ...(await getJobRunUuidSarifOptions()), + ...(await getJobRunUuidSarifOptions(env)), ...getExtraOptionsFromEnv(["database", "interpret-results"]), ]; if (sarifRunPropertyFlag !== undefined) { @@ -1054,7 +1058,7 @@ export async function getCodeQLForCmd( ); } else if ( checkVersion && - process.env[EnvVar.SUPPRESS_DEPRECATED_SOON_WARNING] !== "true" && + env.getOptional(EnvVar.SUPPRESS_DEPRECATED_SOON_WARNING) !== "true" && !(await util.codeQlVersionAtLeast(codeql, CODEQL_NEXT_MINIMUM_VERSION)) ) { const result = await codeql.getVersion(); @@ -1276,17 +1280,20 @@ function getExtractionVerbosityArguments( * Without the fix, long build processes will timeout when pulling down Java packages * https://developercommunity.visualstudio.com/content/problem/292284/maven-hosted-agent-connection-timeout.html */ -function applyAutobuildAzurePipelinesTimeoutFix() { - const javaToolOptions = process.env["JAVA_TOOL_OPTIONS"] || ""; - process.env["JAVA_TOOL_OPTIONS"] = [ - ...javaToolOptions.split(/\s+/), - "-Dhttp.keepAlive=false", - "-Dmaven.wagon.http.pool=false", - ].join(" "); +function applyAutobuildAzurePipelinesTimeoutFix(env: Env) { + const javaToolOptions = env.getOptional("JAVA_TOOL_OPTIONS") ?? ""; + env.set( + "JAVA_TOOL_OPTIONS", + [ + ...javaToolOptions.split(/\s+/), + "-Dhttp.keepAlive=false", + "-Dmaven.wagon.http.pool=false", + ].join(" "), + ); } -async function getJobRunUuidSarifOptions() { - const jobRunUuid = process.env[EnvVar.JOB_RUN_UUID]; +async function getJobRunUuidSarifOptions(env: ReadOnlyEnv) { + const jobRunUuid = env.getOptional(EnvVar.JOB_RUN_UUID); return jobRunUuid ? [`--sarif-run-property=jobRunUuid=${jobRunUuid}`] : []; } diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 04b1330dbf..92c77f2bc3 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -1052,6 +1052,7 @@ export function makeTestToken(length: number = 36) { export async function getCodeQLForTesting( cmd = "codeql-for-testing", logger: Logger = new RecordingLogger(), + env: Env = getEnv(), ): Promise { - return codeql.getCodeQLForCmd(logger, cmd, false); + return codeql.getCodeQLForCmd(logger, cmd, false, env); } From 1b037def00d15ce89b5265ca7c813f18238ed2d4 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 11:01:20 +0100 Subject: [PATCH 066/174] Refactor swift check out of `init-action.ts` --- lib/entry-points.js | 41 +++++++++++++----------- src/init-action.ts | 10 ++---- src/languages/swift.test.ts | 64 +++++++++++++++++++++++++++++++++++++ src/languages/swift.ts | 28 ++++++++++++++++ 4 files changed, 117 insertions(+), 26 deletions(-) create mode 100644 src/languages/swift.test.ts create mode 100644 src/languages/swift.ts diff --git a/lib/entry-points.js b/lib/entry-points.js index 01be23317e..55fe64d7f9 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -42967,11 +42967,11 @@ var require_tracingPolicy = __commonJS({ var import_log = require_log3(); var import_core_util = require_commonjs4(); var import_restError = require_restError3(); - var import_util59 = require_internal3(); + var import_util60 = require_internal3(); var tracingPolicyName2 = "tracingPolicy"; function tracingPolicy2(options = {}) { const userAgentPromise = (0, import_userAgent.getUserAgentValue)(options.userAgentPrefix); - const sanitizer = new import_util59.Sanitizer({ + const sanitizer = new import_util60.Sanitizer({ additionalAllowedQueryParameters: options.additionalAllowedQueryParameters }); const tracingClient = tryCreateTracingClient(); @@ -46597,11 +46597,11 @@ var require_response2 = __commonJS({ }); module2.exports = __toCommonJS2(response_exports); var import_core_rest_pipeline = require_commonjs6(); - var import_util59 = require_util9(); + var import_util60 = require_util9(); var originalResponse = /* @__PURE__ */ Symbol("Original FullOperationResponse"); function toCompatResponse2(response, options) { - let request3 = (0, import_util59.toWebResourceLike)(response.request); - let headers = (0, import_util59.toHttpHeadersLike)(response.headers); + let request3 = (0, import_util60.toWebResourceLike)(response.request); + let headers = (0, import_util60.toHttpHeadersLike)(response.headers); if (options?.createProxy) { return new Proxy(response, { get(target, prop, receiver) { @@ -46642,7 +46642,7 @@ var require_response2 = __commonJS({ return { ...compatResponse, headers, - request: (0, import_util59.toPipelineRequest)(compatResponse.request) + request: (0, import_util60.toPipelineRequest)(compatResponse.request) }; } } @@ -46749,7 +46749,7 @@ var require_requestPolicyFactoryPolicy = __commonJS({ requestPolicyFactoryPolicyName: () => requestPolicyFactoryPolicyName2 }); module2.exports = __toCommonJS2(requestPolicyFactoryPolicy_exports); - var import_util59 = require_util9(); + var import_util60 = require_util9(); var import_response = require_response2(); var HttpPipelineLogLevel2 = /* @__PURE__ */ ((HttpPipelineLogLevel22) => { HttpPipelineLogLevel22[HttpPipelineLogLevel22["ERROR"] = 1] = "ERROR"; @@ -46773,14 +46773,14 @@ var require_requestPolicyFactoryPolicy = __commonJS({ async sendRequest(request3, next) { let httpPipeline = { async sendRequest(httpRequest) { - const response2 = await next((0, import_util59.toPipelineRequest)(httpRequest)); + const response2 = await next((0, import_util60.toPipelineRequest)(httpRequest)); return (0, import_response.toCompatResponse)(response2, { createProxy: true }); } }; for (const factory of orderedFactories) { httpPipeline = factory.create(httpPipeline, mockRequestPolicyOptions); } - const webResourceLike = (0, import_util59.toWebResourceLike)(request3, { createProxy: true }); + const webResourceLike = (0, import_util60.toWebResourceLike)(request3, { createProxy: true }); const response = await httpPipeline.sendRequest(webResourceLike); return (0, import_response.toPipelineResponse)(response); } @@ -46815,12 +46815,12 @@ var require_httpClientAdapter = __commonJS({ }); module2.exports = __toCommonJS2(httpClientAdapter_exports); var import_response = require_response2(); - var import_util59 = require_util9(); + var import_util60 = require_util9(); function convertHttpClient2(requestPolicyClient) { return { sendRequest: async (request3) => { const response = await requestPolicyClient.sendRequest( - (0, import_util59.toWebResourceLike)(request3, { createProxy: true }) + (0, import_util60.toWebResourceLike)(request3, { createProxy: true }) ); return (0, import_response.toPipelineResponse)(response); } @@ -46858,7 +46858,7 @@ var require_commonjs9 = __commonJS({ disableKeepAlivePolicyName: () => import_disableKeepAlivePolicy.disableKeepAlivePolicyName, requestPolicyFactoryPolicyName: () => import_requestPolicyFactoryPolicy.requestPolicyFactoryPolicyName, toCompatResponse: () => import_response.toCompatResponse, - toHttpHeadersLike: () => import_util59.toHttpHeadersLike + toHttpHeadersLike: () => import_util60.toHttpHeadersLike }); module2.exports = __toCommonJS2(src_exports); var import_extendedClient = require_extendedClient(); @@ -46866,7 +46866,7 @@ var require_commonjs9 = __commonJS({ var import_requestPolicyFactoryPolicy = require_requestPolicyFactoryPolicy(); var import_disableKeepAlivePolicy = require_disableKeepAlivePolicy(); var import_httpClientAdapter = require_httpClientAdapter(); - var import_util59 = require_util9(); + var import_util60 = require_util9(); } }); @@ -186058,6 +186058,15 @@ async function getToolsInput(action, repositoryProperties) { return void 0; } +// src/languages/swift.ts +function isSwiftCompatible(action, config) { + if (config.languages.includes("swift" /* swift */) && action.platform !== "darwin") { + throw new ConfigurationError( + `Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.` + ); + } +} + // src/status-report/tools-download.ts function createInitToolsDownloadFields(report, toolsFeatureFlagsValid) { const fields = { ...report?.perLanguage }; @@ -186577,11 +186586,7 @@ async function run3(actionState) { enableFileCoverageInformation: fileCoverageResult.enabled, logger: logger2 }); - if (config.languages.includes("swift" /* swift */) && process.platform !== "darwin") { - throw new ConfigurationError( - `Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.` - ); - } + isSwiftCompatible(actionState, config); if (repositoryPropertiesResult.isFailure()) { addNoLanguageDiagnostic( config, diff --git a/src/init-action.ts b/src/init-action.ts index ceffe9d6e3..dd9b43960d 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -62,6 +62,7 @@ import { runDatabaseInitCluster, } from "./init"; import { JavaEnvVars, BuiltInLanguage } from "./languages"; +import { isSwiftCompatible } from "./languages/swift"; import { Logger, withGroupAsync } from "./logging"; import { downloadOverlayBaseDatabaseFromCache, @@ -418,14 +419,7 @@ async function run( logger, }); - if ( - config.languages.includes(BuiltInLanguage.swift) && - process.platform !== "darwin" - ) { - throw new ConfigurationError( - `Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.`, - ); - } + isSwiftCompatible(actionState, config); if (repositoryPropertiesResult.isFailure()) { addNoLanguageDiagnostic( diff --git a/src/languages/swift.test.ts b/src/languages/swift.test.ts new file mode 100644 index 0000000000..f3836785fb --- /dev/null +++ b/src/languages/swift.test.ts @@ -0,0 +1,64 @@ +import test from "ava"; +import sinon from "sinon"; + +import { ActionsEnvVars } from "../environment"; +import { + createTestConfig, + getCodeQLForTesting, + getTestEnv, + initAllState, + makeVersionInfo, + RecordingLogger, +} from "../testing-utils"; +import { withTmpDir } from "../util"; + +import { isSwiftCompatible } from "./swift"; + +import { BuiltInLanguage } from "."; + +test("isSwiftCompatible doesn't throw for non-Swift languages", (t) => { + for (const language of Object.values(BuiltInLanguage)) { + if (language === BuiltInLanguage.swift) { + continue; + } + + t.notThrows(() => + isSwiftCompatible( + initAllState(), + createTestConfig({ languages: [language] }), + ), + ); + } +}); + +test("isSwiftCompatible doesn't throw for Swift on darwin", async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLForTesting("codeql-for-testing", logger, env); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + t.notThrows(() => + isSwiftCompatible( + initAllState({ platform: "darwin", env, logger }), + createTestConfig({ + tempDir: tmpDir, + languages: [BuiltInLanguage.swift], + }), + ), + ); + })); + +const nonDarwinPlatforms: NodeJS.Platform[] = ["linux", "win32"]; +for (const nonDarwinPlatform of nonDarwinPlatforms) { + test(`isSwiftCompatible throws for Swift on ${nonDarwinPlatform}`, (t) => { + t.throws(() => { + isSwiftCompatible( + initAllState({ platform: nonDarwinPlatform }), + createTestConfig({ languages: [BuiltInLanguage.swift] }), + ); + }); + }); +} diff --git a/src/languages/swift.ts b/src/languages/swift.ts new file mode 100644 index 0000000000..501e7a0274 --- /dev/null +++ b/src/languages/swift.ts @@ -0,0 +1,28 @@ +import { ActionState } from "../action-common"; +import { Config } from "../config-utils"; +import { ConfigurationError } from "../util"; + +import { BuiltInLanguage } from "."; + +/** + * Determines whether we can run a Swift analysis on the current runner. + * + * @param action The Action state. + * @param config The Action configuration. + * + * @throws {ConfigurationError} If Swift analysis is not possible on the current runner. + * @returns True if we can run a Swift analysis. + */ +export function isSwiftCompatible( + action: ActionState<["Base"]>, + config: Config, +) { + if ( + config.languages.includes(BuiltInLanguage.swift) && + action.platform !== "darwin" + ) { + throw new ConfigurationError( + `Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.`, + ); + } +} From bc1b5da783e7b1037c722505d380d5124a3a3b85 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 22 Oct 2026 14:19:07 +0100 Subject: [PATCH 067/174] Use `ActionConfig` in `diagnostics.ts` --- src/diagnostics.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/diagnostics.ts b/src/diagnostics.ts index bec1d28abf..f2d3a152a8 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -3,7 +3,7 @@ import path from "path"; import type { ActionState } from "./action-common"; import { getTemporaryDirectory } from "./actions-util"; -import type { Config } from "./config-utils"; +import type { ActionConfig } from "./config/action-config"; import { Language } from "./languages"; import { getActionsLogger, type Logger } from "./logging"; import { @@ -177,7 +177,10 @@ export function getTempLanguageDiagnosticsPath( } /** Gets the path where diagnostics for {@link language} should be stored in the database. */ -export function getDatabaseDiagnosticsPath(config: Config, language: Language) { +export function getDatabaseDiagnosticsPath( + config: ActionConfig<"dbLocation">, + language: Language, +) { return getLanguageDiagnosticsPath(config.dbLocation, language); } @@ -190,7 +193,7 @@ export function getDatabaseDiagnosticsPath(config: Config, language: Language) { * @param diagnostic The diagnostic message to add to the database. */ export function addDiagnostic( - config: Config, + config: ActionConfig<"dbLocation" | "tempDir">, language: Language, diagnostic: DiagnosticMessage, logger: Logger = getActionsLogger(), @@ -215,7 +218,7 @@ export function addDiagnostic( /** Adds a diagnostic that is not specific to any language. */ export function addNoLanguageDiagnostic( - config: Config | undefined, + config: ActionConfig<"dbLocation" | "languages" | "tempDir"> | undefined, diagnostic: DiagnosticMessage, logger: Logger = getActionsLogger(), ) { @@ -305,7 +308,7 @@ function writeDiagnosticFile( */ function writeDiagnostic( action: ActionState<["Logger"]>, - config: Config, + config: ActionConfig<"dbLocation">, language: Language, diagnostic: DiagnosticMessage, ) { @@ -348,7 +351,7 @@ export function logTemporaryDiagnostics(action: ActionState<["Logger"]>) { /** Relocates all temporary diagnostics to the respective databases. */ export function flushDiagnostics( action: ActionState<["Logger"]>, - config: Config, + config: ActionConfig<"dbLocation" | "languages">, ) { const diagnosticsCount = temporaryDiagnostics.length; action.logger.debug( From 00d7ef8570b67f3bd835a6ef49bdd6c285244657 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 16:23:54 +0100 Subject: [PATCH 068/174] Refactor top-level code into `checkSarif` --- pr-checks/check-diagnostics.ts | 91 ++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/pr-checks/check-diagnostics.ts b/pr-checks/check-diagnostics.ts index 6e9d0ba82c..13bec9c3c5 100644 --- a/pr-checks/check-diagnostics.ts +++ b/pr-checks/check-diagnostics.ts @@ -34,59 +34,66 @@ function checkStatusPageNotification(n: sarif.Notification) { } } -const sarifPath = process.env["SARIF_PATH"]; +function checkSarif(sarifFile: string) { + core.info(`Checking SARIF file at '${sarifFile}'`); -if (sarifPath === undefined) { - throw new Error("The path to a SARIF file must be set in 'SARIF_PATH'."); -} + const log = JSON.parse(fs.readFileSync(sarifFile, "utf8")) as sarif.Log; + const run = log.runs[0]; -const log = JSON.parse(fs.readFileSync(sarifPath, "utf8")) as sarif.Log; -const run = log.runs[0]; + if (run.invocations === undefined) { + throw new Error("run.invocations is undefined"); + } -if (run.invocations === undefined) { - throw new Error("run.invocations is undefined"); -} + const toolExecutionNotifications = + run.invocations[0].toolExecutionNotifications; -const toolExecutionNotifications = - run.invocations[0].toolExecutionNotifications; + if (toolExecutionNotifications === undefined) { + throw new Error("toolExecutionNotifications is undefined"); + } -if (toolExecutionNotifications === undefined) { - throw new Error("toolExecutionNotifications is undefined"); -} + const statusPageNotifications = toolExecutionNotifications.filter( + (n) => + n.descriptor?.id === DIAGNOSTIC_ID && + n.properties?.visibility?.statusPage, + ); + if (statusPageNotifications.length !== 1) { + core.setFailed( + "Expected exactly one status page reporting descriptor for this diagnostic in the " + + `'runs[].invocations[].toolExecutionNotifications[]' SARIF property, but found ` + + `${statusPageNotifications.length}. All notification reporting descriptors: ` + + `${JSON.stringify(toolExecutionNotifications)}.`, + ); + } + checkStatusPageNotification(statusPageNotifications[0]); -const statusPageNotifications = toolExecutionNotifications.filter( - (n) => - n.descriptor?.id === DIAGNOSTIC_ID && n.properties?.visibility?.statusPage, -); -if (statusPageNotifications.length !== 1) { - core.setFailed( - "Expected exactly one status page reporting descriptor for this diagnostic in the " + - `'runs[].invocations[].toolExecutionNotifications[]' SARIF property, but found ` + - `${statusPageNotifications.length}. All notification reporting descriptors: ` + - `${JSON.stringify(toolExecutionNotifications)}.`, + const notifications = run.tool.driver.notifications; + + if (notifications === undefined) { + throw new Error("notifications is undefined"); + } + + const diagnosticNotification = notifications.filter( + (n) => + n.id === DIAGNOSTIC_ID && + n.name === DIAGNOSTIC_ID && + n.fullDescription?.text === DIAGNOSTIC_NAME, ); + if (diagnosticNotification.length !== 1) { + core.setFailed( + "Expected exactly one notification for this diagnostic in the " + + `'runs[].tool.driver.notifications[]' SARIF property, but found ` + + `${diagnosticNotification.length}. All notifications: ` + + `${JSON.stringify(notifications)}.`, + ); + } } -checkStatusPageNotification(statusPageNotifications[0]); -const notifications = run.tool.driver.notifications; +const sarifPath = process.env["SARIF_PATH"]; -if (notifications === undefined) { - throw new Error("notifications is undefined"); +if (sarifPath === undefined) { + throw new Error("The path to a SARIF file must be set in 'SARIF_PATH'."); } -const diagnosticNotification = notifications.filter( - (n) => - n.id === DIAGNOSTIC_ID && - n.name === DIAGNOSTIC_ID && - n.fullDescription?.text === DIAGNOSTIC_NAME, -); -if (diagnosticNotification.length !== 1) { - core.setFailed( - "Expected exactly one notification for this diagnostic in the " + - `'runs[].tool.driver.notifications[]' SARIF property, but found ` + - `${diagnosticNotification.length}. All notifications: ` + - `${JSON.stringify(notifications)}.`, - ); -} +checkSarif(sarifPath); core.info("Finished diagnostic export test"); From 5a546846a418cbd4a2994a4d5ac937f6b3b98299 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 16:29:38 +0100 Subject: [PATCH 069/174] Allow `check-diagnostics.ts` to check multiple SARIF files --- package-lock.json | 1 + pr-checks/check-diagnostics.ts | 20 ++++++++++++++++++-- pr-checks/package.json | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index c06678b604..ec0adc691a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10488,6 +10488,7 @@ "@octokit/core": "^7.0.8", "@octokit/plugin-paginate-rest": ">=16.0.0", "@octokit/plugin-rest-endpoint-methods": "^18.0.0", + "glob": "^13.0.6", "lite-matter": "^0.1.2", "mdast-util-from-markdown": "^2.1.0", "semver": "^7.8.5", diff --git a/pr-checks/check-diagnostics.ts b/pr-checks/check-diagnostics.ts index 13bec9c3c5..b77e6d34ae 100644 --- a/pr-checks/check-diagnostics.ts +++ b/pr-checks/check-diagnostics.ts @@ -1,6 +1,8 @@ import fs from "fs"; +import path from "path"; import * as core from "@actions/core"; +import { globSync } from "glob"; import * as sarif from "../src/sarif"; @@ -91,9 +93,23 @@ function checkSarif(sarifFile: string) { const sarifPath = process.env["SARIF_PATH"]; if (sarifPath === undefined) { - throw new Error("The path to a SARIF file must be set in 'SARIF_PATH'."); + throw new Error( + "The path to a SARIF file or directory must be set in 'SARIF_PATH'.", + ); } -checkSarif(sarifPath); +if (fs.statSync(sarifPath).isDirectory()) { + const sarifFiles = globSync(path.join(sarifPath, "**", "*.sarif")); + + if (sarifFiles.length < 1) { + throw new Error(`Unable to find any .sarif files in '${sarifPath}'.`); + } + + for (const sarifFile of sarifFiles) { + checkSarif(sarifFile); + } +} else { + checkSarif(sarifPath); +} core.info("Finished diagnostic export test"); diff --git a/pr-checks/package.json b/pr-checks/package.json index 343f943814..a29428b9fd 100644 --- a/pr-checks/package.json +++ b/pr-checks/package.json @@ -9,6 +9,7 @@ "@octokit/core": "^7.0.8", "@octokit/plugin-paginate-rest": ">=16.0.0", "@octokit/plugin-rest-endpoint-methods": "^18.0.0", + "glob": "^13.0.6", "lite-matter": "^0.1.2", "mdast-util-from-markdown": "^2.1.0", "semver": "^7.8.5", From 7a0df8fe5b870a1fe472499bb430e5bd7d0a5428 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 22 Oct 2026 14:57:07 +0100 Subject: [PATCH 070/174] Improve `globSync` call --- pr-checks/check-diagnostics.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pr-checks/check-diagnostics.ts b/pr-checks/check-diagnostics.ts index b77e6d34ae..cc619aa9c3 100644 --- a/pr-checks/check-diagnostics.ts +++ b/pr-checks/check-diagnostics.ts @@ -99,7 +99,10 @@ if (sarifPath === undefined) { } if (fs.statSync(sarifPath).isDirectory()) { - const sarifFiles = globSync(path.join(sarifPath, "**", "*.sarif")); + const sarifFiles = globSync("**/*.sarif", { + cwd: path.resolve(sarifPath), + absolute: true, + }); if (sarifFiles.length < 1) { throw new Error(`Unable to find any .sarif files in '${sarifPath}'.`); From c1ab1b406525a15dc4f2910773b6e1e8409cc610 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 22 Oct 2026 15:13:50 +0100 Subject: [PATCH 071/174] Don't require github-advanced-security or License compliance check Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- pr-checks/excluded.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pr-checks/excluded.yml b/pr-checks/excluded.yml index 5563a3e179..bac0b4acee 100644 --- a/pr-checks/excluded.yml +++ b/pr-checks/excluded.yml @@ -20,3 +20,7 @@ is: - "Release info" - "Upload results" - "Update release branch" + # These checks are known not to run on every PR (for example, some release + # PRs), so requiring them would block the PRs they don't run on. + - "github-advanced-security" + - "License compliance check" From 040890448b2ead3ae67c1f514514955da784ec52 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 22 Oct 2026 14:47:35 +0100 Subject: [PATCH 072/174] Add workflow to comment on a PR when it was dequeued --- .github/workflows/pr-dequeued.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/pr-dequeued.yml diff --git a/.github/workflows/pr-dequeued.yml b/.github/workflows/pr-dequeued.yml new file mode 100644 index 0000000000..7d39ef97ec --- /dev/null +++ b/.github/workflows/pr-dequeued.yml @@ -0,0 +1,28 @@ +name: PR dequeued + +on: + pull_request: + types: + - dequeued + +jobs: + notify: + name: Notify + runs-on: ubuntu-slim + + if: github.event.pull_request.merged != true + + permissions: + pull-requests: write + + steps: + - name: Notify that the PR was removed from the merge queue + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number }} + REASON: ${{ github.event.reason }} + SENDER: ${{ github.event.sender.login }} + run: | + echo "@$SENDER The pull request was removed from the merge queue (\`$REASON\`)." \ + "Please resolve any issues if required and enqueue the PR again." | + gh pr comment --body-file - --repo github/codeql-action "$PR_NUMBER" From fbf3125415ab42c51ebbca7b616ba7fcd9181df5 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 23 Oct 2026 12:07:19 +0100 Subject: [PATCH 073/174] Rename `isSwiftCompatible` --- lib/entry-points.js | 4 ++-- src/init-action.ts | 4 ++-- src/languages/swift.test.ts | 14 +++++++------- src/languages/swift.ts | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 1051c51f6b..86c7c220da 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -186046,7 +186046,7 @@ async function getToolsInput(action, repositoryProperties) { } // src/languages/swift.ts -function isSwiftCompatible(action, config) { +function checkSwiftCompatibility(action, config) { if (config.languages.includes("swift" /* swift */) && action.platform !== "darwin") { throw new ConfigurationError( `Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.` @@ -186573,7 +186573,7 @@ async function run3(actionState) { enableFileCoverageInformation: fileCoverageResult.enabled, logger: logger2 }); - isSwiftCompatible(actionState, config); + checkSwiftCompatibility(actionState, config); if (repositoryPropertiesResult.isFailure()) { addNoLanguageDiagnostic( config, diff --git a/src/init-action.ts b/src/init-action.ts index dd9b43960d..5146d7530c 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -62,7 +62,7 @@ import { runDatabaseInitCluster, } from "./init"; import { JavaEnvVars, BuiltInLanguage } from "./languages"; -import { isSwiftCompatible } from "./languages/swift"; +import { checkSwiftCompatibility } from "./languages/swift"; import { Logger, withGroupAsync } from "./logging"; import { downloadOverlayBaseDatabaseFromCache, @@ -419,7 +419,7 @@ async function run( logger, }); - isSwiftCompatible(actionState, config); + checkSwiftCompatibility(actionState, config); if (repositoryPropertiesResult.isFailure()) { addNoLanguageDiagnostic( diff --git a/src/languages/swift.test.ts b/src/languages/swift.test.ts index f3836785fb..e2655ff672 100644 --- a/src/languages/swift.test.ts +++ b/src/languages/swift.test.ts @@ -12,18 +12,18 @@ import { } from "../testing-utils"; import { withTmpDir } from "../util"; -import { isSwiftCompatible } from "./swift"; +import { checkSwiftCompatibility } from "./swift"; import { BuiltInLanguage } from "."; -test("isSwiftCompatible doesn't throw for non-Swift languages", (t) => { +test("checkSwiftCompatibility doesn't throw for non-Swift languages", (t) => { for (const language of Object.values(BuiltInLanguage)) { if (language === BuiltInLanguage.swift) { continue; } t.notThrows(() => - isSwiftCompatible( + checkSwiftCompatibility( initAllState(), createTestConfig({ languages: [language] }), ), @@ -31,7 +31,7 @@ test("isSwiftCompatible doesn't throw for non-Swift languages", (t) => { } }); -test("isSwiftCompatible doesn't throw for Swift on darwin", async (t) => +test("checkSwiftCompatibility doesn't throw for Swift on darwin", async (t) => withTmpDir(async (tmpDir) => { const logger = new RecordingLogger(); const env = getTestEnv(); @@ -41,7 +41,7 @@ test("isSwiftCompatible doesn't throw for Swift on darwin", async (t) => sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); t.notThrows(() => - isSwiftCompatible( + checkSwiftCompatibility( initAllState({ platform: "darwin", env, logger }), createTestConfig({ tempDir: tmpDir, @@ -53,9 +53,9 @@ test("isSwiftCompatible doesn't throw for Swift on darwin", async (t) => const nonDarwinPlatforms: NodeJS.Platform[] = ["linux", "win32"]; for (const nonDarwinPlatform of nonDarwinPlatforms) { - test(`isSwiftCompatible throws for Swift on ${nonDarwinPlatform}`, (t) => { + test(`checkSwiftCompatibility throws for Swift on ${nonDarwinPlatform}`, (t) => { t.throws(() => { - isSwiftCompatible( + checkSwiftCompatibility( initAllState({ platform: nonDarwinPlatform }), createTestConfig({ languages: [BuiltInLanguage.swift] }), ); diff --git a/src/languages/swift.ts b/src/languages/swift.ts index 501e7a0274..3a51491fbf 100644 --- a/src/languages/swift.ts +++ b/src/languages/swift.ts @@ -13,7 +13,7 @@ import { BuiltInLanguage } from "."; * @throws {ConfigurationError} If Swift analysis is not possible on the current runner. * @returns True if we can run a Swift analysis. */ -export function isSwiftCompatible( +export function checkSwiftCompatibility( action: ActionState<["Base"]>, config: Config, ) { From 2d3b6d4530fabb641b307704f8761d043ef08645 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 23 Oct 2026 12:11:00 +0100 Subject: [PATCH 074/174] Check that a `ConfigurationError` is thrown --- src/languages/swift.test.ts | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/languages/swift.test.ts b/src/languages/swift.test.ts index e2655ff672..2f3182fea2 100644 --- a/src/languages/swift.test.ts +++ b/src/languages/swift.test.ts @@ -10,7 +10,7 @@ import { makeVersionInfo, RecordingLogger, } from "../testing-utils"; -import { withTmpDir } from "../util"; +import { ConfigurationError, withTmpDir } from "../util"; import { checkSwiftCompatibility } from "./swift"; @@ -54,11 +54,17 @@ test("checkSwiftCompatibility doesn't throw for Swift on darwin", async (t) => const nonDarwinPlatforms: NodeJS.Platform[] = ["linux", "win32"]; for (const nonDarwinPlatform of nonDarwinPlatforms) { test(`checkSwiftCompatibility throws for Swift on ${nonDarwinPlatform}`, (t) => { - t.throws(() => { - checkSwiftCompatibility( - initAllState({ platform: nonDarwinPlatform }), - createTestConfig({ languages: [BuiltInLanguage.swift] }), - ); - }); + t.throws( + () => { + checkSwiftCompatibility( + initAllState({ platform: nonDarwinPlatform }), + createTestConfig({ languages: [BuiltInLanguage.swift] }), + ); + }, + { + instanceOf: ConfigurationError, + message: /^Swift analysis is only supported on macOS runner images/, + }, + ); }); } From 37a5faff2595fa45bfd7c8fccbe67d7ca717f315 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 23 Oct 2026 12:19:29 +0100 Subject: [PATCH 075/174] Switch to `pull_request.user.login` --- .github/workflows/pr-dequeued.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-dequeued.yml b/.github/workflows/pr-dequeued.yml index 7d39ef97ec..0c47c9dc74 100644 --- a/.github/workflows/pr-dequeued.yml +++ b/.github/workflows/pr-dequeued.yml @@ -21,8 +21,8 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} REASON: ${{ github.event.reason }} - SENDER: ${{ github.event.sender.login }} + USER: ${{ github.event.pull_request.user.login }} run: | - echo "@$SENDER The pull request was removed from the merge queue (\`$REASON\`)." \ + echo "@$USER The pull request was removed from the merge queue (\`$REASON\`)." \ "Please resolve any issues if required and enqueue the PR again." | gh pr comment --body-file - --repo github/codeql-action "$PR_NUMBER" From d7e4421be7388ffe1fec0d0fd351606d6d5445ad Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 22:04:24 +0100 Subject: [PATCH 076/174] Remove unused type parameters from `Env` classes --- src/environment.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/environment.ts b/src/environment.ts index ffc3f305ad..994e7a55c5 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -293,8 +293,8 @@ export function getOptionalEnvVar(paramName: string): string | undefined { * in tests, while clearly signalling in regular code that the consumer of the `ReadOnlyEnv` instance * will only read from it. */ -export class ReadOnlyEnv { - constructor(protected readonly vars: Record) {} +export class ReadOnlyEnv { + constructor(protected readonly vars: Record) {} /** Clones the object while detaching the underlying environment from the original. */ public clone(): this { @@ -302,7 +302,7 @@ export class ReadOnlyEnv { } /** Gets a copy of the underlying environment. */ - public get(): Record { + public get(): Record { return { ...this.vars }; } @@ -317,7 +317,7 @@ export class ReadOnlyEnv { } /** Gets the entries of the underlying `ProcessEnv`. */ - public entries(): Array<[string, T]> { + public entries(): Array<[string, string | undefined]> { return Object.entries(this.vars); } @@ -347,19 +347,17 @@ export class ReadOnlyEnv { * Use `ReadOnlyEnv` instead if you only plan to read from the environment. * This type allows writing to the environment. */ -export class Env< - T extends string | undefined = string | undefined, -> extends ReadOnlyEnv { +export class Env extends ReadOnlyEnv { private changed: boolean = false; /** Sets an environment variable. */ - public set(name: string, value: T): void { + public set(name: string, value: string | undefined): void { this.vars[name] = value; this.changed = true; } /** Sets all environment variables given by `vars`. */ - public setAll(vars: Record): void { + public setAll(vars: Record): void { for (const [key, val] of Object.entries(vars)) { this.set(key, val); } @@ -373,7 +371,7 @@ export class Env< * @param name The name of the environment variable to set and export. * @param val The value to set and export for the environment variable. */ - public export(name: string, val: T): void { + public export(name: string, val: string): void { // Setting the environment variable for this instance is always OK, including // in tests, since we use fresh `Env` instances whenever needed. This allows // tests to pass that rely on that part of the `core.exportVariable` behaviour. From 7cd2203aedcd2f285dbcf4932bd085638cce545e Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 23 Oct 2026 12:59:14 +0100 Subject: [PATCH 077/174] Use `env.export` in `getCodeQLForCmd` --- lib/entry-points.js | 2 +- src/codeql.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 86c7c220da..18873d6503 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -177449,7 +177449,7 @@ Output was: ${extractorPath}` Alternatively, if you want to continue using CodeQL CLI version ${result.version}, you can replace 'github/codeql-action/*@v${getActionVersion().split(".")[0]}' by 'github/codeql-action/*@v${getActionVersion()}' in your code scanning workflow to continue using this version of the CodeQL Action.` ); - exportEnvVar("CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */, "true"); + env.export("CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */, "true"); } return codeql; } diff --git a/src/codeql.ts b/src/codeql.ts index 973ebafd28..641421a7d8 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -18,7 +18,7 @@ import { CliError, wrapCliConfigurationError } from "./cli-errors"; import type { ActionConfig } from "./config/action-config"; import { appendExtraQueryExclusions, type Config } from "./config-utils"; import { DocUrl } from "./doc-url"; -import { EnvVar, getEnv, exportEnvVar, Env, ReadOnlyEnv } from "./environment"; +import { EnvVar, getEnv, Env, ReadOnlyEnv } from "./environment"; import { CodeQLDefaultVersionInfo, Feature, @@ -1076,7 +1076,7 @@ export async function getCodeQLForCmd( }' by 'github/codeql-action/*@v${getActionVersion()}' in your code scanning workflow to ` + "continue using this version of the CodeQL Action.", ); - exportEnvVar(EnvVar.SUPPRESS_DEPRECATED_SOON_WARNING, "true"); + env.export(EnvVar.SUPPRESS_DEPRECATED_SOON_WARNING, "true"); } return codeql; } From 6d448e0c5f30ec9377bfb19342d492239f021408 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 23 Oct 2026 13:09:20 +0100 Subject: [PATCH 078/174] Allow `runTool` to inherit `env` --- lib/entry-points.js | 52 ++++++++++++++++++++++++++++++--------------- src/actions-util.ts | 4 +++- src/codeql.ts | 38 +++++++++++++++++++++------------ src/environment.ts | 14 ++++++++++++ 4 files changed, 76 insertions(+), 32 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 18873d6503..5b5328e88c 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -166124,6 +166124,17 @@ var ReadOnlyEnv = class { get() { return { ...this.vars }; } + /** Gets a copy of the underlying environment, where the values are not `undefined`. */ + getDefined() { + const result = {}; + for (const [key, val] of Object.entries(this.vars)) { + if (val === void 0) { + continue; + } + result[key] = val; + } + return result; + } /** Tries to get the value for `name` and throws if there isn't one. */ getRequired(name) { return getRequiredEnvVar(this.vars, name); @@ -170350,7 +170361,7 @@ function ensureEndsInPeriod(text) { return text[text.length - 1] === "." ? text : `${text}.`; } var MAX_STDERR_BUFFER_SIZE = 2e4; -async function runTool(cmd, args = [], opts = {}) { +async function runTool(env, cmd, args = [], opts = {}) { let stdout = ""; let stderr = ""; if (!opts.noStreamStdout) { @@ -170358,6 +170369,7 @@ async function runTool(cmd, args = [], opts = {}) { `); } const exitCode = await new toolrunner.ToolRunner(cmd, args, { + env: env.getDefined(), ignoreReturnCode: true, listeners: { stdout: (data) => { @@ -177026,6 +177038,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { ); if (result === void 0) { result = await runCliJson( + env, cmd, ["version", "--format=json"], { @@ -177096,6 +177109,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { "--sublanguage-file-coverage" ] : ["--no-calculate-baseline"]; await runCli( + env, cmd, [ "database", @@ -177140,10 +177154,10 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { env.getOptional("CODEQL_VERBOSITY" /* CLI_VERBOSITY */) ?? EXTRACTION_DEBUG_MODE_VERBOSITY ); } - await runCli(autobuildCmd); + await runCli(env, autobuildCmd); }, async extractScannedLanguage(config, language) { - await runCli(cmd, [ + await runCli(env, cmd, [ "database", "trace-command", "--index-traceless-dbs", @@ -177158,7 +177172,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { applyAutobuildAzurePipelinesTimeoutFix(env); } try { - await runCli(cmd, [ + await runCli(env, cmd, [ "database", "trace-command", "--use-build-mode", @@ -177189,12 +177203,12 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { ...getExtraOptionsFromEnv(["database", "finalize"]), databasePath ]; - await runCli(cmd, args); + await runCli(env, cmd, args); }, async resolveLanguages({ filterToLanguagesWithQueries } = { filterToLanguagesWithQueries: false }) { - return runCliJson(cmd, [ + return runCliJson(env, cmd, [ "resolve", "languages", "--format=betterjson", @@ -177218,7 +177232,11 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { if (workingDir !== void 0) { codeqlArgs.push("--working-dir", workingDir); } - return await runCliJson(cmd, codeqlArgs); + return await runCliJson( + env, + cmd, + codeqlArgs + ); }, async databaseRunQueries(databasePath, flags, queries = []) { const codeqlArgs = [ @@ -177234,7 +177252,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { ignoringOptions: ["--expect-discarded-cache"] }) ]; - await runCli(cmd, codeqlArgs); + await runCli(env, cmd, codeqlArgs); }, async databaseInterpretResults(databasePath, querySuitePaths, sarifFile, threadsFlag, verbosityFlag, sarifRunPropertyFlag, automationDetailsId, config, features) { const shouldExportDiagnostics = await features.getValue( @@ -177275,7 +177293,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { if (querySuitePaths) { codeqlArgs.push(...querySuitePaths); } - return await runCli(cmd, codeqlArgs, { + return await runCli(env, cmd, codeqlArgs, { noStreamStdout: true }); }, @@ -177289,7 +177307,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { `--cache-cleanup=${cleanupLevel}`, ...getExtraOptionsFromEnv(["database", "cleanup"]) ]; - await runCli(cmd, codeqlArgs); + await runCli(env, cmd, codeqlArgs); } }, async databaseBundle(databasePath, outputFilePath, databaseName, includeDiagnostics, alsoIncludeRelativePaths) { @@ -177403,7 +177421,7 @@ Output was: ${extractorPath}` ...getExtraOptionsFromEnv(["resolve", "queries"]), ...queries ]; - return await runCliJson(cmd, codeqlArgs, { + return await runCliJson(env, cmd, codeqlArgs, { noStreamStdout: true }); }, @@ -177415,7 +177433,7 @@ Output was: ${extractorPath}` "--format=json", ...getExtraOptionsFromEnv(["resolve", "database"]) ]; - return await runCliJson(cmd, codeqlArgs, { + return await runCliJson(env, cmd, codeqlArgs, { noStreamStdout: true }); }, @@ -177435,7 +177453,7 @@ Output was: ${extractorPath}` if (mergeRunsFromEqualCategory) { args.push("--sarif-merge-runs-from-equal-category"); } - await runCli(cmd, args); + await runCli(env, cmd, args); } }; if (checkVersion && !await codeQlVersionAtLeast(codeql, CODEQL_MINIMUM_VERSION)) { @@ -177489,9 +177507,9 @@ function getExtraOptions(options, paths, pathInfo) { ); return all.concat(specific); } -async function runCli(cmd, args = [], opts = {}) { +async function runCli(env, cmd, args = [], opts = {}) { try { - return await runTool(cmd, args, opts); + return await runTool(env, cmd, args, opts); } catch (e) { if (e instanceof CommandInvocationError) { throw wrapCliConfigurationError(new CliError(e)); @@ -177499,8 +177517,8 @@ async function runCli(cmd, args = [], opts = {}) { throw e; } } -async function runCliJson(cmd, args = [], opts = {}) { - const output = await runCli(cmd, args, opts); +async function runCliJson(env, cmd, args = [], opts = {}) { + const output = await runCli(env, cmd, args, opts); try { return JSON.parse(output); } catch (e) { diff --git a/src/actions-util.ts b/src/actions-util.ts index 997b8ee90a..096bdd8f15 100644 --- a/src/actions-util.ts +++ b/src/actions-util.ts @@ -361,9 +361,10 @@ const MAX_STDERR_BUFFER_SIZE = 20000; * Runs a CLI tool. * * @returns Standard output produced by the tool. - * @throws A `CommandInvocationError` if the tool exits with a non-zero status code. + * @throws A {@link CommandInvocationError} if the tool exits with a non-zero status code. */ export async function runTool( + env: Env, cmd: string, args: string[] = [], opts: { stdin?: string; noStreamStdout?: boolean } = {}, @@ -374,6 +375,7 @@ export async function runTool( process.stdout.write(`[command]${cmd} ${args.join(" ")}\n`); } const exitCode = await new toolrunner.ToolRunner(cmd, args, { + env: env.getDefined(), ignoreReturnCode: true, listeners: { stdout: (data: Buffer) => { diff --git a/src/codeql.ts b/src/codeql.ts index 641421a7d8..9f7b4b5b85 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -514,6 +514,7 @@ export async function getCodeQLForCmd( ); if (result === undefined) { result = await runCliJson( + env, cmd, ["version", "--format=json"], { @@ -597,6 +598,7 @@ export async function getCodeQLForCmd( : ["--no-calculate-baseline"]; await runCli( + env, cmd, [ "database", @@ -663,10 +665,10 @@ export async function getCodeQLForCmd( // When `DYLD_INSERT_LIBRARIES` is set in the environment for a step, // the Actions runtime introduces its own workaround for SIP // (https://github.com/actions/runner/pull/416). - await runCli(autobuildCmd); + await runCli(env, autobuildCmd); }, async extractScannedLanguage(config: Config, language: Language) { - await runCli(cmd, [ + await runCli(env, cmd, [ "database", "trace-command", "--index-traceless-dbs", @@ -681,7 +683,7 @@ export async function getCodeQLForCmd( applyAutobuildAzurePipelinesTimeoutFix(env); } try { - await runCli(cmd, [ + await runCli(env, cmd, [ "database", "trace-command", "--use-build-mode", @@ -720,7 +722,7 @@ export async function getCodeQLForCmd( ...getExtraOptionsFromEnv(["database", "finalize"]), databasePath, ]; - await runCli(cmd, args); + await runCli(env, cmd, args); }, async resolveLanguages( { @@ -729,7 +731,7 @@ export async function getCodeQLForCmd( filterToLanguagesWithQueries: boolean; } = { filterToLanguagesWithQueries: false }, ) { - return runCliJson(cmd, [ + return runCliJson(env, cmd, [ "resolve", "languages", "--format=betterjson", @@ -758,7 +760,11 @@ export async function getCodeQLForCmd( if (workingDir !== undefined) { codeqlArgs.push("--working-dir", workingDir); } - return await runCliJson(cmd, codeqlArgs); + return await runCliJson( + env, + cmd, + codeqlArgs, + ); }, async databaseRunQueries( databasePath: string, @@ -777,7 +783,7 @@ export async function getCodeQLForCmd( ignoringOptions: ["--expect-discarded-cache"], }), ]; - await runCli(cmd, codeqlArgs); + await runCli(env, cmd, codeqlArgs); }, async databaseInterpretResults( databasePath: string, @@ -830,7 +836,7 @@ export async function getCodeQLForCmd( } // Capture the stdout, which contains the analysis summary. Don't stream it to the Actions // logs to avoid printing it twice. - return await runCli(cmd, codeqlArgs, { + return await runCli(env, cmd, codeqlArgs, { noStreamStdout: true, }); }, @@ -847,7 +853,7 @@ export async function getCodeQLForCmd( `--cache-cleanup=${cleanupLevel}`, ...getExtraOptionsFromEnv(["database", "cleanup"]), ]; - await runCli(cmd, codeqlArgs); + await runCli(env, cmd, codeqlArgs); } }, async databaseBundle( @@ -995,7 +1001,7 @@ export async function getCodeQLForCmd( ...getExtraOptionsFromEnv(["resolve", "queries"]), ...queries, ]; - return await runCliJson(cmd, codeqlArgs, { + return await runCliJson(env, cmd, codeqlArgs, { noStreamStdout: true, }); }, @@ -1009,7 +1015,7 @@ export async function getCodeQLForCmd( "--format=json", ...getExtraOptionsFromEnv(["resolve", "database"]), ]; - return await runCliJson(cmd, codeqlArgs, { + return await runCliJson(env, cmd, codeqlArgs, { noStreamStdout: true, }); }, @@ -1036,7 +1042,7 @@ export async function getCodeQLForCmd( args.push("--sarif-merge-runs-from-equal-category"); } - await runCli(cmd, args); + await runCli(env, cmd, args); }, }; // To ensure that status reports include the CodeQL CLI version wherever @@ -1153,12 +1159,13 @@ export function getExtraOptions( } async function runCli( + env: Env, cmd: string, args: string[] = [], opts: { stdin?: string; noStreamStdout?: boolean } = {}, ): Promise { try { - return await runTool(cmd, args, opts); + return await runTool(env, cmd, args, opts); } catch (e) { if (e instanceof CommandInvocationError) { throw wrapCliConfigurationError(new CliError(e)); @@ -1169,6 +1176,8 @@ async function runCli( /** * Wraps the command executor {@link runCli} and tries to parse the output as JSON. + * + * @param env The environment variables. * @param cmd The command to run. * @param args The arguments to pass to the command. * @param opts The options for running the command. @@ -1177,11 +1186,12 @@ async function runCli( * @returns The parsed JSON output from the command. */ async function runCliJson( + env: Env, cmd: string, args: string[] = [], opts: { stdin?: string; noStreamStdout?: boolean } = {}, ): Promise { - const output = await runCli(cmd, args, opts); + const output = await runCli(env, cmd, args, opts); try { return JSON.parse(output) as T; } catch (e) { diff --git a/src/environment.ts b/src/environment.ts index 994e7a55c5..7776238e5d 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -306,6 +306,20 @@ export class ReadOnlyEnv { return { ...this.vars }; } + /** Gets a copy of the underlying environment, where the values are not `undefined`. */ + public getDefined(): Record { + const result: Record = {}; + + for (const [key, val] of Object.entries(this.vars)) { + if (val === undefined) { + continue; + } + result[key] = val; + } + + return result; + } + /** Tries to get the value for `name` and throws if there isn't one. */ public getRequired(name: string): string { return getRequiredEnvVar(this.vars, name); From 49bbf2b590d4c553b85f57a1027767333ae43d05 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Fri, 23 Oct 2026 13:30:18 +0100 Subject: [PATCH 079/174] Ping the user who enqueued a PR when it's removed from the merge queue Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/pr-dequeued.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-dequeued.yml b/.github/workflows/pr-dequeued.yml index 0c47c9dc74..25260c7aa6 100644 --- a/.github/workflows/pr-dequeued.yml +++ b/.github/workflows/pr-dequeued.yml @@ -21,8 +21,23 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} REASON: ${{ github.event.reason }} - USER: ${{ github.event.pull_request.user.login }} run: | - echo "@$USER The pull request was removed from the merge queue (\`$REASON\`)." \ + # Mention whoever added the PR to the merge queue rather than the PR author, who may be a + # bot such as Dependabot. The `dequeued` event payload doesn't identify the enqueuer, so + # look them up in the most recent `AddedToMergeQueueEvent` on the PR's timeline. + enqueuer=$(gh api graphql \ + -F number="$PR_NUMBER" \ + -f query=' + query($number: Int!) { + repository(owner: "github", name: "codeql-action") { + pullRequest(number: $number) { + timelineItems(itemTypes: [ADDED_TO_MERGE_QUEUE_EVENT], last: 1) { + nodes { ... on AddedToMergeQueueEvent { enqueuer { login } } } + } + } + } + }' \ + --jq '.data.repository.pullRequest.timelineItems.nodes[0].enqueuer.login') + echo "@$enqueuer The pull request was removed from the merge queue (\`$REASON\`)." \ "Please resolve any issues if required and enqueue the PR again." | gh pr comment --body-file - --repo github/codeql-action "$PR_NUMBER" From fc9487df66b626f63fcde9944cbe8ec6d53525ed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 24 Oct 2026 00:23:30 +0000 Subject: [PATCH 080/174] Update supported GitHub Enterprise Server versions --- lib/entry-points.js | 2 +- src/api-compatibility.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 7cea6c0b6d..2e8b97e41b 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -169371,7 +169371,7 @@ var semver = __toESM(require_semver2()); // src/api-compatibility.json var maximumVersion = "3.23"; -var minimumVersion = "3.18"; +var minimumVersion = "3.19"; // src/json/index.ts function parseString(data) { diff --git a/src/api-compatibility.json b/src/api-compatibility.json index c1122fb2a9..83ff180db0 100644 --- a/src/api-compatibility.json +++ b/src/api-compatibility.json @@ -1 +1 @@ -{"maximumVersion":"3.23","minimumVersion":"3.18"} +{"maximumVersion":"3.23","minimumVersion":"3.19"} From 49de08391cb0322847ae26f0c78e189b7d8179a7 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 26 Oct 2026 10:46:59 +0000 Subject: [PATCH 081/174] Fix JSDoc --- src/languages/swift.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/languages/swift.ts b/src/languages/swift.ts index 3a51491fbf..4faa3efe96 100644 --- a/src/languages/swift.ts +++ b/src/languages/swift.ts @@ -11,7 +11,6 @@ import { BuiltInLanguage } from "."; * @param config The Action configuration. * * @throws {ConfigurationError} If Swift analysis is not possible on the current runner. - * @returns True if we can run a Swift analysis. */ export function checkSwiftCompatibility( action: ActionState<["Base"]>, From 516bd7cc484cbb9c1714b6e26aef53918df32e03 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 26 Oct 2026 10:50:07 +0000 Subject: [PATCH 082/174] Pass `env` to all `ToolRunner`s in `codeql.ts` --- lib/entry-points.js | 13 ++++++++++--- src/codeql.ts | 13 ++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 5b5328e88c..9c9faffc6a 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -177331,7 +177331,9 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { ]) ); } - await new toolrunner3.ToolRunner(cmd, args).exec(); + await new toolrunner3.ToolRunner(cmd, args, { + env: env.getDefined() + }).exec(); }, async databaseExportDiagnostics(databasePath, sarifFile, automationDetailsId) { const args = [ @@ -177350,7 +177352,9 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { if (automationDetailsId !== void 0) { args.push("--sarif-category", automationDetailsId); } - await new toolrunner3.ToolRunner(cmd, args).exec(); + await new toolrunner3.ToolRunner(cmd, args, { + env: env.getDefined() + }).exec(); }, async diagnosticsExport(sarifFile, automationDetailsId, config, diagnosticDir) { let configPath = getGeneratedCodeScanningConfigPath(config); @@ -177377,7 +177381,9 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { if (automationDetailsId !== void 0) { args.push("--sarif-category", automationDetailsId); } - await new toolrunner3.ToolRunner(cmd, args).exec(); + await new toolrunner3.ToolRunner(cmd, args, { + env: env.getDefined() + }).exec(); }, async resolveExtractor(language) { let extractorPath = ""; @@ -177393,6 +177399,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { ...getExtraOptionsFromEnv(["resolve", "extractor"]) ], { + env: env.getDefined(), silent: true, listeners: { stdout: (data) => { diff --git a/src/codeql.ts b/src/codeql.ts index 9f7b4b5b85..ba004dde1b 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -887,7 +887,9 @@ export async function getCodeQLForCmd( ]), ); } - await new toolrunner.ToolRunner(cmd, args).exec(); + await new toolrunner.ToolRunner(cmd, args, { + env: env.getDefined(), + }).exec(); }, async databaseExportDiagnostics( databasePath: string, @@ -908,7 +910,9 @@ export async function getCodeQLForCmd( if (automationDetailsId !== undefined) { args.push("--sarif-category", automationDetailsId); } - await new toolrunner.ToolRunner(cmd, args).exec(); + await new toolrunner.ToolRunner(cmd, args, { + env: env.getDefined(), + }).exec(); }, async diagnosticsExport( sarifFile: string, @@ -956,7 +960,9 @@ export async function getCodeQLForCmd( if (automationDetailsId !== undefined) { args.push("--sarif-category", automationDetailsId); } - await new toolrunner.ToolRunner(cmd, args).exec(); + await new toolrunner.ToolRunner(cmd, args, { + env: env.getDefined(), + }).exec(); }, async resolveExtractor(language: Language): Promise { // Request it using `format=json` so we don't need to strip the trailing new line generated by @@ -974,6 +980,7 @@ export async function getCodeQLForCmd( ...getExtraOptionsFromEnv(["resolve", "extractor"]), ], { + env: env.getDefined(), silent: true, listeners: { stdout: (data) => { From b63386c3d837cbc23d61b46863530ff01b622ada Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 26 Oct 2026 12:48:51 +0000 Subject: [PATCH 083/174] Update `setup-kotlin` to the latest version --- .github/actions/prepare-test/action.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/prepare-test/action.yml b/.github/actions/prepare-test/action.yml index 5e2b5028f7..4eb840d2d8 100644 --- a/.github/actions/prepare-test/action.yml +++ b/.github/actions/prepare-test/action.yml @@ -6,11 +6,11 @@ inputs: required: true use-all-platform-bundle: description: "If true, we output a tools URL with codeql-bundle.tar.gz file rather than platform-specific URL" - default: 'false' + default: "false" required: false setup-kotlin: description: "If true, we setup kotlin" - default: 'true' + default: "true" required: true outputs: tools-url: @@ -73,7 +73,7 @@ runs: exit 1 fi - - uses: fwilhe2/setup-kotlin@9c245a6425255f5e98ba1ce6c15d31fce7eca9da + - uses: fwilhe2/setup-kotlin@b325539ca8f6e1d9ee04efed06f49bdbf5426dbb # v2.1 if: ${{ inputs.setup-kotlin == 'true' }} with: version: 1.8.21 From b913bf6353dc29e7f1ab45d4de642092f88d5410 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 26 Oct 2026 12:51:54 +0000 Subject: [PATCH 084/174] Point Dependabot at subdirectories in `.github/actions` --- .github/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0e0dd0cce1..ae4a4476e4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -26,7 +26,7 @@ updates: - package-ecosystem: github-actions directories: - "/.github/workflows" - - "/.github/actions" + - "/.github/actions/*/" schedule: interval: weekly cooldown: From 39119659f322397972d8b08390d27c7ae30838ff Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 26 Oct 2026 13:00:39 +0000 Subject: [PATCH 085/174] Bump `undici` override to the latest `7.x` version --- lib/entry-points.js | 18399 ++++++++++++++++++++++++++++++------------ package-lock.json | 10 +- package.json | 4 +- 3 files changed, 13062 insertions(+), 5351 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 7cea6c0b6d..5569352865 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -563,11 +563,13 @@ var require_tunnel2 = __commonJS({ // node_modules/undici/lib/core/symbols.js var require_symbols = __commonJS({ "node_modules/undici/lib/core/symbols.js"(exports2, module2) { + "use strict"; module2.exports = { kClose: /* @__PURE__ */ Symbol("close"), kDestroy: /* @__PURE__ */ Symbol("destroy"), kDispatch: /* @__PURE__ */ Symbol("dispatch"), kUrl: /* @__PURE__ */ Symbol("url"), + kRedirectCacheControl: /* @__PURE__ */ Symbol("redirect cache control"), kWriting: /* @__PURE__ */ Symbol("writing"), kResuming: /* @__PURE__ */ Symbol("resuming"), kQueue: /* @__PURE__ */ Symbol("queue"), @@ -617,7 +619,6 @@ var require_symbols = __commonJS({ kMaxRequests: /* @__PURE__ */ Symbol("maxRequestsPerClient"), kProxy: /* @__PURE__ */ Symbol("proxy agent options"), kCounter: /* @__PURE__ */ Symbol("socket request counter"), - kInterceptors: /* @__PURE__ */ Symbol("dispatch interceptors"), kMaxResponseSize: /* @__PURE__ */ Symbol("max response size"), kHTTP2Session: /* @__PURE__ */ Symbol("http2Session"), kHTTP2SessionState: /* @__PURE__ */ Symbol("http2Session state"), @@ -626,9 +627,245 @@ var require_symbols = __commonJS({ kListeners: /* @__PURE__ */ Symbol("listeners"), kHTTPContext: /* @__PURE__ */ Symbol("http context"), kMaxConcurrentStreams: /* @__PURE__ */ Symbol("max concurrent streams"), + kHTTP2InitialWindowSize: /* @__PURE__ */ Symbol("http2 initial window size"), + kHTTP2ConnectionWindowSize: /* @__PURE__ */ Symbol("http2 connection window size"), + kEnableConnectProtocol: /* @__PURE__ */ Symbol("http2session connect protocol"), + kRemoteSettings: /* @__PURE__ */ Symbol("http2session remote settings"), + kHTTP2Stream: /* @__PURE__ */ Symbol("http2session client stream"), + kPingInterval: /* @__PURE__ */ Symbol("ping interval"), kNoProxyAgent: /* @__PURE__ */ Symbol("no proxy agent"), kHttpProxyAgent: /* @__PURE__ */ Symbol("http proxy agent"), - kHttpsProxyAgent: /* @__PURE__ */ Symbol("https proxy agent") + kHttpsProxyAgent: /* @__PURE__ */ Symbol("https proxy agent"), + kSocks5ProxyAgent: /* @__PURE__ */ Symbol("socks5 proxy agent") + }; + } +}); + +// node_modules/undici/lib/util/timers.js +var require_timers = __commonJS({ + "node_modules/undici/lib/util/timers.js"(exports2, module2) { + "use strict"; + var fastNow = 0; + var RESOLUTION_MS = 1e3; + var TICK_MS = (RESOLUTION_MS >> 1) - 1; + var fastNowTimeout; + var kFastTimer = /* @__PURE__ */ Symbol("kFastTimer"); + var fastTimers = []; + var NOT_IN_LIST = -2; + var TO_BE_CLEARED = -1; + var PENDING = 0; + var ACTIVE = 1; + function onTick() { + fastNow += TICK_MS; + let idx = 0; + let len = fastTimers.length; + while (idx < len) { + const timer = fastTimers[idx]; + if (timer._state === PENDING) { + timer._idleStart = fastNow - TICK_MS; + timer._state = ACTIVE; + } else if (timer._state === ACTIVE && fastNow >= timer._idleStart + timer._idleTimeout) { + timer._state = TO_BE_CLEARED; + timer._idleStart = -1; + timer._onTimeout(timer._timerArg); + } + if (timer._state === TO_BE_CLEARED) { + timer._state = NOT_IN_LIST; + if (--len !== 0) { + fastTimers[idx] = fastTimers[len]; + } + } else { + ++idx; + } + } + fastTimers.length = len; + if (fastTimers.length !== 0) { + refreshTimeout(); + } + } + function refreshTimeout() { + if (fastNowTimeout?.refresh) { + fastNowTimeout.refresh(); + } else { + clearTimeout(fastNowTimeout); + fastNowTimeout = setTimeout(onTick, TICK_MS); + fastNowTimeout?.unref(); + } + } + var FastTimer = class { + [kFastTimer] = true; + /** + * The state of the timer, which can be one of the following: + * - NOT_IN_LIST (-2) + * - TO_BE_CLEARED (-1) + * - PENDING (0) + * - ACTIVE (1) + * + * @type {-2|-1|0|1} + * @private + */ + _state = NOT_IN_LIST; + /** + * The number of milliseconds to wait before calling the callback. + * + * @type {number} + * @private + */ + _idleTimeout = -1; + /** + * The time in milliseconds when the timer was started. This value is used to + * calculate when the timer should expire. + * + * @type {number} + * @default -1 + * @private + */ + _idleStart = -1; + /** + * The function to be executed when the timer expires. + * @type {Function} + * @private + */ + _onTimeout; + /** + * The argument to be passed to the callback when the timer expires. + * + * @type {*} + * @private + */ + _timerArg; + /** + * @constructor + * @param {Function} callback A function to be executed after the timer + * expires. + * @param {number} delay The time, in milliseconds that the timer should wait + * before the specified function or code is executed. + * @param {*} arg + */ + constructor(callback, delay2, arg) { + this._onTimeout = callback; + this._idleTimeout = delay2; + this._timerArg = arg; + this.refresh(); + } + /** + * Sets the timer's start time to the current time, and reschedules the timer + * to call its callback at the previously specified duration adjusted to the + * current time. + * Using this on a timer that has already called its callback will reactivate + * the timer. + * + * @returns {void} + */ + refresh() { + if (this._state === NOT_IN_LIST) { + fastTimers.push(this); + } + if (!fastNowTimeout || fastTimers.length === 1) { + refreshTimeout(); + } + this._state = PENDING; + } + /** + * The `clear` method cancels the timer, preventing it from executing. + * + * @returns {void} + * @private + */ + clear() { + this._state = TO_BE_CLEARED; + this._idleStart = -1; + } + }; + module2.exports = { + /** + * The setTimeout() method sets a timer which executes a function once the + * timer expires. + * @param {Function} callback A function to be executed after the timer + * expires. + * @param {number} delay The time, in milliseconds that the timer should + * wait before the specified function or code is executed. + * @param {*} [arg] An optional argument to be passed to the callback function + * when the timer expires. + * @returns {NodeJS.Timeout|FastTimer} + */ + setTimeout(callback, delay2, arg) { + return delay2 <= RESOLUTION_MS ? setTimeout(callback, delay2, arg) : new FastTimer(callback, delay2, arg); + }, + /** + * The clearTimeout method cancels an instantiated Timer previously created + * by calling setTimeout. + * + * @param {NodeJS.Timeout|FastTimer} timeout + */ + clearTimeout(timeout) { + if (timeout[kFastTimer]) { + timeout.clear(); + } else { + clearTimeout(timeout); + } + }, + /** + * The setFastTimeout() method sets a fastTimer which executes a function once + * the timer expires. + * @param {Function} callback A function to be executed after the timer + * expires. + * @param {number} delay The time, in milliseconds that the timer should + * wait before the specified function or code is executed. + * @param {*} [arg] An optional argument to be passed to the callback function + * when the timer expires. + * @returns {FastTimer} + */ + setFastTimeout(callback, delay2, arg) { + return new FastTimer(callback, delay2, arg); + }, + /** + * The clearTimeout method cancels an instantiated FastTimer previously + * created by calling setFastTimeout. + * + * @param {FastTimer} timeout + */ + clearFastTimeout(timeout) { + timeout.clear(); + }, + /** + * The now method returns the value of the internal fast timer clock. + * + * @returns {number} + */ + now() { + return fastNow; + }, + /** + * Trigger the onTick function to process the fastTimers array. + * Exported for testing purposes only. + * Marking as deprecated to discourage any use outside of testing. + * @deprecated + * @param {number} [delay=0] The delay in milliseconds to add to the now value. + */ + tick(delay2 = 0) { + fastNow += delay2 - RESOLUTION_MS + 1; + onTick(); + onTick(); + }, + /** + * Reset FastTimers. + * Exported for testing purposes only. + * Marking as deprecated to discourage any use outside of testing. + * @deprecated + */ + reset() { + fastNow = 0; + fastTimers.length = 0; + clearTimeout(fastNowTimeout); + fastNowTimeout = null; + }, + /** + * Exporting for testing purposes only. + * Marking as deprecated to discourage any use outside of testing. + * @deprecated + */ + kFastTimer }; } }); @@ -639,15 +876,17 @@ var require_errors = __commonJS({ "use strict"; var kUndiciError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR"); var UndiciError = class extends Error { - constructor(message) { - super(message); + constructor(message, options) { + super(message, options); this.name = "UndiciError"; this.code = "UND_ERR"; } static [Symbol.hasInstance](instance8) { return instance8 && instance8[kUndiciError] === true; } - [kUndiciError] = true; + get [kUndiciError]() { + return true; + } }; var kConnectTimeoutError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_CONNECT_TIMEOUT"); var ConnectTimeoutError = class extends UndiciError { @@ -660,7 +899,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kConnectTimeoutError] === true; } - [kConnectTimeoutError] = true; + get [kConnectTimeoutError]() { + return true; + } }; var kHeadersTimeoutError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_HEADERS_TIMEOUT"); var HeadersTimeoutError = class extends UndiciError { @@ -673,7 +914,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kHeadersTimeoutError] === true; } - [kHeadersTimeoutError] = true; + get [kHeadersTimeoutError]() { + return true; + } }; var kHeadersOverflowError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_HEADERS_OVERFLOW"); var HeadersOverflowError = class extends UndiciError { @@ -686,7 +929,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kHeadersOverflowError] === true; } - [kHeadersOverflowError] = true; + get [kHeadersOverflowError]() { + return true; + } }; var kBodyTimeoutError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_BODY_TIMEOUT"); var BodyTimeoutError = class extends UndiciError { @@ -699,24 +944,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kBodyTimeoutError] === true; } - [kBodyTimeoutError] = true; - }; - var kResponseStatusCodeError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_RESPONSE_STATUS_CODE"); - var ResponseStatusCodeError = class extends UndiciError { - constructor(message, statusCode, headers, body) { - super(message); - this.name = "ResponseStatusCodeError"; - this.message = message || "Response Status Code Error"; - this.code = "UND_ERR_RESPONSE_STATUS_CODE"; - this.body = body; - this.status = statusCode; - this.statusCode = statusCode; - this.headers = headers; - } - static [Symbol.hasInstance](instance8) { - return instance8 && instance8[kResponseStatusCodeError] === true; + get [kBodyTimeoutError]() { + return true; } - [kResponseStatusCodeError] = true; }; var kInvalidArgumentError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_INVALID_ARG"); var InvalidArgumentError = class extends UndiciError { @@ -729,7 +959,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kInvalidArgumentError] === true; } - [kInvalidArgumentError] = true; + get [kInvalidArgumentError]() { + return true; + } }; var kInvalidReturnValueError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_INVALID_RETURN_VALUE"); var InvalidReturnValueError = class extends UndiciError { @@ -742,7 +974,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kInvalidReturnValueError] === true; } - [kInvalidReturnValueError] = true; + get [kInvalidReturnValueError]() { + return true; + } }; var kAbortError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_ABORT"); var AbortError2 = class extends UndiciError { @@ -755,7 +989,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kAbortError] === true; } - [kAbortError] = true; + get [kAbortError]() { + return true; + } }; var kRequestAbortedError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_ABORTED"); var RequestAbortedError = class extends AbortError2 { @@ -768,7 +1004,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kRequestAbortedError] === true; } - [kRequestAbortedError] = true; + get [kRequestAbortedError]() { + return true; + } }; var kInformationalError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_INFO"); var InformationalError = class extends UndiciError { @@ -781,7 +1019,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kInformationalError] === true; } - [kInformationalError] = true; + get [kInformationalError]() { + return true; + } }; var kRequestContentLengthMismatchError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_REQ_CONTENT_LENGTH_MISMATCH"); var RequestContentLengthMismatchError = class extends UndiciError { @@ -794,7 +1034,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kRequestContentLengthMismatchError] === true; } - [kRequestContentLengthMismatchError] = true; + get [kRequestContentLengthMismatchError]() { + return true; + } }; var kResponseContentLengthMismatchError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_RES_CONTENT_LENGTH_MISMATCH"); var ResponseContentLengthMismatchError = class extends UndiciError { @@ -807,7 +1049,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kResponseContentLengthMismatchError] === true; } - [kResponseContentLengthMismatchError] = true; + get [kResponseContentLengthMismatchError]() { + return true; + } }; var kClientDestroyedError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_DESTROYED"); var ClientDestroyedError = class extends UndiciError { @@ -820,7 +1064,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kClientDestroyedError] === true; } - [kClientDestroyedError] = true; + get [kClientDestroyedError]() { + return true; + } }; var kClientClosedError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_CLOSED"); var ClientClosedError = class extends UndiciError { @@ -833,7 +1079,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kClientClosedError] === true; } - [kClientClosedError] = true; + get [kClientClosedError]() { + return true; + } }; var kSocketError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_SOCKET"); var SocketError = class extends UndiciError { @@ -847,7 +1095,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kSocketError] === true; } - [kSocketError] = true; + get [kSocketError]() { + return true; + } }; var kNotSupportedError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_NOT_SUPPORTED"); var NotSupportedError = class extends UndiciError { @@ -860,7 +1110,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kNotSupportedError] === true; } - [kNotSupportedError] = true; + get [kNotSupportedError]() { + return true; + } }; var kBalancedPoolMissingUpstreamError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_BPL_MISSING_UPSTREAM"); var BalancedPoolMissingUpstreamError = class extends UndiciError { @@ -873,7 +1125,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kBalancedPoolMissingUpstreamError] === true; } - [kBalancedPoolMissingUpstreamError] = true; + get [kBalancedPoolMissingUpstreamError]() { + return true; + } }; var kHTTPParserError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_HTTP_PARSER"); var HTTPParserError = class extends Error { @@ -886,7 +1140,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kHTTPParserError] === true; } - [kHTTPParserError] = true; + get [kHTTPParserError]() { + return true; + } }; var kResponseExceededMaxSizeError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_RES_EXCEEDED_MAX_SIZE"); var ResponseExceededMaxSizeError = class extends UndiciError { @@ -899,7 +1155,9 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kResponseExceededMaxSizeError] === true; } - [kResponseExceededMaxSizeError] = true; + get [kResponseExceededMaxSizeError]() { + return true; + } }; var kRequestRetryError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_REQ_RETRY"); var RequestRetryError = class extends UndiciError { @@ -915,28 +1173,32 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kRequestRetryError] === true; } - [kRequestRetryError] = true; + get [kRequestRetryError]() { + return true; + } }; var kResponseError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_RESPONSE"); var ResponseError = class extends UndiciError { - constructor(message, code, { headers, data }) { + constructor(message, code, { headers, body }) { super(message); this.name = "ResponseError"; this.message = message || "Response error"; this.code = "UND_ERR_RESPONSE"; this.statusCode = code; - this.data = data; + this.body = body; this.headers = headers; } static [Symbol.hasInstance](instance8) { return instance8 && instance8[kResponseError] === true; } - [kResponseError] = true; + get [kResponseError]() { + return true; + } }; var kSecureProxyConnectionError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_PRX_TLS"); var SecureProxyConnectionError = class extends UndiciError { - constructor(cause, message, options) { - super(message, { cause, ...options ?? {} }); + constructor(cause, message, options = {}) { + super(message, { cause, ...options }); this.name = "SecureProxyConnectionError"; this.message = message || "Secure Proxy Connection failed"; this.code = "UND_ERR_PRX_TLS"; @@ -945,7 +1207,32 @@ var require_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kSecureProxyConnectionError] === true; } - [kSecureProxyConnectionError] = true; + get [kSecureProxyConnectionError]() { + return true; + } + }; + var kMaxOriginsReachedError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_MAX_ORIGINS_REACHED"); + var MaxOriginsReachedError = class extends UndiciError { + constructor(message) { + super(message); + this.name = "MaxOriginsReachedError"; + this.message = message || "Maximum allowed origins reached"; + this.code = "UND_ERR_MAX_ORIGINS_REACHED"; + } + static [Symbol.hasInstance](instance8) { + return instance8 && instance8[kMaxOriginsReachedError] === true; + } + get [kMaxOriginsReachedError]() { + return true; + } + }; + var Socks5ProxyError = class extends UndiciError { + constructor(message, code) { + super(message); + this.name = "Socks5ProxyError"; + this.message = message || "SOCKS5 proxy error"; + this.code = code || "UND_ERR_SOCKS5"; + } }; var kMessageSizeExceededError = /* @__PURE__ */ Symbol.for("undici.error.UND_ERR_WS_MESSAGE_SIZE_EXCEEDED"); var MessageSizeExceededError = class extends UndiciError { @@ -971,7 +1258,6 @@ var require_errors = __commonJS({ BodyTimeoutError, RequestContentLengthMismatchError, ConnectTimeoutError, - ResponseStatusCodeError, InvalidArgumentError, InvalidReturnValueError, RequestAbortedError, @@ -986,6 +1272,8 @@ var require_errors = __commonJS({ RequestRetryError, ResponseError, SecureProxyConnectionError, + MaxOriginsReachedError, + Socks5ProxyError, MessageSizeExceededError }; } @@ -995,113 +1283,126 @@ var require_errors = __commonJS({ var require_constants = __commonJS({ "node_modules/undici/lib/core/constants.js"(exports2, module2) { "use strict"; + var wellknownHeaderNames = ( + /** @type {const} */ + [ + "Accept", + "Accept-Encoding", + "Accept-Language", + "Accept-Ranges", + "Access-Control-Allow-Credentials", + "Access-Control-Allow-Headers", + "Access-Control-Allow-Methods", + "Access-Control-Allow-Origin", + "Access-Control-Expose-Headers", + "Access-Control-Max-Age", + "Access-Control-Request-Headers", + "Access-Control-Request-Method", + "Age", + "Allow", + "Alt-Svc", + "Alt-Used", + "Authorization", + "Cache-Control", + "Clear-Site-Data", + "Connection", + "Content-Disposition", + "Content-Encoding", + "Content-Language", + "Content-Length", + "Content-Location", + "Content-Range", + "Content-Security-Policy", + "Content-Security-Policy-Report-Only", + "Content-Type", + "Cookie", + "Cross-Origin-Embedder-Policy", + "Cross-Origin-Opener-Policy", + "Cross-Origin-Resource-Policy", + "Date", + "Device-Memory", + "Downlink", + "ECT", + "ETag", + "Expect", + "Expect-CT", + "Expires", + "Forwarded", + "From", + "Host", + "If-Match", + "If-Modified-Since", + "If-None-Match", + "If-Range", + "If-Unmodified-Since", + "Keep-Alive", + "Last-Modified", + "Link", + "Location", + "Max-Forwards", + "Origin", + "Permissions-Policy", + "Pragma", + "Proxy-Authenticate", + "Proxy-Authorization", + "RTT", + "Range", + "Referer", + "Referrer-Policy", + "Refresh", + "Retry-After", + "Sec-WebSocket-Accept", + "Sec-WebSocket-Extensions", + "Sec-WebSocket-Key", + "Sec-WebSocket-Protocol", + "Sec-WebSocket-Version", + "Server", + "Server-Timing", + "Service-Worker-Allowed", + "Service-Worker-Navigation-Preload", + "Set-Cookie", + "SourceMap", + "Strict-Transport-Security", + "Supports-Loading-Mode", + "TE", + "Timing-Allow-Origin", + "Trailer", + "Transfer-Encoding", + "Upgrade", + "Upgrade-Insecure-Requests", + "User-Agent", + "Vary", + "Via", + "WWW-Authenticate", + "X-Content-Type-Options", + "X-DNS-Prefetch-Control", + "X-Frame-Options", + "X-Permitted-Cross-Domain-Policies", + "X-Powered-By", + "X-Requested-With", + "X-XSS-Protection" + ] + ); var headerNameLowerCasedRecord = {}; - var wellknownHeaderNames = [ - "Accept", - "Accept-Encoding", - "Accept-Language", - "Accept-Ranges", - "Access-Control-Allow-Credentials", - "Access-Control-Allow-Headers", - "Access-Control-Allow-Methods", - "Access-Control-Allow-Origin", - "Access-Control-Expose-Headers", - "Access-Control-Max-Age", - "Access-Control-Request-Headers", - "Access-Control-Request-Method", - "Age", - "Allow", - "Alt-Svc", - "Alt-Used", - "Authorization", - "Cache-Control", - "Clear-Site-Data", - "Connection", - "Content-Disposition", - "Content-Encoding", - "Content-Language", - "Content-Length", - "Content-Location", - "Content-Range", - "Content-Security-Policy", - "Content-Security-Policy-Report-Only", - "Content-Type", - "Cookie", - "Cross-Origin-Embedder-Policy", - "Cross-Origin-Opener-Policy", - "Cross-Origin-Resource-Policy", - "Date", - "Device-Memory", - "Downlink", - "ECT", - "ETag", - "Expect", - "Expect-CT", - "Expires", - "Forwarded", - "From", - "Host", - "If-Match", - "If-Modified-Since", - "If-None-Match", - "If-Range", - "If-Unmodified-Since", - "Keep-Alive", - "Last-Modified", - "Link", - "Location", - "Max-Forwards", - "Origin", - "Permissions-Policy", - "Pragma", - "Proxy-Authenticate", - "Proxy-Authorization", - "RTT", - "Range", - "Referer", - "Referrer-Policy", - "Refresh", - "Retry-After", - "Sec-WebSocket-Accept", - "Sec-WebSocket-Extensions", - "Sec-WebSocket-Key", - "Sec-WebSocket-Protocol", - "Sec-WebSocket-Version", - "Server", - "Server-Timing", - "Service-Worker-Allowed", - "Service-Worker-Navigation-Preload", - "Set-Cookie", - "SourceMap", - "Strict-Transport-Security", - "Supports-Loading-Mode", - "TE", - "Timing-Allow-Origin", - "Trailer", - "Transfer-Encoding", - "Upgrade", - "Upgrade-Insecure-Requests", - "User-Agent", - "Vary", - "Via", - "WWW-Authenticate", - "X-Content-Type-Options", - "X-DNS-Prefetch-Control", - "X-Frame-Options", - "X-Permitted-Cross-Domain-Policies", - "X-Powered-By", - "X-Requested-With", - "X-XSS-Protection" - ]; + Object.setPrototypeOf(headerNameLowerCasedRecord, null); + var wellknownHeaderNameBuffers = {}; + Object.setPrototypeOf(wellknownHeaderNameBuffers, null); + function getHeaderNameAsBuffer(header) { + let buffer = wellknownHeaderNameBuffers[header]; + if (buffer === void 0) { + buffer = Buffer.from(header); + } + return buffer; + } for (let i = 0; i < wellknownHeaderNames.length; ++i) { const key = wellknownHeaderNames[i]; const lowerCasedKey = key.toLowerCase(); headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] = lowerCasedKey; } - Object.setPrototypeOf(headerNameLowerCasedRecord, null); module2.exports = { wellknownHeaderNames, - headerNameLowerCasedRecord + headerNameLowerCasedRecord, + getHeaderNameAsBuffer }; } }); @@ -1147,6 +1448,7 @@ var require_tree = __commonJS({ /** * @param {string} key * @param {any} value + * @returns {void} */ add(key, value) { const length = key.length; @@ -1187,7 +1489,7 @@ var require_tree = __commonJS({ } /** * @param {Uint8Array} key - * @return {TstNode | null} + * @returns {TstNode | null} */ search(key) { const keylength = key.length; @@ -1218,6 +1520,7 @@ var require_tree = __commonJS({ /** * @param {string} key * @param {any} value + * @returns {void} * */ insert(key, value) { if (this.node === null) { @@ -1228,7 +1531,7 @@ var require_tree = __commonJS({ } /** * @param {Uint8Array} key - * @return {any} + * @returns {any} */ lookup(key) { return this.node?.search(key)?.value ?? null; @@ -1255,14 +1558,13 @@ var require_util = __commonJS({ var { IncomingMessage } = require("node:http"); var stream2 = require("node:stream"); var net = require("node:net"); - var { Blob: Blob2 } = require("node:buffer"); - var nodeUtil = require("node:util"); var { stringify } = require("node:querystring"); var { EventEmitter: EE } = require("node:events"); - var { InvalidArgumentError } = require_errors(); + var timers = require_timers(); + var { InvalidArgumentError, ConnectTimeoutError } = require_errors(); var { headerNameLowerCasedRecord } = require_constants(); var { tree } = require_tree(); - var [nodeMajor, nodeMinor] = process.versions.node.split(".").map((v) => Number(v)); + var [nodeMajor, nodeMinor] = process.versions.node.split(".", 2).map((v) => Number(v)); var BodyAsyncIterable = class { constructor(body) { this[kBody] = body; @@ -1274,6 +1576,8 @@ var require_util = __commonJS({ yield* this[kBody]; } }; + function noop3() { + } function wrapRequestBody(body) { if (isStream2(body)) { if (bodyLength(body) === 0) { @@ -1290,21 +1594,21 @@ var require_util = __commonJS({ return body; } else if (body && typeof body.pipeTo === "function") { return new BodyAsyncIterable(body); + } else if (body && isFormDataLike(body)) { + return body; } else if (body && typeof body !== "string" && !ArrayBuffer.isView(body) && isIterable2(body)) { return new BodyAsyncIterable(body); } else { return body; } } - function nop() { - } function isStream2(obj) { return obj && typeof obj === "object" && typeof obj.pipe === "function" && typeof obj.on === "function"; } function isBlobLike(object2) { if (object2 === null) { return false; - } else if (object2 instanceof Blob2) { + } else if (object2 instanceof Blob) { return true; } else if (typeof object2 !== "object") { return false; @@ -1313,8 +1617,11 @@ var require_util = __commonJS({ return (sTag === "Blob" || sTag === "File") && ("stream" in object2 && typeof object2.stream === "function" || "arrayBuffer" in object2 && typeof object2.arrayBuffer === "function"); } } - function buildURL(url2, queryParams) { - if (url2.includes("?") || url2.includes("#")) { + function pathHasQueryOrFragment(url2) { + return url2.includes("?") || url2.includes("#"); + } + function serializePathWithQuery(url2, queryParams) { + if (pathHasQueryOrFragment(url2)) { throw new Error('Query params cannot be passed when url already contains "?" or "#".'); } const stringified = stringify(queryParams); @@ -1413,6 +1720,11 @@ var require_util = __commonJS({ function isIterable2(obj) { return !!(obj != null && (typeof obj[Symbol.iterator] === "function" || typeof obj[Symbol.asyncIterator] === "function")); } + function hasSafeIterator(obj) { + const prototype = Object.getPrototypeOf(obj); + const ownIterator = Object.prototype.hasOwnProperty.call(obj, Symbol.iterator); + return ownIterator || prototype != null && prototype !== Object.prototype && typeof obj[Symbol.iterator] === "function"; + } function bodyLength(body) { if (body == null) { return 0; @@ -1449,7 +1761,7 @@ var require_util = __commonJS({ } var KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/; function parseKeepAliveTimeout(val) { - const m = val.toString().match(KEEPALIVE_TIMEOUT_EXPR); + const m = val.match(KEEPALIVE_TIMEOUT_EXPR); return m ? parseInt(m[1], 10) * 1e3 : null; } function headerNameToString(value) { @@ -1463,60 +1775,64 @@ var require_util = __commonJS({ for (let i = 0; i < headers.length; i += 2) { const key = headerNameToString(headers[i]); let val = obj[key]; - if (val) { - if (typeof val === "string") { - val = [val]; - obj[key] = val; - } - val.push(headers[i + 1].toString("utf8")); - } else { - const headersValue = headers[i + 1]; - if (typeof headersValue === "string") { - obj[key] = headersValue; + if (val !== void 0) { + if (!Object.hasOwn(obj, key)) { + const headersValue = typeof headers[i + 1] === "string" ? headers[i + 1] : Array.isArray(headers[i + 1]) ? headers[i + 1].map((x) => x.toString("latin1")) : headers[i + 1].toString("latin1"); + if (key === "__proto__") { + Object.defineProperty(obj, key, { + value: headersValue, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = headersValue; + } } else { - obj[key] = Array.isArray(headersValue) ? headersValue.map((x) => x.toString("utf8")) : headersValue.toString("utf8"); + if (typeof val === "string") { + val = [val]; + obj[key] = val; + } + val.push(headers[i + 1].toString("latin1")); } + } else { + const headersValue = typeof headers[i + 1] === "string" ? headers[i + 1] : Array.isArray(headers[i + 1]) ? headers[i + 1].map((x) => x.toString("latin1")) : headers[i + 1].toString("latin1"); + obj[key] = headersValue; } } - if ("content-length" in obj && "content-disposition" in obj) { - obj["content-disposition"] = Buffer.from(obj["content-disposition"]).toString("latin1"); - } return obj; } function parseRawHeaders(headers) { - const len = headers.length; - const ret = new Array(len); - let hasContentLength = false; - let contentDispositionIdx = -1; + const headersLength = headers.length; + const ret = new Array(headersLength); let key; let val; - let kLen = 0; - for (let n = 0; n < headers.length; n += 2) { + for (let n = 0; n < headersLength; n += 2) { key = headers[n]; val = headers[n + 1]; typeof key !== "string" && (key = key.toString()); - typeof val !== "string" && (val = val.toString("utf8")); - kLen = key.length; - if (kLen === 14 && key[7] === "-" && (key === "content-length" || key.toLowerCase() === "content-length")) { - hasContentLength = true; - } else if (kLen === 19 && key[7] === "-" && (key === "content-disposition" || key.toLowerCase() === "content-disposition")) { - contentDispositionIdx = n + 1; - } + typeof val !== "string" && (val = val.toString("latin1")); ret[n] = key; ret[n + 1] = val; } - if (hasContentLength && contentDispositionIdx !== -1) { - ret[contentDispositionIdx] = Buffer.from(ret[contentDispositionIdx]).toString("latin1"); - } return ret; } + function encodeRawHeaders(headers) { + if (!Array.isArray(headers)) { + throw new TypeError("expected headers to be an array"); + } + return headers.map((x) => Buffer.from(x)); + } function isBuffer(buffer) { return buffer instanceof Uint8Array || Buffer.isBuffer(buffer); } - function validateHandler(handler2, method, upgrade) { + function assertRequestHandler(handler2, method, upgrade) { if (!handler2 || typeof handler2 !== "object") { throw new InvalidArgumentError("handler must be an object"); } + if (typeof handler2.onRequestStart === "function") { + return; + } if (typeof handler2.onConnect !== "function") { throw new InvalidArgumentError("invalid onConnect method"); } @@ -1545,12 +1861,6 @@ var require_util = __commonJS({ function isDisturbed(body) { return !!(body && (stream2.isDisturbed(body) || body[kBodyUsed])); } - function isErrored(body) { - return !!(body && stream2.isErrored(body)); - } - function isReadable(body) { - return !!(body && stream2.isReadable(body)); - } function getSocketInfo(socket) { return { localAddress: socket.localAddress, @@ -1567,26 +1877,28 @@ var require_util = __commonJS({ let iterator2; return new ReadableStream( { - async start() { + start() { iterator2 = iterable[Symbol.asyncIterator](); }, - async pull(controller) { - const { done, value } = await iterator2.next(); - if (done) { - queueMicrotask(() => { - controller.close(); - controller.byobRequest?.respond(0); - }); - } else { - const buf = Buffer.isBuffer(value) ? value : Buffer.from(value); - if (buf.byteLength) { - controller.enqueue(new Uint8Array(buf)); + pull(controller) { + return iterator2.next().then(({ done, value }) => { + if (done) { + return queueMicrotask(() => { + controller.close(); + controller.byobRequest?.respond(0); + }); + } else { + const buf = Buffer.isBuffer(value) ? value : Buffer.from(value); + if (buf.byteLength) { + return controller.enqueue(new Uint8Array(buf)); + } else { + return this.pull(controller); + } } - } - return controller.desiredSize > 0; + }); }, - async cancel(reason) { - await iterator2.return(); + cancel() { + return iterator2.return(); }, type: "bytes" } @@ -1600,47 +1912,292 @@ var require_util = __commonJS({ signal.addEventListener("abort", listener, { once: true }); return () => signal.removeEventListener("abort", listener); } - signal.addListener("abort", listener); + signal.once("abort", listener); return () => signal.removeListener("abort", listener); } - var hasToWellFormed = typeof String.prototype.toWellFormed === "function"; - var hasIsWellFormed = typeof String.prototype.isWellFormed === "function"; - function toUSVString(val) { - return hasToWellFormed ? `${val}`.toWellFormed() : nodeUtil.toUSVString(val); - } - function isUSVString(val) { - return hasIsWellFormed ? `${val}`.isWellFormed() : toUSVString(val) === `${val}`; - } + var validTokenChars = new Uint8Array([ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + // 0-15 + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + // 16-31 + 0, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + // 32-47 (!"#$%&'()*+,-./) + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + // 48-63 (0-9:;<=>?) + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + // 64-79 (@A-O) + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + // 80-95 (P-Z[\]^_) + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + // 96-111 (`a-o) + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 1, + 0, + 1, + 0, + // 112-127 (p-z{|}~) + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + // 128-143 + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + // 144-159 + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + // 160-175 + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + // 176-191 + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + // 192-207 + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + // 208-223 + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + // 224-239 + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + // 240-255 + ]); function isTokenCharCode(c) { - switch (c) { - case 34: - case 40: - case 41: - case 44: - case 47: - case 58: - case 59: - case 60: - case 61: - case 62: - case 63: - case 64: - case 91: - case 92: - case 93: - case 123: - case 125: - return false; - default: - return c >= 33 && c <= 126; - } + return validTokenChars[c] === 1; } + var tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/; function isValidHTTPToken(characters) { - if (characters.length === 0) { - return false; - } - for (let i = 0; i < characters.length; ++i) { - if (!isTokenCharCode(characters.charCodeAt(i))) { + if (characters.length >= 12) return tokenRegExp.test(characters); + if (characters.length === 0) return false; + for (let i = 0; i < characters.length; i++) { + if (validTokenChars[characters.charCodeAt(i)] !== 1) { return false; } } @@ -1650,9 +2207,10 @@ var require_util = __commonJS({ function isValidHeaderValue(characters) { return !headerCharRegex.test(characters); } + var rangeHeaderRegex = /^bytes (\d+)-(\d+)\/(\d+)?$/; function parseRangeHeader(range2) { if (range2 == null || range2 === "") return { start: 0, end: null, size: null }; - const m = range2 ? range2.match(/^bytes (\d+)-(\d+)\/(\d+)?$/) : null; + const m = range2 ? range2.match(rangeHeaderRegex) : null; return m ? { start: parseInt(m[1]), end: m[2] ? parseInt(m[2]) : null, @@ -1666,10 +2224,13 @@ var require_util = __commonJS({ return obj; } function removeAllListeners(obj) { - for (const [name, listener] of obj[kListeners] ?? []) { - obj.removeListener(name, listener); + if (obj[kListeners] != null) { + for (const [name, listener] of obj[kListeners]) { + obj.removeListener(name, listener); + } + obj[kListeners] = null; } - obj[kListeners] = null; + return obj; } function errorRequest2(client, request3, err) { try { @@ -1679,6 +2240,63 @@ var require_util = __commonJS({ client.emit("error", err2); } } + var setupConnectTimeout = process.platform === "win32" ? (socketWeakRef, opts) => { + if (!opts.timeout) { + return noop3; + } + let s1 = null; + let s2 = null; + const fastTimer = timers.setFastTimeout(() => { + s1 = setImmediate(() => { + s2 = setImmediate(() => onConnectTimeout(socketWeakRef.deref(), opts)); + }); + }, opts.timeout); + return () => { + timers.clearFastTimeout(fastTimer); + clearImmediate(s1); + clearImmediate(s2); + }; + } : (socketWeakRef, opts) => { + if (!opts.timeout) { + return noop3; + } + let s1 = null; + const fastTimer = timers.setFastTimeout(() => { + s1 = setImmediate(() => { + onConnectTimeout(socketWeakRef.deref(), opts); + }); + }, opts.timeout); + return () => { + timers.clearFastTimeout(fastTimer); + clearImmediate(s1); + }; + }; + function onConnectTimeout(socket, opts) { + if (socket == null) { + return; + } + let message = "Connect Timeout Error"; + if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) { + message += ` (attempted addresses: ${socket.autoSelectFamilyAttemptedAddresses.join(", ")},`; + } else { + message += ` (attempted address: ${opts.hostname}:${opts.port},`; + } + message += ` timeout: ${opts.timeout}ms)`; + destroy(socket, new ConnectTimeoutError(message)); + } + function getProtocolFromUrlString(urlString) { + if (urlString[0] === "h" && urlString[1] === "t" && urlString[2] === "t" && urlString[3] === "p") { + switch (urlString[4]) { + case ":": + return "http:"; + case "s": + if (urlString[5] === ":") { + return "https:"; + } + } + } + return urlString.slice(0, urlString.indexOf(":") + 1); + } var kEnumerableProperty = /* @__PURE__ */ Object.create(null); kEnumerableProperty.enumerable = true; var normalizedMethodRecordsBase = { @@ -1704,18 +2322,14 @@ var require_util = __commonJS({ Object.setPrototypeOf(normalizedMethodRecords, null); module2.exports = { kEnumerableProperty, - nop, isDisturbed, - isErrored, - isReadable, - toUSVString, - isUSVString, isBlobLike, parseOrigin, parseURL, getServerName, isStream: isStream2, isIterable: isIterable2, + hasSafeIterator, isAsyncIterable: isAsyncIterable2, isDestroyed, headerNameToString, @@ -1724,6 +2338,7 @@ var require_util = __commonJS({ removeAllListeners, errorRequest: errorRequest2, parseRawHeaders, + encodeRawHeaders, parseHeaders, parseKeepAliveTimeout, destroy, @@ -1731,10 +2346,11 @@ var require_util = __commonJS({ deepClone, ReadableStreamFrom, isBuffer, - validateHandler, + assertRequestHandler, getSocketInfo, isFormDataLike, - buildURL, + pathHasQueryOrFragment, + serializePathWithQuery, addAbortListener, isValidHTTPToken, isValidHeaderValue, @@ -1746,9 +2362,45 @@ var require_util = __commonJS({ isHttpOrHttpsPrefixed, nodeMajor, nodeMinor, - safeHTTPMethods: ["GET", "HEAD", "OPTIONS", "TRACE"], - wrapRequestBody + safeHTTPMethods: Object.freeze(["GET", "HEAD", "OPTIONS", "TRACE"]), + wrapRequestBody, + setupConnectTimeout, + getProtocolFromUrlString + }; + } +}); + +// node_modules/undici/lib/util/stats.js +var require_stats = __commonJS({ + "node_modules/undici/lib/util/stats.js"(exports2, module2) { + "use strict"; + var { + kConnected, + kPending, + kRunning, + kSize, + kFree, + kQueued + } = require_symbols(); + var ClientStats = class { + constructor(client) { + this.connected = client[kConnected]; + this.pending = client[kPending]; + this.running = client[kRunning]; + this.size = client[kSize]; + } + }; + var PoolStats = class { + constructor(pool) { + this.connected = pool[kConnected]; + this.free = pool[kFree]; + this.pending = pool[kPending]; + this.queued = pool[kQueued]; + this.running = pool[kRunning]; + this.size = pool[kSize]; + } }; + module2.exports = { ClientStats, PoolStats }; } }); @@ -1761,7 +2413,6 @@ var require_diagnostics = __commonJS({ var undiciDebugLog = util4.debuglog("undici"); var fetchDebuglog = util4.debuglog("fetch"); var websocketDebuglog = util4.debuglog("websocket"); - var isClientSet = false; var channels = { // Client beforeConnect: diagnosticsChannel.channel("undici:client:beforeConnect"), @@ -1771,6 +2422,8 @@ var require_diagnostics = __commonJS({ // Request create: diagnosticsChannel.channel("undici:request:create"), bodySent: diagnosticsChannel.channel("undici:request:bodySent"), + bodyChunkSent: diagnosticsChannel.channel("undici:request:bodyChunkSent"), + bodyChunkReceived: diagnosticsChannel.channel("undici:request:bodyChunkReceived"), headers: diagnosticsChannel.channel("undici:request:headers"), trailers: diagnosticsChannel.channel("undici:request:trailers"), error: diagnosticsChannel.channel("undici:request:error"), @@ -1779,118 +2432,58 @@ var require_diagnostics = __commonJS({ close: diagnosticsChannel.channel("undici:websocket:close"), socketError: diagnosticsChannel.channel("undici:websocket:socket_error"), ping: diagnosticsChannel.channel("undici:websocket:ping"), - pong: diagnosticsChannel.channel("undici:websocket:pong") + pong: diagnosticsChannel.channel("undici:websocket:pong"), + // ProxyAgent + proxyConnected: diagnosticsChannel.channel("undici:proxy:connected") }; - if (undiciDebugLog.enabled || fetchDebuglog.enabled) { - const debuglog = fetchDebuglog.enabled ? fetchDebuglog : undiciDebugLog; - diagnosticsChannel.channel("undici:client:beforeConnect").subscribe((evt) => { - const { - connectParams: { version, protocol, port, host } - } = evt; - debuglog( - "connecting to %s using %s%s", - `${host}${port ? `:${port}` : ""}`, - protocol, - version - ); - }); - diagnosticsChannel.channel("undici:client:connected").subscribe((evt) => { - const { - connectParams: { version, protocol, port, host } - } = evt; - debuglog( - "connected to %s using %s%s", - `${host}${port ? `:${port}` : ""}`, - protocol, - version - ); - }); - diagnosticsChannel.channel("undici:client:connectError").subscribe((evt) => { - const { - connectParams: { version, protocol, port, host }, - error: error3 - } = evt; - debuglog( - "connection to %s using %s%s errored - %s", - `${host}${port ? `:${port}` : ""}`, - protocol, - version, - error3.message - ); - }); - diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { - const { - request: { method, path: path30, origin } - } = evt; - debuglog("sending request to %s %s/%s", method, origin, path30); - }); - diagnosticsChannel.channel("undici:request:headers").subscribe((evt) => { - const { - request: { method, path: path30, origin }, - response: { statusCode } - } = evt; - debuglog( - "received response to %s %s/%s - HTTP %d", - method, - origin, - path30, - statusCode - ); - }); - diagnosticsChannel.channel("undici:request:trailers").subscribe((evt) => { - const { - request: { method, path: path30, origin } - } = evt; - debuglog("trailers received from %s %s/%s", method, origin, path30); - }); - diagnosticsChannel.channel("undici:request:error").subscribe((evt) => { - const { - request: { method, path: path30, origin }, - error: error3 - } = evt; - debuglog( - "request to %s %s/%s errored - %s", - method, - origin, - path30, - error3.message - ); - }); - isClientSet = true; - } - if (websocketDebuglog.enabled) { - if (!isClientSet) { - const debuglog = undiciDebugLog.enabled ? undiciDebugLog : websocketDebuglog; - diagnosticsChannel.channel("undici:client:beforeConnect").subscribe((evt) => { + var isTrackingClientEvents = false; + function trackClientEvents(debugLog = undiciDebugLog) { + if (isTrackingClientEvents) { + return; + } + if (channels.beforeConnect.hasSubscribers || channels.connected.hasSubscribers || channels.connectError.hasSubscribers || channels.sendHeaders.hasSubscribers) { + isTrackingClientEvents = true; + return; + } + isTrackingClientEvents = true; + diagnosticsChannel.subscribe( + "undici:client:beforeConnect", + (evt) => { const { connectParams: { version, protocol, port, host } } = evt; - debuglog( + debugLog( "connecting to %s%s using %s%s", host, port ? `:${port}` : "", protocol, version ); - }); - diagnosticsChannel.channel("undici:client:connected").subscribe((evt) => { + } + ); + diagnosticsChannel.subscribe( + "undici:client:connected", + (evt) => { const { connectParams: { version, protocol, port, host } } = evt; - debuglog( + debugLog( "connected to %s%s using %s%s", host, port ? `:${port}` : "", protocol, version ); - }); - diagnosticsChannel.channel("undici:client:connectError").subscribe((evt) => { + } + ); + diagnosticsChannel.subscribe( + "undici:client:connectError", + (evt) => { const { connectParams: { version, protocol, port, host }, error: error3 } = evt; - debuglog( + debugLog( "connection to %s%s using %s%s errored - %s", host, port ? `:${port}` : "", @@ -1898,38 +2491,129 @@ var require_diagnostics = __commonJS({ version, error3.message ); - }); - diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { + } + ); + diagnosticsChannel.subscribe( + "undici:client:sendHeaders", + (evt) => { const { request: { method, path: path30, origin } } = evt; - debuglog("sending request to %s %s/%s", method, origin, path30); - }); + debugLog("sending request to %s %s%s", method, origin, path30); + } + ); + } + var isTrackingRequestEvents = false; + function trackRequestEvents(debugLog = undiciDebugLog) { + if (isTrackingRequestEvents) { + return; } - diagnosticsChannel.channel("undici:websocket:open").subscribe((evt) => { - const { - address: { address, port } - } = evt; - websocketDebuglog("connection opened %s%s", address, port ? `:${port}` : ""); - }); - diagnosticsChannel.channel("undici:websocket:close").subscribe((evt) => { - const { websocket, code, reason } = evt; - websocketDebuglog( - "closed connection to %s - %s %s", - websocket.url, - code, - reason - ); - }); - diagnosticsChannel.channel("undici:websocket:socket_error").subscribe((err) => { - websocketDebuglog("connection errored - %s", err.message); - }); - diagnosticsChannel.channel("undici:websocket:ping").subscribe((evt) => { - websocketDebuglog("ping received"); - }); - diagnosticsChannel.channel("undici:websocket:pong").subscribe((evt) => { - websocketDebuglog("pong received"); - }); + if (channels.headers.hasSubscribers || channels.trailers.hasSubscribers || channels.error.hasSubscribers) { + isTrackingRequestEvents = true; + return; + } + isTrackingRequestEvents = true; + diagnosticsChannel.subscribe( + "undici:request:headers", + (evt) => { + const { + request: { method, path: path30, origin }, + response: { statusCode } + } = evt; + debugLog( + "received response to %s %s%s - HTTP %d", + method, + origin, + path30, + statusCode + ); + } + ); + diagnosticsChannel.subscribe( + "undici:request:trailers", + (evt) => { + const { + request: { method, path: path30, origin } + } = evt; + debugLog("trailers received from %s %s%s", method, origin, path30); + } + ); + diagnosticsChannel.subscribe( + "undici:request:error", + (evt) => { + const { + request: { method, path: path30, origin }, + error: error3 + } = evt; + debugLog( + "request to %s %s%s errored - %s", + method, + origin, + path30, + error3.message + ); + } + ); + } + var isTrackingWebSocketEvents = false; + function trackWebSocketEvents(debugLog = websocketDebuglog) { + if (isTrackingWebSocketEvents) { + return; + } + if (channels.open.hasSubscribers || channels.close.hasSubscribers || channels.socketError.hasSubscribers || channels.ping.hasSubscribers || channels.pong.hasSubscribers) { + isTrackingWebSocketEvents = true; + return; + } + isTrackingWebSocketEvents = true; + diagnosticsChannel.subscribe( + "undici:websocket:open", + (evt) => { + if (evt.address != null) { + const { address, port } = evt.address; + debugLog("connection opened %s%s", address, port ? `:${port}` : ""); + } else { + debugLog("connection opened"); + } + } + ); + diagnosticsChannel.subscribe( + "undici:websocket:close", + (evt) => { + const { websocket, code, reason } = evt; + debugLog( + "closed connection to %s - %s %s", + websocket.url, + code, + reason + ); + } + ); + diagnosticsChannel.subscribe( + "undici:websocket:socket_error", + (err) => { + debugLog("connection errored - %s", err.message); + } + ); + diagnosticsChannel.subscribe( + "undici:websocket:ping", + (evt) => { + debugLog("ping received"); + } + ); + diagnosticsChannel.subscribe( + "undici:websocket:pong", + (evt) => { + debugLog("pong received"); + } + ); + } + if (undiciDebugLog.enabled || fetchDebuglog.enabled) { + trackClientEvents(fetchDebuglog.enabled ? fetchDebuglog : undiciDebugLog); + trackRequestEvents(fetchDebuglog.enabled ? fetchDebuglog : undiciDebugLog); + } + if (websocketDebuglog.enabled) { + trackClientEvents(undiciDebugLog.enabled ? undiciDebugLog : websocketDebuglog); + trackWebSocketEvents(websocketDebuglog); } module2.exports = { channels @@ -1954,15 +2638,29 @@ var require_request = __commonJS({ isBuffer, isFormDataLike, isIterable: isIterable2, + hasSafeIterator, isBlobLike, - buildURL, - validateHandler, + serializePathWithQuery, + assertRequestHandler, getServerName, - normalizedMethodRecords + normalizedMethodRecords, + getProtocolFromUrlString } = require_util(); var { channels } = require_diagnostics(); var { headerNameLowerCasedRecord } = require_constants(); var invalidPathRegex = /[^\u0021-\u00ff]/; + function isValidContentLengthHeaderValue(val) { + if (typeof val !== "string" || val.length === 0) { + return false; + } + for (let i = 0; i < val.length; i++) { + const charCode = val.charCodeAt(i); + if (charCode < 48 || charCode > 57) { + return false; + } + } + return true; + } var kHandler = /* @__PURE__ */ Symbol("handler"); var Request = class { constructor(origin, { @@ -1977,9 +2675,11 @@ var require_request = __commonJS({ headersTimeout, bodyTimeout, reset, - throwOnError, expectContinue, - servername + servername, + throwOnError, + maxRedirections, + typeOfService }, handler2) { if (typeof path30 !== "string") { throw new InvalidArgumentError("path must be a string"); @@ -2011,10 +2711,19 @@ var require_request = __commonJS({ if (expectContinue != null && typeof expectContinue !== "boolean") { throw new InvalidArgumentError("invalid expectContinue"); } + if (throwOnError != null) { + throw new InvalidArgumentError("invalid throwOnError"); + } + if (maxRedirections != null && maxRedirections !== 0) { + throw new InvalidArgumentError("maxRedirections is not supported, use the redirect interceptor"); + } + if (typeOfService != null && (!Number.isInteger(typeOfService) || typeOfService < 0 || typeOfService > 255)) { + throw new InvalidArgumentError("typeOfService must be an integer between 0 and 255"); + } this.headersTimeout = headersTimeout; this.bodyTimeout = bodyTimeout; - this.throwOnError = throwOnError === true; this.method = method; + this.typeOfService = typeOfService ?? 0; this.abort = null; if (body == null) { this.body = null; @@ -2051,10 +2760,11 @@ var require_request = __commonJS({ this.completed = false; this.aborted = false; this.upgrade = upgrade || null; - this.path = query ? buildURL(path30, query) : path30; + this.path = query ? serializePathWithQuery(path30, query) : path30; this.origin = origin; + this.protocol = getProtocolFromUrlString(origin); this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent; - this.blocking = blocking == null ? false : blocking; + this.blocking = blocking ?? this.method !== "HEAD"; this.reset = reset == null ? null : reset; this.host = null; this.contentLength = null; @@ -2069,7 +2779,7 @@ var require_request = __commonJS({ processHeader(this, headers[i], headers[i + 1]); } } else if (headers && typeof headers === "object") { - if (headers[Symbol.iterator]) { + if (hasSafeIterator(headers)) { for (const header of headers) { if (!Array.isArray(header) || header.length !== 2) { throw new InvalidArgumentError("headers must be in key-value pair format"); @@ -2085,14 +2795,17 @@ var require_request = __commonJS({ } else if (headers != null) { throw new InvalidArgumentError("headers must be an object or an array"); } - validateHandler(handler2, method, upgrade); - this.servername = servername || getServerName(this.host); + assertRequestHandler(handler2, method, upgrade); + this.servername = servername || getServerName(this.host) || null; this[kHandler] = handler2; if (channels.create.hasSubscribers) { channels.create.publish({ request: this }); } } onBodySent(chunk) { + if (channels.bodyChunkSent.hasSubscribers) { + channels.bodyChunkSent.publish({ request: this, chunk }); + } if (this[kHandler].onBodySent) { try { return this[kHandler].onBodySent(chunk); @@ -2141,6 +2854,9 @@ var require_request = __commonJS({ onData(chunk) { assert(!this.aborted); assert(!this.completed); + if (channels.bodyChunkReceived.hasSubscribers) { + channels.bodyChunkReceived.publish({ request: this, chunk }); + } try { return this[kHandler].onData(chunk); } catch (err) { @@ -2148,14 +2864,32 @@ var require_request = __commonJS({ return false; } } - onUpgrade(statusCode, headers, socket) { + /** + * @param {number} statusCode + * @param {Buffer[]|string[]} headers + * @param {import('node:stream').Duplex} socket + * @param {string} [statusText] + */ + onUpgrade(statusCode, headers, socket, statusText = "") { + this.onFinally(); assert(!this.aborted); assert(!this.completed); - return this[kHandler].onUpgrade(statusCode, headers, socket); + if (channels.headers.hasSubscribers) { + channels.headers.publish({ request: this, response: { statusCode, headers, statusText } }); + } + const result = this[kHandler].onUpgrade(statusCode, headers, socket); + if (!this.aborted) { + this.completed = true; + if (channels.trailers.hasSubscribers) { + channels.trailers.publish({ request: this, trailers: [] }); + } + } + return result; } onComplete(trailers) { this.onFinally(); assert(!this.aborted); + assert(!this.completed); this.completed = true; if (channels.trailers.hasSubscribers) { channels.trailers.publish({ request: this, trailers }); @@ -2250,22 +2984,28 @@ var require_request = __commonJS({ if (request3.contentLength !== null) { throw new InvalidArgumentError("duplicate content-length header"); } - request3.contentLength = parseInt(val, 10); - if (!Number.isFinite(request3.contentLength)) { + if (!isValidContentLengthHeaderValue(val)) { throw new InvalidArgumentError("invalid content-length header"); } + request3.contentLength = parseInt(val, 10); } else if (request3.contentType === null && headerName === "content-type") { request3.contentType = val; request3.headers.push(key, val); } else if (headerName === "transfer-encoding" || headerName === "keep-alive" || headerName === "upgrade") { throw new InvalidArgumentError(`invalid ${headerName} header`); } else if (headerName === "connection") { - const value = typeof val === "string" ? val.toLowerCase() : null; - if (value !== "close" && value !== "keep-alive") { + const value = typeof val === "string" ? val : null; + if (value === null) { throw new InvalidArgumentError("invalid connection header"); } - if (value === "close") { - request3.reset = true; + for (const token of value.toLowerCase().split(",")) { + const trimmed = token.trim(); + if (!isValidHTTPToken(trimmed)) { + throw new InvalidArgumentError("invalid connection header"); + } + if (trimmed === "close") { + request3.reset = true; + } } } else if (headerName === "expect") { throw new NotSupportedError("expect header not supported"); @@ -2277,11 +3017,96 @@ var require_request = __commonJS({ } }); +// node_modules/undici/lib/handler/wrap-handler.js +var require_wrap_handler = __commonJS({ + "node_modules/undici/lib/handler/wrap-handler.js"(exports2, module2) { + "use strict"; + var { InvalidArgumentError } = require_errors(); + module2.exports = class WrapHandler { + #handler; + constructor(handler2) { + this.#handler = handler2; + } + static wrap(handler2) { + return handler2.onRequestStart ? handler2 : new WrapHandler(handler2); + } + // Unwrap Interface + onConnect(abort, context5) { + return this.#handler.onConnect?.(abort, context5); + } + onResponseStarted() { + return this.#handler.onResponseStarted?.(); + } + onHeaders(statusCode, rawHeaders, resume, statusMessage) { + return this.#handler.onHeaders?.(statusCode, rawHeaders, resume, statusMessage); + } + onUpgrade(statusCode, rawHeaders, socket) { + return this.#handler.onUpgrade?.(statusCode, rawHeaders, socket); + } + onData(data) { + return this.#handler.onData?.(data); + } + onComplete(trailers) { + return this.#handler.onComplete?.(trailers); + } + onError(err) { + if (!this.#handler.onError) { + throw err; + } + return this.#handler.onError?.(err); + } + // Wrap Interface + onRequestStart(controller, context5) { + this.#handler.onConnect?.((reason) => controller.abort(reason), context5); + } + onRequestUpgrade(controller, statusCode, headers, socket) { + const rawHeaders = []; + for (const [key, val] of Object.entries(headers)) { + rawHeaders.push(Buffer.from(key, "latin1"), toRawHeaderValue(val)); + } + this.#handler.onUpgrade?.(statusCode, rawHeaders, socket); + } + onResponseStart(controller, statusCode, headers, statusMessage) { + const rawHeaders = []; + for (const [key, val] of Object.entries(headers)) { + rawHeaders.push(Buffer.from(key, "latin1"), toRawHeaderValue(val)); + } + if (this.#handler.onHeaders?.(statusCode, rawHeaders, () => controller.resume(), statusMessage) === false) { + controller.pause(); + } + } + onResponseData(controller, data) { + if (this.#handler.onData?.(data) === false) { + controller.pause(); + } + } + onResponseEnd(controller, trailers) { + const rawTrailers = []; + for (const [key, val] of Object.entries(trailers)) { + rawTrailers.push(Buffer.from(key, "latin1"), toRawHeaderValue(val)); + } + this.#handler.onComplete?.(rawTrailers); + } + onResponseError(controller, err) { + if (!this.#handler.onError) { + throw new InvalidArgumentError("invalid onError method"); + } + this.#handler.onError?.(err); + } + }; + function toRawHeaderValue(value) { + return Array.isArray(value) ? value.map((item) => Buffer.from(item, "latin1")) : Buffer.from(value, "latin1"); + } + } +}); + // node_modules/undici/lib/dispatcher/dispatcher.js var require_dispatcher = __commonJS({ "node_modules/undici/lib/dispatcher/dispatcher.js"(exports2, module2) { "use strict"; var EventEmitter2 = require("node:events"); + var WrapHandler = require_wrap_handler(); + var wrapInterceptor = (dispatch) => (opts, handler2) => dispatch(opts, WrapHandler.wrap(handler2)); var Dispatcher = class extends EventEmitter2 { dispatch() { throw new Error("not implemented"); @@ -2303,32 +3128,105 @@ var require_dispatcher = __commonJS({ throw new TypeError(`invalid interceptor, expected function received ${typeof interceptor}`); } dispatch = interceptor(dispatch); + dispatch = wrapInterceptor(dispatch); if (dispatch == null || typeof dispatch !== "function" || dispatch.length !== 2) { throw new TypeError("invalid interceptor"); } } - return new ComposedDispatcher(this, dispatch); + return new Proxy(this, { + get: (target, key) => key === "dispatch" ? dispatch : target[key] + }); } }; - var ComposedDispatcher = class extends Dispatcher { - #dispatcher = null; - #dispatch = null; - constructor(dispatcher, dispatch) { - super(); - this.#dispatcher = dispatcher; - this.#dispatch = dispatch; + module2.exports = Dispatcher; + } +}); + +// node_modules/undici/lib/handler/unwrap-handler.js +var require_unwrap_handler = __commonJS({ + "node_modules/undici/lib/handler/unwrap-handler.js"(exports2, module2) { + "use strict"; + var { parseHeaders } = require_util(); + var { InvalidArgumentError } = require_errors(); + var kResume = /* @__PURE__ */ Symbol("resume"); + var UnwrapController = class { + #paused = false; + #reason = null; + #aborted = false; + #abort; + [kResume] = null; + rawHeaders = null; + rawTrailers = null; + constructor(abort) { + this.#abort = abort; + } + pause() { + this.#paused = true; + } + resume() { + if (this.#paused) { + this.#paused = false; + this[kResume]?.(); + } } - dispatch(...args) { - this.#dispatch(...args); + abort(reason) { + if (!this.#aborted) { + this.#aborted = true; + this.#reason = reason; + this.#abort(reason); + } + } + get aborted() { + return this.#aborted; } - close(...args) { - return this.#dispatcher.close(...args); + get reason() { + return this.#reason; } - destroy(...args) { - return this.#dispatcher.destroy(...args); + get paused() { + return this.#paused; + } + }; + module2.exports = class UnwrapHandler { + #handler; + #controller; + constructor(handler2) { + this.#handler = handler2; + } + static unwrap(handler2) { + return !handler2.onRequestStart ? handler2 : new UnwrapHandler(handler2); + } + onConnect(abort, context5) { + this.#controller = new UnwrapController(abort); + this.#handler.onRequestStart?.(this.#controller, context5); + } + onResponseStarted() { + return this.#handler.onResponseStarted?.(); + } + onUpgrade(statusCode, rawHeaders, socket) { + this.#controller.rawHeaders = rawHeaders; + this.#handler.onRequestUpgrade?.(this.#controller, statusCode, parseHeaders(rawHeaders), socket); + } + onHeaders(statusCode, rawHeaders, resume, statusMessage) { + this.#controller[kResume] = resume; + this.#controller.rawHeaders = rawHeaders; + this.#handler.onResponseStart?.(this.#controller, statusCode, parseHeaders(rawHeaders), statusMessage); + return !this.#controller.paused; + } + onData(data) { + this.#handler.onResponseData?.(this.#controller, data); + return !this.#controller.paused; + } + onComplete(rawTrailers) { + this.#controller.rawTrailers = rawTrailers; + this.#handler.onResponseEnd?.(this.#controller, parseHeaders(rawTrailers)); + } + onError(err) { + if (!this.#handler.onResponseError) { + throw new InvalidArgumentError("invalid onError method"); + } + this.#handler.onResponseError?.(this.#controller, err); } }; - module2.exports = Dispatcher; } }); @@ -2336,52 +3234,62 @@ var require_dispatcher = __commonJS({ var require_dispatcher_base = __commonJS({ "node_modules/undici/lib/dispatcher/dispatcher-base.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var Dispatcher = require_dispatcher(); + var UnwrapHandler = require_unwrap_handler(); var { ClientDestroyedError, ClientClosedError, InvalidArgumentError } = require_errors(); - var { kDestroy, kClose, kClosed, kDestroyed, kDispatch, kInterceptors } = require_symbols(); + var { kDestroy, kClose, kClosed, kDestroyed, kDispatch } = require_symbols(); var kOnDestroyed = /* @__PURE__ */ Symbol("onDestroyed"); var kOnClosed = /* @__PURE__ */ Symbol("onClosed"); - var kInterceptedDispatch = /* @__PURE__ */ Symbol("Intercepted Dispatch"); var kWebSocketOptions = /* @__PURE__ */ Symbol("webSocketOptions"); + var kEventSourceOptions = /* @__PURE__ */ Symbol("eventSourceOptions"); var DispatcherBase = class extends Dispatcher { + /** @type {boolean} */ + [kDestroyed] = false; + /** @type {Array|null} */ + [kOnClosed] = null; + /** + * @param {import('../../types/dispatcher').DispatcherOptions} [opts] + */ constructor(opts) { super(); - this[kDestroyed] = false; - this[kOnDestroyed] = null; - this[kClosed] = false; - this[kOnClosed] = []; this[kWebSocketOptions] = opts?.webSocket ?? {}; + this[kEventSourceOptions] = opts?.eventSource ?? {}; } + /** + * @returns {import('../../types/dispatcher').WebSocketOptions} + */ get webSocketOptions() { return { maxFragments: this[kWebSocketOptions].maxFragments ?? 131072, maxPayloadSize: this[kWebSocketOptions].maxPayloadSize ?? 128 * 1024 * 1024 + // 128 MB default + }; + } + /** + * @returns {import('../../types/client').Client.EventSourceOptions} + */ + get eventSourceOptions() { + return { + maxEventSize: this[kEventSourceOptions].maxEventSize ?? buffer.kStringMaxLength }; } + /** @returns {boolean} */ get destroyed() { return this[kDestroyed]; } + /** @returns {boolean} */ get closed() { return this[kClosed]; } - get interceptors() { - return this[kInterceptors]; - } - set interceptors(newInterceptors) { - if (newInterceptors) { - for (let i = newInterceptors.length - 1; i >= 0; i--) { - const interceptor = this[kInterceptors][i]; - if (typeof interceptor !== "function") { - throw new InvalidArgumentError("interceptor must be an function"); - } - } - } - this[kInterceptors] = newInterceptors; - } close(callback) { if (callback === void 0) { return new Promise((resolve15, reject) => { @@ -2394,7 +3302,8 @@ var require_dispatcher_base = __commonJS({ throw new InvalidArgumentError("invalid callback"); } if (this[kDestroyed]) { - queueMicrotask(() => callback(new ClientDestroyedError(), null)); + const err = new ClientDestroyedError(); + queueMicrotask(() => callback(err, null)); return; } if (this[kClosed]) { @@ -2406,6 +3315,7 @@ var require_dispatcher_base = __commonJS({ return; } this[kClosed] = true; + this[kOnClosed] ??= []; this[kOnClosed].push(callback); const onClosed = () => { const callbacks = this[kOnClosed]; @@ -2414,9 +3324,7 @@ var require_dispatcher_base = __commonJS({ callbacks[i](null, null); } }; - this[kClose]().then(() => this.destroy()).then(() => { - queueMicrotask(onClosed); - }); + this[kClose]().then(() => this.destroy()).then(() => queueMicrotask(onClosed)); } destroy(err, callback) { if (typeof err === "function") { @@ -2426,10 +3334,7 @@ var require_dispatcher_base = __commonJS({ if (callback === void 0) { return new Promise((resolve15, reject) => { this.destroy(err, (err2, data) => { - return err2 ? ( - /* istanbul ignore next: should never error */ - reject(err2) - ) : resolve15(data); + return err2 ? reject(err2) : resolve15(data); }); }); } @@ -2448,7 +3353,7 @@ var require_dispatcher_base = __commonJS({ err = new ClientDestroyedError(); } this[kDestroyed] = true; - this[kOnDestroyed] = this[kOnDestroyed] || []; + this[kOnDestroyed] ??= []; this[kOnDestroyed].push(callback); const onDestroyed = () => { const callbacks = this[kOnDestroyed]; @@ -2457,26 +3362,13 @@ var require_dispatcher_base = __commonJS({ callbacks[i](null, null); } }; - this[kDestroy](err).then(() => { - queueMicrotask(onDestroyed); - }); - } - [kInterceptedDispatch](opts, handler2) { - if (!this[kInterceptors] || this[kInterceptors].length === 0) { - this[kInterceptedDispatch] = this[kDispatch]; - return this[kDispatch](opts, handler2); - } - let dispatch = this[kDispatch].bind(this); - for (let i = this[kInterceptors].length - 1; i >= 0; i--) { - dispatch = this[kInterceptors][i](dispatch); - } - this[kInterceptedDispatch] = dispatch; - return dispatch(opts, handler2); + this[kDestroy](err).then(() => queueMicrotask(onDestroyed)); } dispatch(opts, handler2) { if (!handler2 || typeof handler2 !== "object") { throw new InvalidArgumentError("handler must be an object"); } + handler2 = UnwrapHandler.unwrap(handler2); try { if (!opts || typeof opts !== "object") { throw new InvalidArgumentError("opts must be an object."); @@ -2487,10 +3379,10 @@ var require_dispatcher_base = __commonJS({ if (this[kClosed]) { throw new ClientClosedError(); } - return this[kInterceptedDispatch](opts, handler2); + return this[kDispatch](opts, handler2); } catch (err) { if (typeof handler2.onError !== "function") { - throw new InvalidArgumentError("invalid onError method"); + throw err; } handler2.onError(err); return false; @@ -2501,237 +3393,6 @@ var require_dispatcher_base = __commonJS({ } }); -// node_modules/undici/lib/util/timers.js -var require_timers = __commonJS({ - "node_modules/undici/lib/util/timers.js"(exports2, module2) { - "use strict"; - var fastNow = 0; - var RESOLUTION_MS = 1e3; - var TICK_MS = (RESOLUTION_MS >> 1) - 1; - var fastNowTimeout; - var kFastTimer = /* @__PURE__ */ Symbol("kFastTimer"); - var fastTimers = []; - var NOT_IN_LIST = -2; - var TO_BE_CLEARED = -1; - var PENDING = 0; - var ACTIVE = 1; - function onTick() { - fastNow += TICK_MS; - let idx = 0; - let len = fastTimers.length; - while (idx < len) { - const timer = fastTimers[idx]; - if (timer._state === PENDING) { - timer._idleStart = fastNow - TICK_MS; - timer._state = ACTIVE; - } else if (timer._state === ACTIVE && fastNow >= timer._idleStart + timer._idleTimeout) { - timer._state = TO_BE_CLEARED; - timer._idleStart = -1; - timer._onTimeout(timer._timerArg); - } - if (timer._state === TO_BE_CLEARED) { - timer._state = NOT_IN_LIST; - if (--len !== 0) { - fastTimers[idx] = fastTimers[len]; - } - } else { - ++idx; - } - } - fastTimers.length = len; - if (fastTimers.length !== 0) { - refreshTimeout(); - } - } - function refreshTimeout() { - if (fastNowTimeout) { - fastNowTimeout.refresh(); - } else { - clearTimeout(fastNowTimeout); - fastNowTimeout = setTimeout(onTick, TICK_MS); - if (fastNowTimeout.unref) { - fastNowTimeout.unref(); - } - } - } - var FastTimer = class { - [kFastTimer] = true; - /** - * The state of the timer, which can be one of the following: - * - NOT_IN_LIST (-2) - * - TO_BE_CLEARED (-1) - * - PENDING (0) - * - ACTIVE (1) - * - * @type {-2|-1|0|1} - * @private - */ - _state = NOT_IN_LIST; - /** - * The number of milliseconds to wait before calling the callback. - * - * @type {number} - * @private - */ - _idleTimeout = -1; - /** - * The time in milliseconds when the timer was started. This value is used to - * calculate when the timer should expire. - * - * @type {number} - * @default -1 - * @private - */ - _idleStart = -1; - /** - * The function to be executed when the timer expires. - * @type {Function} - * @private - */ - _onTimeout; - /** - * The argument to be passed to the callback when the timer expires. - * - * @type {*} - * @private - */ - _timerArg; - /** - * @constructor - * @param {Function} callback A function to be executed after the timer - * expires. - * @param {number} delay The time, in milliseconds that the timer should wait - * before the specified function or code is executed. - * @param {*} arg - */ - constructor(callback, delay2, arg) { - this._onTimeout = callback; - this._idleTimeout = delay2; - this._timerArg = arg; - this.refresh(); - } - /** - * Sets the timer's start time to the current time, and reschedules the timer - * to call its callback at the previously specified duration adjusted to the - * current time. - * Using this on a timer that has already called its callback will reactivate - * the timer. - * - * @returns {void} - */ - refresh() { - if (this._state === NOT_IN_LIST) { - fastTimers.push(this); - } - if (!fastNowTimeout || fastTimers.length === 1) { - refreshTimeout(); - } - this._state = PENDING; - } - /** - * The `clear` method cancels the timer, preventing it from executing. - * - * @returns {void} - * @private - */ - clear() { - this._state = TO_BE_CLEARED; - this._idleStart = -1; - } - }; - module2.exports = { - /** - * The setTimeout() method sets a timer which executes a function once the - * timer expires. - * @param {Function} callback A function to be executed after the timer - * expires. - * @param {number} delay The time, in milliseconds that the timer should - * wait before the specified function or code is executed. - * @param {*} [arg] An optional argument to be passed to the callback function - * when the timer expires. - * @returns {NodeJS.Timeout|FastTimer} - */ - setTimeout(callback, delay2, arg) { - return delay2 <= RESOLUTION_MS ? setTimeout(callback, delay2, arg) : new FastTimer(callback, delay2, arg); - }, - /** - * The clearTimeout method cancels an instantiated Timer previously created - * by calling setTimeout. - * - * @param {NodeJS.Timeout|FastTimer} timeout - */ - clearTimeout(timeout) { - if (timeout[kFastTimer]) { - timeout.clear(); - } else { - clearTimeout(timeout); - } - }, - /** - * The setFastTimeout() method sets a fastTimer which executes a function once - * the timer expires. - * @param {Function} callback A function to be executed after the timer - * expires. - * @param {number} delay The time, in milliseconds that the timer should - * wait before the specified function or code is executed. - * @param {*} [arg] An optional argument to be passed to the callback function - * when the timer expires. - * @returns {FastTimer} - */ - setFastTimeout(callback, delay2, arg) { - return new FastTimer(callback, delay2, arg); - }, - /** - * The clearTimeout method cancels an instantiated FastTimer previously - * created by calling setFastTimeout. - * - * @param {FastTimer} timeout - */ - clearFastTimeout(timeout) { - timeout.clear(); - }, - /** - * The now method returns the value of the internal fast timer clock. - * - * @returns {number} - */ - now() { - return fastNow; - }, - /** - * Trigger the onTick function to process the fastTimers array. - * Exported for testing purposes only. - * Marking as deprecated to discourage any use outside of testing. - * @deprecated - * @param {number} [delay=0] The delay in milliseconds to add to the now value. - */ - tick(delay2 = 0) { - fastNow += delay2 - RESOLUTION_MS + 1; - onTick(); - onTick(); - }, - /** - * Reset FastTimers. - * Exported for testing purposes only. - * Marking as deprecated to discourage any use outside of testing. - * @deprecated - */ - reset() { - fastNow = 0; - fastTimers.length = 0; - clearTimeout(fastNowTimeout); - fastNowTimeout = null; - }, - /** - * Exporting for testing purposes only. - * Marking as deprecated to discourage any use outside of testing. - * @deprecated - */ - kFastTimer - }; - } -}); - // node_modules/undici/lib/core/connect.js var require_connect = __commonJS({ "node_modules/undici/lib/core/connect.js"(exports2, module2) { @@ -2739,61 +3400,53 @@ var require_connect = __commonJS({ var net = require("node:net"); var assert = require("node:assert"); var util4 = require_util(); - var { InvalidArgumentError, ConnectTimeoutError } = require_errors(); - var timers = require_timers(); - function noop3() { - } + var { InvalidArgumentError } = require_errors(); var tls; - var SessionCache; - if (global.FinalizationRegistry && !(process.env.NODE_V8_COVERAGE || process.env.UNDICI_NO_FG)) { - SessionCache = class WeakSessionCache { - constructor(maxCachedSessions) { - this._maxCachedSessions = maxCachedSessions; - this._sessionCache = /* @__PURE__ */ new Map(); - this._sessionRegistry = new global.FinalizationRegistry((key) => { - if (this._sessionCache.size < this._maxCachedSessions) { - return; - } - const ref = this._sessionCache.get(key); - if (ref !== void 0 && ref.deref() === void 0) { - this._sessionCache.delete(key); - } - }); - } - get(sessionKey) { - const ref = this._sessionCache.get(sessionKey); - return ref ? ref.deref() : null; - } - set(sessionKey, session) { - if (this._maxCachedSessions === 0) { + var SessionCache = class WeakSessionCache { + constructor(maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions; + this._sessionCache = /* @__PURE__ */ new Map(); + this._sessionRegistry = new FinalizationRegistry((key) => { + if (this._sessionCache.size < this._maxCachedSessions) { return; } - this._sessionCache.set(sessionKey, new WeakRef(session)); - this._sessionRegistry.register(session, sessionKey); - } - }; - } else { - SessionCache = class SimpleSessionCache { - constructor(maxCachedSessions) { - this._maxCachedSessions = maxCachedSessions; - this._sessionCache = /* @__PURE__ */ new Map(); - } - get(sessionKey) { - return this._sessionCache.get(sessionKey); + const ref = this._sessionCache.get(key); + if (ref !== void 0 && ref.deref() === void 0) { + this._sessionCache.delete(key); + } + }); + } + get(sessionKey) { + const ref = this._sessionCache.get(sessionKey); + return ref ? ref.deref() : null; + } + set(sessionKey, session) { + if (this._maxCachedSessions === 0) { + return; } - set(sessionKey, session) { - if (this._maxCachedSessions === 0) { - return; + if (this._sessionCache.has(sessionKey)) { + this._sessionCache.delete(sessionKey); + } else if (this._sessionCache.size >= this._maxCachedSessions) { + let evicted = false; + for (const [key, ref] of this._sessionCache) { + if (ref.deref() === void 0) { + this._sessionCache.delete(key); + evicted = true; + break; + } } - if (this._sessionCache.size >= this._maxCachedSessions) { - const { value: oldestKey } = this._sessionCache.keys().next(); - this._sessionCache.delete(oldestKey); + if (!evicted) { + const oldest = this._sessionCache.keys().next(); + if (!oldest.done) { + this._sessionCache.delete(oldest.value); + } } - this._sessionCache.set(sessionKey, session); } - }; - } - function buildConnector({ allowH2, maxCachedSessions, socketPath, timeout, session: customSession, ...opts }) { + this._sessionCache.set(sessionKey, new WeakRef(session)); + this._sessionRegistry.register(session, sessionKey); + } + }; + function buildConnector({ allowH2, useH2c, maxCachedSessions, socketPath, timeout, session: customSession, ...opts }) { if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) { throw new InvalidArgumentError("maxCachedSessions must be a positive integer or zero"); } @@ -2819,7 +3472,6 @@ var require_connect = __commonJS({ servername, session, localAddress, - // TODO(HTTP/2): Add support for h2c ALPNProtocols: allowH2 ? ["http/1.1", "h2"] : ["http/1.1"], socket: httpSocket, // upgrade socket connection @@ -2840,12 +3492,15 @@ var require_connect = __commonJS({ port, host: hostname }); + if (useH2c === true) { + socket.alpnProtocol = "h2"; + } } if (options.keepAlive == null || options.keepAlive) { const keepAliveInitialDelay = options.keepAliveInitialDelay === void 0 ? 6e4 : options.keepAliveInitialDelay; socket.setKeepAlive(true, keepAliveInitialDelay); } - const clearConnectTimeout = setupConnectTimeout(new WeakRef(socket), { timeout, hostname, port }); + const clearConnectTimeout = util4.setupConnectTimeout(new WeakRef(socket), { timeout, hostname, port }); socket.setNoDelay(true).once(protocol === "https:" ? "secureConnect" : "connect", function() { queueMicrotask(clearConnectTimeout); if (callback) { @@ -2864,50 +3519,6 @@ var require_connect = __commonJS({ return socket; }; } - var setupConnectTimeout = process.platform === "win32" ? (socketWeakRef, opts) => { - if (!opts.timeout) { - return noop3; - } - let s1 = null; - let s2 = null; - const fastTimer = timers.setFastTimeout(() => { - s1 = setImmediate(() => { - s2 = setImmediate(() => onConnectTimeout(socketWeakRef.deref(), opts)); - }); - }, opts.timeout); - return () => { - timers.clearFastTimeout(fastTimer); - clearImmediate(s1); - clearImmediate(s2); - }; - } : (socketWeakRef, opts) => { - if (!opts.timeout) { - return noop3; - } - let s1 = null; - const fastTimer = timers.setFastTimeout(() => { - s1 = setImmediate(() => { - onConnectTimeout(socketWeakRef.deref(), opts); - }); - }, opts.timeout); - return () => { - timers.clearFastTimeout(fastTimer); - clearImmediate(s1); - }; - }; - function onConnectTimeout(socket, opts) { - if (socket == null) { - return; - } - let message = "Connect Timeout Error"; - if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) { - message += ` (attempted addresses: ${socket.autoSelectFamilyAttemptedAddresses.join(", ")},`; - } else { - message += ` (attempted address: ${opts.hostname}:${opts.port},`; - } - message += ` timeout: ${opts.timeout}ms)`; - util4.destroy(socket, new ConnectTimeoutError(message)); - } module2.exports = buildConnector; } }); @@ -2917,18 +3528,14 @@ var require_utils2 = __commonJS({ "node_modules/undici/lib/llhttp/utils.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.enumToMap = void 0; - function enumToMap(obj) { - const res = {}; - Object.keys(obj).forEach((key) => { - const value = obj[key]; - if (typeof value === "number") { - res[key] = value; - } - }); - return res; - } exports2.enumToMap = enumToMap; + function enumToMap(obj, filter2 = [], exceptions = []) { + const emptyFilter = (filter2?.length ?? 0) === 0; + const emptyExceptions = (exceptions?.length ?? 0) === 0; + return Object.fromEntries(Object.entries(obj).filter(([, value]) => { + return typeof value === "number" && (emptyFilter || filter2.includes(value)) && (emptyExceptions || !exceptions.includes(value)); + })); + } } }); @@ -2937,180 +3544,453 @@ var require_constants2 = __commonJS({ "node_modules/undici/lib/llhttp/constants.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.SPECIAL_HEADERS = exports2.HEADER_STATE = exports2.MINOR = exports2.MAJOR = exports2.CONNECTION_TOKEN_CHARS = exports2.HEADER_CHARS = exports2.TOKEN = exports2.STRICT_TOKEN = exports2.HEX = exports2.URL_CHAR = exports2.STRICT_URL_CHAR = exports2.USERINFO_CHARS = exports2.MARK = exports2.ALPHANUM = exports2.NUM = exports2.HEX_MAP = exports2.NUM_MAP = exports2.ALPHA = exports2.FINISH = exports2.H_METHOD_MAP = exports2.METHOD_MAP = exports2.METHODS_RTSP = exports2.METHODS_ICE = exports2.METHODS_HTTP = exports2.METHODS = exports2.LENIENT_FLAGS = exports2.FLAGS = exports2.TYPE = exports2.ERROR = void 0; + exports2.SPECIAL_HEADERS = exports2.MINOR = exports2.MAJOR = exports2.HTAB_SP_VCHAR_OBS_TEXT = exports2.QUOTED_STRING = exports2.CONNECTION_TOKEN_CHARS = exports2.HEADER_CHARS = exports2.TOKEN = exports2.HEX = exports2.URL_CHAR = exports2.USERINFO_CHARS = exports2.MARK = exports2.ALPHANUM = exports2.NUM = exports2.HEX_MAP = exports2.NUM_MAP = exports2.ALPHA = exports2.STATUSES_HTTP = exports2.H_METHOD_MAP = exports2.METHOD_MAP = exports2.METHODS_RTSP = exports2.METHODS_ICE = exports2.METHODS_HTTP = exports2.HEADER_STATE = exports2.FINISH = exports2.STATUSES = exports2.METHODS = exports2.LENIENT_FLAGS = exports2.FLAGS = exports2.TYPE = exports2.ERROR = void 0; var utils_1 = require_utils2(); - var ERROR; - (function(ERROR2) { - ERROR2[ERROR2["OK"] = 0] = "OK"; - ERROR2[ERROR2["INTERNAL"] = 1] = "INTERNAL"; - ERROR2[ERROR2["STRICT"] = 2] = "STRICT"; - ERROR2[ERROR2["LF_EXPECTED"] = 3] = "LF_EXPECTED"; - ERROR2[ERROR2["UNEXPECTED_CONTENT_LENGTH"] = 4] = "UNEXPECTED_CONTENT_LENGTH"; - ERROR2[ERROR2["CLOSED_CONNECTION"] = 5] = "CLOSED_CONNECTION"; - ERROR2[ERROR2["INVALID_METHOD"] = 6] = "INVALID_METHOD"; - ERROR2[ERROR2["INVALID_URL"] = 7] = "INVALID_URL"; - ERROR2[ERROR2["INVALID_CONSTANT"] = 8] = "INVALID_CONSTANT"; - ERROR2[ERROR2["INVALID_VERSION"] = 9] = "INVALID_VERSION"; - ERROR2[ERROR2["INVALID_HEADER_TOKEN"] = 10] = "INVALID_HEADER_TOKEN"; - ERROR2[ERROR2["INVALID_CONTENT_LENGTH"] = 11] = "INVALID_CONTENT_LENGTH"; - ERROR2[ERROR2["INVALID_CHUNK_SIZE"] = 12] = "INVALID_CHUNK_SIZE"; - ERROR2[ERROR2["INVALID_STATUS"] = 13] = "INVALID_STATUS"; - ERROR2[ERROR2["INVALID_EOF_STATE"] = 14] = "INVALID_EOF_STATE"; - ERROR2[ERROR2["INVALID_TRANSFER_ENCODING"] = 15] = "INVALID_TRANSFER_ENCODING"; - ERROR2[ERROR2["CB_MESSAGE_BEGIN"] = 16] = "CB_MESSAGE_BEGIN"; - ERROR2[ERROR2["CB_HEADERS_COMPLETE"] = 17] = "CB_HEADERS_COMPLETE"; - ERROR2[ERROR2["CB_MESSAGE_COMPLETE"] = 18] = "CB_MESSAGE_COMPLETE"; - ERROR2[ERROR2["CB_CHUNK_HEADER"] = 19] = "CB_CHUNK_HEADER"; - ERROR2[ERROR2["CB_CHUNK_COMPLETE"] = 20] = "CB_CHUNK_COMPLETE"; - ERROR2[ERROR2["PAUSED"] = 21] = "PAUSED"; - ERROR2[ERROR2["PAUSED_UPGRADE"] = 22] = "PAUSED_UPGRADE"; - ERROR2[ERROR2["PAUSED_H2_UPGRADE"] = 23] = "PAUSED_H2_UPGRADE"; - ERROR2[ERROR2["USER"] = 24] = "USER"; - })(ERROR = exports2.ERROR || (exports2.ERROR = {})); - var TYPE; - (function(TYPE2) { - TYPE2[TYPE2["BOTH"] = 0] = "BOTH"; - TYPE2[TYPE2["REQUEST"] = 1] = "REQUEST"; - TYPE2[TYPE2["RESPONSE"] = 2] = "RESPONSE"; - })(TYPE = exports2.TYPE || (exports2.TYPE = {})); - var FLAGS; - (function(FLAGS2) { - FLAGS2[FLAGS2["CONNECTION_KEEP_ALIVE"] = 1] = "CONNECTION_KEEP_ALIVE"; - FLAGS2[FLAGS2["CONNECTION_CLOSE"] = 2] = "CONNECTION_CLOSE"; - FLAGS2[FLAGS2["CONNECTION_UPGRADE"] = 4] = "CONNECTION_UPGRADE"; - FLAGS2[FLAGS2["CHUNKED"] = 8] = "CHUNKED"; - FLAGS2[FLAGS2["UPGRADE"] = 16] = "UPGRADE"; - FLAGS2[FLAGS2["CONTENT_LENGTH"] = 32] = "CONTENT_LENGTH"; - FLAGS2[FLAGS2["SKIPBODY"] = 64] = "SKIPBODY"; - FLAGS2[FLAGS2["TRAILING"] = 128] = "TRAILING"; - FLAGS2[FLAGS2["TRANSFER_ENCODING"] = 512] = "TRANSFER_ENCODING"; - })(FLAGS = exports2.FLAGS || (exports2.FLAGS = {})); - var LENIENT_FLAGS; - (function(LENIENT_FLAGS2) { - LENIENT_FLAGS2[LENIENT_FLAGS2["HEADERS"] = 1] = "HEADERS"; - LENIENT_FLAGS2[LENIENT_FLAGS2["CHUNKED_LENGTH"] = 2] = "CHUNKED_LENGTH"; - LENIENT_FLAGS2[LENIENT_FLAGS2["KEEP_ALIVE"] = 4] = "KEEP_ALIVE"; - })(LENIENT_FLAGS = exports2.LENIENT_FLAGS || (exports2.LENIENT_FLAGS = {})); - var METHODS; - (function(METHODS2) { - METHODS2[METHODS2["DELETE"] = 0] = "DELETE"; - METHODS2[METHODS2["GET"] = 1] = "GET"; - METHODS2[METHODS2["HEAD"] = 2] = "HEAD"; - METHODS2[METHODS2["POST"] = 3] = "POST"; - METHODS2[METHODS2["PUT"] = 4] = "PUT"; - METHODS2[METHODS2["CONNECT"] = 5] = "CONNECT"; - METHODS2[METHODS2["OPTIONS"] = 6] = "OPTIONS"; - METHODS2[METHODS2["TRACE"] = 7] = "TRACE"; - METHODS2[METHODS2["COPY"] = 8] = "COPY"; - METHODS2[METHODS2["LOCK"] = 9] = "LOCK"; - METHODS2[METHODS2["MKCOL"] = 10] = "MKCOL"; - METHODS2[METHODS2["MOVE"] = 11] = "MOVE"; - METHODS2[METHODS2["PROPFIND"] = 12] = "PROPFIND"; - METHODS2[METHODS2["PROPPATCH"] = 13] = "PROPPATCH"; - METHODS2[METHODS2["SEARCH"] = 14] = "SEARCH"; - METHODS2[METHODS2["UNLOCK"] = 15] = "UNLOCK"; - METHODS2[METHODS2["BIND"] = 16] = "BIND"; - METHODS2[METHODS2["REBIND"] = 17] = "REBIND"; - METHODS2[METHODS2["UNBIND"] = 18] = "UNBIND"; - METHODS2[METHODS2["ACL"] = 19] = "ACL"; - METHODS2[METHODS2["REPORT"] = 20] = "REPORT"; - METHODS2[METHODS2["MKACTIVITY"] = 21] = "MKACTIVITY"; - METHODS2[METHODS2["CHECKOUT"] = 22] = "CHECKOUT"; - METHODS2[METHODS2["MERGE"] = 23] = "MERGE"; - METHODS2[METHODS2["M-SEARCH"] = 24] = "M-SEARCH"; - METHODS2[METHODS2["NOTIFY"] = 25] = "NOTIFY"; - METHODS2[METHODS2["SUBSCRIBE"] = 26] = "SUBSCRIBE"; - METHODS2[METHODS2["UNSUBSCRIBE"] = 27] = "UNSUBSCRIBE"; - METHODS2[METHODS2["PATCH"] = 28] = "PATCH"; - METHODS2[METHODS2["PURGE"] = 29] = "PURGE"; - METHODS2[METHODS2["MKCALENDAR"] = 30] = "MKCALENDAR"; - METHODS2[METHODS2["LINK"] = 31] = "LINK"; - METHODS2[METHODS2["UNLINK"] = 32] = "UNLINK"; - METHODS2[METHODS2["SOURCE"] = 33] = "SOURCE"; - METHODS2[METHODS2["PRI"] = 34] = "PRI"; - METHODS2[METHODS2["DESCRIBE"] = 35] = "DESCRIBE"; - METHODS2[METHODS2["ANNOUNCE"] = 36] = "ANNOUNCE"; - METHODS2[METHODS2["SETUP"] = 37] = "SETUP"; - METHODS2[METHODS2["PLAY"] = 38] = "PLAY"; - METHODS2[METHODS2["PAUSE"] = 39] = "PAUSE"; - METHODS2[METHODS2["TEARDOWN"] = 40] = "TEARDOWN"; - METHODS2[METHODS2["GET_PARAMETER"] = 41] = "GET_PARAMETER"; - METHODS2[METHODS2["SET_PARAMETER"] = 42] = "SET_PARAMETER"; - METHODS2[METHODS2["REDIRECT"] = 43] = "REDIRECT"; - METHODS2[METHODS2["RECORD"] = 44] = "RECORD"; - METHODS2[METHODS2["FLUSH"] = 45] = "FLUSH"; - })(METHODS = exports2.METHODS || (exports2.METHODS = {})); + exports2.ERROR = { + OK: 0, + INTERNAL: 1, + STRICT: 2, + CR_EXPECTED: 25, + LF_EXPECTED: 3, + UNEXPECTED_CONTENT_LENGTH: 4, + UNEXPECTED_SPACE: 30, + CLOSED_CONNECTION: 5, + INVALID_METHOD: 6, + INVALID_URL: 7, + INVALID_CONSTANT: 8, + INVALID_VERSION: 9, + INVALID_HEADER_TOKEN: 10, + INVALID_CONTENT_LENGTH: 11, + INVALID_CHUNK_SIZE: 12, + INVALID_STATUS: 13, + INVALID_EOF_STATE: 14, + INVALID_TRANSFER_ENCODING: 15, + CB_MESSAGE_BEGIN: 16, + CB_HEADERS_COMPLETE: 17, + CB_MESSAGE_COMPLETE: 18, + CB_CHUNK_HEADER: 19, + CB_CHUNK_COMPLETE: 20, + PAUSED: 21, + PAUSED_UPGRADE: 22, + PAUSED_H2_UPGRADE: 23, + USER: 24, + CB_URL_COMPLETE: 26, + CB_STATUS_COMPLETE: 27, + CB_METHOD_COMPLETE: 32, + CB_VERSION_COMPLETE: 33, + CB_HEADER_FIELD_COMPLETE: 28, + CB_HEADER_VALUE_COMPLETE: 29, + CB_CHUNK_EXTENSION_NAME_COMPLETE: 34, + CB_CHUNK_EXTENSION_VALUE_COMPLETE: 35, + CB_RESET: 31, + CB_PROTOCOL_COMPLETE: 38 + }; + exports2.TYPE = { + BOTH: 0, + // default + REQUEST: 1, + RESPONSE: 2 + }; + exports2.FLAGS = { + CONNECTION_KEEP_ALIVE: 1 << 0, + CONNECTION_CLOSE: 1 << 1, + CONNECTION_UPGRADE: 1 << 2, + CHUNKED: 1 << 3, + UPGRADE: 1 << 4, + CONTENT_LENGTH: 1 << 5, + SKIPBODY: 1 << 6, + TRAILING: 1 << 7, + // 1 << 8 is unused + TRANSFER_ENCODING: 1 << 9 + }; + exports2.LENIENT_FLAGS = { + HEADERS: 1 << 0, + CHUNKED_LENGTH: 1 << 1, + KEEP_ALIVE: 1 << 2, + TRANSFER_ENCODING: 1 << 3, + VERSION: 1 << 4, + DATA_AFTER_CLOSE: 1 << 5, + OPTIONAL_LF_AFTER_CR: 1 << 6, + OPTIONAL_CRLF_AFTER_CHUNK: 1 << 7, + OPTIONAL_CR_BEFORE_LF: 1 << 8, + SPACES_AFTER_CHUNK_SIZE: 1 << 9 + }; + exports2.METHODS = { + "DELETE": 0, + "GET": 1, + "HEAD": 2, + "POST": 3, + "PUT": 4, + /* pathological */ + "CONNECT": 5, + "OPTIONS": 6, + "TRACE": 7, + /* WebDAV */ + "COPY": 8, + "LOCK": 9, + "MKCOL": 10, + "MOVE": 11, + "PROPFIND": 12, + "PROPPATCH": 13, + "SEARCH": 14, + "UNLOCK": 15, + "BIND": 16, + "REBIND": 17, + "UNBIND": 18, + "ACL": 19, + /* subversion */ + "REPORT": 20, + "MKACTIVITY": 21, + "CHECKOUT": 22, + "MERGE": 23, + /* upnp */ + "M-SEARCH": 24, + "NOTIFY": 25, + "SUBSCRIBE": 26, + "UNSUBSCRIBE": 27, + /* RFC-5789 */ + "PATCH": 28, + "PURGE": 29, + /* CalDAV */ + "MKCALENDAR": 30, + /* RFC-2068, section 19.6.1.2 */ + "LINK": 31, + "UNLINK": 32, + /* icecast */ + "SOURCE": 33, + /* RFC-7540, section 11.6 */ + "PRI": 34, + /* RFC-2326 RTSP */ + "DESCRIBE": 35, + "ANNOUNCE": 36, + "SETUP": 37, + "PLAY": 38, + "PAUSE": 39, + "TEARDOWN": 40, + "GET_PARAMETER": 41, + "SET_PARAMETER": 42, + "REDIRECT": 43, + "RECORD": 44, + /* RAOP */ + "FLUSH": 45, + /* DRAFT https://www.ietf.org/archive/id/draft-ietf-httpbis-safe-method-w-body-02.html */ + "QUERY": 46 + }; + exports2.STATUSES = { + CONTINUE: 100, + SWITCHING_PROTOCOLS: 101, + PROCESSING: 102, + EARLY_HINTS: 103, + RESPONSE_IS_STALE: 110, + // Unofficial + REVALIDATION_FAILED: 111, + // Unofficial + DISCONNECTED_OPERATION: 112, + // Unofficial + HEURISTIC_EXPIRATION: 113, + // Unofficial + MISCELLANEOUS_WARNING: 199, + // Unofficial + OK: 200, + CREATED: 201, + ACCEPTED: 202, + NON_AUTHORITATIVE_INFORMATION: 203, + NO_CONTENT: 204, + RESET_CONTENT: 205, + PARTIAL_CONTENT: 206, + MULTI_STATUS: 207, + ALREADY_REPORTED: 208, + TRANSFORMATION_APPLIED: 214, + // Unofficial + IM_USED: 226, + MISCELLANEOUS_PERSISTENT_WARNING: 299, + // Unofficial + MULTIPLE_CHOICES: 300, + MOVED_PERMANENTLY: 301, + FOUND: 302, + SEE_OTHER: 303, + NOT_MODIFIED: 304, + USE_PROXY: 305, + SWITCH_PROXY: 306, + // No longer used + TEMPORARY_REDIRECT: 307, + PERMANENT_REDIRECT: 308, + BAD_REQUEST: 400, + UNAUTHORIZED: 401, + PAYMENT_REQUIRED: 402, + FORBIDDEN: 403, + NOT_FOUND: 404, + METHOD_NOT_ALLOWED: 405, + NOT_ACCEPTABLE: 406, + PROXY_AUTHENTICATION_REQUIRED: 407, + REQUEST_TIMEOUT: 408, + CONFLICT: 409, + GONE: 410, + LENGTH_REQUIRED: 411, + PRECONDITION_FAILED: 412, + PAYLOAD_TOO_LARGE: 413, + URI_TOO_LONG: 414, + UNSUPPORTED_MEDIA_TYPE: 415, + RANGE_NOT_SATISFIABLE: 416, + EXPECTATION_FAILED: 417, + IM_A_TEAPOT: 418, + PAGE_EXPIRED: 419, + // Unofficial + ENHANCE_YOUR_CALM: 420, + // Unofficial + MISDIRECTED_REQUEST: 421, + UNPROCESSABLE_ENTITY: 422, + LOCKED: 423, + FAILED_DEPENDENCY: 424, + TOO_EARLY: 425, + UPGRADE_REQUIRED: 426, + PRECONDITION_REQUIRED: 428, + TOO_MANY_REQUESTS: 429, + REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL: 430, + // Unofficial + REQUEST_HEADER_FIELDS_TOO_LARGE: 431, + LOGIN_TIMEOUT: 440, + // Unofficial + NO_RESPONSE: 444, + // Unofficial + RETRY_WITH: 449, + // Unofficial + BLOCKED_BY_PARENTAL_CONTROL: 450, + // Unofficial + UNAVAILABLE_FOR_LEGAL_REASONS: 451, + CLIENT_CLOSED_LOAD_BALANCED_REQUEST: 460, + // Unofficial + INVALID_X_FORWARDED_FOR: 463, + // Unofficial + REQUEST_HEADER_TOO_LARGE: 494, + // Unofficial + SSL_CERTIFICATE_ERROR: 495, + // Unofficial + SSL_CERTIFICATE_REQUIRED: 496, + // Unofficial + HTTP_REQUEST_SENT_TO_HTTPS_PORT: 497, + // Unofficial + INVALID_TOKEN: 498, + // Unofficial + CLIENT_CLOSED_REQUEST: 499, + // Unofficial + INTERNAL_SERVER_ERROR: 500, + NOT_IMPLEMENTED: 501, + BAD_GATEWAY: 502, + SERVICE_UNAVAILABLE: 503, + GATEWAY_TIMEOUT: 504, + HTTP_VERSION_NOT_SUPPORTED: 505, + VARIANT_ALSO_NEGOTIATES: 506, + INSUFFICIENT_STORAGE: 507, + LOOP_DETECTED: 508, + BANDWIDTH_LIMIT_EXCEEDED: 509, + NOT_EXTENDED: 510, + NETWORK_AUTHENTICATION_REQUIRED: 511, + WEB_SERVER_UNKNOWN_ERROR: 520, + // Unofficial + WEB_SERVER_IS_DOWN: 521, + // Unofficial + CONNECTION_TIMEOUT: 522, + // Unofficial + ORIGIN_IS_UNREACHABLE: 523, + // Unofficial + TIMEOUT_OCCURED: 524, + // Unofficial + SSL_HANDSHAKE_FAILED: 525, + // Unofficial + INVALID_SSL_CERTIFICATE: 526, + // Unofficial + RAILGUN_ERROR: 527, + // Unofficial + SITE_IS_OVERLOADED: 529, + // Unofficial + SITE_IS_FROZEN: 530, + // Unofficial + IDENTITY_PROVIDER_AUTHENTICATION_ERROR: 561, + // Unofficial + NETWORK_READ_TIMEOUT: 598, + // Unofficial + NETWORK_CONNECT_TIMEOUT: 599 + // Unofficial + }; + exports2.FINISH = { + SAFE: 0, + SAFE_WITH_CB: 1, + UNSAFE: 2 + }; + exports2.HEADER_STATE = { + GENERAL: 0, + CONNECTION: 1, + CONTENT_LENGTH: 2, + TRANSFER_ENCODING: 3, + UPGRADE: 4, + CONNECTION_KEEP_ALIVE: 5, + CONNECTION_CLOSE: 6, + CONNECTION_UPGRADE: 7, + TRANSFER_ENCODING_CHUNKED: 8 + }; exports2.METHODS_HTTP = [ - METHODS.DELETE, - METHODS.GET, - METHODS.HEAD, - METHODS.POST, - METHODS.PUT, - METHODS.CONNECT, - METHODS.OPTIONS, - METHODS.TRACE, - METHODS.COPY, - METHODS.LOCK, - METHODS.MKCOL, - METHODS.MOVE, - METHODS.PROPFIND, - METHODS.PROPPATCH, - METHODS.SEARCH, - METHODS.UNLOCK, - METHODS.BIND, - METHODS.REBIND, - METHODS.UNBIND, - METHODS.ACL, - METHODS.REPORT, - METHODS.MKACTIVITY, - METHODS.CHECKOUT, - METHODS.MERGE, - METHODS["M-SEARCH"], - METHODS.NOTIFY, - METHODS.SUBSCRIBE, - METHODS.UNSUBSCRIBE, - METHODS.PATCH, - METHODS.PURGE, - METHODS.MKCALENDAR, - METHODS.LINK, - METHODS.UNLINK, - METHODS.PRI, + exports2.METHODS.DELETE, + exports2.METHODS.GET, + exports2.METHODS.HEAD, + exports2.METHODS.POST, + exports2.METHODS.PUT, + exports2.METHODS.CONNECT, + exports2.METHODS.OPTIONS, + exports2.METHODS.TRACE, + exports2.METHODS.COPY, + exports2.METHODS.LOCK, + exports2.METHODS.MKCOL, + exports2.METHODS.MOVE, + exports2.METHODS.PROPFIND, + exports2.METHODS.PROPPATCH, + exports2.METHODS.SEARCH, + exports2.METHODS.UNLOCK, + exports2.METHODS.BIND, + exports2.METHODS.REBIND, + exports2.METHODS.UNBIND, + exports2.METHODS.ACL, + exports2.METHODS.REPORT, + exports2.METHODS.MKACTIVITY, + exports2.METHODS.CHECKOUT, + exports2.METHODS.MERGE, + exports2.METHODS["M-SEARCH"], + exports2.METHODS.NOTIFY, + exports2.METHODS.SUBSCRIBE, + exports2.METHODS.UNSUBSCRIBE, + exports2.METHODS.PATCH, + exports2.METHODS.PURGE, + exports2.METHODS.MKCALENDAR, + exports2.METHODS.LINK, + exports2.METHODS.UNLINK, + exports2.METHODS.PRI, // TODO(indutny): should we allow it with HTTP? - METHODS.SOURCE + exports2.METHODS.SOURCE, + exports2.METHODS.QUERY ]; exports2.METHODS_ICE = [ - METHODS.SOURCE + exports2.METHODS.SOURCE ]; exports2.METHODS_RTSP = [ - METHODS.OPTIONS, - METHODS.DESCRIBE, - METHODS.ANNOUNCE, - METHODS.SETUP, - METHODS.PLAY, - METHODS.PAUSE, - METHODS.TEARDOWN, - METHODS.GET_PARAMETER, - METHODS.SET_PARAMETER, - METHODS.REDIRECT, - METHODS.RECORD, - METHODS.FLUSH, + exports2.METHODS.OPTIONS, + exports2.METHODS.DESCRIBE, + exports2.METHODS.ANNOUNCE, + exports2.METHODS.SETUP, + exports2.METHODS.PLAY, + exports2.METHODS.PAUSE, + exports2.METHODS.TEARDOWN, + exports2.METHODS.GET_PARAMETER, + exports2.METHODS.SET_PARAMETER, + exports2.METHODS.REDIRECT, + exports2.METHODS.RECORD, + exports2.METHODS.FLUSH, // For AirPlay - METHODS.GET, - METHODS.POST + exports2.METHODS.GET, + exports2.METHODS.POST + ]; + exports2.METHOD_MAP = (0, utils_1.enumToMap)(exports2.METHODS); + exports2.H_METHOD_MAP = Object.fromEntries(Object.entries(exports2.METHODS).filter(([k]) => k.startsWith("H"))); + exports2.STATUSES_HTTP = [ + exports2.STATUSES.CONTINUE, + exports2.STATUSES.SWITCHING_PROTOCOLS, + exports2.STATUSES.PROCESSING, + exports2.STATUSES.EARLY_HINTS, + exports2.STATUSES.RESPONSE_IS_STALE, + exports2.STATUSES.REVALIDATION_FAILED, + exports2.STATUSES.DISCONNECTED_OPERATION, + exports2.STATUSES.HEURISTIC_EXPIRATION, + exports2.STATUSES.MISCELLANEOUS_WARNING, + exports2.STATUSES.OK, + exports2.STATUSES.CREATED, + exports2.STATUSES.ACCEPTED, + exports2.STATUSES.NON_AUTHORITATIVE_INFORMATION, + exports2.STATUSES.NO_CONTENT, + exports2.STATUSES.RESET_CONTENT, + exports2.STATUSES.PARTIAL_CONTENT, + exports2.STATUSES.MULTI_STATUS, + exports2.STATUSES.ALREADY_REPORTED, + exports2.STATUSES.TRANSFORMATION_APPLIED, + exports2.STATUSES.IM_USED, + exports2.STATUSES.MISCELLANEOUS_PERSISTENT_WARNING, + exports2.STATUSES.MULTIPLE_CHOICES, + exports2.STATUSES.MOVED_PERMANENTLY, + exports2.STATUSES.FOUND, + exports2.STATUSES.SEE_OTHER, + exports2.STATUSES.NOT_MODIFIED, + exports2.STATUSES.USE_PROXY, + exports2.STATUSES.SWITCH_PROXY, + exports2.STATUSES.TEMPORARY_REDIRECT, + exports2.STATUSES.PERMANENT_REDIRECT, + exports2.STATUSES.BAD_REQUEST, + exports2.STATUSES.UNAUTHORIZED, + exports2.STATUSES.PAYMENT_REQUIRED, + exports2.STATUSES.FORBIDDEN, + exports2.STATUSES.NOT_FOUND, + exports2.STATUSES.METHOD_NOT_ALLOWED, + exports2.STATUSES.NOT_ACCEPTABLE, + exports2.STATUSES.PROXY_AUTHENTICATION_REQUIRED, + exports2.STATUSES.REQUEST_TIMEOUT, + exports2.STATUSES.CONFLICT, + exports2.STATUSES.GONE, + exports2.STATUSES.LENGTH_REQUIRED, + exports2.STATUSES.PRECONDITION_FAILED, + exports2.STATUSES.PAYLOAD_TOO_LARGE, + exports2.STATUSES.URI_TOO_LONG, + exports2.STATUSES.UNSUPPORTED_MEDIA_TYPE, + exports2.STATUSES.RANGE_NOT_SATISFIABLE, + exports2.STATUSES.EXPECTATION_FAILED, + exports2.STATUSES.IM_A_TEAPOT, + exports2.STATUSES.PAGE_EXPIRED, + exports2.STATUSES.ENHANCE_YOUR_CALM, + exports2.STATUSES.MISDIRECTED_REQUEST, + exports2.STATUSES.UNPROCESSABLE_ENTITY, + exports2.STATUSES.LOCKED, + exports2.STATUSES.FAILED_DEPENDENCY, + exports2.STATUSES.TOO_EARLY, + exports2.STATUSES.UPGRADE_REQUIRED, + exports2.STATUSES.PRECONDITION_REQUIRED, + exports2.STATUSES.TOO_MANY_REQUESTS, + exports2.STATUSES.REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL, + exports2.STATUSES.REQUEST_HEADER_FIELDS_TOO_LARGE, + exports2.STATUSES.LOGIN_TIMEOUT, + exports2.STATUSES.NO_RESPONSE, + exports2.STATUSES.RETRY_WITH, + exports2.STATUSES.BLOCKED_BY_PARENTAL_CONTROL, + exports2.STATUSES.UNAVAILABLE_FOR_LEGAL_REASONS, + exports2.STATUSES.CLIENT_CLOSED_LOAD_BALANCED_REQUEST, + exports2.STATUSES.INVALID_X_FORWARDED_FOR, + exports2.STATUSES.REQUEST_HEADER_TOO_LARGE, + exports2.STATUSES.SSL_CERTIFICATE_ERROR, + exports2.STATUSES.SSL_CERTIFICATE_REQUIRED, + exports2.STATUSES.HTTP_REQUEST_SENT_TO_HTTPS_PORT, + exports2.STATUSES.INVALID_TOKEN, + exports2.STATUSES.CLIENT_CLOSED_REQUEST, + exports2.STATUSES.INTERNAL_SERVER_ERROR, + exports2.STATUSES.NOT_IMPLEMENTED, + exports2.STATUSES.BAD_GATEWAY, + exports2.STATUSES.SERVICE_UNAVAILABLE, + exports2.STATUSES.GATEWAY_TIMEOUT, + exports2.STATUSES.HTTP_VERSION_NOT_SUPPORTED, + exports2.STATUSES.VARIANT_ALSO_NEGOTIATES, + exports2.STATUSES.INSUFFICIENT_STORAGE, + exports2.STATUSES.LOOP_DETECTED, + exports2.STATUSES.BANDWIDTH_LIMIT_EXCEEDED, + exports2.STATUSES.NOT_EXTENDED, + exports2.STATUSES.NETWORK_AUTHENTICATION_REQUIRED, + exports2.STATUSES.WEB_SERVER_UNKNOWN_ERROR, + exports2.STATUSES.WEB_SERVER_IS_DOWN, + exports2.STATUSES.CONNECTION_TIMEOUT, + exports2.STATUSES.ORIGIN_IS_UNREACHABLE, + exports2.STATUSES.TIMEOUT_OCCURED, + exports2.STATUSES.SSL_HANDSHAKE_FAILED, + exports2.STATUSES.INVALID_SSL_CERTIFICATE, + exports2.STATUSES.RAILGUN_ERROR, + exports2.STATUSES.SITE_IS_OVERLOADED, + exports2.STATUSES.SITE_IS_FROZEN, + exports2.STATUSES.IDENTITY_PROVIDER_AUTHENTICATION_ERROR, + exports2.STATUSES.NETWORK_READ_TIMEOUT, + exports2.STATUSES.NETWORK_CONNECT_TIMEOUT ]; - exports2.METHOD_MAP = utils_1.enumToMap(METHODS); - exports2.H_METHOD_MAP = {}; - Object.keys(exports2.METHOD_MAP).forEach((key) => { - if (/^H/.test(key)) { - exports2.H_METHOD_MAP[key] = exports2.METHOD_MAP[key]; - } - }); - var FINISH; - (function(FINISH2) { - FINISH2[FINISH2["SAFE"] = 0] = "SAFE"; - FINISH2[FINISH2["SAFE_WITH_CB"] = 1] = "SAFE_WITH_CB"; - FINISH2[FINISH2["UNSAFE"] = 2] = "UNSAFE"; - })(FINISH = exports2.FINISH || (exports2.FINISH = {})); exports2.ALPHA = []; for (let i = "A".charCodeAt(0); i <= "Z".charCodeAt(0); i++) { exports2.ALPHA.push(String.fromCharCode(i)); @@ -3167,7 +4047,7 @@ var require_constants2 = __commonJS({ exports2.ALPHANUM = exports2.ALPHA.concat(exports2.NUM); exports2.MARK = ["-", "_", ".", "!", "~", "*", "'", "(", ")"]; exports2.USERINFO_CHARS = exports2.ALPHANUM.concat(exports2.MARK).concat(["%", ";", ":", "&", "=", "+", "$", ","]); - exports2.STRICT_URL_CHAR = [ + exports2.URL_CHAR = [ "!", '"', "$", @@ -3199,12 +4079,8 @@ var require_constants2 = __commonJS({ "}", "~" ].concat(exports2.ALPHANUM); - exports2.URL_CHAR = exports2.STRICT_URL_CHAR.concat([" ", "\f"]); - for (let i = 128; i <= 255; i++) { - exports2.URL_CHAR.push(i); - } exports2.HEX = exports2.NUM.concat(["a", "b", "c", "d", "e", "f", "A", "B", "C", "D", "E", "F"]); - exports2.STRICT_TOKEN = [ + exports2.TOKEN = [ "!", "#", "$", @@ -3221,7 +4097,6 @@ var require_constants2 = __commonJS({ "|", "~" ].concat(exports2.ALPHANUM); - exports2.TOKEN = exports2.STRICT_TOKEN.concat([" "]); exports2.HEADER_CHARS = [" "]; for (let i = 32; i <= 255; i++) { if (i !== 127) { @@ -3229,26 +4104,60 @@ var require_constants2 = __commonJS({ } } exports2.CONNECTION_TOKEN_CHARS = exports2.HEADER_CHARS.filter((c) => c !== 44); + exports2.QUOTED_STRING = [" ", " "]; + for (let i = 33; i <= 255; i++) { + if (i !== 34 && i !== 92) { + exports2.QUOTED_STRING.push(i); + } + } + exports2.HTAB_SP_VCHAR_OBS_TEXT = [" ", " "]; + for (let i = 33; i <= 126; i++) { + exports2.HTAB_SP_VCHAR_OBS_TEXT.push(i); + } + for (let i = 128; i <= 255; i++) { + exports2.HTAB_SP_VCHAR_OBS_TEXT.push(i); + } exports2.MAJOR = exports2.NUM_MAP; exports2.MINOR = exports2.MAJOR; - var HEADER_STATE; - (function(HEADER_STATE2) { - HEADER_STATE2[HEADER_STATE2["GENERAL"] = 0] = "GENERAL"; - HEADER_STATE2[HEADER_STATE2["CONNECTION"] = 1] = "CONNECTION"; - HEADER_STATE2[HEADER_STATE2["CONTENT_LENGTH"] = 2] = "CONTENT_LENGTH"; - HEADER_STATE2[HEADER_STATE2["TRANSFER_ENCODING"] = 3] = "TRANSFER_ENCODING"; - HEADER_STATE2[HEADER_STATE2["UPGRADE"] = 4] = "UPGRADE"; - HEADER_STATE2[HEADER_STATE2["CONNECTION_KEEP_ALIVE"] = 5] = "CONNECTION_KEEP_ALIVE"; - HEADER_STATE2[HEADER_STATE2["CONNECTION_CLOSE"] = 6] = "CONNECTION_CLOSE"; - HEADER_STATE2[HEADER_STATE2["CONNECTION_UPGRADE"] = 7] = "CONNECTION_UPGRADE"; - HEADER_STATE2[HEADER_STATE2["TRANSFER_ENCODING_CHUNKED"] = 8] = "TRANSFER_ENCODING_CHUNKED"; - })(HEADER_STATE = exports2.HEADER_STATE || (exports2.HEADER_STATE = {})); exports2.SPECIAL_HEADERS = { - "connection": HEADER_STATE.CONNECTION, - "content-length": HEADER_STATE.CONTENT_LENGTH, - "proxy-connection": HEADER_STATE.CONNECTION, - "transfer-encoding": HEADER_STATE.TRANSFER_ENCODING, - "upgrade": HEADER_STATE.UPGRADE + "connection": exports2.HEADER_STATE.CONNECTION, + "content-length": exports2.HEADER_STATE.CONTENT_LENGTH, + "proxy-connection": exports2.HEADER_STATE.CONNECTION, + "transfer-encoding": exports2.HEADER_STATE.TRANSFER_ENCODING, + "upgrade": exports2.HEADER_STATE.UPGRADE + }; + exports2.default = { + ERROR: exports2.ERROR, + TYPE: exports2.TYPE, + FLAGS: exports2.FLAGS, + LENIENT_FLAGS: exports2.LENIENT_FLAGS, + METHODS: exports2.METHODS, + STATUSES: exports2.STATUSES, + FINISH: exports2.FINISH, + HEADER_STATE: exports2.HEADER_STATE, + ALPHA: exports2.ALPHA, + NUM_MAP: exports2.NUM_MAP, + HEX_MAP: exports2.HEX_MAP, + NUM: exports2.NUM, + ALPHANUM: exports2.ALPHANUM, + MARK: exports2.MARK, + USERINFO_CHARS: exports2.USERINFO_CHARS, + URL_CHAR: exports2.URL_CHAR, + HEX: exports2.HEX, + TOKEN: exports2.TOKEN, + HEADER_CHARS: exports2.HEADER_CHARS, + CONNECTION_TOKEN_CHARS: exports2.CONNECTION_TOKEN_CHARS, + QUOTED_STRING: exports2.QUOTED_STRING, + HTAB_SP_VCHAR_OBS_TEXT: exports2.HTAB_SP_VCHAR_OBS_TEXT, + MAJOR: exports2.MAJOR, + MINOR: exports2.MINOR, + SPECIAL_HEADERS: exports2.SPECIAL_HEADERS, + METHODS_HTTP: exports2.METHODS_HTTP, + METHODS_ICE: exports2.METHODS_ICE, + METHODS_RTSP: exports2.METHODS_RTSP, + METHOD_MAP: exports2.METHOD_MAP, + H_METHOD_MAP: exports2.H_METHOD_MAP, + STATUSES_HTTP: exports2.STATUSES_HTTP }; } }); @@ -3258,7 +4167,13 @@ var require_llhttp_wasm = __commonJS({ "node_modules/undici/lib/llhttp/llhttp-wasm.js"(exports2, module2) { "use strict"; var { Buffer: Buffer3 } = require("node:buffer"); - module2.exports = Buffer3.from("AGFzbQEAAAABJwdgAX8Bf2ADf39/AX9gAX8AYAJ/fwBgBH9/f38Bf2AAAGADf39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQAEA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAAy0sBQYAAAIAAAAAAAACAQIAAgICAAADAAAAAAMDAwMBAQEBAQEBAQEAAAIAAAAEBQFwARISBQMBAAIGCAF/AUGA1AQLB9EFIgZtZW1vcnkCAAtfaW5pdGlhbGl6ZQAIGV9faW5kaXJlY3RfZnVuY3Rpb25fdGFibGUBAAtsbGh0dHBfaW5pdAAJGGxsaHR0cF9zaG91bGRfa2VlcF9hbGl2ZQAvDGxsaHR0cF9hbGxvYwALBm1hbGxvYwAxC2xsaHR0cF9mcmVlAAwEZnJlZQAMD2xsaHR0cF9nZXRfdHlwZQANFWxsaHR0cF9nZXRfaHR0cF9tYWpvcgAOFWxsaHR0cF9nZXRfaHR0cF9taW5vcgAPEWxsaHR0cF9nZXRfbWV0aG9kABAWbGxodHRwX2dldF9zdGF0dXNfY29kZQAREmxsaHR0cF9nZXRfdXBncmFkZQASDGxsaHR0cF9yZXNldAATDmxsaHR0cF9leGVjdXRlABQUbGxodHRwX3NldHRpbmdzX2luaXQAFQ1sbGh0dHBfZmluaXNoABYMbGxodHRwX3BhdXNlABcNbGxodHRwX3Jlc3VtZQAYG2xsaHR0cF9yZXN1bWVfYWZ0ZXJfdXBncmFkZQAZEGxsaHR0cF9nZXRfZXJybm8AGhdsbGh0dHBfZ2V0X2Vycm9yX3JlYXNvbgAbF2xsaHR0cF9zZXRfZXJyb3JfcmVhc29uABwUbGxodHRwX2dldF9lcnJvcl9wb3MAHRFsbGh0dHBfZXJybm9fbmFtZQAeEmxsaHR0cF9tZXRob2RfbmFtZQAfEmxsaHR0cF9zdGF0dXNfbmFtZQAgGmxsaHR0cF9zZXRfbGVu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PgtBhwEMPQtBiAEMPAtBiQEMOwtBigEMOgtBiwEMOQtBjAEMOAtBjQEMNwtBjgEMNgtBjwEMNQtBkAEMNAtBkQEMMwtBkgEMMgtBkwEMMQtBlAEMMAtBlQEMLwtBlgEMLgtBlwEMLQtBmAEMLAtBmQEMKwtBmgEMKgtBmwEMKQtBnAEMKAtBnQEMJwtBngEMJgtBnwEMJQtBoAEMJAtBoQEMIwtBogEMIgtBowEMIQtBpAEMIAtBpQEMHwtBpgEMHgtBpwEMHQtBqAEMHAtBqQEMGwtBqgEMGgtBqwEMGQtBrAEMGAtBrQEMFwtBrgEMFgtBAQwVC0GvAQwUC0GwAQwTC0GxAQwSC0GzAQwRC0GyAQwQC0G0AQwPC0G1AQwOC0G2AQwNC0G3AQwMC0G4AQwLC0G5AQwKC0G6AQwJC0G7AQwIC0HGAQwHC0G8AQwGC0G9AQwFC0G+AQwEC0G/AQwDC0HAAQwCC0HCAQwBC0HBAQshAwNAAkACQAJAAkACQAJAAkACQAJAIAICfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAgJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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iQEhAwykAgtBASABLQAAQd8ARw1nGiABQQFqIQEMXgtBigEhAyABIARGDaICIAIoAgAiACAEIAFraiEFIAEgAGtBAWohBgNAIAEtAAAgAEGMzwBqLQAARw1kIABBAUYN+gEgAEEBaiEAIAQgAUEBaiIBRw0ACyACIAU2AgAMogILQYsBIQMgASAERg2hAiACKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGOzwBqLQAARw1kIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAyiAgsgAkEANgIAIAZBAWohAUECDGULQYwBIQMgASAERg2gAiACKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHwzwBqLQAARw1jIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAyhAgsgAkEANgIAIAZBAWohAUEfDGQLQY0BIQMgASAERg2fAiACKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHyzwBqLQAARw1iIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAygAgsgAkEANgIAIAZBAWohAUEJDGMLIAEgBEYEQEGOASEDDJ8CCwJAAkAgAS0AAEHJAGsOBwBiYmJiYgFiCyABQQFqIQFB+AAhAwyGAgsgAUEBaiEBQfkAIQMMhQILQY8BIQMgASAERg2dAiACKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEGRzwBqLQAARw1gIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAyeAgsgAkEANgIAIAZBAWohAUEYDGELQZABIQMgASAERg2cAiACKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGXzwBqLQAARw1fIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAydAgsgAkEANgIAIAZBAWohAUEXDGALQZEBIQMgASAERg2bAiACKAIAIgAgBCABa2ohBSABIABrQQZqIQYCQANAIAEtAAAgAEGazwBqLQAARw1eIABBBkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAycAgsgAkEANgIAIAZBAWohAUEV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JSIARQ0RIAJB5QA2AhwgAiABNgIUIAIgADYCDEEAIQMMtAELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0gIAJB0wA2AhwgAiABNgIUIAIgADYCDEEAIQMMswELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0iIAJB0gA2AhwgAiABNgIUIAIgADYCDEEAIQMMsgELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0OIAJB5QA2AhwgAiABNgIUIAIgADYCDEEAIQMMsQELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0dIAJB0wA2AhwgAiABNgIUIAIgADYCDEEAIQMMsAELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0fIAJB0gA2AhwgAiABNgIUIAIgADYCDEEAIQMMrwELIABBP0cNASABQQFqCyEBQQUhAwyUAQtBACEDIAJBADYCHCACIAE2AhQgAkH9EjYCECACQQc2AgwMrAELIAJBADYCHCACIAE2AhQgAkHcCDYCECACQQc2AgxBACEDDKsBCyACKAIEIQAgAkEANgIEIAIgACABECUiAEUNByACQeUANgIcIAIgATYCFCACIAA2AgxBACEDDKoBCyACKAIEIQAgAkEANgIEIAIgACABECUiAEUNFiACQdMANgIcIAIgATYCFCACIAA2AgxBACEDDKkBCyACKAIEIQAgAkEANgIEIAIgACABECUiAEUNGCACQdIANgIcIAIgATYCFCACIAA2AgxBACEDDKgBCyACQQA2AhwgAiABNgIUIAJBxgo2AhAgAkEHNgIMQQAhAwynAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDQMgAkHlADYCHCACIAE2AhQgAiAANgIMQQAhAwymAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDRIgAkHTADYCHCACIAE2AhQgAiAANgIMQQAhAwylAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDRQgAkHSADYCHCACIAE2AhQgAiAANgIMQQAhAwykAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDQAgAkHlADYCHCACIAE2AhQgAiAANgIMQQAhAwyjAQtB1QAhAwyJAQsgAEEVRwRAIAJBADYCHCACIAE2AhQgAkG5DTYCECACQRo2AgxB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AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIABB5ABrDvQDY2IAAWFhYWFhYQIDBAVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhBgcICQoLDA0OD2FhYWFhEGFhYWFhYWFhYWFhEWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYRITFBUWFxgZGhthYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2YTc4OTphYWFhYWFhYTthYWE8YWFhYT0+P2FhYWFhYWFhQGFhQWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYUJDREVGR0hJSktMTU5PUFFSU2FhYWFhYWFhVFVWV1hZWlthXF1hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFeYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhX2BhC0HhJw8LQaQhDwtByywPC0H+MQ8LQcAkDwtBqyQPC0GNKA8LQeImDwtBgDAPC0G5Lw8LQdckDwtB7x8PC0HhHw8LQfofDwtB8iAPC0GoLw8LQa4yDwtBiDAPC0HsJw8LQYIiDwtBjh0PC0HQLg8LQcojDwtBxTIPC0HfHA8LQdIcDwtBxCAPC0HXIA8LQaIfDwtB7S4PC0GrMA8LQdQlDwtBzC4PC0H6Lg8LQfwrDwtB0jAPC0HxHQ8LQbsgDwtB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CABB3AgLii1JbnZhbGlkIGNoYXIgaW4gdXJsIHF1ZXJ5AFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fYm9keQBDb250ZW50LUxlbmd0aCBvdmVyZmxvdwBDaHVuayBzaXplIG92ZXJmbG93AFJlc3BvbnNlIG92ZXJmbG93AEludmFsaWQgbWV0aG9kIGZvciBIVFRQL3gueCByZXF1ZXN0AEludmFsaWQgbWV0aG9kIGZvciBSVFNQL3gueCByZXF1ZXN0AEV4cGVjdGVkIFNPVVJDRSBtZXRob2QgZm9yIElDRS94LnggcmVxdWVzdABJbnZhbGlkIGNoYXIgaW4gdXJsIGZyYWdtZW50IHN0YXJ0AEV4cGVjdGVkIGRvdABTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3N0YXR1cwBJbnZhbGlkIHJlc3BvbnNlIHN0YXR1cwBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zAFVzZXIgY2FsbGJhY2sgZXJyb3IAYG9uX3Jlc2V0YCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfaGVhZGVyYCBjYWxsYmFjayBlcnJvcgBgb25fbWVzc2FnZV9iZWdpbmAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3N0YXR1c19jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3ZlcnNpb25fY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl91cmxfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2hlYWRlcl92YWx1ZV9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX21lc3NhZ2VfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXRob2RfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfZmllbGRfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19leHRlbnNpb25fbmFtZWAgY2FsbGJhY2sgZXJyb3IAVW5leHBlY3RlZCBjaGFyIGluIHVybCBzZXJ2ZXIASW52YWxpZCBoZWFkZXIgdmFsdWUgY2hhcgBJbnZhbGlkIGhlYWRlciBmaWVsZCBjaGFyAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fdmVyc2lvbgBJbnZhbGlkIG1pbm9yIHZlcnNpb24ASW52YWxpZCBtYWpvciB2ZXJzaW9uAEV4cGVjdGVkIHNwYWNlIGFmdGVyIHZlcnNpb24ARXhwZWN0ZWQgQ1JMRiBhZnRlciB2ZXJzaW9uAEludmFsaWQgSFRUUCB2ZXJzaW9uAEludmFsaWQgaGVhZGVyIHRva2VuAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fdXJsAEludmFsaWQgY2hhcmFjdGVycyBpbiB1cmwAVW5leHBlY3RlZCBzdGFydCBjaGFyIGluIHVybABEb3VibGUgQCBpbiB1cmwARW1wdHkgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyYWN0ZXIgaW4gQ29udGVudC1MZW5ndGgARHVwbGljYXRlIENvbnRlbnQtTGVuZ3RoAEludmFsaWQgY2hhciBpbiB1cmwgcGF0aABDb250ZW50LUxlbmd0aCBjYW4ndCBiZSBwcmVzZW50IHdpdGggVHJhbnNmZXItRW5jb2RpbmcASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgc2l6ZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2hlYWRlcl92YWx1ZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgTEYgYWZ0ZXIgaGVhZGVyIHZhbHVlAEludmFsaWQgYFRyYW5zZmVyLUVuY29kaW5nYCBoZWFkZXIgdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZSB2YWx1ZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIHF1b3RlZCB2YWx1ZQBQYXVzZWQgYnkgb25faGVhZGVyc19jb21wbGV0ZQBJbnZhbGlkIEVPRiBzdGF0ZQBvbl9yZXNldCBwYXVzZQBvbl9jaHVua19oZWFkZXIgcGF1c2UAb25fbWVzc2FnZV9iZWdpbiBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fdmFsdWUgcGF1c2UAb25fc3RhdHVzX2NvbXBsZXRlIHBhdXNlAG9uX3ZlcnNpb25fY29tcGxldGUgcGF1c2UAb25fdXJsX2NvbXBsZXRlIHBhdXNlAG9uX2NodW5rX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl92YWx1ZV9jb21wbGV0ZSBwYXVzZQBvbl9tZXNzYWdlX2NvbXBsZXRlIHBhdXNlAG9uX21ldGhvZF9jb21wbGV0ZSBwYXVzZQBvbl9oZWFkZXJfZmllbGRfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfZXh0ZW5zaW9uX25hbWUgcGF1c2UAVW5leHBlY3RlZCBzcGFjZSBhZnRlciBzdGFydCBsaW5lAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX25hbWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBuYW1lAFBhdXNlIG9uIENPTk5FQ1QvVXBncmFkZQBQYXVzZSBvbiBQUkkvVXBncmFkZQBFeHBlY3RlZCBIVFRQLzIgQ29ubmVjdGlvbiBQcmVmYWNlAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fbWV0aG9kAEV4cGVjdGVkIHNwYWNlIGFmdGVyIG1ldGhvZABTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2hlYWRlcl9maWVsZABQYXVzZWQASW52YWxpZCB3b3JkIGVuY291bnRlcmVkAEludmFsaWQgbWV0aG9kIGVuY291bnRlcmVkAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2NoZW1hAFJlcXVlc3QgaGFzIGludmFsaWQgYFRyYW5zZmVyLUVuY29kaW5nYABTV0lUQ0hfUFJPWFkAVVNFX1BST1hZAE1LQUNUSVZJVFkAVU5QUk9DRVNTQUJMRV9FTlRJVFkAQ09QWQBNT1ZFRF9QRVJNQU5FTlRMWQBUT09fRUFSTFkATk9USUZZAEZBSUxFRF9ERVBFTkRFTkNZAEJBRF9HQVRFV0FZAFBMQVkAUFVUAENIRUNLT1VUAEdBVEVXQVlfVElNRU9VVABSRVFVRVNUX1RJTUVPVVQATkVUV09SS19DT05ORUNUX1RJTUVPVVQAQ09OTkVDVElPTl9USU1FT1VUAExPR0lOX1RJTUVPVVQATkVUV09SS19SRUFEX1RJTUVPVVQAUE9TVABNSVNESVJFQ1RFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfUkVRVUVTVABDTElFTlRfQ0xPU0VEX0xPQURfQkFMQU5DRURfUkVRVUVTVABCQURfUkVRVUVTVABIVFRQX1JFUVVFU1RfU0VOVF9UT19IVFRQU19QT1JUAFJFUE9SVABJTV9BX1RFQVBPVABSRVNFVF9DT05URU5UAE5PX0NPTlRFTlQAUEFSVElBTF9DT05URU5UAEhQRV9JTlZBTElEX0NPTlNUQU5UAEhQRV9DQl9SRVNFVABHRVQASFBFX1NUUklDVABDT05GTElDVABURU1QT1JBUllfUkVESVJFQ1QAUEVSTUFORU5UX1JFRElSRUNUAENPTk5FQ1QATVVMVElfU1RBVFVTAEhQRV9JTlZBTElEX1NUQVRVUwBUT09fTUFOWV9SRVFVRVNUUwBFQVJMWV9ISU5UUwBVTkFWQUlMQUJMRV9GT1JfTEVHQUxfUkVBU09OUwBPUFRJT05TAFNXSVRDSElOR19QUk9UT0NPTFMAVkFSSUFOVF9BTFNPX05FR09USUFURVMATVVMVElQTEVfQ0hPSUNFUwBJTlRFUk5BTF9TRVJWRVJfRVJST1IAV0VCX1NFUlZFUl9VTktOT1dOX0VSUk9SAFJBSUxHVU5fRVJST1IASURFTlRJVFlfUFJPVklERVJfQVVUSEVOVElDQVRJT05fRVJST1IAU1NMX0NFUlRJRklDQVRFX0VSUk9SAElOVkFMSURfWF9GT1JXQVJERURfRk9SAFNFVF9QQVJBTUVURVIAR0VUX1BBUkFNRVRFUgBIUEVfVVNFUgBTRUVfT1RIRVIASFBFX0NCX0NIVU5LX0hFQURFUgBNS0NBTEVOREFSAFNFVFVQAFdFQl9TRVJWRVJfSVNfRE9XTgBURUFSRE9XTgBIUEVfQ0xPU0VEX0NPTk5FQ1RJT04ASEVVUklTVElDX0VYUElSQVRJT04ARElTQ09OTkVDVEVEX09QRVJBVElPTgBOT05fQVVUSE9SSVRBVElWRV9JTkZPUk1BVElPTgBIUEVfSU5WQUxJRF9WRVJTSU9OAEhQRV9DQl9NRVNTQUdFX0JFR0lOAFNJVEVfSVNfRlJPWkVOAEhQRV9JTlZBTElEX0hFQURFUl9UT0tFTgBJTlZBTElEX1RPS0VOAEZPUkJJRERFTgBFTkhBTkNFX1lPVVJfQ0FMTQBIUEVfSU5WQUxJRF9VUkwAQkxPQ0tFRF9CWV9QQVJFTlRBTF9DT05UUk9MAE1LQ09MAEFDTABIUEVfSU5URVJOQUwAUkVRVUVTVF9IRUFERVJfRklFTERTX1RPT19MQVJHRV9VTk9GRklDSUFMAEhQRV9PSwBVTkxJTksAVU5MT0NLAFBSSQBSRVRSWV9XSVRIAEhQRV9JTlZBTElEX0NPTlRFTlRfTEVOR1RIAEhQRV9VTkVYUEVDVEVEX0NPTlRFTlRfTEVOR1RIAEZMVVNIAFBST1BQQVRDSABNLVNFQVJDSABVUklfVE9PX0xPTkcAUFJPQ0VTU0lORwBNSVNDRUxMQU5FT1VTX1BFUlNJU1RFTlRfV0FSTklORwBNSVNDRUxMQU5FT1VTX1dBUk5JTkcASFBFX0lOVkFMSURfVFJBTlNGRVJfRU5DT0RJTkcARXhwZWN0ZWQgQ1JMRgBIUEVfSU5WQUxJRF9DSFVOS19TSVpFAE1PVkUAQ09OVElOVUUASFBFX0NCX1NUQVRVU19DT01QTEVURQBIUEVfQ0JfSEVBREVSU19DT01QTEVURQBIUEVfQ0JfVkVSU0lPTl9DT01QTEVURQBIUEVfQ0JfVVJMX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19DT01QTEVURQBIUEVfQ0JfSEVBREVSX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9OQU1FX0NPTVBMRVRFAEhQRV9DQl9NRVNTQUdFX0NPTVBMRVRFAEhQRV9DQl9NRVRIT0RfQ09NUExFVEUASFBFX0NCX0hFQURFUl9GSUVMRF9DT01QTEVURQBERUxFVEUASFBFX0lOVkFMSURfRU9GX1NUQVRFAElOVkFMSURfU1NMX0NFUlRJRklDQVRFAFBBVVNFAE5PX1JFU1BPTlNFAFVOU1VQUE9SVEVEX01FRElBX1RZUEUAR09ORQBOT1RfQUNDRVBUQUJMRQBTRVJWSUNFX1VOQVZBSUxBQkxFAFJBTkdFX05PVF9TQVRJU0ZJQUJMRQBPUklHSU5fSVNfVU5SRUFDSEFCTEUAUkVTUE9OU0VfSVNfU1RBTEUAUFVSR0UATUVSR0UAUkVRVUVTVF9IRUFERVJfRklFTERTX1RPT19MQVJHRQBSRVFVRVNUX0hFQURFUl9UT09fTEFSR0UAUEFZTE9BRF9UT09fTEFSR0UASU5TVUZGSUNJRU5UX1NUT1JBR0UASFBFX1BBVVNFRF9VUEdSQURFAEhQRV9QQVVTRURfSDJfVVBHUkFERQBTT1VSQ0UAQU5OT1VOQ0UAVFJBQ0UASFBFX1VORVhQRUNURURfU1BBQ0UAREVTQ1JJQkUAVU5TVUJTQ1JJQkUAUkVDT1JEAEhQRV9JTlZBTElEX01FVEhPRABOT1RfRk9VTkQAUFJPUEZJTkQAVU5CSU5EAFJFQklORABVTkFVVEhPUklaRUQATUVUSE9EX05PVF9BTExPV0VEAEhUVFBfVkVSU0lPTl9OT1RfU1VQUE9SVEVEAEFMUkVBRFlfUkVQT1JURUQAQUNDRVBURUQATk9UX0lNUExFTUVOVEVEAExPT1BfREVURUNURUQASFBFX0NSX0VYUEVDVEVEAEhQRV9MRl9FWFBFQ1RFRABDUkVBVEVEAElNX1VTRUQASFBFX1BBVVNFRABUSU1FT1VUX09DQ1VSRUQAUEFZTUVOVF9SRVFVSVJFRABQUkVDT05ESVRJT05fUkVRVUlSRUQAUFJPWFlfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATkVUV09SS19BVVRIRU5USUNBVElPTl9SRVFVSVJFRABMRU5HVEhfUkVRVUlSRUQAU1NMX0NFUlRJRklDQVRFX1JFUVVJUkVEAFVQR1JBREVfUkVRVUlSRUQAUEFHRV9FWFBJUkVEAFBSRUNPTkRJVElPTl9GQUlMRUQARVhQRUNUQVRJT05fRkFJTEVEAFJFVkFMSURBVElPTl9GQUlMRUQAU1NMX0hBTkRTSEFLRV9GQUlMRUQATE9DS0VEAFRSQU5TRk9STUFUSU9OX0FQUExJRUQATk9UX01PRElGSUVEAE5PVF9FWFRFTkRFRABCQU5EV0lEVEhfTElNSVRfRVhDRUVERUQAU0lURV9JU19PVkVSTE9BREVEAEhFQUQARXhwZWN0ZWQgSFRUUC8AAF4TAAAmEwAAMBAAAPAXAACdEwAAFRIAADkXAADwEgAAChAAAHUSAACtEgAAghMAAE8UAAB/EAAAoBUAACMUAACJEgAAixQAAE0VAADUEQAAzxQAABAYAADJFgAA3BYAAMERAADgFwAAuxQAAHQUAAB8FQAA5RQAAAgXAAAfEAAAZRUAAKMUAAAoFQAAAhUAAJkVAAAsEAAAixkAAE8PAADUDgAAahAAAM4QAAACFwAAiQ4AAG4TAAAcEwAAZhQAAFYXAADBEwAAzRMAAGwTAABoFwAAZhcAAF8XAAAiEwAAzg8AAGkOAADYDgAAYxYAAMsTAACqDgAAKBcAACYXAADFEwAAXRYAAOgRAABnEwAAZRMAAPIWAABzEwAAHRcAAPkWAADzEQAAzw4AAM4VAAAMEgAAsxEAAKURAABhEAAAMhcAALsTAEH5NQsBAQBBkDYL4AEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBB/TcLAQEAQZE4C14CAwICAgICAAACAgACAgACAgICAgICAgICAAQAAAAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgACAEH9OQsBAQBBkToLXgIAAgICAgIAAAICAAICAAICAgICAgICAgIAAwAEAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAQfA7Cw1sb3NlZWVwLWFsaXZlAEGJPAsBAQBBoDwL4AEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBiT4LAQEAQaA+C+cBAQEBAQEBAQEBAQEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQFjaHVua2VkAEGwwAALXwEBAAEBAQEBAAABAQABAQABAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAEGQwgALIWVjdGlvbmVudC1sZW5ndGhvbnJveHktY29ubmVjdGlvbgBBwMIACy1yYW5zZmVyLWVuY29kaW5ncGdyYWRlDQoNCg0KU00NCg0KVFRQL0NFL1RTUC8AQfnCAAsFAQIAAQMAQZDDAAvgAQQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAEH5xAALBQECAAEDAEGQxQAL4AEEAQEFAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBB+cYACwQBAAABAEGRxwAL3wEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAEH6yAALBAEAAAIAQZDJAAtfAwQAAAQEBAQEBAQEBAQEBQQEBAQEBAQEBAQEBAAEAAYHBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQAQfrKAAsEAQAAAQBBkMsACwEBAEGqywALQQIAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAEH6zAALBAEAAAEAQZDNAAsBAQBBms0ACwYCAAAAAAIAQbHNAAs6AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBB8M4AC5YBTk9VTkNFRUNLT1VUTkVDVEVURUNSSUJFTFVTSEVURUFEU0VBUkNIUkdFQ1RJVklUWUxFTkRBUlZFT1RJRllQVElPTlNDSFNFQVlTVEFUQ0hHRU9SRElSRUNUT1JUUkNIUEFSQU1FVEVSVVJDRUJTQ1JJQkVBUkRPV05BQ0VJTkROS0NLVUJTQ1JJQkVIVFRQL0FEVFAv", "base64"); + var wasmBase64 = "AGFzbQEAAAABJwdgAX8Bf2ADf39/AX9gAn9/AGABfwBgBH9/f38Bf2AAAGADf39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQAEA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAAzU0BQYAAAMAAAAAAAADAQMAAwMDAAACAAAAAAICAgICAgICAgIBAQEBAQEBAQEBAwAAAwAAAAQFAXABExMFAwEAAgYIAX8BQcDZBAsHxQcoBm1lbW9yeQIAC19pbml0aWFsaXplAAgZX19pbmRpcmVjdF9mdW5jdGlvbl90YWJsZQEAC2xsaHR0cF9pbml0AAkYbGxodHRwX3Nob3VsZF9rZWVwX2FsaXZlADcMbGxodHRwX2FsbG9jAAsGbWFsbG9jADkLbGxodHRwX2ZyZWUADARmcmVlAAwPbGxodHRwX2dldF90eXBlAA0VbGxodHRwX2dldF9odHRwX21ham9yAA4VbGxodHRwX2dldF9odHRwX21pbm9yAA8RbGxodHRwX2dldF9tZXRob2QAEBZsbGh0dHBfZ2V0X3N0YXR1c19jb2RlABESbGxodHRwX2dldF91cGdyYWRlABIMbGxodHRwX3Jlc2V0ABMObGxodHRwX2V4ZWN1dGUAFBRsbGh0dHBfc2V0dGluZ3NfaW5pdAAVDWxsaHR0cF9maW5pc2gAFgxsbGh0dHBfcGF1c2UAFw1sbGh0dHBfcmVzdW1lABgbbGxodHRwX3Jlc3VtZV9hZnRlcl91cGdyYWRlABkQbGxodHRwX2dldF9lcnJubwAaF2xsaHR0cF9nZXRfZXJyb3JfcmVhc29uABsXbGxodHRwX3NldF9lcnJvcl9yZWFzb24AHBRsbGh0dHBfZ2V0X2Vycm9yX3BvcwAdEWxsaHR0cF9lcnJub19uYW1lAB4SbGxodHRwX21ldGhvZF9uYW1lAB8SbGxodHRwX3N0YXR1c19uYW1lACAabGxodHRw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AXRrQT5qIQILIAEgAjYCHCABQgA3AhAgAkECdEH01wBqIQACQEHI1QAoAgAiA0EBIAJ0IgdxRQRAIAAgATYCAEHI1QAgAyAHcjYCACABIAA2AhggASABNgIIIAEgATYCDAwBCyAEQRkgAkEBdmtBACACQR9HG3QhAiAAKAIAIQACQANAIAAiAygCBEF4cSAERg0BIAJBHXYhACACQQF0IQIgAyAAQQRxakEQaiIHKAIAIgANAAsgByABNgIAIAEgAzYCGCABIAE2AgwgASABNgIIDAELIAMoAggiACABNgIMIAMgATYCCCABQQA2AhggASADNgIMIAEgADYCCAtB5NUAQeTVACgCAEEBayIAQX8gABs2AgALCwcAIAAtACgLBwAgAC0AKgsHACAALQArCwcAIAAtACkLBwAgAC8BNAsHACAALQAwC0ABBH8gACgCGCEBIAAvAS4hAiAALQAoIQMgACgCOCEEIAAQOCAAIAQ2AjggACADOgAoIAAgAjsBLiAAIAE2AhgL5YUCAgd/A34gASACaiEEAkAgACIDKAIMIgANACADKAIEBEAgAyABNgIECyMAQRBrIgkkAAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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C0HjAQwHC0HXAQwGC0HYAQwFC0HZAQwEC0HaAQwDC0HbAQwCC0HdAQwBC0HcAQshAgNAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCADAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQAJ/AkACQAJAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAMCfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAg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ogKiAqICogKiAqICogKiAqICogKiAqICogIAogILIAQgAUEBaiIBRw0AC0HJACECDOwCCyABQQFqIQEgA0Evai0AAEEBcQ2lAiADQQA2AhwgAyABNgIUIANBlxA2AhAgA0EKNgIMQQAhAgzrAgsgASAERwRAA0AgAS0AAEEgRw0VIAQgAUEBaiIBRw0AC0H4ACECDOsCC0H4ACECDOoCCyADQQI6ACgMOAtBACECIANBADYCHCADQb8LNgIQIANBAjYCDCADIAFBAWo2AhQM6AILQQAhAgzOAgtBDSECDM0CC0ETIQIMzAILQRUhAgzLAgtBFiECDMoCC0EYIQIMyQILQRkhAgzIAgtBGiECDMcCC0EbIQIMxgILQRwhAgzFAgtBHSECDMQCC0EeIQIMwwILQR8hAgzCAgtBICECDMECC0EiIQIMwAILQSMhAgy/AgtBJSECDL4CC0HlACECDL0CCyADQT02AhwgAyABNgIUIAMgADYCDEEAIQIM1QILIANBGzYCHCADIAE2AhQgA0GkHDYCECADQRU2AgxBACECDNQCCyADQSA2AhwgAyABNgIUIANBmBo2AhAgA0EVNgIMQQAhAgzTAgsgA0ETNgIcIAMgATYCFCADQZgaNgIQIANBFTYCDEEAIQIM0gILIANBCzYCHCADIAE2AhQgA0GYGjYCECADQRU2AgxBACECDNECCyADQRA2AhwgAyABNgIUIANBmBo2AhAgA0EVNgIMQQAhAgzQAgsgA0EgNgIcIAMgATYCFCADQaQcNgIQIANBFTYCDEEAIQIMzwILIANBCzYCHCADIAE2AhQgA0GkHDYCECADQRU2AgxBACECDM4CCyADQQw2AhwgAyABNgIUIANBpBw2AhAgA0EVNgIMQQAhAgzNAgtBACECIANBADYCHCADIAE2AhQgA0HdDjYCECADQRI2AgwMzAILAkADQAJAIAEtAABBCmsOBAACAgACCyAEIAFBAWoiAUcNAAtB/QEhAgzMAgsCQAJAIAMtADZBAUcNAEEAIQACQCADKAI4IgJFDQAgAigCYCICRQ0AIAMgAhEAACEACyAARQ0AIABBFUcNASADQfwBNgIcIAMgATYCFCADQdwZNgIQIANBFTYCDEEAIQIMzQILQdwBIQIMswILIANBADYCHCADIAE2AhQgA0H5CzYCECADQR82AgxBACECDMsCCwJAAkAgAy0AKEEBaw4CBAEAC0HbASECDLICC0HUASECDLECCyADQQI6ADFBACEAAkAgAygCOCICRQ0AIAIoAgAiAkUNACADIAIRAAAhAAsgAEUEQEHdASECDLECCyAAQRVHBEAgA0EANgIcIAMgATYCFCADQbQMNgIQIANBEDYCDEEAIQIMygILIANB+wE2AhwgAyABNgIUIANBgRo2AhAgA0EVNgIMQQAhAgzJAgsgASAERgRAQfoBIQIMyQILIAEtAABByABGDQEgA0EBOgAoC0HAASECDK4CC0HaASECDK0CCyABIARHBEAgA0EMNgIIIAMgATYCBEHZASECDK0CC0H5ASECDMUCCyABIARGBEBB+AEhAgzFAgsgAS0AAEHIAEcNBCABQQFqIQFB2AEhAgyrAgsgASAERgRAQfcBIQIMxAILAkACQCABLQAAQcUAaw4QAAUFBQUFBQUFBQUFBQUFAQULIAFBAWohAUHWASECDKsCCyABQQFqIQFB1wEhAgyqAgtB9gEhAiABIARGDcICIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbrVAGotAABHDQMgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADMMCCyADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQLiIARQRAQeMBIQIMqgILIANB9QE2AhwgAyABNgIUIAMgADYCDEEAIQIMwgILQfQBIQIgASAERg3BAiADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEG41QBqLQAARw0CIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzCAgsgA0GBBDsBKCADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQLiIADQMMAgsgA0EANgIAC0EAIQIgA0EANgIcIAMgATYCFCADQeUfNgIQIANBCDYCDAy/AgtB1QEhAgylAgsgA0HzATYCHCADIAE2AhQgAyAANgIMQQAhAgy9AgtBACEAAkAgAygCOCICRQ0AIAIoAkAiAkUNACADIAIRAAAhAAsgAEUNbiAAQRVHBEAgA0EANgIcIAMgATYCFCADQYIPNgIQIANBIDYCDEEAIQIMvQILIANBjwE2AhwgAyABNgIUIANB7Bs2AhAgA0EVNgIMQQAhAgy8AgsgASAERwRAIANBDTYCCCADIAE2AgRB0wEhAgyjAgtB8gEhAgy7AgsgASAERgRAQfEBIQIMuwILAkACQAJAIAEtAABByABrDgsAAQgICAgICAgIAggLIAFBAWohAUHQASECDKMCCyABQQFqIQFB0QEhAgyiAgsgAUEBaiEBQdIBIQIMoQILQfABIQIgASAERg25AiADKAIAIgAgBCABa2ohBiABIABrQQJqIQUDQCABLQAAIABBtdUAai0AAEcNBCAAQQJGDQMgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAY2AgAMuQILQe8BIQIgASAERg24AiADKAIAIgAgBCABa2ohBiABIABrQQFqIQUDQCABLQAAIABBs9UAai0AAEcNAyAAQQFGDQIgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAY2AgAMuAILQe4BIQIgASAERg23AiADKAIAIgAgBCABa2ohBiABIABrQQJqIQUDQCABLQAAIABBsNUAai0AAEcNAiAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAY2AgAMtwILIAMoAgQhACADQgA3AwAgAyAAIAVBAWoiARArIgBFDQIgA0HsATYCHCADIAE2AhQgAyAANgIMQQAhAgy2AgsgA0EANgIACyADKAIEIQAgA0EANgIEIAMgACABECsiAEUNnAIgA0HtATYCHCADIAE2AhQgAyAANgIMQQAhAgy0AgtBzwEhAgyaAgtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDLQCC0HOASECDJoCCyADQesBNgIcIAMgATYCFCADQYAbNgIQIANBFTYCDEEAIQIMsgILIAEgBEYEQEHrASECDLICCyABLQAAQS9GBEAgAUEBaiEBDAELIANBADYCHCADIAE2AhQgA0GyODYCECADQQg2AgxBACECDLECC0HNASECDJcCCyABIARHBEAgA0EONgIIIAMgATYCBEHMASECDJcCC0HqASECDK8CCyABIARGBEBB6QEhAgyvAgsgAS0AAEEwayIAQf8BcUEKSQRAIAMgADoAKiABQQFqIQFBywEhAgyWAgsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZcCIANB6AE2AhwgAyABNgIUIAMgADYCDEEAIQIMrgILIAEgBEYEQEHnASECDK4CCwJAIAEtAABBLkYEQCABQQFqIQEMAQsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZgCIANB5gE2AhwgAyABNgIUIAMgADYCDEEAIQIMrgILQcoBIQIMlAILIAEgBEYEQEHlASECDK0CC0EAIQBBASEFQQEhB0EAIQICQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQCABLQAAQTBrDgoKCQABAgMEBQYICwtBAgwGC0EDDAULQQQMBAtBBQwDC0EGDAILQQcMAQtBCAshAkEAIQVBACEHDAILQQkhAkEBIQBBACEFQQAhBwwBC0EAIQVBASECCyADIAI6ACsgAUEBaiEBAkACQCADLQAuQRBxDQACQAJAAkAgAy0AKg4DAQACBAsgB0UNAwwCCyAADQEMAgsgBUUNAQsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDQIgA0HiATYCHCADIAE2AhQgAyAANgIMQQAhAgyvAgsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZoCIANB4wE2AhwgAyABNgIUIAMgADYCDEEAIQIMrgILIAMoAgQhACADQQA2AgQgAyAAIAEQLyIARQ2YAiADQeQBNgIcIAMgATYCFCADIAA2AgwMrQILQckBIQIMkwILQQAhAAJAIAMoAjgiAkUNACACKAJEIgJFDQAgAyACEQAAIQALAkAgAARAIABBFUYNASADQQA2AhwgAyABNgIUIANBpA02AhAgA0EhNgIMQQAhAgytAgtByAEhAgyTAgsgA0HhATYCHCADIAE2AhQgA0HQGjYCECADQRU2AgxBACECDKsCCyABIARGBEBB4QEhAgyrAgsCQCABLQAAQSBGBEAgA0EAOwE0IAFBAWohAQwBCyADQQA2AhwgAyABNgIUIANBmRE2AhAgA0EJNgIMQQAhAgyrAgtBxwEhAgyRAgsgASAERgRAQeABIQIMqgILAkAgAS0AAEEwa0H/AXEiAkEKSQRAIAFBAWohAQJAIAMvATQiAEGZM0sNACADIABBCmwiADsBNCAAQf7/A3EgAkH//wNzSw0AIAMgACACajsBNAwCC0EAIQIgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDAyrAgsgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDEEAIQIMqgILQcYBIQIMkAILIAEgBEYEQEHfASECDKkCCwJAIAEtAABBMGtB/wFxIgJBCkkEQCABQQFqIQECQCADLwE0IgBBmTNLDQAgAyAAQQpsIgA7ATQgAEH+/wNxIAJB//8Dc0sNACADIAAgAmo7ATQMAgtBACECIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgwMqgILIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgxBACECDKkCC0HFASECDI8CCyABIARGBEBB3gEhAgyoAgsCQCABLQAAQTBrQf8BcSICQQpJBEAgAUEBaiEBAkAgAy8BNCIAQZkzSw0AIAMgAEEKbCIAOwE0IABB/v8DcSACQf//A3NLDQAgAyAAIAJqOwE0DAILQQAhAiADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMDKkCCyADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMQQAhAgyoAgtBxAEhAgyOAgsgASAERgRAQd0BIQIMpwILAkACQAJAAkAgAS0AAEEKaw4XAgMDAAMDAwMDAwMDAwMDAwMDAwMDAwEDCyABQQFqDAULIAFBAWohAUHDASECDI8CCyABQQFqIQEgA0Evai0AAEEBcQ0IIANBADYCHCADIAE2AhQgA0GNCzYCECADQQ02AgxBACECDKcCCyADQQA2AhwgAyABNgIUIANBjQs2AhAgA0ENNgIMQQAhAgymAgsgASAERwRAIANBDzYCCCADIAE2AgRBASECDI0CC0HcASECDKUCCwJAAkADQAJAIAEtAABBCmsOBAIAAAMACyAEIAFBAWoiAUcNAAtB2wEhAgymAgsgAygCBCEAIANBADYCBCADIAAgARAtIgBFBEAgAUEBaiEBDAQLIANB2gE2AhwgAyAANgIMIAMgAUEBajYCFEEAIQIMpQILIAMoAgQhACADQQA2AgQgAyAAIAEQLSIADQEgAUEBagshAUHBASECDIoCCyADQdkBNgIcIAMgADYCDCADIAFBAWo2AhRBACECDKICC0HCASECDIgCCyADQS9qLQAAQQFxDQEgA0EANgIcIAMgATYCFCADQeQcNgIQIANBGTYCDEEAIQIMoAILIAEgBEYEQEHZASECDKACCwJAAkACQCABLQAAQQprDgQBAgIAAgsgAUEBaiEBDAILIAFBAWohAQwBCyADLQAuQcAAcUUNAQtBACEAAkAgAygCOCICRQ0AIAIoAjwiAkUNACADIAIRAAAhAAsgAEUNoAEgAEEVRgRAIANB2QA2AhwgAyABNgIUIANBtxo2AhAgA0EVNgIMQQAhAgyfAgsgA0EANgIcIAMgATYCFCADQYANNgIQIANBGzYCDEEAIQIMngILIANBADYCHCADIAE2AhQgA0HcKDYCECADQQI2AgxBACECDJ0CCyABIARHBEAgA0EMNgIIIAMgATYCBEG/ASECDIQCC0HYASECDJwCCyABIARGBEBB1wEhAgycAgsCQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAEtAABBwQBrDhUAAQIDWgQFBlpaWgcICQoLDA0ODxBaCyABQQFqIQFB+wAhAgySAgsgAUEBaiEBQfwAIQIMkQILIAFBAWohAUGBASECDJACCyABQQFqIQFBhQEhAgyPAgsgAUEBaiEBQYYBIQIMjgILIAFBAWohAUGJASECDI0CCyABQQFqIQFBigEhAgyMAgsgAUEBaiEBQY0BIQIMiwILIAFBAWohAUGWASECDIoCCyABQQFqIQFBlwEhAgyJAgsgAUEBaiEBQZgBIQIMiAILIAFBAWohAUGlASECDIcCCyABQQFqIQFBpgEhAgyGAgsgAUEBaiEBQawBIQIMhQILIAFBAWohAUG0ASECDIQCCyABQQFqIQFBtwEhAgyDAgsgAUEBaiEBQb4BIQIMggILIAEgBEYEQEHWASECDJsCCyABLQAAQc4ARw1IIAFBAWohAUG9ASECDIECCyABIARGBEBB1QEhAgyaAgsCQAJAAkAgAS0AAEHCAGsOEgBKSkpKSkpKSkoBSkpKSkpKAkoLIAFBAWohAUG4ASECDIICCyABQQFqIQFBuwEhAgyBAgsgAUEBaiEBQbwBIQIMgAILQdQBIQIgASAERg2YAiADKAIAIgAgBCABa2ohBSABIABrQQdqIQYCQANAIAEtAAAgAEGo1QBqLQAARw1FIABBB0YNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyZAgsgA0EANgIAIAZBAWohAUEbDEULIAEgBEYEQEHTASECDJgCCwJAAkAgAS0AAEHJAGsOBwBHR0dHRwFHCyABQQFqIQFBuQEhAgz/AQsgAUEBaiEBQboBIQIM/gELQdIBIQIgASAERg2WAiADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGm1QBqLQAARw1DIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyXAgsgA0EANgIAIAZBAWohAUEPDEMLQdEBIQIgASAERg2VAiADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGk1QBqLQAARw1CIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyWAgsgA0EANgIAIAZBAWohAUEgDEILQdABIQIgASAERg2UAiADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGh1QBqLQAARw1BIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyVAgsgA0EANgIAIAZBAWohAUESDEELIAEgBEYEQEHPASECDJQCCwJAAkAgAS0AAEHFAGsODgBDQ0NDQ0NDQ0NDQ0MBQwsgAUEBaiEBQbUBIQIM+wELIAFBAWohAUG2ASECDPoBC0HOASECIAEgBEYNkgIgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBntUAai0AAEcNPyAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMkwILIANBADYCACAGQQFqIQFBBww/C0HNASECIAEgBEYNkQIgAygCACIAIAQgAWtqIQUgASAAa0EFaiEGAkADQCABLQAAIABBmNUAai0AAEcNPiAAQQVGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMkgILIANBADYCACAGQQFqIQFBKAw+CyABIARGBEBBzAEhAgyRAgsCQAJAAkAgAS0AAEHFAGsOEQBBQUFBQUFBQUEBQUFBQUECQQsgAUEBaiEBQbEBIQIM+QELIAFBAWohAUGyASECDPgBCyABQQFqIQFBswEhAgz3AQtBywEhAiABIARGDY8CIAMoAgAiACAEIAFraiEFIAEgAGtBBmohBgJAA0AgAS0AACAAQZHVAGotAABHDTwgAEEGRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADJACCyADQQA2AgAgBkEBaiEBQRoMPAtBygEhAiABIARGDY4CIAMoAgAiACAEIAFraiEFIAEgAGtBA2ohBgJAA0AgAS0AACAAQY3VAGotAABHDTsgAEEDRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADI8CCyADQQA2AgAgBkEBaiEBQSEMOwsgASAERgRAQckBIQIMjgILAkACQCABLQAAQcEAaw4UAD09PT09PT09PT09PT09PT09PQE9CyABQQFqIQFBrQEhAgz1AQsgAUEBaiEBQbABIQIM9AELIAEgBEYEQEHIASECDI0CCwJAAkAgAS0AAEHVAGsOCwA8PDw8PDw8PDwBPAsgAUEBaiEBQa4BIQIM9AELIAFBAWohAUGvASECDPMBC0HHASECIAEgBEYNiwIgAygCACIAIAQgAWtqIQUgASAAa0EIaiEGAkADQCABLQAAIABBhNUAai0AAEcNOCAAQQhGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMjAILIANBADYCACAGQQFqIQFBKgw4CyABIARGBEBBxgEhAgyLAgsgAS0AAEHQAEcNOCABQQFqIQFBJQw3C0HFASECIAEgBEYNiQIgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBgdUAai0AAEcNNiAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMigILIANBADYCACAGQQFqIQFBDgw2CyABIARGBEBBxAEhAgyJAgsgAS0AAEHFAEcNNiABQQFqIQFBqwEhAgzvAQsgASAERgRAQcMBIQIMiAILAkACQAJAAkAgAS0AAEHCAGsODwABAjk5OTk5OTk5OTk5AzkLIAFBAWohAUGnASECDPEBCyABQQFqIQFBqAEhAgzwAQsgAUEBaiEBQakBIQIM7wELIAFBAWohAUGqASECDO4BC0HCASECIAEgBEYNhgIgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABB/tQAai0AAEcNMyAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMhwILIANBADYCACAGQQFqIQFBFAwzC0HBASECIAEgBEYNhQIgAygCACIAIAQgAWtqIQUgASAAa0EEaiEGAkADQCABLQAAIABB+dQAai0AAEcNMiAAQQRGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMhgILIANBADYCACAGQQFqIQFBKwwyC0HAASECIAEgBEYNhAIgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABB9tQAai0AAEcNMSAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMhQILIANBADYCACAGQQFqIQFBLAwxC0G/ASECIAEgBEYNgwIgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBodUAai0AAEcNMCAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMhAILIANBADYCACAGQQFqIQFBEQwwC0G+ASECIAEgBEYNggIgAygCACIAIAQgAWtqIQUgASAAa0EDaiEGAkADQCABLQAAIABB8tQAai0AAEcNLyAAQQNGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMgwILIANBADYCACAGQQFqIQFBLgwvCyABIARGBEBBvQEhAgyCAgsCQAJAAkACQAJAIAEtAABBwQBrDhUANDQ0NDQ0NDQ0NAE0NAI0NAM0NAQ0CyABQQFqIQFBmwEhAgzsAQsgAUEBaiEBQZwBIQIM6wELIAFBAWohAUGdASECDOoBCyABQQFqIQFBogEhAgzpAQsgAUEBaiEBQaQBIQIM6AELIAEgBEYEQEG8ASECDIECCwJAAkAgAS0AAEHSAGsOAwAwATALIAFBAWohAUGjASECDOgBCyABQQFqIQFBBAwtC0G7ASECIAEgBEYN/wEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABB8NQAai0AAEcNLCAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMgAILIANBADYCACAGQQFqIQFBHQwsCyABIARGBEBBugEhAgz/AQsCQAJAIAEtAABByQBrDgcBLi4uLi4ALgsgAUEBaiEBQaEBIQIM5gELIAFBAWohAUEiDCsLIAEgBEYEQEG5ASECDP4BCyABLQAAQdAARw0rIAFBAWohAUGgASECDOQBCyABIARGBEBBuAEhAgz9AQsCQAJAIAEtAABBxgBrDgsALCwsLCwsLCwsASwLIAFBAWohAUGeASECDOQBCyABQQFqIQFBnwEhAgzjAQtBtwEhAiABIARGDfsBIAMoAgAiACAEIAFraiEFIAEgAGtBA2ohBgJAA0AgAS0AACAAQezUAGotAABHDSggAEEDRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPwBCyADQQA2AgAgBkEBaiEBQQ0MKAtBtgEhAiABIARGDfoBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQaHVAGotAABHDScgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPsBCyADQQA2AgAgBkEBaiEBQQwMJwtBtQEhAiABIARGDfkBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQerUAGotAABHDSYgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPoBCyADQQA2AgAgBkEBaiEBQQMMJgtBtAEhAiABIARGDfgBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQejUAGotAABHDSUgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPkBCyADQQA2AgAgBkEBaiEBQSYMJQsgASAERgRAQbMBIQIM+AELAkACQCABLQAAQdQAaw4CAAEnCyABQQFqIQFBmQEhAgzfAQsgAUEBaiEBQZoBIQIM3gELQbIBIQIgASAERg32ASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHm1ABqLQAARw0jIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz3AQsgA0EANgIAIAZBAWohAUEnDCMLQbEBIQIgASAERg31ASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHk1ABqLQAARw0iIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz2AQsgA0EANgIAIAZBAWohAUEcDCILQbABIQIgASAERg30ASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEHe1ABqLQAARw0hIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz1AQsgA0EANgIAIAZBAWohAUEGDCELQa8BIQIgASAERg3zASADKAIAIgAgBCABa2ohBSABIABrQQRqIQYCQANAIAEtAAAgAEHZ1ABqLQAARw0gIABBBEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz0AQsgA0EANgIAIAZBAWohAUEZDCALIAEgBEYEQEGuASECDPMBCwJAAkACQAJAIAEtAABBLWsOIwAkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJAEkJCQkJAIkJCQDJAsgAUEBaiEBQY4BIQIM3AELIAFBAWohAUGPASECDNsBCyABQQFqIQFBlAEhAgzaAQsgAUEBaiEBQZUBIQIM2QELQa0BIQIgASAERg3xASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHX1ABqLQAARw0eIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzyAQsgA0EANgIAIAZBAWohAUELDB4LIAEgBEYEQEGsASECDPEBCwJAAkAgAS0AAEHBAGsOAwAgASALIAFBAWohAUGQASECDNgBCyABQQFqIQFBkwEhAgzXAQsgASAERgRAQasBIQIM8AELAkACQCABLQAAQcEAaw4PAB8fHx8fHx8fHx8fHx8BHwsgAUEBaiEBQZEBIQIM1wELIAFBAWohAUGSASECDNYBCyABIARGBEBBqgEhAgzvAQsgAS0AAEHMAEcNHCABQQFqIQFBCgwbC0GpASECIAEgBEYN7QEgAygCACIAIAQgAWtqIQUgASAAa0EFaiEGAkADQCABLQAAIABB0dQAai0AAEcNGiAAQQVGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM7gELIANBADYCACAGQQFqIQFBHgwaC0GoASECIAEgBEYN7AEgAygCACIAIAQgAWtqIQUgASAAa0EGaiEGAkADQCABLQAAIABBytQAai0AAEcNGSAAQQZGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM7QELIANBADYCACAGQQFqIQFBFQwZC0GnASECIAEgBEYN6wEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBx9QAai0AAEcNGCAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM7AELIANBADYCACAGQQFqIQFBFwwYC0GmASECIAEgBEYN6gEgAygCACIAIAQgAWtqIQUgASAAa0EFaiEGAkADQCABLQAAIABBwdQAai0AAEcNFyAAQQVGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM6wELIANBADYCACAGQQFqIQFBGAwXCyABIARGBEBBpQEhAgzqAQsCQAJAIAEtAABByQBrDgcAGRkZGRkBGQsgAUEBaiEBQYsBIQIM0QELIAFBAWohAUGMASECDNABC0GkASECIAEgBEYN6AEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABBptUAai0AAEcNFSAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM6QELIANBADYCACAGQQFqIQFBCQwVC0GjASECIAEgBEYN5wEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABBpNUAai0AAEcNFCAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM6AELIANBADYCACAGQQFqIQFBHwwUC0GiASECIAEgBEYN5gEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBvtQAai0AAEcNEyAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM5wELIANBADYCACAGQQFqIQFBAgwTC0GhASECIAEgBEYN5QEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGA0AgAS0AACAAQbzUAGotAABHDREgAEEBRg0CIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADOUBCyABIARGBEBBoAEhAgzlAQtBASABLQAAQd8ARw0RGiABQQFqIQFBhwEhAgzLAQsgA0EANgIAIAZBAWohAUGIASECDMoBC0GfASECIAEgBEYN4gEgAygCACIAIAQgAWtqIQUgASAAa0EIaiEGAkADQCABLQAAIABBhNUAai0AAEcNDyAAQQhGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM4wELIANBADYCACAGQQFqIQFBKQwPC0GeASECIAEgBEYN4QEgAygCACIAIAQgAWtqIQUgASAAa0EDaiEGAkADQCABLQAAIABBuNQAai0AAEcNDiAAQQNGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM4gELIANBADYCACAGQQFqIQFBLQwOCyABIARGBEBBnQEhAgzhAQsgAS0AAEHFAEcNDiABQQFqIQFBhAEhAgzHAQsgASAERgRAQZwBIQIM4AELAkACQCABLQAAQcwAaw4IAA8PDw8PDwEPCyABQQFqIQFBggEhAgzHAQsgAUEBaiEBQYMBIQIMxgELQZsBIQIgASAERg3eASADKAIAIgAgBCABa2ohBSABIABrQQRqIQYCQANAIAEtAAAgAEGz1ABqLQAARw0LIABBBEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzfAQsgA0EANgIAIAZBAWohAUEjDAsLQZoBIQIgASAERg3dASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGw1ABqLQAARw0KIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzeAQsgA0EANgIAIAZBAWohAUEADAoLIAEgBEYEQEGZASECDN0BCwJAAkAgAS0AAEHIAGsOCAAMDAwMDAwBDAsgAUEBaiEBQf0AIQIMxAELIAFBAWohAUGAASECDMMBCyABIARGBEBBmAEhAgzcAQsCQAJAIAEtAABBzgBrDgMACwELCyABQQFqIQFB/gAhAgzDAQsgAUEBaiEBQf8AIQIMwgELIAEgBEYEQEGXASECDNsBCyABLQAAQdkARw0IIAFBAWohAUEIDAcLQZYBIQIgASAERg3ZASADKAIAIgAgBCABa2ohBSABIABrQQNqIQYCQANAIAEtAAAgAEGs1ABqLQAARw0GIABBA0YNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzaAQsgA0EANgIAIAZBAWohAUEFDAYLQZUBIQIgASAERg3YASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEGm1ABqLQAARw0FIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzZAQsgA0EANgIAIAZBAWohAUEWDAULQZQBIQIgASAERg3XASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGh1QBqLQAARw0EIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzYAQsgA0EANgIAIAZBAWohAUEQDAQLIAEgBEYEQEGTASECDNcBCwJAAkAgAS0AAEHDAGsODAAGBgYGBgYGBgYGAQYLIAFBAWohAUH5ACECDL4BCyABQQFqIQFB+gAhAgy9AQtBkgEhAiABIARGDdUBIAMoAgAiACAEIAFraiEFIAEgAGtBBWohBgJAA0AgAS0AACAAQaDUAGotAABHDQIgAEEFRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNYBCyADQQA2AgAgBkEBaiEBQSQMAgsgA0EANgIADAILIAEgBEYEQEGRASECDNQBCyABLQAAQcwARw0BIAFBAWohAUETCzoAKSADKAIEIQAgA0EANgIEIAMgACABEC4iAA0CDAELQQAhAiADQQA2AhwgAyABNgIUIANB/h82AhAgA0EGNgIMDNEBC0H4ACECDLcBCyADQZABNgIcIAMgATYCFCADIAA2AgxBACECDM8BC0EAIQACQCADKAI4IgJFDQAgAigCQCICRQ0AIAMgAhEAACEACyAARQ0AIABBFUYNASADQQA2AhwgAyABNgIUIANBgg82AhAgA0EgNgIMQQAhAgzOAQtB9wAhAgy0AQsgA0GPATYCHCADIAE2AhQgA0HsGzYCECADQRU2AgxBACECDMwBCyABIARGBEBBjwEhAgzMAQsCQCABLQAAQSBGBEAgAUEBaiEBDAELIANBADYCHCADIAE2AhQgA0GbHzYCECADQQY2AgxBACECDMwBC0ECIQIMsgELA0AgAS0AAEEgRw0CIAQgAUEBaiIBRw0AC0GOASECDMoBCyABIARGBEBBjQEhAgzKAQsCQCABLQAAQQlrDgRKAABKAAtB9QAhAgywAQsgAy0AKUEFRgRAQfYAIQIMsAELQfQAIQIMrwELIAEgBEYEQEGMASECDMgBCyADQRA2AgggAyABNgIEDAoLIAEgBEYEQEGLASECDMcBCwJAIAEtAABBCWsOBEcAAEcAC0HzACECDK0BCyABIARHBEAgA0EQNgIIIAMgATYCBEHxACECDK0BC0GKASECDMUBCwJAIAEgBEcEQANAIAEtAABBoNAAai0AACIAQQNHBEACQCAAQQFrDgJJAAQLQfAAIQIMrwELIAQgAUEBaiIBRw0AC0GIASEC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BCABQQFqIgFHDQALQfsAIQIMpwELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0DIANB2wA2AhwgAyABNgIUIAMgADYCDEEAIQIMpgELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0DIANB3QA2AhwgAyABNgIUIAMgADYCDEEAIQIMpQELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0DIANB+gA2AhwgAyABNgIUIAMgADYCDEEAIQIMpAELIANBADYCHCADIAE2AhQgA0G8CjYCECADQQc2AgxBACECDKMBC0HPACECDIkBC0HRACECDIgBC0HnACECDIcBCyABIARGBEBB+gAhAgygAQsCQCABLQAAQQlrDgQgAAAgAAsgAUEBaiEBQeYAIQIMhgELIAEgBEYEQEH5ACECDJ8BCwJAIAEtAABBCWsOBB8AAB8AC0EAIQACQCADKAI4IgJFDQAgAigCOCICRQ0AIAMgAhEAACEACyAARQRAQeIBIQIMhgELIABBFUcEQCADQQA2AhwgAyABNgIUIANByQ02AhAgA0EaNgIMQQAhAgyfAQsgA0H4ADYCHCADIAE2AhQgA0HqGjYCECADQRU2AgxBACECDJ4BCyABIARHBEAgA0ENNgIIIAMgATYCBEHkACECDIUBC0H3ACECDJ0BCyABIARGBEBB9gAhAgydAQsCQAJAAkAgAS0AAEHIAGsOCwABCwsLCwsLCwsCCwsgAUEBaiEBQd0AIQIMhQELIAFBAWohAUHgACECDIQBCyABQQFqIQFB4wAhAgyDAQtB9QAhAiABIARGDZsBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbXVAGotAABHDQggAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADJwBCyADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQKyIABEAgA0H0ADYCHCADIAE2AhQgAyAANgIMQQAhAgycAQtB4gAhAgyCAQtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDJwBC0HhACECDIIBCyADQfMANgIcIAMgATYCFCADQYAbNgIQIANBFTYCDEEAIQIMmgELIAMtACkiAEEja0ELSQ0JAkAgAEEGSw0AQQEgAHRBygBxRQ0ADAoLQQAhAiADQQA2AhwgAyABNgIUIANB7Qk2AhAgA0EINgIMDJkBC0HyACECIAEgBEYNmAEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABBs9UAai0AAEcNBSAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMmQELIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARArIgAEQCADQfEANgIcIAMgATYCFCADIAA2AgxBACECDJkBC0HfACECDH8LQQAhAAJAIAMoAjgiAkUNACACKAI0IgJFDQAgAyACEQAAIQALAkAgAARAIABBFUYNASADQQA2AhwgAyABNgIUIANB6g02AhAgA0EmNgIMQQAhAgyZAQtB3gAhAgx/CyADQfAANgIcIAMgATYCFCADQYAbNgIQIANBFTYCDEEAIQIMlwELIAMtAClBIUYNBiADQQA2AhwgAyABNgIUIANBkQo2AhAgA0EINgIMQQAhAgyWAQtB7wAhAiABIARGDZUBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbDVAGotAABHDQIgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADJYBCyADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQKyIARQ0CIANB7QA2AhwgAyABNgIUIAMgADYCDEEAIQIMlQELIANBADYCAAsgAygCBCEAIANBADYCBCADIAAgARArIgBFDYABIANB7gA2AhwgAyABNgIUIAMgADYCDEEAIQIMkwELQdwAIQIMeQtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDJMBC0HbACECDHkLIANB7AA2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyRAQsgAy0AKSIAQSNJDQAgAEEuRg0AIANBADYCHCADIAE2AhQgA0HJCTYCECADQQg2AgxBACECDJABC0HaACECDHYLIAEgBEYEQEHrACECDI8BCwJAIAEtAABBL0YEQCABQQFqIQEMAQsgA0EANgIcIAMgATYCFCADQbI4NgIQIANBCDYCDEEAIQIMjwELQdkAIQIMdQsgASAERwRAIANBDjYCCCADIAE2AgRB2AAhAgx1C0HqACECDI0BCyABIARGBEBB6QAhAgyNAQsgAS0AAEEwayIAQf8BcUEKSQRAIAMgADoAKiABQQFqIQFB1wAhAgx0CyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNeiADQegANgIcIAMgATYCFCADIAA2AgxBACECDIwBCyABIARGBEBB5wAhAgyMAQsCQCABLQAAQS5GBEAgAUEBaiEBDAELIAMoAgQhACADQQA2AgQgAyAAIAEQLyIARQ17IANB5gA2AhwgAyABNgIUIAMgADYCDEEAIQIMjAELQdYAIQIMcgsgASAERgRAQeUAIQIMiwELQQAhAEEBIQVBASEHQQAhAgJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAIAEtAABBMGsOCgoJAAECAwQFBggLC0ECDAYLQQMMBQtBBAwEC0EFDAMLQQYMAgtBBwwBC0EICyECQQAhBUEAIQcMAgtBCSECQQEhAEEAIQVBACEHDAELQQAhBUEBIQILIAMgAjoAKyABQQFqIQECQAJAIAMtAC5BEHENAAJAAkACQCADLQAqDgMBAAIECyAHRQ0DDAILIAANAQwCCyAFRQ0BCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNAiADQeIANgIcIAMgATYCFCADIAA2AgxBACECDI0BCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNfSADQeMANgIcIAMgATYCFCADIAA2AgxBACECDIwBCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNeyADQeQANgIcIAMgATYCFCADIAA2AgwMiwELQdQAIQIMcQsgAy0AKUEiRg2GAUHTACECDHALQQAhAAJAIAMoAjgiAkUNACACKAJEIgJFDQAgAyACEQAAIQALIABFBEBB1QAhAgxwCyAAQRVHBEAgA0EANgIcIAMgATYCFCADQaQNNgIQIANBITYCDEEAIQIMiQELIANB4QA2AhwgAyABNgIUIANB0Bo2AhAgA0EVNgIMQQAhAgyIAQsgASAERgRAQeAAIQIMiAELAkACQAJAAkACQCABLQAAQQprDgQBBAQABAsgAUEBaiEBDAELIAFBAWohASADQS9qLQAAQQFxRQ0BC0HSACECDHALIANBADYCHCADIAE2AhQgA0G2ETYCECADQQk2AgxBACECDIgBCyADQQA2AhwgAyABNgIUIANBthE2AhAgA0EJNgIMQQAhAgyHAQsgASAERgRAQd8AIQIMhwELIAEtAABBCkYEQCABQQFqIQEMCQsgAy0ALkHAAHENCCADQQA2AhwgAyABNgIUIANBthE2AhAgA0ECNgIMQQAhAgyGAQsgASAERgRAQd0AIQIMhgELIAEtAAAiAkENRgRAIAFBAWohAUHQACECDG0LIAEhACACQQlrDgQFAQEFAQsgBCABIgBGBEBB3AAhAgyFAQsgAC0AAEEKRw0AIABBAWoMAgtBACECIANBADYCHCADIAA2AhQgA0HKLTYCECADQQc2AgwMgwELIAEgBEYEQEHbACECDIMBCwJAIAEtAABBCWsOBAMAAAMACyABQQFqCyEBQc4AIQIMaAsgASAERgRAQdoAIQIMgQELIAEtAABBCWsOBAABAQABC0EAIQIgA0EANgIcIANBmhI2AhAgA0EHNgIMIAMgAUEBajYCFAx/CyADQYASOwEqQQAhAAJAIAMoAjgiAkUNACACKAI4IgJFDQAgAyACEQAAIQALIABFDQAgAEEVRw0BIANB2QA2AhwgAyABNgIUIANB6ho2AhAgA0EVNgIMQQAhAgx+C0HNACECDGQLIANBADYCHCADIAE2AhQgA0HJDTYCECADQRo2AgxBACECDHwLIAEgBEYEQEHZACECDHwLIAEtAABBIEcNPSABQQFqIQEgAy0ALkEBcQ09IANBADYCHCADIAE2AhQgA0HCHDYCECADQR42AgxBACECDHsLIAEgBEYEQEHYACECDHsLAkACQAJAAkACQCABLQAAIgBBCmsOBAIDAwABCyABQQFqIQFBLCECDGULIABBOkcNASADQQA2AhwgAyABNgIUIANB5xE2AhAgA0EKNgIMQQAhAgx9CyABQQFqIQEgA0Evai0AAEEBcUUNcyADLQAyQYABcUUEQCADQTJqIQIgAxA1QQAhAAJAIAMoAjgiBkUNACAGKAIoIgZFDQAgAyAGEQAAIQALAkACQCAADhZNTEsBAQEBAQEBAQEBAQEBAQEBAQEAAQsgA0EpNgIcIAMgATYCFCADQawZNgIQIANBFTYCDEEAIQIMfgsg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c3BvbnNlIHN0YXR1cwBFeHBlY3RlZCBMRiBhZnRlciBoZWFkZXJzAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMAVXNlciBjYWxsYmFjayBlcnJvcgBgb25fcmVzZXRgIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19oZWFkZXJgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3Byb3RvY29sX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fcHJvdG9jb2wARW1wdHkgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyYWN0ZXIgaW4gQ29udGVudC1MZW5ndGgAVHJhbnNmZXItRW5jb2RpbmcgY2FuJ3QgYmUgcHJlc2VudCB3aXRoIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgc2l6ZQBFeHBlY3RlZCBMRiBhZnRlciBjaHVuayBzaXplAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBVbmV4cGVjdGVkIHdoaXRlc3BhY2UgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgTEYgYWZ0ZXIgaGVhZGVyIHZhbHVlAEludmFsaWQgYFRyYW5zZmVyLUVuY29kaW5nYCBoZWFkZXIgdmFsdWUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciBjaHVuayBleHRlbnNpb24gdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZSB2YWx1ZQBJbnZhbGlkIHF1b3RlZC1wYWlyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fcHJvdG9jb2xfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciByZXNwb25zZSBsaW5lAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX25hbWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBuYW1lAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgZXh0ZW5zaW9uIG5hbWUASW52YWxpZCBzdGF0dXMgY29kZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABNaXNzaW5nIGV4cGVjdGVkIENSIGFmdGVyIGNodW5rIGRhdGEARXhwZWN0ZWQgTEYgYWZ0ZXIgY2h1bmsgZGF0YQBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AARGF0YSBhZnRlciBgQ29ubmVjdGlvbjogY2xvc2VgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBRVUVSWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAEV4cGVjdGVkIExGIGFmdGVyIENSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX1BST1RPQ09MX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19DT01QTEVURQBIUEVfQ0JfSEVBREVSX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9OQU1FX0NPTVBMRVRFAEhQRV9DQl9NRVNTQUdFX0NPTVBMRVRFAEhQRV9DQl9NRVRIT0RfQ09NUExFVEUASFBFX0NCX0hFQURFUl9GSUVMRF9DT01QTEVURQBERUxFVEUASFBFX0lOVkFMSURfRU9GX1NUQVRFAElOVkFMSURfU1NMX0NFUlRJRklDQVRFAFBBVVNFAE5PX1JFU1BPTlNFAFVOU1VQUE9SVEVEX01FRElBX1RZUEUAR09ORQBOT1RfQUNDRVBUQUJMRQBTRVJWSUNFX1VOQVZBSUxBQkxFAFJBTkdFX05PVF9TQVRJU0ZJQUJMRQBPUklHSU5fSVNfVU5SRUFDSEFCTEUAUkVTUE9OU0VfSVNfU1RBTEUAUFVSR0UATUVSR0UAUkVRVUVTVF9IRUFERVJfRklFTERTX1RPT19MQVJHRQBSRVFVRVNUX0hFQURFUl9UT09fTEFSR0UAUEFZTE9BRF9UT09fTEFSR0UASU5TVUZGSUNJRU5UX1NUT1JBR0UASFBFX1BBVVNFRF9VUEdSQURFAEhQRV9QQVVTRURfSDJfVVBHUkFERQBTT1VSQ0UAQU5OT1VOQ0UAVFJBQ0UASFBFX1VORVhQRUNURURfU1BBQ0UAREVTQ1JJQkUAVU5TVUJTQ1JJQkUAUkVDT1JEAEhQRV9JTlZBTElEX01FVEhPRABOT1RfRk9VTkQAUFJPUEZJTkQAVU5CSU5EAFJFQklORABVTkFVVEhPUklaRUQATUVUSE9EX05PVF9BTExPV0VEAEhUVFBfVkVSU0lPTl9OT1RfU1VQUE9SVEVEAEFMUkVBRFlfUkVQT1JURUQAQUNDRVBURUQATk9UX0lNUExFTUVOVEVEAExPT1BfREVURUNURUQASFBFX0NSX0VYUEVDVEVEAEhQRV9MRl9FWFBFQ1RFRABDUkVBVEVEAElNX1VTRUQASFBFX1BBVVNFRABUSU1FT1VUX09DQ1VSRUQAUEFZTUVOVF9SRVFVSVJFRABQUkVDT05ESVRJT05fUkVRVUlSRUQAUFJPWFlfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATkVUV09SS19BVVRIRU5USUNBVElPTl9SRVFVSVJFRABMRU5HVEhfUkVRVUlSRUQAU1NMX0NFUlRJRklDQVRFX1JFUVVJUkVEAFVQR1JBREVfUkVRVUlSRUQAUEFHRV9FWFBJUkVEAFBSRUNPTkRJVElPTl9GQUlMRUQARVhQRUNUQVRJT05fRkFJTEVEAFJFVkFMSURBVElPTl9GQUlMRUQAU1NMX0hBTkRTSEFLRV9GQUlMRUQATE9DS0VEAFRSQU5TRk9STUFUSU9OX0FQUExJRUQATk9UX01PRElGSUVEAE5PVF9FWFRFTkRFRABCQU5EV0lEVEhfTElNSVRfRVhDRUVERUQAU0lURV9JU19PVkVSTE9BREVEAEhFQUQARXhwZWN0ZWQgSFRUUC8sIFJUU1AvIG9yIElDRS8A5xUAAK8VAACkEgAAkhoAACYWAACeFAAA2xkAAHkVAAB+EgAA/hQAADYVAAALFgAA2BYAAPMSAABCGAAArBYAABIVAAAUFwAA7xcAAEgUAABxFwAAshoAAGsZAAB+GQAANRQAAIIaAABEFwAA/RYAAB4YAACHFwAAqhkAAJMSAAAHGAAALBcAAMoXAACkFwAA5xUAAOcVAABYFwAAOxgAAKASAAAtHAAAwxEAAEgRAADeEgAAQhMAAKQZAAD9EAAA9xUAAKUVAADvFgAA+BkAAEoWAABWFgAA9RUAAAoaAAAIGgAAARoAAKsVAABCEgAA1xAAAEwRAAAFGQAAVBYAAB4RAADKGQAAyBkAAE4WAAD/GAAAcRQAAPAVAADuFQAAlBkAAPwVAAC/GQAAmxkAAHwUAABDEQAAcBgAAJUUAAAnFAAAGRQAANUSAADUGQAARBYAAPcQAEG5OwsBAQBB0DsL4AEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBuj0LBAEAAAIAQdE9C14DBAMDAwMDAAADAwADAwADAwMDAwMDAwMDAAUAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAwADAEG6PwsEAQAAAgBB0T8LXgMAAwMDAwMAAAMDAAMDAAMDAwMDAwMDAwMABAAFAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwADAAMAQbDBAAsNbG9zZWVlcC1hbGl2ZQBBycEACwEBAEHgwQAL4AEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBycMACwEBAEHgwwAL5wEBAQEBAQEBAQEBAQECAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAWNodW5rZWQAQfHFAAteAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQBB0McACyFlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AQYDIAAsgcmFuc2Zlci1lbmNvZGluZ3BncmFkZQ0KDQpTTQ0KDQoAQanIAAsFAQIAAQMAQcDIAAtfBAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanKAAsFAQIAAQMAQcDKAAtfBAUFBgUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanMAAsEAQAAAQBBwcwAC14CAgACAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAEGpzgALBQECAAEDAEHAzgALXwQFAAAFBQUFBQUFBQUFBQYFBQUFBQUFBQUFBQUABQAHCAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQAFAAUABQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAAAAFAEGp0AALBQEBAAEBAEHA0AALAQEAQdrQAAtBAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQanSAAsFAQEAAQEAQcDSAAsBAQBBytIACwYCAAAAAAIAQeHSAAs6AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBBoNQAC50BTk9VTkNFRUNLT1VUTkVDVEVURUNSSUJFTFVTSEVURUFEU0VBUkNIUkdFQ1RJVklUWUxFTkRBUlZFT1RJRllQVElPTlNDSFNFQVlTVEFUQ0hHRVVFUllPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFVFRQQ0VUU1BBRFRQLw=="; + var wasmBuffer; + Object.defineProperty(module2, "exports", { + get: () => { + return wasmBuffer ? wasmBuffer : wasmBuffer = Buffer3.from(wasmBase64, "base64"); + } + }); } }); @@ -3267,7 +4182,13 @@ var require_llhttp_simd_wasm = __commonJS({ "node_modules/undici/lib/llhttp/llhttp_simd-wasm.js"(exports2, module2) { "use strict"; var { Buffer: Buffer3 } = require("node:buffer"); - module2.exports = Buffer3.from("AGFzbQEAAAABJwdgAX8Bf2ADf39/AX9gAX8AYAJ/fwBgBH9/f38Bf2AAAGADf39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQAEA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAAy0sBQYAAAIAAAAAAAACAQIAAgICAAADAAAAAAMDAwMBAQEBAQEBAQEAAAIAAAAEBQFwARISBQMBAAIGCAF/AUGA1AQLB9EFIgZtZW1vcnkCAAtfaW5pdGlhbGl6ZQAIGV9faW5kaXJlY3RfZnVuY3Rpb25fdGFibGUBAAtsbGh0dHBfaW5pdAAJGGxsaHR0cF9zaG91bGRfa2VlcF9hbGl2ZQAvDGxsaHR0cF9hbGxvYwALBm1hbGxvYwAxC2xsaHR0cF9mcmVlAAwEZnJlZQAMD2xsaHR0cF9nZXRfdHlwZQANFWxsaHR0cF9nZXRfaHR0cF9tYWpvcgAOFWxsaHR0cF9nZXRfaHR0cF9taW5vcgAPEWxsaHR0cF9nZXRfbWV0aG9kABAWbGxodHRwX2dldF9zdGF0dXNfY29kZQAREmxsaHR0cF9nZXRfdXBncmFkZQASDGxsaHR0cF9yZXNldAATDmxsaHR0cF9leGVjdXRlABQUbGxodHRwX3NldHRpbmdzX2luaXQAFQ1sbGh0dHBfZmluaXNoABYMbGxodHRwX3BhdXNlABcNbGxodHRwX3Jlc3VtZQAYG2xsaHR0cF9yZXN1bWVfYWZ0ZXJfdXBncmFkZQAZEGxsaHR0cF9nZXRfZXJybm8AGhdsbGh0dHBfZ2V0X2Vycm9yX3JlYXNvbgAbF2xsaHR0cF9zZXRfZXJyb3JfcmVhc29uABwUbGxodHRwX2dldF9lcnJvcl9wb3MAHRFsbGh0dHBfZXJybm9fbmFtZQAeEmxsaHR0cF9tZXRob2RfbmFtZQAfEmxsaHR0cF9zdGF0dXNfbmFtZQAgGmxsaHR0cF9zZXRfbGVu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PgtBhwEMPQtBiAEMPAtBiQEMOwtBigEMOgtBiwEMOQtBjAEMOAtBjQEMNwtBjgEMNgtBjwEMNQtBkAEMNAtBkQEMMwtBkgEMMgtBkwEMMQtBlAEMMAtBlQEMLwtBlgEMLgtBlwEMLQtBmAEMLAtBmQEMKwtBmgEMKgtBmwEMKQtBnAEMKAtBnQEMJwtBngEMJgtBnwEMJQtBoAEMJAtBoQEMIwtBogEMIgtBowEMIQtBpAEMIAtBpQEMHwtBpgEMHgtBpwEMHQtBqAEMHAtBqQEMGwtBqgEMGgtBqwEMGQtBrAEMGAtBrQEMFwtBrgEMFgtBAQwVC0GvAQwUC0GwAQwTC0GxAQwSC0GzAQwRC0GyAQwQC0G0AQwPC0G1AQwOC0G2AQwNC0G3AQwMC0G4AQwLC0G5AQwKC0G6AQwJC0G7AQwIC0HGAQwHC0G8AQwGC0G9AQwFC0G+AQwEC0G/AQwDC0HAAQwCC0HCAQwBC0HBAQshAwNAAkACQAJAAkACQAJAAkACQAJAIAICfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAgJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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iQEhAwykAgtBASABLQAAQd8ARw1nGiABQQFqIQEMXgtBigEhAyABIARGDaICIAIoAgAiACAEIAFraiEFIAEgAGtBAWohBgNAIAEtAAAgAEGMzwBqLQAARw1kIABBAUYN+gEgAEEBaiEAIAQgAUEBaiIBRw0ACyACIAU2AgAMogILQYsBIQMgASAERg2hAiACKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGOzwBqLQAARw1kIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAyiAgsgAkEANgIAIAZBAWohAUECDGULQYwBIQMgASAERg2gAiACKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHwzwBqLQAARw1jIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAyhAgsgAkEANgIAIAZBAWohAUEfDGQLQY0BIQMgASAERg2fAiACKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHyzwBqLQAARw1iIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAygAgsgAkEANgIAIAZBAWohAUEJDGMLIAEgBEYEQEGOASEDDJ8CCwJAAkAgAS0AAEHJAGsOBwBiYmJiYgFiCyABQQFqIQFB+AAhAwyGAgsgAUEBaiEBQfkAIQMMhQILQY8BIQMgASAERg2dAiACKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEGRzwBqLQAARw1gIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAyeAgsgAkEANgIAIAZBAWohAUEYDGELQZABIQMgASAERg2cAiACKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGXzwBqLQAARw1fIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAydAgsgAkEANgIAIAZBAWohAUEXDGALQZEBIQMgASAERg2bAiACKAIAIgAgBCABa2ohBSABIABrQQZqIQYCQANAIAEtAAAgAEGazwBqLQAARw1eIABBBkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAycAgsgAkEANgIAIAZBAWohAUEV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JSIARQ0RIAJB5QA2AhwgAiABNgIUIAIgADYCDEEAIQMMtAELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0gIAJB0wA2AhwgAiABNgIUIAIgADYCDEEAIQMMswELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0iIAJB0gA2AhwgAiABNgIUIAIgADYCDEEAIQMMsgELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0OIAJB5QA2AhwgAiABNgIUIAIgADYCDEEAIQMMsQELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0dIAJB0wA2AhwgAiABNgIUIAIgADYCDEEAIQMMsAELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0fIAJB0gA2AhwgAiABNgIUIAIgADYCDEEAIQMMrwELIABBP0cNASABQQFqCyEBQQUhAwyUAQtBACEDIAJBADYCHCACIAE2AhQgAkH9EjYCECACQQc2AgwMrAELIAJBADYCHCACIAE2AhQgAkHcCDYCECACQQc2AgxBACEDDKsBCyACKAIEIQAgAkEANgIEIAIgACABECUiAEUNByACQeUANgIcIAIgATYCFCACIAA2AgxBACEDDKoBCyACKAIEIQAgAkEANgIEIAIgACABECUiAEUNFiACQdMANgIcIAIgATYCFCACIAA2AgxBACEDDKkBCyACKAIEIQAgAkEANgIEIAIgACABECUiAEUNGCACQdIANgIcIAIgATYCFCACIAA2AgxBACEDDKgBCyACQQA2AhwgAiABNgIUIAJBxgo2AhAgAkEHNgIMQQAhAwynAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDQMgAkHlADYCHCACIAE2AhQgAiAANgIMQQAhAwymAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDRIgAkHTADYCHCACIAE2AhQgAiAANgIMQQAhAwylAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDRQgAkHSADYCHCACIAE2AhQgAiAANgIMQQAhAwykAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDQAgAkHlADYCHCACIAE2AhQgAiAANgIMQQAhAwyjAQtB1QAhAwyJAQsgAEEVRwRAIAJBADYCHCACIAE2AhQgAkG5DTYCECACQRo2AgxB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AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIABB5ABrDvQDY2IAAWFhYWFhYQIDBAVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhBgcICQoLDA0OD2FhYWFhEGFhYWFhYWFhYWFhEWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYRITFBUWFxgZGhthYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2YTc4OTphYWFhYWFhYTthYWE8YWFhYT0+P2FhYWFhYWFhQGFhQWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYUJDREVGR0hJSktMTU5PUFFSU2FhYWFhYWFhVFVWV1hZWlthXF1hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFeYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhX2BhC0HhJw8LQaQhDwtByywPC0H+MQ8LQcAkDwtBqyQPC0GNKA8LQeImDwtBgDAPC0G5Lw8LQdckDwtB7x8PC0HhHw8LQfofDwtB8iAPC0GoLw8LQa4yDwtBiDAPC0HsJw8LQYIiDwtBjh0PC0HQLg8LQcojDwtBxTIPC0HfHA8LQdIcDwtBxCAPC0HXIA8LQaIfDwtB7S4PC0GrMA8LQdQlDwtBzC4PC0H6Lg8LQfwrDwtB0jAPC0HxHQ8LQbsgDwtB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AAADAEGUCAsFBAAAAAUAQaQICwkGAAAABwAAAAgAQdwIC4otSW52YWxpZCBjaGFyIGluIHVybCBxdWVyeQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2JvZHkAQ29udGVudC1MZW5ndGggb3ZlcmZsb3cAQ2h1bmsgc2l6ZSBvdmVyZmxvdwBSZXNwb25zZSBvdmVyZmxvdwBJbnZhbGlkIG1ldGhvZCBmb3IgSFRUUC94LnggcmVxdWVzdABJbnZhbGlkIG1ldGhvZCBmb3IgUlRTUC94LnggcmVxdWVzdABFeHBlY3RlZCBTT1VSQ0UgbWV0aG9kIGZvciBJQ0UveC54IHJlcXVlc3QASW52YWxpZCBjaGFyIGluIHVybCBmcmFnbWVudCBzdGFydABFeHBlY3RlZCBkb3QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9zdGF0dXMASW52YWxpZCByZXNwb25zZSBzdGF0dXMASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucwBVc2VyIGNhbGxiYWNrIGVycm9yAGBvbl9yZXNldGAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2hlYWRlcmAgY2FsbGJhY2sgZXJyb3IAYG9uX21lc3NhZ2VfYmVnaW5gIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19leHRlbnNpb25fdmFsdWVgIGNhbGxiYWNrIGVycm9yAGBvbl9zdGF0dXNfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl92ZXJzaW9uX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdXJsX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAEVtcHR5IENvbnRlbnQtTGVuZ3RoAEludmFsaWQgY2hhcmFjdGVyIGluIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBNaXNzaW5nIGV4cGVjdGVkIExGIGFmdGVyIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AgaGVhZGVyIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGUgdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZWQgdmFsdWUAUGF1c2VkIGJ5IG9uX2hlYWRlcnNfY29tcGxldGUASW52YWxpZCBFT0Ygc3RhdGUAb25fcmVzZXQgcGF1c2UAb25fY2h1bmtfaGVhZGVyIHBhdXNlAG9uX21lc3NhZ2VfYmVnaW4gcGF1c2UAb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlIHBhdXNlAG9uX3N0YXR1c19jb21wbGV0ZSBwYXVzZQBvbl92ZXJzaW9uX2NvbXBsZXRlIHBhdXNlAG9uX3VybF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19jb21wbGV0ZSBwYXVzZQBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGUgcGF1c2UAb25fbWVzc2FnZV9jb21wbGV0ZSBwYXVzZQBvbl9tZXRob2RfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lIHBhdXNlAFVuZXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgc3RhcnQgbGluZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgbmFtZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AAU1dJVENIX1BST1hZAFVTRV9QUk9YWQBNS0FDVElWSVRZAFVOUFJPQ0VTU0FCTEVfRU5USVRZAENPUFkATU9WRURfUEVSTUFORU5UTFkAVE9PX0VBUkxZAE5PVElGWQBGQUlMRURfREVQRU5ERU5DWQBCQURfR0FURVdBWQBQTEFZAFBVVABDSEVDS09VVABHQVRFV0FZX1RJTUVPVVQAUkVRVUVTVF9USU1FT1VUAE5FVFdPUktfQ09OTkVDVF9USU1FT1VUAENPTk5FQ1RJT05fVElNRU9VVABMT0dJTl9USU1FT1VUAE5FVFdPUktfUkVBRF9USU1FT1VUAFBPU1QATUlTRElSRUNURURfUkVRVUVTVABDTElFTlRfQ0xPU0VEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9MT0FEX0JBTEFOQ0VEX1JFUVVFU1QAQkFEX1JFUVVFU1QASFRUUF9SRVFVRVNUX1NFTlRfVE9fSFRUUFNfUE9SVABSRVBPUlQASU1fQV9URUFQT1QAUkVTRVRfQ09OVEVOVABOT19DT05URU5UAFBBUlRJQUxfQ09OVEVOVABIUEVfSU5WQUxJRF9DT05TVEFOVABIUEVfQ0JfUkVTRVQAR0VUAEhQRV9TVFJJQ1QAQ09ORkxJQ1QAVEVNUE9SQVJZX1JFRElSRUNUAFBFUk1BTkVOVF9SRURJUkVDVABDT05ORUNUAE1VTFRJX1NUQVRVUwBIUEVfSU5WQUxJRF9TVEFUVVMAVE9PX01BTllfUkVRVUVTVFMARUFSTFlfSElOVFMAVU5BVkFJTEFCTEVfRk9SX0xFR0FMX1JFQVNPTlMAT1BUSU9OUwBTV0lUQ0hJTkdfUFJPVE9DT0xTAFZBUklBTlRfQUxTT19ORUdPVElBVEVTAE1VTFRJUExFX0NIT0lDRVMASU5URVJOQUxfU0VSVkVSX0VSUk9SAFdFQl9TRVJWRVJfVU5LTk9XTl9FUlJPUgBSQUlMR1VOX0VSUk9SAElERU5USVRZX1BST1ZJREVSX0FVVEhFTlRJQ0FUSU9OX0VSUk9SAFNTTF9DRVJUSUZJQ0FURV9FUlJPUgBJTlZBTElEX1hfRk9SV0FSREVEX0ZPUgBTRVRfUEFSQU1FVEVSAEdFVF9QQVJBTUVURVIASFBFX1VTRVIAU0VFX09USEVSAEhQRV9DQl9DSFVOS19IRUFERVIATUtDQUxFTkRBUgBTRVRVUABXRUJfU0VSVkVSX0lTX0RPV04AVEVBUkRPV04ASFBFX0NMT1NFRF9DT05ORUNUSU9OAEhFVVJJU1RJQ19FWFBJUkFUSU9OAERJU0NPTk5FQ1RFRF9PUEVSQVRJT04ATk9OX0FVVEhPUklUQVRJVkVfSU5GT1JNQVRJT04ASFBFX0lOVkFMSURfVkVSU0lPTgBIUEVfQ0JfTUVTU0FHRV9CRUdJTgBTSVRFX0lTX0ZST1pFTgBIUEVfSU5WQUxJRF9IRUFERVJfVE9LRU4ASU5WQUxJRF9UT0tFTgBGT1JCSURERU4ARU5IQU5DRV9ZT1VSX0NBTE0ASFBFX0lOVkFMSURfVVJMAEJMT0NLRURfQllfUEFSRU5UQUxfQ09OVFJPTABNS0NPTABBQ0wASFBFX0lOVEVSTkFMAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0VfVU5PRkZJQ0lBTABIUEVfT0sAVU5MSU5LAFVOTE9DSwBQUkkAUkVUUllfV0lUSABIUEVfSU5WQUxJRF9DT05URU5UX0xFTkdUSABIUEVfVU5FWFBFQ1RFRF9DT05URU5UX0xFTkdUSABGTFVTSABQUk9QUEFUQ0gATS1TRUFSQ0gAVVJJX1RPT19MT05HAFBST0NFU1NJTkcATUlTQ0VMTEFORU9VU19QRVJTSVNURU5UX1dBUk5JTkcATUlTQ0VMTEFORU9VU19XQVJOSU5HAEhQRV9JTlZBTElEX1RSQU5TRkVSX0VOQ09ESU5HAEV4cGVjdGVkIENSTEYASFBFX0lOVkFMSURfQ0hVTktfU0laRQBNT1ZFAENPTlRJTlVFAEhQRV9DQl9TVEFUVVNfQ09NUExFVEUASFBFX0NCX0hFQURFUlNfQ09NUExFVEUASFBFX0NCX1ZFUlNJT05fQ09NUExFVEUASFBFX0NCX1VSTF9DT01QTEVURQBIUEVfQ0JfQ0hVTktfQ09NUExFVEUASFBFX0NCX0hFQURFUl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fTkFNRV9DT01QTEVURQBIUEVfQ0JfTUVTU0FHRV9DT01QTEVURQBIUEVfQ0JfTUVUSE9EX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfRklFTERfQ09NUExFVEUAREVMRVRFAEhQRV9JTlZBTElEX0VPRl9TVEFURQBJTlZBTElEX1NTTF9DRVJUSUZJQ0FURQBQQVVTRQBOT19SRVNQT05TRQBVTlNVUFBPUlRFRF9NRURJQV9UWVBFAEdPTkUATk9UX0FDQ0VQVEFCTEUAU0VSVklDRV9VTkFWQUlMQUJMRQBSQU5HRV9OT1RfU0FUSVNGSUFCTEUAT1JJR0lOX0lTX1VOUkVBQ0hBQkxFAFJFU1BPTlNFX0lTX1NUQUxFAFBVUkdFAE1FUkdFAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0UAUkVRVUVTVF9IRUFERVJfVE9PX0xBUkdFAFBBWUxPQURfVE9PX0xBUkdFAElOU1VGRklDSUVOVF9TVE9SQUdFAEhQRV9QQVVTRURfVVBHUkFERQBIUEVfUEFVU0VEX0gyX1VQR1JBREUAU09VUkNFAEFOTk9VTkNFAFRSQUNFAEhQRV9VTkVYUEVDVEVEX1NQQUNFAERFU0NSSUJFAFVOU1VCU0NSSUJFAFJFQ09SRABIUEVfSU5WQUxJRF9NRVRIT0QATk9UX0ZPVU5EAFBST1BGSU5EAFVOQklORABSRUJJTkQAVU5BVVRIT1JJWkVEAE1FVEhPRF9OT1RfQUxMT1dFRABIVFRQX1ZFUlNJT05fTk9UX1NVUFBPUlRFRABBTFJFQURZX1JFUE9SVEVEAEFDQ0VQVEVEAE5PVF9JTVBMRU1FTlRFRABMT09QX0RFVEVDVEVEAEhQRV9DUl9FWFBFQ1RFRABIUEVfTEZfRVhQRUNURUQAQ1JFQVRFRABJTV9VU0VEAEhQRV9QQVVTRUQAVElNRU9VVF9PQ0NVUkVEAFBBWU1FTlRfUkVRVUlSRUQAUFJFQ09ORElUSU9OX1JFUVVJUkVEAFBST1hZX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAE5FVFdPUktfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATEVOR1RIX1JFUVVJUkVEAFNTTF9DRVJUSUZJQ0FURV9SRVFVSVJFRABVUEdSQURFX1JFUVVJUkVEAFBBR0VfRVhQSVJFRABQUkVDT05ESVRJT05fRkFJTEVEAEVYUEVDVEFUSU9OX0ZBSUxFRABSRVZBTElEQVRJT05fRkFJTEVEAFNTTF9IQU5EU0hBS0VfRkFJTEVEAExPQ0tFRABUUkFOU0ZPUk1BVElPTl9BUFBMSUVEAE5PVF9NT0RJRklFRABOT1RfRVhURU5ERUQAQkFORFdJRFRIX0xJTUlUX0VYQ0VFREVEAFNJVEVfSVNfT1ZFUkxPQURFRABIRUFEAEV4cGVjdGVkIEhUVFAvAABeEwAAJhMAADAQAADwFwAAnRMAABUSAAA5FwAA8BIAAAoQAAB1EgAArRIAAIITAABPFAAAfxAAAKAVAAAjFAAAiRIAAIsUAABNFQAA1BEAAM8UAAAQGAAAyRYAANwWAADBEQAA4BcAALsUAAB0FAAAfBUAAOUUAAAIFwAAHxAAAGUVAACjFAAAKBUAAAIVAACZFQAALBAAAIsZAABPDwAA1A4AAGoQAADOEAAAAhcAAIkOAABuEwAAHBMAAGYUAABWFwAAwRMAAM0TAABsEwAAaBcAAGYXAABfFwAAIhMAAM4PAABpDgAA2A4AAGMWAADLEwAAqg4AACgXAAAmFwAAxRMAAF0WAADoEQAAZxMAAGUTAADyFgAAcxMAAB0XAAD5FgAA8xEAAM8OAADOFQAADBIAALMRAAClEQAAYRAAADIXAAC7EwBB+TULAQEAQZA2C+ABAQECAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAQf03CwEBAEGROAteAgMCAgICAgAAAgIAAgIAAgICAgICAgICAgAEAAAAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAAIAAgBB/TkLAQEAQZE6C14CAAICAgICAAACAgACAgACAgICAgICAgICAAMABAAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgACAEHwOwsNbG9zZWVlcC1hbGl2ZQBBiTwLAQEAQaA8C+ABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAQYk+CwEBAEGgPgvnAQEBAQEBAQEBAQEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBY2h1bmtlZABBsMAAC18BAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQBBkMIACyFlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AQcDCAAstcmFuc2Zlci1lbmNvZGluZ3BncmFkZQ0KDQoNClNNDQoNClRUUC9DRS9UU1AvAEH5wgALBQECAAEDAEGQwwAL4AEEAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBB+cQACwUBAgABAwBBkMUAC+ABBAEBBQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAQfnGAAsEAQAAAQBBkccAC98BAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBB+sgACwQBAAACAEGQyQALXwMEAAAEBAQEBAQEBAQEBAUEBAQEBAQEBAQEBAQABAAGBwQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEAEH6ygALBAEAAAEAQZDLAAsBAQBBqssAC0ECAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBB+swACwQBAAABAEGQzQALAQEAQZrNAAsGAgAAAAACAEGxzQALOgMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQfDOAAuWAU5PVU5DRUVDS09VVE5FQ1RFVEVDUklCRUxVU0hFVEVBRFNFQVJDSFJHRUNUSVZJVFlMRU5EQVJWRU9USUZZUFRJT05TQ0hTRUFZU1RBVENIR0VPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFSFRUUC9BRFRQLw==", "base64"); + var wasmBase64 = "AGFzbQEAAAABJwdgAX8Bf2ADf39/AX9gAn9/AGABfwBgBH9/f38Bf2AAAGADf39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQAEA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAAzU0BQYAAAMAAAAAAAADAQMAAwMDAAACAAAAAAICAgICAgICAgIBAQEBAQEBAQEBAwAAAwAAAAQFAXABExMFAwEAAgYIAX8BQcDZBAsHxQcoBm1lbW9yeQIAC19pbml0aWFsaXplAAgZX19pbmRpcmVjdF9mdW5jdGlvbl90YWJsZQEAC2xsaHR0cF9pbml0AAkYbGxodHRwX3Nob3VsZF9rZWVwX2FsaXZlADcMbGxodHRwX2FsbG9jAAsGbWFsbG9jADkLbGxodHRwX2ZyZWUADARmcmVlAAwPbGxodHRwX2dldF90eXBlAA0VbGxodHRwX2dldF9odHRwX21ham9yAA4VbGxodHRwX2dldF9odHRwX21pbm9yAA8RbGxodHRwX2dldF9tZXRob2QAEBZsbGh0dHBfZ2V0X3N0YXR1c19jb2RlABESbGxodHRwX2dldF91cGdyYWRlABIMbGxodHRwX3Jlc2V0ABMObGxodHRwX2V4ZWN1dGUAFBRsbGh0dHBfc2V0dGluZ3NfaW5pdAAVDWxsaHR0cF9maW5pc2gAFgxsbGh0dHBfcGF1c2UAFw1sbGh0dHBfcmVzdW1lABgbbGxodHRwX3Jlc3VtZV9hZnRlcl91cGdyYWRlABkQbGxodHRwX2dldF9lcnJubwAaF2xsaHR0cF9nZXRfZXJyb3JfcmVhc29uABsXbGxodHRwX3NldF9lcnJvcl9yZWFzb24AHBRsbGh0dHBfZ2V0X2Vycm9yX3BvcwAdEWxsaHR0cF9lcnJub19uYW1lAB4SbGxodHRwX21ldGhvZF9uYW1lAB8SbGxodHRwX3N0YXR1c19uYW1lACAabGxodHRw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AXRrQT5qIQILIAEgAjYCHCABQgA3AhAgAkECdEH01wBqIQACQEHI1QAoAgAiA0EBIAJ0IgdxRQRAIAAgATYCAEHI1QAgAyAHcjYCACABIAA2AhggASABNgIIIAEgATYCDAwBCyAEQRkgAkEBdmtBACACQR9HG3QhAiAAKAIAIQACQANAIAAiAygCBEF4cSAERg0BIAJBHXYhACACQQF0IQIgAyAAQQRxakEQaiIHKAIAIgANAAsgByABNgIAIAEgAzYCGCABIAE2AgwgASABNgIIDAELIAMoAggiACABNgIMIAMgATYCCCABQQA2AhggASADNgIMIAEgADYCCAtB5NUAQeTVACgCAEEBayIAQX8gABs2AgALCwcAIAAtACgLBwAgAC0AKgsHACAALQArCwcAIAAtACkLBwAgAC8BNAsHACAALQAwC0ABBH8gACgCGCEBIAAvAS4hAiAALQAoIQMgACgCOCEEIAAQOCAAIAQ2AjggACADOgAoIAAgAjsBLiAAIAE2AhgLhocCAwd/A34BeyABIAJqIQQCQCAAIgMoAgwiAA0AIAMoAgQEQCADIAE2AgQLIwBBEGsiCSQAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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DAgLQeMBDAcLQdcBDAYLQdgBDAULQdkBDAQLQdoBDAMLQdsBDAILQd0BDAELQdwBCyECA0ACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAMCfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAn8CQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAwJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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A0EXNgIcIAMgADYCDCADIAFBAWo2AhQM+AILIABBFUYNI0EAIQIgA0EANgIcIAMgATYCFCADQdYMNgIQIANBIzYCDAz3AgsgAygCBCEAQQAhAiADQQA2AgQgAyAAIAEQNCIARQRAIAFBAWohAQwdCyADQRk2AhwgAyAANgIMIAMgAUEBajYCFAz2AgsgAygCBCEAQQAhAiADQQA2AgQgAyAAIAEQNCIARQRAIAFBAWohAQzvAgsgA0EaNgIcIAMgADYCDCADIAFBAWo2AhQM9QILIABBFUYNH0EAIQIgA0EANgIcIAMgATYCFCADQdAPNgIQIANBIjYCDAz0AgsgAygCBCEAIANBADYCBCADIAAgARAzIgBFBEAgAUEBaiEBDBsLIANBHDYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgzzAgsgAygCBCEAIANBADYCBCADIAAgARAzIgBFBEAgAUEBaiEBDOsCCyADQR02AhwgAyAANgIMIAMgAUEBajYCFEEAIQIM8gILIABBO0cNASABQQFqIQELQSYhAgzXAgtBACECIANBADYCHCADIAE2AhQgA0GfFTYCECADQQw2AgwM7wILIAEgBEcEQANAIAEtAABBIEcNhAIgBCABQQFqIgFHDQALQSwhAgzvAgtBLCECDO4CCyABIARGBEBBNCECDO4CCwJAAkADQAJAIAEtAABBCmsOBAIAAAMACyAEIAFBAWoiAUcNAAtBNCECDO8CCyADKAIEIQAgA0EANgIEIAMgACABEDEiAEUNnwIgA0EyNgIcIAMgATYCFCADIAA2AgxBACECDO4CCyADKAIEIQAgA0EANgIEIAMgACABEDEiAEUEQCABQQFqIQEMnwILIANBMjYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgztAgsgASAERwRAAkADQCABLQAAQTBrIgBB/wFxQQpPBEBBOiECDNcCCyADKQMgIgtCmbPmzJmz5swZVg0BIAMgC0IKfiIKNwMgIAogAK1C/wGDIgtCf4VWDQEgAyAKIAt8NwMgIAQgAUEBaiIBRw0AC0HAACECDO4CCyADKAIEIQAgA0EANgIEIAMgACABQQFqIgEQMSIADRcM4gILQcAAIQIM7AILIAEgBEYEQEHJACECDOwCCwJAA0ACQCABLQAAQQlrDhgAAqICogKpAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAgCiAgsgBCABQQFqIgFHDQALQckAIQIM7AILIAFBAWohASADQS9qLQAAQQFxDaUCIANBADYCHCADIAE2AhQgA0GXEDYCECADQQo2AgxBACECDOsCCyABIARHBEADQCABLQAAQSBHDRUgBCABQQFqIgFHDQALQfgAIQIM6wILQfgAIQIM6gILIANBAjoAKAw4C0EAIQIgA0EANgIcIANBvws2AhAgA0ECNgIMIAMgAUEBajYCFAzoAgtBACECDM4CC0ENIQIMzQILQRMhAgzMAgtBFSECDMsCC0EWIQIMygILQRghAgzJAgtBGSECDMgCC0EaIQIMxwILQRshAgzGAgtBHCECDMUCC0EdIQIMxAILQR4hAgzDAgtBHyECDMICC0EgIQIMwQILQSIhAgzAAgtBIyECDL8CC0ElIQIMvgILQeUAIQIMvQILIANBPTYCHCADIAE2AhQgAyAANgIMQQAhAgzVAgsgA0EbNgIcIAMgATYCFCADQaQcNgIQIANBFTYCDEEAIQIM1AILIANBIDYCHCADIAE2AhQgA0GYGjYCECADQRU2AgxBACECDNMCCyADQRM2AhwgAyABNgIUIANBmBo2AhAgA0EVNgIMQQAhAgzSAgsgA0ELNgIcIAMgATYCFCADQZgaNgIQIANBFTYCDEEAIQIM0QILIANBEDYCHCADIAE2AhQgA0GYGjYCECADQRU2AgxBACECDNACCyADQSA2AhwgAyABNgIUIANBpBw2AhAgA0EVNgIMQQAhAgzPAgsgA0ELNgIcIAMgATYCFCADQaQcNgIQIANBFTYCDEEAIQIMzgILIANBDDYCHCADIAE2AhQgA0GkHDYCECADQRU2AgxBACECDM0CC0EAIQIgA0EANgIcIAMgATYCFCADQd0ONgIQIANBEjYCDAzMAgsCQANAAkAgAS0AAEEKaw4EAAICAAILIAQgAUEBaiIBRw0AC0H9ASECDMwCCwJAAkAgAy0ANkEBRw0AQQAhAAJAIAMoAjgiAkUNACACKAJgIgJFDQAgAyACEQAAIQALIABFDQAgAEEVRw0BIANB/AE2AhwgAyABNgIUIANB3Bk2AhAgA0EVNgIMQQAhAgzNAgtB3AEhAgyzAgsgA0EANgIcIAMgATYCFCADQfkLNgIQIANBHzYCDEEAIQIMywILAkACQCADLQAoQQFrDgIEAQALQdsBIQIMsgILQdQBIQIMsQILIANBAjoAMUEAIQACQCADKAI4IgJFDQAgAigCACICRQ0AIAMgAhEAACEACyAARQRAQd0BIQIMsQILIABBFUcEQCADQQA2AhwgAyABNgIUIANBtAw2AhAgA0EQNgIMQQAhAgzKAgsgA0H7ATYCHCADIAE2AhQgA0GBGjYCECADQRU2AgxBACECDMkCCyABIARGBEBB+gEhAgzJAgsgAS0AAEHIAEYNASADQQE6ACgLQcABIQIMrgILQdoBIQIMrQILIAEgBEcEQCADQQw2AgggAyABNgIEQdkBIQIMrQILQfkBIQIMxQILIAEgBEYEQEH4ASECDMUCCyABLQAAQcgARw0EIAFBAWohAUHYASECDKsCCyABIARGBEBB9wEhAgzEAgsCQAJAIAEtAABBxQBrDhAABQUFBQUFBQUFBQUFBQUBBQsgAUEBaiEBQdYBIQIMqwILIAFBAWohAUHXASECDKoCC0H2ASECIAEgBEYNwgIgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABButUAai0AAEcNAyAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMwwILIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARAuIgBFBEBB4wEhAgyqAgsgA0H1ATYCHCADIAE2AhQgAyAANgIMQQAhAgzCAgtB9AEhAiABIARGDcECIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQbjVAGotAABHDQIgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADMICCyADQYEEOwEoIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARAuIgANAwwCCyADQQA2AgALQQAhAiADQQA2AhwgAyABNgIUIANB5R82AhAgA0EINgIMDL8CC0HVASECDKUCCyADQfMBNgIcIAMgATYCFCADIAA2AgxBACECDL0CC0EAIQACQCADKAI4IgJFDQAgAigCQCICRQ0AIAMgAhEAACEACyAARQ1uIABBFUcEQCADQQA2AhwgAyABNgIUIANBgg82AhAgA0EgNgIMQQAhAgy9AgsgA0GPATYCHCADIAE2AhQgA0HsGzYCECADQRU2AgxBACECDLwCCyABIARHBEAgA0ENNgIIIAMgATYCBEHTASECDKMCC0HyASECDLsCCyABIARGBEBB8QEhAgy7AgsCQAJAAkAgAS0AAEHIAGsOCwABCAgICAgICAgCCAsgAUEBaiEBQdABIQIMowILIAFBAWohAUHRASECDKICCyABQQFqIQFB0gEhAgyhAgtB8AEhAiABIARGDbkCIAMoAgAiACAEIAFraiEGIAEgAGtBAmohBQNAIAEtAAAgAEG11QBqLQAARw0EIABBAkYNAyAAQQFqIQAgBCABQQFqIgFHDQALIAMgBjYCAAy5AgtB7wEhAiABIARGDbgCIAMoAgAiACAEIAFraiEGIAEgAGtBAWohBQNAIAEtAAAgAEGz1QBqLQAARw0DIABBAUYNAiAAQQFqIQAgBCABQQFqIgFHDQALIAMgBjYCAAy4AgtB7gEhAiABIARGDbcCIAMoAgAiACAEIAFraiEGIAEgAGtBAmohBQNAIAEtAAAgAEGw1QBqLQAARw0CIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBjYCAAy3AgsgAygCBCEAIANCADcDACADIAAgBUEBaiIBECsiAEUNAiADQewBNgIcIAMgATYCFCADIAA2AgxBACECDLYCCyADQQA2AgALIAMoAgQhACADQQA2AgQgAyAAIAEQKyIARQ2cAiADQe0BNgIcIAMgATYCFCADIAA2AgxBACECDLQCC0HPASECDJoCC0EAIQACQCADKAI4IgJFDQAgAigCNCICRQ0AIAMgAhEAACEACwJAIAAEQCAAQRVGDQEgA0EANgIcIAMgATYCFCADQeoNNgIQIANBJjYCDEEAIQIMtAILQc4BIQIMmgILIANB6wE2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyyAgsgASAERgRAQesBIQIMsgILIAEtAABBL0YEQCABQQFqIQEMAQsgA0EANgIcIAMgATYCFCADQbI4NgIQIANBCDYCDEEAIQIMsQILQc0BIQIMlwILIAEgBEcEQCADQQ42AgggAyABNgIEQcwBIQIMlwILQeoBIQIMrwILIAEgBEYEQEHpASECDK8CCyABLQAAQTBrIgBB/wFxQQpJBEAgAyAAOgAqIAFBAWohAUHLASECDJYCCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNlwIgA0HoATYCHCADIAE2AhQgAyAANgIMQQAhAgyuAgsgASAERgRAQecBIQIMrgILAkAgAS0AAEEuRgRAIAFBAWohAQwBCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNmAIgA0HmATYCHCADIAE2AhQgAyAANgIMQQAhAgyuAgtBygEhAgyUAgsgASAERgRAQeUBIQIMrQILQQAhAEEBIQVBASEHQQAhAgJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAIAEtAABBMGsOCgoJAAECAwQFBggLC0ECDAYLQQMMBQtBBAwEC0EFDAMLQQYMAgtBBwwBC0EICyECQQAhBUEAIQcMAgtBCSECQQEhAEEAIQVBACEHDAELQQAhBUEBIQILIAMgAjoAKyABQQFqIQECQAJAIAMtAC5BEHENAAJAAkACQCADLQAqDgMBAAIECyAHRQ0DDAILIAANAQwCCyAFRQ0BCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNAiADQeIBNgIcIAMgATYCFCADIAA2AgxBACECDK8CCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNmgIgA0HjATYCHCADIAE2AhQgAyAANgIMQQAhAgyuAgsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZgCIANB5AE2AhwgAyABNgIUIAMgADYCDAytAgtByQEhAgyTAgtBACEAAkAgAygCOCICRQ0AIAIoAkQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0GkDTYCECADQSE2AgxBACECDK0CC0HIASECDJMCCyADQeEBNgIcIAMgATYCFCADQdAaNgIQIANBFTYCDEEAIQIMqwILIAEgBEYEQEHhASECDKsCCwJAIAEtAABBIEYEQCADQQA7ATQgAUEBaiEBDAELIANBADYCHCADIAE2AhQgA0GZETYCECADQQk2AgxBACECDKsCC0HHASECDJECCyABIARGBEBB4AEhAgyqAgsCQCABLQAAQTBrQf8BcSICQQpJBEAgAUEBaiEBAkAgAy8BNCIAQZkzSw0AIAMgAEEKbCIAOwE0IABB/v8DcSACQf//A3NLDQAgAyAAIAJqOwE0DAILQQAhAiADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMDKsCCyADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMQQAhAgyqAgtBxgEhAgyQAgsgASAERgRAQd8BIQIMqQILAkAgAS0AAEEwa0H/AXEiAkEKSQRAIAFBAWohAQJAIAMvATQiAEGZM0sNACADIABBCmwiADsBNCAAQf7/A3EgAkH//wNzSw0AIAMgACACajsBNAwCC0EAIQIgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDAyqAgsgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDEEAIQIMqQILQcUBIQIMjwILIAEgBEYEQEHeASECDKgCCwJAIAEtAABBMGtB/wFxIgJBCkkEQCABQQFqIQECQCADLwE0IgBBmTNLDQAgAyAAQQpsIgA7ATQgAEH+/wNxIAJB//8Dc0sNACADIAAgAmo7ATQMAgtBACECIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgwMqQILIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgxBACECDKgCC0HEASECDI4CCyABIARGBEBB3QEhAgynAgsCQAJAAkACQCABLQAAQQprDhcCAwMAAwMDAwMDAwMDAwMDAwMDAwMDAQMLIAFBAWoMBQsgAUEBaiEBQcMBIQIMjwILIAFBAWohASADQS9qLQAAQQFxDQggA0EANgIcIAMgATYCFCADQY0LNgIQIANBDTYCDEEAIQIMpwILIANBADYCHCADIAE2AhQgA0GNCzYCECADQQ02AgxBACECDKYCCyABIARHBEAgA0EPNgIIIAMgATYCBEEBIQIMjQILQdwBIQIMpQILAkACQANAAkAgAS0AAEEKaw4EAgAAAwALIAQgAUEBaiIBRw0AC0HbASECDKYCCyADKAIEIQAgA0EANgIEIAMgACABEC0iAEUEQCABQQFqIQEMBAsgA0HaATYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgylAgsgAygCBCEAIANBADYCBCADIAAgARAtIgANASABQQFqCyEBQcEBIQIMigILIANB2QE2AhwgAyAANgIMIAMgAUEBajYCFEEAIQIMogILQcIBIQIMiAILIANBL2otAABBAXENASADQQA2AhwgAyABNgIUIANB5Bw2AhAgA0EZNgIMQQAhAgygAgsgASAERgRAQdkB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CyADIAU2AgAMkAILIANBADYCACAGQQFqIQFBGgw8C0HKASECIAEgBEYNjgIgAygCACIAIAQgAWtqIQUgASAAa0EDaiEGAkADQCABLQAAIABBjdUAai0AAEcNOyAAQQNGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMjwILIANBADYCACAGQQFqIQFBIQw7CyABIARGBEBByQEhAgyOAgsCQAJAIAEtAABBwQBrDhQAPT09PT09PT09PT09PT09PT09AT0LIAFBAWohAUGtASECDPUBCyABQQFqIQFBsAEhAgz0AQsgASAERgRAQcgBIQIMjQILAkACQCABLQAAQdUAaw4LADw8PDw8PDw8PAE8CyABQQFqIQFBrgEhAgz0AQsgAUEBaiEBQa8BIQIM8wELQccBIQIgASAERg2LAiADKAIAIgAgBCABa2ohBSABIABrQQhqIQYCQANAIAEtAAAgAEGE1QBqLQAARw04IABBCEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyMAgsgA0EANgIAIAZBAWohAUEqDDgLIAEgBEYEQEHGASECDIsCCyABLQAAQdAARw04IAFBAWohAUElDDcLQcUBIQIgASAERg2JAiADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGB1QBqLQAARw02IABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyKAgsgA0EANgIAIAZBAWohAUEODDYLIAEgBEYEQEHEASECDIkCCyABLQAAQcUARw02IAFBAWohAUGrASECDO8BCyABIARGBEBBwwEhAgyIAgsCQAJAAkACQCABLQAAQcIAaw4PAAECOTk5OTk5OTk5OTkDOQsgAUEBaiEBQacBIQIM8QELIAFBAWohAUGoASECDPABCyABQQFqIQFBqQEhAgzvAQsgAUEBaiEBQaoBIQIM7gELQcIBIQIgASAERg2GAiADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEH+1ABqLQAARw0zIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyHAgsgA0EANgIAIAZBAWohAUEUDDMLQcEBIQIgASAERg2FAiADKAIAIgAgBCABa2ohBSABIABrQQRqIQYCQANA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BTYCAAzsAQsgA0EANgIAIAZBAWohAUEXDBgLQaYBIQIgASAERg3qASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEHB1ABqLQAARw0XIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzrAQsgA0EANgIAIAZBAWohAUEYDBcLIAEgBEYEQEGlASECDOoBCwJAAkAgAS0AAEHJAGsOBwAZGRkZGQEZCyABQQFqIQFBiwEhAgzRAQsgAUEBaiEBQYwBIQIM0AELQaQBIQIgASAERg3oASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGm1QBqLQAARw0VIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzpAQsgA0EANgIAIAZBAWohAUEJDBULQaMBIQIgASAERg3nASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGk1QBqLQAARw0UIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzoAQsgA0EANgIAIAZBAWohAUEfDBQLQaIBIQIgASAERg3mASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEG+1ABqLQAARw0TIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAznAQsgA0EANgIAIAZBAWohAUECDBMLQaEBIQIgASAERg3lASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYDQCABLQAAIABBvNQAai0AAEcNESAAQQFGDQIgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM5QELIAEgBEYEQEGgASECDOUBC0EBIAEtAABB3wBHDREaIAFBAWohAUGHASECDMsBCyADQQA2AgAgBkEBaiEBQYgBIQIMygELQZ8BIQIgASAERg3iASADKAIAIgAgBCABa2ohBSABIABrQQhqIQYCQANAIAEtAAAgAEGE1QBqLQAARw0PIABBCEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzjAQsgA0EANgIAIAZBAWohAUEpDA8LQZ4BIQIgASAERg3hASADKAIAIgAgBCABa2ohBSABIABrQQNqIQYCQANAIAEtAAAgAEG41ABqLQAARw0OIABBA0YNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAziAQsgA0EANgIAIAZBAWohAUEtDA4LIAEgBEYEQEGdASECDOEBCyABLQAAQcUARw0OIAFBAWohAUGEASECDMcBCyABIARGBEBBnAEhAgzgAQsCQAJAIAEtAABBzABrDggADw8PDw8PAQ8LIAFBAWohAUGCASECDMcBCyABQQFqIQFBgwEhAgzGAQtBmwEhAiABIARGDd4BIAMoAgAiACAEIAFraiEFIAEgAGtBBGohBgJAA0AgAS0AACAAQbPUAGotAABHDQsgAEEERg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADN8BCyADQQA2AgAgBkEBaiEBQSMMCwtBmgEhAiABIARGDd0BIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbDUAGotAABHDQogAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADN4BCyADQQA2AgAgBkEBaiEBQQAMCgsgASAERgRAQZkBIQIM3QELAkACQCABLQAAQcgAaw4IAAwMDAwMDAEMCyABQQFqIQFB/QAhAgzEAQsgAUEBaiEBQYABIQIMwwELIAEgBEYEQEGYASECDNwBCwJAAkAgAS0AAEHOAGsOAwALAQsLIAFBAWohAUH+ACECDMMBCyABQQFqIQFB/wAhAgzCAQsgASAERgRAQZcBIQIM2wELIAEtAABB2QBHDQggAUEBaiEBQQgMBwtBlgEhAiABIARGDdkBIAMoAgAiACAEIAFraiEFIAEgAGtBA2ohBgJAA0AgAS0AACAAQazUAGotAABHDQYgAEEDRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNoBCyADQQA2AgAgBkEBaiEBQQUMBgtBlQEhAiABIARGDdgBIAMoAgAiACAEIAFraiEFIAEgAGtBBWohBgJAA0AgAS0AACAAQabUAGotAABHDQUgAEEFRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNkBCyADQQA2AgAgBkEBaiEBQRYMBQtBlAEhAiABIARGDdcBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQaHVAGotAABHDQQgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNgBCyADQQA2AgAgBkEBaiEBQRAMBAsgASAERgRAQZMBIQIM1wELAkACQCABLQAAQcMAaw4MAAYGBgYGBgYGBgYBBgsgAUEBaiEBQfkAIQIMvgELIAFBAWohAUH6ACECDL0BC0GSASECIAEgBEYN1QEgAygCACIAIAQgAWtqIQUgASAAa0EFaiEGAkADQCABLQAAIABBoNQAai0AAEcNAiAAQQVGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM1gELIANBADYCACAGQQFqIQFBJAwCCyADQQA2AgAMAgsgASAERgRAQZEBIQIM1AELIAEtAABBzABHDQEgAUEBaiEBQRMLOgApIAMoAgQhACADQQA2AgQgAyAAIAEQLiIADQIMAQtBACECIANBADYCHCADIAE2AhQgA0H+HzYCECADQQY2AgwM0QELQfgAIQIMtwELIANBkAE2AhwgAyABNgIUIAMgADYCDEEAIQIMzwELQQAhAAJAIAMoAjgiAkUNACACKAJAIgJFDQAgAyACEQAAIQALIABFDQAgAEEVRg0BIANBADYCHCADIAE2AhQgA0GCDzYCECADQSA2AgxBACECDM4BC0H3ACECDLQBCyADQY8BNgIcIAMgATYCFCADQewbNgIQIANBFTYCDEEAIQIMzAELIAEgBEYEQEGPASECDMwBCwJAIAEtAABBIEYEQCABQQFqIQEMAQsgA0EANgIcIAMgATYCFCADQZsfNgIQIANBBjYCDEEAIQIMzAELQQIhAgyyAQsDQCABLQAAQSBHDQIgBCABQQFqIgFHDQALQY4BIQIMygELIAEgBEYEQEGNASECDMoBCwJAIAEtAABBCWsOBEoAAEoAC0H1ACECDLABCyADLQApQQVGBEBB9gAhAgywAQtB9AAhAgyvAQsgASAERgRAQYwBIQIMyAELIANBEDYCCCADIAE2AgQMCgsgASAERgRAQYsBIQIMxwELAkAgAS0AAEEJaw4ERwAARwALQfMAIQIMrQELIAEgBEcEQCADQRA2AgggAyABNgIEQfEAIQIMrQELQYoBIQIMxQELAkAgASAERwRAA0AgAS0AAEGg0ABqLQAAIgBBA0cEQAJAIABBAWsOAkkABAtB8AAhAgyvAQsgBCABQQFqIgFHDQALQYgBIQIMxgELQYgBIQIMxQELIANBADYCHCADIAE2AhQgA0HbIDYCECADQQc2AgxBACECDMQBCyABIARGBEBBiQEhAgzEAQsCQAJAAkAgAS0AAEGg0gBqLQAAQQFrDgNGAgABC0HyACECDKwBCyADQQA2AhwgAyABNgIUIANBtBI2AhAgA0EHNgIMQQAhAgzEAQtB6gAhAgyqAQsgASAERwRAIAFBAWohAUHvACECDKoBC0GHASECDMIBCyAEIAEiAEYEQEGGASECDMIBCyAALQAAIgFBL0YEQCAAQQFqIQFB7gAhAgypAQsgAUEJayICQRdLDQEgACEBQQEgAnRBm4CABHENQQwBCyAEIAEiAEYEQEGFASECDMEBCyAALQAAQS9HDQAgAEEBaiEBDAMLQQAhAiADQQA2AhwgAyAANgIUIANB2yA2AhAgA0EHNgIMDL8BCwJAAkACQAJAAkADQCABLQAAQaDOAGotAAAiAEEFRwRAAkACQCAAQQFrDghHBQYHCAAEAQgLQesAIQIMrQELIAFBAWohAUHtACECDKwBCyAEIAFBAWoiAUcNAAtBhAEhAgzDAQsgAUEBagwUCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNHiADQdsANgIcIAMgATYCFCADIAA2AgxBACECDMEBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNHiADQd0ANgIcIAMgATYCFCADIAA2AgxBACECDMABCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNHiADQfoANgIcIAMgATYCFCADIAA2AgxBACECDL8BCyADQQA2AhwgAyABNgIUIANB+Q82AhAgA0EHNgIMQQAhAgy+AQsgASAERgRAQYMBIQIMvgELAkAgAS0AAEGgzgBqLQAAQQFrDgg+BAUGAAgCAwcLIAFBAWohAQtBAyECDKMBCyABQQFqDA0LQQAhAiADQQA2AhwgA0HREjYCECADQQc2AgwgAyABQQFqNgIUDLoBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNFiADQdsANgIcIAMgATYCFCADIAA2AgxBACECDLkBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNFiADQd0ANgIcIAMgATYCFCADIAA2AgxBACECDLgBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNFiADQfoANgIcIAMgATYCFCADIAA2AgxBACECDLcBCyADQQA2AhwgAyABNgIUIANB+Q82AhAgA0EHNgIMQQAhAgy2AQtB7AAhAgycAQsgASAERgRAQYIBIQIMtQELIAFBAWoMAgsgASAERgRAQYEBIQIMtAELIAFBAWoMAQsgASAERg0BIAFBAWoLIQFBBCECDJgBC0GAASECDLABCwNAIAEtAABBoMwAai0AACIAQQJHBEAgAEEBRwRAQekAIQIMmQELDDELIAQgAUEBaiIBRw0AC0H/ACECDK8BCyABIARGBEBB/gAhAgyvAQsCQCABLQAAQQlrDjcvAwYvBAYGBgYGBgYGBgYGBgYGBgYGBgUGBgIGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYABgsgAUEBagshAUEFIQIMlAELIAFBAWoMBgsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQggA0HbADYCHCADIAE2AhQgAyAANgIMQQAhAgyrAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQggA0HdADYCHCADIAE2AhQgAyAANgIMQQAhAgyqAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQggA0H6ADYCHCADIAE2AhQgAyAANgIMQQAhAgypAQsgA0EANgIcIAMgATYCFCADQY0UNgIQIANBBzYCDEEAIQIMqAELAkACQAJAAkADQCABLQAAQaDKAGotAAAiAEEFRwRAAkAgAEEBaw4GLgMEBQYABgtB6AAhAgyUAQsgBCABQQFqIgFHDQALQf0AIQIMqwELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0HIANB2wA2AhwgAyABNgIUIAMgADYCDEEAIQIMqgELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0HIANB3QA2AhwgAyABNgIUIAMgADYCDEEAIQIMqQELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0HIANB+gA2AhwgAyABNgIUIAMgADYCDEEAIQIMqAELIANBADYCHCADIAE2AhQgA0HkCDYCECADQQc2AgxBACECDKcBCyABIARGDQEgAUEBagshAUEGIQIMjAELQfwAIQIMpAELAkACQAJAAkADQCABLQAAQaDIAGotAAAiAEEFRwRAIABBAWsOBCkCAwQFCyAEIAFBAWoiAUcNAAtB+wAhAgynAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQMgA0HbADYCHCADIAE2AhQgAyAANgIMQQAhAgymAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQMgA0HdADYCHCADIAE2AhQgAyAANgIMQQAhAgylAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQMgA0H6ADYCHCADIAE2AhQgAyAANgIMQQAhAgykAQsgA0EANgIcIAMgATYCFCADQbwKNgIQIANBBzYCDEEAIQIMowELQc8AIQIMiQELQdEAIQIMiAELQecAIQIMhwELIAEgBEYEQEH6ACECDKABCwJAIAEtAABBCWsOBCAAACAACyABQQFqIQFB5gAhAgyGAQsgASAERgRAQfkAIQIMnwELAkAgAS0AAEEJaw4EHwAAHwALQQAhAAJAIAMoAjgiAkUNACACKAI4IgJFDQAgAyACEQAAIQALIABFBEBB4gEhAgyGAQsgAEEVRwRAIANBADYCHCADIAE2AhQgA0HJDTYCECADQRo2AgxBACECDJ8BCyADQfgANgIcIAMgATYCFCADQeoaNgIQIANBFTYCDEEAIQIMngELIAEgBEcEQCADQQ02AgggAyABNgIEQeQAIQIMhQELQfcAIQIMnQELIAEgBEYEQEH2ACECDJ0BCwJAAkACQCABLQAAQcgAaw4LAAELCwsLCwsLCwILCyABQQFqIQFB3QAhAgyFAQsgAUEBaiEBQeAAIQIMhAELIAFBAWohAUHjACECDIMBC0H1ACECIAEgBEYNmwEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBtdUAai0AAEcNCCAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMnAELIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARArIgAEQCADQfQANgIcIAMgATYCFCADIAA2AgxBACECDJwBC0HiACECDIIBC0EAIQACQCADKAI4IgJFDQAgAigCNCICRQ0AIAMgAhEAACEACwJAIAAEQCAAQRVGDQEgA0EANgIcIAMgATYCFCADQeoNNgIQIANBJjYCDEEAIQIMnAELQeEAIQIMggELIANB8wA2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyaAQsgAy0AKSIAQSNrQQtJDQkCQCAAQQZLDQBBASAAdEHKAHFFDQAMCgtBACECIANBADYCHCADIAE2AhQgA0HtCTYCECADQQg2AgwMmQELQfIAIQIgASAERg2YASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGz1QBqLQAARw0FIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyZAQsgAygCBCEAIANCADcDACADIAAgBkEBaiIBECsiAARAIANB8QA2AhwgAyABNgIUIAMgADYCDEEAIQIMmQELQd8AIQIMfwtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDJkBC0HeACECDH8LIANB8AA2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyXAQsgAy0AKUEhRg0GIANBADYCHCADIAE2AhQgA0GRCjYCECADQQg2AgxBACECDJYBC0HvACECIAEgBEYNlQEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBsNUAai0AAEcNAiAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMlgELIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARArIgBFDQIgA0HtADYCHCADIAE2AhQgAyAANgIMQQAhAgyVAQsgA0EANgIACyADKAIEIQAgA0EANgIEIAMgACABECsiAEUNgAEgA0HuADYCHCADIAE2AhQgAyAANgIMQQAhAgyTAQtB3AAhAgx5C0EAIQACQCADKAI4IgJFDQAgAigCNCICRQ0AIAMgAhEAACEACwJAIAAEQCAAQRVGDQEgA0EANgIcIAMgATYCFCADQeoNNgIQIANBJjYCDEEAIQIMkwELQdsAIQIMeQsgA0HsADYCHCADIAE2AhQgA0GAGzYCECADQRU2AgxBACECDJEBCyADLQApIgBBI0kNACAAQS5GDQAgA0EANgIcIAMgATYCFCADQckJNgIQIANBCDYCDEEAIQIMkAELQdoAIQIMdgsgASAERgRAQesAIQIMjwELAkAgAS0AAEEvRgRAIAFBAWohAQwBCyAD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ciBIVFRQL3gueCByZXF1ZXN0AEludmFsaWQgbWV0aG9kIGZvciBSVFNQL3gueCByZXF1ZXN0AEV4cGVjdGVkIFNPVVJDRSBtZXRob2QgZm9yIElDRS94LnggcmVxdWVzdABJbnZhbGlkIGNoYXIgaW4gdXJsIGZyYWdtZW50IHN0YXJ0AEV4cGVjdGVkIGRvdABTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3N0YXR1cwBJbnZhbGlkIHJlc3BvbnNlIHN0YXR1cwBFeHBlY3RlZCBMRiBhZnRlciBoZWFkZXJzAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMAVXNlciBjYWxsYmFjayBlcnJvcgBgb25fcmVzZXRgIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19oZWFkZXJgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3Byb3RvY29sX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fcHJvdG9jb2wARW1wdHkgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyYWN0ZXIgaW4gQ29udGVudC1MZW5ndGgAVHJhbnNmZXItRW5jb2RpbmcgY2FuJ3QgYmUgcHJlc2VudCB3aXRoIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgc2l6ZQBFeHBlY3RlZCBMRiBhZnRlciBjaHVuayBzaXplAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBVbmV4cGVjdGVkIHdoaXRlc3BhY2UgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgTEYgYWZ0ZXIgaGVhZGVyIHZhbHVlAEludmFsaWQgYFRyYW5zZmVyLUVuY29kaW5nYCBoZWFkZXIgdmFsdWUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciBjaHVuayBleHRlbnNpb24gdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZSB2YWx1ZQBJbnZhbGlkIHF1b3RlZC1wYWlyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fcHJvdG9jb2xfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciByZXNwb25zZSBsaW5lAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX25hbWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBuYW1lAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgZXh0ZW5zaW9uIG5hbWUASW52YWxpZCBzdGF0dXMgY29kZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABNaXNzaW5nIGV4cGVjdGVkIENSIGFmdGVyIGNodW5rIGRhdGEARXhwZWN0ZWQgTEYgYWZ0ZXIgY2h1bmsgZGF0YQBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AARGF0YSBhZnRlciBgQ29ubmVjdGlvbjogY2xvc2VgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBRVUVSWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAEV4cGVjdGVkIExGIGFmdGVyIENSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX1BST1RPQ09MX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19DT01QTEVURQBIUEVfQ0JfSEVBREVSX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9OQU1FX0NPTVBMRVRFAEhQRV9DQl9NRVNTQUdFX0NPTVBMRVRFAEhQRV9DQl9NRVRIT0RfQ09NUExFVEUASFBFX0NCX0hFQURFUl9GSUVMRF9DT01QTEVURQBERUxFVEUASFBFX0lOVkFMSURfRU9GX1NUQVRFAElOVkFMSURfU1NMX0NFUlRJRklDQVRFAFBBVVNFAE5PX1JFU1BPTlNFAFVOU1VQUE9SVEVEX01FRElBX1RZUEUAR09ORQBOT1RfQUNDRVBUQUJMRQBTRVJWSUNFX1VOQVZBSUxBQkxFAFJBTkdFX05PVF9TQVRJU0ZJQUJMRQBPUklHSU5fSVNfVU5SRUFDSEFCTEUAUkVTUE9OU0VfSVNfU1RBTEUAUFVSR0UATUVSR0UAUkVRVUVTVF9IRUFERVJfRklFTERTX1RPT19MQVJHRQBSRVFVRVNUX0hFQURFUl9UT09fTEFSR0UAUEFZTE9BRF9UT09fTEFSR0UASU5TVUZGSUNJRU5UX1NUT1JBR0UASFBFX1BBVVNFRF9VUEdSQURFAEhQRV9QQVVTRURfSDJfVVBHUkFERQBTT1VSQ0UAQU5OT1VOQ0UAVFJBQ0UASFBFX1VORVhQRUNURURfU1BBQ0UAREVTQ1JJQkUAVU5TVUJTQ1JJQkUAUkVDT1JEAEhQRV9JTlZBTElEX01FVEhPRABOT1RfRk9VTkQAUFJPUEZJTkQAVU5CSU5EAFJFQklORABVTkFVVEhPUklaRUQATUVUSE9EX05PVF9BTExPV0VEAEhUVFBfVkVSU0lPTl9OT1RfU1VQUE9SVEVEAEFMUkVBRFlfUkVQT1JURUQAQUNDRVBURUQATk9UX0lNUExFTUVOVEVEAExPT1BfREVURUNURUQASFBFX0NSX0VYUEVDVEVEAEhQRV9MRl9FWFBFQ1RFRABDUkVBVEVEAElNX1VTRUQASFBFX1BBVVNFRABUSU1FT1VUX09DQ1VSRUQAUEFZTUVOVF9SRVFVSVJFRABQUkVDT05ESVRJT05fUkVRVUlSRUQAUFJPWFlfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATkVUV09SS19BVVRIRU5USUNBVElPTl9SRVFVSVJFRABMRU5HVEhfUkVRVUlSRUQAU1NMX0NFUlRJRklDQVRFX1JFUVVJUkVEAFVQR1JBREVfUkVRVUlSRUQAUEFHRV9FWFBJUkVEAFBSRUNPTkRJVElPTl9GQUlMRUQARVhQRUNUQVRJT05fRkFJTEVEAFJFVkFMSURBVElPTl9GQUlMRUQAU1NMX0hBTkRTSEFLRV9GQUlMRUQATE9DS0VEAFRSQU5TRk9STUFUSU9OX0FQUExJRUQATk9UX01PRElGSUVEAE5PVF9FWFRFTkRFRABCQU5EV0lEVEhfTElNSVRfRVhDRUVERUQAU0lURV9JU19PVkVSTE9BREVEAEhFQUQARXhwZWN0ZWQgSFRUUC8sIFJUU1AvIG9yIElDRS8A5xUAAK8VAACkEgAAkhoAACYWAACeFAAA2xkAAHkVAAB+EgAA/hQAADYVAAALFgAA2BYAAPMSAABCGAAArBYAABIVAAAUFwAA7xcAAEgUAABxFwAAshoAAGsZAAB+GQAANRQAAIIaAABEFwAA/RYAAB4YAACHFwAAqhkAAJMSAAAHGAAALBcAAMoXAACkFwAA5xUAAOcVAABYFwAAOxgAAKASAAAtHAAAwxEAAEgRAADeEgAAQhMAAKQZAAD9EAAA9xUAAKUVAADvFgAA+BkAAEoWAABWFgAA9RUAAAoaAAAIGgAAARoAAKsVAABCEgAA1xAAAEwRAAAFGQAAVBYAAB4RAADKGQAAyBkAAE4WAAD/GAAAcRQAAPAVAADuFQAAlBkAAPwVAAC/GQAAmxkAAHwUAABDEQAAcBgAAJUUAAAnFAAAGRQAANUSAADUGQAARBYAAPcQAEG5OwsBAQBB0DsL4AEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBuj0LBAEAAAIAQdE9C14DBAMDAwMDAAADAwADAwADAwMDAwMDAwMDAAUAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAwADAEG6PwsEAQAAAgBB0T8LXgMAAwMDAwMAAAMDAAMDAAMDAwMDAwMDAwMABAAFAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwADAAMAQbDBAAsNbG9zZWVlcC1hbGl2ZQBBycEACwEBAEHgwQAL4AEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBycMACwEBAEHgwwAL5wEBAQEBAQEBAQEBAQECAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAWNodW5rZWQAQfHFAAteAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQBB0McACyFlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AQYDIAAsgcmFuc2Zlci1lbmNvZGluZ3BncmFkZQ0KDQpTTQ0KDQoAQanIAAsFAQIAAQMAQcDIAAtfBAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanKAAsFAQIAAQMAQcDKAAtfBAUFBgUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanMAAsEAQAAAQBBwcwAC14CAgACAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAEGpzgALBQECAAEDAEHAzgALXwQFAAAFBQUFBQUFBQUFBQYFBQUFBQUFBQUFBQUABQAHCAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQAFAAUABQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAAAAFAEGp0AALBQEBAAEBAEHA0AALAQEAQdrQAAtBAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQanSAAsFAQEAAQEAQcDSAAsBAQBBytIACwYCAAAAAAIAQeHSAAs6AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBBoNQAC50BTk9VTkNFRUNLT1VUTkVDVEVURUNSSUJFTFVTSEVURUFEU0VBUkNIUkdFQ1RJVklUWUxFTkRBUlZFT1RJRllQVElPTlNDSFNFQVlTVEFUQ0hHRVVFUllPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFVFRQQ0VUU1BBRFRQLw=="; + var wasmBuffer; + Object.defineProperty(module2, "exports", { + get: () => { + return wasmBuffer ? wasmBuffer : wasmBuffer = Buffer3.from(wasmBase64, "base64"); + } + }); } }); @@ -3377,10 +4298,9 @@ var require_constants3 = __commonJS({ ] ); var badPortsSet = new Set(badPorts); - var referrerPolicy = ( + var referrerPolicyTokens = ( /** @type {const} */ [ - "", "no-referrer", "no-referrer-when-downgrade", "same-origin", @@ -3391,7 +4311,14 @@ var require_constants3 = __commonJS({ "unsafe-url" ] ); - var referrerPolicySet = new Set(referrerPolicy); + var referrerPolicy = ( + /** @type {const} */ + [ + "", + ...referrerPolicyTokens + ] + ); + var referrerPolicyTokensSet = new Set(referrerPolicyTokens); var requestRedirect = ( /** @type {const} */ ["follow", "manual", "error"] @@ -3484,7 +4411,7 @@ var require_constants3 = __commonJS({ corsSafeListedMethodsSet, safeMethodsSet, forbiddenMethodsSet, - referrerPolicySet + referrerPolicyTokens: referrerPolicyTokensSet }; } }); @@ -3525,65 +4452,33 @@ var require_global = __commonJS({ } }); -// node_modules/undici/lib/web/fetch/data-url.js -var require_data_url = __commonJS({ - "node_modules/undici/lib/web/fetch/data-url.js"(exports2, module2) { +// node_modules/undici/lib/encoding/index.js +var require_encoding = __commonJS({ + "node_modules/undici/lib/encoding/index.js"(exports2, module2) { "use strict"; - var assert = require("node:assert"); - var encoder2 = new TextEncoder(); - var HTTP_TOKEN_CODEPOINTS = /^[!#$%&'*+\-.^_|~A-Za-z0-9]+$/; - var HTTP_WHITESPACE_REGEX = /[\u000A\u000D\u0009\u0020]/; - var ASCII_WHITESPACE_REPLACE_REGEX = /[\u0009\u000A\u000C\u000D\u0020]/g; - var HTTP_QUOTED_STRING_TOKENS = /^[\u0009\u0020-\u007E\u0080-\u00FF]+$/; - function dataURLProcessor(dataURL) { - assert(dataURL.protocol === "data:"); - let input = URLSerializer(dataURL, true); - input = input.slice(5); - const position = { position: 0 }; - let mimeType = collectASequenceOfCodePointsFast( - ",", - input, - position - ); - const mimeTypeLength = mimeType.length; - mimeType = removeASCIIWhitespace(mimeType, true, true); - if (position.position >= input.length) { - return "failure"; - } - position.position++; - const encodedBody = input.slice(mimeTypeLength + 1); - let body = stringPercentDecode(encodedBody); - if (/;(\u0020){0,}base64$/i.test(mimeType)) { - const stringBody = isomorphicDecode(body); - body = forgivingBase64(stringBody); - if (body === "failure") { - return "failure"; - } - mimeType = mimeType.slice(0, -6); - mimeType = mimeType.replace(/(\u0020)+$/, ""); - mimeType = mimeType.slice(0, -1); - } - if (mimeType.startsWith(";")) { - mimeType = "text/plain" + mimeType; - } - let mimeTypeRecord = parseMIMEType(mimeType); - if (mimeTypeRecord === "failure") { - mimeTypeRecord = parseMIMEType("text/plain;charset=US-ASCII"); - } - return { mimeType: mimeTypeRecord, body }; - } - function URLSerializer(url2, excludeFragment = false) { - if (!excludeFragment) { - return url2.href; + var textDecoder = new TextDecoder(); + function utf8DecodeBytes(buffer) { + if (buffer.length === 0) { + return ""; } - const href = url2.href; - const hashLength = url2.hash.length; - const serialized = hashLength === 0 ? href : href.substring(0, href.length - hashLength); - if (!hashLength && href.endsWith("#")) { - return serialized.slice(0, -1); + if (buffer[0] === 239 && buffer[1] === 187 && buffer[2] === 191) { + buffer = buffer.subarray(3); } - return serialized; + const output = textDecoder.decode(buffer); + return output; } + module2.exports = { + utf8DecodeBytes + }; + } +}); + +// node_modules/undici/lib/web/infra/index.js +var require_infra = __commonJS({ + "node_modules/undici/lib/web/infra/index.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { utf8DecodeBytes } = require_encoding(); function collectASequenceOfCodePoints(condition, input, position) { let result = ""; while (position.position < input.length && condition(input[position.position])) { @@ -3602,24 +4497,178 @@ var require_data_url = __commonJS({ position.position = idx; return input.slice(start, position.position); } - function stringPercentDecode(input) { - const bytes = encoder2.encode(input); - return percentDecode(bytes); - } - function isHexCharByte(byte) { - return byte >= 48 && byte <= 57 || byte >= 65 && byte <= 70 || byte >= 97 && byte <= 102; - } - function hexByteToNumber(byte) { - return ( - // 0-9 - byte >= 48 && byte <= 57 ? byte - 48 : (byte & 223) - 55 - ); + var ASCII_WHITESPACE_REPLACE_REGEX = /[\u0009\u000A\u000C\u000D\u0020]/g; + var nonASCIIRegex = /[^\x00-\x7F]/; + function asciiLowercase(str) { + return nonASCIIRegex.test(str) ? str.replace(/[A-Z]+/g, (upper) => upper.toLowerCase()) : str.toLowerCase(); } - function percentDecode(input) { - const length = input.length; - const output = new Uint8Array(length); - let j = 0; - for (let i = 0; i < length; ++i) { + function forgivingBase64(data) { + data = data.replace(ASCII_WHITESPACE_REPLACE_REGEX, ""); + let dataLength = data.length; + if (dataLength % 4 === 0) { + if (data.charCodeAt(dataLength - 1) === 61) { + --dataLength; + if (data.charCodeAt(dataLength - 1) === 61) { + --dataLength; + } + } + } + if (dataLength % 4 === 1) { + return "failure"; + } + if (/[^+/0-9A-Za-z]/.test(data.length === dataLength ? data : data.substring(0, dataLength))) { + return "failure"; + } + const buffer = Buffer.from(data, "base64"); + return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength); + } + function isASCIIWhitespace(char) { + return char === 9 || // \t + char === 10 || // \n + char === 12 || // \f + char === 13 || // \r + char === 32; + } + function isomorphicDecode(input) { + const length = input.length; + if ((2 << 15) - 1 > length) { + return String.fromCharCode.apply(null, input); + } + let result = ""; + let i = 0; + let addition = (2 << 15) - 1; + while (i < length) { + if (i + addition > length) { + addition = length - i; + } + result += String.fromCharCode.apply(null, input.subarray(i, i += addition)); + } + return result; + } + var invalidIsomorphicEncodeValueRegex = /[^\x00-\xFF]/; + function isomorphicEncode(input) { + assert(!invalidIsomorphicEncodeValueRegex.test(input)); + return input; + } + function parseJSONFromBytes(bytes) { + return JSON.parse(utf8DecodeBytes(bytes)); + } + function removeASCIIWhitespace(str, leading = true, trailing = true) { + return removeChars(str, leading, trailing, isASCIIWhitespace); + } + function removeChars(str, leading, trailing, predicate) { + let lead = 0; + let trail = str.length - 1; + if (leading) { + while (lead < str.length && predicate(str.charCodeAt(lead))) lead++; + } + if (trailing) { + while (trail > 0 && predicate(str.charCodeAt(trail))) trail--; + } + return lead === 0 && trail === str.length - 1 ? str : str.slice(lead, trail + 1); + } + function serializeJavascriptValueToJSONString(value) { + const result = JSON.stringify(value); + if (result === void 0) { + throw new TypeError("Value is not JSON serializable"); + } + assert(typeof result === "string"); + return result; + } + module2.exports = { + asciiLowercase, + collectASequenceOfCodePoints, + collectASequenceOfCodePointsFast, + forgivingBase64, + isASCIIWhitespace, + isomorphicDecode, + isomorphicEncode, + parseJSONFromBytes, + removeASCIIWhitespace, + removeChars, + serializeJavascriptValueToJSONString + }; + } +}); + +// node_modules/undici/lib/web/fetch/data-url.js +var require_data_url = __commonJS({ + "node_modules/undici/lib/web/fetch/data-url.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { forgivingBase64, collectASequenceOfCodePoints, collectASequenceOfCodePointsFast, isomorphicDecode, removeASCIIWhitespace, removeChars } = require_infra(); + var encoder2 = new TextEncoder(); + var HTTP_TOKEN_CODEPOINTS = /^[-!#$%&'*+.^_|~A-Za-z0-9]+$/u; + var HTTP_WHITESPACE_REGEX = /[\u000A\u000D\u0009\u0020]/u; + var HTTP_QUOTED_STRING_TOKENS = /^[\u0009\u0020-\u007E\u0080-\u00FF]+$/u; + function dataURLProcessor(dataURL) { + assert(dataURL.protocol === "data:"); + let input = URLSerializer(dataURL, true); + input = input.slice(5); + const position = { position: 0 }; + let mimeType = collectASequenceOfCodePointsFast( + ",", + input, + position + ); + const mimeTypeLength = mimeType.length; + mimeType = removeASCIIWhitespace(mimeType, true, true); + if (position.position >= input.length) { + return "failure"; + } + position.position++; + const encodedBody = input.slice(mimeTypeLength + 1); + let body = stringPercentDecode(encodedBody); + if (/;(?:\u0020*)base64$/ui.test(mimeType)) { + const stringBody = isomorphicDecode(body); + body = forgivingBase64(stringBody); + if (body === "failure") { + return "failure"; + } + mimeType = mimeType.slice(0, -6); + mimeType = mimeType.replace(/(\u0020+)$/u, ""); + mimeType = mimeType.slice(0, -1); + } + if (mimeType.startsWith(";")) { + mimeType = "text/plain" + mimeType; + } + let mimeTypeRecord = parseMIMEType(mimeType); + if (mimeTypeRecord === "failure") { + mimeTypeRecord = parseMIMEType("text/plain;charset=US-ASCII"); + } + return { mimeType: mimeTypeRecord, body }; + } + function URLSerializer(url2, excludeFragment = false) { + if (!excludeFragment) { + return url2.href; + } + const href = url2.href; + const hashLength = url2.hash.length; + const serialized = hashLength === 0 ? href : href.substring(0, href.length - hashLength); + if (!hashLength && href.endsWith("#")) { + return serialized.slice(0, -1); + } + return serialized; + } + function stringPercentDecode(input) { + const bytes = encoder2.encode(input); + return percentDecode(bytes); + } + function isHexCharByte(byte) { + return byte >= 48 && byte <= 57 || byte >= 65 && byte <= 70 || byte >= 97 && byte <= 102; + } + function hexByteToNumber(byte) { + return ( + // 0-9 + byte >= 48 && byte <= 57 ? byte - 48 : (byte & 223) - 55 + ); + } + function percentDecode(input) { + const length = input.length; + const output = new Uint8Array(length); + let j = 0; + let i = 0; + while (i < length) { const byte = input[i]; if (byte !== 37) { output[j++] = byte; @@ -3629,6 +4678,7 @@ var require_data_url = __commonJS({ output[j++] = hexByteToNumber(input[i + 1]) << 4 | hexByteToNumber(input[i + 2]); i += 2; } + ++i; } return length === j ? output : output.subarray(0, j); } @@ -3643,7 +4693,7 @@ var require_data_url = __commonJS({ if (type.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(type)) { return "failure"; } - if (position.position > input.length) { + if (position.position >= input.length) { return "failure"; } position.position++; @@ -3686,7 +4736,7 @@ var require_data_url = __commonJS({ } position.position++; } - if (position.position > input.length) { + if (position.position >= input.length) { break; } let parameterValue = null; @@ -3714,27 +4764,7 @@ var require_data_url = __commonJS({ } return mimeType; } - function forgivingBase64(data) { - data = data.replace(ASCII_WHITESPACE_REPLACE_REGEX, ""); - let dataLength = data.length; - if (dataLength % 4 === 0) { - if (data.charCodeAt(dataLength - 1) === 61) { - --dataLength; - if (data.charCodeAt(dataLength - 1) === 61) { - --dataLength; - } - } - } - if (dataLength % 4 === 1) { - return "failure"; - } - if (/[^+/0-9A-Za-z]/.test(data.length === dataLength ? data : data.substring(0, dataLength))) { - return "failure"; - } - const buffer = Buffer.from(data, "base64"); - return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength); - } - function collectAnHTTPQuotedString(input, position, extractValue) { + function collectAnHTTPQuotedString(input, position, extractValue = false) { const positionStart = position.position; let value = ""; assert(input[position.position] === '"'); @@ -3776,7 +4806,7 @@ var require_data_url = __commonJS({ serialization += name; serialization += "="; if (!HTTP_TOKEN_CODEPOINTS.test(value)) { - value = value.replace(/(\\|")/g, "\\$1"); + value = value.replace(/[\\"]/ug, "\\$&"); value = '"' + value; value += '"'; } @@ -3790,39 +4820,6 @@ var require_data_url = __commonJS({ function removeHTTPWhitespace(str, leading = true, trailing = true) { return removeChars(str, leading, trailing, isHTTPWhiteSpace); } - function isASCIIWhitespace(char) { - return char === 13 || char === 10 || char === 9 || char === 12 || char === 32; - } - function removeASCIIWhitespace(str, leading = true, trailing = true) { - return removeChars(str, leading, trailing, isASCIIWhitespace); - } - function removeChars(str, leading, trailing, predicate) { - let lead = 0; - let trail = str.length - 1; - if (leading) { - while (lead < str.length && predicate(str.charCodeAt(lead))) lead++; - } - if (trailing) { - while (trail > 0 && predicate(str.charCodeAt(trail))) trail--; - } - return lead === 0 && trail === str.length - 1 ? str : str.slice(lead, trail + 1); - } - function isomorphicDecode(input) { - const length = input.length; - if ((2 << 15) - 1 > length) { - return String.fromCharCode.apply(null, input); - } - let result = ""; - let i = 0; - let addition = (2 << 15) - 1; - while (i < length) { - if (i + addition > length) { - addition = length - i; - } - result += String.fromCharCode.apply(null, input.subarray(i, i += addition)); - } - return result; - } function minimizeSupportedMimeType(mimeType) { switch (mimeType.essence) { case "application/ecmascript": @@ -3862,40 +4859,149 @@ var require_data_url = __commonJS({ module2.exports = { dataURLProcessor, URLSerializer, - collectASequenceOfCodePoints, - collectASequenceOfCodePointsFast, stringPercentDecode, parseMIMEType, collectAnHTTPQuotedString, serializeAMimeType, - removeChars, removeHTTPWhitespace, minimizeSupportedMimeType, - HTTP_TOKEN_CODEPOINTS, - isomorphicDecode + HTTP_TOKEN_CODEPOINTS }; } }); -// node_modules/undici/lib/web/fetch/webidl.js +// node_modules/undici/lib/util/runtime-features.js +var require_runtime_features = __commonJS({ + "node_modules/undici/lib/util/runtime-features.js"(exports2, module2) { + "use strict"; + var lazyLoaders = { + __proto__: null, + "node:crypto": () => require("node:crypto"), + "node:sqlite": () => require("node:sqlite"), + "node:worker_threads": () => require("node:worker_threads"), + "node:zlib": () => require("node:zlib") + }; + function detectRuntimeFeatureByNodeModule(moduleName) { + try { + lazyLoaders[moduleName](); + return true; + } catch (err) { + if (err.code !== "ERR_UNKNOWN_BUILTIN_MODULE" && err.code !== "ERR_NO_CRYPTO") { + throw err; + } + return false; + } + } + function detectRuntimeFeatureByExportedProperty(moduleName, property) { + const module3 = lazyLoaders[moduleName](); + return typeof module3[property] !== "undefined"; + } + var runtimeFeaturesByExportedProperty = ( + /** @type {const} */ + ["markAsUncloneable", "zstd"] + ); + var exportedPropertyLookup = { + markAsUncloneable: ["node:worker_threads", "markAsUncloneable"], + zstd: ["node:zlib", "createZstdDecompress"] + }; + var runtimeFeaturesAsNodeModule = ( + /** @type {const} */ + ["crypto", "sqlite"] + ); + var features = ( + /** @type {const} */ + [ + ...runtimeFeaturesAsNodeModule, + ...runtimeFeaturesByExportedProperty + ] + ); + function detectRuntimeFeature(feature) { + if (runtimeFeaturesAsNodeModule.includes( + /** @type {RuntimeFeatureByNodeModule} */ + feature + )) { + return detectRuntimeFeatureByNodeModule(`node:${feature}`); + } else if (runtimeFeaturesByExportedProperty.includes( + /** @type {RuntimeFeatureByExportedProperty} */ + feature + )) { + const [moduleName, property] = exportedPropertyLookup[feature]; + return detectRuntimeFeatureByExportedProperty(moduleName, property); + } + throw new TypeError(`unknown feature: ${feature}`); + } + var RuntimeFeatures = class { + /** @type {Map} */ + #map = /* @__PURE__ */ new Map(); + /** + * Clears all cached feature detections. + */ + clear() { + this.#map.clear(); + } + /** + * @param {Feature} feature + * @returns {boolean} + */ + has(feature) { + return this.#map.get(feature) ?? this.#detectRuntimeFeature(feature); + } + /** + * @param {Feature} feature + * @param {boolean} value + */ + set(feature, value) { + if (features.includes(feature) === false) { + throw new TypeError(`unknown feature: ${feature}`); + } + this.#map.set(feature, value); + } + /** + * @param {Feature} feature + * @returns {boolean} + */ + #detectRuntimeFeature(feature) { + const result = detectRuntimeFeature(feature); + this.#map.set(feature, result); + return result; + } + }; + var instance8 = new RuntimeFeatures(); + module2.exports.runtimeFeatures = instance8; + module2.exports.default = instance8; + } +}); + +// node_modules/undici/lib/web/webidl/index.js var require_webidl = __commonJS({ - "node_modules/undici/lib/web/fetch/webidl.js"(exports2, module2) { + "node_modules/undici/lib/web/webidl/index.js"(exports2, module2) { "use strict"; + var assert = require("node:assert"); var { types: types2, inspect } = require("node:util"); - var { markAsUncloneable } = require("node:worker_threads"); - var { toUSVString } = require_util(); - var webidl = {}; - webidl.converters = {}; - webidl.util = {}; - webidl.errors = {}; + var { runtimeFeatures } = require_runtime_features(); + var UNDEFINED = 1; + var BOOLEAN = 2; + var STRING = 3; + var SYMBOL = 4; + var NUMBER = 5; + var BIGINT = 6; + var NULL = 7; + var OBJECT = 8; + var FunctionPrototypeSymbolHasInstance = Function.call.bind(Function.prototype[Symbol.hasInstance]); + var webidl = { + converters: {}, + util: {}, + errors: {}, + is: {} + }; webidl.errors.exception = function(message) { return new TypeError(`${message.header}: ${message.message}`); }; - webidl.errors.conversionFailed = function(context5) { - const plural = context5.types.length === 1 ? "" : " one of"; - const message = `${context5.argument} could not be converted to${plural}: ${context5.types.join(", ")}.`; + webidl.errors.conversionFailed = function(opts) { + const plural = opts.types.length === 1 ? "" : " one of"; + const message = `${opts.argument} could not be converted to${plural}: ${opts.types.join(", ")}.`; return webidl.errors.exception({ - header: context5.prefix, + header: opts.prefix, message }); }; @@ -3905,20 +5011,22 @@ var require_webidl = __commonJS({ message: `"${context5.value}" is an invalid ${context5.type}.` }); }; - webidl.brandCheck = function(V, I, opts) { - if (opts?.strict !== false) { - if (!(V instanceof I)) { - const err = new TypeError("Illegal invocation"); - err.code = "ERR_INVALID_THIS"; - throw err; - } - } else { - if (V?.[Symbol.toStringTag] !== I.prototype[Symbol.toStringTag]) { + webidl.brandCheck = function(V, I) { + if (!FunctionPrototypeSymbolHasInstance(I, V)) { + const err = new TypeError("Illegal invocation"); + err.code = "ERR_INVALID_THIS"; + throw err; + } + }; + webidl.brandCheckMultiple = function(List3) { + const prototypes = List3.map((c) => webidl.util.MakeTypeAssertion(c)); + return (V) => { + if (prototypes.every((typeCheck) => !typeCheck(V))) { const err = new TypeError("Illegal invocation"); err.code = "ERR_INVALID_THIS"; throw err; } - } + }; }; webidl.argumentLengthCheck = function({ length }, min, ctx) { if (length < min) { @@ -3934,32 +5042,65 @@ var require_webidl = __commonJS({ message: "Illegal constructor" }); }; + webidl.util.MakeTypeAssertion = function(I) { + return (O) => FunctionPrototypeSymbolHasInstance(I, O); + }; webidl.util.Type = function(V) { switch (typeof V) { case "undefined": - return "Undefined"; + return UNDEFINED; case "boolean": - return "Boolean"; + return BOOLEAN; case "string": - return "String"; + return STRING; case "symbol": - return "Symbol"; + return SYMBOL; case "number": - return "Number"; + return NUMBER; case "bigint": - return "BigInt"; + return BIGINT; case "function": case "object": { if (V === null) { - return "Null"; + return NULL; } - return "Object"; + return OBJECT; } } }; - webidl.util.markAsUncloneable = markAsUncloneable || (() => { - }); - webidl.util.ConvertToInt = function(V, bitLength, signedness, opts) { + webidl.util.Types = { + UNDEFINED, + BOOLEAN, + STRING, + SYMBOL, + NUMBER, + BIGINT, + NULL, + OBJECT + }; + webidl.util.TypeValueToString = function(o) { + switch (webidl.util.Type(o)) { + case UNDEFINED: + return "Undefined"; + case BOOLEAN: + return "Boolean"; + case STRING: + return "String"; + case SYMBOL: + return "Symbol"; + case NUMBER: + return "Number"; + case BIGINT: + return "BigInt"; + case NULL: + return "Null"; + case OBJECT: + return "Object"; + } + }; + webidl.util.markAsUncloneable = runtimeFeatures.has("markAsUncloneable") ? require("node:worker_threads").markAsUncloneable : () => { + }; + webidl.util.ConvertToInt = function(V, bitLength, signedness, flags) { let upperBound; let lowerBound; if (bitLength === 64) { @@ -3973,14 +5114,14 @@ var require_webidl = __commonJS({ lowerBound = 0; upperBound = Math.pow(2, bitLength) - 1; } else { - lowerBound = Math.pow(-2, bitLength) - 1; + lowerBound = -Math.pow(2, bitLength - 1); upperBound = Math.pow(2, bitLength - 1) - 1; } let x = Number(V); if (x === 0) { x = 0; } - if (opts?.enforceRange === true) { + if (webidl.util.HasFlag(flags, webidl.attributes.EnforceRange)) { if (Number.isNaN(x) || x === Number.POSITIVE_INFINITY || x === Number.NEGATIVE_INFINITY) { throw webidl.errors.exception({ header: "Integer conversion", @@ -3996,7 +5137,7 @@ var require_webidl = __commonJS({ } return x; } - if (!Number.isNaN(x) && opts?.clamp === true) { + if (!Number.isNaN(x) && webidl.util.HasFlag(flags, webidl.attributes.Clamp)) { x = Math.min(Math.max(x, lowerBound), upperBound); if (Math.floor(x) % 2 === 0) { x = Math.floor(x); @@ -4010,7 +5151,7 @@ var require_webidl = __commonJS({ } x = webidl.util.IntegerPart(x); x = x % Math.pow(2, bitLength); - if (signedness === "signed" && x >= Math.pow(2, bitLength) - 1) { + if (signedness === "signed" && x >= Math.pow(2, bitLength - 1)) { return x - Math.pow(2, bitLength); } return x; @@ -4025,19 +5166,36 @@ var require_webidl = __commonJS({ webidl.util.Stringify = function(V) { const type = webidl.util.Type(V); switch (type) { - case "Symbol": + case SYMBOL: return `Symbol(${V.description})`; - case "Object": + case OBJECT: return inspect(V); - case "String": + case STRING: return `"${V}"`; + case BIGINT: + return `${V}n`; default: return `${V}`; } }; + webidl.util.IsResizableArrayBuffer = function(V) { + if (types2.isArrayBuffer(V)) { + return V.resizable; + } + if (types2.isSharedArrayBuffer(V)) { + return V.growable; + } + throw webidl.errors.exception({ + header: "IsResizableArrayBuffer", + message: `"${webidl.util.Stringify(V)}" is not an array buffer.` + }); + }; + webidl.util.HasFlag = function(flags, attributes) { + return typeof flags === "number" && (flags & attributes) === attributes; + }; webidl.sequenceConverter = function(converter) { return (V, prefix, argument, Iterable) => { - if (webidl.util.Type(V) !== "Object") { + if (webidl.util.Type(V) !== OBJECT) { throw webidl.errors.exception({ header: prefix, message: `${argument} (${webidl.util.Stringify(V)}) is not iterable.` @@ -4064,18 +5222,19 @@ var require_webidl = __commonJS({ }; webidl.recordConverter = function(keyConverter, valueConverter) { return (O, prefix, argument) => { - if (webidl.util.Type(O) !== "Object") { + if (webidl.util.Type(O) !== OBJECT) { throw webidl.errors.exception({ header: prefix, - message: `${argument} ("${webidl.util.Type(O)}") is not an Object.` + message: `${argument} ("${webidl.util.TypeValueToString(O)}") is not an Object.` }); } const result = {}; if (!types2.isProxy(O)) { const keys2 = [...Object.getOwnPropertyNames(O), ...Object.getOwnPropertySymbols(O)]; for (const key of keys2) { - const typedKey = keyConverter(key, prefix, argument); - const typedValue = valueConverter(O[key], prefix, argument); + const keyName = webidl.util.Stringify(key); + const typedKey = keyConverter(key, prefix, `Key ${keyName} in ${argument}`); + const typedValue = valueConverter(O[key], prefix, `${argument}[${keyName}]`); result[typedKey] = typedValue; } return result; @@ -4092,24 +5251,22 @@ var require_webidl = __commonJS({ return result; }; }; - webidl.interfaceConverter = function(i) { - return (V, prefix, argument, opts) => { - if (opts?.strict !== false && !(V instanceof i)) { + webidl.interfaceConverter = function(TypeCheck, name) { + return (V, prefix, argument) => { + if (!TypeCheck(V)) { throw webidl.errors.exception({ header: prefix, - message: `Expected ${argument} ("${webidl.util.Stringify(V)}") to be an instance of ${i.name}.` + message: `Expected ${argument} ("${webidl.util.Stringify(V)}") to be an instance of ${name}.` }); } return V; }; }; webidl.dictionaryConverter = function(converters) { + converters.sort((a, b) => (a.key > b.key) - (a.key < b.key)); return (dictionary, prefix, argument) => { - const type = webidl.util.Type(dictionary); const dict = {}; - if (type === "Null" || type === "Undefined") { - return dict; - } else if (type !== "Object") { + if (dictionary != null && webidl.util.Type(dictionary) !== OBJECT) { throw webidl.errors.exception({ header: prefix, message: `Expected ${dictionary} to be one of: Null, Undefined, Object.` @@ -4118,17 +5275,17 @@ var require_webidl = __commonJS({ for (const options of converters) { const { key, defaultValue, required, converter } = options; if (required === true) { - if (!Object.hasOwn(dictionary, key)) { + if (dictionary == null || !Object.hasOwn(dictionary, key)) { throw webidl.errors.exception({ header: prefix, message: `Missing required key "${key}".` }); } } - let value = dictionary[key]; - const hasDefault = Object.hasOwn(options, "defaultValue"); - if (hasDefault && value !== null) { - value ??= defaultValue(); + let value = dictionary?.[key]; + const hasDefault = defaultValue !== void 0; + if (hasDefault && value === void 0) { + value = defaultValue(); } if (required || hasDefault || value !== void 0) { value = converter(value, prefix, `${argument}.${key}`); @@ -4152,8 +5309,42 @@ var require_webidl = __commonJS({ return converter(V, prefix, argument); }; }; - webidl.converters.DOMString = function(V, prefix, argument, opts) { - if (V === null && opts?.legacyNullToEmptyString) { + webidl.is.USVString = function(value) { + return typeof value === "string" && value.isWellFormed(); + }; + webidl.is.ReadableStream = webidl.util.MakeTypeAssertion(ReadableStream); + webidl.is.Blob = webidl.util.MakeTypeAssertion(Blob); + webidl.is.URLSearchParams = webidl.util.MakeTypeAssertion(URLSearchParams); + webidl.is.File = webidl.util.MakeTypeAssertion(File); + webidl.is.URL = webidl.util.MakeTypeAssertion(URL); + webidl.is.AbortSignal = webidl.util.MakeTypeAssertion(AbortSignal); + webidl.is.MessagePort = webidl.util.MakeTypeAssertion(MessagePort); + webidl.is.BufferSource = function(V) { + return types2.isArrayBuffer(V) || ArrayBuffer.isView(V) && types2.isArrayBuffer(V.buffer); + }; + webidl.util.getCopyOfBytesHeldByBufferSource = function(bufferSource) { + const jsBufferSource = bufferSource; + let jsArrayBuffer = jsBufferSource; + let offset = 0; + let length = 0; + if (types2.isTypedArray(jsBufferSource) || types2.isDataView(jsBufferSource)) { + jsArrayBuffer = jsBufferSource.buffer; + offset = jsBufferSource.byteOffset; + length = jsBufferSource.byteLength; + } else { + assert(types2.isAnyArrayBuffer(jsBufferSource)); + length = jsBufferSource.byteLength; + } + if (jsArrayBuffer.detached) { + return new Uint8Array(0); + } + const bytes = new Uint8Array(length); + const view = new Uint8Array(jsArrayBuffer, offset, length); + bytes.set(view); + return bytes; + }; + webidl.converters.DOMString = function(V, prefix, argument, flags) { + if (V === null && webidl.util.HasFlag(flags, webidl.attributes.LegacyNullToEmptyString)) { return ""; } if (typeof V === "symbol") { @@ -4165,7 +5356,13 @@ var require_webidl = __commonJS({ return String(V); }; webidl.converters.ByteString = function(V, prefix, argument) { - const x = webidl.converters.DOMString(V, prefix, argument); + if (typeof V === "symbol") { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} is a symbol, which cannot be converted to a ByteString.` + }); + } + const x = String(V); for (let index2 = 0; index2 < x.length; index2++) { if (x.charCodeAt(index2) > 255) { throw new TypeError( @@ -4175,7 +5372,12 @@ var require_webidl = __commonJS({ } return x; }; - webidl.converters.USVString = toUSVString; + webidl.converters.USVString = function(value) { + if (typeof value === "string") { + return value.toWellFormed(); + } + return `${value}`.toWellFormed(); + }; webidl.converters.boolean = function(V) { const x = Boolean(V); return x; @@ -4184,100 +5386,154 @@ var require_webidl = __commonJS({ return V; }; webidl.converters["long long"] = function(V, prefix, argument) { - const x = webidl.util.ConvertToInt(V, 64, "signed", void 0, prefix, argument); + const x = webidl.util.ConvertToInt(V, 64, "signed", 0, prefix, argument); return x; }; webidl.converters["unsigned long long"] = function(V, prefix, argument) { - const x = webidl.util.ConvertToInt(V, 64, "unsigned", void 0, prefix, argument); + const x = webidl.util.ConvertToInt(V, 64, "unsigned", 0, prefix, argument); return x; }; webidl.converters["unsigned long"] = function(V, prefix, argument) { - const x = webidl.util.ConvertToInt(V, 32, "unsigned", void 0, prefix, argument); + const x = webidl.util.ConvertToInt(V, 32, "unsigned", 0, prefix, argument); return x; }; - webidl.converters["unsigned short"] = function(V, prefix, argument, opts) { - const x = webidl.util.ConvertToInt(V, 16, "unsigned", opts, prefix, argument); + webidl.converters["unsigned short"] = function(V, prefix, argument, flags) { + const x = webidl.util.ConvertToInt(V, 16, "unsigned", flags, prefix, argument); return x; }; - webidl.converters.ArrayBuffer = function(V, prefix, argument, opts) { - if (webidl.util.Type(V) !== "Object" || !types2.isAnyArrayBuffer(V)) { + webidl.converters.ArrayBuffer = function(V, prefix, argument, flags) { + if (webidl.util.Type(V) !== OBJECT || !types2.isArrayBuffer(V)) { throw webidl.errors.conversionFailed({ prefix, argument: `${argument} ("${webidl.util.Stringify(V)}")`, types: ["ArrayBuffer"] }); } - if (opts?.allowShared === false && types2.isSharedArrayBuffer(V)) { + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) { throw webidl.errors.exception({ - header: "ArrayBuffer", - message: "SharedArrayBuffer is not allowed." + header: prefix, + message: `${argument} cannot be a resizable ArrayBuffer.` }); } - if (V.resizable || V.growable) { + return V; + }; + webidl.converters.SharedArrayBuffer = function(V, prefix, argument, flags) { + if (webidl.util.Type(V) !== OBJECT || !types2.isSharedArrayBuffer(V)) { + throw webidl.errors.conversionFailed({ + prefix, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, + types: ["SharedArrayBuffer"] + }); + } + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) { throw webidl.errors.exception({ - header: "ArrayBuffer", - message: "Received a resizable ArrayBuffer." + header: prefix, + message: `${argument} cannot be a resizable SharedArrayBuffer.` }); } return V; }; - webidl.converters.TypedArray = function(V, T, prefix, name, opts) { - if (webidl.util.Type(V) !== "Object" || !types2.isTypedArray(V) || V.constructor.name !== T.name) { + webidl.converters.TypedArray = function(V, T, prefix, argument, flags) { + if (webidl.util.Type(V) !== OBJECT || !types2.isTypedArray(V) || V.constructor.name !== T.name) { throw webidl.errors.conversionFailed({ prefix, - argument: `${name} ("${webidl.util.Stringify(V)}")`, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, types: [T.name] }); } - if (opts?.allowShared === false && types2.isSharedArrayBuffer(V.buffer)) { + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types2.isSharedArrayBuffer(V.buffer)) { throw webidl.errors.exception({ - header: "ArrayBuffer", - message: "SharedArrayBuffer is not allowed." + header: prefix, + message: `${argument} cannot be a view on a shared array buffer.` }); } - if (V.buffer.resizable || V.buffer.growable) { + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) { throw webidl.errors.exception({ - header: "ArrayBuffer", - message: "Received a resizable ArrayBuffer." + header: prefix, + message: `${argument} cannot be a view on a resizable array buffer.` }); } return V; }; - webidl.converters.DataView = function(V, prefix, name, opts) { - if (webidl.util.Type(V) !== "Object" || !types2.isDataView(V)) { + webidl.converters.DataView = function(V, prefix, argument, flags) { + if (webidl.util.Type(V) !== OBJECT || !types2.isDataView(V)) { + throw webidl.errors.conversionFailed({ + prefix, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, + types: ["DataView"] + }); + } + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types2.isSharedArrayBuffer(V.buffer)) { throw webidl.errors.exception({ header: prefix, - message: `${name} is not a DataView.` + message: `${argument} cannot be a view on a shared array buffer.` }); } - if (opts?.allowShared === false && types2.isSharedArrayBuffer(V.buffer)) { + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) { throw webidl.errors.exception({ - header: "ArrayBuffer", - message: "SharedArrayBuffer is not allowed." + header: prefix, + message: `${argument} cannot be a view on a resizable array buffer.` }); } - if (V.buffer.resizable || V.buffer.growable) { + return V; + }; + webidl.converters.ArrayBufferView = function(V, prefix, argument, flags) { + if (webidl.util.Type(V) !== OBJECT || !types2.isArrayBufferView(V)) { + throw webidl.errors.conversionFailed({ + prefix, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, + types: ["ArrayBufferView"] + }); + } + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types2.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} cannot be a view on a shared array buffer.` + }); + } + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) { throw webidl.errors.exception({ - header: "ArrayBuffer", - message: "Received a resizable ArrayBuffer." + header: prefix, + message: `${argument} cannot be a view on a resizable array buffer.` }); } return V; }; - webidl.converters.BufferSource = function(V, prefix, name, opts) { - if (types2.isAnyArrayBuffer(V)) { - return webidl.converters.ArrayBuffer(V, prefix, name, { ...opts, allowShared: false }); + webidl.converters.BufferSource = function(V, prefix, argument, flags) { + if (types2.isArrayBuffer(V)) { + return webidl.converters.ArrayBuffer(V, prefix, argument, flags); + } + if (types2.isArrayBufferView(V)) { + flags &= ~webidl.attributes.AllowShared; + return webidl.converters.ArrayBufferView(V, prefix, argument, flags); + } + if (types2.isSharedArrayBuffer(V)) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} cannot be a SharedArrayBuffer.` + }); + } + throw webidl.errors.conversionFailed({ + prefix, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, + types: ["ArrayBuffer", "ArrayBufferView"] + }); + }; + webidl.converters.AllowSharedBufferSource = function(V, prefix, argument, flags) { + if (types2.isArrayBuffer(V)) { + return webidl.converters.ArrayBuffer(V, prefix, argument, flags); } - if (types2.isTypedArray(V)) { - return webidl.converters.TypedArray(V, V.constructor, prefix, name, { ...opts, allowShared: false }); + if (types2.isSharedArrayBuffer(V)) { + return webidl.converters.SharedArrayBuffer(V, prefix, argument, flags); } - if (types2.isDataView(V)) { - return webidl.converters.DataView(V, prefix, name, { ...opts, allowShared: false }); + if (types2.isArrayBufferView(V)) { + flags |= webidl.attributes.AllowShared; + return webidl.converters.ArrayBufferView(V, prefix, argument, flags); } throw webidl.errors.conversionFailed({ prefix, - argument: `${name} ("${webidl.util.Stringify(V)}")`, - types: ["BufferSource"] + argument: `${argument} ("${webidl.util.Stringify(V)}")`, + types: ["ArrayBuffer", "SharedArrayBuffer", "ArrayBufferView"] }); }; webidl.converters["sequence"] = webidl.sequenceConverter( @@ -4290,6 +5546,28 @@ var require_webidl = __commonJS({ webidl.converters.ByteString, webidl.converters.ByteString ); + webidl.converters.Blob = webidl.interfaceConverter(webidl.is.Blob, "Blob"); + webidl.converters.AbortSignal = webidl.interfaceConverter( + webidl.is.AbortSignal, + "AbortSignal" + ); + webidl.converters.EventHandlerNonNull = function(V) { + if (webidl.util.Type(V) !== OBJECT) { + return null; + } + if (typeof V === "function") { + return V; + } + return () => { + }; + }; + webidl.attributes = { + Clamp: 1 << 0, + EnforceRange: 1 << 1, + AllowShared: 1 << 2, + AllowResizable: 1 << 3, + LegacyNullToEmptyString: 1 << 4 + }; module2.exports = { webidl }; @@ -4302,22 +5580,15 @@ var require_util2 = __commonJS({ "use strict"; var { Transform: Transform5 } = require("node:stream"); var zlib3 = require("node:zlib"); - var { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = require_constants3(); + var { redirectStatusSet, referrerPolicyTokens, badPortsSet } = require_constants3(); var { getGlobalOrigin } = require_global(); - var { collectASequenceOfCodePoints, collectAnHTTPQuotedString, removeChars, parseMIMEType } = require_data_url(); + var { collectAnHTTPQuotedString, parseMIMEType } = require_data_url(); var { performance: performance8 } = require("node:perf_hooks"); - var { isBlobLike, ReadableStreamFrom, isValidHTTPToken, normalizedMethodRecordsBase } = require_util(); + var { ReadableStreamFrom, isValidHTTPToken, normalizedMethodRecordsBase } = require_util(); var assert = require("node:assert"); var { isUint8Array } = require("node:util/types"); var { webidl } = require_webidl(); - var supportedHashes = []; - var crypto3; - try { - crypto3 = require("node:crypto"); - const possibleRelevantHashes = ["sha256", "sha384", "sha512"]; - supportedHashes = crypto3.getHashes().filter((hash2) => possibleRelevantHashes.includes(hash2)); - } catch { - } + var { isomorphicEncode, collectASequenceOfCodePoints, removeChars } = require_infra(); function responseURL(response) { const urlList = response.urlList; const length = urlList.length; @@ -4380,11 +5651,10 @@ var require_util2 = __commonJS({ function isValidHeaderValue(potentialValue) { return (potentialValue[0] === " " || potentialValue[0] === " " || potentialValue[potentialValue.length - 1] === " " || potentialValue[potentialValue.length - 1] === " " || potentialValue.includes("\n") || potentialValue.includes("\r") || potentialValue.includes("\0")) === false; } - function setRequestReferrerPolicyOnRedirect(request3, actualResponse) { - const { headersList } = actualResponse; - const policyHeader = (headersList.get("referrer-policy", true) ?? "").split(","); + function parseReferrerPolicy(actualResponse) { + const policyHeader = (actualResponse.headersList.get("referrer-policy", true) ?? "").split(","); let policy = ""; - if (policyHeader.length > 0) { + if (policyHeader.length) { for (let i = policyHeader.length; i !== 0; i--) { const token = policyHeader[i - 1].trim(); if (referrerPolicyTokens.has(token)) { @@ -4393,6 +5663,10 @@ var require_util2 = __commonJS({ } } } + return policy; + } + function setRequestReferrerPolicyOnRedirect(request3, actualResponse) { + const policy = parseReferrerPolicy(actualResponse); if (policy !== "") { request3.referrerPolicy = policy; } @@ -4501,7 +5775,7 @@ var require_util2 = __commonJS({ return "no-referrer"; } referrerSource = new URL(globalOrigin); - } else if (request3.referrer instanceof URL) { + } else if (webidl.is.URL(request3.referrer)) { referrerSource = request3.referrer; } let referrerURL = stripURLForReferrer(referrerSource); @@ -4509,17 +5783,23 @@ var require_util2 = __commonJS({ if (referrerURL.toString().length > 4096) { referrerURL = referrerOrigin; } - const areSameOrigin = sameOrigin(request3, referrerURL); - const isNonPotentiallyTrustWorthy = isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(request3.url); switch (policy) { + case "no-referrer": + return "no-referrer"; case "origin": - return referrerOrigin != null ? referrerOrigin : stripURLForReferrer(referrerSource, true); + if (referrerOrigin != null) { + return referrerOrigin; + } + return stripURLForReferrer(referrerSource, true); case "unsafe-url": return referrerURL; - case "same-origin": - return areSameOrigin ? referrerOrigin : "no-referrer"; - case "origin-when-cross-origin": - return areSameOrigin ? referrerURL : referrerOrigin; + case "strict-origin": { + const currentURL = requestCurrentURL(request3); + if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { + return "no-referrer"; + } + return referrerOrigin; + } case "strict-origin-when-cross-origin": { const currentURL = requestCurrentURL(request3); if (sameOrigin(referrerURL, currentURL)) { @@ -4530,157 +5810,83 @@ var require_util2 = __commonJS({ } return referrerOrigin; } - case "strict-origin": - // eslint-disable-line - /** - * 1. If referrerURL is a potentially trustworthy URL and - * request’s current URL is not a potentially trustworthy URL, - * then return no referrer. - * 2. Return referrerOrigin - */ - case "no-referrer-when-downgrade": - // eslint-disable-line - /** - * 1. If referrerURL is a potentially trustworthy URL and - * request’s current URL is not a potentially trustworthy URL, - * then return no referrer. - * 2. Return referrerOrigin - */ - default: - return isNonPotentiallyTrustWorthy ? "no-referrer" : referrerOrigin; + case "same-origin": + if (sameOrigin(request3, referrerURL)) { + return referrerURL; + } + return "no-referrer"; + case "origin-when-cross-origin": + if (sameOrigin(request3, referrerURL)) { + return referrerURL; + } + return referrerOrigin; + case "no-referrer-when-downgrade": { + const currentURL = requestCurrentURL(request3); + if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { + return "no-referrer"; + } + return referrerURL; + } } } - function stripURLForReferrer(url2, originOnly) { - assert(url2 instanceof URL); + function stripURLForReferrer(url2, originOnly = false) { + assert(webidl.is.URL(url2)); url2 = new URL(url2); - if (url2.protocol === "file:" || url2.protocol === "about:" || url2.protocol === "blank:") { + if (urlIsLocal(url2)) { return "no-referrer"; } url2.username = ""; url2.password = ""; url2.hash = ""; - if (originOnly) { + if (originOnly === true) { url2.pathname = ""; url2.search = ""; } return url2; } - function isURLPotentiallyTrustworthy(url2) { - if (!(url2 instanceof URL)) { + var isPotentialleTrustworthyIPv4 = RegExp.prototype.test.bind(/^127\.(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.){2}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)$/); + var isPotentiallyTrustworthyIPv6 = RegExp.prototype.test.bind(/^(?:(?:0{1,4}:){7}|(?:0{1,4}:){1,6}:|::)0{0,3}1$/); + function isOriginIPPotentiallyTrustworthy(origin) { + if (origin.includes(":")) { + if (origin[0] === "[" && origin[origin.length - 1] === "]") { + origin = origin.slice(1, -1); + } + return isPotentiallyTrustworthyIPv6(origin); + } + return isPotentialleTrustworthyIPv4(origin); + } + function isOriginPotentiallyTrustworthy(origin) { + if (origin == null || origin === "null") { return false; } - if (url2.href === "about:blank" || url2.href === "about:srcdoc") { + origin = new URL(origin); + if (origin.protocol === "https:" || origin.protocol === "wss:") { return true; } - if (url2.protocol === "data:") return true; - if (url2.protocol === "file:") return true; - return isOriginPotentiallyTrustworthy(url2.origin); - function isOriginPotentiallyTrustworthy(origin) { - if (origin == null || origin === "null") return false; - const originAsURL = new URL(origin); - if (originAsURL.protocol === "https:" || originAsURL.protocol === "wss:") { - return true; - } - if (/^127(?:\.[0-9]+){0,2}\.[0-9]+$|^\[(?:0*:)*?:?0*1\]$/.test(originAsURL.hostname) || (originAsURL.hostname === "localhost" || originAsURL.hostname.includes("localhost.")) || originAsURL.hostname.endsWith(".localhost")) { - return true; - } - return false; - } - } - function bytesMatch(bytes, metadataList) { - if (crypto3 === void 0) { + if (isOriginIPPotentiallyTrustworthy(origin.hostname)) { return true; } - const parsedMetadata = parseMetadata(metadataList); - if (parsedMetadata === "no metadata") { + if (origin.hostname === "localhost" || origin.hostname === "localhost.") { return true; } - if (parsedMetadata.length === 0) { + if (origin.hostname.endsWith(".localhost") || origin.hostname.endsWith(".localhost.")) { return true; } - const strongest = getStrongestMetadata(parsedMetadata); - const metadata = filterMetadataListByAlgorithm(parsedMetadata, strongest); - for (const item of metadata) { - const algorithm = item.algo; - const expectedValue = item.hash; - let actualValue = crypto3.createHash(algorithm).update(bytes).digest("base64"); - if (actualValue[actualValue.length - 1] === "=") { - if (actualValue[actualValue.length - 2] === "=") { - actualValue = actualValue.slice(0, -2); - } else { - actualValue = actualValue.slice(0, -1); - } - } - if (compareBase64Mixed(actualValue, expectedValue)) { - return true; - } + if (origin.protocol === "file:") { + return true; } return false; } - var parseHashWithOptions = /(?sha256|sha384|sha512)-((?[A-Za-z0-9+/]+|[A-Za-z0-9_-]+)={0,2}(?:\s|$)( +[!-~]*)?)?/i; - function parseMetadata(metadata) { - const result = []; - let empty = true; - for (const token of metadata.split(" ")) { - empty = false; - const parsedToken = parseHashWithOptions.exec(token); - if (parsedToken === null || parsedToken.groups === void 0 || parsedToken.groups.algo === void 0) { - continue; - } - const algorithm = parsedToken.groups.algo.toLowerCase(); - if (supportedHashes.includes(algorithm)) { - result.push(parsedToken.groups); - } - } - if (empty === true) { - return "no metadata"; - } - return result; - } - function getStrongestMetadata(metadataList) { - let algorithm = metadataList[0].algo; - if (algorithm[3] === "5") { - return algorithm; - } - for (let i = 1; i < metadataList.length; ++i) { - const metadata = metadataList[i]; - if (metadata.algo[3] === "5") { - algorithm = "sha512"; - break; - } else if (algorithm[3] === "3") { - continue; - } else if (metadata.algo[3] === "3") { - algorithm = "sha384"; - } - } - return algorithm; - } - function filterMetadataListByAlgorithm(metadataList, algorithm) { - if (metadataList.length === 1) { - return metadataList; - } - let pos = 0; - for (let i = 0; i < metadataList.length; ++i) { - if (metadataList[i].algo === algorithm) { - metadataList[pos++] = metadataList[i]; - } - } - metadataList.length = pos; - return metadataList; - } - function compareBase64Mixed(actualValue, expectedValue) { - if (actualValue.length !== expectedValue.length) { + function isURLPotentiallyTrustworthy(url2) { + if (!webidl.is.URL(url2)) { return false; } - for (let i = 0; i < actualValue.length; ++i) { - if (actualValue[i] !== expectedValue[i]) { - if (actualValue[i] === "+" && expectedValue[i] === "-" || actualValue[i] === "/" && expectedValue[i] === "_") { - continue; - } - return false; - } + if (url2.href === "about:blank" || url2.href === "about:srcdoc") { + return true; } - return true; + if (url2.protocol === "data:") return true; + if (url2.protocol === "blob:") return true; + return isOriginPotentiallyTrustworthy(url2.origin); } function tryUpgradeRequestToAPotentiallyTrustworthyURL(request3) { } @@ -4693,15 +5899,6 @@ var require_util2 = __commonJS({ } return false; } - function createDeferredPromise() { - let res; - let rej; - const promise = new Promise((resolve15, reject) => { - res = resolve15; - rej = reject; - }); - return { promise, resolve: res, reject: rej }; - } function isAborted(fetchParams) { return fetchParams.controller.state === "aborted"; } @@ -4711,14 +5908,6 @@ var require_util2 = __commonJS({ function normalizeMethod(method) { return normalizedMethodRecordsBase[method.toLowerCase()] ?? method; } - function serializeJavascriptValueToJSONString(value) { - const result = JSON.stringify(value); - if (result === void 0) { - throw new TypeError("Value is not JSON serializable"); - } - assert(typeof result === "string"); - return result; - } var esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())); function createIterator(name, kInternalIterator, keyIndex = 0, valueIndex = 1) { class FastIterableIterator { @@ -4745,7 +5934,7 @@ var require_util2 = __commonJS({ ); } const index2 = this.#index; - const values = this.#target[kInternalIterator]; + const values = kInternalIterator(this.#target); const len = values.length; if (index2 >= len) { return { @@ -4846,25 +6035,16 @@ var require_util2 = __commonJS({ } }); } - async function fullyReadBody(body, processBody, processBodyError) { + function fullyReadBody(body, processBody, processBodyError) { const successSteps = processBody; const errorSteps = processBodyError; - let reader; try { - reader = body.stream.getReader(); - } catch (e) { - errorSteps(e); - return; - } - try { - successSteps(await readAllBytes(reader)); + const reader = body.stream.getReader(); + readAllBytes(reader, successSteps, errorSteps); } catch (e) { errorSteps(e); } } - function isReadableStreamLike(stream2) { - return stream2 instanceof ReadableStream || stream2[Symbol.toStringTag] === "ReadableStream" && typeof stream2.tee === "function"; - } function readableStreamClose(controller) { try { controller.close(); @@ -4875,24 +6055,25 @@ var require_util2 = __commonJS({ } } } - var invalidIsomorphicEncodeValueRegex = /[^\x00-\xFF]/; - function isomorphicEncode(input) { - assert(!invalidIsomorphicEncodeValueRegex.test(input)); - return input; - } - async function readAllBytes(reader) { - const bytes = []; - let byteLength = 0; - while (true) { - const { done, value: chunk } = await reader.read(); - if (done) { - return Buffer.concat(bytes, byteLength); - } - if (!isUint8Array(chunk)) { - throw new TypeError("Received non-Uint8Array chunk"); - } - bytes.push(chunk); - byteLength += chunk.length; + async function readAllBytes(reader, successSteps, failureSteps) { + try { + const bytes = []; + let byteLength = 0; + do { + const { done, value: chunk } = await reader.read(); + if (done) { + successSteps(Buffer.concat(bytes, byteLength)); + return; + } + if (!isUint8Array(chunk)) { + failureSteps(new TypeError("Received non-Uint8Array chunk")); + return; + } + bytes.push(chunk); + byteLength += chunk.length; + } while (true); + } catch (e) { + failureSteps(e); } } function urlIsLocal(url2) { @@ -5086,16 +6267,14 @@ var require_util2 = __commonJS({ } return gettingDecodingSplitting(value); } - var textDecoder = new TextDecoder(); - function utf8DecodeBytes(buffer) { - if (buffer.length === 0) { - return ""; - } - if (buffer[0] === 239 && buffer[1] === 187 && buffer[2] === 191) { - buffer = buffer.subarray(3); - } - const output = textDecoder.decode(buffer); - return output; + function hasAuthenticationEntry(request3) { + return false; + } + function includesCredentials(url2) { + return !!(url2.username || url2.password); + } + function isTraversableNavigable(navigable) { + return navigable != null && navigable !== "client" && navigable !== "no-traversable"; } var EnvironmentSettingsObjectBase = class { get baseUrl() { @@ -5114,7 +6293,6 @@ var require_util2 = __commonJS({ isAborted, isCancelled, isValidEncodedURL, - createDeferredPromise, ReadableStreamFrom, tryUpgradeRequestToAPotentiallyTrustworthyURL, clampAndCoarsenConnectionTimingInfo, @@ -5134,129 +6312,46 @@ var require_util2 = __commonJS({ requestCurrentURL, responseURL, responseLocationURL, - isBlobLike, isURLPotentiallyTrustworthy, isValidReasonPhrase, sameOrigin, normalizeMethod, - serializeJavascriptValueToJSONString, iteratorMixin, createIterator, isValidHeaderName, isValidHeaderValue, isErrorLike, fullyReadBody, - bytesMatch, - isReadableStreamLike, readableStreamClose, - isomorphicEncode, urlIsLocal, urlHasHttpsScheme, urlIsHttpHttpsScheme, readAllBytes, simpleRangeHeaderValue, buildContentRange, - parseMetadata, createInflate, extractMimeType, getDecodeSplit, - utf8DecodeBytes, - environmentSettingsObject + environmentSettingsObject, + isOriginIPPotentiallyTrustworthy, + hasAuthenticationEntry, + includesCredentials, + isTraversableNavigable }; } }); -// node_modules/undici/lib/web/fetch/symbols.js -var require_symbols2 = __commonJS({ - "node_modules/undici/lib/web/fetch/symbols.js"(exports2, module2) { - "use strict"; - module2.exports = { - kUrl: /* @__PURE__ */ Symbol("url"), - kHeaders: /* @__PURE__ */ Symbol("headers"), - kSignal: /* @__PURE__ */ Symbol("signal"), - kState: /* @__PURE__ */ Symbol("state"), - kDispatcher: /* @__PURE__ */ Symbol("dispatcher") - }; - } -}); - -// node_modules/undici/lib/web/fetch/file.js -var require_file = __commonJS({ - "node_modules/undici/lib/web/fetch/file.js"(exports2, module2) { - "use strict"; - var { Blob: Blob2, File: File2 } = require("node:buffer"); - var { kState } = require_symbols2(); - var { webidl } = require_webidl(); - var FileLike = class _FileLike { - constructor(blobLike, fileName, options = {}) { - const n = fileName; - const t = options.type; - const d = options.lastModified ?? Date.now(); - this[kState] = { - blobLike, - name: n, - type: t, - lastModified: d - }; - } - stream(...args) { - webidl.brandCheck(this, _FileLike); - return this[kState].blobLike.stream(...args); - } - arrayBuffer(...args) { - webidl.brandCheck(this, _FileLike); - return this[kState].blobLike.arrayBuffer(...args); - } - slice(...args) { - webidl.brandCheck(this, _FileLike); - return this[kState].blobLike.slice(...args); - } - text(...args) { - webidl.brandCheck(this, _FileLike); - return this[kState].blobLike.text(...args); - } - get size() { - webidl.brandCheck(this, _FileLike); - return this[kState].blobLike.size; - } - get type() { - webidl.brandCheck(this, _FileLike); - return this[kState].blobLike.type; - } - get name() { - webidl.brandCheck(this, _FileLike); - return this[kState].name; - } - get lastModified() { - webidl.brandCheck(this, _FileLike); - return this[kState].lastModified; - } - get [Symbol.toStringTag]() { - return "File"; - } - }; - webidl.converters.Blob = webidl.interfaceConverter(Blob2); - function isFileLike(object2) { - return object2 instanceof File2 || object2 && (typeof object2.stream === "function" || typeof object2.arrayBuffer === "function") && object2[Symbol.toStringTag] === "File"; - } - module2.exports = { FileLike, isFileLike }; - } -}); - // node_modules/undici/lib/web/fetch/formdata.js var require_formdata = __commonJS({ "node_modules/undici/lib/web/fetch/formdata.js"(exports2, module2) { "use strict"; - var { isBlobLike, iteratorMixin } = require_util2(); - var { kState } = require_symbols2(); + var { iteratorMixin } = require_util2(); var { kEnumerableProperty } = require_util(); - var { FileLike, isFileLike } = require_file(); var { webidl } = require_webidl(); - var { File: NativeFile } = require("node:buffer"); var nodeUtil = require("node:util"); - var File2 = globalThis.File ?? NativeFile; var FormData2 = class _FormData { - constructor(form) { + #state = []; + constructor(form = void 0) { webidl.util.markAsUncloneable(this); if (form !== void 0) { throw webidl.errors.conversionFailed({ @@ -5265,81 +6360,82 @@ var require_formdata = __commonJS({ types: ["undefined"] }); } - this[kState] = []; } append(name, value, filename = void 0) { webidl.brandCheck(this, _FormData); const prefix = "FormData.append"; webidl.argumentLengthCheck(arguments, 2, prefix); - if (arguments.length === 3 && !isBlobLike(value)) { - throw new TypeError( - "Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'" - ); + name = webidl.converters.USVString(name); + if (arguments.length === 3 || webidl.is.Blob(value)) { + value = webidl.converters.Blob(value, prefix, "value"); + if (filename !== void 0) { + filename = webidl.converters.USVString(filename); + } + } else { + value = webidl.converters.USVString(value); } - name = webidl.converters.USVString(name, prefix, "name"); - value = isBlobLike(value) ? webidl.converters.Blob(value, prefix, "value", { strict: false }) : webidl.converters.USVString(value, prefix, "value"); - filename = arguments.length === 3 ? webidl.converters.USVString(filename, prefix, "filename") : void 0; const entry = makeEntry(name, value, filename); - this[kState].push(entry); + this.#state.push(entry); } delete(name) { webidl.brandCheck(this, _FormData); const prefix = "FormData.delete"; webidl.argumentLengthCheck(arguments, 1, prefix); - name = webidl.converters.USVString(name, prefix, "name"); - this[kState] = this[kState].filter((entry) => entry.name !== name); + name = webidl.converters.USVString(name); + this.#state = this.#state.filter((entry) => entry.name !== name); } get(name) { webidl.brandCheck(this, _FormData); const prefix = "FormData.get"; webidl.argumentLengthCheck(arguments, 1, prefix); - name = webidl.converters.USVString(name, prefix, "name"); - const idx = this[kState].findIndex((entry) => entry.name === name); + name = webidl.converters.USVString(name); + const idx = this.#state.findIndex((entry) => entry.name === name); if (idx === -1) { return null; } - return this[kState][idx].value; + return this.#state[idx].value; } getAll(name) { webidl.brandCheck(this, _FormData); const prefix = "FormData.getAll"; webidl.argumentLengthCheck(arguments, 1, prefix); - name = webidl.converters.USVString(name, prefix, "name"); - return this[kState].filter((entry) => entry.name === name).map((entry) => entry.value); + name = webidl.converters.USVString(name); + return this.#state.filter((entry) => entry.name === name).map((entry) => entry.value); } has(name) { webidl.brandCheck(this, _FormData); const prefix = "FormData.has"; webidl.argumentLengthCheck(arguments, 1, prefix); - name = webidl.converters.USVString(name, prefix, "name"); - return this[kState].findIndex((entry) => entry.name === name) !== -1; + name = webidl.converters.USVString(name); + return this.#state.findIndex((entry) => entry.name === name) !== -1; } set(name, value, filename = void 0) { webidl.brandCheck(this, _FormData); const prefix = "FormData.set"; webidl.argumentLengthCheck(arguments, 2, prefix); - if (arguments.length === 3 && !isBlobLike(value)) { - throw new TypeError( - "Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'" - ); + name = webidl.converters.USVString(name); + if (arguments.length === 3 || webidl.is.Blob(value)) { + value = webidl.converters.Blob(value, prefix, "value"); + if (filename !== void 0) { + filename = webidl.converters.USVString(filename); + } + } else { + value = webidl.converters.USVString(value); } - name = webidl.converters.USVString(name, prefix, "name"); - value = isBlobLike(value) ? webidl.converters.Blob(value, prefix, "name", { strict: false }) : webidl.converters.USVString(value, prefix, "name"); - filename = arguments.length === 3 ? webidl.converters.USVString(filename, prefix, "name") : void 0; const entry = makeEntry(name, value, filename); - const idx = this[kState].findIndex((entry2) => entry2.name === name); + const idx = this.#state.findIndex((entry2) => entry2.name === name); if (idx !== -1) { - this[kState] = [ - ...this[kState].slice(0, idx), + this.#state = [ + ...this.#state.slice(0, idx), entry, - ...this[kState].slice(idx + 1).filter((entry2) => entry2.name !== name) + ...this.#state.slice(idx + 1).filter((entry2) => entry2.name !== name) ]; } else { - this[kState].push(entry); + this.#state.push(entry); } } [nodeUtil.inspect.custom](depth, options) { - const state = this[kState].reduce((a, b) => { + const state = this.#state.reduce((a, b) => { if (a[b.name]) { if (Array.isArray(a[b.name])) { a[b.name].push(b.value); @@ -5356,8 +6452,24 @@ var require_formdata = __commonJS({ const output = nodeUtil.formatWithOptions(options, state); return `FormData ${output.slice(output.indexOf("]") + 2)}`; } + /** + * @param {FormData} formData + */ + static getFormDataState(formData) { + return formData.#state; + } + /** + * @param {FormData} formData + * @param {any[]} newState + */ + static setFormDataState(formData, newState) { + formData.#state = newState; + } }; - iteratorMixin("FormData", FormData2, kState, "name", "value"); + var { getFormDataState, setFormDataState } = FormData2; + Reflect.deleteProperty(FormData2, "getFormDataState"); + Reflect.deleteProperty(FormData2, "setFormDataState"); + iteratorMixin("FormData", FormData2, getFormDataState, "name", "value"); Object.defineProperties(FormData2.prototype, { append: kEnumerableProperty, delete: kEnumerableProperty, @@ -5373,20 +6485,21 @@ var require_formdata = __commonJS({ function makeEntry(name, value, filename) { if (typeof value === "string") { } else { - if (!isFileLike(value)) { - value = value instanceof Blob ? new File2([value], "blob", { type: value.type }) : new FileLike(value, "blob", { type: value.type }); + if (!webidl.is.File(value)) { + value = new File([value], "blob", { type: value.type }); } if (filename !== void 0) { const options = { type: value.type, lastModified: value.lastModified }; - value = value instanceof NativeFile ? new File2([value], filename, options) : new FileLike(value, filename, options); + value = new File([value], filename, options); } } return { name, value }; } - module2.exports = { FormData: FormData2, makeEntry }; + webidl.is.FormData = webidl.util.MakeTypeAssertion(FormData2); + module2.exports = { FormData: FormData2, makeEntry, setFormDataState }; } }); @@ -5394,18 +6507,15 @@ var require_formdata = __commonJS({ var require_formdata_parser = __commonJS({ "node_modules/undici/lib/web/fetch/formdata-parser.js"(exports2, module2) { "use strict"; - var { isUSVString, bufferToLowerCasedHeaderName } = require_util(); - var { utf8DecodeBytes } = require_util2(); - var { HTTP_TOKEN_CODEPOINTS, isomorphicDecode } = require_data_url(); - var { isFileLike } = require_file(); + var { bufferToLowerCasedHeaderName } = require_util(); + var { HTTP_TOKEN_CODEPOINTS } = require_data_url(); var { makeEntry } = require_formdata(); + var { webidl } = require_webidl(); var assert = require("node:assert"); - var { File: NodeFile } = require("node:buffer"); - var File2 = globalThis.File ?? NodeFile; - var formDataNameBuffer = Buffer.from('form-data; name="'); - var filenameBuffer = Buffer.from("; filename"); + var { isomorphicDecode } = require_infra(); var dd = Buffer.from("--"); - var ddcrlf = Buffer.from("--\r\n"); + var decoder2 = new TextDecoder(); + var decoderIgnoreBOM = new TextDecoder("utf-8", { ignoreBOM: true }); function isAsciiString(chars) { for (let i = 0; i < chars.length; ++i) { if ((chars.charCodeAt(i) & ~127) !== 0) { @@ -5431,45 +6541,37 @@ var require_formdata_parser = __commonJS({ assert(mimeType !== "failure" && mimeType.essence === "multipart/form-data"); const boundaryString = mimeType.parameters.get("boundary"); if (boundaryString === void 0) { - return "failure"; + throw parsingError("missing boundary in content-type header"); } const boundary = Buffer.from(`--${boundaryString}`, "utf8"); const entryList = []; const position = { position: 0 }; - while (input[position.position] === 13 && input[position.position + 1] === 10) { - position.position += 2; - } - let trailing = input.length; - while (input[trailing - 1] === 10 && input[trailing - 2] === 13) { - trailing -= 2; - } - if (trailing !== input.length) { - input = input.subarray(0, trailing); + const firstBoundaryIndex = input.indexOf(boundary); + if (firstBoundaryIndex === -1) { + throw parsingError("no boundary found in multipart body"); } + position.position = firstBoundaryIndex; while (true) { if (input.subarray(position.position, position.position + boundary.length).equals(boundary)) { position.position += boundary.length; } else { - return "failure"; + throw parsingError("expected a value starting with -- and the boundary"); } - if (position.position === input.length - 2 && bufferStartsWith(input, dd, position) || position.position === input.length - 4 && bufferStartsWith(input, ddcrlf, position)) { + if (bufferStartsWith(input, dd, position)) { return entryList; } if (input[position.position] !== 13 || input[position.position + 1] !== 10) { - return "failure"; + throw parsingError("expected CRLF"); } position.position += 2; const result = parseMultipartFormDataHeaders(input, position); - if (result === "failure") { - return "failure"; - } let { name, filename, contentType, encoding } = result; position.position += 2; let body; { const boundaryIndex = input.indexOf(boundary.subarray(2), position.position); if (boundaryIndex === -1) { - return "failure"; + throw parsingError("expected boundary after body"); } body = input.subarray(position.position, boundaryIndex - 4); position.position += body.length; @@ -5478,7 +6580,7 @@ var require_formdata_parser = __commonJS({ } } if (input[position.position] !== 13 || input[position.position + 1] !== 10) { - return "failure"; + throw parsingError("expected CRLF"); } else { position.position += 2; } @@ -5488,15 +6590,87 @@ var require_formdata_parser = __commonJS({ if (!isAsciiString(contentType)) { contentType = ""; } - value = new File2([body], filename, { type: contentType }); + value = new File([body], filename, { type: contentType }); } else { - value = utf8DecodeBytes(Buffer.from(body)); + value = decoderIgnoreBOM.decode(Buffer.from(body)); } - assert(isUSVString(name)); - assert(typeof value === "string" && isUSVString(value) || isFileLike(value)); + assert(webidl.is.USVString(name)); + assert(typeof value === "string" && webidl.is.USVString(value) || webidl.is.File(value)); entryList.push(makeEntry(name, value, filename)); } } + function parseContentDispositionAttribute(input, position) { + if (input[position.position] === 59) { + position.position++; + } + collectASequenceOfBytes( + (char) => char === 32 || char === 9, + input, + position + ); + const attributeName = collectASequenceOfBytes( + (char) => isToken2(char) && char !== 61 && char !== 42, + // not = or * + input, + position + ); + if (attributeName.length === 0) { + return null; + } + const attrNameStr = attributeName.toString("ascii").toLowerCase(); + const isExtended = input[position.position] === 42; + if (isExtended) { + position.position++; + } + if (input[position.position] !== 61) { + return null; + } + position.position++; + collectASequenceOfBytes( + (char) => char === 32 || char === 9, + input, + position + ); + let value; + if (isExtended) { + const headerValue = collectASequenceOfBytes( + (char) => char !== 32 && char !== 13 && char !== 10 && char !== 59, + // not space, CRLF, or ; + input, + position + ); + if (headerValue[0] !== 117 && headerValue[0] !== 85 || // u or U + headerValue[1] !== 116 && headerValue[1] !== 84 || // t or T + headerValue[2] !== 102 && headerValue[2] !== 70 || // f or F + headerValue[3] !== 45 || // - + headerValue[4] !== 56) { + throw parsingError("unknown encoding, expected utf-8''"); + } + value = decodeURIComponent(decoder2.decode(headerValue.subarray(7))); + } else if (input[position.position] === 34) { + position.position++; + const quotedValue = collectASequenceOfBytes( + (char) => char !== 10 && char !== 13 && char !== 34, + // not LF, CR, or " + input, + position + ); + if (input[position.position] !== 34) { + throw parsingError("Closing quote not found"); + } + position.position++; + value = decoder2.decode(quotedValue).replace(/%0A/ig, "\n").replace(/%0D/ig, "\r").replace(/%22/g, '"'); + } else { + const tokenValue = collectASequenceOfBytes( + (char) => isToken2(char) && char !== 59, + // not ; + input, + position + ); + value = decoder2.decode(tokenValue); + } + return { name: attrNameStr, value, extended: isExtended }; + } function parseMultipartFormDataHeaders(input, position) { let name = null; let filename = null; @@ -5505,7 +6679,7 @@ var require_formdata_parser = __commonJS({ while (true) { if (input[position.position] === 13 && input[position.position + 1] === 10) { if (name === null) { - return "failure"; + throw parsingError("header name is null"); } return { name, filename, contentType, encoding }; } @@ -5516,10 +6690,10 @@ var require_formdata_parser = __commonJS({ ); headerName = removeChars(headerName, true, true, (char) => char === 9 || char === 32); if (!HTTP_TOKEN_CODEPOINTS.test(headerName.toString())) { - return "failure"; + throw parsingError("header name does not match the field-name token production"); } if (input[position.position] !== 58) { - return "failure"; + throw parsingError("expected :"); } position.position++; collectASequenceOfBytes( @@ -5530,29 +6704,34 @@ var require_formdata_parser = __commonJS({ switch (bufferToLowerCasedHeaderName(headerName)) { case "content-disposition": { name = filename = null; - if (!bufferStartsWith(input, formDataNameBuffer, position)) { - return "failure"; - } - position.position += 17; - name = parseMultipartFormDataName(input, position); - if (name === null) { - return "failure"; + let filenameIsExtended = false; + const dispositionType = collectASequenceOfBytes( + (char) => isToken2(char), + input, + position + ); + if (dispositionType.toString("ascii").toLowerCase() !== "form-data") { + throw parsingError("expected form-data for content-disposition header"); } - if (bufferStartsWith(input, filenameBuffer, position)) { - let check = position.position + filenameBuffer.length; - if (input[check] === 42) { - position.position += 1; - check += 1; - } - if (input[check] !== 61 || input[check + 1] !== 34) { - return "failure"; + while (position.position < input.length && (input[position.position] !== 13 || input[position.position + 1] !== 10)) { + const attribute = parseContentDispositionAttribute(input, position); + if (!attribute) { + break; } - position.position += 12; - filename = parseMultipartFormDataName(input, position); - if (filename === null) { - return "failure"; + if (attribute.name === "name") { + name = attribute.value; + } else if (attribute.name === "filename") { + if (attribute.extended) { + filename = attribute.value; + filenameIsExtended = true; + } else if (!filenameIsExtended) { + filename = attribute.value; + } } } + if (name === null) { + throw parsingError("name attribute is required in content-disposition header"); + } break; } case "content-type": { @@ -5583,28 +6762,13 @@ var require_formdata_parser = __commonJS({ ); } } - if (input[position.position] !== 13 && input[position.position + 1] !== 10) { - return "failure"; + if (input[position.position] !== 13 || input[position.position + 1] !== 10) { + throw parsingError("expected CRLF"); } else { position.position += 2; } } } - function parseMultipartFormDataName(input, position) { - assert(input[position.position - 1] === 34); - let name = collectASequenceOfBytes( - (char) => char !== 10 && char !== 13 && char !== 34, - input, - position - ); - if (input[position.position] !== 34) { - return null; - } else { - position.position++; - } - name = new TextDecoder().decode(name).replace(/%0A/ig, "\n").replace(/%0D/ig, "\r").replace(/%22/g, '"'); - return name; - } function collectASequenceOfBytes(condition, input, position) { let start = position.position; while (start < input.length && condition(input[start])) { @@ -5634,6 +6798,34 @@ var require_formdata_parser = __commonJS({ } return true; } + function parsingError(cause) { + return new TypeError("Failed to parse body as FormData.", { cause: new TypeError(cause) }); + } + function isCTL(char) { + return char <= 31 || char === 127; + } + function isTSpecial(char) { + return char === 40 || // ( + char === 41 || // ) + char === 60 || // < + char === 62 || // > + char === 64 || // @ + char === 44 || // , + char === 59 || // ; + char === 58 || // : + char === 92 || // \ + char === 34 || // " + char === 47 || // / + char === 91 || // [ + char === 93 || // ] + char === 63 || // ? + char === 61; + } + function isToken2(char) { + return char <= 127 && // ascii + char !== 32 && // space + char !== 9 && !isCTL(char) && !isTSpecial(char); + } module2.exports = { multipartFormDataParser, validateBoundary @@ -5641,6 +6833,25 @@ var require_formdata_parser = __commonJS({ } }); +// node_modules/undici/lib/util/promise.js +var require_promise = __commonJS({ + "node_modules/undici/lib/util/promise.js"(exports2, module2) { + "use strict"; + function createDeferredPromise() { + let res; + let rej; + const promise = new Promise((resolve15, reject) => { + res = resolve15; + rej = reject; + }); + return { promise, resolve: res, reject: rej }; + } + module2.exports = { + createDeferredPromise + }; + } +}); + // node_modules/undici/lib/web/fetch/body.js var require_body = __commonJS({ "node_modules/undici/lib/web/fetch/body.js"(exports2, module2) { @@ -5648,64 +6859,51 @@ var require_body = __commonJS({ var util4 = require_util(); var { ReadableStreamFrom, - isBlobLike, - isReadableStreamLike, readableStreamClose, - createDeferredPromise, fullyReadBody, - extractMimeType, - utf8DecodeBytes + extractMimeType } = require_util2(); - var { FormData: FormData2 } = require_formdata(); - var { kState } = require_symbols2(); + var { FormData: FormData2, setFormDataState } = require_formdata(); var { webidl } = require_webidl(); - var { Blob: Blob2 } = require("node:buffer"); var assert = require("node:assert"); var { isErrored, isDisturbed } = require("node:stream"); - var { isArrayBuffer } = require("node:util/types"); + var { isUint8Array } = require("node:util/types"); var { serializeAMimeType } = require_data_url(); var { multipartFormDataParser } = require_formdata_parser(); - var random; - try { - const crypto3 = require("node:crypto"); - random = (max) => crypto3.randomInt(0, max); - } catch { - random = (max) => Math.floor(Math.random(max)); - } + var { createDeferredPromise } = require_promise(); + var { parseJSONFromBytes } = require_infra(); + var { utf8DecodeBytes } = require_encoding(); + var { runtimeFeatures } = require_runtime_features(); + var random = runtimeFeatures.has("crypto") ? require("node:crypto").randomInt : (max) => Math.floor(Math.random() * max); var textEncoder = new TextEncoder(); function noop3() { } - var hasFinalizationRegistry = globalThis.FinalizationRegistry && process.version.indexOf("v18") !== 0; - var streamRegistry; - if (hasFinalizationRegistry) { - streamRegistry = new FinalizationRegistry((weakRef) => { - const stream2 = weakRef.deref(); - if (stream2 && !stream2.locked && !isDisturbed(stream2) && !isErrored(stream2)) { - stream2.cancel("Response object has been garbage collected").catch(noop3); - } - }); - } + var streamRegistry = new FinalizationRegistry((weakRef) => { + const stream2 = weakRef.deref(); + if (stream2 && !stream2.locked && !isDisturbed(stream2) && !isErrored(stream2)) { + stream2.cancel("Response object has been garbage collected").catch(noop3); + } + }); function extractBody(object2, keepalive = false) { let stream2 = null; - if (object2 instanceof ReadableStream) { + let controller = null; + if (webidl.is.ReadableStream(object2)) { stream2 = object2; - } else if (isBlobLike(object2)) { + } else if (webidl.is.Blob(object2)) { stream2 = object2.stream(); } else { stream2 = new ReadableStream({ - async pull(controller) { - const buffer = typeof source === "string" ? textEncoder.encode(source) : source; - if (buffer.byteLength) { - controller.enqueue(buffer); - } - queueMicrotask(() => readableStreamClose(controller)); + pull() { }, - start() { + start(c) { + controller = c; + }, + cancel() { }, type: "bytes" }); } - assert(isReadableStreamLike(stream2)); + assert(webidl.is.ReadableStream(stream2)); let action = null; let source = null; let length = null; @@ -5713,18 +6911,16 @@ var require_body = __commonJS({ if (typeof object2 === "string") { source = object2; type = "text/plain;charset=UTF-8"; - } else if (object2 instanceof URLSearchParams) { + } else if (webidl.is.URLSearchParams(object2)) { source = object2.toString(); type = "application/x-www-form-urlencoded;charset=UTF-8"; - } else if (isArrayBuffer(object2)) { - source = new Uint8Array(object2.slice()); - } else if (ArrayBuffer.isView(object2)) { - source = new Uint8Array(object2.buffer.slice(object2.byteOffset, object2.byteOffset + object2.byteLength)); - } else if (util4.isFormDataLike(object2)) { + } else if (webidl.is.BufferSource(object2)) { + source = webidl.util.getCopyOfBytesHeldByBufferSource(object2); + } else if (webidl.is.FormData(object2)) { const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, "0")}`; const prefix = `--${boundary}\r Content-Disposition: form-data`; - const escape3 = (str) => str.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22"); + const formdataEscape = (str) => str.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22"); const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, "\r\n"); const blobParts = []; const rn = new Uint8Array([13, 10]); @@ -5732,14 +6928,14 @@ Content-Disposition: form-data`; let hasUnknownSizeValue = false; for (const [name, value] of object2) { if (typeof value === "string") { - const chunk2 = textEncoder.encode(prefix + `; name="${escape3(normalizeLinefeeds(name))}"\r + const chunk2 = textEncoder.encode(prefix + `; name="${formdataEscape(normalizeLinefeeds(name))}"\r \r ${normalizeLinefeeds(value)}\r `); blobParts.push(chunk2); length += chunk2.byteLength; } else { - const chunk2 = textEncoder.encode(`${prefix}; name="${escape3(normalizeLinefeeds(name))}"` + (value.name ? `; filename="${escape3(value.name)}"` : "") + `\r + const chunk2 = textEncoder.encode(`${prefix}; name="${formdataEscape(normalizeLinefeeds(name))}"` + (value.name ? `; filename="${formdataEscape(value.name)}"` : "") + `\r Content-Type: ${value.type || "application/octet-stream"}\r \r `); @@ -5769,7 +6965,7 @@ Content-Type: ${value.type || "application/octet-stream"}\r } }; type = `multipart/form-data; boundary=${boundary}`; - } else if (isBlobLike(object2)) { + } else if (webidl.is.Blob(object2)) { source = object2; length = object2.size; if (object2.type) { @@ -5784,52 +6980,44 @@ Content-Type: ${value.type || "application/octet-stream"}\r "Response body object should not be disturbed or locked" ); } - stream2 = object2 instanceof ReadableStream ? object2 : ReadableStreamFrom(object2); + stream2 = webidl.is.ReadableStream(object2) ? object2 : ReadableStreamFrom(object2); } - if (typeof source === "string" || util4.isBuffer(source)) { - length = Buffer.byteLength(source); + if (typeof source === "string" || isUint8Array(source)) { + action = () => { + length = typeof source === "string" ? Buffer.byteLength(source) : source.length; + return source; + }; } if (action != null) { - let iterator2; - stream2 = new ReadableStream({ - async start() { - iterator2 = action(object2)[Symbol.asyncIterator](); - }, - async pull(controller) { - const { value, done } = await iterator2.next(); - if (done) { - queueMicrotask(() => { - controller.close(); - controller.byobRequest?.respond(0); - }); - } else { - if (!isErrored(stream2)) { - const buffer = new Uint8Array(value); - if (buffer.byteLength) { - controller.enqueue(buffer); - } + ; + (async () => { + const result = action(); + const iterator2 = result?.[Symbol.asyncIterator]?.(); + if (iterator2) { + for await (const bytes of iterator2) { + if (isErrored(stream2)) break; + if (bytes.length) { + controller.enqueue(new Uint8Array(bytes)); } } - return controller.desiredSize > 0; - }, - async cancel(reason) { - await iterator2.return(); - }, - type: "bytes" - }); + } else if (result?.length && !isErrored(stream2)) { + controller.enqueue(typeof result === "string" ? textEncoder.encode(result) : new Uint8Array(result)); + } + queueMicrotask(() => readableStreamClose(controller)); + })(); } const body = { stream: stream2, source, length }; return [body, type]; } function safelyExtractBody(object2, keepalive = false) { - if (object2 instanceof ReadableStream) { + if (webidl.is.ReadableStream(object2)) { assert(!util4.isDisturbed(object2), "The body has already been consumed."); assert(!object2.locked, "The stream is locked."); } return extractBody(object2, keepalive); } - function cloneBody(instance8, body) { - const [out1, out2] = body.stream.tee(); + function cloneBody(body) { + const { 0: out1, 1: out2 } = body.stream.tee(); body.stream = out1; return { stream: out2, @@ -5837,47 +7025,39 @@ Content-Type: ${value.type || "application/octet-stream"}\r source: body.source }; } - function throwIfAborted(state) { - if (state.aborted) { - throw new DOMException("The operation was aborted.", "AbortError"); - } - } - function bodyMixinMethods(instance8) { + function bodyMixinMethods(instance8, getInternalState) { const methods = { blob() { return consumeBody(this, (bytes) => { - let mimeType = bodyMimeType(this); + let mimeType = bodyMimeType(getInternalState(this)); if (mimeType === null) { mimeType = ""; } else if (mimeType) { mimeType = serializeAMimeType(mimeType); } - return new Blob2([bytes], { type: mimeType }); - }, instance8); + return new Blob([bytes], { type: mimeType }); + }, instance8, getInternalState); }, arrayBuffer() { return consumeBody(this, (bytes) => { return new Uint8Array(bytes).buffer; - }, instance8); + }, instance8, getInternalState); }, text() { - return consumeBody(this, utf8DecodeBytes, instance8); + return consumeBody(this, utf8DecodeBytes, instance8, getInternalState); }, json() { - return consumeBody(this, parseJSONFromBytes, instance8); + return consumeBody(this, parseJSONFromBytes, instance8, getInternalState); }, formData() { return consumeBody(this, (value) => { - const mimeType = bodyMimeType(this); + const mimeType = bodyMimeType(getInternalState(this)); if (mimeType !== null) { switch (mimeType.essence) { case "multipart/form-data": { const parsed = multipartFormDataParser(value, mimeType); - if (parsed === "failure") { - throw new TypeError("Failed to parse body as FormData."); - } const fd = new FormData2(); - fd[kState] = parsed; + setFormDataState(fd, parsed); return fd; } case "application/x-www-form-urlencoded": { @@ -5893,27 +7073,31 @@ Content-Type: ${value.type || "application/octet-stream"}\r throw new TypeError( 'Content-Type was not one of "multipart/form-data" or "application/x-www-form-urlencoded".' ); - }, instance8); + }, instance8, getInternalState); }, bytes() { return consumeBody(this, (bytes) => { return new Uint8Array(bytes); - }, instance8); + }, instance8, getInternalState); } }; return methods; } - function mixinBody(prototype) { - Object.assign(prototype.prototype, bodyMixinMethods(prototype)); + function mixinBody(prototype, getInternalState) { + Object.assign(prototype.prototype, bodyMixinMethods(prototype, getInternalState)); } - async function consumeBody(object2, convertBytesToJSValue, instance8) { - webidl.brandCheck(object2, instance8); + function consumeBody(object2, convertBytesToJSValue, instance8, getInternalState) { + try { + webidl.brandCheck(object2, instance8); + } catch (e) { + return Promise.reject(e); + } + object2 = getInternalState(object2); if (bodyUnusable(object2)) { - throw new TypeError("Body is unusable: Body has already been read"); + return Promise.reject(new TypeError("Body is unusable: Body has already been read")); } - throwIfAborted(object2[kState]); const promise = createDeferredPromise(); - const errorSteps = (error3) => promise.reject(error3); + const errorSteps = promise.reject; const successSteps = (data) => { try { promise.resolve(convertBytesToJSValue(data)); @@ -5921,22 +7105,19 @@ Content-Type: ${value.type || "application/octet-stream"}\r errorSteps(e); } }; - if (object2[kState].body == null) { + if (object2.body == null) { successSteps(Buffer.allocUnsafe(0)); return promise.promise; } - await fullyReadBody(object2[kState].body, successSteps, errorSteps); + fullyReadBody(object2.body, successSteps, errorSteps); return promise.promise; } function bodyUnusable(object2) { - const body = object2[kState].body; + const body = object2.body; return body != null && (body.stream.locked || util4.isDisturbed(body.stream)); } - function parseJSONFromBytes(bytes) { - return JSON.parse(utf8DecodeBytes(bytes)); - } function bodyMimeType(requestOrResponse) { - const headers = requestOrResponse[kState].headersList; + const headers = requestOrResponse.headersList; const mimeType = extractMimeType(headers); if (mimeType === "failure") { return null; @@ -5949,7 +7130,6 @@ Content-Type: ${value.type || "application/octet-stream"}\r cloneBody, mixinBody, streamRegistry, - hasFinalizationRegistry, bodyUnusable }; } @@ -6007,70 +7187,127 @@ var require_client_h1 = __commonJS({ kMaxResponseSize, kOnError, kResume, - kHTTPContext + kHTTPContext, + kClosed } = require_symbols(); var constants = require_constants2(); var EMPTY_BUF = Buffer.alloc(0); var FastBuffer = Buffer[Symbol.species]; - var addListener = util4.addListener; var removeAllListeners = util4.removeAllListeners; var kIdleSocketValidation = /* @__PURE__ */ Symbol("kIdleSocketValidation"); var kIdleSocketValidationTimeout = /* @__PURE__ */ Symbol("kIdleSocketValidationTimeout"); var kSocketUsed = /* @__PURE__ */ Symbol("kSocketUsed"); var extractBody; - async function lazyllhttp() { + function lazyllhttp() { const llhttpWasmData = process.env.JEST_WORKER_ID ? require_llhttp_wasm() : void 0; let mod; - try { - mod = await WebAssembly.compile(require_llhttp_simd_wasm()); - } catch (e) { - mod = await WebAssembly.compile(llhttpWasmData || require_llhttp_wasm()); + let useWasmSIMD = true; + if (process.arch === "ppc64") { + const [major, minor] = process.versions.node.split(".").map((n) => parseInt(n, 10)); + if (major < 24 || major === 24 && minor < 12) { + useWasmSIMD = false; + } } - return await WebAssembly.instantiate(mod, { + if (process.env.UNDICI_NO_WASM_SIMD === "1") { + useWasmSIMD = false; + } else if (process.env.UNDICI_NO_WASM_SIMD === "0") { + useWasmSIMD = true; + } + if (useWasmSIMD) { + try { + mod = new WebAssembly.Module(require_llhttp_simd_wasm()); + } catch { + } + } + if (!mod) { + mod = new WebAssembly.Module(llhttpWasmData || require_llhttp_wasm()); + } + return new WebAssembly.Instance(mod, { env: { - /* eslint-disable camelcase */ + /** + * @param {number} p + * @param {number} at + * @param {number} len + * @returns {number} + */ wasm_on_url: (p, at, len) => { return 0; }, + /** + * @param {number} p + * @param {number} at + * @param {number} len + * @returns {number} + */ wasm_on_status: (p, at, len) => { assert(currentParser.ptr === p); const start = at - currentBufferPtr + currentBufferRef.byteOffset; - return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; + return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)); }, + /** + * @param {number} p + * @returns {number} + */ wasm_on_message_begin: (p) => { assert(currentParser.ptr === p); - return currentParser.onMessageBegin() || 0; + return currentParser.onMessageBegin(); }, + /** + * @param {number} p + * @param {number} at + * @param {number} len + * @returns {number} + */ wasm_on_header_field: (p, at, len) => { assert(currentParser.ptr === p); const start = at - currentBufferPtr + currentBufferRef.byteOffset; - return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; + return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)); }, + /** + * @param {number} p + * @param {number} at + * @param {number} len + * @returns {number} + */ wasm_on_header_value: (p, at, len) => { assert(currentParser.ptr === p); const start = at - currentBufferPtr + currentBufferRef.byteOffset; - return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; + return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)); }, + /** + * @param {number} p + * @param {number} statusCode + * @param {0|1} upgrade + * @param {0|1} shouldKeepAlive + * @returns {number} + */ wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => { assert(currentParser.ptr === p); - return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0; + return currentParser.onHeadersComplete(statusCode, upgrade === 1, shouldKeepAlive === 1); }, + /** + * @param {number} p + * @param {number} at + * @param {number} len + * @returns {number} + */ wasm_on_body: (p, at, len) => { assert(currentParser.ptr === p); const start = at - currentBufferPtr + currentBufferRef.byteOffset; - return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; + return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)); }, + /** + * @param {number} p + * @returns {number} + */ wasm_on_message_complete: (p) => { assert(currentParser.ptr === p); - return currentParser.onMessageComplete() || 0; + return currentParser.onMessageComplete(); } - /* eslint-enable camelcase */ } }); } var llhttpInstance = null; - var llhttpPromise = lazyllhttp(); - llhttpPromise.catch(); var currentParser = null; var currentBufferRef = null; var currentBufferSize = 0; @@ -6081,16 +7318,21 @@ var require_client_h1 = __commonJS({ var TIMEOUT_BODY = 4 | USE_FAST_TIMER; var TIMEOUT_KEEP_ALIVE = 8 | USE_NATIVE_TIMER; var Parser = class { + /** + * @param {import('./client.js')} client + * @param {import('net').Socket} socket + * @param {*} llhttp + */ constructor(client, socket, { exports: exports3 }) { - assert(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0); this.llhttp = exports3; this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE); this.client = client; this.socket = socket; this.timeout = null; + this.timeoutWeakRef = new WeakRef(this); this.timeoutValue = null; this.timeoutType = null; - this.statusCode = null; + this.statusCode = 0; this.statusText = ""; this.upgrade = false; this.headers = []; @@ -6113,10 +7355,10 @@ var require_client_h1 = __commonJS({ } if (delay2) { if (type & USE_FAST_TIMER) { - this.timeout = timers.setFastTimeout(onParserTimeout, delay2, new WeakRef(this)); + this.timeout = timers.setFastTimeout(onParserTimeout, delay2, this.timeoutWeakRef); } else { - this.timeout = setTimeout(onParserTimeout, delay2, new WeakRef(this)); - this.timeout.unref(); + this.timeout = setTimeout(onParserTimeout, delay2, this.timeoutWeakRef); + this.timeout?.unref(); } } this.timeoutValue = delay2; @@ -6132,7 +7374,7 @@ var require_client_h1 = __commonJS({ return; } assert(this.ptr != null); - assert(currentParser == null); + assert(currentParser === null); this.llhttp.llhttp_resume(this.ptr); assert(this.timeoutType === TIMEOUT_BODY); if (this.timeout) { @@ -6153,41 +7395,41 @@ var require_client_h1 = __commonJS({ this.execute(chunk); } } - execute(data) { + /** + * @param {Buffer} chunk + */ + execute(chunk) { + assert(currentParser === null); assert(this.ptr != null); - assert(currentParser == null); assert(!this.paused); const { socket, llhttp } = this; - if (data.length > currentBufferSize) { + if (chunk.length > currentBufferSize) { if (currentBufferPtr) { llhttp.free(currentBufferPtr); } - currentBufferSize = Math.ceil(data.length / 4096) * 4096; + currentBufferSize = Math.ceil(chunk.length / 4096) * 4096; currentBufferPtr = llhttp.malloc(currentBufferSize); } - new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(data); + new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(chunk); try { let ret; try { - currentBufferRef = data; + currentBufferRef = chunk; currentParser = this; - ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, data.length); - } catch (err) { - throw err; + ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, chunk.length); } finally { currentParser = null; currentBufferRef = null; } - const offset = llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr; if (ret !== constants.ERROR.OK) { - const body = data.subarray(offset); + const data = chunk.subarray(llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr); if (ret === constants.ERROR.PAUSED_UPGRADE) { - this.onUpgrade(body); + this.onUpgrade(data); } else if (ret === constants.ERROR.PAUSED) { this.paused = true; - socket.unshift(body); + socket.unshift(data); } else { - throw this.createError(ret, body); + throw this.createError(ret, data); } } } catch (err) { @@ -6229,8 +7471,8 @@ var require_client_h1 = __commonJS({ return new HTTPParserError(message, constants.ERROR[ret], data); } destroy() { + assert(currentParser === null); assert(this.ptr != null); - assert(currentParser == null); this.llhttp.llhttp_free(this.ptr); this.ptr = null; this.timeout && timers.clearTimeout(this.timeout); @@ -6239,9 +7481,17 @@ var require_client_h1 = __commonJS({ this.timeoutType = null; this.paused = false; } + /** + * @param {Buffer} buf + * @returns {0} + */ onStatus(buf) { this.statusText = buf.toString(); + return 0; } + /** + * @returns {0|-1} + */ onMessageBegin() { const { socket, client } = this; if (socket.destroyed) { @@ -6256,7 +7506,12 @@ var require_client_h1 = __commonJS({ return -1; } request3.onResponseStarted(); + return 0; } + /** + * @param {Buffer} buf + * @returns {number} + */ onHeaderField(buf) { const len = this.headers.length; if ((len & 1) === 0) { @@ -6265,7 +7520,12 @@ var require_client_h1 = __commonJS({ this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]); } this.trackHeader(buf.length); + return 0; } + /** + * @param {Buffer} buf + * @returns {number} + */ onHeaderValue(buf) { let len = this.headers.length; if ((len & 1) === 1) { @@ -6286,15 +7546,22 @@ var require_client_h1 = __commonJS({ this.contentLength += buf.toString(); } this.trackHeader(buf.length); + return 0; } + /** + * @param {number} len + */ trackHeader(len) { this.headersSize += len; if (this.headersSize >= this.headersMaxSize) { util4.destroy(this.socket, new HeadersOverflowError()); } } + /** + * @param {Buffer} head + */ onUpgrade(head) { - const { upgrade, client, socket, headers, statusCode } = this; + const { upgrade, client, socket, headers, statusCode, statusText } = this; assert(upgrade); assert(client[kSocket] === socket); assert(!socket.destroyed); @@ -6303,9 +7570,9 @@ var require_client_h1 = __commonJS({ const request3 = client[kQueue][client[kRunningIdx]]; assert(request3); assert(request3.upgrade || request3.method === "CONNECT"); - this.statusCode = null; + this.statusCode = 0; this.statusText = ""; - this.shouldKeepAlive = null; + this.shouldKeepAlive = false; this.headers = []; this.headersSize = 0; socket.unshift(head); @@ -6319,12 +7586,19 @@ var require_client_h1 = __commonJS({ client[kQueue][client[kRunningIdx]++] = null; client.emit("disconnect", client[kUrl], [client], new InformationalError("upgrade")); try { - request3.onUpgrade(statusCode, headers, socket); + request3.onUpgrade(statusCode, headers, socket, statusText); } catch (err) { + util4.errorRequest(client, request3, err); util4.destroy(socket, err); } client[kResume](); } + /** + * @param {number} statusCode + * @param {boolean} upgrade + * @param {boolean} shouldKeepAlive + * @returns {number} + */ onHeadersComplete(statusCode, upgrade, shouldKeepAlive) { const { client, socket, headers, statusText } = this; if (socket.destroyed) { @@ -6407,6 +7681,10 @@ var require_client_h1 = __commonJS({ } return pause ? constants.ERROR.PAUSED : 0; } + /** + * @param {Buffer} buf + * @returns {number} + */ onBody(buf) { const { client, socket, statusCode, maxResponseSize } = this; if (socket.destroyed) { @@ -6429,20 +7707,24 @@ var require_client_h1 = __commonJS({ if (request3.onData(buf) === false) { return constants.ERROR.PAUSED; } + return 0; } + /** + * @returns {number} + */ onMessageComplete() { const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this; if (socket.destroyed && (!statusCode || shouldKeepAlive)) { return -1; } if (upgrade) { - return; + return 0; } assert(statusCode >= 100); assert((this.headers.length & 1) === 0); const request3 = client[kQueue][client[kRunningIdx]]; assert(request3); - this.statusCode = null; + this.statusCode = 0; this.statusText = ""; this.bytesRead = 0; this.contentLength = ""; @@ -6451,7 +7733,7 @@ var require_client_h1 = __commonJS({ this.headers = []; this.headersSize = 0; if (statusCode < 200) { - return; + return 0; } if (request3.method !== "HEAD" && contentLength && bytesRead !== parseInt(contentLength, 10)) { util4.destroy(socket, new ResponseContentLengthMismatchError()); @@ -6459,7 +7741,7 @@ var require_client_h1 = __commonJS({ } request3.onComplete(headers); client[kQueue][client[kRunningIdx]++] = null; - socket[kSocketUsed] = true; + socket[kSocketUsed] = client[kPending] === 0; if (socket[kWriting]) { assert(client[kRunning] === 0); util4.destroy(socket, new InformationalError("reset")); @@ -6471,14 +7753,19 @@ var require_client_h1 = __commonJS({ util4.destroy(socket, new InformationalError("reset")); return constants.ERROR.PAUSED; } else if (client[kPipelining] == null || client[kPipelining] === 1) { - setImmediate(() => client[kResume]()); + setImmediate(client[kResume]); } else { client[kResume](); } + return 0; } }; - function onParserTimeout(parser) { - const { socket, timeoutType, client, paused } = parser.deref(); + function onParserTimeout(parserWeakRef) { + const parser = parserWeakRef.deref(); + if (!parser) { + return; + } + const { socket, timeoutType, client, paused } = parser; if (timeoutType === TIMEOUT_HEADERS) { if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) { assert(!paused, "cannot be paused while waiting for headers"); @@ -6493,11 +7780,16 @@ var require_client_h1 = __commonJS({ util4.destroy(socket, new InformationalError("socket idle timeout")); } } - async function connectH1(client, socket) { + function connectH1(client, socket) { client[kSocket] = socket; if (!llhttpInstance) { - llhttpInstance = await llhttpPromise; - llhttpPromise = null; + llhttpInstance = lazyllhttp(); + } + if (socket.errored) { + throw socket.errored; + } + if (socket.destroyed) { + throw new SocketError("destroyed"); } socket[kNoRef] = false; socket[kWriting] = false; @@ -6507,91 +7799,43 @@ var require_client_h1 = __commonJS({ socket[kIdleSocketValidationTimeout] = null; socket[kSocketUsed] = false; socket[kParser] = new Parser(client, socket, llhttpInstance); - addListener(socket, "error", function(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); - const parser = this[kParser]; - if (err.code === "ECONNRESET" && parser.statusCode && !parser.shouldKeepAlive) { - const parserErr = parser.finish(); - if (parserErr) { - this[kError] = parserErr; - this[kClient][kOnError](parserErr); - } - return; - } - this[kError] = err; - this[kClient][kOnError](err); - }); - addListener(socket, "readable", function() { - const parser = this[kParser]; - if (parser) { - parser.readMore(); - } - }); - addListener(socket, "end", function() { - const parser = this[kParser]; - if (parser.statusCode && !parser.shouldKeepAlive) { - const parserErr = parser.finish(); - if (parserErr) { - util4.destroy(this, parserErr); - } - return; - } - util4.destroy(this, new SocketError("other side closed", util4.getSocketInfo(this))); - }); - addListener(socket, "close", function() { - const client2 = this[kClient]; - const parser = this[kParser]; - clearIdleSocketValidation(this); - if (parser) { - if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { - this[kError] = parser.finish() || this[kError]; - } - this[kParser].destroy(); - this[kParser] = null; - } - const err = this[kError] || new SocketError("closed", util4.getSocketInfo(this)); - client2[kSocket] = null; - client2[kHTTPContext] = null; - if (client2.destroyed) { - assert(client2[kPending] === 0); - const requests = client2[kQueue].splice(client2[kRunningIdx]); - for (let i = 0; i < requests.length; i++) { - const request3 = requests[i]; - util4.errorRequest(client2, request3, err); - } - } else if (client2[kRunning] > 0 && err.code !== "UND_ERR_INFO") { - const request3 = client2[kQueue][client2[kRunningIdx]]; - client2[kQueue][client2[kRunningIdx]++] = null; - util4.errorRequest(client2, request3, err); - } - client2[kPendingIdx] = client2[kRunningIdx]; - assert(client2[kRunning] === 0); - client2.emit("disconnect", client2[kUrl], [client2], err); - client2[kResume](); - }); - let closed = false; - socket.on("close", () => { - closed = true; - }); + util4.addListener(socket, "error", onHttpSocketError); + util4.addListener(socket, "readable", onHttpSocketReadable); + util4.addListener(socket, "end", onHttpSocketEnd); + util4.addListener(socket, "close", onHttpSocketClose); + socket[kClosed] = false; + socket.on("close", onSocketClose); return { version: "h1", defaultPipelining: 1, - write(...args) { - return writeH1(client, ...args); + write(request3) { + return writeH1(client, request3); }, resume() { resumeH1(client); }, + /** + * @param {Error|undefined} err + * @param {() => void} callback + */ destroy(err, callback) { - if (closed) { + if (socket[kClosed]) { queueMicrotask(callback); } else { - socket.destroy(err).on("close", callback); + socket.on("close", callback); + socket.destroy(err); } }, + /** + * @returns {boolean} + */ get destroyed() { return socket.destroyed; }, + /** + * @param {import('../core/request.js')} request + * @returns {boolean} + */ busy(request3) { if (socket[kWriting] || socket[kReset] || socket[kBlocking] || socket[kIdleSocketValidation] === 1) { return true; @@ -6611,23 +7855,83 @@ var require_client_h1 = __commonJS({ } }; } + function onHttpSocketError(err) { + const parser = this[kParser]; + if (err.code === "ECONNRESET" && parser.statusCode && !parser.shouldKeepAlive) { + const parserErr = parser.finish(); + if (parserErr) { + this[kError] = parserErr; + this[kClient][kOnError](parserErr); + } + return; + } + this[kError] = err; + this[kClient][kOnError](err); + } + function onHttpSocketReadable() { + this[kParser]?.readMore(); + } + function onHttpSocketEnd() { + const parser = this[kParser]; + if (parser.statusCode && !parser.shouldKeepAlive) { + const parserErr = parser.finish(); + if (parserErr) { + util4.destroy(this, parserErr); + } + return; + } + util4.destroy(this, new SocketError("other side closed", util4.getSocketInfo(this))); + } + function onHttpSocketClose() { + const parser = this[kParser]; + clearIdleSocketValidation(this); + if (parser) { + if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { + this[kError] = parser.finish() || this[kError]; + } + this[kParser].destroy(); + this[kParser] = null; + } + const err = this[kError] || new SocketError("closed", util4.getSocketInfo(this)); + const client = this[kClient]; + client[kSocket] = null; + client[kHTTPContext] = null; + if (client.destroyed) { + assert(client[kPending] === 0); + const requests = client[kQueue].splice(client[kRunningIdx]); + for (let i = 0; i < requests.length; i++) { + const request3 = requests[i]; + util4.errorRequest(client, request3, err); + } + } else if (client[kRunning] > 0 && err.code !== "UND_ERR_INFO") { + const request3 = client[kQueue][client[kRunningIdx]]; + client[kQueue][client[kRunningIdx]++] = null; + util4.errorRequest(client, request3, err); + } + client[kPendingIdx] = client[kRunningIdx]; + assert(client[kRunning] === 0); + client.emit("disconnect", client[kUrl], [client], err); + client[kResume](); + } + function onSocketClose() { + this[kClosed] = true; + } function clearIdleSocketValidation(socket) { if (socket[kIdleSocketValidationTimeout]) { - clearTimeout(socket[kIdleSocketValidationTimeout]); + clearImmediate(socket[kIdleSocketValidationTimeout]); socket[kIdleSocketValidationTimeout] = null; } socket[kIdleSocketValidation] = 0; } function scheduleIdleSocketValidation(client, socket) { socket[kIdleSocketValidation] = 1; - socket[kIdleSocketValidationTimeout] = setTimeout(() => { + socket[kIdleSocketValidationTimeout] = setImmediate(() => { socket[kIdleSocketValidationTimeout] = null; socket[kIdleSocketValidation] = 2; if (client[kSocket] === socket && !socket.destroyed) { client[kResume](); } - }, 0); - socket[kIdleSocketValidationTimeout].unref?.(); + }); } function resumeH1(client) { const socket = client[kSocket]; @@ -6756,6 +8060,9 @@ var require_client_h1 = __commonJS({ if (blocking) { socket[kBlocking] = true; } + if (socket.setTypeOfService) { + socket.setTypeOfService(request3.typeOfService); + } let header = `${method} ${path30} HTTP/1.1\r `; if (typeof host === "string") { @@ -6871,9 +8178,9 @@ upgrade: ${upgrade}\r } socket.on("drain", onDrain).on("error", onFinished); if (body.errorEmitted ?? body.errored) { - setImmediate(() => onFinished(body.errored)); + setImmediate(onFinished, body.errored); } else if (body.endEmitted ?? body.readableEnded) { - setImmediate(() => onFinished(null)); + setImmediate(onFinished, null); } if (body.closeEmitted ?? body.closed) { setImmediate(onClose); @@ -6970,6 +8277,17 @@ upgrade: ${upgrade}\r } } var AsyncWriter = class { + /** + * + * @param {object} arg + * @param {AbortCallback} arg.abort + * @param {import('net').Socket} arg.socket + * @param {import('../core/request.js')} arg.request + * @param {number} arg.contentLength + * @param {import('./client.js')} arg.client + * @param {boolean} arg.expectsPayload + * @param {string} arg.header + */ constructor({ abort, socket, request: request3, contentLength, client, expectsPayload, header }) { this.socket = socket; this.request = request3; @@ -6981,6 +8299,10 @@ upgrade: ${upgrade}\r this.abort = abort; socket[kWriting] = true; } + /** + * @param {Buffer} chunk + * @returns + */ write(chunk) { const { socket, request: request3, contentLength, client, bytesWritten, expectsPayload, header } = this; if (socket[kError]) { @@ -7031,6 +8353,9 @@ ${len.toString(16)}\r } return ret; } + /** + * @returns {void} + */ end() { const { socket, contentLength, client, bytesWritten, expectsPayload, header, request: request3 } = this; request3.onRequestSent(); @@ -7067,6 +8392,10 @@ ${len.toString(16)}\r } client[kResume](); } + /** + * @param {Error} [err] + * @returns {void} + */ destroy(err) { const { socket, client, abort } = this; socket[kWriting] = false; @@ -7091,7 +8420,10 @@ var require_client_h2 = __commonJS({ RequestContentLengthMismatchError, RequestAbortedError, SocketError, - InformationalError + InformationalError, + InvalidArgumentError, + HeadersTimeoutError, + BodyTimeoutError } = require_errors(); var { kUrl, @@ -7107,14 +8439,24 @@ var require_client_h2 = __commonJS({ kStrictContentLength, kOnError, kMaxConcurrentStreams, + kPingInterval, kHTTP2Session, + kHTTP2InitialWindowSize, + kHTTP2ConnectionWindowSize, kResume, kSize, - kHTTPContext + kHTTPContext, + kClosed, + kBodyTimeout, + kHeadersTimeout, + kEnableConnectProtocol, + kRemoteSettings, + kHTTP2Stream, + kHTTP2SessionState } = require_symbols(); + var { channels } = require_diagnostics(); var kOpenStreams = /* @__PURE__ */ Symbol("open streams"); var extractBody; - var h2ExperimentalWarned = false; var http2; try { http2 = require("node:http2"); @@ -7129,7 +8471,10 @@ var require_client_h2 = __commonJS({ HTTP2_HEADER_SCHEME, HTTP2_HEADER_CONTENT_LENGTH, HTTP2_HEADER_EXPECT, - HTTP2_HEADER_STATUS + HTTP2_HEADER_STATUS, + HTTP2_HEADER_PROTOCOL, + NGHTTP2_REFUSED_STREAM, + NGHTTP2_CANCEL } } = http2; function parseH2Headers(headers) { @@ -7145,85 +8490,94 @@ var require_client_h2 = __commonJS({ } return result; } - async function connectH2(client, socket) { + function connectH2(client, socket) { client[kSocket] = socket; - if (!h2ExperimentalWarned) { - h2ExperimentalWarned = true; - process.emitWarning("H2 support is experimental, expect them to change at any time.", { - code: "UNDICI-H2" - }); - } + const http2InitialWindowSize = client[kHTTP2InitialWindowSize]; + const http2ConnectionWindowSize = client[kHTTP2ConnectionWindowSize]; const session = http2.connect(client[kUrl], { createConnection: () => socket, - peerMaxConcurrentStreams: client[kMaxConcurrentStreams] + peerMaxConcurrentStreams: client[kMaxConcurrentStreams], + settings: { + // TODO(metcoder95): add support for PUSH + enablePush: false, + ...http2InitialWindowSize != null ? { initialWindowSize: http2InitialWindowSize } : null + } }); + client[kSocket] = socket; session[kOpenStreams] = 0; session[kClient] = client; session[kSocket] = socket; + session[kHTTP2SessionState] = { + ping: { + interval: client[kPingInterval] === 0 ? null : setInterval(onHttp2SendPing, client[kPingInterval], session).unref() + } + }; + session[kEnableConnectProtocol] = false; + session[kRemoteSettings] = false; + if (http2ConnectionWindowSize) { + util4.addListener(session, "connect", applyConnectionWindowSize.bind(session, http2ConnectionWindowSize)); + } util4.addListener(session, "error", onHttp2SessionError); util4.addListener(session, "frameError", onHttp2FrameError); util4.addListener(session, "end", onHttp2SessionEnd); - util4.addListener(session, "goaway", onHTTP2GoAway); - util4.addListener(session, "close", function() { - const { [kClient]: client2 } = this; - const { [kSocket]: socket2 } = client2; - const err = this[kSocket][kError] || this[kError] || new SocketError("closed", util4.getSocketInfo(socket2)); - client2[kHTTP2Session] = null; - if (client2.destroyed) { - assert(client2[kPending] === 0); - const requests = client2[kQueue].splice(client2[kRunningIdx]); - for (let i = 0; i < requests.length; i++) { - const request3 = requests[i]; - util4.errorRequest(client2, request3, err); - } - } - }); + util4.addListener(session, "goaway", onHttp2SessionGoAway); + util4.addListener(session, "close", onHttp2SessionClose); + util4.addListener(session, "remoteSettings", onHttp2RemoteSettings); session.unref(); client[kHTTP2Session] = session; socket[kHTTP2Session] = session; - util4.addListener(socket, "error", function(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); - this[kError] = err; - this[kClient][kOnError](err); - }); - util4.addListener(socket, "end", function() { - util4.destroy(this, new SocketError("other side closed", util4.getSocketInfo(this))); - }); - util4.addListener(socket, "close", function() { - const err = this[kError] || new SocketError("closed", util4.getSocketInfo(this)); - client[kSocket] = null; - if (this[kHTTP2Session] != null) { - this[kHTTP2Session].destroy(err); - } - client[kPendingIdx] = client[kRunningIdx]; - assert(client[kRunning] === 0); - client.emit("disconnect", client[kUrl], [client], err); - client[kResume](); - }); - let closed = false; - socket.on("close", () => { - closed = true; - }); + util4.addListener(socket, "error", onHttp2SocketError); + util4.addListener(socket, "end", onHttp2SocketEnd); + util4.addListener(socket, "close", onHttp2SocketClose); + socket[kClosed] = false; + socket.on("close", onSocketClose); return { version: "h2", defaultPipelining: Infinity, - write(...args) { - return writeH2(client, ...args); + /** + * @param {import('../core/request.js')} request + * @returns {boolean} + */ + write(request3) { + return writeH2(client, request3); }, + /** + * @returns {void} + */ resume() { resumeH2(client); }, + /** + * @param {Error | null} err + * @param {() => void} callback + */ destroy(err, callback) { - if (closed) { + if (socket[kClosed]) { queueMicrotask(callback); } else { socket.destroy(err).on("close", callback); } }, + /** + * @type {boolean} + */ get destroyed() { return socket.destroyed; }, - busy() { + /** + * @param {import('../core/request.js')} request + * @returns {boolean} + */ + busy(request3) { + if (request3 != null) { + if (client[kRunning] > 0) { + if (request3.idempotent === false) return true; + if ((request3.upgrade === "websocket" || request3.method === "CONNECT") && session[kRemoteSettings] === false) return true; + if (util4.bodyLength(request3.body) !== 0 && (util4.isStream(request3.body) || util4.isAsyncIterable(request3.body) || util4.isFormDataLike(request3.body))) return true; + } else { + return (request3.upgrade === "websocket" || request3.method === "CONNECT") && session[kRemoteSettings] === false; + } + } return false; } }; @@ -7231,7 +8585,7 @@ var require_client_h2 = __commonJS({ function resumeH2(client) { const socket = client[kSocket]; if (socket?.destroyed === false) { - if (client[kSize] === 0 && client[kMaxConcurrentStreams] === 0) { + if (client[kSize] === 0) { socket.unref(); client[kHTTP2Session].unref(); } else { @@ -7240,8 +8594,47 @@ var require_client_h2 = __commonJS({ } } } + function applyConnectionWindowSize(connectionWindowSize) { + try { + if (typeof this.setLocalWindowSize === "function") { + this.setLocalWindowSize(connectionWindowSize); + } + } catch { + } + } + function onHttp2RemoteSettings(settings) { + this[kClient][kMaxConcurrentStreams] = settings.maxConcurrentStreams ?? this[kClient][kMaxConcurrentStreams]; + if (this[kRemoteSettings] === true && this[kEnableConnectProtocol] === true && settings.enableConnectProtocol === false) { + const err = new InformationalError("HTTP/2: Server disabled extended CONNECT protocol against RFC-8441"); + this[kSocket][kError] = err; + this[kClient][kOnError](err); + return; + } + this[kEnableConnectProtocol] = settings.enableConnectProtocol ?? this[kEnableConnectProtocol]; + this[kRemoteSettings] = true; + this[kClient][kResume](); + } + function onHttp2SendPing(session) { + const state = session[kHTTP2SessionState]; + if ((session.closed || session.destroyed) && state.ping.interval != null) { + clearInterval(state.ping.interval); + state.ping.interval = null; + return; + } + session.ping(onPing.bind(session)); + function onPing(err, duration) { + const client = this[kClient]; + const socket = this[kClient]; + if (err != null) { + const error3 = new InformationalError(`HTTP/2: "PING" errored - type ${err.message}`); + socket[kError] = error3; + client[kOnError](error3); + } else { + client.emit("ping", duration); + } + } + } function onHttp2SessionError(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); this[kSocket][kError] = err; this[kClient][kOnError](err); } @@ -7257,54 +8650,129 @@ var require_client_h2 = __commonJS({ this.destroy(err); util4.destroy(this[kSocket], err); } - function onHTTP2GoAway(code) { - const err = this[kError] || new SocketError(`HTTP/2: "GOAWAY" frame received with code ${code}`, util4.getSocketInfo(this)); + function completeRequest(client, request3, resetPendingIdx = false) { + const queue2 = client[kQueue]; + const runningIdx = client[kRunningIdx]; + if (runningIdx < client[kPendingIdx] && queue2[runningIdx] === request3) { + queue2[runningIdx] = null; + client[kRunningIdx] = runningIdx + 1; + return; + } + const index2 = queue2.indexOf(request3, runningIdx); + if (index2 === -1 || index2 >= client[kPendingIdx]) { + return; + } + queue2.splice(index2, 1); + client[kPendingIdx]--; + if (resetPendingIdx && client[kPendingIdx] < client[kRunningIdx]) { + client[kPendingIdx] = client[kRunningIdx]; + } + } + function onHttp2SessionGoAway(errorCode) { + const err = this[kError] || new SocketError(`HTTP/2: "GOAWAY" frame received with code ${errorCode}`, util4.getSocketInfo(this[kSocket])); const client = this[kClient]; client[kSocket] = null; client[kHTTPContext] = null; - if (this[kHTTP2Session] != null) { - this[kHTTP2Session].destroy(err); - this[kHTTP2Session] = null; - } + this.close(); + this[kHTTP2Session] = null; util4.destroy(this[kSocket], err); if (client[kRunningIdx] < client[kQueue].length) { const request3 = client[kQueue][client[kRunningIdx]]; client[kQueue][client[kRunningIdx]++] = null; - util4.errorRequest(client, request3, err); + if (request3 != null) { + util4.errorRequest(client, request3, err); + } client[kPendingIdx] = client[kRunningIdx]; } assert(client[kRunning] === 0); client.emit("disconnect", client[kUrl], [client], err); + client.emit("connectionError", client[kUrl], [client], err); + client[kResume](); + } + function onHttp2SessionClose() { + const { [kClient]: client, [kHTTP2SessionState]: state } = this; + const { [kSocket]: socket } = client; + const err = this[kSocket][kError] || this[kError] || new SocketError("closed", util4.getSocketInfo(socket)); + client[kSocket] = null; + client[kHTTPContext] = null; + if (state.ping.interval != null) { + clearInterval(state.ping.interval); + state.ping.interval = null; + } + if (client.destroyed) { + assert(client[kPending] === 0); + const requests = client[kQueue].splice(client[kRunningIdx]); + for (let i = 0; i < requests.length; i++) { + const request3 = requests[i]; + if (request3 != null) { + util4.errorRequest(client, request3, err); + } + } + } + } + function onHttp2SocketClose() { + const err = this[kError] || new SocketError("closed", util4.getSocketInfo(this)); + const client = this[kHTTP2Session][kClient]; + client[kSocket] = null; + client[kHTTPContext] = null; + if (this[kHTTP2Session] !== null) { + this[kHTTP2Session].destroy(err); + } + client[kPendingIdx] = client[kRunningIdx]; + assert(client[kRunning] === 0); + client.emit("disconnect", client[kUrl], [client], err); client[kResume](); } + function onHttp2SocketError(err) { + this[kError] = err; + this[kClient][kOnError](err); + } + function onHttp2SocketEnd() { + util4.destroy(this, new SocketError("other side closed", util4.getSocketInfo(this))); + } + function onSocketClose() { + this[kClosed] = true; + } function shouldSendContentLength(method) { return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; } function writeH2(client, request3) { + const headersTimeout = request3.headersTimeout ?? client[kHeadersTimeout]; + const bodyTimeout = request3.bodyTimeout ?? client[kBodyTimeout]; const session = client[kHTTP2Session]; - const { method, path: path30, host, upgrade, expectContinue, signal, headers: reqHeaders } = request3; + const { method, path: path30, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request3; let { body } = request3; - if (upgrade) { - util4.errorRequest(client, request3, new Error("Upgrade not supported for H2")); + if (upgrade != null && upgrade !== "websocket") { + util4.errorRequest(client, request3, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`)); return false; } const headers = {}; for (let n = 0; n < reqHeaders.length; n += 2) { const key = reqHeaders[n + 0]; const val = reqHeaders[n + 1]; + if (key === "cookie") { + if (headers[key] != null) { + headers[key] = Array.isArray(headers[key]) ? (headers[key].push(val), headers[key]) : [headers[key], val]; + } else { + headers[key] = val; + } + continue; + } if (Array.isArray(val)) { for (let i = 0; i < val.length; i++) { if (headers[key]) { - headers[key] += `,${val[i]}`; + headers[key] += `, ${val[i]}`; } else { headers[key] = val[i]; } } + } else if (headers[key]) { + headers[key] += `, ${val}`; } else { headers[key] = val; } } - let stream2; + let stream2 = null; const { hostname, port } = client[kUrl]; headers[HTTP2_HEADER_AUTHORITY] = host || `${hostname}${port ? `:${port}` : ""}`; headers[HTTP2_HEADER_METHOD] = method; @@ -7315,11 +8783,13 @@ var require_client_h2 = __commonJS({ err = err || new RequestAbortedError(); util4.errorRequest(client, request3, err); if (stream2 != null) { - util4.destroy(stream2, err); + stream2.removeAllListeners("data"); + stream2.close(); + client[kOnError](err); + completeRequest(client, request3); + client[kResume](); } util4.destroy(body, err); - client[kQueue][client[kRunningIdx]++] = null; - client[kResume](); }; try { request3.onConnect(abort); @@ -7329,28 +8799,70 @@ var require_client_h2 = __commonJS({ if (request3.aborted) { return false; } - if (method === "CONNECT") { + if (upgrade || method === "CONNECT") { session.ref(); - stream2 = session.request(headers, { endStream: false, signal }); - if (stream2.id && !stream2.pending) { - request3.onUpgrade(null, null, stream2); + if (upgrade === "websocket") { + if (session[kEnableConnectProtocol] === false) { + util4.errorRequest(client, request3, new InformationalError("HTTP/2: Extended CONNECT protocol not supported by server")); + session.unref(); + return false; + } + headers[HTTP2_HEADER_METHOD] = "CONNECT"; + headers[HTTP2_HEADER_PROTOCOL] = "websocket"; + headers[HTTP2_HEADER_PATH] = path30; + if (protocol === "ws:" || protocol === "wss:") { + headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https"; + } else { + headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https"; + } + stream2 = session.request(headers, { endStream: false, signal }); + stream2[kHTTP2Stream] = true; ++session[kOpenStreams]; - client[kQueue][client[kRunningIdx]++] = null; - } else { - stream2.once("ready", () => { - request3.onUpgrade(null, null, stream2); - ++session[kOpenStreams]; - client[kQueue][client[kRunningIdx]++] = null; + stream2.once("response", (headers2, _flags) => { + const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers2; + try { + request3.onUpgrade(statusCode, parseH2Headers(realHeaders), stream2); + } catch (err) { + abort(err); + return; + } + completeRequest(client, request3); + }); + stream2.on("error", () => { + if (stream2.rstCode === NGHTTP2_REFUSED_STREAM || stream2.rstCode === NGHTTP2_CANCEL) { + abort(new InformationalError(`HTTP/2: "stream error" received - code ${stream2.rstCode}`)); + } }); + stream2.once("close", () => { + session[kOpenStreams] -= 1; + if (session[kOpenStreams] === 0) session.unref(); + }); + stream2.setTimeout(headersTimeout); + return true; } + stream2 = session.request(headers, { endStream: false, signal }); + stream2[kHTTP2Stream] = true; + ++session[kOpenStreams]; + stream2.on("response", (headers2) => { + const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers2; + try { + request3.onUpgrade(statusCode, parseH2Headers(realHeaders), stream2); + } catch (err) { + abort(err); + return; + } + completeRequest(client, request3); + }); + stream2.on("error", abort); stream2.once("close", () => { session[kOpenStreams] -= 1; if (session[kOpenStreams] === 0) session.unref(); }); + stream2.setTimeout(headersTimeout); return true; } headers[HTTP2_HEADER_PATH] = path30; - headers[HTTP2_HEADER_SCHEME] = "https"; + headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https"; const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; if (body && typeof body.read === "function") { body.read(0); @@ -7366,7 +8878,7 @@ var require_client_h2 = __commonJS({ if (contentLength == null) { contentLength = request3.contentLength; } - if (contentLength === 0 || !expectsPayload) { + if (!expectsPayload) { contentLength = null; } if (shouldSendContentLength(method) && contentLength > 0 && request3.contentLength != null && request3.contentLength !== contentLength) { @@ -7377,65 +8889,107 @@ var require_client_h2 = __commonJS({ process.emitWarning(new RequestContentLengthMismatchError()); } if (contentLength != null) { - assert(body, "no body must not have content length"); + assert(body || contentLength === 0, "no body must not have content length"); headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}`; } session.ref(); + if (channels.sendHeaders.hasSubscribers) { + let header = ""; + for (const key in headers) { + header += `${key}: ${headers[key]}\r +`; + } + channels.sendHeaders.publish({ request: request3, headers: header, socket: session[kSocket] }); + } const shouldEndStream = method === "GET" || method === "HEAD" || body === null; if (expectContinue) { headers[HTTP2_HEADER_EXPECT] = "100-continue"; stream2 = session.request(headers, { endStream: shouldEndStream, signal }); + stream2[kHTTP2Stream] = true; stream2.once("continue", writeBodyH2); } else { stream2 = session.request(headers, { endStream: shouldEndStream, signal }); + stream2[kHTTP2Stream] = true; writeBodyH2(); } ++session[kOpenStreams]; + stream2.setTimeout(headersTimeout); + let responseReceived = false; stream2.once("response", (headers2) => { const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers2; request3.onResponseStarted(); + responseReceived = true; + stream2.setTimeout(bodyTimeout); if (request3.aborted) { - const err = new RequestAbortedError(); - util4.errorRequest(client, request3, err); - util4.destroy(stream2, err); + stream2.removeAllListeners("data"); return; } if (request3.onHeaders(Number(statusCode), parseH2Headers(realHeaders), stream2.resume.bind(stream2), "") === false) { stream2.pause(); } stream2.on("data", (chunk) => { + if (request3.aborted || request3.completed) { + return; + } if (request3.onData(chunk) === false) { stream2.pause(); } }); }); stream2.once("end", () => { - if (stream2.state?.state == null || stream2.state.state < 6) { - request3.onComplete([]); - } - if (session[kOpenStreams] === 0) { - session.unref(); + stream2.removeAllListeners("data"); + if (responseReceived) { + if (!request3.aborted && !request3.completed) { + request3.onComplete({}); + } + completeRequest(client, request3); + client[kResume](); + } else { + abort(new InformationalError("HTTP/2: stream half-closed (remote)")); + completeRequest(client, request3, true); + client[kResume](); } - abort(new InformationalError("HTTP/2: stream half-closed (remote)")); - client[kQueue][client[kRunningIdx]++] = null; - client[kPendingIdx] = client[kRunningIdx]; - client[kResume](); }); stream2.once("close", () => { + stream2.removeAllListeners("data"); session[kOpenStreams] -= 1; if (session[kOpenStreams] === 0) { session.unref(); } + if (!request3.aborted && !request3.completed) { + abort(new InformationalError("HTTP/2: stream closed before the response was complete")); + } }); stream2.once("error", function(err) { + stream2.removeAllListeners("data"); abort(err); }); stream2.once("frameError", (type, code) => { + stream2.removeAllListeners("data"); abort(new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`)); }); + stream2.on("aborted", () => { + stream2.removeAllListeners("data"); + }); + stream2.on("timeout", () => { + const err = responseReceived ? new BodyTimeoutError(`HTTP/2: "body timeout after ${bodyTimeout}"`) : new HeadersTimeoutError(`HTTP/2: "headers timeout after ${headersTimeout}"`); + stream2.removeAllListeners("data"); + session[kOpenStreams] -= 1; + if (session[kOpenStreams] === 0) { + session.unref(); + } + abort(err); + }); + stream2.once("trailers", (trailers) => { + if (request3.aborted || request3.completed) { + return; + } + stream2.removeAllListeners("data"); + request3.onComplete(trailers); + }); return true; function writeBodyH2() { if (!body || contentLength === 0) { @@ -7621,187 +9175,6 @@ var require_client_h2 = __commonJS({ } }); -// node_modules/undici/lib/handler/redirect-handler.js -var require_redirect_handler = __commonJS({ - "node_modules/undici/lib/handler/redirect-handler.js"(exports2, module2) { - "use strict"; - var util4 = require_util(); - var { kBodyUsed } = require_symbols(); - var assert = require("node:assert"); - var { InvalidArgumentError } = require_errors(); - var EE = require("node:events"); - var redirectableStatusCodes = [300, 301, 302, 303, 307, 308]; - var kBody = /* @__PURE__ */ Symbol("body"); - var BodyAsyncIterable = class { - constructor(body) { - this[kBody] = body; - this[kBodyUsed] = false; - } - async *[Symbol.asyncIterator]() { - assert(!this[kBodyUsed], "disturbed"); - this[kBodyUsed] = true; - yield* this[kBody]; - } - }; - var RedirectHandler = class { - constructor(dispatch, maxRedirections, opts, handler2) { - if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { - throw new InvalidArgumentError("maxRedirections must be a positive number"); - } - util4.validateHandler(handler2, opts.method, opts.upgrade); - this.dispatch = dispatch; - this.location = null; - this.abort = null; - this.opts = { ...opts, maxRedirections: 0 }; - this.maxRedirections = maxRedirections; - this.handler = handler2; - this.history = []; - this.redirectionLimitReached = false; - if (util4.isStream(this.opts.body)) { - if (util4.bodyLength(this.opts.body) === 0) { - this.opts.body.on("data", function() { - assert(false); - }); - } - if (typeof this.opts.body.readableDidRead !== "boolean") { - this.opts.body[kBodyUsed] = false; - EE.prototype.on.call(this.opts.body, "data", function() { - this[kBodyUsed] = true; - }); - } - } else if (this.opts.body && typeof this.opts.body.pipeTo === "function") { - this.opts.body = new BodyAsyncIterable(this.opts.body); - } else if (this.opts.body && typeof this.opts.body !== "string" && !ArrayBuffer.isView(this.opts.body) && util4.isIterable(this.opts.body)) { - this.opts.body = new BodyAsyncIterable(this.opts.body); - } - } - onConnect(abort) { - this.abort = abort; - this.handler.onConnect(abort, { history: this.history }); - } - onUpgrade(statusCode, headers, socket) { - this.handler.onUpgrade(statusCode, headers, socket); - } - onError(error3) { - this.handler.onError(error3); - } - onHeaders(statusCode, headers, resume, statusText) { - this.location = this.history.length >= this.maxRedirections || util4.isDisturbed(this.opts.body) ? null : parseLocation(statusCode, headers); - if (this.opts.throwOnMaxRedirect && this.history.length >= this.maxRedirections) { - if (this.request) { - this.request.abort(new Error("max redirects")); - } - this.redirectionLimitReached = true; - this.abort(new Error("max redirects")); - return; - } - if (this.opts.origin) { - this.history.push(new URL(this.opts.path, this.opts.origin)); - } - if (!this.location) { - return this.handler.onHeaders(statusCode, headers, resume, statusText); - } - const { origin, pathname, search } = util4.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))); - const path30 = search ? `${pathname}${search}` : pathname; - this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin); - this.opts.path = path30; - this.opts.origin = origin; - this.opts.maxRedirections = 0; - this.opts.query = null; - if (statusCode === 303 && this.opts.method !== "HEAD") { - this.opts.method = "GET"; - this.opts.body = null; - } - } - onData(chunk) { - if (this.location) { - } else { - return this.handler.onData(chunk); - } - } - onComplete(trailers) { - if (this.location) { - this.location = null; - this.abort = null; - this.dispatch(this.opts, this); - } else { - this.handler.onComplete(trailers); - } - } - onBodySent(chunk) { - if (this.handler.onBodySent) { - this.handler.onBodySent(chunk); - } - } - }; - function parseLocation(statusCode, headers) { - if (redirectableStatusCodes.indexOf(statusCode) === -1) { - return null; - } - for (let i = 0; i < headers.length; i += 2) { - if (headers[i].length === 8 && util4.headerNameToString(headers[i]) === "location") { - return headers[i + 1]; - } - } - } - function shouldRemoveHeader(header, removeContent, unknownOrigin) { - if (header.length === 4) { - return util4.headerNameToString(header) === "host"; - } - if (removeContent && util4.headerNameToString(header).startsWith("content-")) { - return true; - } - if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) { - const name = util4.headerNameToString(header); - return name === "authorization" || name === "cookie" || name === "proxy-authorization"; - } - return false; - } - function cleanRequestHeaders(headers, removeContent, unknownOrigin) { - const ret = []; - if (Array.isArray(headers)) { - for (let i = 0; i < headers.length; i += 2) { - if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { - ret.push(headers[i], headers[i + 1]); - } - } - } else if (headers && typeof headers === "object") { - for (const key of Object.keys(headers)) { - if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { - ret.push(key, headers[key]); - } - } - } else { - assert(headers == null, "headers must be an object or an array"); - } - return ret; - } - module2.exports = RedirectHandler; - } -}); - -// node_modules/undici/lib/interceptor/redirect-interceptor.js -var require_redirect_interceptor = __commonJS({ - "node_modules/undici/lib/interceptor/redirect-interceptor.js"(exports2, module2) { - "use strict"; - var RedirectHandler = require_redirect_handler(); - function createRedirectInterceptor({ maxRedirections: defaultMaxRedirections }) { - return (dispatch) => { - return function Intercept(opts, handler2) { - const { maxRedirections = defaultMaxRedirections } = opts; - if (!maxRedirections) { - return dispatch(opts, handler2); - } - const redirectHandler = new RedirectHandler(dispatch, maxRedirections, opts, handler2); - opts = { ...opts, maxRedirections: 0 }; - return dispatch(opts, redirectHandler); - }; - }; - } - module2.exports = createRedirectInterceptor; - } -}); - // node_modules/undici/lib/dispatcher/client.js var require_client = __commonJS({ "node_modules/undici/lib/dispatcher/client.js"(exports2, module2) { @@ -7810,6 +9183,7 @@ var require_client = __commonJS({ var net = require("node:net"); var http = require("node:http"); var util4 = require_util(); + var { ClientStats } = require_stats(); var { channels } = require_diagnostics(); var Request = require_request(); var DispatcherBase = require_dispatcher_base(); @@ -7847,24 +9221,27 @@ var require_client = __commonJS({ kBodyTimeout, kStrictContentLength, kConnector, - kMaxRedirections, kMaxRequests, kCounter, kClose, kDestroy, kDispatch, - kInterceptors, kLocalAddress, kMaxResponseSize, kOnError, kHTTPContext, kMaxConcurrentStreams, - kResume + kHTTP2InitialWindowSize, + kHTTP2ConnectionWindowSize, + kResume, + kPingInterval } = require_symbols(); var connectH1 = require_client_h1(); var connectH2 = require_client_h2(); - var deprecatedInterceptorWarned = false; var kClosedResolve = /* @__PURE__ */ Symbol("kClosedResolve"); + var getDefaultNodeMaxHeaderSize = http && http.maxHeaderSize && Number.isInteger(http.maxHeaderSize) && http.maxHeaderSize > 0 ? () => http.maxHeaderSize : () => { + throw new InvalidArgumentError("http module not available or http.maxHeaderSize invalid"); + }; var noop3 = () => { }; function getPipelining(client) { @@ -7877,7 +9254,6 @@ var require_client = __commonJS({ * @param {import('../../types/client.js').Client.Options} options */ constructor(url2, { - interceptors, maxHeaderSize, headersTimeout, socketTimeout, @@ -7895,7 +9271,6 @@ var require_client = __commonJS({ tls, strictContentLength, maxCachedSessions, - maxRedirections, connect: connect2, maxRequestsPerClient, localAddress, @@ -7905,9 +9280,13 @@ var require_client = __commonJS({ // h2 maxConcurrentStreams, allowH2, - webSocket + useH2c, + initialWindowSize, + connectionWindowSize, + pingInterval, + webSocket, + eventSource } = {}) { - super({ webSocket }); if (keepAlive !== void 0) { throw new InvalidArgumentError("unsupported keepAlive, use pipelining=0 instead"); } @@ -7923,8 +9302,12 @@ var require_client = __commonJS({ if (maxKeepAliveTimeout !== void 0) { throw new InvalidArgumentError("unsupported maxKeepAliveTimeout, use keepAliveMaxTimeout instead"); } - if (maxHeaderSize != null && !Number.isFinite(maxHeaderSize)) { - throw new InvalidArgumentError("invalid maxHeaderSize"); + if (maxHeaderSize != null) { + if (!Number.isInteger(maxHeaderSize) || maxHeaderSize < 1) { + throw new InvalidArgumentError("invalid maxHeaderSize"); + } + } else { + maxHeaderSize = getDefaultNodeMaxHeaderSize(); } if (socketPath != null && typeof socketPath !== "string") { throw new InvalidArgumentError("invalid socketPath"); @@ -7950,9 +9333,6 @@ var require_client = __commonJS({ if (connect2 != null && typeof connect2 !== "function" && typeof connect2 !== "object") { throw new InvalidArgumentError("connect must be a function or an object"); } - if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { - throw new InvalidArgumentError("maxRedirections must be a positive number"); - } if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) { throw new InvalidArgumentError("maxRequestsPerClient must be a positive number"); } @@ -7971,32 +9351,42 @@ var require_client = __commonJS({ if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== "number" || maxConcurrentStreams < 1)) { throw new InvalidArgumentError("maxConcurrentStreams must be a positive integer, greater than 0"); } + if (useH2c != null && typeof useH2c !== "boolean") { + throw new InvalidArgumentError("useH2c must be a valid boolean value"); + } + if (initialWindowSize != null && (!Number.isInteger(initialWindowSize) || initialWindowSize < 1)) { + throw new InvalidArgumentError("initialWindowSize must be a positive integer, greater than 0"); + } + if (connectionWindowSize != null && (!Number.isInteger(connectionWindowSize) || connectionWindowSize < 1)) { + throw new InvalidArgumentError("connectionWindowSize must be a positive integer, greater than 0"); + } + if (pingInterval != null && (typeof pingInterval !== "number" || !Number.isInteger(pingInterval) || pingInterval < 0)) { + throw new InvalidArgumentError("pingInterval must be a positive integer, greater or equal to 0"); + } + super({ webSocket, eventSource }); if (typeof connect2 !== "function") { connect2 = buildConnector({ ...tls, maxCachedSessions, allowH2, + useH2c, socketPath, timeout: connectTimeout, - ...autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0, + ...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0, ...connect2 }); - } - if (interceptors?.Client && Array.isArray(interceptors.Client)) { - this[kInterceptors] = interceptors.Client; - if (!deprecatedInterceptorWarned) { - deprecatedInterceptorWarned = true; - process.emitWarning("Client.Options#interceptor is deprecated. Use Dispatcher#compose instead.", { - code: "UNDICI-CLIENT-INTERCEPTOR-DEPRECATED" - }); - } } else { - this[kInterceptors] = [createRedirectInterceptor({ maxRedirections })]; + const customConnect = connect2; + connect2 = (opts, callback) => customConnect({ + ...opts, + ...socketPath != null ? { socketPath } : null, + ...allowH2 != null ? { allowH2 } : null + }, callback); } this[kUrl] = util4.parseOrigin(url2); this[kConnector] = connect2; this[kPipelining] = pipelining != null ? pipelining : 1; - this[kMaxHeadersSize] = maxHeaderSize || http.maxHeaderSize; + this[kMaxHeadersSize] = maxHeaderSize; this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout; this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 6e5 : keepAliveMaxTimeout; this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 2e3 : keepAliveTimeoutThreshold; @@ -8010,12 +9400,14 @@ var require_client = __commonJS({ this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 3e5; this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 3e5; this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength; - this[kMaxRedirections] = maxRedirections; this[kMaxRequests] = maxRequestsPerClient; this[kClosedResolve] = null; this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1; - this[kMaxConcurrentStreams] = maxConcurrentStreams != null ? maxConcurrentStreams : 100; this[kHTTPContext] = null; + this[kMaxConcurrentStreams] = maxConcurrentStreams != null ? maxConcurrentStreams : 100; + this[kHTTP2InitialWindowSize] = initialWindowSize != null ? initialWindowSize : 262144; + this[kHTTP2ConnectionWindowSize] = connectionWindowSize != null ? connectionWindowSize : 524288; + this[kPingInterval] = pingInterval != null ? pingInterval : 6e4; this[kQueue] = []; this[kRunningIdx] = 0; this[kPendingIdx] = 0; @@ -8029,6 +9421,9 @@ var require_client = __commonJS({ this[kPipelining] = value; this[kResume](true); } + get stats() { + return new ClientStats(this); + } get [kPending]() { return this[kQueue].length - this[kPendingIdx]; } @@ -8046,14 +9441,12 @@ var require_client = __commonJS({ this[kHTTPContext]?.busy(null) || this[kSize] >= (getPipelining(this) || 1) || this[kPending] > 0 ); } - /* istanbul ignore: only used for test */ [kConnect](cb) { connect(this); this.once("connect", cb); } [kDispatch](opts, handler2) { - const origin = opts.origin || this[kUrl].origin; - const request3 = new Request(origin, opts, handler2); + const request3 = new Request(this[kUrl].origin, opts, handler2); this[kQueue].push(request3); if (this[kResuming]) { } else if (util4.bodyLength(request3.body) == null && util4.isIterable(request3.body)) { @@ -8067,7 +9460,7 @@ var require_client = __commonJS({ } return this[kNeedDrain] < 2; } - async [kClose]() { + [kClose]() { return new Promise((resolve15) => { if (this[kSize]) { this[kClosedResolve] = resolve15; @@ -8076,12 +9469,14 @@ var require_client = __commonJS({ } }); } - async [kDestroy](err) { + [kDestroy](err) { return new Promise((resolve15) => { const requests = this[kQueue].splice(this[kPendingIdx]); for (let i = 0; i < requests.length; i++) { const request3 = requests[i]; - util4.errorRequest(this, request3, err); + if (request3 != null) { + util4.errorRequest(this, request3, err); + } } const callback = () => { if (this[kClosedResolve]) { @@ -8100,19 +9495,20 @@ var require_client = __commonJS({ }); } }; - var createRedirectInterceptor = require_redirect_interceptor(); function onError(client, err) { if (client[kRunning] === 0 && err.code !== "UND_ERR_INFO" && err.code !== "UND_ERR_SOCKET") { assert(client[kPendingIdx] === client[kRunningIdx]); const requests = client[kQueue].splice(client[kRunningIdx]); for (let i = 0; i < requests.length; i++) { const request3 = requests[i]; - util4.errorRequest(client, request3, err); + if (request3 != null) { + util4.errorRequest(client, request3, err); + } } assert(client[kSize] === 0); } } - async function connect(client) { + function connect(client) { assert(!client[kConnecting]); assert(!client[kHTTPContext]); let { host, hostname, protocol, port } = client[kUrl]; @@ -8120,7 +9516,7 @@ var require_client = __commonJS({ const idx = hostname.indexOf("]"); assert(idx !== -1); const ip = hostname.substring(1, idx); - assert(net.isIP(ip)); + assert(net.isIPv6(ip)); hostname = ip; } client[kConnecting] = true; @@ -8139,86 +9535,91 @@ var require_client = __commonJS({ }); } try { - const socket = await new Promise((resolve15, reject) => { - client[kConnector]({ + client[kConnector]({ + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, (err, socket) => { + if (err) { + handleConnectError(client, err, { host, hostname, protocol, port }); + client[kResume](); + return; + } + if (client.destroyed) { + util4.destroy(socket.on("error", noop3), new ClientDestroyedError()); + client[kResume](); + return; + } + assert(socket); + try { + client[kHTTPContext] = socket.alpnProtocol === "h2" ? connectH2(client, socket) : connectH1(client, socket); + } catch (err2) { + socket.destroy().on("error", noop3); + handleConnectError(client, err2, { host, hostname, protocol, port }); + client[kResume](); + return; + } + client[kConnecting] = false; + socket[kCounter] = 0; + socket[kMaxRequests] = client[kMaxRequests]; + socket[kClient] = client; + socket[kError] = null; + if (channels.connected.hasSubscribers) { + channels.connected.publish({ + connectParams: { + host, + hostname, + protocol, + port, + version: client[kHTTPContext]?.version, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + socket + }); + } + client.emit("connect", client[kUrl], [client]); + client[kResume](); + }); + } catch (err) { + handleConnectError(client, err, { host, hostname, protocol, port }); + client[kResume](); + } + } + function handleConnectError(client, err, { host, hostname, protocol, port }) { + if (client.destroyed) { + return; + } + client[kConnecting] = false; + if (channels.connectError.hasSubscribers) { + channels.connectError.publish({ + connectParams: { host, hostname, protocol, port, + version: client[kHTTPContext]?.version, servername: client[kServerName], localAddress: client[kLocalAddress] - }, (err, socket2) => { - if (err) { - reject(err); - } else { - resolve15(socket2); - } - }); + }, + connector: client[kConnector], + error: err }); - if (client.destroyed) { - util4.destroy(socket.on("error", noop3), new ClientDestroyedError()); - return; - } - assert(socket); - try { - client[kHTTPContext] = socket.alpnProtocol === "h2" ? await connectH2(client, socket) : await connectH1(client, socket); - } catch (err) { - socket.destroy().on("error", noop3); - throw err; - } - client[kConnecting] = false; - socket[kCounter] = 0; - socket[kMaxRequests] = client[kMaxRequests]; - socket[kClient] = client; - socket[kError] = null; - if (channels.connected.hasSubscribers) { - channels.connected.publish({ - connectParams: { - host, - hostname, - protocol, - port, - version: client[kHTTPContext]?.version, - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, - connector: client[kConnector], - socket - }); - } - client.emit("connect", client[kUrl], [client]); - } catch (err) { - if (client.destroyed) { - return; - } - client[kConnecting] = false; - if (channels.connectError.hasSubscribers) { - channels.connectError.publish({ - connectParams: { - host, - hostname, - protocol, - port, - version: client[kHTTPContext]?.version, - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, - connector: client[kConnector], - error: err - }); - } - if (err.code === "ERR_TLS_CERT_ALTNAME_INVALID") { - assert(client[kRunning] === 0); - while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { - const request3 = client[kQueue][client[kPendingIdx]++]; - util4.errorRequest(client, request3, err); - } - } else { - onError(client, err); + } + if (err.code === "ERR_TLS_CERT_ALTNAME_INVALID") { + assert(client[kRunning] === 0); + while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { + const request3 = client[kQueue][client[kPendingIdx]++]; + util4.errorRequest(client, request3, err); } - client.emit("connectionError", client[kUrl], [client], err); + } else { + onError(client, err); } - client[kResume](); + client.emit("connectionError", client[kUrl], [client], err); } function emitDrain(client) { client[kNeedDrain] = 0; @@ -8269,6 +9670,9 @@ var require_client = __commonJS({ return; } const request3 = client[kQueue][client[kPendingIdx]]; + if (request3 === null) { + return; + } if (client[kUrl].protocol === "https:" && client[kServerName] !== request3.servername) { if (client[kRunning] > 0) { return; @@ -8310,26 +9714,36 @@ var require_fixed_queue = __commonJS({ var kSize = 2048; var kMask = kSize - 1; var FixedCircularBuffer = class { - constructor() { - this.bottom = 0; - this.top = 0; - this.list = new Array(kSize); - this.next = null; - } + /** @type {number} */ + bottom = 0; + /** @type {number} */ + top = 0; + /** @type {Array} */ + list = new Array(kSize).fill(void 0); + /** @type {T|null} */ + next = null; + /** @returns {boolean} */ isEmpty() { return this.top === this.bottom; } + /** @returns {boolean} */ isFull() { return (this.top + 1 & kMask) === this.bottom; } + /** + * @param {T} data + * @returns {void} + */ push(data) { this.list[this.top] = data; this.top = this.top + 1 & kMask; } + /** @returns {T|null} */ shift() { const nextItem = this.list[this.bottom]; - if (nextItem === void 0) + if (nextItem === void 0) { return null; + } this.list[this.bottom] = void 0; this.bottom = this.bottom + 1 & kMask; return nextItem; @@ -8339,20 +9753,24 @@ var require_fixed_queue = __commonJS({ constructor() { this.head = this.tail = new FixedCircularBuffer(); } + /** @returns {boolean} */ isEmpty() { return this.head.isEmpty(); } + /** @param {T} data */ push(data) { if (this.head.isFull()) { this.head = this.head.next = new FixedCircularBuffer(); } this.head.push(data); } + /** @returns {T|null} */ shift() { const tail = this.tail; const next = tail.shift(); if (tail.isEmpty() && tail.next !== null) { this.tail = tail.next; + tail.next = null; } return next; } @@ -8360,46 +9778,14 @@ var require_fixed_queue = __commonJS({ } }); -// node_modules/undici/lib/dispatcher/pool-stats.js -var require_pool_stats = __commonJS({ - "node_modules/undici/lib/dispatcher/pool-stats.js"(exports2, module2) { - var { kFree, kConnected, kPending, kQueued, kRunning, kSize } = require_symbols(); - var kPool = /* @__PURE__ */ Symbol("pool"); - var PoolStats = class { - constructor(pool) { - this[kPool] = pool; - } - get connected() { - return this[kPool][kConnected]; - } - get free() { - return this[kPool][kFree]; - } - get pending() { - return this[kPool][kPending]; - } - get queued() { - return this[kPool][kQueued]; - } - get running() { - return this[kPool][kRunning]; - } - get size() { - return this[kPool][kSize]; - } - }; - module2.exports = PoolStats; - } -}); - // node_modules/undici/lib/dispatcher/pool-base.js var require_pool_base = __commonJS({ "node_modules/undici/lib/dispatcher/pool-base.js"(exports2, module2) { "use strict"; + var { PoolStats } = require_stats(); var DispatcherBase = require_dispatcher_base(); var FixedQueue = require_fixed_queue(); var { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = require_symbols(); - var PoolStats = require_pool_stats(); var kClients = /* @__PURE__ */ Symbol("clients"); var kNeedDrain = /* @__PURE__ */ Symbol("needDrain"); var kQueue = /* @__PURE__ */ Symbol("queue"); @@ -8411,53 +9797,63 @@ var require_pool_base = __commonJS({ var kGetDispatcher = /* @__PURE__ */ Symbol("get dispatcher"); var kAddClient = /* @__PURE__ */ Symbol("add client"); var kRemoveClient = /* @__PURE__ */ Symbol("remove client"); - var kStats = /* @__PURE__ */ Symbol("stats"); var PoolBase = class extends DispatcherBase { - constructor(opts) { - super(opts); - this[kQueue] = new FixedQueue(); - this[kClients] = []; - this[kQueued] = 0; - const pool = this; - this[kOnDrain] = function onDrain(origin, targets) { - const queue2 = pool[kQueue]; - let needDrain = false; - while (!needDrain) { - const item = queue2.shift(); - if (!item) { - break; - } - pool[kQueued]--; - needDrain = !this.dispatch(item.opts, item.handler); - } - this[kNeedDrain] = needDrain; - if (!this[kNeedDrain] && pool[kNeedDrain]) { - pool[kNeedDrain] = false; - pool.emit("drain", origin, [pool, ...targets]); + [kQueue] = new FixedQueue(); + [kQueued] = 0; + [kClients] = []; + [kNeedDrain] = false; + [kOnDrain](client, origin, targets) { + const queue2 = this[kQueue]; + let needDrain = false; + while (!needDrain) { + const item = queue2.shift(); + if (!item) { + break; } - if (pool[kClosedResolve] && queue2.isEmpty()) { - Promise.all(pool[kClients].map((c) => c.close())).then(pool[kClosedResolve]); + this[kQueued]--; + needDrain = !client.dispatch(item.opts, item.handler); + } + client[kNeedDrain] = needDrain; + if (!needDrain && this[kNeedDrain]) { + this[kNeedDrain] = false; + this.emit("drain", origin, [this, ...targets]); + } + if (this[kClosedResolve] && queue2.isEmpty()) { + const closeAll = []; + for (let i = 0; i < this[kClients].length; i++) { + const client2 = this[kClients][i]; + if (!client2.destroyed) { + closeAll.push(client2.close()); + } } - }; - this[kOnConnect] = (origin, targets) => { - pool.emit("connect", origin, [pool, ...targets]); - }; - this[kOnDisconnect] = (origin, targets, err) => { - pool.emit("disconnect", origin, [pool, ...targets], err); - }; - this[kOnConnectionError] = (origin, targets, err) => { - pool.emit("connectionError", origin, [pool, ...targets], err); - }; - this[kStats] = new PoolStats(this); + return Promise.all(closeAll).then(this[kClosedResolve]); + } } + [kOnConnect] = (origin, targets) => { + this.emit("connect", origin, [this, ...targets]); + }; + [kOnDisconnect] = (origin, targets, err) => { + this.emit("disconnect", origin, [this, ...targets], err); + }; + [kOnConnectionError] = (origin, targets, err) => { + this.emit("connectionError", origin, [this, ...targets], err); + }; get [kBusy]() { return this[kNeedDrain]; } get [kConnected]() { - return this[kClients].filter((client) => client[kConnected]).length; + let ret = 0; + for (const { [kConnected]: connected } of this[kClients]) { + ret += connected; + } + return ret; } get [kFree]() { - return this[kClients].filter((client) => client[kConnected] && !client[kNeedDrain]).length; + let ret = 0; + for (const { [kConnected]: connected, [kNeedDrain]: needDrain } of this[kClients]) { + ret += connected && !needDrain; + } + return ret; } get [kPending]() { let ret = this[kQueued]; @@ -8481,18 +9877,25 @@ var require_pool_base = __commonJS({ return ret; } get stats() { - return this[kStats]; + return new PoolStats(this); } - async [kClose]() { + [kClose]() { if (this[kQueue].isEmpty()) { - await Promise.all(this[kClients].map((c) => c.close())); + const closeAll = []; + for (let i = 0; i < this[kClients].length; i++) { + const client = this[kClients][i]; + if (!client.destroyed) { + closeAll.push(client.close()); + } + } + return Promise.all(closeAll); } else { - await new Promise((resolve15) => { + return new Promise((resolve15) => { this[kClosedResolve] = resolve15; }); } } - async [kDestroy](err) { + [kDestroy](err) { while (true) { const item = this[kQueue].shift(); if (!item) { @@ -8500,7 +9903,11 @@ var require_pool_base = __commonJS({ } item.handler.onError(err); } - await Promise.all(this[kClients].map((c) => c.destroy(err))); + const destroyAll = new Array(this[kClients].length); + for (let i = 0; i < this[kClients].length; i++) { + destroyAll[i] = this[kClients][i].destroy(err); + } + return Promise.all(destroyAll); } [kDispatch](opts, handler2) { const dispatcher = this[kGetDispatcher](); @@ -8515,12 +9922,12 @@ var require_pool_base = __commonJS({ return !this[kNeedDrain]; } [kAddClient](client) { - client.on("drain", this[kOnDrain]).on("connect", this[kOnConnect]).on("disconnect", this[kOnDisconnect]).on("connectionError", this[kOnConnectionError]); + client.on("drain", this[kOnDrain].bind(this, client)).on("connect", this[kOnConnect]).on("disconnect", this[kOnDisconnect]).on("connectionError", this[kOnConnectionError]); this[kClients].push(client); if (this[kNeedDrain]) { queueMicrotask(() => { if (this[kNeedDrain]) { - this[kOnDrain](client[kUrl], [this, client]); + this[kOnDrain](client, client[kUrl], [client, this]); } }); } @@ -8556,14 +9963,15 @@ var require_pool = __commonJS({ kClients, kNeedDrain, kAddClient, - kGetDispatcher + kGetDispatcher, + kRemoveClient } = require_pool_base(); var Client = require_client(); var { InvalidArgumentError } = require_errors(); var util4 = require_util(); - var { kUrl, kInterceptors } = require_symbols(); + var { kUrl } = require_symbols(); var buildConnector = require_connect(); var kOptions = /* @__PURE__ */ Symbol("options"); var kConnections = /* @__PURE__ */ Symbol("connections"); @@ -8583,6 +9991,7 @@ var require_pool = __commonJS({ autoSelectFamily, autoSelectFamilyAttemptTimeout, allowH2, + clientTtl, ...options } = {}) { if (connections != null && (!Number.isFinite(connections) || connections < 0)) { @@ -8601,17 +10010,23 @@ var require_pool = __commonJS({ allowH2, socketPath, timeout: connectTimeout, - ...autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0, + ...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0, ...connect }); } super(options); - this[kInterceptors] = options.interceptors?.Pool && Array.isArray(options.interceptors.Pool) ? options.interceptors.Pool : []; this[kConnections] = connections || null; this[kUrl] = util4.parseOrigin(origin); - this[kOptions] = { ...util4.deepClone(options), connect, allowH2 }; + this[kOptions] = { ...util4.deepClone(options), connect, allowH2, clientTtl, socketPath }; this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0; this[kFactory] = factory; + this.on("connect", (origin2, targets) => { + if (clientTtl != null && clientTtl > 0) { + for (const target of targets) { + Object.assign(target, { ttl: Date.now() }); + } + } + }); this.on("connectionError", (origin2, targets, error3) => { for (const target of targets) { const idx = this[kClients].indexOf(target); @@ -8622,8 +10037,11 @@ var require_pool = __commonJS({ }); } [kGetDispatcher]() { + const clientTtlOption = this[kOptions].clientTtl; for (const client of this[kClients]) { - if (!client[kNeedDrain]) { + if (clientTtlOption != null && clientTtlOption > 0 && client.ttl && Date.now() - client.ttl > clientTtlOption) { + this[kRemoveClient](client); + } else if (!client[kNeedDrain]) { return client; } } @@ -8655,8 +10073,8 @@ var require_balanced_pool = __commonJS({ kGetDispatcher } = require_pool_base(); var Pool = require_pool(); - var { kUrl, kInterceptors } = require_symbols(); - var { parseOrigin } = require_util(); + var { kUrl } = require_symbols(); + var util4 = require_util(); var kFactory = /* @__PURE__ */ Symbol("factory"); var kOptions = /* @__PURE__ */ Symbol("options"); var kGreatestCommonDivisor = /* @__PURE__ */ Symbol("kGreatestCommonDivisor"); @@ -8678,9 +10096,15 @@ var require_balanced_pool = __commonJS({ return new Pool(origin, opts); } var BalancedPool = class extends PoolBase { - constructor(upstreams = [], { factory = defaultFactory, ...opts } = {}) { - super(); - this[kOptions] = opts; + constructor(upstreams = [], { factory = defaultFactory, connect, tls, ...opts } = {}) { + if (typeof factory !== "function") { + throw new InvalidArgumentError("factory must be a function."); + } + super(opts); + if (connect && typeof connect !== "function") connect = { ...connect }; + if (tls && typeof tls !== "function") tls = { ...tls }; + this[kOptions] = { ...util4.deepClone(opts), connect, tls }; + this[kOptions].interceptors = opts.interceptors ? { ...opts.interceptors } : void 0; this[kIndex] = -1; this[kCurrentWeight] = 0; this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100; @@ -8688,10 +10112,6 @@ var require_balanced_pool = __commonJS({ if (!Array.isArray(upstreams)) { upstreams = [upstreams]; } - if (typeof factory !== "function") { - throw new InvalidArgumentError("factory must be a function."); - } - this[kInterceptors] = opts.interceptors?.BalancedPool && Array.isArray(opts.interceptors.BalancedPool) ? opts.interceptors.BalancedPool : []; this[kFactory] = factory; for (const upstream of upstreams) { this.addUpstream(upstream); @@ -8699,11 +10119,11 @@ var require_balanced_pool = __commonJS({ this._updateBalancedPoolStats(); } addUpstream(upstream) { - const upstreamOrigin = parseOrigin(upstream).origin; + const upstreamOrigin = util4.parseOrigin(upstream).origin; if (this[kClients].find((pool2) => pool2[kUrl].origin === upstreamOrigin && pool2.closed !== true && pool2.destroyed !== true)) { return this; } - const pool = this[kFactory](upstreamOrigin, Object.assign({}, this[kOptions])); + const pool = this[kFactory](upstreamOrigin, this[kOptions]); this[kAddClient](pool); pool.on("connect", () => { pool[kWeight] = Math.min(this[kMaxWeightPerServer], pool[kWeight] + this[kErrorPenalty]); @@ -8733,13 +10153,17 @@ var require_balanced_pool = __commonJS({ this[kGreatestCommonDivisor] = result; } removeUpstream(upstream) { - const upstreamOrigin = parseOrigin(upstream).origin; + const upstreamOrigin = util4.parseOrigin(upstream).origin; const pool = this[kClients].find((pool2) => pool2[kUrl].origin === upstreamOrigin && pool2.closed !== true && pool2.destroyed !== true); if (pool) { this[kRemoveClient](pool); } return this; } + getUpstream(upstream) { + const upstreamOrigin = util4.parseOrigin(upstream).origin; + return this[kClients].find((pool) => pool[kUrl].origin === upstreamOrigin && pool.closed !== true && pool.destroyed !== true); + } get upstreams() { return this[kClients].filter((dispatcher) => dispatcher.closed !== true && dispatcher.destroyed !== true).map((p) => p[kUrl].origin); } @@ -8782,48 +10206,165 @@ var require_balanced_pool = __commonJS({ } }); +// node_modules/undici/lib/dispatcher/round-robin-pool.js +var require_round_robin_pool = __commonJS({ + "node_modules/undici/lib/dispatcher/round-robin-pool.js"(exports2, module2) { + "use strict"; + var { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kGetDispatcher, + kRemoveClient + } = require_pool_base(); + var Client = require_client(); + var { + InvalidArgumentError + } = require_errors(); + var util4 = require_util(); + var { kUrl } = require_symbols(); + var buildConnector = require_connect(); + var kOptions = /* @__PURE__ */ Symbol("options"); + var kConnections = /* @__PURE__ */ Symbol("connections"); + var kFactory = /* @__PURE__ */ Symbol("factory"); + var kIndex = /* @__PURE__ */ Symbol("index"); + function defaultFactory(origin, opts) { + return new Client(origin, opts); + } + var RoundRobinPool = class extends PoolBase { + constructor(origin, { + connections, + factory = defaultFactory, + connect, + connectTimeout, + tls, + maxCachedSessions, + socketPath, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + allowH2, + clientTtl, + ...options + } = {}) { + if (connections != null && (!Number.isFinite(connections) || connections < 0)) { + throw new InvalidArgumentError("invalid connections"); + } + if (typeof factory !== "function") { + throw new InvalidArgumentError("factory must be a function."); + } + if (connect != null && typeof connect !== "function" && typeof connect !== "object") { + throw new InvalidArgumentError("connect must be a function or an object"); + } + if (typeof connect !== "function") { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0, + ...connect + }); + } + super(); + this[kConnections] = connections || null; + this[kUrl] = util4.parseOrigin(origin); + this[kOptions] = { ...util4.deepClone(options), connect, allowH2, clientTtl, socketPath }; + this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0; + this[kFactory] = factory; + this[kIndex] = -1; + this.on("connect", (origin2, targets) => { + if (clientTtl != null && clientTtl > 0) { + for (const target of targets) { + Object.assign(target, { ttl: Date.now() }); + } + } + }); + this.on("connectionError", (origin2, targets, error3) => { + for (const target of targets) { + const idx = this[kClients].indexOf(target); + if (idx !== -1) { + this[kClients].splice(idx, 1); + } + } + }); + } + [kGetDispatcher]() { + const clientTtlOption = this[kOptions].clientTtl; + const clientsLength = this[kClients].length; + if (clientsLength === 0) { + const dispatcher = this[kFactory](this[kUrl], this[kOptions]); + this[kAddClient](dispatcher); + return dispatcher; + } + let checked = 0; + while (checked < clientsLength) { + this[kIndex] = (this[kIndex] + 1) % clientsLength; + const client = this[kClients][this[kIndex]]; + if (clientTtlOption != null && clientTtlOption > 0 && client.ttl && Date.now() - client.ttl > clientTtlOption) { + this[kRemoveClient](client); + checked++; + continue; + } + if (!client[kNeedDrain]) { + return client; + } + checked++; + } + if (!this[kConnections] || clientsLength < this[kConnections]) { + const dispatcher = this[kFactory](this[kUrl], this[kOptions]); + this[kAddClient](dispatcher); + return dispatcher; + } + } + }; + module2.exports = RoundRobinPool; + } +}); + // node_modules/undici/lib/dispatcher/agent.js var require_agent = __commonJS({ "node_modules/undici/lib/dispatcher/agent.js"(exports2, module2) { "use strict"; - var { InvalidArgumentError } = require_errors(); - var { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = require_symbols(); + var { InvalidArgumentError, MaxOriginsReachedError } = require_errors(); + var { kClients, kRunning, kClose, kDestroy, kDispatch, kUrl } = require_symbols(); var DispatcherBase = require_dispatcher_base(); var Pool = require_pool(); var Client = require_client(); var util4 = require_util(); - var createRedirectInterceptor = require_redirect_interceptor(); var kOnConnect = /* @__PURE__ */ Symbol("onConnect"); var kOnDisconnect = /* @__PURE__ */ Symbol("onDisconnect"); var kOnConnectionError = /* @__PURE__ */ Symbol("onConnectionError"); - var kMaxRedirections = /* @__PURE__ */ Symbol("maxRedirections"); var kOnDrain = /* @__PURE__ */ Symbol("onDrain"); var kFactory = /* @__PURE__ */ Symbol("factory"); var kOptions = /* @__PURE__ */ Symbol("options"); + var kOrigins = /* @__PURE__ */ Symbol("origins"); function defaultFactory(origin, opts) { return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts); } var Agent = class extends DispatcherBase { - constructor({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { + constructor({ factory = defaultFactory, maxOrigins = Infinity, connect, tls, ...options } = {}) { if (typeof factory !== "function") { throw new InvalidArgumentError("factory must be a function."); } if (connect != null && typeof connect !== "function" && typeof connect !== "object") { throw new InvalidArgumentError("connect must be a function or an object"); } - if (!Number.isInteger(maxRedirections) || maxRedirections < 0) { - throw new InvalidArgumentError("maxRedirections must be a positive number"); + if (typeof maxOrigins !== "number" || Number.isNaN(maxOrigins) || maxOrigins <= 0) { + throw new InvalidArgumentError("maxOrigins must be a number greater than 0"); } super(options); if (connect && typeof connect !== "function") { connect = { ...connect }; } - this[kInterceptors] = options.interceptors?.Agent && Array.isArray(options.interceptors.Agent) ? options.interceptors.Agent : [createRedirectInterceptor({ maxRedirections })]; - this[kOptions] = { ...util4.deepClone(options), connect }; - this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0; - this[kMaxRedirections] = maxRedirections; + if (tls && typeof tls !== "function") { + tls = { ...tls }; + } + this[kOptions] = { ...util4.deepClone(options), maxOrigins, connect, tls }; this[kFactory] = factory; this[kClients] = /* @__PURE__ */ new Map(); + this[kOrigins] = /* @__PURE__ */ new Set(); this[kOnDrain] = (origin, targets) => { this.emit("drain", origin, [this, ...targets]); }; @@ -8839,8 +10380,8 @@ var require_agent = __commonJS({ } get [kRunning]() { let ret = 0; - for (const client of this[kClients].values()) { - ret += client[kRunning]; + for (const { dispatcher } of this[kClients].values()) { + ret += dispatcher[kRunning]; } return ret; } @@ -8851,31 +10392,767 @@ var require_agent = __commonJS({ } else { throw new InvalidArgumentError("opts.origin must be a non-empty string or URL."); } - let dispatcher = this[kClients].get(key); + if (this[kOrigins].size >= this[kOptions].maxOrigins && !this[kOrigins].has(key)) { + throw new MaxOriginsReachedError(); + } + const result = this[kClients].get(key); + let dispatcher = result && result.dispatcher; if (!dispatcher) { - dispatcher = this[kFactory](opts.origin, this[kOptions]).on("drain", this[kOnDrain]).on("connect", this[kOnConnect]).on("disconnect", this[kOnDisconnect]).on("connectionError", this[kOnConnectionError]); - this[kClients].set(key, dispatcher); + const closeClientIfUnused = (connected) => { + const result2 = this[kClients].get(key); + if (result2) { + if (connected) result2.count -= 1; + if (result2.count <= 0) { + this[kClients].delete(key); + if (!result2.dispatcher.destroyed) { + result2.dispatcher.close(); + } + } + this[kOrigins].delete(key); + } + }; + dispatcher = this[kFactory](opts.origin, this[kOptions]).on("drain", this[kOnDrain]).on("connect", (origin, targets) => { + const result2 = this[kClients].get(key); + if (result2) { + result2.count += 1; + } + this[kOnConnect](origin, targets); + }).on("disconnect", (origin, targets, err) => { + closeClientIfUnused(true); + this[kOnDisconnect](origin, targets, err); + }).on("connectionError", (origin, targets, err) => { + closeClientIfUnused(false); + this[kOnConnectionError](origin, targets, err); + }); + this[kClients].set(key, { count: 0, dispatcher }); + this[kOrigins].add(key); } return dispatcher.dispatch(opts, handler2); } - async [kClose]() { + [kClose]() { const closePromises = []; - for (const client of this[kClients].values()) { - closePromises.push(client.close()); + for (const { dispatcher } of this[kClients].values()) { + closePromises.push(dispatcher.close()); + } + this[kClients].clear(); + return Promise.all(closePromises); + } + [kDestroy](err) { + const destroyPromises = []; + for (const { dispatcher } of this[kClients].values()) { + destroyPromises.push(dispatcher.destroy(err)); } this[kClients].clear(); + return Promise.all(destroyPromises); + } + get stats() { + const allClientStats = {}; + for (const { dispatcher } of this[kClients].values()) { + if (dispatcher.stats) { + allClientStats[dispatcher[kUrl].origin] = dispatcher.stats; + } + } + return allClientStats; + } + }; + module2.exports = Agent; + } +}); + +// node_modules/undici/lib/core/socks5-utils.js +var require_socks5_utils = __commonJS({ + "node_modules/undici/lib/core/socks5-utils.js"(exports2, module2) { + "use strict"; + var { Buffer: Buffer3 } = require("node:buffer"); + var net = require("node:net"); + var { InvalidArgumentError } = require_errors(); + function parseAddress(address) { + if (net.isIPv4(address)) { + const parts = address.split(".").map(Number); + return { + type: 1, + // IPv4 + buffer: Buffer3.from(parts) + }; + } + if (net.isIPv6(address)) { + return { + type: 4, + // IPv6 + buffer: parseIPv6(address) + }; + } + const domainBuffer = Buffer3.from(address, "utf8"); + if (domainBuffer.length > 255) { + throw new InvalidArgumentError("Domain name too long (max 255 bytes)"); + } + return { + type: 3, + // Domain + buffer: Buffer3.concat([Buffer3.from([domainBuffer.length]), domainBuffer]) + }; + } + function parseIPv6(address) { + const buffer = Buffer3.alloc(16); + let normalizedAddress = address; + if (address.includes(".")) { + const lastColonIndex = address.lastIndexOf(":"); + const ipv4Part = address.slice(lastColonIndex + 1); + if (net.isIPv4(ipv4Part)) { + const octets = ipv4Part.split(".").map(Number); + const high = (octets[0] << 8 | octets[1]).toString(16); + const low = (octets[2] << 8 | octets[3]).toString(16); + normalizedAddress = `${address.slice(0, lastColonIndex)}:${high}:${low}`; + } + } + const doubleColonIndex = normalizedAddress.indexOf("::"); + if (doubleColonIndex !== -1) { + const before = normalizedAddress.slice(0, doubleColonIndex); + const after = normalizedAddress.slice(doubleColonIndex + 2); + const beforeParts = before === "" ? [] : before.split(":"); + const afterParts = after === "" ? [] : after.split(":"); + let bufferIndex = 0; + for (const part of beforeParts) { + buffer.writeUInt16BE(parseInt(part, 16), bufferIndex); + bufferIndex += 2; + } + bufferIndex = 16 - afterParts.length * 2; + for (const part of afterParts) { + buffer.writeUInt16BE(parseInt(part, 16), bufferIndex); + bufferIndex += 2; + } + } else { + const parts = normalizedAddress.split(":"); + for (let i = 0; i < parts.length; i++) { + buffer.writeUInt16BE(parseInt(parts[i], 16), i * 2); + } + } + return buffer; + } + function buildAddressBuffer(type, addressBuffer, port) { + const portBuffer = Buffer3.allocUnsafe(2); + portBuffer.writeUInt16BE(port, 0); + return Buffer3.concat([ + Buffer3.from([type]), + addressBuffer, + portBuffer + ]); + } + function parseResponseAddress(buffer, offset = 0) { + if (buffer.length < offset + 1) { + throw new InvalidArgumentError("Buffer too small to contain address type"); + } + const addressType = buffer[offset]; + let address; + let currentOffset = offset + 1; + switch (addressType) { + case 1: { + if (buffer.length < currentOffset + 6) { + throw new InvalidArgumentError("Buffer too small for IPv4 address"); + } + address = Array.from(buffer.subarray(currentOffset, currentOffset + 4)).join("."); + currentOffset += 4; + break; + } + case 3: { + if (buffer.length < currentOffset + 1) { + throw new InvalidArgumentError("Buffer too small for domain length"); + } + const domainLength = buffer[currentOffset]; + currentOffset += 1; + if (buffer.length < currentOffset + domainLength + 2) { + throw new InvalidArgumentError("Buffer too small for domain address"); + } + address = buffer.subarray(currentOffset, currentOffset + domainLength).toString("utf8"); + currentOffset += domainLength; + break; + } + case 4: { + if (buffer.length < currentOffset + 18) { + throw new InvalidArgumentError("Buffer too small for IPv6 address"); + } + const parts = []; + for (let i = 0; i < 8; i++) { + const value = buffer.readUInt16BE(currentOffset + i * 2); + parts.push(value.toString(16)); + } + address = parts.join(":"); + currentOffset += 16; + break; + } + default: + throw new InvalidArgumentError(`Invalid address type: ${addressType}`); + } + if (buffer.length < currentOffset + 2) { + throw new InvalidArgumentError("Buffer too small for port"); + } + const port = buffer.readUInt16BE(currentOffset); + currentOffset += 2; + return { + address, + port, + bytesRead: currentOffset - offset + }; + } + function createReplyError(replyCode) { + const messages = { + 1: "General SOCKS server failure", + 2: "Connection not allowed by ruleset", + 3: "Network unreachable", + 4: "Host unreachable", + 5: "Connection refused", + 6: "TTL expired", + 7: "Command not supported", + 8: "Address type not supported" + }; + const message = messages[replyCode] || `Unknown SOCKS5 error code: ${replyCode}`; + const error3 = new Error(message); + error3.code = `SOCKS5_${replyCode}`; + return error3; + } + module2.exports = { + parseAddress, + parseIPv6, + buildAddressBuffer, + parseResponseAddress, + createReplyError + }; + } +}); + +// node_modules/undici/lib/core/socks5-client.js +var require_socks5_client = __commonJS({ + "node_modules/undici/lib/core/socks5-client.js"(exports2, module2) { + "use strict"; + var { EventEmitter: EventEmitter2 } = require("node:events"); + var { Buffer: Buffer3 } = require("node:buffer"); + var { InvalidArgumentError, Socks5ProxyError } = require_errors(); + var { debuglog } = require("node:util"); + var { parseAddress } = require_socks5_utils(); + var debug6 = debuglog("undici:socks5"); + var EMPTY_BUFFER = Buffer3.alloc(0); + var SOCKS_VERSION = 5; + var AUTH_METHODS = { + NO_AUTH: 0, + GSSAPI: 1, + USERNAME_PASSWORD: 2, + NO_ACCEPTABLE: 255 + }; + var COMMANDS = { + CONNECT: 1, + BIND: 2, + UDP_ASSOCIATE: 3 + }; + var ADDRESS_TYPES = { + IPV4: 1, + DOMAIN: 3, + IPV6: 4 + }; + var REPLY_CODES = { + SUCCEEDED: 0, + GENERAL_FAILURE: 1, + CONNECTION_NOT_ALLOWED: 2, + NETWORK_UNREACHABLE: 3, + HOST_UNREACHABLE: 4, + CONNECTION_REFUSED: 5, + TTL_EXPIRED: 6, + COMMAND_NOT_SUPPORTED: 7, + ADDRESS_TYPE_NOT_SUPPORTED: 8 + }; + var STATES = { + INITIAL: "initial", + HANDSHAKING: "handshaking", + AUTHENTICATING: "authenticating", + AUTHENTICATED: "authenticated", + CONNECTING: "connecting", + CONNECTED: "connected", + ERROR: "error", + CLOSED: "closed" + }; + var Socks5Client = class extends EventEmitter2 { + constructor(socket, options = {}) { + super(); + if (!socket) { + throw new InvalidArgumentError("socket is required"); + } + this.socket = socket; + this.options = options; + this.state = STATES.INITIAL; + this.buffer = EMPTY_BUFFER; + this.onSocketData = this.onData.bind(this); + this.onSocketError = this.onError.bind(this); + this.onSocketClose = this.onClose.bind(this); + this.authMethods = []; + if (options.username && options.password) { + this.authMethods.push(AUTH_METHODS.USERNAME_PASSWORD); + } + this.authMethods.push(AUTH_METHODS.NO_AUTH); + this.socket.on("data", this.onSocketData); + this.socket.on("error", this.onSocketError); + this.socket.on("close", this.onSocketClose); + } + /** + * Handle incoming data from the socket + */ + onData(data) { + debug6("received data", data.length, "bytes in state", this.state); + this.buffer = Buffer3.concat([this.buffer, data]); + try { + switch (this.state) { + case STATES.HANDSHAKING: + this.handleHandshakeResponse(); + break; + case STATES.AUTHENTICATING: + this.handleAuthResponse(); + break; + case STATES.CONNECTING: + this.handleConnectResponse(); + break; + } + } catch (err) { + this.onError(err); + } + } + /** + * Handle socket errors + */ + onError(err) { + debug6("socket error", err); + this.state = STATES.ERROR; + this.emit("error", err); + this.destroy(); + } + /** + * Handle socket close + */ + onClose() { + debug6("socket closed"); + this.state = STATES.CLOSED; + this.emit("close"); + } + /** + * Destroy the client and underlying socket + */ + destroy() { + if (this.socket && !this.socket.destroyed) { + this.socket.destroy(); + } + } + markAuthenticated() { + this.state = STATES.AUTHENTICATED; + this.emit("authenticated"); + } + /** + * Start the SOCKS5 handshake + */ + handshake() { + if (this.state !== STATES.INITIAL) { + throw new InvalidArgumentError("Handshake already started"); + } + debug6("starting handshake with", this.authMethods.length, "auth methods"); + this.state = STATES.HANDSHAKING; + const request3 = Buffer3.alloc(2 + this.authMethods.length); + request3[0] = SOCKS_VERSION; + request3[1] = this.authMethods.length; + this.authMethods.forEach((method, i) => { + request3[2 + i] = method; + }); + this.socket.write(request3); + } + /** + * Handle handshake response from server + */ + handleHandshakeResponse() { + if (this.buffer.length < 2) { + return; + } + const version = this.buffer[0]; + const method = this.buffer[1]; + if (version !== SOCKS_VERSION) { + throw new Socks5ProxyError(`Invalid SOCKS version: ${version}`, "UND_ERR_SOCKS5_VERSION"); + } + if (method === AUTH_METHODS.NO_ACCEPTABLE) { + throw new Socks5ProxyError("No acceptable authentication method", "UND_ERR_SOCKS5_AUTH_REJECTED"); + } + this.buffer = this.buffer.subarray(2); + debug6("server selected auth method", method); + if (method === AUTH_METHODS.NO_AUTH) { + this.markAuthenticated(); + } else if (method === AUTH_METHODS.USERNAME_PASSWORD) { + this.state = STATES.AUTHENTICATING; + this.sendAuthRequest(); + } else { + throw new Socks5ProxyError(`Unsupported authentication method: ${method}`, "UND_ERR_SOCKS5_AUTH_METHOD"); + } + } + /** + * Send username/password authentication request + */ + sendAuthRequest() { + const { username, password } = this.options; + if (!username || !password) { + throw new InvalidArgumentError("Username and password required for authentication"); + } + debug6("sending username/password auth"); + const usernameBuffer = Buffer3.from(username); + const passwordBuffer = Buffer3.from(password); + if (usernameBuffer.length > 255 || passwordBuffer.length > 255) { + throw new InvalidArgumentError("Username or password too long"); + } + const request3 = Buffer3.alloc(3 + usernameBuffer.length + passwordBuffer.length); + request3[0] = 1; + request3[1] = usernameBuffer.length; + usernameBuffer.copy(request3, 2); + request3[2 + usernameBuffer.length] = passwordBuffer.length; + passwordBuffer.copy(request3, 3 + usernameBuffer.length); + this.socket.write(request3); + } + /** + * Handle authentication response + */ + handleAuthResponse() { + if (this.buffer.length < 2) { + return; + } + const version = this.buffer[0]; + const status = this.buffer[1]; + if (version !== 1) { + throw new Socks5ProxyError(`Invalid auth sub-negotiation version: ${version}`, "UND_ERR_SOCKS5_AUTH_VERSION"); + } + if (status !== 0) { + throw new Socks5ProxyError("Authentication failed", "UND_ERR_SOCKS5_AUTH_FAILED"); + } + this.buffer = this.buffer.subarray(2); + debug6("authentication successful"); + this.markAuthenticated(); + } + /** + * Send CONNECT command + * @param {string} address - Target address (IP or domain) + * @param {number} port - Target port + */ + connect(address, port) { + if (this.state === STATES.CONNECTING || this.state === STATES.CONNECTED) { + throw new InvalidArgumentError("Connection already in progress"); + } + if (this.state !== STATES.AUTHENTICATED) { + throw new InvalidArgumentError("Client must be authenticated before CONNECT"); + } + debug6("connecting to", address, port); + this.state = STATES.CONNECTING; + const request3 = this.buildConnectRequest(COMMANDS.CONNECT, address, port); + this.socket.write(request3); + } + /** + * Build a SOCKS5 request + */ + buildConnectRequest(command, address, port) { + const { type: addressType, buffer: addressBuffer } = parseAddress(address); + const request3 = Buffer3.alloc(4 + addressBuffer.length + 2); + request3[0] = SOCKS_VERSION; + request3[1] = command; + request3[2] = 0; + request3[3] = addressType; + addressBuffer.copy(request3, 4); + request3.writeUInt16BE(port, 4 + addressBuffer.length); + return request3; + } + /** + * Handle CONNECT response + */ + handleConnectResponse() { + if (this.buffer.length < 4) { + return; + } + const version = this.buffer[0]; + const reply = this.buffer[1]; + const addressType = this.buffer[3]; + if (version !== SOCKS_VERSION) { + throw new Socks5ProxyError(`Invalid SOCKS version in reply: ${version}`, "UND_ERR_SOCKS5_REPLY_VERSION"); + } + let responseLength = 4; + if (addressType === ADDRESS_TYPES.IPV4) { + responseLength += 4 + 2; + } else if (addressType === ADDRESS_TYPES.DOMAIN) { + if (this.buffer.length < 5) { + return; + } + responseLength += 1 + this.buffer[4] + 2; + } else if (addressType === ADDRESS_TYPES.IPV6) { + responseLength += 16 + 2; + } else { + throw new Socks5ProxyError(`Invalid address type in reply: ${addressType}`, "UND_ERR_SOCKS5_ADDR_TYPE"); + } + if (this.buffer.length < responseLength) { + return; + } + if (reply !== REPLY_CODES.SUCCEEDED) { + const errorMessage = this.getReplyErrorMessage(reply); + throw new Socks5ProxyError(`SOCKS5 connection failed: ${errorMessage}`, `UND_ERR_SOCKS5_REPLY_${reply}`); + } + let boundAddress; + let offset = 4; + if (addressType === ADDRESS_TYPES.IPV4) { + boundAddress = Array.from(this.buffer.subarray(offset, offset + 4)).join("."); + offset += 4; + } else if (addressType === ADDRESS_TYPES.DOMAIN) { + const domainLength = this.buffer[offset]; + offset += 1; + boundAddress = this.buffer.subarray(offset, offset + domainLength).toString(); + offset += domainLength; + } else if (addressType === ADDRESS_TYPES.IPV6) { + const parts = []; + for (let i = 0; i < 8; i++) { + const value = this.buffer.readUInt16BE(offset + i * 2); + parts.push(value.toString(16)); + } + boundAddress = parts.join(":"); + offset += 16; + } + const boundPort = this.buffer.readUInt16BE(offset); + this.buffer = EMPTY_BUFFER; + this.state = STATES.CONNECTED; + this.socket.removeListener("data", this.onSocketData); + debug6("connected, bound address:", boundAddress, "port:", boundPort); + this.emit("connected", { address: boundAddress, port: boundPort }); + } + /** + * Get human-readable error message for reply code + */ + getReplyErrorMessage(reply) { + switch (reply) { + case REPLY_CODES.GENERAL_FAILURE: + return "General SOCKS server failure"; + case REPLY_CODES.CONNECTION_NOT_ALLOWED: + return "Connection not allowed by ruleset"; + case REPLY_CODES.NETWORK_UNREACHABLE: + return "Network unreachable"; + case REPLY_CODES.HOST_UNREACHABLE: + return "Host unreachable"; + case REPLY_CODES.CONNECTION_REFUSED: + return "Connection refused"; + case REPLY_CODES.TTL_EXPIRED: + return "TTL expired"; + case REPLY_CODES.COMMAND_NOT_SUPPORTED: + return "Command not supported"; + case REPLY_CODES.ADDRESS_TYPE_NOT_SUPPORTED: + return "Address type not supported"; + default: + return `Unknown error code: ${reply}`; + } + } + }; + module2.exports = { + Socks5Client, + AUTH_METHODS, + COMMANDS, + ADDRESS_TYPES, + REPLY_CODES, + STATES + }; + } +}); + +// node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +var require_socks5_proxy_agent = __commonJS({ + "node_modules/undici/lib/dispatcher/socks5-proxy-agent.js"(exports2, module2) { + "use strict"; + var { URL: URL2 } = require("node:url"); + var tls; + var DispatcherBase = require_dispatcher_base(); + var { InvalidArgumentError } = require_errors(); + var { Socks5Client, STATES } = require_socks5_client(); + var { kDispatch, kClose, kDestroy } = require_symbols(); + var Pool = require_pool(); + var buildConnector = require_connect(); + var { debuglog } = require("node:util"); + var debug6 = debuglog("undici:socks5-proxy"); + var kProxyUrl = /* @__PURE__ */ Symbol("proxy url"); + var kProxyHeaders = /* @__PURE__ */ Symbol("proxy headers"); + var kProxyAuth = /* @__PURE__ */ Symbol("proxy auth"); + var kProxyProtocol = /* @__PURE__ */ Symbol("proxy protocol"); + var kPools = /* @__PURE__ */ Symbol("pools"); + var kConnector = /* @__PURE__ */ Symbol("connector"); + var kRequestTls = /* @__PURE__ */ Symbol("request tls settings"); + var experimentalWarningEmitted = false; + var Socks5ProxyAgent = class extends DispatcherBase { + constructor(proxyUrl, options = {}) { + super(); + if (!experimentalWarningEmitted) { + process.emitWarning( + "SOCKS5 proxy support is experimental and subject to change", + "ExperimentalWarning" + ); + experimentalWarningEmitted = true; + } + if (!proxyUrl) { + throw new InvalidArgumentError("Proxy URL is mandatory"); + } + const url2 = typeof proxyUrl === "string" ? new URL2(proxyUrl) : proxyUrl; + if (url2.protocol !== "socks5:" && url2.protocol !== "socks:") { + throw new InvalidArgumentError("Proxy URL must use socks5:// or socks:// protocol"); + } + this[kProxyUrl] = url2; + this[kProxyHeaders] = options.headers || {}; + this[kProxyProtocol] = options.proxyTls ? "https:" : "http:"; + this[kRequestTls] = options.requestTls; + this[kProxyAuth] = { + username: options.username || (url2.username ? decodeURIComponent(url2.username) : null), + password: options.password || (url2.password ? decodeURIComponent(url2.password) : null) + }; + this[kConnector] = options.connect || buildConnector({ + ...options.proxyTls, + servername: options.proxyTls?.servername || url2.hostname + }); + this[kPools] = /* @__PURE__ */ new Map(); + } + /** + * Create a SOCKS5 connection to the proxy + */ + async createSocks5Connection(targetHost, targetPort) { + const proxyHost = this[kProxyUrl].hostname; + const proxyPort = parseInt(this[kProxyUrl].port) || 1080; + debug6("creating SOCKS5 connection to", proxyHost, proxyPort); + const socket = await new Promise((resolve15, reject) => { + this[kConnector]({ + hostname: proxyHost, + host: proxyHost, + port: proxyPort, + protocol: this[kProxyProtocol] + }, (err, socket2) => { + if (err) { + reject(err); + } else { + resolve15(socket2); + } + }); + }); + const socks5Client = new Socks5Client(socket, this[kProxyAuth]); + socks5Client.on("error", (err) => { + debug6("SOCKS5 error:", err); + socket.destroy(); + }); + await socks5Client.handshake(); + await new Promise((resolve15, reject) => { + const timeout = setTimeout(() => { + reject(new Error("SOCKS5 authentication timeout")); + }, 5e3); + const onAuthenticated = () => { + clearTimeout(timeout); + socks5Client.removeListener("error", onError); + resolve15(); + }; + const onError = (err) => { + clearTimeout(timeout); + socks5Client.removeListener("authenticated", onAuthenticated); + reject(err); + }; + if (socks5Client.state === STATES.AUTHENTICATED) { + clearTimeout(timeout); + resolve15(); + } else { + socks5Client.once("authenticated", onAuthenticated); + socks5Client.once("error", onError); + } + }); + await socks5Client.connect(targetHost, targetPort); + await new Promise((resolve15, reject) => { + const timeout = setTimeout(() => { + reject(new Error("SOCKS5 connection timeout")); + }, 5e3); + const onConnected = (info8) => { + debug6("SOCKS5 tunnel established to", targetHost, targetPort, "via", info8); + clearTimeout(timeout); + socks5Client.removeListener("error", onError); + resolve15(); + }; + const onError = (err) => { + clearTimeout(timeout); + socks5Client.removeListener("connected", onConnected); + reject(err); + }; + socks5Client.once("connected", onConnected); + socks5Client.once("error", onError); + }); + return socket; + } + /** + * Dispatch a request through the SOCKS5 proxy + */ + [kDispatch](opts, handler2) { + const { origin } = opts; + debug6("dispatching request to", origin, "via SOCKS5"); + try { + const originKey = String(origin); + let pool = this[kPools].get(originKey); + if (!pool || pool.destroyed || pool.closed) { + pool = new Pool(origin, { + pipelining: opts.pipelining, + connections: opts.connections, + connect: async (connectOpts, callback) => { + try { + const url2 = new URL2(origin); + const targetHost = url2.hostname; + const targetPort = parseInt(url2.port) || (url2.protocol === "https:" ? 443 : 80); + debug6("establishing SOCKS5 connection to", targetHost, targetPort); + const socket = await this.createSocks5Connection(targetHost, targetPort); + let finalSocket = socket; + if (url2.protocol === "https:") { + if (!tls) { + tls = require("node:tls"); + } + debug6("upgrading to TLS"); + finalSocket = tls.connect({ + ...this[kRequestTls], + socket, + servername: this[kRequestTls]?.servername || targetHost + }); + await new Promise((resolve15, reject) => { + finalSocket.once("secureConnect", resolve15); + finalSocket.once("error", reject); + }); + } + callback(null, finalSocket); + } catch (err) { + debug6("SOCKS5 connection error:", err); + callback(err); + } + } + }); + this[kPools].set(originKey, pool); + } + return pool[kDispatch](opts, handler2); + } catch (err) { + debug6("dispatch error:", err); + if (typeof handler2.onResponseError === "function") { + handler2.onResponseError(null, err); + return false; + } else if (typeof handler2.onError === "function") { + handler2.onError(err); + return false; + } else { + throw err; + } + } + } + async [kClose]() { + const closePromises = []; + for (const pool of this[kPools].values()) { + closePromises.push(pool.close()); + } + this[kPools].clear(); await Promise.all(closePromises); } async [kDestroy](err) { const destroyPromises = []; - for (const client of this[kClients].values()) { - destroyPromises.push(client.destroy(err)); + for (const pool of this[kPools].values()) { + destroyPromises.push(pool.destroy(err)); } - this[kClients].clear(); + this[kPools].clear(); await Promise.all(destroyPromises); } }; - module2.exports = Agent; + module2.exports = Socks5ProxyAgent; } }); @@ -8883,14 +11160,15 @@ var require_agent = __commonJS({ var require_proxy_agent = __commonJS({ "node_modules/undici/lib/dispatcher/proxy-agent.js"(exports2, module2) { "use strict"; - var { kProxy, kClose, kDestroy, kDispatch, kInterceptors } = require_symbols(); - var { URL: URL2 } = require("node:url"); + var { kProxy, kClose, kDestroy, kDispatch } = require_symbols(); var Agent = require_agent(); var Pool = require_pool(); var DispatcherBase = require_dispatcher_base(); var { InvalidArgumentError, RequestAbortedError, SecureProxyConnectionError } = require_errors(); var buildConnector = require_connect(); var Client = require_client(); + var { channels } = require_diagnostics(); + var Socks5ProxyAgent = require_socks5_proxy_agent(); var kAgent = /* @__PURE__ */ Symbol("proxy agent"); var kClient = /* @__PURE__ */ Symbol("proxy client"); var kProxyHeaders = /* @__PURE__ */ Symbol("proxy headers"); @@ -8915,10 +11193,10 @@ var require_proxy_agent = __commonJS({ var Http1ProxyWrapper = class extends DispatcherBase { #client; constructor(proxyUrl, { headers = {}, connect, factory }) { - super(); if (!proxyUrl) { throw new InvalidArgumentError("Proxy URL is mandatory"); } + super(); this[kProxyHeaders] = headers; if (factory) { this.#client = factory(proxyUrl, { connect }); @@ -8944,23 +11222,22 @@ var require_proxy_agent = __commonJS({ } = opts; opts.path = origin + path30; if (!("host" in headers) && !("Host" in headers)) { - const { host } = new URL2(origin); + const { host } = new URL(origin); headers.host = host; } opts.headers = { ...this[kProxyHeaders], ...headers }; return this.#client[kDispatch](opts, handler2); } - async [kClose]() { + [kClose]() { return this.#client.close(); } - async [kDestroy](err) { + [kDestroy](err) { return this.#client.destroy(err); } }; var ProxyAgent2 = class extends DispatcherBase { constructor(opts) { - super(); - if (!opts || typeof opts === "object" && !(opts instanceof URL2) && !opts.uri) { + if (!opts || typeof opts === "object" && !(opts instanceof URL) && !opts.uri) { throw new InvalidArgumentError("Proxy uri is mandatory"); } const { clientFactory = defaultFactory } = opts; @@ -8968,10 +11245,10 @@ var require_proxy_agent = __commonJS({ throw new InvalidArgumentError("Proxy opts.clientFactory must be a function."); } const { proxyTunnel = true } = opts; + super(); const url2 = this.#getUrl(opts); const { href, origin, port, protocol, username, password, hostname: proxyHostname } = url2; this[kProxy] = { uri: href, protocol }; - this[kInterceptors] = opts.interceptors?.ProxyAgent && Array.isArray(opts.interceptors.ProxyAgent) ? opts.interceptors.ProxyAgent : []; this[kRequestTls] = opts.requestTls; this[kProxyTls] = opts.proxyTls; this[kProxyHeaders] = opts.headers || {}; @@ -8989,7 +11266,18 @@ var require_proxy_agent = __commonJS({ this[kConnectEndpoint] = buildConnector({ ...opts.requestTls }); const agentFactory = opts.factory || defaultAgentFactory; const factory = (origin2, options) => { - const { protocol: protocol2 } = new URL2(origin2); + const { protocol: protocol2 } = new URL(origin2); + if (this[kProxy].protocol === "socks5:" || this[kProxy].protocol === "socks:") { + return new Socks5ProxyAgent(this[kProxy].uri, { + headers: this[kProxyHeaders], + connect, + factory: agentFactory, + username: opts.username || username, + password: opts.password || password, + proxyTls: opts.proxyTls, + requestTls: opts.requestTls + }); + } if (!this[kTunnelProxy] && protocol2 === "http:" && this[kProxy].protocol === "http:") { return new Http1ProxyWrapper(this[kProxy].uri, { headers: this[kProxyHeaders], @@ -8999,30 +11287,47 @@ var require_proxy_agent = __commonJS({ } return agentFactory(origin2, options); }; - this[kClient] = clientFactory(url2, { connect }); + if (protocol === "socks5:" || protocol === "socks:") { + this[kClient] = null; + } else { + this[kClient] = clientFactory(url2, { connect }); + } this[kAgent] = new Agent({ ...opts, factory, connect: async (opts2, callback) => { + if (!this[kClient]) { + callback(new InvalidArgumentError("Cannot establish tunnel connection without a proxy client")); + return; + } let requestedPath = opts2.host; if (!opts2.port) { requestedPath += `:${defaultProtocolPort(opts2.protocol)}`; } try { - const { socket, statusCode } = await this[kClient].connect({ + const connectParams = { origin, port, path: requestedPath, signal: opts2.signal, headers: { ...this[kProxyHeaders], - host: opts2.host + host: opts2.host, + ...opts2.connections == null || opts2.connections > 0 ? { "proxy-connection": "keep-alive" } : {} }, servername: this[kProxyTls]?.servername || proxyHostname - }); + }; + const { socket, statusCode } = await this[kClient].connect(connectParams); if (statusCode !== 200) { socket.on("error", noop3).destroy(); callback(new RequestAbortedError(`Proxy response (${statusCode}) !== 200 when HTTP Tunneling`)); + return; + } + if (channels.proxyConnected.hasSubscribers) { + channels.proxyConnected.publish({ + socket, + connectParams + }); } if (opts2.protocol !== "https:") { callback(null, socket); @@ -9049,7 +11354,7 @@ var require_proxy_agent = __commonJS({ const headers = buildHeaders(opts.headers); throwIfProxyAuthIsSent(headers); if (headers && !("host" in headers) && !("Host" in headers)) { - const { host } = new URL2(opts.origin); + const { host } = new URL(opts.origin); headers.host = host; } return this[kAgent].dispatch( @@ -9061,25 +11366,31 @@ var require_proxy_agent = __commonJS({ ); } /** - * @param {import('../types/proxy-agent').ProxyAgent.Options | string | URL} opts + * @param {import('../../types/proxy-agent').ProxyAgent.Options | string | URL} opts * @returns {URL} */ #getUrl(opts) { if (typeof opts === "string") { - return new URL2(opts); - } else if (opts instanceof URL2) { + return new URL(opts); + } else if (opts instanceof URL) { return opts; } else { - return new URL2(opts.uri); + return new URL(opts.uri); } } - async [kClose]() { - await this[kAgent].close(); - await this[kClient].close(); + [kClose]() { + const promises7 = [this[kAgent].close()]; + if (this[kClient]) { + promises7.push(this[kClient].close()); + } + return Promise.all(promises7); } - async [kDestroy]() { - await this[kAgent].destroy(); - await this[kClient].destroy(); + [kDestroy]() { + const promises7 = [this[kAgent].destroy()]; + if (this[kClient]) { + promises7.push(this[kClient].destroy()); + } + return Promise.all(promises7); } }; function buildHeaders(headers) { @@ -9114,7 +11425,6 @@ var require_env_http_proxy_agent = __commonJS({ "http:": 80, "https:": 443 }; - var experimentalWarned = false; var EnvHttpProxyAgent = class extends DispatcherBase { #noProxyValue = null; #noProxyEntries = null; @@ -9122,12 +11432,6 @@ var require_env_http_proxy_agent = __commonJS({ constructor(opts = {}) { super(); this.#opts = opts; - if (!experimentalWarned) { - experimentalWarned = true; - process.emitWarning("EnvHttpProxyAgent is experimental, expect them to change at any time.", { - code: "UNDICI-EHPA" - }); - } const { httpProxy, httpsProxy, noProxy, ...agentOpts } = opts; this[kNoProxyAgent] = new Agent(agentOpts); const HTTP_PROXY = httpProxy ?? process.env.http_proxy ?? process.env.HTTP_PROXY; @@ -9149,23 +11453,19 @@ var require_env_http_proxy_agent = __commonJS({ const agent = this.#getProxyAgentForUrl(url2); return agent.dispatch(opts, handler2); } - async [kClose]() { - await this[kNoProxyAgent].close(); - if (!this[kHttpProxyAgent][kClosed]) { - await this[kHttpProxyAgent].close(); - } - if (!this[kHttpsProxyAgent][kClosed]) { - await this[kHttpsProxyAgent].close(); - } + [kClose]() { + return Promise.all([ + this[kNoProxyAgent].close(), + !this[kHttpProxyAgent][kClosed] && this[kHttpProxyAgent].close(), + !this[kHttpsProxyAgent][kClosed] && this[kHttpsProxyAgent].close() + ]); } - async [kDestroy](err) { - await this[kNoProxyAgent].destroy(err); - if (!this[kHttpProxyAgent][kDestroyed]) { - await this[kHttpProxyAgent].destroy(err); - } - if (!this[kHttpsProxyAgent][kDestroyed]) { - await this[kHttpsProxyAgent].destroy(err); - } + [kDestroy](err) { + return Promise.all([ + this[kNoProxyAgent].destroy(err), + !this[kHttpProxyAgent][kDestroyed] && this[kHttpProxyAgent].destroy(err), + !this[kHttpsProxyAgent][kDestroyed] && this[kHttpsProxyAgent].destroy(err) + ]); } #getProxyAgentForUrl(url2) { let { protocol, host: hostname, port } = url2; @@ -9194,14 +11494,11 @@ var require_env_http_proxy_agent = __commonJS({ if (entry.port && entry.port !== port) { continue; } - if (!/^[.*]/.test(entry.hostname)) { - if (hostname === entry.hostname) { - return false; - } - } else { - if (hostname.endsWith(entry.hostname.replace(/^\*/, ""))) { - return false; - } + if (hostname === entry.hostname) { + return false; + } + if (hostname.slice(-(entry.hostname.length + 1)) === `.${entry.hostname}`) { + return false; } } return true; @@ -9217,7 +11514,8 @@ var require_env_http_proxy_agent = __commonJS({ } const parsed = entry.match(/^(.+):(\d+)$/); noProxyEntries.push({ - hostname: (parsed ? parsed[1] : entry).toLowerCase(), + // strip leading dot or asterisk with dot + hostname: (parsed ? parsed[1] : entry).replace(/^\*?\./, "").toLowerCase(), port: parsed ? Number.parseInt(parsed[2], 10) : 0 }); } @@ -9245,36 +11543,84 @@ var require_retry_handler = __commonJS({ var assert = require("node:assert"); var { kRetryHandlerDefaultRetry } = require_symbols(); var { RequestRetryError } = require_errors(); + var WrapHandler = require_wrap_handler(); var { isDisturbed, - parseHeaders, parseRangeHeader, wrapRequestBody } = require_util(); function calculateRetryAfterHeader(retryAfter) { - const current = Date.now(); - return new Date(retryAfter).getTime() - current; + const retryTime = new Date(retryAfter).getTime(); + return isNaN(retryTime) ? 0 : retryTime - Date.now(); } function validatePartialResponseContentLength(headers, range2, statusCode, retryCount) { const contentLength = headers["content-length"]; if (contentLength == null) { - return null; + return; } if (!Number.isFinite(range2.start) || !Number.isFinite(range2.end)) { - return null; + return; } const length = Number(contentLength); const expectedLength = range2.end - range2.start + 1; if (!Number.isFinite(length) || length !== expectedLength) { - return new RequestRetryError("Content-Length mismatch", statusCode, { + throw new RequestRetryError("Content-Length mismatch", statusCode, { headers, data: { count: retryCount } }); } - return null; } + var RetryController = class { + #paused = false; + #target = null; + set target(target) { + this.#target = target; + if (this.#paused) { + target?.pause(); + } + } + get target() { + return this.#target; + } + pause() { + this.#paused = true; + this.#target?.pause(); + } + resume() { + this.#paused = false; + this.#target?.resume(); + } + abort(reason) { + this.#target?.abort(reason); + } + get paused() { + return this.#paused || (this.#target?.paused ?? false); + } + get aborted() { + return this.#target?.aborted ?? false; + } + get reason() { + return this.#target?.reason ?? null; + } + get rawHeaders() { + return this.#target?.rawHeaders ?? null; + } + set rawHeaders(value) { + if (this.#target) { + this.#target.rawHeaders = value; + } + } + get rawTrailers() { + return this.#target?.rawTrailers ?? null; + } + set rawTrailers(value) { + if (this.#target) { + this.#target.rawTrailers = value; + } + } + }; var RetryHandler = class _RetryHandler { - constructor(opts, handlers) { + constructor(opts, { dispatch, handler: handler2 }) { const { retryOptions, ...dispatchOpts } = opts; const { // Retry scoped @@ -9287,14 +11633,15 @@ var require_retry_handler = __commonJS({ methods, errorCodes, retryAfter, - statusCodes + statusCodes, + throwOnError } = retryOptions ?? {}; - this.dispatch = handlers.dispatch; - this.handler = handlers.handler; + this.error = null; + this.dispatch = dispatch; + this.handler = WrapHandler.wrap(handler2); this.opts = { ...dispatchOpts, body: wrapRequestBody(opts.body) }; - this.abort = null; - this.aborted = false; this.retryOpts = { + throwOnError: throwOnError ?? true, retry: retryFn ?? _RetryHandler[kRetryHandlerDefaultRetry], retryAfter: retryAfter ?? true, maxTimeout: maxTimeout ?? 30 * 1e3, @@ -9322,38 +11669,77 @@ var require_retry_handler = __commonJS({ }; this.retryCount = 0; this.retryCountCheckpoint = 0; + this.headersSent = false; this.start = 0; this.end = null; this.etag = null; - this.resume = null; - this.handler.onConnect((reason) => { - this.aborted = true; - if (this.abort) { - this.abort(reason); + this.controllerProxy = new RetryController(); + } + onResponseStartWithRetry(controller, statusCode, headers, statusMessage, err) { + if (this.retryOpts.throwOnError) { + if (this.retryOpts.statusCodes.includes(statusCode) === false) { + if (this.headersSent) { + this.handler.onResponseError?.(this.controllerProxy, err); + } else { + this.headersSent = true; + this.checkpointResponseEnd(headers); + this.handler.onResponseStart?.(this.controllerProxy, statusCode, headers, statusMessage); + } } else { - this.reason = reason; + this.error = err; } - }); - } - onRequestSent() { - if (this.handler.onRequestSent) { - this.handler.onRequestSent(); + return; + } + if (isDisturbed(this.opts.body)) { + this.headersSent = true; + this.checkpointResponseEnd(headers); + this.handler.onResponseStart?.(this.controllerProxy, statusCode, headers, statusMessage); + return; } + function shouldRetry(passedErr) { + if (passedErr) { + if (this.headersSent) { + this.handler.onResponseError?.(this.controllerProxy, passedErr); + } else { + this.headersSent = true; + this.checkpointResponseEnd(headers); + this.handler.onResponseStart?.(this.controllerProxy, statusCode, headers, statusMessage); + } + controller.resume(); + return; + } + this.error = err; + controller.resume(); + } + controller.pause(); + this.retryOpts.retry( + err, + { + state: { counter: this.retryCount }, + opts: { retryOptions: this.retryOpts, ...this.opts } + }, + shouldRetry.bind(this) + ); } - onUpgrade(statusCode, headers, socket) { - if (this.handler.onUpgrade) { - this.handler.onUpgrade(statusCode, headers, socket); + checkpointResponseEnd(headers) { + if (this.end == null && this.opts.method !== "HEAD") { + const contentLength = headers["content-length"]; + this.end = contentLength != null ? Number(contentLength) - 1 : null; + assert( + this.end == null || Number.isFinite(this.end), + "invalid content-length" + ); + this.resume = this.end != null; } } - onConnect(abort) { - if (this.aborted) { - abort(this.reason); - } else { - this.abort = abort; + onRequestStart(controller, context5) { + this.controllerProxy.target = controller; + if (!this.headersSent) { + this.handler.onRequestStart?.(this.controllerProxy, context5); } } - onBodySent(chunk) { - if (this.handler.onBodySent) return this.handler.onBodySent(chunk); + onRequestUpgrade(_controller, statusCode, headers, socket) { + this.handler.onRequestUpgrade?.(this.controllerProxy, statusCode, headers, socket); } static [kRetryHandlerDefaultRetry](err, { state, opts }, cb) { const { statusCode, code, headers } = err; @@ -9387,92 +11773,69 @@ var require_retry_handler = __commonJS({ let retryAfterHeader = headers?.["retry-after"]; if (retryAfterHeader) { retryAfterHeader = Number(retryAfterHeader); - retryAfterHeader = Number.isNaN(retryAfterHeader) ? calculateRetryAfterHeader(retryAfterHeader) : retryAfterHeader * 1e3; + retryAfterHeader = Number.isNaN(retryAfterHeader) ? calculateRetryAfterHeader(headers["retry-after"]) : retryAfterHeader * 1e3; } const retryTimeout = retryAfterHeader > 0 ? Math.min(retryAfterHeader, maxTimeout) : Math.min(minTimeout * timeoutFactor ** (counter - 1), maxTimeout); setTimeout(() => cb(null), retryTimeout); } - onHeaders(statusCode, rawHeaders, resume, statusMessage) { - const headers = parseHeaders(rawHeaders); + onResponseStart(controller, statusCode, headers, statusMessage) { + this.error = null; this.retryCount += 1; if (statusCode >= 300) { - if (this.retryOpts.statusCodes.includes(statusCode) === false) { - return this.handler.onHeaders( - statusCode, - rawHeaders, - resume, - statusMessage - ); - } else { - this.abort( - new RequestRetryError("Request failed", statusCode, { - headers, - data: { - count: this.retryCount - } - }) - ); - return false; - } + const err = new RequestRetryError("Request failed", statusCode, { + headers, + data: { + count: this.retryCount + } + }); + this.onResponseStartWithRetry(controller, statusCode, headers, statusMessage, err); + return; } - if (this.resume != null) { - this.resume = null; + if (this.headersSent) { if (statusCode !== 206 && (this.start > 0 || statusCode !== 200)) { - this.abort( - new RequestRetryError("server does not support the range header and the payload was partially consumed", statusCode, { - headers, - data: { count: this.retryCount } - }) - ); - return false; + throw new RequestRetryError("server does not support the range header and the payload was partially consumed", statusCode, { + headers, + data: { count: this.retryCount } + }); } const contentRange = parseRangeHeader(headers["content-range"]); if (!contentRange) { - this.abort( - new RequestRetryError("Content-Range mismatch", statusCode, { - headers, - data: { count: this.retryCount } - }) - ); - return false; + throw new RequestRetryError("Content-Range mismatch", statusCode, { + headers, + data: { count: this.retryCount } + }); } if (this.etag != null && this.etag !== headers.etag) { - this.abort( - new RequestRetryError("ETag mismatch", statusCode, { - headers, - data: { count: this.retryCount } - }) - ); - return false; + throw new RequestRetryError("ETag mismatch", statusCode, { + headers, + data: { count: this.retryCount } + }); } - const contentLengthError = validatePartialResponseContentLength(headers, contentRange, statusCode, this.retryCount); - if (contentLengthError != null) { - this.abort(contentLengthError); - return false; + validatePartialResponseContentLength(headers, contentRange, statusCode, this.retryCount); + const { start, size, end = size ? size - 1 : null } = contentRange; + if (this.start !== start || this.end != null && this.end !== end) { + throw new RequestRetryError("Content-Range mismatch", statusCode, { + headers, + data: { count: this.retryCount } + }); } - const { start, size, end = size - 1 } = contentRange; - assert(this.start === start, "content-range mismatch"); - assert(this.end == null || this.end === end, "content-range mismatch"); - this.resume = resume; - return true; + return; } if (this.end == null) { if (statusCode === 206) { const range2 = parseRangeHeader(headers["content-range"]); if (range2 == null) { - return this.handler.onHeaders( + this.headersSent = true; + this.handler.onResponseStart?.( + this.controllerProxy, statusCode, - rawHeaders, - resume, + headers, statusMessage ); + return; } - const contentLengthError = validatePartialResponseContentLength(headers, range2, statusCode, this.retryCount); - if (contentLengthError != null) { - this.abort(contentLengthError); - return false; - } - const { start, size, end = size - 1 } = range2; + validatePartialResponseContentLength(headers, range2, statusCode, this.retryCount); + const { start, size, end = size ? size - 1 : null } = range2; assert( start != null && Number.isFinite(start), "content-range mismatch" @@ -9490,36 +11853,74 @@ var require_retry_handler = __commonJS({ this.end == null || Number.isFinite(this.end), "invalid content-length" ); - this.resume = resume; + this.resume = true; this.etag = headers.etag != null ? headers.etag : null; - if (this.etag != null && this.etag.startsWith("W/")) { + if (this.etag != null && this.etag[0] === "W" && this.etag[1] === "/") { this.etag = null; } - return this.handler.onHeaders( + this.headersSent = true; + this.handler.onResponseStart?.( + this.controllerProxy, statusCode, - rawHeaders, - resume, + headers, statusMessage ); + } else { + throw new RequestRetryError("Request failed", statusCode, { + headers, + data: { count: this.retryCount } + }); } - const err = new RequestRetryError("Request failed", statusCode, { - headers, - data: { count: this.retryCount } - }); - this.abort(err); - return false; } - onData(chunk) { + onResponseData(_controller, chunk) { + if (this.error) { + return; + } this.start += chunk.length; - return this.handler.onData(chunk); + this.handler.onResponseData?.(this.controllerProxy, chunk); } - onComplete(rawTrailers) { - this.retryCount = 0; - return this.handler.onComplete(rawTrailers); + onResponseEnd(_controller, trailers) { + if (this.error && this.retryOpts.throwOnError) { + throw this.error; + } + if (!this.error) { + this.retryCount = 0; + return this.handler.onResponseEnd?.(this.controllerProxy, trailers); + } + this.retry(); } - onError(err) { - if (this.aborted || isDisturbed(this.opts.body)) { - return this.handler.onError(err); + retry() { + if (this.start !== 0) { + const headers = { range: `bytes=${this.start}-${this.end ?? ""}` }; + if (this.etag != null) { + headers["if-match"] = this.etag; + } + this.opts = { + ...this.opts, + headers: { + ...this.opts.headers, + ...headers + } + }; + } + try { + this.retryCountCheckpoint = this.retryCount; + this.dispatch(this.opts, this); + } catch (err) { + this.handler.onResponseError?.(this.controllerProxy, err); + } + } + onResponseError(controller, err) { + if (controller?.aborted || isDisturbed(this.opts.body) || this.headersSent && !this.resume) { + this.handler.onResponseError?.(this.controllerProxy, err); + return; + } + function shouldRetry(returnedErr) { + if (!returnedErr) { + this.retry(); + return; + } + this.handler?.onResponseError?.(this.controllerProxy, returnedErr); } if (this.retryCount - this.retryCountCheckpoint > 0) { this.retryCount = this.retryCountCheckpoint + (this.retryCount - this.retryCountCheckpoint); @@ -9532,32 +11933,8 @@ var require_retry_handler = __commonJS({ state: { counter: this.retryCount }, opts: { retryOptions: this.retryOpts, ...this.opts } }, - onRetry.bind(this) + shouldRetry.bind(this) ); - function onRetry(err2) { - if (err2 != null || this.aborted || isDisturbed(this.opts.body)) { - return this.handler.onError(err2); - } - if (this.start !== 0) { - const headers = { range: `bytes=${this.start}-${this.end ?? ""}` }; - if (this.etag != null) { - headers["if-match"] = this.etag; - } - this.opts = { - ...this.opts, - headers: { - ...this.opts.headers, - ...headers - } - }; - } - try { - this.retryCountCheckpoint = this.retryCount; - this.dispatch(this.opts, this); - } catch (err3) { - this.handler.onError(err3); - } - } } }; module2.exports = RetryHandler; @@ -9599,6 +11976,49 @@ var require_retry_agent = __commonJS({ } }); +// node_modules/undici/lib/dispatcher/h2c-client.js +var require_h2c_client = __commonJS({ + "node_modules/undici/lib/dispatcher/h2c-client.js"(exports2, module2) { + "use strict"; + var { InvalidArgumentError } = require_errors(); + var Client = require_client(); + var H2CClient = class extends Client { + constructor(origin, clientOpts) { + if (typeof origin === "string") { + origin = new URL(origin); + } + if (origin.protocol !== "http:") { + throw new InvalidArgumentError( + "h2c-client: Only h2c protocol is supported" + ); + } + const { maxConcurrentStreams, pipelining, ...opts } = clientOpts ?? {}; + let defaultMaxConcurrentStreams = 100; + let defaultPipelining = 100; + if (maxConcurrentStreams != null && Number.isInteger(maxConcurrentStreams) && maxConcurrentStreams > 0) { + defaultMaxConcurrentStreams = maxConcurrentStreams; + } + if (pipelining != null && Number.isInteger(pipelining) && pipelining > 0) { + defaultPipelining = pipelining; + } + if (defaultPipelining > defaultMaxConcurrentStreams) { + throw new InvalidArgumentError( + "h2c-client: pipelining cannot be greater than maxConcurrentStreams" + ); + } + super(origin, { + ...opts, + maxConcurrentStreams: defaultMaxConcurrentStreams, + pipelining: defaultPipelining, + allowH2: true, + useH2c: true + }); + } + }; + module2.exports = H2CClient; + } +}); + // node_modules/undici/lib/api/readable.js var require_readable = __commonJS({ "node_modules/undici/lib/api/readable.js"(exports2, module2) { @@ -9614,9 +12034,19 @@ var require_readable = __commonJS({ var kAbort = /* @__PURE__ */ Symbol("kAbort"); var kContentType = /* @__PURE__ */ Symbol("kContentType"); var kContentLength = /* @__PURE__ */ Symbol("kContentLength"); + var kUsed = /* @__PURE__ */ Symbol("kUsed"); + var kBytesRead = /* @__PURE__ */ Symbol("kBytesRead"); var noop3 = () => { }; var BodyReadable = class extends Readable4 { + /** + * @param {object} opts + * @param {(this: Readable, size: number) => void} opts.resume + * @param {() => (void | null)} opts.abort + * @param {string} [opts.contentType = ''] + * @param {number} [opts.contentLength] + * @param {number} [opts.highWaterMark = 64 * 1024] + */ constructor({ resume, abort, @@ -9633,84 +12063,155 @@ var require_readable = __commonJS({ this._readableState.dataEmitted = false; this[kAbort] = abort; this[kConsume] = null; + this[kBytesRead] = 0; this[kBody] = null; + this[kUsed] = false; this[kContentType] = contentType; - this[kContentLength] = contentLength; + this[kContentLength] = Number.isFinite(contentLength) ? contentLength : null; this[kReading] = false; } - destroy(err) { + /** + * @param {Error|null} err + * @param {(error:(Error|null)) => void} callback + * @returns {void} + */ + _destroy(err, callback) { if (!err && !this._readableState.endEmitted) { err = new RequestAbortedError(); } if (err) { this[kAbort](); } - return super.destroy(err); - } - _destroy(err, callback) { - if (!this[kReading]) { - setImmediate(() => { - callback(err); - }); + if (!this[kUsed]) { + setImmediate(callback, err); } else { callback(err); } } - on(ev, ...args) { - if (ev === "data" || ev === "readable") { + /** + * @param {string|symbol} event + * @param {(...args: any[]) => void} listener + * @returns {this} + */ + on(event, listener) { + if (event === "data" || event === "readable") { this[kReading] = true; + this[kUsed] = true; } - return super.on(ev, ...args); + return super.on(event, listener); } - addListener(ev, ...args) { - return this.on(ev, ...args); + /** + * @param {string|symbol} event + * @param {(...args: any[]) => void} listener + * @returns {this} + */ + addListener(event, listener) { + return this.on(event, listener); } - off(ev, ...args) { - const ret = super.off(ev, ...args); - if (ev === "data" || ev === "readable") { + /** + * @param {string|symbol} event + * @param {(...args: any[]) => void} listener + * @returns {this} + */ + off(event, listener) { + const ret = super.off(event, listener); + if (event === "data" || event === "readable") { this[kReading] = this.listenerCount("data") > 0 || this.listenerCount("readable") > 0; } return ret; } - removeListener(ev, ...args) { - return this.off(ev, ...args); + /** + * @param {string|symbol} event + * @param {(...args: any[]) => void} listener + * @returns {this} + */ + removeListener(event, listener) { + return this.off(event, listener); } + /** + * @param {Buffer|null} chunk + * @returns {boolean} + */ push(chunk) { - if (this[kConsume] && chunk !== null) { - consumePush(this[kConsume], chunk); - return this[kReading] ? super.push(chunk) : true; + if (chunk) { + this[kBytesRead] += chunk.length; + if (this[kConsume]) { + consumePush(this[kConsume], chunk); + return this[kReading] ? super.push(chunk) : true; + } } return super.push(chunk); } - // https://fetch.spec.whatwg.org/#dom-body-text - async text() { + /** + * Consumes and returns the body as a string. + * + * @see https://fetch.spec.whatwg.org/#dom-body-text + * @returns {Promise} + */ + text() { return consume(this, "text"); } - // https://fetch.spec.whatwg.org/#dom-body-json - async json() { + /** + * Consumes and returns the body as a JavaScript Object. + * + * @see https://fetch.spec.whatwg.org/#dom-body-json + * @returns {Promise} + */ + json() { return consume(this, "json"); } - // https://fetch.spec.whatwg.org/#dom-body-blob - async blob() { + /** + * Consumes and returns the body as a Blob + * + * @see https://fetch.spec.whatwg.org/#dom-body-blob + * @returns {Promise} + */ + blob() { return consume(this, "blob"); } - // https://fetch.spec.whatwg.org/#dom-body-bytes - async bytes() { + /** + * Consumes and returns the body as an Uint8Array. + * + * @see https://fetch.spec.whatwg.org/#dom-body-bytes + * @returns {Promise} + */ + bytes() { return consume(this, "bytes"); } - // https://fetch.spec.whatwg.org/#dom-body-arraybuffer - async arrayBuffer() { + /** + * Consumes and returns the body as an ArrayBuffer. + * + * @see https://fetch.spec.whatwg.org/#dom-body-arraybuffer + * @returns {Promise} + */ + arrayBuffer() { return consume(this, "arrayBuffer"); } - // https://fetch.spec.whatwg.org/#dom-body-formdata + /** + * Not implemented + * + * @see https://fetch.spec.whatwg.org/#dom-body-formdata + * @throws {NotSupportedError} + */ async formData() { throw new NotSupportedError(); } - // https://fetch.spec.whatwg.org/#dom-body-bodyused + /** + * Returns true if the body is not null and the body has been consumed. + * Otherwise, returns false. + * + * @see https://fetch.spec.whatwg.org/#dom-body-bodyused + * @readonly + * @returns {boolean} + */ get bodyUsed() { return util4.isDisturbed(this); } - // https://fetch.spec.whatwg.org/#dom-body-body + /** + * @see https://fetch.spec.whatwg.org/#dom-body-body + * @readonly + * @returns {ReadableStream} + */ get body() { if (!this[kBody]) { this[kBody] = ReadableStreamFrom(this); @@ -9721,55 +12222,76 @@ var require_readable = __commonJS({ } return this[kBody]; } - async dump(opts) { - let limit = Number.isFinite(opts?.limit) ? opts.limit : 128 * 1024; + /** + * Dumps the response body by reading `limit` number of bytes. + * @param {object} opts + * @param {number} [opts.limit = 131072] Number of bytes to read. + * @param {AbortSignal} [opts.signal] An AbortSignal to cancel the dump. + * @returns {Promise} + */ + dump(opts) { const signal = opts?.signal; if (signal != null && (typeof signal !== "object" || !("aborted" in signal))) { - throw new InvalidArgumentError("signal must be an AbortSignal"); + return Promise.reject(new InvalidArgumentError("signal must be an AbortSignal")); + } + const limit = opts?.limit && Number.isFinite(opts.limit) ? opts.limit : 128 * 1024; + if (signal?.aborted) { + return Promise.reject(signal.reason ?? new AbortError2()); } - signal?.throwIfAborted(); if (this._readableState.closeEmitted) { - return null; + return Promise.resolve(null); } - return await new Promise((resolve15, reject) => { - if (this[kContentLength] > limit) { + return new Promise((resolve15, reject) => { + if (this[kContentLength] && this[kContentLength] > limit || this[kBytesRead] > limit) { this.destroy(new AbortError2()); } - const onAbort = () => { - this.destroy(signal.reason ?? new AbortError2()); - }; - signal?.addEventListener("abort", onAbort); - this.on("close", function() { - signal?.removeEventListener("abort", onAbort); - if (signal?.aborted) { - reject(signal.reason ?? new AbortError2()); - } else { - resolve15(null); - } - }).on("error", noop3).on("data", function(chunk) { - limit -= chunk.length; - if (limit <= 0) { + if (signal) { + const onAbort = () => { + this.destroy(signal.reason ?? new AbortError2()); + }; + signal.addEventListener("abort", onAbort); + this.on("close", function() { + signal.removeEventListener("abort", onAbort); + if (signal.aborted) { + reject(signal.reason ?? new AbortError2()); + } else { + resolve15(null); + } + }); + } else { + this.on("close", resolve15); + } + this.on("error", noop3).on("data", () => { + if (this[kBytesRead] > limit) { this.destroy(); } }).resume(); }); } + /** + * @param {BufferEncoding} encoding + * @returns {this} + */ + setEncoding(encoding) { + if (Buffer.isEncoding(encoding)) { + this._readableState.encoding = encoding; + } + return this; + } }; - function isLocked(self2) { - return self2[kBody] && self2[kBody].locked === true || self2[kConsume]; + function isLocked(bodyReadable) { + return bodyReadable[kBody]?.locked === true || bodyReadable[kConsume] !== null; } - function isUnusable(self2) { - return util4.isDisturbed(self2) || isLocked(self2); + function isUnusable(bodyReadable) { + return util4.isDisturbed(bodyReadable) || isLocked(bodyReadable); } - async function consume(stream2, type) { + function consume(stream2, type) { assert(!stream2[kConsume]); return new Promise((resolve15, reject) => { if (isUnusable(stream2)) { const rState = stream2._readableState; if (rState.destroyed && rState.closeEmitted === false) { - stream2.on("error", (err) => { - reject(err); - }).on("close", () => { + stream2.on("error", reject).on("close", () => { reject(new TypeError("unusable")); }); } else { @@ -9814,24 +12336,28 @@ var require_readable = __commonJS({ } } if (state.endEmitted) { - consumeEnd(this[kConsume]); + consumeEnd(this[kConsume], this._readableState.encoding); } else { consume2.stream.on("end", function() { - consumeEnd(this[kConsume]); + consumeEnd(this[kConsume], this._readableState.encoding); }); } consume2.stream.resume(); while (consume2.stream.read() != null) { } } - function chunksDecode(chunks, length) { + function chunksDecode(chunks, length, encoding) { if (chunks.length === 0 || length === 0) { return ""; } const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, length); const bufferLength = buffer.length; const start = bufferLength > 2 && buffer[0] === 239 && buffer[1] === 187 && buffer[2] === 191 ? 3 : 0; - return buffer.utf8Slice(start, bufferLength); + if (!encoding || encoding === "utf8" || encoding === "utf-8") { + return buffer.utf8Slice(start, bufferLength); + } else { + return buffer.subarray(start, bufferLength).toString(encoding); + } } function chunksConcat(chunks, length) { if (chunks.length === 0 || length === 0) { @@ -9849,13 +12375,13 @@ var require_readable = __commonJS({ } return buffer; } - function consumeEnd(consume2) { + function consumeEnd(consume2, encoding) { const { type, body, resolve: resolve15, stream: stream2, length } = consume2; try { if (type === "text") { - resolve15(chunksDecode(body, length)); + resolve15(chunksDecode(body, length, encoding)); } else if (type === "json") { - resolve15(JSON.parse(chunksDecode(body, length))); + resolve15(JSON.parse(chunksDecode(body, length, encoding))); } else if (type === "arrayBuffer") { resolve15(chunksConcat(body, length).buffer); } else if (type === "blob") { @@ -9888,67 +12414,9 @@ var require_readable = __commonJS({ consume2.length = 0; consume2.body = null; } - module2.exports = { Readable: BodyReadable, chunksDecode }; - } -}); - -// node_modules/undici/lib/api/util.js -var require_util3 = __commonJS({ - "node_modules/undici/lib/api/util.js"(exports2, module2) { - var assert = require("node:assert"); - var { - ResponseStatusCodeError - } = require_errors(); - var { chunksDecode } = require_readable(); - var CHUNK_LIMIT = 128 * 1024; - async function getResolveErrorBodyCallback({ callback, body, contentType, statusCode, statusMessage, headers }) { - assert(body); - let chunks = []; - let length = 0; - try { - for await (const chunk of body) { - chunks.push(chunk); - length += chunk.length; - if (length > CHUNK_LIMIT) { - chunks = []; - length = 0; - break; - } - } - } catch { - chunks = []; - length = 0; - } - const message = `Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ""}`; - if (statusCode === 204 || !contentType || !length) { - queueMicrotask(() => callback(new ResponseStatusCodeError(message, statusCode, headers))); - return; - } - const stackTraceLimit = Error.stackTraceLimit; - Error.stackTraceLimit = 0; - let payload; - try { - if (isContentTypeApplicationJson(contentType)) { - payload = JSON.parse(chunksDecode(chunks, length)); - } else if (isContentTypeText(contentType)) { - payload = chunksDecode(chunks, length); - } - } catch { - } finally { - Error.stackTraceLimit = stackTraceLimit; - } - queueMicrotask(() => callback(new ResponseStatusCodeError(message, statusCode, headers, payload))); - } - var isContentTypeApplicationJson = (contentType) => { - return contentType.length > 15 && contentType[11] === "/" && contentType[0] === "a" && contentType[1] === "p" && contentType[2] === "p" && contentType[3] === "l" && contentType[4] === "i" && contentType[5] === "c" && contentType[6] === "a" && contentType[7] === "t" && contentType[8] === "i" && contentType[9] === "o" && contentType[10] === "n" && contentType[12] === "j" && contentType[13] === "s" && contentType[14] === "o" && contentType[15] === "n"; - }; - var isContentTypeText = (contentType) => { - return contentType.length > 4 && contentType[4] === "/" && contentType[0] === "t" && contentType[1] === "e" && contentType[2] === "x" && contentType[3] === "t"; - }; module2.exports = { - getResolveErrorBodyCallback, - isContentTypeApplicationJson, - isContentTypeText + Readable: BodyReadable, + chunksDecode }; } }); @@ -9958,22 +12426,23 @@ var require_api_request = __commonJS({ "node_modules/undici/lib/api/api-request.js"(exports2, module2) { "use strict"; var assert = require("node:assert"); + var { AsyncResource } = require("node:async_hooks"); var { Readable: Readable4 } = require_readable(); var { InvalidArgumentError, RequestAbortedError } = require_errors(); var util4 = require_util(); - var { getResolveErrorBodyCallback } = require_util3(); - var { AsyncResource } = require("node:async_hooks"); + function noop3() { + } var RequestHandler = class extends AsyncResource { constructor(opts, callback) { if (!opts || typeof opts !== "object") { throw new InvalidArgumentError("invalid opts"); } - const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError, highWaterMark } = opts; + const { signal, method, opaque, body, onInfo, responseHeaders, highWaterMark } = opts; try { if (typeof callback !== "function") { throw new InvalidArgumentError("invalid callback"); } - if (highWaterMark && (typeof highWaterMark !== "number" || highWaterMark < 0)) { + if (highWaterMark != null && (!Number.isFinite(highWaterMark) || highWaterMark < 0)) { throw new InvalidArgumentError("invalid highWaterMark"); } if (signal && typeof signal.on !== "function" && typeof signal.addEventListener !== "function") { @@ -9988,7 +12457,7 @@ var require_api_request = __commonJS({ super("UNDICI_REQUEST"); } catch (err) { if (util4.isStream(body)) { - util4.destroy(body.on("error", util4.nop), err); + util4.destroy(body.on("error", noop3), err); } throw err; } @@ -10002,35 +12471,21 @@ var require_api_request = __commonJS({ this.trailers = {}; this.context = null; this.onInfo = onInfo || null; - this.throwOnError = throwOnError; this.highWaterMark = highWaterMark; - this.signal = signal; this.reason = null; this.removeAbortListener = null; - if (util4.isStream(body)) { - body.on("error", (err) => { - this.onError(err); + if (signal?.aborted) { + this.reason = signal.reason ?? new RequestAbortedError(); + } else if (signal) { + this.removeAbortListener = util4.addAbortListener(signal, () => { + this.reason = signal.reason ?? new RequestAbortedError(); + if (this.res) { + util4.destroy(this.res.on("error", noop3), this.reason); + } else if (this.abort) { + this.abort(this.reason); + } }); } - if (this.signal) { - if (this.signal.aborted) { - this.reason = this.signal.reason ?? new RequestAbortedError(); - } else { - this.removeAbortListener = util4.addAbortListener(this.signal, () => { - this.reason = this.signal.reason ?? new RequestAbortedError(); - if (this.res) { - util4.destroy(this.res.on("error", util4.nop), this.reason); - } else if (this.abort) { - this.abort(this.reason); - } - if (this.removeAbortListener) { - this.res?.off("close", this.removeAbortListener); - this.removeAbortListener(); - this.removeAbortListener = null; - } - }); - } - } } onConnect(abort, context5) { if (this.reason) { @@ -10062,25 +12517,27 @@ var require_api_request = __commonJS({ }); if (this.removeAbortListener) { res.on("close", this.removeAbortListener); + this.removeAbortListener = null; } this.callback = null; this.res = res; if (callback !== null) { - if (this.throwOnError && statusCode >= 400) { - this.runInAsyncScope( - getResolveErrorBodyCallback, - null, - { callback, body: res, contentType, statusCode, statusMessage, headers } - ); - } else { + try { this.runInAsyncScope(callback, null, null, { statusCode, + statusText: statusMessage, headers, trailers: this.trailers, opaque, body: res, context: context5 }); + } catch (err) { + this.res = null; + util4.destroy(res.on("error", noop3), err); + queueMicrotask(() => { + throw err; + }); } } } @@ -10102,15 +12559,17 @@ var require_api_request = __commonJS({ if (res) { this.res = null; queueMicrotask(() => { - util4.destroy(res, err); + util4.destroy(res.on("error", noop3), err); }); } if (body) { this.body = null; - util4.destroy(body, err); + if (util4.isStream(body)) { + body.on("error", noop3); + util4.destroy(body, err); + } } if (this.removeAbortListener) { - res?.off("close", this.removeAbortListener); this.removeAbortListener(); this.removeAbortListener = null; } @@ -10125,7 +12584,8 @@ var require_api_request = __commonJS({ }); } try { - this.dispatch(opts, new RequestHandler(opts, callback)); + const handler2 = new RequestHandler(opts, callback); + this.dispatch(opts, handler2); } catch (err) { if (typeof callback !== "function") { throw err; @@ -10142,6 +12602,7 @@ var require_api_request = __commonJS({ // node_modules/undici/lib/api/abort-signal.js var require_abort_signal = __commonJS({ "node_modules/undici/lib/api/abort-signal.js"(exports2, module2) { + "use strict"; var { addAbortListener } = require_util(); var { RequestAbortedError } = require_errors(); var kListener = /* @__PURE__ */ Symbol("kListener"); @@ -10195,18 +12656,19 @@ var require_api_stream = __commonJS({ "node_modules/undici/lib/api/api-stream.js"(exports2, module2) { "use strict"; var assert = require("node:assert"); - var { finished, PassThrough: PassThrough3 } = require("node:stream"); + var { finished } = require("node:stream"); + var { AsyncResource } = require("node:async_hooks"); var { InvalidArgumentError, InvalidReturnValueError } = require_errors(); var util4 = require_util(); - var { getResolveErrorBodyCallback } = require_util3(); - var { AsyncResource } = require("node:async_hooks"); var { addSignal, removeSignal } = require_abort_signal(); + function noop3() { + } var StreamHandler = class extends AsyncResource { constructor(opts, factory, callback) { if (!opts || typeof opts !== "object") { throw new InvalidArgumentError("invalid opts"); } - const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError } = opts; + const { signal, method, opaque, body, onInfo, responseHeaders } = opts; try { if (typeof callback !== "function") { throw new InvalidArgumentError("invalid callback"); @@ -10226,7 +12688,7 @@ var require_api_stream = __commonJS({ super("UNDICI_STREAM"); } catch (err) { if (util4.isStream(body)) { - util4.destroy(body.on("error", util4.nop), err); + util4.destroy(body.on("error", noop3), err); } throw err; } @@ -10240,7 +12702,6 @@ var require_api_stream = __commonJS({ this.trailers = null; this.body = body; this.onInfo = onInfo || null; - this.throwOnError = throwOnError || false; if (util4.isStream(body)) { body.on("error", (err) => { this.onError(err); @@ -10258,7 +12719,7 @@ var require_api_stream = __commonJS({ this.context = context5; } onHeaders(statusCode, rawHeaders, resume, statusMessage) { - const { factory, opaque, context: context5, callback, responseHeaders } = this; + const { factory, opaque, context: context5, responseHeaders } = this; const headers = responseHeaders === "raw" ? util4.parseRawHeaders(rawHeaders) : util4.parseHeaders(rawHeaders); if (statusCode < 200) { if (this.onInfo) { @@ -10267,43 +12728,30 @@ var require_api_stream = __commonJS({ return; } this.factory = null; - let res; - if (this.throwOnError && statusCode >= 400) { - const parsedHeaders = responseHeaders === "raw" ? util4.parseHeaders(rawHeaders) : headers; - const contentType = parsedHeaders["content-type"]; - res = new PassThrough3(); - this.callback = null; - this.runInAsyncScope( - getResolveErrorBodyCallback, - null, - { callback, body: res, contentType, statusCode, statusMessage, headers } - ); - } else { - if (factory === null) { - return; + if (factory === null) { + return; + } + const res = this.runInAsyncScope(factory, null, { + statusCode, + headers, + opaque, + context: context5 + }); + if (!res || typeof res.write !== "function" || typeof res.end !== "function" || typeof res.on !== "function") { + throw new InvalidReturnValueError("expected Writable"); + } + finished(res, { readable: false }, (err) => { + const { callback, res: res2, opaque: opaque2, trailers, abort } = this; + this.res = null; + if (err || !res2?.readable) { + util4.destroy(res2, err); } - res = this.runInAsyncScope(factory, null, { - statusCode, - headers, - opaque, - context: context5 - }); - if (!res || typeof res.write !== "function" || typeof res.end !== "function" || typeof res.on !== "function") { - throw new InvalidReturnValueError("expected Writable"); + this.callback = null; + this.runInAsyncScope(callback, null, err || null, { opaque: opaque2, trailers }); + if (err) { + abort(); } - finished(res, { readable: false }, (err) => { - const { callback: callback2, res: res2, opaque: opaque2, trailers, abort } = this; - this.res = null; - if (err || !res2.readable) { - util4.destroy(res2, err); - } - this.callback = null; - this.runInAsyncScope(callback2, null, err || null, { opaque: opaque2, trailers }); - if (err) { - abort(); - } - }); - } + }); res.on("drain", resume); this.res = res; const needDrain = res.writableNeedDrain !== void 0 ? res.writableNeedDrain : res._writableState?.needDrain; @@ -10350,7 +12798,8 @@ var require_api_stream = __commonJS({ }); } try { - this.dispatch(opts, new StreamHandler(opts, factory, callback)); + const handler2 = new StreamHandler(opts, factory, callback); + this.dispatch(opts, handler2); } catch (err) { if (typeof callback !== "function") { throw err; @@ -10372,15 +12821,17 @@ var require_api_pipeline = __commonJS({ Duplex: Duplex4, PassThrough: PassThrough3 } = require("node:stream"); + var assert = require("node:assert"); + var { AsyncResource } = require("node:async_hooks"); var { InvalidArgumentError, InvalidReturnValueError, RequestAbortedError } = require_errors(); var util4 = require_util(); - var { AsyncResource } = require("node:async_hooks"); var { addSignal, removeSignal } = require_abort_signal(); - var assert = require("node:assert"); + function noop3() { + } var kResume = /* @__PURE__ */ Symbol("resume"); var PipelineRequest = class extends Readable4 { constructor() { @@ -10439,7 +12890,7 @@ var require_api_pipeline = __commonJS({ this.abort = null; this.context = null; this.onInfo = onInfo || null; - this.req = new PipelineRequest().on("error", util4.nop); + this.req = new PipelineRequest().on("error", noop3); this.ret = new Duplex4({ readableObjectMode: opts.objectMode, autoDestroy: true, @@ -10479,13 +12930,12 @@ var require_api_pipeline = __commonJS({ addSignal(this, signal); } onConnect(abort, context5) { - const { ret, res } = this; + const { res } = this; if (this.reason) { abort(this.reason); return; } assert(!res, "pipeline cannot be retried"); - assert(!ret.destroyed); this.abort = abort; this.context = context5; } @@ -10511,7 +12961,7 @@ var require_api_pipeline = __commonJS({ context: context5 }); } catch (err) { - this.res.on("error", util4.nop); + this.res.on("error", noop3); throw err; } if (!body || typeof body.on !== "function") { @@ -10569,9 +13019,10 @@ var require_api_upgrade = __commonJS({ "use strict"; var { InvalidArgumentError, SocketError } = require_errors(); var { AsyncResource } = require("node:async_hooks"); + var assert = require("node:assert"); var util4 = require_util(); + var { kHTTP2Stream } = require_symbols(); var { addSignal, removeSignal } = require_abort_signal(); - var assert = require("node:assert"); var UpgradeHandler = class extends AsyncResource { constructor(opts, callback) { if (!opts || typeof opts !== "object") { @@ -10605,7 +13056,7 @@ var require_api_upgrade = __commonJS({ throw new SocketError("bad upgrade", null); } onUpgrade(statusCode, rawHeaders, socket) { - assert(statusCode === 101); + assert(socket[kHTTP2Stream] === true ? statusCode === 200 : statusCode === 101); const { callback, opaque, context: context5 } = this; removeSignal(this); this.callback = null; @@ -10638,11 +13089,12 @@ var require_api_upgrade = __commonJS({ } try { const upgradeHandler = new UpgradeHandler(opts, callback); - this.dispatch({ + const upgradeOpts = { ...opts, method: opts.method || "GET", upgrade: opts.protocol || "Websocket" - }, upgradeHandler); + }; + this.dispatch(upgradeOpts, upgradeHandler); } catch (err) { if (typeof callback !== "function") { throw err; @@ -10732,7 +13184,8 @@ var require_api_connect = __commonJS({ } try { const connectHandler = new ConnectHandler(opts, callback); - this.dispatch({ ...opts, method: "CONNECT" }, connectHandler); + const connectOptions = { ...opts, method: "CONNECT" }; + this.dispatch(connectOptions, connectHandler); } catch (err) { if (typeof callback !== "function") { throw err; @@ -10763,10 +13216,9 @@ var require_mock_errors = __commonJS({ "use strict"; var { UndiciError } = require_errors(); var kMockNotMatchedError = /* @__PURE__ */ Symbol.for("undici.error.UND_MOCK_ERR_MOCK_NOT_MATCHED"); - var MockNotMatchedError = class _MockNotMatchedError extends UndiciError { + var MockNotMatchedError = class extends UndiciError { constructor(message) { super(message); - Error.captureStackTrace(this, _MockNotMatchedError); this.name = "MockNotMatchedError"; this.message = message || "The request does not match any registered mock dispatches"; this.code = "UND_MOCK_ERR_MOCK_NOT_MATCHED"; @@ -10774,7 +13226,9 @@ var require_mock_errors = __commonJS({ static [Symbol.hasInstance](instance8) { return instance8 && instance8[kMockNotMatchedError] === true; } - [kMockNotMatchedError] = true; + get [kMockNotMatchedError]() { + return true; + } }; module2.exports = { MockNotMatchedError @@ -10801,11 +13255,20 @@ var require_mock_symbols = __commonJS({ kMockDispatch: /* @__PURE__ */ Symbol("mock dispatch"), kClose: /* @__PURE__ */ Symbol("close"), kOriginalClose: /* @__PURE__ */ Symbol("original agent close"), + kOriginalDispatch: /* @__PURE__ */ Symbol("original dispatch"), kOrigin: /* @__PURE__ */ Symbol("origin"), kIsMockActive: /* @__PURE__ */ Symbol("is mock active"), kNetConnect: /* @__PURE__ */ Symbol("net connect"), kGetNetConnect: /* @__PURE__ */ Symbol("get net connect"), - kConnected: /* @__PURE__ */ Symbol("connected") + kConnected: /* @__PURE__ */ Symbol("connected"), + kIgnoreTrailingSlash: /* @__PURE__ */ Symbol("ignore trailing slash"), + kMockAgentMockCallHistoryInstance: /* @__PURE__ */ Symbol("mock agent mock call history name"), + kMockAgentRegisterCallHistory: /* @__PURE__ */ Symbol("mock agent register mock call history"), + kMockAgentAddCallHistoryLog: /* @__PURE__ */ Symbol("mock agent add call history log"), + kMockAgentIsCallHistoryEnabled: /* @__PURE__ */ Symbol("mock agent is call history enabled"), + kMockAgentAcceptsNonStandardSearchParameters: /* @__PURE__ */ Symbol("mock agent accepts non standard search parameters"), + kMockCallHistoryAddLog: /* @__PURE__ */ Symbol("mock call history add log"), + kTotalDispatchCount: /* @__PURE__ */ Symbol("total dispatch count") }; } }); @@ -10820,15 +13283,17 @@ var require_mock_utils = __commonJS({ kMockAgent, kOriginalDispatch, kOrigin, - kGetNetConnect + kGetNetConnect, + kTotalDispatchCount } = require_mock_symbols(); - var { buildURL } = require_util(); + var { serializePathWithQuery } = require_util(); var { STATUS_CODES } = require("node:http"); var { types: { isPromise: isPromise2 } } = require("node:util"); + var { InvalidArgumentError } = require_errors(); function matchValue(match2, value) { if (typeof match2 === "string") { return match2 === value; @@ -10891,11 +13356,35 @@ var require_mock_utils = __commonJS({ } return true; } + function normalizeSearchParams(query) { + if (typeof query !== "string") { + return query; + } + const originalQp = new URLSearchParams(query); + const normalizedQp = new URLSearchParams(); + for (let [key, value] of originalQp.entries()) { + key = key.replace("[]", ""); + const valueRepresentsString = /^(['"]).*\1$/.test(value); + if (valueRepresentsString) { + normalizedQp.append(key, value); + continue; + } + if (value.includes(",")) { + const values = value.split(","); + for (const v of values) { + normalizedQp.append(key, v); + } + continue; + } + normalizedQp.append(key, value); + } + return normalizedQp; + } function safeUrl(path30) { if (typeof path30 !== "string") { return path30; } - const pathSegments = path30.split("?"); + const pathSegments = path30.split("?", 3); if (pathSegments.length !== 2) { return path30; } @@ -10919,14 +13408,19 @@ var require_mock_utils = __commonJS({ return data; } else if (typeof data === "object") { return JSON.stringify(data); - } else { + } else if (data) { return data.toString(); + } else { + return ""; } } function getMockDispatch(mockDispatches, key) { - const basePath = key.query ? buildURL(key.path, key.query) : key.path; + const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path; const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath; - let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path30 }) => matchValue(safeUrl(path30), resolvedPath)); + const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath); + let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path30, ignoreTrailingSlash }) => { + return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path30)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path30), resolvedPath); + }); if (matchedMockDispatches.length === 0) { throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`); } @@ -10945,11 +13439,12 @@ var require_mock_utils = __commonJS({ } return matchedMockDispatches[0]; } - function addMockDispatch(mockDispatches, key, data) { - const baseData = { timesInvoked: 0, times: 1, persist: false, consumed: false }; + function addMockDispatch(mockDispatches, key, data, opts) { + const baseData = { timesInvoked: 0, times: 1, persist: false, consumed: false, ...opts }; const replyData = typeof data === "function" ? { callback: data } : { ...data }; const newMockDispatch = { ...baseData, ...key, pending: true, data: { error: null, ...replyData } }; mockDispatches.push(newMockDispatch); + mockDispatches[kTotalDispatchCount] = (mockDispatches[kTotalDispatchCount] || 0) + 1; return newMockDispatch; } function deleteMockDispatch(mockDispatches, key) { @@ -10963,6 +13458,15 @@ var require_mock_utils = __commonJS({ mockDispatches.splice(index2, 1); } } + function removeTrailingSlash(path30) { + while (path30.endsWith("/")) { + path30 = path30.slice(0, -1); + } + if (path30.length === 0) { + path30 = "/"; + } + return path30; + } function buildKey(opts) { const { path: path30, method, body, headers, query } = opts; return { @@ -11016,24 +13520,43 @@ var require_mock_utils = __commonJS({ handler2.onError(error3); return true; } + let aborted = false; + let timer = null; + function abort(err) { + if (aborted) { + return; + } + aborted = true; + if (timer !== null) { + clearTimeout(timer); + timer = null; + } + handler2.onError(err); + } + handler2.onConnect?.(abort, null); if (typeof delay2 === "number" && delay2 > 0) { - setTimeout(() => { + timer = setTimeout(() => { + timer = null; handleReply(this[kDispatches]); }, delay2); } else { handleReply(this[kDispatches]); } function handleReply(mockDispatches, _data = data) { + if (aborted) { + return; + } const optsHeaders = Array.isArray(opts.headers) ? buildHeadersFromArray(opts.headers) : opts.headers; const body = typeof _data === "function" ? _data({ ...opts, headers: optsHeaders }) : _data; if (isPromise2(body)) { - body.then((newData) => handleReply(mockDispatches, newData)); + return body.then((newData) => handleReply(mockDispatches, newData)); + } + if (aborted) { return; } const responseData = getResponseData2(body); const responseHeaders = generateKeyValues(headers); const responseTrailers = generateKeyValues(trailers); - handler2.onConnect?.((err) => handler2.onError(err), null); handler2.onHeaders?.(statusCode, responseHeaders, resume, getStatusText(statusCode)); handler2.onData?.(Buffer.from(responseData)); handler2.onComplete?.(responseTrailers); @@ -11052,15 +13575,18 @@ var require_mock_utils = __commonJS({ try { mockDispatch.call(this, opts, handler2); } catch (error3) { - if (error3 instanceof MockNotMatchedError) { + if (error3.code === "UND_MOCK_ERR_MOCK_NOT_MATCHED") { const netConnect = agent[kGetNetConnect](); + const totalInterceptsCount = this[kDispatches][kTotalDispatchCount] || this[kDispatches].length; + const pendingInterceptsCount = this[kDispatches].filter(({ consumed }) => !consumed).length; + const interceptsMessage = `, ${pendingInterceptsCount} interceptor(s) remaining out of ${totalInterceptsCount} defined`; if (netConnect === false) { - throw new MockNotMatchedError(`${error3.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)`); + throw new MockNotMatchedError(`${error3.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)${interceptsMessage}`); } if (checkNetConnect(netConnect, origin)) { originalDispatch.call(this, opts, handler2); } else { - throw new MockNotMatchedError(`${error3.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)`); + throw new MockNotMatchedError(`${error3.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)${interceptsMessage}`); } } else { throw error3; @@ -11080,11 +13606,27 @@ var require_mock_utils = __commonJS({ } return false; } - function buildMockOptions(opts) { - if (opts) { - const { agent, ...mockOptions } = opts; - return mockOptions; + function normalizeOrigin(origin) { + if (typeof origin !== "string" && !(origin instanceof URL)) { + return origin; + } + if (origin instanceof URL) { + return origin.origin; + } + return origin.toLowerCase(); + } + function buildAndValidateMockOptions(opts) { + const { agent, ...mockOptions } = opts; + if ("enableCallHistory" in mockOptions && typeof mockOptions.enableCallHistory !== "boolean") { + throw new InvalidArgumentError("options.enableCallHistory must to be a boolean"); } + if ("acceptNonStandardSearchParameters" in mockOptions && typeof mockOptions.acceptNonStandardSearchParameters !== "boolean") { + throw new InvalidArgumentError("options.acceptNonStandardSearchParameters must to be a boolean"); + } + if ("ignoreTrailingSlash" in mockOptions && typeof mockOptions.ignoreTrailingSlash !== "boolean") { + throw new InvalidArgumentError("options.ignoreTrailingSlash must to be a boolean"); + } + return mockOptions; } module2.exports = { getResponseData: getResponseData2, @@ -11099,9 +13641,11 @@ var require_mock_utils = __commonJS({ mockDispatch, buildMockDispatch, checkNetConnect, - buildMockOptions, + buildAndValidateMockOptions, getHeaderByName, - buildHeadersFromArray + buildHeadersFromArray, + normalizeSearchParams, + normalizeOrigin }; } }); @@ -11117,10 +13661,11 @@ var require_mock_interceptor = __commonJS({ kDefaultHeaders, kDefaultTrailers, kContentLength, - kMockDispatch + kMockDispatch, + kIgnoreTrailingSlash } = require_mock_symbols(); var { InvalidArgumentError } = require_errors(); - var { buildURL } = require_util(); + var { serializePathWithQuery } = require_util(); var MockScope = class { constructor(mockDispatch) { this[kMockDispatch] = mockDispatch; @@ -11166,7 +13711,7 @@ var require_mock_interceptor = __commonJS({ } if (typeof opts.path === "string") { if (opts.query) { - opts.path = buildURL(opts.path, opts.query); + opts.path = serializePathWithQuery(opts.path, opts.query); } else { const parsedURL = new URL(opts.path, "data://"); opts.path = parsedURL.pathname + parsedURL.search; @@ -11177,6 +13722,7 @@ var require_mock_interceptor = __commonJS({ } this[kDispatchKey] = buildKey(opts); this[kDispatches] = mockDispatches; + this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false; this[kDefaultHeaders] = {}; this[kDefaultTrailers] = {}; this[kContentLength] = false; @@ -11212,7 +13758,7 @@ var require_mock_interceptor = __commonJS({ ...this.createMockScopeDispatchData(replyParameters2) }; }; - const newMockDispatch2 = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback); + const newMockDispatch2 = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] }); return new MockScope(newMockDispatch2); } const replyParameters = { @@ -11222,7 +13768,7 @@ var require_mock_interceptor = __commonJS({ }; this.validateReplyParameters(replyParameters); const dispatchData = this.createMockScopeDispatchData(replyParameters); - const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData); + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] }); return new MockScope(newMockDispatch); } /** @@ -11232,7 +13778,7 @@ var require_mock_interceptor = __commonJS({ if (typeof error3 === "undefined") { throw new InvalidArgumentError("error must be defined"); } - const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], { error: error3 }); + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], { error: error3 }, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] }); return new MockScope(newMockDispatch); } /** @@ -11282,19 +13828,21 @@ var require_mock_client = __commonJS({ kOriginalClose, kOrigin, kOriginalDispatch, - kConnected + kConnected, + kIgnoreTrailingSlash } = require_mock_symbols(); var { MockInterceptor } = require_mock_interceptor(); var Symbols = require_symbols(); var { InvalidArgumentError } = require_errors(); var MockClient = class extends Client { constructor(origin, opts) { - super(origin, opts); if (!opts || !opts.agent || typeof opts.agent.dispatch !== "function") { throw new InvalidArgumentError("Argument opts.agent must implement Agent"); } + super(origin, opts); this[kMockAgent] = opts.agent; this[kOrigin] = origin; + this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false; this[kDispatches] = []; this[kConnected] = 1; this[kOriginalDispatch] = this.dispatch; @@ -11309,7 +13857,13 @@ var require_mock_client = __commonJS({ * Sets up the base interceptor for mocking replies from undici. */ intercept(opts) { - return new MockInterceptor(opts, this[kDispatches]); + return new MockInterceptor( + opts && { ignoreTrailingSlash: this[kIgnoreTrailingSlash], ...opts }, + this[kDispatches] + ); + } + cleanMocks() { + this[kDispatches] = []; } async [kClose]() { await promisify(this[kOriginalClose])(); @@ -11321,6 +13875,206 @@ var require_mock_client = __commonJS({ } }); +// node_modules/undici/lib/mock/mock-call-history.js +var require_mock_call_history = __commonJS({ + "node_modules/undici/lib/mock/mock-call-history.js"(exports2, module2) { + "use strict"; + var { kMockCallHistoryAddLog } = require_mock_symbols(); + var { InvalidArgumentError } = require_errors(); + function handleFilterCallsWithOptions(criteria, options, handler2, store, allLogs) { + switch (options.operator) { + case "OR": + store.push(...handler2(criteria, allLogs)); + return store; + case "AND": + return handler2(criteria, store); + default: + throw new InvalidArgumentError("options.operator must to be a case insensitive string equal to 'OR' or 'AND'"); + } + } + function buildAndValidateFilterCallsOptions(options = {}) { + const finalOptions = {}; + if ("operator" in options) { + if (typeof options.operator !== "string" || options.operator.toUpperCase() !== "OR" && options.operator.toUpperCase() !== "AND") { + throw new InvalidArgumentError("options.operator must to be a case insensitive string equal to 'OR' or 'AND'"); + } + return { + ...finalOptions, + operator: options.operator.toUpperCase() + }; + } + return finalOptions; + } + function makeFilterCalls(parameterName) { + return (parameterValue, logs) => { + if (typeof parameterValue === "string" || parameterValue == null) { + return logs.filter((log) => { + return log[parameterName] === parameterValue; + }); + } + if (parameterValue instanceof RegExp) { + return logs.filter((log) => { + return parameterValue.test(log[parameterName]); + }); + } + throw new InvalidArgumentError(`${parameterName} parameter should be one of string, regexp, undefined or null`); + }; + } + function computeUrlWithMaybeSearchParameters(requestInit) { + try { + const url2 = new URL(requestInit.path, requestInit.origin); + if (url2.search.length !== 0) { + return url2; + } + url2.search = new URLSearchParams(requestInit.query).toString(); + return url2; + } catch (error3) { + throw new InvalidArgumentError("An error occurred when computing MockCallHistoryLog.url", { cause: error3 }); + } + } + var MockCallHistoryLog = class { + constructor(requestInit = {}) { + this.body = requestInit.body; + this.headers = requestInit.headers; + this.method = requestInit.method; + const url2 = computeUrlWithMaybeSearchParameters(requestInit); + this.fullUrl = url2.toString(); + this.origin = url2.origin; + this.path = url2.pathname; + this.searchParams = Object.fromEntries(url2.searchParams); + this.protocol = url2.protocol; + this.host = url2.host; + this.port = url2.port; + this.hash = url2.hash; + } + toMap() { + return /* @__PURE__ */ new Map( + [ + ["protocol", this.protocol], + ["host", this.host], + ["port", this.port], + ["origin", this.origin], + ["path", this.path], + ["hash", this.hash], + ["searchParams", this.searchParams], + ["fullUrl", this.fullUrl], + ["method", this.method], + ["body", this.body], + ["headers", this.headers] + ] + ); + } + toString() { + const options = { betweenKeyValueSeparator: "->", betweenPairSeparator: "|" }; + let result = ""; + this.toMap().forEach((value, key) => { + if (typeof value === "string" || value === void 0 || value === null) { + result = `${result}${key}${options.betweenKeyValueSeparator}${value}${options.betweenPairSeparator}`; + } + if (typeof value === "object" && value !== null || Array.isArray(value)) { + result = `${result}${key}${options.betweenKeyValueSeparator}${JSON.stringify(value)}${options.betweenPairSeparator}`; + } + }); + return result.slice(0, -1); + } + }; + var MockCallHistory = class { + logs = []; + calls() { + return this.logs; + } + firstCall() { + return this.logs.at(0); + } + lastCall() { + return this.logs.at(-1); + } + nthCall(number2) { + if (typeof number2 !== "number") { + throw new InvalidArgumentError("nthCall must be called with a number"); + } + if (!Number.isInteger(number2)) { + throw new InvalidArgumentError("nthCall must be called with an integer"); + } + if (Math.sign(number2) !== 1) { + throw new InvalidArgumentError("nthCall must be called with a positive value. use firstCall or lastCall instead"); + } + return this.logs.at(number2 - 1); + } + filterCalls(criteria, options) { + if (this.logs.length === 0) { + return this.logs; + } + if (typeof criteria === "function") { + return this.logs.filter(criteria); + } + if (criteria instanceof RegExp) { + return this.logs.filter((log) => { + return criteria.test(log.toString()); + }); + } + if (typeof criteria === "object" && criteria !== null) { + if (Object.keys(criteria).length === 0) { + return this.logs; + } + const finalOptions = { operator: "OR", ...buildAndValidateFilterCallsOptions(options) }; + let maybeDuplicatedLogsFiltered = finalOptions.operator === "AND" ? this.logs : []; + if ("protocol" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.protocol, finalOptions, this.filterCallsByProtocol, maybeDuplicatedLogsFiltered, this.logs); + } + if ("host" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.host, finalOptions, this.filterCallsByHost, maybeDuplicatedLogsFiltered, this.logs); + } + if ("port" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.port, finalOptions, this.filterCallsByPort, maybeDuplicatedLogsFiltered, this.logs); + } + if ("origin" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.origin, finalOptions, this.filterCallsByOrigin, maybeDuplicatedLogsFiltered, this.logs); + } + if ("path" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.path, finalOptions, this.filterCallsByPath, maybeDuplicatedLogsFiltered, this.logs); + } + if ("hash" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.hash, finalOptions, this.filterCallsByHash, maybeDuplicatedLogsFiltered, this.logs); + } + if ("fullUrl" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.fullUrl, finalOptions, this.filterCallsByFullUrl, maybeDuplicatedLogsFiltered, this.logs); + } + if ("method" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.method, finalOptions, this.filterCallsByMethod, maybeDuplicatedLogsFiltered, this.logs); + } + const uniqLogsFiltered = [...new Set(maybeDuplicatedLogsFiltered)]; + return uniqLogsFiltered; + } + throw new InvalidArgumentError("criteria parameter should be one of function, regexp, or object"); + } + filterCallsByProtocol = makeFilterCalls.call(this, "protocol"); + filterCallsByHost = makeFilterCalls.call(this, "host"); + filterCallsByPort = makeFilterCalls.call(this, "port"); + filterCallsByOrigin = makeFilterCalls.call(this, "origin"); + filterCallsByPath = makeFilterCalls.call(this, "path"); + filterCallsByHash = makeFilterCalls.call(this, "hash"); + filterCallsByFullUrl = makeFilterCalls.call(this, "fullUrl"); + filterCallsByMethod = makeFilterCalls.call(this, "method"); + clear() { + this.logs = []; + } + [kMockCallHistoryAddLog](requestInit) { + const log = new MockCallHistoryLog(requestInit); + this.logs.push(log); + return log; + } + *[Symbol.iterator]() { + for (const log of this.calls()) { + yield log; + } + } + }; + module2.exports.MockCallHistory = MockCallHistory; + module2.exports.MockCallHistoryLog = MockCallHistoryLog; + } +}); + // node_modules/undici/lib/mock/mock-pool.js var require_mock_pool = __commonJS({ "node_modules/undici/lib/mock/mock-pool.js"(exports2, module2) { @@ -11335,19 +14089,21 @@ var require_mock_pool = __commonJS({ kOriginalClose, kOrigin, kOriginalDispatch, - kConnected + kConnected, + kIgnoreTrailingSlash } = require_mock_symbols(); var { MockInterceptor } = require_mock_interceptor(); var Symbols = require_symbols(); var { InvalidArgumentError } = require_errors(); var MockPool = class extends Pool { constructor(origin, opts) { - super(origin, opts); if (!opts || !opts.agent || typeof opts.agent.dispatch !== "function") { throw new InvalidArgumentError("Argument opts.agent must implement Agent"); } + super(origin, opts); this[kMockAgent] = opts.agent; this[kOrigin] = origin; + this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false; this[kDispatches] = []; this[kConnected] = 1; this[kOriginalDispatch] = this.dispatch; @@ -11362,7 +14118,13 @@ var require_mock_pool = __commonJS({ * Sets up the base interceptor for mocking replies from undici. */ intercept(opts) { - return new MockInterceptor(opts, this[kDispatches]); + return new MockInterceptor( + opts && { ignoreTrailingSlash: this[kIgnoreTrailingSlash], ...opts }, + this[kDispatches] + ); + } + cleanMocks() { + this[kDispatches] = []; } async [kClose]() { await promisify(this[kOriginalClose])(); @@ -11374,37 +14136,6 @@ var require_mock_pool = __commonJS({ } }); -// node_modules/undici/lib/mock/pluralizer.js -var require_pluralizer = __commonJS({ - "node_modules/undici/lib/mock/pluralizer.js"(exports2, module2) { - "use strict"; - var singulars = { - pronoun: "it", - is: "is", - was: "was", - this: "this" - }; - var plurals = { - pronoun: "they", - is: "are", - was: "were", - this: "these" - }; - module2.exports = class Pluralizer { - constructor(singular, plural) { - this.singular = singular; - this.plural = plural; - } - pluralize(count) { - const one = count === 1; - const keys = one ? singulars : plurals; - const noun = one ? this.singular : this.plural; - return { ...keys, count, noun }; - } - }; - } -}); - // node_modules/undici/lib/mock/pending-interceptors-formatter.js var require_pending_interceptors_formatter = __commonJS({ "node_modules/undici/lib/mock/pending-interceptors-formatter.js"(exports2, module2) { @@ -11461,626 +14192,5408 @@ var require_mock_agent = __commonJS({ kNetConnect, kGetNetConnect, kOptions, - kFactory + kFactory, + kMockAgentRegisterCallHistory, + kMockAgentIsCallHistoryEnabled, + kMockAgentAddCallHistoryLog, + kMockAgentMockCallHistoryInstance, + kMockAgentAcceptsNonStandardSearchParameters, + kMockCallHistoryAddLog, + kIgnoreTrailingSlash } = require_mock_symbols(); var MockClient = require_mock_client(); var MockPool = require_mock_pool(); - var { matchValue, buildMockOptions } = require_mock_utils(); + var { matchValue, normalizeSearchParams, buildAndValidateMockOptions, normalizeOrigin } = require_mock_utils(); var { InvalidArgumentError, UndiciError } = require_errors(); var Dispatcher = require_dispatcher(); - var Pluralizer = require_pluralizer(); var PendingInterceptorsFormatter = require_pending_interceptors_formatter(); + var { MockCallHistory } = require_mock_call_history(); var MockAgent = class extends Dispatcher { - constructor(opts) { + constructor(opts = {}) { super(opts); + const mockOptions = buildAndValidateMockOptions(opts); this[kNetConnect] = true; this[kIsMockActive] = true; + this[kMockAgentIsCallHistoryEnabled] = mockOptions.enableCallHistory ?? false; + this[kMockAgentAcceptsNonStandardSearchParameters] = mockOptions.acceptNonStandardSearchParameters ?? false; + this[kIgnoreTrailingSlash] = mockOptions.ignoreTrailingSlash ?? false; if (opts?.agent && typeof opts.agent.dispatch !== "function") { throw new InvalidArgumentError("Argument opts.agent must implement Agent"); } const agent = opts?.agent ? opts.agent : new Agent(opts); this[kAgent] = agent; this[kClients] = agent[kClients]; - this[kOptions] = buildMockOptions(opts); + this[kOptions] = mockOptions; + if (this[kMockAgentIsCallHistoryEnabled]) { + this[kMockAgentRegisterCallHistory](); + } } get(origin) { - let dispatcher = this[kMockAgentGet](origin); + const normalizedOrigin = normalizeOrigin(origin); + const originKey = this[kIgnoreTrailingSlash] ? normalizedOrigin.replace(/\/$/, "") : normalizedOrigin; + let dispatcher = this[kMockAgentGet](originKey); if (!dispatcher) { - dispatcher = this[kFactory](origin); + dispatcher = this[kFactory](originKey); + this[kMockAgentSet](originKey, dispatcher); + } + return dispatcher; + } + dispatch(opts, handler2) { + opts.origin = normalizeOrigin(opts.origin); + this.get(opts.origin); + this[kMockAgentAddCallHistoryLog](opts); + const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters]; + const dispatchOpts = { ...opts }; + if (acceptNonStandardSearchParameters && dispatchOpts.path) { + const [path30, searchParams] = dispatchOpts.path.split("?"); + const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters); + dispatchOpts.path = `${path30}?${normalizedSearchParams}`; + } + return this[kAgent].dispatch(dispatchOpts, handler2); + } + async close() { + this.clearCallHistory(); + await this[kAgent].close(); + this[kClients].clear(); + } + deactivate() { + this[kIsMockActive] = false; + } + activate() { + this[kIsMockActive] = true; + } + enableNetConnect(matcher) { + if (typeof matcher === "string" || typeof matcher === "function" || matcher instanceof RegExp) { + if (Array.isArray(this[kNetConnect])) { + this[kNetConnect].push(matcher); + } else { + this[kNetConnect] = [matcher]; + } + } else if (typeof matcher === "undefined") { + this[kNetConnect] = true; + } else { + throw new InvalidArgumentError("Unsupported matcher. Must be one of String|Function|RegExp."); + } + } + disableNetConnect() { + this[kNetConnect] = false; + } + enableCallHistory() { + this[kMockAgentIsCallHistoryEnabled] = true; + return this; + } + disableCallHistory() { + this[kMockAgentIsCallHistoryEnabled] = false; + return this; + } + getCallHistory() { + return this[kMockAgentMockCallHistoryInstance]; + } + clearCallHistory() { + if (this[kMockAgentMockCallHistoryInstance] !== void 0) { + this[kMockAgentMockCallHistoryInstance].clear(); + } + } + // This is required to bypass issues caused by using global symbols - see: + // https://github.com/nodejs/undici/issues/1447 + get isMockActive() { + return this[kIsMockActive]; + } + [kMockAgentRegisterCallHistory]() { + if (this[kMockAgentMockCallHistoryInstance] === void 0) { + this[kMockAgentMockCallHistoryInstance] = new MockCallHistory(); + } + } + [kMockAgentAddCallHistoryLog](opts) { + if (this[kMockAgentIsCallHistoryEnabled]) { + this[kMockAgentRegisterCallHistory](); + this[kMockAgentMockCallHistoryInstance][kMockCallHistoryAddLog](opts); + } + } + [kMockAgentSet](origin, dispatcher) { + this[kClients].set(origin, { count: 0, dispatcher }); + } + [kFactory](origin) { + const mockOptions = Object.assign({ agent: this }, this[kOptions]); + return this[kOptions] && this[kOptions].connections === 1 ? new MockClient(origin, mockOptions) : new MockPool(origin, mockOptions); + } + [kMockAgentGet](origin) { + const result = this[kClients].get(origin); + if (result?.dispatcher) { + return result.dispatcher; + } + if (typeof origin !== "string") { + const dispatcher = this[kFactory]("http://localhost:9999"); this[kMockAgentSet](origin, dispatcher); + return dispatcher; + } + for (const [keyMatcher, result2] of Array.from(this[kClients])) { + if (result2 && typeof keyMatcher !== "string" && matchValue(keyMatcher, origin)) { + const dispatcher = this[kFactory](origin); + this[kMockAgentSet](origin, dispatcher); + dispatcher[kDispatches] = result2.dispatcher[kDispatches]; + return dispatcher; + } + } + } + [kGetNetConnect]() { + return this[kNetConnect]; + } + pendingInterceptors() { + const mockAgentClients = this[kClients]; + return Array.from(mockAgentClients.entries()).flatMap(([origin, result]) => result.dispatcher[kDispatches].map((dispatch) => ({ ...dispatch, origin }))).filter(({ pending }) => pending); + } + assertNoPendingInterceptors({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) { + const pending = this.pendingInterceptors(); + if (pending.length === 0) { + return; + } + throw new UndiciError( + pending.length === 1 ? `1 interceptor is pending: + +${pendingInterceptorsFormatter.format(pending)}`.trim() : `${pending.length} interceptors are pending: + +${pendingInterceptorsFormatter.format(pending)}`.trim() + ); + } + }; + module2.exports = MockAgent; + } +}); + +// node_modules/undici/lib/mock/snapshot-utils.js +var require_snapshot_utils = __commonJS({ + "node_modules/undici/lib/mock/snapshot-utils.js"(exports2, module2) { + "use strict"; + var { InvalidArgumentError } = require_errors(); + var { runtimeFeatures } = require_runtime_features(); + function createHeaderFilters(matchOptions = {}) { + const { ignoreHeaders = [], excludeHeaders = [], matchHeaders = [], caseSensitive = false } = matchOptions; + return { + ignore: new Set(ignoreHeaders.map((header) => caseSensitive ? header : header.toLowerCase())), + exclude: new Set(excludeHeaders.map((header) => caseSensitive ? header : header.toLowerCase())), + match: new Set(matchHeaders.map((header) => caseSensitive ? header : header.toLowerCase())) + }; + } + var crypto3 = runtimeFeatures.has("crypto") ? require("node:crypto") : null; + var hashId = crypto3?.hash ? (value) => crypto3.hash("sha256", value, "base64url") : (value) => Buffer.from(value).toString("base64url"); + function isUndiciHeaders(headers) { + return Array.isArray(headers) && (headers.length & 1) === 0; + } + function isUrlExcludedFactory(excludePatterns = []) { + if (excludePatterns.length === 0) { + return () => false; + } + return function isUrlExcluded(url2) { + let urlLowerCased; + for (const pattern of excludePatterns) { + if (typeof pattern === "string") { + if (!urlLowerCased) { + urlLowerCased = url2.toLowerCase(); + } + if (urlLowerCased.includes(pattern.toLowerCase())) { + return true; + } + } else if (pattern instanceof RegExp) { + if (pattern.test(url2)) { + return true; + } + } + } + return false; + }; + } + function normalizeHeaders(headers) { + const normalizedHeaders = {}; + if (!headers) return normalizedHeaders; + if (isUndiciHeaders(headers)) { + for (let i = 0; i < headers.length; i += 2) { + const key = headers[i]; + const value = headers[i + 1]; + if (key && value !== void 0) { + const keyStr = Buffer.isBuffer(key) ? key.toString() : key; + const valueStr = Buffer.isBuffer(value) ? value.toString() : value; + normalizedHeaders[keyStr.toLowerCase()] = valueStr; + } + } + return normalizedHeaders; + } + if (headers && typeof headers === "object") { + for (const [key, value] of Object.entries(headers)) { + if (key && typeof key === "string") { + normalizedHeaders[key.toLowerCase()] = Array.isArray(value) ? value.join(", ") : String(value); + } + } + } + return normalizedHeaders; + } + var validSnapshotModes = ( + /** @type {const} */ + ["record", "playback", "update"] + ); + function validateSnapshotMode(mode) { + if (!validSnapshotModes.includes(mode)) { + throw new InvalidArgumentError(`Invalid snapshot mode: ${mode}. Must be one of: ${validSnapshotModes.join(", ")}`); + } + } + module2.exports = { + createHeaderFilters, + hashId, + isUndiciHeaders, + normalizeHeaders, + isUrlExcludedFactory, + validateSnapshotMode + }; + } +}); + +// node_modules/undici/lib/mock/snapshot-recorder.js +var require_snapshot_recorder = __commonJS({ + "node_modules/undici/lib/mock/snapshot-recorder.js"(exports2, module2) { + "use strict"; + var { writeFile, readFile, mkdir } = require("node:fs/promises"); + var { dirname: dirname6, resolve: resolve15 } = require("node:path"); + var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = require("node:timers"); + var { InvalidArgumentError, UndiciError } = require_errors(); + var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils(); + function formatRequestKey(opts, headerFilters, matchOptions = {}) { + const url2 = new URL(opts.path, opts.origin); + const normalized = opts._normalizedHeaders || normalizeHeaders(opts.headers); + if (!opts._normalizedHeaders) { + opts._normalizedHeaders = normalized; + } + return { + method: opts.method || "GET", + url: matchOptions.matchQuery !== false ? url2.toString() : `${url2.origin}${url2.pathname}`, + headers: filterHeadersForMatching(normalized, headerFilters, matchOptions), + body: matchOptions.matchBody !== false && opts.body ? String(opts.body) : "" + }; + } + function filterHeadersForMatching(headers, headerFilters, matchOptions = {}) { + if (!headers || typeof headers !== "object") return {}; + const { + caseSensitive = false + } = matchOptions; + const filtered = {}; + const { ignore, exclude, match: match2 } = headerFilters; + for (const [key, value] of Object.entries(headers)) { + const headerKey = caseSensitive ? key : key.toLowerCase(); + if (exclude.has(headerKey)) continue; + if (ignore.has(headerKey)) continue; + if (match2.size !== 0) { + if (!match2.has(headerKey)) continue; + } + filtered[headerKey] = value; + } + return filtered; + } + function filterHeadersForStorage(headers, headerFilters, matchOptions = {}) { + if (!headers || typeof headers !== "object") return {}; + const { + caseSensitive = false + } = matchOptions; + const filtered = {}; + const { exclude: excludeSet } = headerFilters; + for (const [key, value] of Object.entries(headers)) { + const headerKey = caseSensitive ? key : key.toLowerCase(); + if (excludeSet.has(headerKey)) continue; + filtered[headerKey] = value; + } + return filtered; + } + function createRequestHash(formattedRequest) { + const parts = [ + formattedRequest.method, + formattedRequest.url + ]; + if (formattedRequest.headers && typeof formattedRequest.headers === "object") { + const headerKeys = Object.keys(formattedRequest.headers).sort(); + for (const key of headerKeys) { + const values = Array.isArray(formattedRequest.headers[key]) ? formattedRequest.headers[key] : [formattedRequest.headers[key]]; + parts.push(key); + for (const value of values.sort()) { + parts.push(String(value)); + } + } + } + parts.push(formattedRequest.body); + const content = parts.join("|"); + return hashId(content); + } + var SnapshotRecorder = class { + /** @type {NodeJS.Timeout | null} */ + #flushTimeout; + /** @type {import('./snapshot-utils').IsUrlExcluded} */ + #isUrlExcluded; + /** @type {Map} */ + #snapshots = /* @__PURE__ */ new Map(); + /** @type {string|undefined} */ + #snapshotPath; + /** @type {number} */ + #maxSnapshots = Infinity; + /** @type {boolean} */ + #autoFlush = false; + /** @type {import('./snapshot-utils').HeaderFilters} */ + #headerFilters; + /** + * Creates a new SnapshotRecorder instance + * @param {SnapshotRecorderOptions&SnapshotRecorderMatchOptions} [options={}] - Configuration options for the recorder + */ + constructor(options = {}) { + this.#snapshotPath = options.snapshotPath; + this.#maxSnapshots = options.maxSnapshots || Infinity; + this.#autoFlush = options.autoFlush || false; + this.flushInterval = options.flushInterval || 3e4; + this._flushTimer = null; + this.matchOptions = { + matchHeaders: options.matchHeaders || [], + // empty means match all headers + ignoreHeaders: options.ignoreHeaders || [], + excludeHeaders: options.excludeHeaders || [], + matchBody: options.matchBody !== false, + // default: true + matchQuery: options.matchQuery !== false, + // default: true + caseSensitive: options.caseSensitive || false + }; + this.#headerFilters = createHeaderFilters(this.matchOptions); + this.shouldRecord = options.shouldRecord || (() => true); + this.shouldPlayback = options.shouldPlayback || (() => true); + this.#isUrlExcluded = isUrlExcludedFactory(options.excludeUrls); + if (this.#autoFlush && this.#snapshotPath) { + this.#startAutoFlush(); + } + } + /** + * Records a request-response interaction + * @param {SnapshotRequestOptions} requestOpts - Request options + * @param {SnapshotEntryResponse} response - Response data to record + * @return {Promise} - Resolves when the recording is complete + */ + async record(requestOpts, response) { + if (!this.shouldRecord(requestOpts)) { + return; + } + if (this.isUrlExcluded(requestOpts)) { + return; + } + const request3 = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions); + const hash2 = createRequestHash(request3); + const normalizedHeaders = normalizeHeaders(response.headers); + const responseData = { + statusCode: response.statusCode, + headers: filterHeadersForStorage(normalizedHeaders, this.#headerFilters, this.matchOptions), + body: Buffer.isBuffer(response.body) ? response.body.toString("base64") : Buffer.from(String(response.body || "")).toString("base64"), + trailers: response.trailers + }; + if (this.#snapshots.size >= this.#maxSnapshots && !this.#snapshots.has(hash2)) { + const oldestKey = this.#snapshots.keys().next().value; + this.#snapshots.delete(oldestKey); + } + const existingSnapshot = this.#snapshots.get(hash2); + if (existingSnapshot && existingSnapshot.responses) { + existingSnapshot.responses.push(responseData); + existingSnapshot.timestamp = (/* @__PURE__ */ new Date()).toISOString(); + } else { + this.#snapshots.set(hash2, { + request: request3, + responses: [responseData], + // Always store as array for consistency + callCount: 0, + timestamp: (/* @__PURE__ */ new Date()).toISOString() + }); + } + if (this.#autoFlush && this.#snapshotPath) { + this.#scheduleFlush(); + } + } + /** + * Checks if a URL should be excluded from recording/playback + * @param {SnapshotRequestOptions} requestOpts - Request options to check + * @returns {boolean} - True if URL is excluded + */ + isUrlExcluded(requestOpts) { + const url2 = new URL(requestOpts.path, requestOpts.origin).toString(); + return this.#isUrlExcluded(url2); + } + /** + * Finds a matching snapshot for the given request + * Returns the appropriate response based on call count for sequential responses + * + * @param {SnapshotRequestOptions} requestOpts - Request options to match + * @returns {SnapshotEntry&Record<'response', SnapshotEntryResponse>|undefined} - Matching snapshot response or undefined if not found + */ + findSnapshot(requestOpts) { + if (!this.shouldPlayback(requestOpts)) { + return void 0; + } + if (this.isUrlExcluded(requestOpts)) { + return void 0; + } + const request3 = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions); + const hash2 = createRequestHash(request3); + const snapshot = this.#snapshots.get(hash2); + if (!snapshot) return void 0; + const currentCallCount = snapshot.callCount || 0; + const responseIndex = Math.min(currentCallCount, snapshot.responses.length - 1); + snapshot.callCount = currentCallCount + 1; + return { + ...snapshot, + response: snapshot.responses[responseIndex] + }; + } + /** + * Loads snapshots from file + * @param {string} [filePath] - Optional file path to load snapshots from + * @return {Promise} - Resolves when snapshots are loaded + */ + async loadSnapshots(filePath) { + const path30 = filePath || this.#snapshotPath; + if (!path30) { + throw new InvalidArgumentError("Snapshot path is required"); + } + try { + const data = await readFile(resolve15(path30), "utf8"); + const parsed = JSON.parse(data); + if (Array.isArray(parsed)) { + this.#snapshots.clear(); + for (const { hash: hash2, snapshot } of parsed) { + this.#snapshots.set(hash2, snapshot); + } + } else { + this.#snapshots = new Map(Object.entries(parsed)); + } + } catch (error3) { + if (error3.code === "ENOENT") { + this.#snapshots.clear(); + } else { + throw new UndiciError(`Failed to load snapshots from ${path30}`, { cause: error3 }); + } + } + } + /** + * Saves snapshots to file + * + * @param {string} [filePath] - Optional file path to save snapshots + * @returns {Promise} - Resolves when snapshots are saved + */ + async saveSnapshots(filePath) { + const path30 = filePath || this.#snapshotPath; + if (!path30) { + throw new InvalidArgumentError("Snapshot path is required"); + } + const resolvedPath = resolve15(path30); + await mkdir(dirname6(resolvedPath), { recursive: true }); + const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({ + hash: hash2, + snapshot + })); + await writeFile(resolvedPath, JSON.stringify(data, null, 2), { flush: true }); + } + /** + * Clears all recorded snapshots + * @returns {void} + */ + clear() { + this.#snapshots.clear(); + } + /** + * Gets all recorded snapshots + * @return {Array} - Array of all recorded snapshots + */ + getSnapshots() { + return Array.from(this.#snapshots.values()); + } + /** + * Gets snapshot count + * @return {number} - Number of recorded snapshots + */ + size() { + return this.#snapshots.size; + } + /** + * Resets call counts for all snapshots (useful for test cleanup) + * @returns {void} + */ + resetCallCounts() { + for (const snapshot of this.#snapshots.values()) { + snapshot.callCount = 0; + } + } + /** + * Deletes a specific snapshot by request options + * @param {SnapshotRequestOptions} requestOpts - Request options to match + * @returns {boolean} - True if snapshot was deleted, false if not found + */ + deleteSnapshot(requestOpts) { + const request3 = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions); + const hash2 = createRequestHash(request3); + return this.#snapshots.delete(hash2); + } + /** + * Gets information about a specific snapshot + * @param {SnapshotRequestOptions} requestOpts - Request options to match + * @returns {SnapshotInfo|null} - Snapshot information or null if not found + */ + getSnapshotInfo(requestOpts) { + const request3 = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions); + const hash2 = createRequestHash(request3); + const snapshot = this.#snapshots.get(hash2); + if (!snapshot) return null; + return { + hash: hash2, + request: snapshot.request, + responseCount: snapshot.responses ? snapshot.responses.length : snapshot.response ? 1 : 0, + // .response for legacy snapshots + callCount: snapshot.callCount || 0, + timestamp: snapshot.timestamp + }; + } + /** + * Replaces all snapshots with new data (full replacement) + * @param {Array<{hash: string; snapshot: SnapshotEntry}>|Record} snapshotData - New snapshot data to replace existing ones + * @returns {void} + */ + replaceSnapshots(snapshotData) { + this.#snapshots.clear(); + if (Array.isArray(snapshotData)) { + for (const { hash: hash2, snapshot } of snapshotData) { + this.#snapshots.set(hash2, snapshot); + } + } else if (snapshotData && typeof snapshotData === "object") { + this.#snapshots = new Map(Object.entries(snapshotData)); + } + } + /** + * Starts the auto-flush timer + * @returns {void} + */ + #startAutoFlush() { + return this.#scheduleFlush(); + } + /** + * Stops the auto-flush timer + * @returns {void} + */ + #stopAutoFlush() { + if (this.#flushTimeout) { + clearTimeout2(this.#flushTimeout); + this.saveSnapshots().catch(() => { + }); + this.#flushTimeout = null; + } + } + /** + * Schedules a flush (debounced to avoid excessive writes) + */ + #scheduleFlush() { + this.#flushTimeout = setTimeout2(() => { + this.saveSnapshots().catch(() => { + }); + if (this.#autoFlush) { + this.#flushTimeout?.refresh(); + } else { + this.#flushTimeout = null; + } + }, 1e3); + } + /** + * Cleanup method to stop timers + * @returns {void} + */ + destroy() { + this.#stopAutoFlush(); + if (this.#flushTimeout) { + clearTimeout2(this.#flushTimeout); + this.#flushTimeout = null; + } + } + /** + * Async close method that saves all recordings and performs cleanup + * @returns {Promise} + */ + async close() { + if (this.#snapshotPath && this.#snapshots.size !== 0) { + await this.saveSnapshots(); + } + this.destroy(); + } + }; + module2.exports = { SnapshotRecorder, formatRequestKey, createRequestHash, filterHeadersForMatching, filterHeadersForStorage, createHeaderFilters }; + } +}); + +// node_modules/undici/lib/mock/snapshot-agent.js +var require_snapshot_agent = __commonJS({ + "node_modules/undici/lib/mock/snapshot-agent.js"(exports2, module2) { + "use strict"; + var Agent = require_agent(); + var MockAgent = require_mock_agent(); + var { SnapshotRecorder } = require_snapshot_recorder(); + var WrapHandler = require_wrap_handler(); + var { InvalidArgumentError, UndiciError } = require_errors(); + var { validateSnapshotMode } = require_snapshot_utils(); + var kSnapshotRecorder = /* @__PURE__ */ Symbol("kSnapshotRecorder"); + var kSnapshotMode = /* @__PURE__ */ Symbol("kSnapshotMode"); + var kSnapshotPath = /* @__PURE__ */ Symbol("kSnapshotPath"); + var kSnapshotLoaded = /* @__PURE__ */ Symbol("kSnapshotLoaded"); + var kRealAgent = /* @__PURE__ */ Symbol("kRealAgent"); + var warningEmitted = false; + var SnapshotAgent = class extends MockAgent { + constructor(opts = {}) { + if (!warningEmitted) { + process.emitWarning( + "SnapshotAgent is experimental and subject to change", + "ExperimentalWarning" + ); + warningEmitted = true; + } + const { + mode = "record", + snapshotPath = null, + ...mockAgentOpts + } = opts; + super(mockAgentOpts); + validateSnapshotMode(mode); + if ((mode === "playback" || mode === "update") && !snapshotPath) { + throw new InvalidArgumentError(`snapshotPath is required when mode is '${mode}'`); + } + this[kSnapshotMode] = mode; + this[kSnapshotPath] = snapshotPath; + this[kSnapshotRecorder] = new SnapshotRecorder({ + snapshotPath: this[kSnapshotPath], + mode: this[kSnapshotMode], + maxSnapshots: opts.maxSnapshots, + autoFlush: opts.autoFlush, + flushInterval: opts.flushInterval, + matchHeaders: opts.matchHeaders, + ignoreHeaders: opts.ignoreHeaders, + excludeHeaders: opts.excludeHeaders, + matchBody: opts.matchBody, + matchQuery: opts.matchQuery, + caseSensitive: opts.caseSensitive, + shouldRecord: opts.shouldRecord, + shouldPlayback: opts.shouldPlayback, + excludeUrls: opts.excludeUrls + }); + this[kSnapshotLoaded] = false; + if (this[kSnapshotMode] === "record" || this[kSnapshotMode] === "update" || this[kSnapshotMode] === "playback" && opts.excludeUrls && opts.excludeUrls.length > 0) { + this[kRealAgent] = new Agent(opts); + } + if ((this[kSnapshotMode] === "playback" || this[kSnapshotMode] === "update") && this[kSnapshotPath]) { + this.loadSnapshots().catch(() => { + }); + } + } + dispatch(opts, handler2) { + handler2 = WrapHandler.wrap(handler2); + const mode = this[kSnapshotMode]; + if (this[kSnapshotRecorder].isUrlExcluded(opts)) { + return this[kRealAgent].dispatch(opts, handler2); + } + if (mode === "playback" || mode === "update") { + if (!this[kSnapshotLoaded]) { + return this.#asyncDispatch(opts, handler2); + } + const snapshot = this[kSnapshotRecorder].findSnapshot(opts); + if (snapshot) { + return this.#replaySnapshot(snapshot, handler2); + } else if (mode === "update") { + return this.#recordAndReplay(opts, handler2); + } else { + const error3 = new UndiciError(`No snapshot found for ${opts.method || "GET"} ${opts.path}`); + if (handler2.onError) { + handler2.onError(error3); + return; + } + throw error3; + } + } else if (mode === "record") { + return this.#recordAndReplay(opts, handler2); + } + } + /** + * Async version of dispatch for when we need to load snapshots first + */ + async #asyncDispatch(opts, handler2) { + await this.loadSnapshots(); + return this.dispatch(opts, handler2); + } + /** + * Records a real request and replays the response + */ + #recordAndReplay(opts, handler2) { + const responseData = { + statusCode: null, + headers: {}, + trailers: {}, + body: [] + }; + const self2 = this; + const recordingHandler = { + onRequestStart(controller, context5) { + return handler2.onRequestStart(controller, { ...context5, history: this.history }); + }, + onRequestUpgrade(controller, statusCode, headers, socket) { + return handler2.onRequestUpgrade(controller, statusCode, headers, socket); + }, + onResponseStart(controller, statusCode, headers, statusMessage) { + responseData.statusCode = statusCode; + responseData.headers = headers; + return handler2.onResponseStart(controller, statusCode, headers, statusMessage); + }, + onResponseData(controller, chunk) { + responseData.body.push(chunk); + return handler2.onResponseData(controller, chunk); + }, + onResponseEnd(controller, trailers) { + responseData.trailers = trailers; + const responseBody = Buffer.concat(responseData.body); + self2[kSnapshotRecorder].record(opts, { + statusCode: responseData.statusCode, + headers: responseData.headers, + body: responseBody, + trailers: responseData.trailers + }).then(() => handler2.onResponseEnd(controller, trailers)).catch((error3) => handler2.onResponseError(controller, error3)); + } + }; + const agent = this[kRealAgent]; + return agent.dispatch(opts, recordingHandler); + } + /** + * Replays a recorded response + * + * @param {Object} snapshot - The recorded snapshot to replay. + * @param {Object} handler - The handler to call with the response data. + * @returns {void} + */ + #replaySnapshot(snapshot, handler2) { + try { + const { response } = snapshot; + const controller = { + pause() { + }, + resume() { + }, + abort(reason) { + this.aborted = true; + this.reason = reason; + }, + aborted: false, + paused: false + }; + handler2.onRequestStart(controller); + handler2.onResponseStart(controller, response.statusCode, response.headers); + const body = Buffer.from(response.body, "base64"); + handler2.onResponseData(controller, body); + handler2.onResponseEnd(controller, response.trailers); + } catch (error3) { + handler2.onError?.(error3); + } + } + /** + * Loads snapshots from file + * + * @param {string} [filePath] - Optional file path to load snapshots from. + * @returns {Promise} - Resolves when snapshots are loaded. + */ + async loadSnapshots(filePath) { + await this[kSnapshotRecorder].loadSnapshots(filePath || this[kSnapshotPath]); + this[kSnapshotLoaded] = true; + if (this[kSnapshotMode] === "playback") { + this.#setupMockInterceptors(); + } + } + /** + * Saves snapshots to file + * + * @param {string} [filePath] - Optional file path to save snapshots to. + * @returns {Promise} - Resolves when snapshots are saved. + */ + async saveSnapshots(filePath) { + return this[kSnapshotRecorder].saveSnapshots(filePath || this[kSnapshotPath]); + } + /** + * Sets up MockAgent interceptors based on recorded snapshots. + * + * This method creates MockAgent interceptors for each recorded snapshot, + * allowing the SnapshotAgent to fall back to MockAgent's standard intercept + * mechanism in playback mode. Each interceptor is configured to persist + * (remain active for multiple requests) and responds with the recorded + * response data. + * + * Called automatically when loading snapshots in playback mode. + * + * @returns {void} + */ + #setupMockInterceptors() { + for (const snapshot of this[kSnapshotRecorder].getSnapshots()) { + const { request: request3, responses, response } = snapshot; + const url2 = new URL(request3.url); + const mockPool = this.get(url2.origin); + const responseData = responses ? responses[0] : response; + if (!responseData) continue; + mockPool.intercept({ + path: url2.pathname + url2.search, + method: request3.method, + headers: request3.headers, + body: request3.body + }).reply(responseData.statusCode, responseData.body, { + headers: responseData.headers, + trailers: responseData.trailers + }).persist(); + } + } + /** + * Gets the snapshot recorder + * @return {SnapshotRecorder} - The snapshot recorder instance + */ + getRecorder() { + return this[kSnapshotRecorder]; + } + /** + * Gets the current mode + * @return {import('./snapshot-utils').SnapshotMode} - The current snapshot mode + */ + getMode() { + return this[kSnapshotMode]; + } + /** + * Clears all snapshots + * @returns {void} + */ + clearSnapshots() { + this[kSnapshotRecorder].clear(); + } + /** + * Resets call counts for all snapshots (useful for test cleanup) + * @returns {void} + */ + resetCallCounts() { + this[kSnapshotRecorder].resetCallCounts(); + } + /** + * Deletes a specific snapshot by request options + * @param {import('./snapshot-recorder').SnapshotRequestOptions} requestOpts - Request options to identify the snapshot + * @return {Promise} - Returns true if the snapshot was deleted, false if not found + */ + deleteSnapshot(requestOpts) { + return this[kSnapshotRecorder].deleteSnapshot(requestOpts); + } + /** + * Gets information about a specific snapshot + * @returns {import('./snapshot-recorder').SnapshotInfo|null} - Snapshot information or null if not found + */ + getSnapshotInfo(requestOpts) { + return this[kSnapshotRecorder].getSnapshotInfo(requestOpts); + } + /** + * Replaces all snapshots with new data (full replacement) + * @param {Array<{hash: string; snapshot: import('./snapshot-recorder').SnapshotEntryshotEntry}>|Record} snapshotData - New snapshot data to replace existing snapshots + * @returns {void} + */ + replaceSnapshots(snapshotData) { + this[kSnapshotRecorder].replaceSnapshots(snapshotData); + } + /** + * Closes the agent, saving snapshots and cleaning up resources. + * + * @returns {Promise} + */ + async close() { + await this[kSnapshotRecorder].close(); + await this[kRealAgent]?.close(); + await super.close(); + } + }; + module2.exports = SnapshotAgent; + } +}); + +// node_modules/undici/lib/global.js +var require_global2 = __commonJS({ + "node_modules/undici/lib/global.js"(exports2, module2) { + "use strict"; + var globalDispatcher = /* @__PURE__ */ Symbol.for("undici.globalDispatcher.2"); + var legacyGlobalDispatcher = /* @__PURE__ */ Symbol.for("undici.globalDispatcher.1"); + var { InvalidArgumentError } = require_errors(); + var Agent = require_agent(); + if (getGlobalDispatcher() === void 0) { + setGlobalDispatcher(new Agent()); + } + function setGlobalDispatcher(agent) { + if (!agent || typeof agent.dispatch !== "function") { + throw new InvalidArgumentError("Argument agent must implement Agent"); + } + Object.defineProperty(globalThis, globalDispatcher, { + value: agent, + writable: true, + enumerable: false, + configurable: false + }); + Object.defineProperty(globalThis, legacyGlobalDispatcher, { + value: agent, + writable: true, + enumerable: false, + configurable: false + }); + } + function getGlobalDispatcher() { + return globalThis[legacyGlobalDispatcher]; + } + var installedExports = ( + /** @type {const} */ + [ + "fetch", + "Headers", + "Response", + "Request", + "FormData", + "WebSocket", + "CloseEvent", + "ErrorEvent", + "MessageEvent", + "EventSource" + ] + ); + module2.exports = { + setGlobalDispatcher, + getGlobalDispatcher, + installedExports + }; + } +}); + +// node_modules/undici/lib/handler/decorator-handler.js +var require_decorator_handler = __commonJS({ + "node_modules/undici/lib/handler/decorator-handler.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var WrapHandler = require_wrap_handler(); + module2.exports = class DecoratorHandler { + #handler; + #onCompleteCalled = false; + #onErrorCalled = false; + #onResponseStartCalled = false; + constructor(handler2) { + if (typeof handler2 !== "object" || handler2 === null) { + throw new TypeError("handler must be an object"); + } + this.#handler = WrapHandler.wrap(handler2); + } + onRequestStart(...args) { + this.#handler.onRequestStart?.(...args); + } + onRequestUpgrade(...args) { + assert(!this.#onCompleteCalled); + assert(!this.#onErrorCalled); + return this.#handler.onRequestUpgrade?.(...args); + } + onResponseStart(...args) { + assert(!this.#onCompleteCalled); + assert(!this.#onErrorCalled); + assert(!this.#onResponseStartCalled); + this.#onResponseStartCalled = true; + return this.#handler.onResponseStart?.(...args); + } + onResponseData(...args) { + assert(!this.#onCompleteCalled); + assert(!this.#onErrorCalled); + return this.#handler.onResponseData?.(...args); + } + onResponseEnd(...args) { + assert(!this.#onCompleteCalled); + assert(!this.#onErrorCalled); + this.#onCompleteCalled = true; + return this.#handler.onResponseEnd?.(...args); + } + onResponseError(...args) { + this.#onErrorCalled = true; + return this.#handler.onResponseError?.(...args); + } + /** + * @deprecated + */ + onBodySent() { + } + }; + } +}); + +// node_modules/undici/lib/handler/redirect-handler.js +var require_redirect_handler = __commonJS({ + "node_modules/undici/lib/handler/redirect-handler.js"(exports2, module2) { + "use strict"; + var util4 = require_util(); + var { kBodyUsed, kRedirectCacheControl } = require_symbols(); + var assert = require("node:assert"); + var { InvalidArgumentError } = require_errors(); + var EE = require("node:events"); + var redirectableStatusCodes = [300, 301, 302, 303, 307, 308]; + var kBody = /* @__PURE__ */ Symbol("body"); + var noop3 = () => { + }; + var BodyAsyncIterable = class { + constructor(body) { + this[kBody] = body; + this[kBodyUsed] = false; + } + async *[Symbol.asyncIterator]() { + assert(!this[kBodyUsed], "disturbed"); + this[kBodyUsed] = true; + yield* this[kBody]; + } + }; + var RedirectHandler = class _RedirectHandler { + static buildDispatch(dispatcher, maxRedirections) { + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError("maxRedirections must be a positive number"); + } + const dispatch = dispatcher.dispatch.bind(dispatcher); + return (opts, originalHandler) => dispatch(opts, new _RedirectHandler(dispatch, maxRedirections, opts, originalHandler)); + } + constructor(dispatch, maxRedirections, opts, handler2) { + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError("maxRedirections must be a positive number"); + } + this.dispatch = dispatch; + this.location = null; + const { maxRedirections: _2, ...cleanOpts } = opts; + this.opts = cleanOpts; + this.maxRedirections = maxRedirections; + this.handler = handler2; + this.history = []; + Object.defineProperty(this.history, kRedirectCacheControl, { + value: [], + enumerable: false + }); + if (util4.isStream(this.opts.body)) { + if (util4.bodyLength(this.opts.body) === 0) { + this.opts.body.on("data", function() { + assert(false); + }); + } + if (typeof this.opts.body.readableDidRead !== "boolean") { + this.opts.body[kBodyUsed] = false; + EE.prototype.on.call(this.opts.body, "data", function() { + this[kBodyUsed] = true; + }); + } + } else if (this.opts.body && typeof this.opts.body.pipeTo === "function") { + this.opts.body = new BodyAsyncIterable(this.opts.body); + } else if (this.opts.body && typeof this.opts.body !== "string" && !ArrayBuffer.isView(this.opts.body) && util4.isIterable(this.opts.body) && !util4.isFormDataLike(this.opts.body)) { + this.opts.body = new BodyAsyncIterable(this.opts.body); + } + } + onRequestStart(controller, context5) { + this.handler.onRequestStart?.(controller, { ...context5, history: this.history }); + } + onRequestUpgrade(controller, statusCode, headers, socket) { + this.handler.onRequestUpgrade?.(controller, statusCode, headers, socket); + } + onResponseStart(controller, statusCode, headers, statusMessage) { + if (this.opts.throwOnMaxRedirect && this.history.length >= this.maxRedirections) { + throw new Error("max redirects"); + } + if ((statusCode === 301 || statusCode === 302) && this.opts.method === "POST") { + this.opts.method = "GET"; + if (util4.isStream(this.opts.body)) { + util4.destroy(this.opts.body.on("error", noop3)); + } + this.opts.body = null; + } + if (statusCode === 303 && this.opts.method !== "HEAD") { + this.opts.method = "GET"; + if (util4.isStream(this.opts.body)) { + util4.destroy(this.opts.body.on("error", noop3)); + } + this.opts.body = null; + } + this.location = this.history.length >= this.maxRedirections || util4.isDisturbed(this.opts.body) || redirectableStatusCodes.indexOf(statusCode) === -1 ? null : headers.location; + if (this.opts.origin) { + this.history.push(new URL(this.opts.path, this.opts.origin)); + } + if (!this.location) { + this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage); + return; + } + this.history[kRedirectCacheControl].push(headers["cache-control"]); + const { origin, pathname, search } = util4.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))); + const path30 = search ? `${pathname}${search}` : pathname; + const redirectUrlString = `${origin}${path30}`; + for (const historyUrl of this.history) { + if (historyUrl.toString() === redirectUrlString) { + throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`); + } + } + this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin); + this.opts.path = path30; + this.opts.origin = origin; + this.opts.query = null; + } + onResponseData(controller, chunk) { + if (this.location) { + } else { + this.handler.onResponseData?.(controller, chunk); + } + } + onResponseEnd(controller, trailers) { + if (this.location) { + this.dispatch(this.opts, this); + } else { + this.handler.onResponseEnd(controller, trailers); + } + } + onResponseError(controller, error3) { + this.handler.onResponseError?.(controller, error3); + } + }; + function shouldRemoveHeader(header, removeContent, unknownOrigin) { + if (header.length === 4) { + return util4.headerNameToString(header) === "host"; + } + if (removeContent && util4.headerNameToString(header).startsWith("content-")) { + return true; + } + if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) { + const name = util4.headerNameToString(header); + return name === "authorization" || name === "cookie" || name === "proxy-authorization"; + } + return false; + } + function cleanRequestHeaders(headers, removeContent, unknownOrigin) { + const ret = []; + if (Array.isArray(headers)) { + for (let i = 0; i < headers.length; i += 2) { + if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { + ret.push(headers[i], headers[i + 1]); + } + } + } else if (headers && typeof headers === "object") { + const entries = util4.hasSafeIterator(headers) ? headers : Object.entries(headers); + for (const [key, value] of entries) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { + ret.push(key, value); + } + } + } else { + assert(headers == null, "headers must be an object or an array"); + } + return ret; + } + module2.exports = RedirectHandler; + } +}); + +// node_modules/undici/lib/interceptor/redirect.js +var require_redirect = __commonJS({ + "node_modules/undici/lib/interceptor/redirect.js"(exports2, module2) { + "use strict"; + var RedirectHandler = require_redirect_handler(); + function createRedirectInterceptor({ maxRedirections: defaultMaxRedirections } = {}) { + return (dispatch) => { + return function Intercept(opts, handler2) { + const { maxRedirections = defaultMaxRedirections, ...rest } = opts; + if (maxRedirections == null || maxRedirections === 0) { + return dispatch(opts, handler2); + } + const dispatchOpts = { ...rest }; + const redirectHandler = new RedirectHandler(dispatch, maxRedirections, dispatchOpts, handler2); + return dispatch(dispatchOpts, redirectHandler); + }; + }; + } + module2.exports = createRedirectInterceptor; + } +}); + +// node_modules/undici/lib/interceptor/response-error.js +var require_response_error = __commonJS({ + "node_modules/undici/lib/interceptor/response-error.js"(exports2, module2) { + "use strict"; + var DecoratorHandler = require_decorator_handler(); + var { ResponseError } = require_errors(); + var ResponseErrorHandler = class extends DecoratorHandler { + #statusCode; + #contentType; + #decoder; + #headers; + #body; + constructor(_opts, { handler: handler2 }) { + super(handler2); + } + #checkContentType(contentType) { + return (this.#contentType ?? "").indexOf(contentType) === 0; + } + onRequestStart(controller, context5) { + this.#statusCode = 0; + this.#contentType = null; + this.#decoder = null; + this.#headers = null; + this.#body = ""; + return super.onRequestStart(controller, context5); + } + onResponseStart(controller, statusCode, headers, statusMessage) { + this.#statusCode = statusCode; + this.#headers = headers; + this.#contentType = headers["content-type"]; + if (this.#statusCode < 400) { + return super.onResponseStart(controller, statusCode, headers, statusMessage); + } + if (this.#checkContentType("application/json") || this.#checkContentType("text/plain")) { + this.#decoder = new TextDecoder("utf-8"); + } + } + onResponseData(controller, chunk) { + if (this.#statusCode < 400) { + return super.onResponseData(controller, chunk); + } + this.#body += this.#decoder?.decode(chunk, { stream: true }) ?? ""; + } + onResponseEnd(controller, trailers) { + if (this.#statusCode >= 400) { + this.#body += this.#decoder?.decode(void 0, { stream: false }) ?? ""; + if (this.#checkContentType("application/json")) { + try { + this.#body = JSON.parse(this.#body); + } catch { + } + } + let err; + const stackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = 0; + try { + err = new ResponseError("Response Error", this.#statusCode, { + body: this.#body, + headers: this.#headers + }); + } finally { + Error.stackTraceLimit = stackTraceLimit; + } + super.onResponseError(controller, err); + } else { + super.onResponseEnd(controller, trailers); + } + } + onResponseError(controller, err) { + super.onResponseError(controller, err); + } + }; + module2.exports = () => { + return (dispatch) => { + return function Intercept(opts, handler2) { + return dispatch(opts, new ResponseErrorHandler(opts, { handler: handler2 })); + }; + }; + }; + } +}); + +// node_modules/undici/lib/interceptor/retry.js +var require_retry = __commonJS({ + "node_modules/undici/lib/interceptor/retry.js"(exports2, module2) { + "use strict"; + var RetryHandler = require_retry_handler(); + module2.exports = (globalOpts) => { + return (dispatch) => { + return function retryInterceptor(opts, handler2) { + return dispatch( + opts, + new RetryHandler( + { ...opts, retryOptions: { ...globalOpts, ...opts.retryOptions } }, + { + handler: handler2, + dispatch + } + ) + ); + }; + }; + }; + } +}); + +// node_modules/undici/lib/interceptor/dump.js +var require_dump = __commonJS({ + "node_modules/undici/lib/interceptor/dump.js"(exports2, module2) { + "use strict"; + var { InvalidArgumentError, RequestAbortedError } = require_errors(); + var DecoratorHandler = require_decorator_handler(); + var DumpHandler = class extends DecoratorHandler { + #maxSize = 1024 * 1024; + #dumped = false; + #size = 0; + aborted = false; + reason = false; + constructor({ maxSize, signal }, handler2) { + if (maxSize != null && (!Number.isFinite(maxSize) || maxSize < 1)) { + throw new InvalidArgumentError("maxSize must be a number greater than 0"); + } + super(handler2); + this.#maxSize = maxSize ?? this.#maxSize; + } + #abort(reason) { + this.aborted = true; + this.reason = reason; + } + onRequestStart(controller, context5) { + controller.abort = this.#abort.bind(this); + return super.onRequestStart(controller, context5); + } + onResponseStart(controller, statusCode, headers, statusMessage) { + const contentLength = headers["content-length"]; + if (contentLength != null && contentLength > this.#maxSize) { + throw new RequestAbortedError( + `Response size (${contentLength}) larger than maxSize (${this.#maxSize})` + ); + } + if (this.aborted === true) { + return true; + } + return super.onResponseStart(controller, statusCode, headers, statusMessage); + } + onResponseError(controller, err) { + super.onResponseError(controller, this.aborted === true ? this.reason : err); + } + onResponseData(controller, chunk) { + this.#size = this.#size + chunk.length; + if (this.#size > this.#maxSize) { + throw new RequestAbortedError( + `Response size (${this.#size}) larger than maxSize (${this.#maxSize})` + ); + } + if (this.#size === this.#maxSize) { + this.#dumped = true; + } + return true; + } + onResponseEnd(controller, trailers) { + if (this.aborted === true) { + super.onResponseError(controller, this.reason); + return; + } + super.onResponseEnd(controller, this.#dumped ? {} : trailers); + } + }; + function createDumpInterceptor({ maxSize: defaultMaxSize } = { + maxSize: 1024 * 1024 + }) { + return (dispatch) => { + return function Intercept(opts, handler2) { + const { dumpMaxSize = defaultMaxSize } = opts; + const dumpHandler = new DumpHandler({ maxSize: dumpMaxSize, signal: opts.signal }, handler2); + return dispatch(opts, dumpHandler); + }; + }; + } + module2.exports = createDumpInterceptor; + } +}); + +// node_modules/undici/lib/interceptor/dns.js +var require_dns = __commonJS({ + "node_modules/undici/lib/interceptor/dns.js"(exports2, module2) { + "use strict"; + var { isIP } = require("node:net"); + var { lookup } = require("node:dns"); + var DecoratorHandler = require_decorator_handler(); + var { InvalidArgumentError, InformationalError } = require_errors(); + var maxInt = Math.pow(2, 31) - 1; + function hasSafeIterator(headers) { + const prototype = Object.getPrototypeOf(headers); + const ownIterator = Object.prototype.hasOwnProperty.call(headers, Symbol.iterator); + return ownIterator || prototype != null && prototype !== Object.prototype && typeof headers[Symbol.iterator] === "function"; + } + function isHostHeader(key) { + return typeof key === "string" && key.toLowerCase() === "host"; + } + function normalizeHeaders(headers) { + if (headers == null) { + return null; + } + if (Array.isArray(headers)) { + if (headers.length === 0 || !Array.isArray(headers[0])) { + return headers; + } + const normalized = []; + for (const header of headers) { + if (Array.isArray(header) && header.length === 2) { + normalized.push(header[0], header[1]); + } else { + normalized.push(header); + } + } + return normalized; + } + if (typeof headers === "object" && hasSafeIterator(headers)) { + const normalized = []; + for (const header of headers) { + if (Array.isArray(header) && header.length === 2) { + normalized.push(header[0], header[1]); + } else { + normalized.push(header); + } + } + return normalized; + } + return headers; + } + function hasHostHeader(headers) { + if (headers == null) { + return false; + } + if (Array.isArray(headers)) { + if (headers.length === 0) { + return false; + } + for (let i = 0; i < headers.length; i += 2) { + if (isHostHeader(headers[i])) { + return true; + } + } + return false; + } + if (typeof headers === "object") { + for (const key in headers) { + if (isHostHeader(key)) { + return true; + } + } + } + return false; + } + function withHostHeader(host, headers) { + const normalizedHeaders = normalizeHeaders(headers); + if (hasHostHeader(normalizedHeaders)) { + return normalizedHeaders; + } + if (Array.isArray(normalizedHeaders)) { + return ["host", host, ...normalizedHeaders]; + } + if (normalizedHeaders && typeof normalizedHeaders === "object") { + return { + host, + ...normalizedHeaders + }; + } + return { host }; + } + var DNSStorage = class { + #maxItems = 0; + #records = /* @__PURE__ */ new Map(); + constructor(opts) { + this.#maxItems = opts.maxItems; + } + get size() { + return this.#records.size; + } + get(hostname) { + return this.#records.get(hostname) ?? null; + } + set(hostname, records) { + this.#records.set(hostname, records); + } + delete(hostname) { + this.#records.delete(hostname); + } + // Delegate to storage decide can we do more lookups or not + full() { + return this.size >= this.#maxItems; + } + }; + var DNSInstance = class { + #maxTTL = 0; + #maxItems = 0; + dualStack = true; + affinity = null; + lookup = null; + pick = null; + storage = null; + constructor(opts) { + this.#maxTTL = opts.maxTTL; + this.#maxItems = opts.maxItems; + this.dualStack = opts.dualStack; + this.affinity = opts.affinity; + this.lookup = opts.lookup ?? this.#defaultLookup; + this.pick = opts.pick ?? this.#defaultPick; + this.storage = opts.storage ?? new DNSStorage(opts); + } + runLookup(origin, opts, cb) { + const ips = this.storage.get(origin.hostname); + if (ips == null && this.storage.full()) { + cb(null, origin); + return; + } + const newOpts = { + affinity: this.affinity, + dualStack: this.dualStack, + lookup: this.lookup, + pick: this.pick, + ...opts.dns, + maxTTL: this.#maxTTL, + maxItems: this.#maxItems + }; + if (ips == null) { + this.lookup(origin, newOpts, (err, addresses) => { + if (err || addresses == null || addresses.length === 0) { + cb(err ?? new InformationalError("No DNS entries found")); + return; + } + this.setRecords(origin, addresses); + const records = this.storage.get(origin.hostname); + const ip = this.pick( + origin, + records, + newOpts.affinity + ); + let port; + if (typeof ip.port === "number") { + port = `:${ip.port}`; + } else if (origin.port !== "") { + port = `:${origin.port}`; + } else { + port = ""; + } + cb( + null, + new URL(`${origin.protocol}//${ip.family === 6 ? `[${ip.address}]` : ip.address}${port}`) + ); + }); + } else { + const ip = this.pick( + origin, + ips, + newOpts.affinity + ); + if (ip == null) { + this.storage.delete(origin.hostname); + this.runLookup(origin, opts, cb); + return; + } + let port; + if (typeof ip.port === "number") { + port = `:${ip.port}`; + } else if (origin.port !== "") { + port = `:${origin.port}`; + } else { + port = ""; + } + cb( + null, + new URL(`${origin.protocol}//${ip.family === 6 ? `[${ip.address}]` : ip.address}${port}`) + ); + } + } + #defaultLookup(origin, opts, cb) { + lookup( + origin.hostname, + { + all: true, + family: this.dualStack === false ? this.affinity : 0, + order: "ipv4first" + }, + (err, addresses) => { + if (err) { + return cb(err); + } + const results = /* @__PURE__ */ new Map(); + for (const addr of addresses) { + results.set(`${addr.address}:${addr.family}`, addr); + } + cb(null, results.values()); + } + ); + } + #defaultPick(origin, hostnameRecords, affinity) { + let ip = null; + const { records, offset } = hostnameRecords; + let family; + if (this.dualStack) { + if (affinity == null) { + if (offset == null || offset === maxInt) { + hostnameRecords.offset = 0; + affinity = 4; + } else { + hostnameRecords.offset++; + affinity = (hostnameRecords.offset & 1) === 1 ? 6 : 4; + } + } + if (records[affinity] != null && records[affinity].ips.length > 0) { + family = records[affinity]; + } else { + family = records[affinity === 4 ? 6 : 4]; + } + } else { + family = records[affinity]; + } + if (family == null || family.ips.length === 0) { + return ip; + } + if (family.offset == null || family.offset === maxInt) { + family.offset = 0; + } else { + family.offset++; + } + const position = family.offset % family.ips.length; + ip = family.ips[position] ?? null; + if (ip == null) { + return ip; + } + if (Date.now() - ip.timestamp > ip.ttl) { + family.ips.splice(position, 1); + return this.pick(origin, hostnameRecords, affinity); + } + return ip; + } + pickFamily(origin, ipFamily) { + const records = this.storage.get(origin.hostname)?.records; + if (!records) { + return null; + } + const family = records[ipFamily]; + if (!family) { + return null; + } + if (family.offset == null || family.offset === maxInt) { + family.offset = 0; + } else { + family.offset++; + } + const position = family.offset % family.ips.length; + const ip = family.ips[position] ?? null; + if (ip == null) { + return ip; + } + if (Date.now() - ip.timestamp > ip.ttl) { + family.ips.splice(position, 1); + } + return ip; + } + setRecords(origin, addresses) { + const timestamp = Date.now(); + const records = { records: { 4: null, 6: null } }; + let minTTL = this.#maxTTL; + for (const record of addresses) { + record.timestamp = timestamp; + if (typeof record.ttl === "number") { + record.ttl = Math.min(record.ttl, this.#maxTTL); + minTTL = Math.min(minTTL, record.ttl); + } else { + record.ttl = this.#maxTTL; + } + const familyRecords = records.records[record.family] ?? { ips: [] }; + familyRecords.ips.push(record); + records.records[record.family] = familyRecords; + } + this.storage.set(origin.hostname, records, { ttl: minTTL }); + } + deleteRecords(origin) { + this.storage.delete(origin.hostname); + } + getHandler(meta, opts) { + return new DNSDispatchHandler(this, meta, opts); + } + }; + var DNSDispatchHandler = class extends DecoratorHandler { + #state = null; + #opts = null; + #dispatch = null; + #origin = null; + #controller = null; + #newOrigin = null; + #firstTry = true; + constructor(state, { origin, handler: handler2, dispatch, newOrigin }, opts) { + super(handler2); + this.#origin = origin; + this.#newOrigin = newOrigin; + this.#opts = { ...opts }; + this.#state = state; + this.#dispatch = dispatch; + } + onResponseError(controller, err) { + switch (err.code) { + case "ETIMEDOUT": + case "ECONNREFUSED": { + if (this.#state.dualStack) { + if (!this.#firstTry) { + super.onResponseError(controller, err); + return; + } + this.#firstTry = false; + const otherFamily = this.#newOrigin.hostname[0] === "[" ? 4 : 6; + const ip = this.#state.pickFamily(this.#origin, otherFamily); + if (ip == null) { + super.onResponseError(controller, err); + return; + } + let port; + if (typeof ip.port === "number") { + port = `:${ip.port}`; + } else if (this.#origin.port !== "") { + port = `:${this.#origin.port}`; + } else { + port = ""; + } + const dispatchOpts = { + ...this.#opts, + origin: `${this.#origin.protocol}//${ip.family === 6 ? `[${ip.address}]` : ip.address}${port}`, + headers: withHostHeader(this.#origin.host, this.#opts.headers) + }; + this.#dispatch(dispatchOpts, this); + return; + } + super.onResponseError(controller, err); + break; + } + case "ENOTFOUND": + this.#state.deleteRecords(this.#origin); + super.onResponseError(controller, err); + break; + default: + super.onResponseError(controller, err); + break; + } + } + }; + module2.exports = (interceptorOpts) => { + if (interceptorOpts?.maxTTL != null && (typeof interceptorOpts?.maxTTL !== "number" || interceptorOpts?.maxTTL < 0)) { + throw new InvalidArgumentError("Invalid maxTTL. Must be a positive number"); + } + if (interceptorOpts?.maxItems != null && (typeof interceptorOpts?.maxItems !== "number" || interceptorOpts?.maxItems < 1)) { + throw new InvalidArgumentError( + "Invalid maxItems. Must be a positive number and greater than zero" + ); + } + if (interceptorOpts?.affinity != null && interceptorOpts?.affinity !== 4 && interceptorOpts?.affinity !== 6) { + throw new InvalidArgumentError("Invalid affinity. Must be either 4 or 6"); + } + if (interceptorOpts?.dualStack != null && typeof interceptorOpts?.dualStack !== "boolean") { + throw new InvalidArgumentError("Invalid dualStack. Must be a boolean"); + } + if (interceptorOpts?.lookup != null && typeof interceptorOpts?.lookup !== "function") { + throw new InvalidArgumentError("Invalid lookup. Must be a function"); + } + if (interceptorOpts?.pick != null && typeof interceptorOpts?.pick !== "function") { + throw new InvalidArgumentError("Invalid pick. Must be a function"); + } + if (interceptorOpts?.storage != null && (typeof interceptorOpts?.storage?.get !== "function" || typeof interceptorOpts?.storage?.set !== "function" || typeof interceptorOpts?.storage?.full !== "function" || typeof interceptorOpts?.storage?.delete !== "function")) { + throw new InvalidArgumentError("Invalid storage. Must be a object with methods: { get, set, full, delete }"); + } + const dualStack = interceptorOpts?.dualStack ?? true; + let affinity; + if (dualStack) { + affinity = interceptorOpts?.affinity ?? null; + } else { + affinity = interceptorOpts?.affinity ?? 4; + } + const opts = { + maxTTL: interceptorOpts?.maxTTL ?? 1e4, + // Expressed in ms + lookup: interceptorOpts?.lookup ?? null, + pick: interceptorOpts?.pick ?? null, + dualStack, + affinity, + maxItems: interceptorOpts?.maxItems ?? Infinity, + storage: interceptorOpts?.storage + }; + const instance8 = new DNSInstance(opts); + return (dispatch) => { + return function dnsInterceptor(origDispatchOpts, handler2) { + const origin = origDispatchOpts.origin.constructor === URL ? origDispatchOpts.origin : new URL(origDispatchOpts.origin); + if (isIP(origin.hostname) !== 0) { + return dispatch(origDispatchOpts, handler2); + } + instance8.runLookup(origin, origDispatchOpts, (err, newOrigin) => { + if (err) { + return handler2.onResponseError(null, err); + } + const dispatchOpts = { + ...origDispatchOpts, + servername: origin.hostname, + // For SNI on TLS + origin: newOrigin.origin, + headers: withHostHeader(origin.host, origDispatchOpts.headers) + }; + dispatch( + dispatchOpts, + instance8.getHandler( + { origin, dispatch, handler: handler2, newOrigin }, + origDispatchOpts + ) + ); + }); + return true; + }; + }; + }; + } +}); + +// node_modules/undici/lib/util/cache.js +var require_cache = __commonJS({ + "node_modules/undici/lib/util/cache.js"(exports2, module2) { + "use strict"; + var { + safeHTTPMethods, + pathHasQueryOrFragment, + hasSafeIterator, + isValidHTTPToken + } = require_util(); + var { serializePathWithQuery } = require_util(); + var MAX_DELTA_SECONDS = 2147483647; + var RESTRICTIVE_DIRECTIVE_NAMES = ["no-store", "private", "no-cache"]; + var kInvalidCacheControlDirectives = /* @__PURE__ */ Symbol("invalid cache-control directives"); + function trimOWS(value) { + return value.replace(/^[\t ]+|[\t ]+$/g, ""); + } + function arrayIncludes(array2, value) { + for (let i = 0; i < array2.length; i++) { + if (array2[i] === value) { + return true; + } + } + return false; + } + function trimOWSStart(value) { + return value.replace(/^[\t ]+/, ""); + } + function trimOWSEnd(value) { + return value.replace(/[\t ]+$/, ""); + } + function findUnescapedQuote(value, start) { + let escaped = false; + for (let i = start; i < value.length; i++) { + if (escaped) { + escaped = false; + } else if (value[i] === "\\") { + escaped = true; + } else if (value[i] === '"') { + return i; + } + } + return -1; + } + function splitCacheControlHeaderValue(value) { + const directives = []; + let start = 0; + let quoteStart = -1; + let inQuote = false; + let escaped = false; + for (let i = 0; i < value.length; i++) { + if (inQuote) { + if (escaped) { + escaped = false; + } else if (value[i] === "\\") { + escaped = true; + } else if (value[i] === '"') { + inQuote = false; + quoteStart = -1; + } + } else if (value[i] === '"') { + inQuote = true; + quoteStart = i; + } else if (value[i] === ",") { + directives.push({ value: value.substring(start, i), fromMalformedQuote: false }); + start = i + 1; + } + } + if (!inQuote) { + directives.push({ value: value.substring(start), fromMalformedQuote: false }); + return directives; + } + const tail = value.substring(start); + const quoteOffset = quoteStart - start; + let tailStart = 0; + for (let i = 0; i < tail.length; i++) { + if (tail[i] === ",") { + directives.push({ + value: tail.substring(tailStart, i), + fromMalformedQuote: tailStart > quoteOffset + }); + tailStart = i + 1; + } + } + directives.push({ + value: tail.substring(tailStart), + fromMalformedQuote: tailStart > quoteOffset + }); + return directives; + } + function markInvalidCacheControlDirective(directives, key) { + let invalidDirectives = directives[kInvalidCacheControlDirectives]; + if (invalidDirectives === void 0) { + invalidDirectives = /* @__PURE__ */ new Set(); + Object.defineProperty(directives, kInvalidCacheControlDirectives, { + value: invalidDirectives + }); + } + invalidDirectives.add(key); + } + function hasInvalidCacheControlDirective(directives, key) { + return directives[kInvalidCacheControlDirectives]?.has(key) === true; + } + function getMalformedRestrictiveDirectiveName(key) { + for (const directiveName of RESTRICTIVE_DIRECTIVE_NAMES) { + if (key.startsWith(directiveName) && key.length > directiveName.length && !isValidHTTPToken(key[directiveName.length])) { + return directiveName; + } + } + let tokenOnlyKey = ""; + let hasInvalidTokenChar = false; + for (let i = 0; i < key.length; i++) { + if (isValidHTTPToken(key[i])) { + tokenOnlyKey += key[i]; + } else { + hasInvalidTokenChar = true; + } + } + if (hasInvalidTokenChar && arrayIncludes(RESTRICTIVE_DIRECTIVE_NAMES, tokenOnlyKey)) { + return tokenOnlyKey; + } + } + function makeCacheKey(opts) { + if (!opts.origin) { + throw new Error("opts.origin is undefined"); + } + let fullPath = opts.path || "/"; + if (opts.query && !pathHasQueryOrFragment(fullPath)) { + fullPath = serializePathWithQuery(fullPath, opts.query); + } + return { + origin: opts.origin.toString(), + method: opts.method, + path: fullPath, + headers: opts.headers + }; + } + function appendHeader(headers, key, val) { + const headerName = key.toLowerCase(); + const current = headers[headerName]; + const values = Array.isArray(val) ? val : [val]; + if (current === void 0) { + headers[headerName] = Array.isArray(val) ? val.slice() : val; + } else if (Array.isArray(current)) { + current.push(...values); + } else { + headers[headerName] = [current, ...values]; + } + } + function normalizeHeaders(opts) { + let headers; + if (opts.headers == null) { + headers = {}; + } else if (typeof opts.headers === "object") { + headers = {}; + if (hasSafeIterator(opts.headers)) { + for (const x of opts.headers) { + if (!Array.isArray(x)) { + throw new Error("opts.headers is not a valid header map"); + } + const [key, val] = x; + if (typeof key !== "string" || typeof val !== "string") { + throw new Error("opts.headers is not a valid header map"); + } + appendHeader(headers, key, val); + } + } else { + for (const key of Object.keys(opts.headers)) { + appendHeader(headers, key, opts.headers[key]); + } + } + } else { + throw new Error("opts.headers is not an object"); + } + return headers; + } + function assertCacheKey(key) { + if (typeof key !== "object") { + throw new TypeError(`expected key to be object, got ${typeof key}`); + } + for (const property of ["origin", "method", "path"]) { + if (typeof key[property] !== "string") { + throw new TypeError(`expected key.${property} to be string, got ${typeof key[property]}`); + } + } + if (key.headers !== void 0 && typeof key.headers !== "object") { + throw new TypeError(`expected headers to be object, got ${typeof key}`); + } + } + function assertCacheValue(value) { + if (typeof value !== "object") { + throw new TypeError(`expected value to be object, got ${typeof value}`); + } + for (const property of ["statusCode", "cachedAt", "staleAt", "deleteAt"]) { + if (typeof value[property] !== "number") { + throw new TypeError(`expected value.${property} to be number, got ${typeof value[property]}`); + } + } + if (typeof value.statusMessage !== "string") { + throw new TypeError(`expected value.statusMessage to be string, got ${typeof value.statusMessage}`); + } + if (value.headers != null && typeof value.headers !== "object") { + throw new TypeError(`expected value.rawHeaders to be object, got ${typeof value.headers}`); + } + if (value.vary !== void 0 && typeof value.vary !== "object") { + throw new TypeError(`expected value.vary to be object, got ${typeof value.vary}`); + } + if (value.etag !== void 0 && typeof value.etag !== "string") { + throw new TypeError(`expected value.etag to be string, got ${typeof value.etag}`); + } + } + function parseCacheControlHeader(header) { + const output = {}; + const invalidNumericDirectives = /* @__PURE__ */ new Set(); + const invalidNoArgumentDirectives = /* @__PURE__ */ new Set(); + const directives = splitCacheControlHeaderValue(Array.isArray(header) ? header.join(",") : header); + for (let i = 0; i < directives.length; i++) { + const directiveRecord = directives[i]; + const directive = directiveRecord.value.toLowerCase(); + const fromMalformedQuote = directiveRecord.fromMalformedQuote; + const keyValueDelimiter = directive.indexOf("="); + let key; + let value; + let keyHasTrailingWhitespace = false; + let valueHasLeadingWhitespace = false; + if (keyValueDelimiter !== -1) { + const rawKey = directive.substring(0, keyValueDelimiter); + const rawValue = directive.substring(keyValueDelimiter + 1); + keyHasTrailingWhitespace = trimOWSEnd(rawKey) !== rawKey; + valueHasLeadingWhitespace = trimOWSStart(rawValue) !== rawValue; + key = trimOWS(rawKey); + value = trimOWSStart(rawValue); + } else { + key = trimOWS(directive); + } + const malformedRestrictiveDirectiveName = getMalformedRestrictiveDirectiveName(key); + if (malformedRestrictiveDirectiveName !== void 0) { + output[malformedRestrictiveDirectiveName] = true; + continue; + } + switch (key) { + case "min-fresh": + case "max-stale": + case "max-age": + case "s-maxage": + case "stale-while-revalidate": + case "stale-if-error": { + if (fromMalformedQuote || invalidNumericDirectives.has(key)) { + continue; + } + if (value === void 0 || keyHasTrailingWhitespace || valueHasLeadingWhitespace) { + delete output[key]; + invalidNumericDirectives.add(key); + markInvalidCacheControlDirective(output, key); + continue; + } + if (value.length >= 2 && value[0] === '"' && value[value.length - 1] === '"') { + value = value.substring(1, value.length - 1); + } + if (!/^[0-9]+$/.test(value)) { + delete output[key]; + invalidNumericDirectives.add(key); + markInvalidCacheControlDirective(output, key); + continue; + } + const parsedValue = Math.min(parseInt(value, 10), MAX_DELTA_SECONDS); + if (key === "min-fresh") { + if (!(key in output) || output[key] < parsedValue) { + output[key] = parsedValue; + } + } else if (!(key in output) || output[key] > parsedValue) { + output[key] = parsedValue; + } + break; + } + case "private": + case "no-cache": { + if (fromMalformedQuote) { + output[key] = true; + break; + } + if (value !== void 0 && value.length === 0) { + output[key] = true; + break; + } + if (value) { + if (value[0] === '"') { + value = trimOWSEnd(value); + let fieldList = ""; + let lastQuotedPart = i; + let foundEndingQuote = false; + const closingQuote = findUnescapedQuote(value, 1); + if (closingQuote !== -1) { + fieldList = value.substring(1, closingQuote); + foundEndingQuote = true; + } else { + const fieldListParts = [value.substring(1)]; + for (let j = i + 1; j < directives.length; j++) { + const nextPart = trimOWS(directives[j].value); + const closingQuote2 = findUnescapedQuote(nextPart, 0); + lastQuotedPart = j; + if (closingQuote2 !== -1) { + fieldListParts.push(nextPart.substring(0, closingQuote2)); + foundEndingQuote = true; + break; + } + fieldListParts.push(nextPart); + } + fieldList = fieldListParts.join(","); + } + if (!foundEndingQuote) { + output[key] = true; + break; + } + i = lastQuotedPart; + const headers = fieldList.split(","); + let validFieldNames = true; + for (let j = 0; j < headers.length; j++) { + headers[j] = trimOWS(headers[j]); + if (!isValidHTTPToken(headers[j])) { + validFieldNames = false; + } + } + if (!validFieldNames) { + output[key] = true; + } else if (output[key] !== true) { + if (key in output) { + output[key] = output[key].concat(headers); + } else { + output[key] = headers; + } + } + } else { + const fieldName = trimOWS(value); + if (!isValidHTTPToken(fieldName)) { + output[key] = true; + } else if (output[key] !== true) { + if (key in output) { + output[key] = output[key].concat(fieldName); + } else { + output[key] = [fieldName]; + } + } + } + break; + } + } + // eslint-disable-next-line no-fallthrough + case "public": + case "must-revalidate": + case "proxy-revalidate": + case "immutable": + case "no-transform": + case "must-understand": + case "only-if-cached": + if (fromMalformedQuote || invalidNoArgumentDirectives.has(key)) { + continue; + } + if (value !== void 0) { + delete output[key]; + invalidNoArgumentDirectives.add(key); + continue; + } + output[key] = true; + break; + case "no-store": + output[key] = true; + break; + default: + continue; + } + } + return output; + } + function splitVaryHeader(varyHeader) { + const values = Array.isArray(varyHeader) ? varyHeader : [varyHeader]; + const output = []; + for (let i = 0; i < values.length; i++) { + const parts = values[i].split(","); + for (let j = 0; j < parts.length; j++) { + output.push(parts[j]); + } + } + return output; + } + function hasVaryStar(varyHeader) { + const values = splitVaryHeader(varyHeader); + for (let i = 0; i < values.length; i++) { + if (trimOWS(values[i]).indexOf("*") !== -1) { + return true; + } + } + return false; + } + function parseVaryHeader(varyHeader, headers) { + if (hasVaryStar(varyHeader)) { + return headers; + } + const output = ( + /** @type {Record} */ + {} + ); + const varyingHeaders = splitVaryHeader(varyHeader); + for (const header of varyingHeaders) { + const trimmedHeader = trimOWS(header).toLowerCase(); + if (trimmedHeader.length === 0) { + continue; + } + if (!isValidHTTPToken(trimmedHeader)) { + return void 0; + } + const headerValue = headers[trimmedHeader]; + output[trimmedHeader] = Array.isArray(headerValue) ? headerValue.slice() : headerValue ?? null; + } + return output; + } + function isInvalidOrWildcardVaryHeader(varyHeader) { + return hasVaryStar(varyHeader) || parseVaryHeader(varyHeader, {}) === void 0; + } + function isEtagUsable(etag) { + if (etag.length <= 2) { + return false; + } + if (etag[0] === '"' && etag[etag.length - 1] === '"') { + return !(etag[1] === '"' || etag.startsWith('"W/')); + } + if (etag.startsWith('W/"') && etag[etag.length - 1] === '"') { + return etag.length !== 4; + } + return false; + } + function assertCacheStore(store, name = "CacheStore") { + if (typeof store !== "object" || store === null) { + throw new TypeError(`expected type of ${name} to be a CacheStore, got ${store === null ? "null" : typeof store}`); + } + for (const fn of ["get", "createWriteStream", "delete"]) { + if (typeof store[fn] !== "function") { + throw new TypeError(`${name} needs to have a \`${fn}()\` function`); + } + } + } + function assertCacheMethods(methods, name = "CacheMethods") { + if (!Array.isArray(methods)) { + throw new TypeError(`expected type of ${name} needs to be an array, got ${methods === null ? "null" : typeof methods}`); + } + if (methods.length === 0) { + throw new TypeError(`${name} needs to have at least one method`); + } + for (const method of methods) { + if (!arrayIncludes(safeHTTPMethods, method)) { + throw new TypeError(`element of ${name}-array needs to be one of following values: ${safeHTTPMethods.join(", ")}, got ${method}`); + } + } + } + function makeDeduplicationKey(cacheKey3, excludeHeaders) { + const headers = {}; + if (cacheKey3.headers) { + const sortedHeaders = Object.keys(cacheKey3.headers).sort(); + for (const header of sortedHeaders) { + if (excludeHeaders?.has(header.toLowerCase())) { + continue; + } + headers[header] = cacheKey3.headers[header]; + } + } + return JSON.stringify([cacheKey3.origin, cacheKey3.method, cacheKey3.path, headers]); + } + module2.exports = { + makeCacheKey, + normalizeHeaders, + assertCacheKey, + assertCacheValue, + parseCacheControlHeader, + hasInvalidCacheControlDirective, + parseVaryHeader, + hasVaryStar, + isInvalidOrWildcardVaryHeader, + isEtagUsable, + assertCacheMethods, + assertCacheStore, + makeDeduplicationKey + }; + } +}); + +// node_modules/undici/lib/util/date.js +var require_date = __commonJS({ + "node_modules/undici/lib/util/date.js"(exports2, module2) { + "use strict"; + function parseHttpDate(date) { + switch (date[3]) { + case ",": + return parseImfDate(date); + case " ": + return parseAscTimeDate(date); + default: + return parseRfc850Date(date); + } + } + function makeDate(year, monthIdx, day, hour, minute, second, weekday) { + const result = new Date(Date.UTC(year, monthIdx, day, hour, minute, second)); + if (year >= 0 && year <= 99) { + result.setUTCFullYear(year); + } + return result.getUTCFullYear() === year && result.getUTCMonth() === monthIdx && result.getUTCDate() === day && result.getUTCHours() === hour && result.getUTCMinutes() === minute && result.getUTCSeconds() === second && result.getUTCDay() === weekday ? result : void 0; + } + function parseImfDate(date) { + if (date.length !== 29 || date[4] !== " " || date[7] !== " " || date[11] !== " " || date[16] !== " " || date[19] !== ":" || date[22] !== ":" || date[25] !== " " || date[26] !== "G" || date[27] !== "M" || date[28] !== "T") { + return void 0; + } + let weekday = -1; + if (date[0] === "S" && date[1] === "u" && date[2] === "n") { + weekday = 0; + } else if (date[0] === "M" && date[1] === "o" && date[2] === "n") { + weekday = 1; + } else if (date[0] === "T" && date[1] === "u" && date[2] === "e") { + weekday = 2; + } else if (date[0] === "W" && date[1] === "e" && date[2] === "d") { + weekday = 3; + } else if (date[0] === "T" && date[1] === "h" && date[2] === "u") { + weekday = 4; + } else if (date[0] === "F" && date[1] === "r" && date[2] === "i") { + weekday = 5; + } else if (date[0] === "S" && date[1] === "a" && date[2] === "t") { + weekday = 6; + } else { + return void 0; + } + let day = 0; + if (date[5] === "0") { + const code = date.charCodeAt(6); + if (code < 49 || code > 57) { + return void 0; + } + day = code - 48; + } else { + const code1 = date.charCodeAt(5); + if (code1 < 49 || code1 > 51) { + return void 0; + } + const code2 = date.charCodeAt(6); + if (code2 < 48 || code2 > 57) { + return void 0; + } + day = (code1 - 48) * 10 + (code2 - 48); + } + let monthIdx = -1; + if (date[8] === "J" && date[9] === "a" && date[10] === "n") { + monthIdx = 0; + } else if (date[8] === "F" && date[9] === "e" && date[10] === "b") { + monthIdx = 1; + } else if (date[8] === "M" && date[9] === "a") { + if (date[10] === "r") { + monthIdx = 2; + } else if (date[10] === "y") { + monthIdx = 4; + } else { + return void 0; + } + } else if (date[8] === "J") { + if (date[9] === "a" && date[10] === "n") { + monthIdx = 0; + } else if (date[9] === "u") { + if (date[10] === "n") { + monthIdx = 5; + } else if (date[10] === "l") { + monthIdx = 6; + } else { + return void 0; + } + } else { + return void 0; + } + } else if (date[8] === "A") { + if (date[9] === "p" && date[10] === "r") { + monthIdx = 3; + } else if (date[9] === "u" && date[10] === "g") { + monthIdx = 7; + } else { + return void 0; + } + } else if (date[8] === "S" && date[9] === "e" && date[10] === "p") { + monthIdx = 8; + } else if (date[8] === "O" && date[9] === "c" && date[10] === "t") { + monthIdx = 9; + } else if (date[8] === "N" && date[9] === "o" && date[10] === "v") { + monthIdx = 10; + } else if (date[8] === "D" && date[9] === "e" && date[10] === "c") { + monthIdx = 11; + } else { + return void 0; + } + const yearDigit1 = date.charCodeAt(12); + if (yearDigit1 < 48 || yearDigit1 > 57) { + return void 0; + } + const yearDigit2 = date.charCodeAt(13); + if (yearDigit2 < 48 || yearDigit2 > 57) { + return void 0; + } + const yearDigit3 = date.charCodeAt(14); + if (yearDigit3 < 48 || yearDigit3 > 57) { + return void 0; + } + const yearDigit4 = date.charCodeAt(15); + if (yearDigit4 < 48 || yearDigit4 > 57) { + return void 0; + } + const year = (yearDigit1 - 48) * 1e3 + (yearDigit2 - 48) * 100 + (yearDigit3 - 48) * 10 + (yearDigit4 - 48); + let hour = 0; + if (date[17] === "0") { + const code = date.charCodeAt(18); + if (code < 48 || code > 57) { + return void 0; + } + hour = code - 48; + } else { + const code1 = date.charCodeAt(17); + if (code1 < 48 || code1 > 50) { + return void 0; + } + const code2 = date.charCodeAt(18); + if (code2 < 48 || code2 > 57) { + return void 0; + } + if (code1 === 50 && code2 > 51) { + return void 0; + } + hour = (code1 - 48) * 10 + (code2 - 48); + } + let minute = 0; + if (date[20] === "0") { + const code = date.charCodeAt(21); + if (code < 48 || code > 57) { + return void 0; + } + minute = code - 48; + } else { + const code1 = date.charCodeAt(20); + if (code1 < 48 || code1 > 53) { + return void 0; + } + const code2 = date.charCodeAt(21); + if (code2 < 48 || code2 > 57) { + return void 0; + } + minute = (code1 - 48) * 10 + (code2 - 48); + } + let second = 0; + if (date[23] === "0") { + const code = date.charCodeAt(24); + if (code < 48 || code > 57) { + return void 0; + } + second = code - 48; + } else { + const code1 = date.charCodeAt(23); + if (code1 < 48 || code1 > 53) { + return void 0; + } + const code2 = date.charCodeAt(24); + if (code2 < 48 || code2 > 57) { + return void 0; + } + second = (code1 - 48) * 10 + (code2 - 48); + } + return makeDate(year, monthIdx, day, hour, minute, second, weekday); + } + function parseAscTimeDate(date) { + if (date.length !== 24 || date[7] !== " " || date[10] !== " " || date[19] !== " ") { + return void 0; + } + let weekday = -1; + if (date[0] === "S" && date[1] === "u" && date[2] === "n") { + weekday = 0; + } else if (date[0] === "M" && date[1] === "o" && date[2] === "n") { + weekday = 1; + } else if (date[0] === "T" && date[1] === "u" && date[2] === "e") { + weekday = 2; + } else if (date[0] === "W" && date[1] === "e" && date[2] === "d") { + weekday = 3; + } else if (date[0] === "T" && date[1] === "h" && date[2] === "u") { + weekday = 4; + } else if (date[0] === "F" && date[1] === "r" && date[2] === "i") { + weekday = 5; + } else if (date[0] === "S" && date[1] === "a" && date[2] === "t") { + weekday = 6; + } else { + return void 0; + } + let monthIdx = -1; + if (date[4] === "J" && date[5] === "a" && date[6] === "n") { + monthIdx = 0; + } else if (date[4] === "F" && date[5] === "e" && date[6] === "b") { + monthIdx = 1; + } else if (date[4] === "M" && date[5] === "a") { + if (date[6] === "r") { + monthIdx = 2; + } else if (date[6] === "y") { + monthIdx = 4; + } else { + return void 0; + } + } else if (date[4] === "J") { + if (date[5] === "a" && date[6] === "n") { + monthIdx = 0; + } else if (date[5] === "u") { + if (date[6] === "n") { + monthIdx = 5; + } else if (date[6] === "l") { + monthIdx = 6; + } else { + return void 0; + } + } else { + return void 0; + } + } else if (date[4] === "A") { + if (date[5] === "p" && date[6] === "r") { + monthIdx = 3; + } else if (date[5] === "u" && date[6] === "g") { + monthIdx = 7; + } else { + return void 0; + } + } else if (date[4] === "S" && date[5] === "e" && date[6] === "p") { + monthIdx = 8; + } else if (date[4] === "O" && date[5] === "c" && date[6] === "t") { + monthIdx = 9; + } else if (date[4] === "N" && date[5] === "o" && date[6] === "v") { + monthIdx = 10; + } else if (date[4] === "D" && date[5] === "e" && date[6] === "c") { + monthIdx = 11; + } else { + return void 0; + } + let day = 0; + if (date[8] === " ") { + const code = date.charCodeAt(9); + if (code < 49 || code > 57) { + return void 0; + } + day = code - 48; + } else { + const code1 = date.charCodeAt(8); + if (code1 < 49 || code1 > 51) { + return void 0; + } + const code2 = date.charCodeAt(9); + if (code2 < 48 || code2 > 57) { + return void 0; + } + day = (code1 - 48) * 10 + (code2 - 48); + } + let hour = 0; + if (date[11] === "0") { + const code = date.charCodeAt(12); + if (code < 48 || code > 57) { + return void 0; + } + hour = code - 48; + } else { + const code1 = date.charCodeAt(11); + if (code1 < 48 || code1 > 50) { + return void 0; + } + const code2 = date.charCodeAt(12); + if (code2 < 48 || code2 > 57) { + return void 0; + } + if (code1 === 50 && code2 > 51) { + return void 0; + } + hour = (code1 - 48) * 10 + (code2 - 48); + } + let minute = 0; + if (date[14] === "0") { + const code = date.charCodeAt(15); + if (code < 48 || code > 57) { + return void 0; + } + minute = code - 48; + } else { + const code1 = date.charCodeAt(14); + if (code1 < 48 || code1 > 53) { + return void 0; + } + const code2 = date.charCodeAt(15); + if (code2 < 48 || code2 > 57) { + return void 0; + } + minute = (code1 - 48) * 10 + (code2 - 48); + } + let second = 0; + if (date[17] === "0") { + const code = date.charCodeAt(18); + if (code < 48 || code > 57) { + return void 0; + } + second = code - 48; + } else { + const code1 = date.charCodeAt(17); + if (code1 < 48 || code1 > 53) { + return void 0; + } + const code2 = date.charCodeAt(18); + if (code2 < 48 || code2 > 57) { + return void 0; + } + second = (code1 - 48) * 10 + (code2 - 48); + } + const yearDigit1 = date.charCodeAt(20); + if (yearDigit1 < 48 || yearDigit1 > 57) { + return void 0; + } + const yearDigit2 = date.charCodeAt(21); + if (yearDigit2 < 48 || yearDigit2 > 57) { + return void 0; + } + const yearDigit3 = date.charCodeAt(22); + if (yearDigit3 < 48 || yearDigit3 > 57) { + return void 0; + } + const yearDigit4 = date.charCodeAt(23); + if (yearDigit4 < 48 || yearDigit4 > 57) { + return void 0; + } + const year = (yearDigit1 - 48) * 1e3 + (yearDigit2 - 48) * 100 + (yearDigit3 - 48) * 10 + (yearDigit4 - 48); + return makeDate(year, monthIdx, day, hour, minute, second, weekday); + } + function parseRfc850Date(date) { + let commaIndex = -1; + let weekday = -1; + if (date[0] === "S") { + if (date[1] === "u" && date[2] === "n" && date[3] === "d" && date[4] === "a" && date[5] === "y") { + weekday = 0; + commaIndex = 6; + } else if (date[1] === "a" && date[2] === "t" && date[3] === "u" && date[4] === "r" && date[5] === "d" && date[6] === "a" && date[7] === "y") { + weekday = 6; + commaIndex = 8; + } + } else if (date[0] === "M" && date[1] === "o" && date[2] === "n" && date[3] === "d" && date[4] === "a" && date[5] === "y") { + weekday = 1; + commaIndex = 6; + } else if (date[0] === "T") { + if (date[1] === "u" && date[2] === "e" && date[3] === "s" && date[4] === "d" && date[5] === "a" && date[6] === "y") { + weekday = 2; + commaIndex = 7; + } else if (date[1] === "h" && date[2] === "u" && date[3] === "r" && date[4] === "s" && date[5] === "d" && date[6] === "a" && date[7] === "y") { + weekday = 4; + commaIndex = 8; + } + } else if (date[0] === "W" && date[1] === "e" && date[2] === "d" && date[3] === "n" && date[4] === "e" && date[5] === "s" && date[6] === "d" && date[7] === "a" && date[8] === "y") { + weekday = 3; + commaIndex = 9; + } else if (date[0] === "F" && date[1] === "r" && date[2] === "i" && date[3] === "d" && date[4] === "a" && date[5] === "y") { + weekday = 5; + commaIndex = 6; + } else { + return void 0; + } + if (date[commaIndex] !== "," || date.length - commaIndex - 1 !== 23 || date[commaIndex + 1] !== " " || date[commaIndex + 4] !== "-" || date[commaIndex + 8] !== "-" || date[commaIndex + 11] !== " " || date[commaIndex + 14] !== ":" || date[commaIndex + 17] !== ":" || date[commaIndex + 20] !== " " || date[commaIndex + 21] !== "G" || date[commaIndex + 22] !== "M" || date[commaIndex + 23] !== "T") { + return void 0; + } + let day = 0; + if (date[commaIndex + 2] === "0") { + const code = date.charCodeAt(commaIndex + 3); + if (code < 49 || code > 57) { + return void 0; + } + day = code - 48; + } else { + const code1 = date.charCodeAt(commaIndex + 2); + if (code1 < 49 || code1 > 51) { + return void 0; + } + const code2 = date.charCodeAt(commaIndex + 3); + if (code2 < 48 || code2 > 57) { + return void 0; + } + day = (code1 - 48) * 10 + (code2 - 48); + } + let monthIdx = -1; + if (date[commaIndex + 5] === "J" && date[commaIndex + 6] === "a" && date[commaIndex + 7] === "n") { + monthIdx = 0; + } else if (date[commaIndex + 5] === "F" && date[commaIndex + 6] === "e" && date[commaIndex + 7] === "b") { + monthIdx = 1; + } else if (date[commaIndex + 5] === "M" && date[commaIndex + 6] === "a" && date[commaIndex + 7] === "r") { + monthIdx = 2; + } else if (date[commaIndex + 5] === "A" && date[commaIndex + 6] === "p" && date[commaIndex + 7] === "r") { + monthIdx = 3; + } else if (date[commaIndex + 5] === "M" && date[commaIndex + 6] === "a" && date[commaIndex + 7] === "y") { + monthIdx = 4; + } else if (date[commaIndex + 5] === "J" && date[commaIndex + 6] === "u" && date[commaIndex + 7] === "n") { + monthIdx = 5; + } else if (date[commaIndex + 5] === "J" && date[commaIndex + 6] === "u" && date[commaIndex + 7] === "l") { + monthIdx = 6; + } else if (date[commaIndex + 5] === "A" && date[commaIndex + 6] === "u" && date[commaIndex + 7] === "g") { + monthIdx = 7; + } else if (date[commaIndex + 5] === "S" && date[commaIndex + 6] === "e" && date[commaIndex + 7] === "p") { + monthIdx = 8; + } else if (date[commaIndex + 5] === "O" && date[commaIndex + 6] === "c" && date[commaIndex + 7] === "t") { + monthIdx = 9; + } else if (date[commaIndex + 5] === "N" && date[commaIndex + 6] === "o" && date[commaIndex + 7] === "v") { + monthIdx = 10; + } else if (date[commaIndex + 5] === "D" && date[commaIndex + 6] === "e" && date[commaIndex + 7] === "c") { + monthIdx = 11; + } else { + return void 0; + } + const yearDigit1 = date.charCodeAt(commaIndex + 9); + if (yearDigit1 < 48 || yearDigit1 > 57) { + return void 0; + } + const yearDigit2 = date.charCodeAt(commaIndex + 10); + if (yearDigit2 < 48 || yearDigit2 > 57) { + return void 0; + } + let year = (yearDigit1 - 48) * 10 + (yearDigit2 - 48); + year += year < 70 ? 2e3 : 1900; + let hour = 0; + if (date[commaIndex + 12] === "0") { + const code = date.charCodeAt(commaIndex + 13); + if (code < 48 || code > 57) { + return void 0; + } + hour = code - 48; + } else { + const code1 = date.charCodeAt(commaIndex + 12); + if (code1 < 48 || code1 > 50) { + return void 0; + } + const code2 = date.charCodeAt(commaIndex + 13); + if (code2 < 48 || code2 > 57) { + return void 0; + } + if (code1 === 50 && code2 > 51) { + return void 0; + } + hour = (code1 - 48) * 10 + (code2 - 48); + } + let minute = 0; + if (date[commaIndex + 15] === "0") { + const code = date.charCodeAt(commaIndex + 16); + if (code < 48 || code > 57) { + return void 0; + } + minute = code - 48; + } else { + const code1 = date.charCodeAt(commaIndex + 15); + if (code1 < 48 || code1 > 53) { + return void 0; + } + const code2 = date.charCodeAt(commaIndex + 16); + if (code2 < 48 || code2 > 57) { + return void 0; + } + minute = (code1 - 48) * 10 + (code2 - 48); + } + let second = 0; + if (date[commaIndex + 18] === "0") { + const code = date.charCodeAt(commaIndex + 19); + if (code < 48 || code > 57) { + return void 0; + } + second = code - 48; + } else { + const code1 = date.charCodeAt(commaIndex + 18); + if (code1 < 48 || code1 > 53) { + return void 0; + } + const code2 = date.charCodeAt(commaIndex + 19); + if (code2 < 48 || code2 > 57) { + return void 0; + } + second = (code1 - 48) * 10 + (code2 - 48); + } + return makeDate(year, monthIdx, day, hour, minute, second, weekday); + } + module2.exports = { + parseHttpDate + }; + } +}); + +// node_modules/undici/lib/handler/cache-handler.js +var require_cache_handler = __commonJS({ + "node_modules/undici/lib/handler/cache-handler.js"(exports2, module2) { + "use strict"; + var util4 = require_util(); + var { kRedirectCacheControl } = require_symbols(); + var { + parseCacheControlHeader, + hasInvalidCacheControlDirective, + parseVaryHeader, + hasVaryStar, + isInvalidOrWildcardVaryHeader, + isEtagUsable + } = require_cache(); + var { parseHttpDate } = require_date(); + function noop3() { + } + function sameOrigin(a, b) { + try { + return new URL(String(a)).origin === new URL(String(b)).origin; + } catch { + return String(a) === String(b); + } + } + var HEURISTICALLY_CACHEABLE_STATUS_CODES = [ + 200, + 203, + 204, + 206, + 300, + 301, + 308, + 404, + 405, + 410, + 414, + 501 + ]; + var NOT_UNDERSTOOD_STATUS_CODES = [ + 206 + ]; + var MAX_RESPONSE_AGE = 2147483647e3; + function trimOWS(value) { + return value.replace(/^[\t ]+|[\t ]+$/g, ""); + } + function arrayIncludes(array2, value) { + for (let i = 0; i < array2.length; i++) { + if (array2[i] === value) { + return true; + } + } + return false; + } + function appendConnectionHeaderTokens(headersToRemove, connectionHeader) { + const values = Array.isArray(connectionHeader) ? connectionHeader : [connectionHeader]; + for (let i = 0; i < values.length; i++) { + const tokens = values[i].split(","); + for (let j = 0; j < tokens.length; j++) { + headersToRemove.push(trimOWS(tokens[j]).toLowerCase()); + } + } + } + function getSameOriginPath(cacheKey3, location) { + if (typeof location !== "string") { + return void 0; + } + let originUrl; + let requestUrl; + let locationUrl; + try { + originUrl = new URL(cacheKey3.origin); + requestUrl = new URL(cacheKey3.path, originUrl); + locationUrl = new URL(location, requestUrl); + } catch { + return void 0; + } + if (locationUrl.origin !== originUrl.origin) { + return void 0; + } + return locationUrl.pathname + locationUrl.search; + } + function deleteCachedUri(store, cacheKey3, path30) { + deleteCachedValue(store, { + ...cacheKey3, + path: path30 + }); + for (let i = 0; i < util4.safeHTTPMethods.length; i++) { + const method = util4.safeHTTPMethods[i]; + if (method !== cacheKey3.method) { + deleteCachedValue(store, { + ...cacheKey3, + method, + path: path30 + }); + } + } + } + function deleteLocationTargets(store, cacheKey3, headerValue) { + if (headerValue === void 0) { + return; + } + const values = Array.isArray(headerValue) ? headerValue : [headerValue]; + for (let i = 0; i < values.length; i++) { + const path30 = getSameOriginPath(cacheKey3, values[i]); + if (path30 !== void 0) { + deleteCachedUri(store, cacheKey3, path30); + } + } + } + function invalidateUnsafeRequest(store, cacheKey3, resHeaders) { + deleteCachedUri(store, cacheKey3, cacheKey3.path); + deleteLocationTargets(store, cacheKey3, resHeaders.location); + deleteLocationTargets(store, cacheKey3, resHeaders["content-location"]); + } + var CacheHandler = class { + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheKey} + */ + #cacheKey; + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions['type']} + */ + #cacheType; + /** + * @type {number | undefined} + */ + #cacheByDefault; + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheStore} + */ + #store; + /** + * @type {import('../../types/dispatcher.d.ts').default.DispatchHandler} + */ + #handler; + /** + * @type {import('node:stream').Writable | undefined} + */ + #writeStream; + /** + * The URLs visited while following redirects, shared by reference from the + * redirect handler through the request context. Carries the suppressed hops' + * cache-control under {@link kRedirectCacheControl}. + * @type {URL[] | undefined} + */ + #history; + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} opts + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey + * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler + */ + constructor({ store, type, cacheByDefault }, cacheKey3, handler2) { + this.#store = store; + this.#cacheType = type; + this.#cacheByDefault = cacheByDefault; + this.#cacheKey = cacheKey3; + this.#handler = handler2; + } + onRequestStart(controller, context5) { + this.#writeStream?.destroy(); + this.#writeStream = void 0; + this.#history = context5?.history; + this.#handler.onRequestStart?.(controller, context5); + } + onRequestUpgrade(controller, statusCode, headers, socket) { + this.#handler.onRequestUpgrade?.(controller, statusCode, headers, socket); + } + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {number} statusCode + * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders + * @param {string} statusMessage + */ + onResponseStart(controller, statusCode, resHeaders, statusMessage) { + const downstreamOnHeaders = () => this.#handler.onResponseStart?.( + controller, + statusCode, + resHeaders, + statusMessage + ); + const handler2 = this; + if (!arrayIncludes(util4.safeHTTPMethods, this.#cacheKey.method) && statusCode >= 200 && statusCode <= 399) { + invalidateUnsafeRequest(this.#store, this.#cacheKey, resHeaders); + return downstreamOnHeaders(); + } + if (this.#history && this.#history.length > 0) { + const finalUrl = this.#history[this.#history.length - 1]; + if (!sameOrigin(finalUrl.origin, this.#cacheKey.origin)) { + return downstreamOnHeaders(); + } + } + const redirectCacheControl = this.#history?.[kRedirectCacheControl]; + if (redirectCacheControl) { + for (const hopCacheControl of redirectCacheControl) { + const hopDirectives = hopCacheControl ? parseCacheControlHeader(hopCacheControl) : {}; + if (hopDirectives["no-store"] === true || this.#cacheType === "shared" && hopDirectives.private === true) { + return downstreamOnHeaders(); + } + } + } + const cacheControlHeader = resHeaders["cache-control"]; + const cacheControlDirectives = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {}; + if (revalidationResponseDisallowsCachedReuse(this.#cacheType, resHeaders, cacheControlDirectives)) { + deleteCachedValue(this.#store, this.#cacheKey); + return downstreamOnHeaders(); + } + const heuristicallyCacheable = resHeaders["last-modified"] && arrayIncludes(HEURISTICALLY_CACHEABLE_STATUS_CODES, statusCode); + if (!cacheControlHeader && !resHeaders["expires"] && !heuristicallyCacheable && !this.#cacheByDefault) { + if (statusCode === 304 && resHeaders.vary && isInvalidOrWildcardVaryHeader(resHeaders.vary)) { + deleteCachedValue(this.#store, this.#cacheKey); + } + return downstreamOnHeaders(); + } + if (!canCacheResponse(this.#cacheType, this.#cacheKey.method, statusCode, resHeaders, cacheControlDirectives, this.#cacheKey.headers)) { + if (statusCode === 304 && (cacheControlHeader || revalidationResponseDisallowsCachedReuse(this.#cacheType, resHeaders, cacheControlDirectives))) { + deleteCachedValue(this.#store, this.#cacheKey); + } + return downstreamOnHeaders(); + } + const now = Date.now(); + const resAge = Object.hasOwn(resHeaders, "age") ? getAge(resHeaders.age) : void 0; + if (resAge !== void 0 && resAge >= MAX_RESPONSE_AGE) { + deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); + return downstreamOnHeaders(); + } + const resDate = Object.hasOwn(resHeaders, "date") ? getDate2(resHeaders.date) : void 0; + if (resDate === null) { + deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); + return downstreamOnHeaders(); + } + const apparentAge = resDate ? Math.max(0, now - resDate.getTime()) : 0; + const currentAge = Math.max(apparentAge, resAge ?? 0); + const staleAt = determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives) ?? this.#cacheByDefault; + if (staleAt === void 0 || currentAge >= staleAt) { + if (cacheControlHeader || staleAt !== void 0) { + deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); + } + return downstreamOnHeaders(); + } + const baseTime = now - currentAge; + const absoluteStaleAt = staleAt + baseTime; + if (now >= absoluteStaleAt) { + deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); + return downstreamOnHeaders(); + } + let varyDirectives; + if (this.#cacheKey.headers && resHeaders.vary) { + varyDirectives = parseVaryHeader(resHeaders.vary, this.#cacheKey.headers); + if (!varyDirectives) { + return downstreamOnHeaders(); + } + } + const cachedAt = baseTime; + const deleteAt = determineDeleteAt(baseTime, now, cacheControlDirectives, absoluteStaleAt); + const strippedHeaders = stripNecessaryHeaders(resHeaders, cacheControlDirectives); + const value = { + statusCode, + statusMessage, + headers: strippedHeaders, + vary: varyDirectives, + cacheControlDirectives, + cachedAt, + staleAt: absoluteStaleAt, + deleteAt + }; + if (statusCode === 304) { + const handle304 = (cachedValue) => { + if (!cachedValue) { + return downstreamOnHeaders(); + } + value.statusCode = cachedValue.statusCode; + value.statusMessage = cachedValue.statusMessage; + value.etag = cachedValue.etag; + value.vary = varyDirectives ?? cachedValue.vary; + value.headers = { ...cachedValue.headers, ...strippedHeaders }; + downstreamOnHeaders(); + this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value); + if (!this.#writeStream || !cachedValue?.body) { + return; + } + if (typeof cachedValue.body.values === "function") { + const bodyIterator = cachedValue.body.values(); + const streamCachedBody = () => { + for (const chunk of bodyIterator) { + const full = this.#writeStream.write(chunk) === false; + this.#handler.onResponseData?.(controller, chunk); + if (full) { + break; + } + } + }; + this.#writeStream.on("error", function() { + handler2.#writeStream = void 0; + handler2.#store.delete(handler2.#cacheKey); + }).on("drain", () => { + streamCachedBody(); + }).on("close", function() { + if (handler2.#writeStream === this) { + handler2.#writeStream = void 0; + } + }); + streamCachedBody(); + } else if (typeof cachedValue.body.on === "function") { + cachedValue.body.on("data", (chunk) => { + this.#writeStream.write(chunk); + this.#handler.onResponseData?.(controller, chunk); + }).on("end", () => { + this.#writeStream.end(); + }).on("error", () => { + this.#writeStream = void 0; + this.#store.delete(this.#cacheKey); + }); + this.#writeStream.on("error", function() { + handler2.#writeStream = void 0; + handler2.#store.delete(handler2.#cacheKey); + }).on("close", function() { + if (handler2.#writeStream === this) { + handler2.#writeStream = void 0; + } + }); + } + }; + const result = this.#store.get(this.#cacheKey); + if (result && typeof result.then === "function") { + result.then(handle304); + } else { + handle304(result); + } + } else { + if (typeof resHeaders.etag === "string" && isEtagUsable(resHeaders.etag)) { + value.etag = resHeaders.etag; + } + this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value); + if (!this.#writeStream) { + return downstreamOnHeaders(); + } + this.#writeStream.on("drain", () => controller.resume()).on("error", function() { + handler2.#writeStream = void 0; + handler2.#store.delete(handler2.#cacheKey); + }).on("close", function() { + if (handler2.#writeStream === this) { + handler2.#writeStream = void 0; + } + controller.resume(); + }); + downstreamOnHeaders(); + } + } + onResponseData(controller, chunk) { + if (this.#writeStream?.write(chunk) === false) { + controller.pause(); + } + this.#handler.onResponseData?.(controller, chunk); + } + onResponseEnd(controller, trailers) { + this.#writeStream?.end(); + this.#handler.onResponseEnd?.(controller, trailers); + } + onResponseError(controller, err) { + this.#writeStream?.destroy(err); + this.#writeStream = void 0; + this.#handler.onResponseError?.(controller, err); + } + }; + function deleteCachedValue(store, cacheKey3) { + try { + store.delete(cacheKey3)?.catch?.(noop3); + } catch { + } + } + function deleteCachedValueIfNotModified(statusCode, store, cacheKey3) { + if (statusCode === 304) { + deleteCachedValue(store, cacheKey3); + } + } + function revalidationResponseDisallowsCachedReuse(cacheType, resHeaders, cacheControlDirectives) { + return cacheControlDirectives["no-store"] === true || cacheType === "shared" && (cacheControlDirectives.private === true || Object.hasOwn(resHeaders, "set-cookie")) || (resHeaders.vary ? isInvalidOrWildcardVaryHeader(resHeaders.vary) : false); + } + function canCacheResponse(cacheType, method, statusCode, resHeaders, cacheControlDirectives, reqHeaders) { + if (!arrayIncludes(util4.safeHTTPMethods, method)) { + return false; + } + if (statusCode < 200 || arrayIncludes(NOT_UNDERSTOOD_STATUS_CODES, statusCode)) { + return false; + } + if (!arrayIncludes(HEURISTICALLY_CACHEABLE_STATUS_CODES, statusCode) && !resHeaders["expires"] && !cacheControlDirectives.public && cacheControlDirectives["max-age"] === void 0 && // RFC 9111: a private response directive, if the cache is not shared + !(cacheControlDirectives.private && cacheType === "private") && !(cacheControlDirectives["s-maxage"] !== void 0 && cacheType === "shared")) { + return false; + } + if (cacheControlDirectives["no-store"]) { + return false; + } + if (cacheType === "shared" && (cacheControlDirectives.private === true || Object.hasOwn(resHeaders, "set-cookie"))) { + return false; + } + if (resHeaders.vary && hasVaryStar(resHeaders.vary)) { + return false; + } + if (reqHeaders != null && Object.hasOwn(reqHeaders, "authorization")) { + if (!cacheControlDirectives.public && !cacheControlDirectives["s-maxage"] && !cacheControlDirectives["must-revalidate"]) { + return false; + } + if (typeof reqHeaders.authorization !== "string") { + return false; + } + if (Array.isArray(cacheControlDirectives["no-cache"]) && arrayIncludes(cacheControlDirectives["no-cache"], "authorization")) { + return false; + } + if (Array.isArray(cacheControlDirectives["private"]) && arrayIncludes(cacheControlDirectives["private"], "authorization")) { + return false; + } + } + return true; + } + function getDate2(dateHeader) { + let dateValue = dateHeader; + if (Array.isArray(dateValue)) { + if (dateValue.length !== 1) { + return null; + } + dateValue = dateValue[0]; + } + if (typeof dateValue !== "string") { + return null; + } + return parseHttpDate(dateValue); + } + function getAge(ageHeader) { + let ageValue = ageHeader; + if (Array.isArray(ageValue)) { + if (ageValue.length !== 1) { + return MAX_RESPONSE_AGE; + } + ageValue = ageValue[0]; + } + if (typeof ageValue !== "string" || !/^[\t ]*[0-9]+[\t ]*$/.test(ageValue)) { + return MAX_RESPONSE_AGE; + } + const age = BigInt(ageValue.replace(/^[\t ]+|[\t ]+$/g, "")); + if (age >= BigInt(MAX_RESPONSE_AGE / 1e3)) { + return MAX_RESPONSE_AGE; + } + return Number(age) * 1e3; + } + function determineStaleAt(cacheType, now, age, resHeaders, responseDate, cacheControlDirectives) { + if (cacheType === "shared") { + if (hasInvalidCacheControlDirective(cacheControlDirectives, "s-maxage")) { + return 0; + } + const sMaxAge = cacheControlDirectives["s-maxage"]; + if (sMaxAge !== void 0) { + return sMaxAge * 1e3; + } + } + if (hasInvalidCacheControlDirective(cacheControlDirectives, "max-age")) { + return 0; + } + const maxAge = cacheControlDirectives["max-age"]; + if (maxAge !== void 0) { + return maxAge * 1e3; + } + if (Object.hasOwn(resHeaders, "expires")) { + if (typeof resHeaders.expires !== "string") { + return 0; + } + const expiresDate = parseHttpDate(resHeaders.expires); + if (!expiresDate) { + return 0; + } + if (now >= expiresDate.getTime()) { + return 0; + } + if (responseDate) { + if (responseDate >= expiresDate) { + return 0; + } + const freshnessLifetime = expiresDate.getTime() - responseDate.getTime(); + if (age !== void 0 && age >= freshnessLifetime) { + return 0; + } + return freshnessLifetime; + } + return expiresDate.getTime() - now; + } + if (typeof resHeaders["last-modified"] === "string") { + const lastModified = parseHttpDate(resHeaders["last-modified"]); + if (lastModified) { + if (lastModified.getTime() >= now) { + return void 0; + } + const responseAge = now - lastModified.getTime(); + return responseAge * 0.1; + } + } + if (cacheControlDirectives.immutable) { + return 31536e6; + } + return void 0; + } + function determineDeleteAt(baseTime, cachedAt, cacheControlDirectives, staleAt) { + let staleWhileRevalidate = -Infinity; + let staleIfError = -Infinity; + let immutable = -Infinity; + if (cacheControlDirectives["stale-while-revalidate"]) { + staleWhileRevalidate = staleAt + cacheControlDirectives["stale-while-revalidate"] * 1e3; + } + if (cacheControlDirectives["stale-if-error"]) { + staleIfError = staleAt + cacheControlDirectives["stale-if-error"] * 1e3; + } + if (cacheControlDirectives.immutable && staleWhileRevalidate === -Infinity && staleIfError === -Infinity) { + immutable = cachedAt + 31536e6; + } + if (staleWhileRevalidate === -Infinity && staleIfError === -Infinity && immutable === -Infinity) { + const freshnessLifetime = staleAt - baseTime; + const datePrecisionPadding = Math.min(Math.max(cachedAt - baseTime, 0), 1e3); + return staleAt + freshnessLifetime + datePrecisionPadding; + } + return Math.max(staleAt, staleWhileRevalidate, staleIfError, immutable); + } + function stripNecessaryHeaders(resHeaders, cacheControlDirectives) { + const headersToRemove = [ + "connection", + "proxy-authenticate", + "proxy-authentication-info", + "proxy-authorization", + "proxy-connection", + "te", + "transfer-encoding", + "upgrade", + // We'll add age back when serving it + "age" + ]; + if (resHeaders["connection"]) { + appendConnectionHeaderTokens(headersToRemove, resHeaders["connection"]); + } + if (Array.isArray(cacheControlDirectives["no-cache"])) { + headersToRemove.push(...cacheControlDirectives["no-cache"]); + } + if (Array.isArray(cacheControlDirectives["private"])) { + headersToRemove.push(...cacheControlDirectives["private"]); + } + let strippedHeaders; + for (const headerName of headersToRemove) { + if (Object.hasOwn(resHeaders, headerName)) { + strippedHeaders ??= { ...resHeaders }; + delete strippedHeaders[headerName]; + } + } + return strippedHeaders ?? resHeaders; + } + module2.exports = CacheHandler; + } +}); + +// node_modules/undici/lib/cache/memory-cache-store.js +var require_memory_cache_store = __commonJS({ + "node_modules/undici/lib/cache/memory-cache-store.js"(exports2, module2) { + "use strict"; + var { Writable } = require("node:stream"); + var { EventEmitter: EventEmitter2 } = require("node:events"); + var { assertCacheKey, assertCacheValue } = require_cache(); + var MemoryCacheStore = class extends EventEmitter2 { + #maxCount = 1024; + #maxSize = 104857600; + // 100MB + #maxEntrySize = 5242880; + // 5MB + #size = 0; + #count = 0; + #entries = /* @__PURE__ */ new Map(); + #hasEmittedMaxSizeEvent = false; + /** + * @param {import('../../types/cache-interceptor.d.ts').default.MemoryCacheStoreOpts | undefined} [opts] + */ + constructor(opts) { + super(); + if (opts) { + if (typeof opts !== "object") { + throw new TypeError("MemoryCacheStore options must be an object"); + } + if (opts.maxCount !== void 0) { + if (typeof opts.maxCount !== "number" || !Number.isInteger(opts.maxCount) || opts.maxCount < 0) { + throw new TypeError("MemoryCacheStore options.maxCount must be a non-negative integer"); + } + this.#maxCount = opts.maxCount; + } + if (opts.maxSize !== void 0) { + if (typeof opts.maxSize !== "number" || !Number.isInteger(opts.maxSize) || opts.maxSize < 0) { + throw new TypeError("MemoryCacheStore options.maxSize must be a non-negative integer"); + } + this.#maxSize = opts.maxSize; + } + if (opts.maxEntrySize !== void 0) { + if (typeof opts.maxEntrySize !== "number" || !Number.isInteger(opts.maxEntrySize) || opts.maxEntrySize < 0) { + throw new TypeError("MemoryCacheStore options.maxEntrySize must be a non-negative integer"); + } + this.#maxEntrySize = opts.maxEntrySize; + } + } + } + /** + * Get the current size of the cache in bytes + * @returns {number} The current size of the cache in bytes + */ + get size() { + return this.#size; + } + /** + * Check if the cache is full (either max size or max count reached) + * @returns {boolean} True if the cache is full, false otherwise + */ + isFull() { + return this.#size >= this.#maxSize || this.#count >= this.#maxCount; + } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} req + * @returns {import('../../types/cache-interceptor.d.ts').default.GetResult | undefined} + */ + get(key) { + assertCacheKey(key); + const topLevelKey = `${key.origin}:${key.path}`; + const now = Date.now(); + const entries = this.#entries.get(topLevelKey); + const entry = entries ? findEntry(key, entries, now) : null; + return entry == null ? void 0 : { + statusMessage: entry.statusMessage, + statusCode: entry.statusCode, + headers: entry.headers, + body: entry.body, + vary: entry.vary ? entry.vary : void 0, + etag: entry.etag, + cacheControlDirectives: entry.cacheControlDirectives, + cachedAt: entry.cachedAt, + staleAt: entry.staleAt, + deleteAt: entry.deleteAt + }; + } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @param {import('../../types/cache-interceptor.d.ts').default.CacheValue} val + * @returns {Writable | undefined} + */ + createWriteStream(key, val) { + assertCacheKey(key); + assertCacheValue(val); + const topLevelKey = `${key.origin}:${key.path}`; + const store = this; + const entry = { ...key, ...val, body: [], size: 0 }; + return new Writable({ + write(chunk, encoding, callback) { + if (typeof chunk === "string") { + chunk = Buffer.from(chunk, encoding); + } + entry.size += chunk.byteLength; + if (entry.size >= store.#maxEntrySize) { + this.destroy(); + } else { + entry.body.push(chunk); + } + callback(null); + }, + final(callback) { + let entries = store.#entries.get(topLevelKey); + if (!entries) { + entries = []; + store.#entries.set(topLevelKey, entries); + } + const previousEntry = findEntry(key, entries, Date.now()); + if (previousEntry) { + const index2 = entries.indexOf(previousEntry); + entries.splice(index2, 1, entry); + store.#size -= previousEntry.size; + } else { + entries.push(entry); + store.#count += 1; + } + store.#size += entry.size; + if (store.#size > store.#maxSize || store.#count > store.#maxCount) { + if (!store.#hasEmittedMaxSizeEvent) { + store.emit("maxSizeExceeded", { + size: store.#size, + maxSize: store.#maxSize, + count: store.#count, + maxCount: store.#maxCount + }); + store.#hasEmittedMaxSizeEvent = true; + } + for (const [key2, entries2] of store.#entries) { + for (const entry2 of entries2.splice(0, entries2.length / 2)) { + store.#size -= entry2.size; + store.#count -= 1; + } + if (entries2.length === 0) { + store.#entries.delete(key2); + } + } + if (store.#size < store.#maxSize && store.#count < store.#maxCount) { + store.#hasEmittedMaxSizeEvent = false; + } + } + callback(null); + } + }); + } + /** + * @param {CacheKey} key + */ + delete(key) { + if (typeof key !== "object") { + throw new TypeError(`expected key to be object, got ${typeof key}`); + } + const topLevelKey = `${key.origin}:${key.path}`; + for (const entry of this.#entries.get(topLevelKey) ?? []) { + this.#size -= entry.size; + this.#count -= 1; + } + this.#entries.delete(topLevelKey); + } + }; + function findEntry(key, entries, now) { + for (let i = 0; i < entries.length; i++) { + const entry = entries[i]; + if (entry.deleteAt > now && entry.method === key.method && varyMatches(key, entry)) { + return entry; + } + } + } + function varyMatches(key, entry) { + if (entry.vary == null) { + return true; + } + for (const headerName in entry.vary) { + if (Object.hasOwn(entry.vary, headerName) && !headerValueEquals(key.headers?.[headerName], entry.vary[headerName])) { + return false; + } + } + return true; + } + function headerValueEquals(lhs, rhs) { + if (lhs == null && rhs == null) { + return true; + } + if (lhs == null && rhs != null || lhs != null && rhs == null) { + return false; + } + if (Array.isArray(lhs) && Array.isArray(rhs)) { + if (lhs.length !== rhs.length) { + return false; + } + for (let i = 0; i < lhs.length; i++) { + if (lhs[i] !== rhs[i]) { + return false; + } + } + return true; + } + return lhs === rhs; + } + module2.exports = MemoryCacheStore; + } +}); + +// node_modules/undici/lib/handler/cache-revalidation-handler.js +var require_cache_revalidation_handler = __commonJS({ + "node_modules/undici/lib/handler/cache-revalidation-handler.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var CacheRevalidationHandler = class { + #successful = false; + /** + * @type {((success: boolean, context?: any, statusCode?: number, headers?: import('../../types/header.d.ts').IncomingHttpHeaders) => void) | null} + */ + #callback; + /** + * @type {(import('../../types/dispatcher.d.ts').default.DispatchHandler)} + */ + #handler; + #context; + /** + * @type {boolean} + */ + #allowErrorStatusCodes; + /** + * @param {(success: boolean, context?: any, statusCode?: number, headers?: import('../../types/header.d.ts').IncomingHttpHeaders) => void} callback Function to call if the cached value is valid + * @param {import('../../types/dispatcher.d.ts').default.DispatchHandlers} handler + * @param {boolean} allowErrorStatusCodes + */ + constructor(callback, handler2, allowErrorStatusCodes) { + if (typeof callback !== "function") { + throw new TypeError("callback must be a function"); + } + this.#callback = callback; + this.#handler = handler2; + this.#allowErrorStatusCodes = allowErrorStatusCodes; + } + onRequestStart(_2, context5) { + this.#successful = false; + this.#context = context5; + } + onRequestUpgrade(controller, statusCode, headers, socket) { + this.#handler.onRequestUpgrade?.(controller, statusCode, headers, socket); + } + onResponseStart(controller, statusCode, headers, statusMessage) { + assert(this.#callback != null); + this.#successful = statusCode === 304 || this.#allowErrorStatusCodes && statusCode >= 500 && statusCode <= 504; + this.#callback(this.#successful, this.#context, statusCode, headers); + this.#callback = null; + if (this.#successful) { + return true; + } + this.#handler.onRequestStart?.(controller, this.#context); + this.#handler.onResponseStart?.( + controller, + statusCode, + headers, + statusMessage + ); + } + onResponseData(controller, chunk) { + if (this.#successful) { + return; + } + return this.#handler.onResponseData?.(controller, chunk); + } + onResponseEnd(controller, trailers) { + if (this.#successful) { + return; + } + this.#handler.onResponseEnd?.(controller, trailers); + } + onResponseError(controller, err) { + if (this.#successful) { + return; + } + if (this.#callback) { + this.#callback(false); + this.#callback = null; + } + if (typeof this.#handler.onResponseError === "function") { + this.#handler.onResponseError(controller, err); + } else { + throw err; + } + } + }; + module2.exports = CacheRevalidationHandler; + } +}); + +// node_modules/undici/lib/interceptor/cache.js +var require_cache2 = __commonJS({ + "node_modules/undici/lib/interceptor/cache.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { Readable: Readable4 } = require("node:stream"); + var util4 = require_util(); + var CacheHandler = require_cache_handler(); + var MemoryCacheStore = require_memory_cache_store(); + var CacheRevalidationHandler = require_cache_revalidation_handler(); + var { assertCacheStore, assertCacheMethods, makeCacheKey, normalizeHeaders, parseCacheControlHeader, isInvalidOrWildcardVaryHeader } = require_cache(); + var { AbortError: AbortError2 } = require_errors(); + var { parseHttpDate } = require_date(); + function assertCacheOrigins(origins, name) { + if (origins === void 0) return; + if (!Array.isArray(origins)) { + throw new TypeError(`expected ${name} to be an array or undefined, got ${typeof origins}`); + } + for (let i = 0; i < origins.length; i++) { + const origin = origins[i]; + if (typeof origin !== "string" && !(origin instanceof RegExp)) { + throw new TypeError(`expected ${name}[${i}] to be a string or RegExp, got ${typeof origin}`); + } + } + } + var nop = () => { + }; + function trimOWS(value) { + return value.replace(/^[\t ]+|[\t ]+$/g, ""); + } + function arrayIncludes(array2, value) { + for (let i = 0; i < array2.length; i++) { + if (array2[i] === value) { + return true; + } + } + return false; + } + function hasPragmaNoCache(headers) { + const pragma = headers?.pragma; + if (!pragma) { + return false; + } + const values = Array.isArray(pragma) ? pragma : [pragma]; + for (let i = 0; i < values.length; i++) { + const value = values[i]; + if (typeof value !== "string") { + continue; + } + const directives = value.split(","); + for (let j = 0; j < directives.length; j++) { + if (trimOWS(directives[j]).toLowerCase() === "no-cache") { + return true; + } + } + } + return false; + } + function needsRevalidation(result, cacheControlDirectives, { headers = {} }) { + if (cacheControlDirectives?.["no-cache"]) { + return true; + } + if (result.cacheControlDirectives?.["no-cache"] && !Array.isArray(result.cacheControlDirectives["no-cache"])) { + return true; + } + if (headers["if-modified-since"] || headers["if-none-match"]) { + return true; + } + return false; + } + function staleResponseRequiresRevalidation(result, cacheType) { + return result.cacheControlDirectives?.["must-revalidate"] === true || cacheType === "shared" && (result.cacheControlDirectives?.["proxy-revalidate"] === true || // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.2.10 + // s-maxage implies proxy-revalidate for shared caches. + result.cacheControlDirectives?.["s-maxage"] !== void 0); + } + function revalidationResponseDisallowsCachedReuse(cacheType, headers) { + if (headers.vary && isInvalidOrWildcardVaryHeader(headers.vary) || cacheType === "shared" && Object.hasOwn(headers, "set-cookie")) { + return true; + } + const cacheControl = headers["cache-control"]; + if (!cacheControl) { + return false; + } + const cacheControlDirectives = parseCacheControlHeader(cacheControl); + return cacheControlDirectives["no-store"] === true || cacheType === "shared" && cacheControlDirectives.private === true; + } + function revalidationResponseUpdatesCacheControl(headers) { + return headers["cache-control"] !== void 0; + } + function deleteCachedValue(store, cacheKey3) { + try { + store.delete(cacheKey3)?.catch?.(nop); + } catch { + } + } + function getUsableLastModified(headers) { + const lastModified = headers?.["last-modified"]; + if (typeof lastModified === "string" && parseHttpDate(lastModified)) { + return lastModified; + } + } + function makeRevalidationHeaders(opts, result) { + const headers = { + ...opts.headers, + "if-modified-since": getUsableLastModified(result.headers) ?? new Date(result.cachedAt).toUTCString() + }; + if (result.etag) { + headers["if-none-match"] = result.etag; + } + if (result.vary) { + for (const key in result.vary) { + if (result.vary[key] != null) { + headers[key] = result.vary[key]; + } + } + } + return headers; + } + function isStale(result, cacheControlDirectives, cacheType) { + const now = Date.now(); + if (now > result.staleAt) { + if (!staleResponseRequiresRevalidation(result, cacheType) && cacheControlDirectives?.["max-stale"]) { + const gracePeriod = result.staleAt + cacheControlDirectives["max-stale"] * 1e3; + return now > gracePeriod; + } + return true; + } + if (cacheControlDirectives?.["min-fresh"]) { + const timeLeftTillStale = result.staleAt - now; + const threshold = cacheControlDirectives["min-fresh"] * 1e3; + return timeLeftTillStale <= threshold; + } + return false; + } + function withinStaleWhileRevalidateWindow(result, cacheType) { + const staleWhileRevalidate = result.cacheControlDirectives?.["stale-while-revalidate"]; + if (!staleWhileRevalidate || staleResponseRequiresRevalidation(result, cacheType)) { + return false; + } + const now = Date.now(); + const staleWhileRevalidateExpiry = result.staleAt + staleWhileRevalidate * 1e3; + return now <= staleWhileRevalidateExpiry; + } + function handleUncachedResponse(dispatch, globalOpts, cacheKey3, handler2, opts, reqCacheControl) { + if (reqCacheControl?.["only-if-cached"]) { + let aborted = false; + try { + if (typeof handler2.onConnect === "function") { + handler2.onConnect(() => { + aborted = true; + }); + if (aborted) { + return; + } + } + if (typeof handler2.onHeaders === "function") { + handler2.onHeaders(504, [], nop, "Gateway Timeout"); + if (aborted) { + return; + } + } + if (typeof handler2.onComplete === "function") { + handler2.onComplete([]); + } + } catch (err) { + if (typeof handler2.onError === "function") { + handler2.onError(err); + } + } + return true; + } + return dispatch(opts, new CacheHandler(globalOpts, cacheKey3, handler2)); + } + function sendCachedValue(handler2, opts, result, age, context5, isStale2) { + const stream2 = util4.isStream(result.body) ? result.body : Readable4.from(result.body ?? []); + assert(!stream2.destroyed, "stream should not be destroyed"); + assert(!stream2.readableDidRead, "stream should not be readableDidRead"); + const controller = { + resume() { + stream2.resume(); + }, + pause() { + stream2.pause(); + }, + get paused() { + return stream2.isPaused(); + }, + get aborted() { + return stream2.destroyed; + }, + get reason() { + return stream2.errored; + }, + abort(reason) { + stream2.destroy(reason ?? new AbortError2()); + } + }; + stream2.on("error", function(err) { + if (!this.readableEnded) { + if (typeof handler2.onResponseError === "function") { + handler2.onResponseError(controller, err); + } else { + throw err; + } + } + }).on("close", function() { + if (!this.errored) { + handler2.onResponseEnd?.(controller, {}); + } + }); + handler2.onRequestStart?.(controller, context5); + if (stream2.destroyed) { + return; + } + const headers = { ...result.headers, age: String(age) }; + if (isStale2) { + headers.warning = '110 - "response is stale"'; + } + handler2.onResponseStart?.(controller, result.statusCode, headers, result.statusMessage); + if (opts.method === "HEAD") { + stream2.destroy(); + } else { + stream2.on("data", function(chunk) { + handler2.onResponseData?.(controller, chunk); + }); + } + } + function handleResult(dispatch, globalOpts, cacheKey3, handler2, opts, reqCacheControl, result) { + if (!result) { + return handleUncachedResponse(dispatch, globalOpts, cacheKey3, handler2, opts, reqCacheControl); + } + if (globalOpts.type === "shared" && Object.hasOwn(result.headers, "set-cookie")) { + if (util4.isStream(result.body)) { + result.body.on("error", nop).destroy(); + } + deleteCachedValue(globalOpts.store, cacheKey3); + return handleUncachedResponse(dispatch, globalOpts, cacheKey3, handler2, opts, reqCacheControl); + } + const now = Date.now(); + if (now > result.deleteAt) { + return dispatch(opts, new CacheHandler(globalOpts, cacheKey3, handler2)); + } + const age = Math.round((now - result.cachedAt) / 1e3); + const requestMaxAgeExpired = reqCacheControl?.["max-age"] !== void 0 && age >= reqCacheControl["max-age"]; + const stale = requestMaxAgeExpired || isStale(result, reqCacheControl, globalOpts.type); + const revalidate = requestMaxAgeExpired || needsRevalidation(result, reqCacheControl, opts); + if (stale || revalidate) { + if (util4.isStream(opts.body) && util4.bodyLength(opts.body) !== 0) { + return dispatch(opts, new CacheHandler(globalOpts, cacheKey3, handler2)); + } + if (!revalidate && withinStaleWhileRevalidateWindow(result, globalOpts.type)) { + sendCachedValue(handler2, opts, result, age, null, true); + queueMicrotask(() => { + const headers2 = makeRevalidationHeaders(opts, result); + dispatch( + { + ...opts, + headers: headers2 + }, + new CacheHandler(globalOpts, cacheKey3, { + // Silent handler that just updates the cache + onRequestStart() { + }, + onRequestUpgrade() { + }, + onResponseStart() { + }, + onResponseData() { + }, + onResponseEnd() { + }, + onResponseError() { + } + }) + ); + }); + return true; + } + let withinStaleIfErrorThreshold = false; + if (!staleResponseRequiresRevalidation(result, globalOpts.type)) { + const staleIfErrorExpiry = result.cacheControlDirectives["stale-if-error"] ?? reqCacheControl?.["stale-if-error"]; + if (staleIfErrorExpiry) { + withinStaleIfErrorThreshold = now < result.staleAt + staleIfErrorExpiry * 1e3; + } + } + const headers = makeRevalidationHeaders(opts, result); + return dispatch( + { + ...opts, + headers + }, + new CacheRevalidationHandler( + (success, context5, statusCode, headers2) => { + if (success) { + if (statusCode === 304) { + if (revalidationResponseDisallowsCachedReuse(globalOpts.type, headers2)) { + if (util4.isStream(result.body)) { + result.body.on("error", nop).destroy(); + } + deleteCachedValue(globalOpts.store, cacheKey3); + return dispatch(opts, new CacheHandler(globalOpts, cacheKey3, handler2)); + } + if (revalidationResponseUpdatesCacheControl(headers2)) { + deleteCachedValue(globalOpts.store, cacheKey3); + } + } + sendCachedValue(handler2, opts, result, age, context5, stale); + } else if (util4.isStream(result.body)) { + result.body.on("error", nop).destroy(); + } + }, + new CacheHandler(globalOpts, cacheKey3, handler2), + withinStaleIfErrorThreshold + ) + ); + } + if (util4.isStream(opts.body)) { + opts.body.on("error", nop).destroy(); + } + sendCachedValue(handler2, opts, result, age, null, false); + } + module2.exports = (opts = {}) => { + const { + store = new MemoryCacheStore(), + methods = ["GET"], + cacheByDefault = void 0, + type = "shared", + origins = void 0 + } = opts; + if (typeof opts !== "object" || opts === null) { + throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? "null" : typeof opts}`); + } + assertCacheStore(store, "opts.store"); + assertCacheMethods(methods, "opts.methods"); + assertCacheOrigins(origins, "opts.origins"); + if (typeof cacheByDefault !== "undefined" && typeof cacheByDefault !== "number") { + throw new TypeError(`expected opts.cacheByDefault to be number or undefined, got ${typeof cacheByDefault}`); + } + if (typeof type !== "undefined" && type !== "shared" && type !== "private") { + throw new TypeError(`expected opts.type to be shared, private, or undefined, got ${typeof type}`); + } + const globalOpts = { + store, + methods, + cacheByDefault, + type + }; + const safeMethodsToNotCache = []; + for (let i = 0; i < util4.safeHTTPMethods.length; i++) { + const method = util4.safeHTTPMethods[i]; + if (!arrayIncludes(methods, method)) { + safeMethodsToNotCache.push(method); + } + } + return (dispatch) => { + return (opts2, handler2) => { + if (!opts2.origin || arrayIncludes(safeMethodsToNotCache, opts2.method)) { + return dispatch(opts2, handler2); + } + if (origins !== void 0) { + const requestOrigin = opts2.origin.toString().toLowerCase(); + let isAllowed = false; + for (let i = 0; i < origins.length; i++) { + const allowed = origins[i]; + if (typeof allowed === "string") { + if (allowed.toLowerCase() === requestOrigin) { + isAllowed = true; + break; + } + } else if (allowed.test(requestOrigin)) { + isAllowed = true; + break; + } + } + if (!isAllowed) { + return dispatch(opts2, handler2); + } + } + opts2 = { + ...opts2, + headers: normalizeHeaders(opts2) + }; + const reqCacheControl = opts2.headers?.["cache-control"] ? parseCacheControlHeader(opts2.headers["cache-control"]) : hasPragmaNoCache(opts2.headers) ? { "no-cache": true } : void 0; + if (reqCacheControl?.["no-store"]) { + return dispatch(opts2, handler2); + } + const cacheKey3 = makeCacheKey(opts2); + if (!arrayIncludes(util4.safeHTTPMethods, opts2.method)) { + return dispatch(opts2, new CacheHandler(globalOpts, cacheKey3, handler2)); + } + const result = store.get(cacheKey3); + if (result && typeof result.then === "function") { + return result.then((result2) => handleResult( + dispatch, + globalOpts, + cacheKey3, + handler2, + opts2, + reqCacheControl, + result2 + )); + } else { + return handleResult( + dispatch, + globalOpts, + cacheKey3, + handler2, + opts2, + reqCacheControl, + result + ); + } + }; + }; + }; + } +}); + +// node_modules/undici/lib/interceptor/decompress.js +var require_decompress = __commonJS({ + "node_modules/undici/lib/interceptor/decompress.js"(exports2, module2) { + "use strict"; + var { createInflate, createGunzip, createBrotliDecompress, createZstdDecompress } = require("node:zlib"); + var { pipeline: pipeline2, Transform: TransformStream2 } = require("node:stream"); + var { InvalidArgumentError, ResponseExceededMaxSizeError } = require_errors(); + var DecoratorHandler = require_decorator_handler(); + var { runtimeFeatures } = require_runtime_features(); + var DecompressController = class { + #onPause; + #onResume; + #onAbort; + #paused = false; + constructor(onPause, onResume, onAbort) { + this.#onPause = onPause; + this.#onResume = onResume; + this.#onAbort = onAbort; + this.target = null; + } + pause() { + if (this.#paused) { + return; + } + this.#paused = true; + this.#onPause(); + } + resume() { + if (!this.#paused) { + return; } - return dispatcher; + this.#paused = false; + this.#onResume(); } - dispatch(opts, handler2) { - this.get(opts.origin); - return this[kAgent].dispatch(opts, handler2); + abort(reason) { + this.target?.abort(reason); + this.#onAbort(reason); } - async close() { - await this[kAgent].close(); - this[kClients].clear(); + get paused() { + return this.#paused; } - deactivate() { - this[kIsMockActive] = false; + get aborted() { + return this.target?.aborted ?? false; } - activate() { - this[kIsMockActive] = true; + get reason() { + return this.target?.reason ?? null; } - enableNetConnect(matcher) { - if (typeof matcher === "string" || typeof matcher === "function" || matcher instanceof RegExp) { - if (Array.isArray(this[kNetConnect])) { - this[kNetConnect].push(matcher); - } else { - this[kNetConnect] = [matcher]; - } - } else if (typeof matcher === "undefined") { - this[kNetConnect] = true; - } else { - throw new InvalidArgumentError("Unsupported matcher. Must be one of String|Function|RegExp."); + get rawHeaders() { + return this.target?.rawHeaders ?? null; + } + set rawHeaders(value) { + if (this.target) { + this.target.rawHeaders = value; } } - disableNetConnect() { - this[kNetConnect] = false; + get rawTrailers() { + return this.target?.rawTrailers ?? null; } - // This is required to bypass issues caused by using global symbols - see: - // https://github.com/nodejs/undici/issues/1447 - get isMockActive() { - return this[kIsMockActive]; + set rawTrailers(value) { + if (this.target) { + this.target.rawTrailers = value; + } } - [kMockAgentSet](origin, dispatcher) { - this[kClients].set(origin, dispatcher); + }; + var supportedEncodings = { + gzip: createGunzip, + "x-gzip": createGunzip, + br: createBrotliDecompress, + deflate: createInflate, + compress: createInflate, + "x-compress": createInflate, + ...runtimeFeatures.has("zstd") ? { zstd: createZstdDecompress } : {} + }; + var defaultSkipStatusCodes = ( + /** @type {const} */ + [204, 304] + ); + var defaultMaxSize = 0; + function createMaxSizeLimiter(maxSize) { + let size = 0; + return new TransformStream2({ + transform(chunk, _encoding, callback) { + const decompressedSize = size + chunk.length; + if (decompressedSize > maxSize) { + callback(new ResponseExceededMaxSizeError( + `Decompressed response size (${decompressedSize}) exceeded maxSize (${maxSize})` + )); + return; + } + size = decompressedSize; + callback(null, chunk); + } + }); + } + var warningEmitted = ( + /** @type {boolean} */ + false + ); + var DecompressHandler = class extends DecoratorHandler { + /** @type {Transform[]} */ + #decompressors = []; + /** @type {Record | undefined} */ + #trailers; + /** @type {Readonly} */ + #skipStatusCodes; + /** @type {boolean} */ + #skipErrorResponses; + /** @type {number} */ + #maxSize; + /** @type {number} */ + #decompressedSize = 0; + /** @type {boolean} */ + #terminated = false; + /** @type {boolean} */ + #inputEnded = false; + /** @type {boolean} */ + #inputBackpressured = false; + /** @type {boolean} */ + #upstreamPaused = false; + /** @type {boolean} */ + #draining = false; + /** @type {boolean} */ + #drainRequested = false; + /** @type {boolean} */ + #completionPending = false; + /** @type {DecompressorStream | undefined} */ + #finalDecompressor; + /** @type {DecompressController} */ + #controller; + constructor(handler2, { skipStatusCodes = defaultSkipStatusCodes, skipErrorResponses = true, maxSize = defaultMaxSize } = {}) { + if (!Number.isSafeInteger(maxSize) || maxSize < 0) { + throw new InvalidArgumentError("maxSize must be a non-negative integer"); + } + super(handler2); + this.#skipStatusCodes = skipStatusCodes; + this.#skipErrorResponses = skipErrorResponses; + this.#maxSize = maxSize; + this.#controller = new DecompressController( + () => this.#onDownstreamPause(), + () => this.#onDownstreamResume(), + (reason) => { + if (this.#inputEnded && !this.#terminated) { + this.onResponseError(this.#controller, reason); + } + } + ); } - [kFactory](origin) { - const mockOptions = Object.assign({ agent: this }, this[kOptions]); - return this[kOptions] && this[kOptions].connections === 1 ? new MockClient(origin, mockOptions) : new MockPool(origin, mockOptions); + #onDownstreamPause() { + this.#pauseUpstream(); } - [kMockAgentGet](origin) { - const client = this[kClients].get(origin); - if (client) { - return client; + #onDownstreamResume() { + const drainWasDeferred = this.#draining; + this.#drainOutput(); + if (!drainWasDeferred) { + this.#resumeUpstreamIfNeeded(); + this.#finishIfReady(); } - if (typeof origin !== "string") { - const dispatcher = this[kFactory]("http://localhost:9999"); - this[kMockAgentSet](origin, dispatcher); - return dispatcher; + } + #pauseUpstream() { + if (!this.#upstreamPaused && !this.#terminated) { + this.#upstreamPaused = true; + this.#controller.target?.pause(); } - for (const [keyMatcher, nonExplicitDispatcher] of Array.from(this[kClients])) { - if (nonExplicitDispatcher && typeof keyMatcher !== "string" && matchValue(keyMatcher, origin)) { - const dispatcher = this[kFactory](origin); - this[kMockAgentSet](origin, dispatcher); - dispatcher[kDispatches] = nonExplicitDispatcher[kDispatches]; - return dispatcher; + } + #resumeUpstreamIfNeeded() { + if (this.#upstreamPaused && !this.#controller.paused && !this.#inputBackpressured) { + this.#upstreamPaused = false; + if (!this.#inputEnded) { + this.#controller.target?.resume(); } } } - [kGetNetConnect]() { - return this[kNetConnect]; + #drainOutput() { + if (this.#terminated || this.#controller.paused || !this.#finalDecompressor) { + return; + } + if (this.#draining) { + this.#drainRequested = true; + return; + } + this.#draining = true; + try { + do { + this.#drainRequested = false; + let chunk; + while (!this.#terminated && !this.#controller.paused && (chunk = this.#finalDecompressor.read()) !== null) { + if (this.#maxSize > 0) { + const decompressedSize = this.#decompressedSize + chunk.length; + if (decompressedSize > this.#maxSize) { + this.#fail(new ResponseExceededMaxSizeError( + `Decompressed response size (${decompressedSize}) exceeded maxSize (${this.#maxSize})` + )); + return; + } + this.#decompressedSize = decompressedSize; + } + try { + const result = super.onResponseData(this.#controller, chunk); + if (result === false && !this.#controller.paused) { + this.#controller.pause(); + } + } catch (err) { + this.#fail(err); + return; + } + } + } while (this.#drainRequested && !this.#terminated && !this.#controller.paused); + } finally { + this.#draining = false; + } + this.#resumeUpstreamIfNeeded(); + this.#finishIfReady(); } - pendingInterceptors() { - const mockAgentClients = this[kClients]; - return Array.from(mockAgentClients.entries()).flatMap(([origin, scope]) => scope[kDispatches].map((dispatch) => ({ ...dispatch, origin }))).filter(({ pending }) => pending); + #finishIfReady() { + if (this.#terminated || !this.#completionPending || this.#controller.paused || this.#draining) { + return; + } + this.#cleanupDecompressors(); + try { + super.onResponseEnd(this.#controller, this.#trailers); + } catch (err) { + this.#fail(err); + return; + } + this.#terminated = true; } - assertNoPendingInterceptors({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) { - const pending = this.pendingInterceptors(); - if (pending.length === 0) { + #onDecompressionEnd() { + if (this.#terminated) { return; } - const pluralizer = new Pluralizer("interceptor", "interceptors").pluralize(pending.length); - throw new UndiciError(` -${pluralizer.count} ${pluralizer.noun} ${pluralizer.is} pending: - -${pendingInterceptorsFormatter.format(pending)} -`.trim()); + this.#completionPending = true; + this.#drainOutput(); + this.#finishIfReady(); } - }; - module2.exports = MockAgent; - } -}); - -// node_modules/undici/lib/global.js -var require_global2 = __commonJS({ - "node_modules/undici/lib/global.js"(exports2, module2) { - "use strict"; - var globalDispatcher = /* @__PURE__ */ Symbol.for("undici.globalDispatcher.1"); - var { InvalidArgumentError } = require_errors(); - var Agent = require_agent(); - if (getGlobalDispatcher() === void 0) { - setGlobalDispatcher(new Agent()); - } - function setGlobalDispatcher(agent) { - if (!agent || typeof agent.dispatch !== "function") { - throw new InvalidArgumentError("Argument agent must implement Agent"); + /** + * Determines if decompression should be skipped based on encoding and status code + * @param {string} contentEncoding - Content-Encoding header value + * @param {number} statusCode - HTTP status code of the response + * @returns {boolean} - True if decompression should be skipped + */ + #shouldSkipDecompression(contentEncoding, statusCode) { + if (!contentEncoding || statusCode < 200) return true; + if (this.#skipStatusCodes.includes(statusCode)) return true; + if (this.#skipErrorResponses && statusCode >= 400) return true; + return false; } - Object.defineProperty(globalThis, globalDispatcher, { - value: agent, - writable: true, - enumerable: false, - configurable: false - }); - } - function getGlobalDispatcher() { - return globalThis[globalDispatcher]; - } - module2.exports = { - setGlobalDispatcher, - getGlobalDispatcher - }; - } -}); - -// node_modules/undici/lib/handler/decorator-handler.js -var require_decorator_handler = __commonJS({ - "node_modules/undici/lib/handler/decorator-handler.js"(exports2, module2) { - "use strict"; - module2.exports = class DecoratorHandler { - #handler; - constructor(handler2) { - if (typeof handler2 !== "object" || handler2 === null) { - throw new TypeError("handler must be an object"); + /** + * Creates a chain of decompressors for multiple content encodings + * + * @param {string} encodings - Comma-separated list of content encodings + * @returns {Array} - Array of decompressor and limiting streams + * @throws {Error} - If the number of content-encodings exceeds the maximum allowed + */ + #createDecompressionChain(encodings) { + const parts = encodings.split(","); + const maxContentEncodings = 5; + if (parts.length > maxContentEncodings) { + throw new Error(`too many content-encodings in response: ${parts.length}, maximum allowed is ${maxContentEncodings}`); } - this.#handler = handler2; + const decompressors = []; + for (let i = parts.length - 1; i >= 0; i--) { + const encoding = parts[i].trim(); + if (!encoding) continue; + if (!supportedEncodings[encoding]) { + decompressors.length = 0; + return decompressors; + } + decompressors.push(supportedEncodings[encoding]()); + } + if (decompressors.length < 2) { + return decompressors; + } + const streams = []; + for (let i = 0; i < decompressors.length; i++) { + streams.push(decompressors[i]); + if (i < decompressors.length - 1 && this.#maxSize > 0) { + streams.push(createMaxSizeLimiter(this.#maxSize)); + } + } + return streams; } - onConnect(...args) { - return this.#handler.onConnect?.(...args); + /** + * Stops decompression and reports an error. + * @param {Error} error - The decompression error + * @returns {void} + */ + #fail(error3) { + if (this.#terminated) { + return; + } + if (this.#inputEnded) { + this.onResponseError(this.#controller, error3); + } else { + this.#controller.abort(error3); + } } - onError(...args) { - return this.#handler.onError?.(...args); + /** + * Sets up event handlers for the final decompressor stream. + * @param {DecompressorStream} decompressor - The decompressor stream + * @returns {void} + */ + #setupDecompressorEvents(decompressor) { + this.#finalDecompressor = decompressor; + decompressor.on("readable", () => this.#drainOutput()); + decompressor.on("error", (error3) => this.#fail(error3)); } - onUpgrade(...args) { - return this.#handler.onUpgrade?.(...args); + /** + * Sets up event handling for a single decompressor + * @returns {void} + */ + #setupSingleDecompressor() { + const decompressor = this.#decompressors[0]; + this.#setupDecompressorEvents(decompressor); + decompressor.on("end", () => this.#onDecompressionEnd()); } - onResponseStarted(...args) { - return this.#handler.onResponseStarted?.(...args); + /** + * Sets up event handling for multiple chained decompressors using pipeline + * @returns {void} + */ + #setupMultipleDecompressors() { + const lastDecompressor = this.#decompressors[this.#decompressors.length - 1]; + this.#setupDecompressorEvents(lastDecompressor); + pipeline2(this.#decompressors, (err) => { + if (this.#terminated) { + return; + } + if (err) { + this.#fail(err); + return; + } + this.#onDecompressionEnd(); + }); } - onHeaders(...args) { - return this.#handler.onHeaders?.(...args); + #setupInputBackpressure() { + const decompressor = this.#decompressors[0]; + decompressor.on("drain", () => { + if (this.#terminated) { + return; + } + this.#inputBackpressured = false; + if (!this.#controller.paused) { + this.#drainOutput(); + this.#resumeUpstreamIfNeeded(); + } + }); } - onData(...args) { - return this.#handler.onData?.(...args); + /** + * Cleans up decompressor references to prevent memory leaks + * @returns {void} + */ + #cleanupDecompressors() { + this.#decompressors.length = 0; + this.#finalDecompressor = void 0; } - onComplete(...args) { - return this.#handler.onComplete?.(...args); + onRequestStart(controller, context5) { + this.#controller.target = controller; + return super.onRequestStart(this.#controller, context5); } - onBodySent(...args) { - return this.#handler.onBodySent?.(...args); + onRequestUpgrade(controller, statusCode, headers, socket) { + return super.onRequestUpgrade(this.#controller, statusCode, headers, socket); } - }; - } -}); - -// node_modules/undici/lib/interceptor/redirect.js -var require_redirect = __commonJS({ - "node_modules/undici/lib/interceptor/redirect.js"(exports2, module2) { - "use strict"; - var RedirectHandler = require_redirect_handler(); - module2.exports = (opts) => { - const globalMaxRedirections = opts?.maxRedirections; - return (dispatch) => { - return function redirectInterceptor(opts2, handler2) { - const { maxRedirections = globalMaxRedirections, ...baseOpts } = opts2; - if (!maxRedirections) { - return dispatch(opts2, handler2); + /** + * @param {Controller} controller + * @param {number} statusCode + * @param {Record} headers + * @param {string} statusMessage + * @returns {void} + */ + onResponseStart(controller, statusCode, headers, statusMessage) { + const contentEncoding = headers["content-encoding"]; + if (this.#shouldSkipDecompression(contentEncoding, statusCode)) { + return super.onResponseStart(this.#controller, statusCode, headers, statusMessage); + } + const decompressors = this.#createDecompressionChain(contentEncoding.toLowerCase()); + if (decompressors.length === 0) { + this.#cleanupDecompressors(); + return super.onResponseStart(this.#controller, statusCode, headers, statusMessage); + } + this.#decompressors = decompressors; + const { "content-encoding": _2, "content-length": __, ...newHeaders } = headers; + if (this.#controller.rawHeaders) { + const rawHeaders = this.#controller.rawHeaders; + if (Array.isArray(rawHeaders)) { + const filteredHeaders = []; + for (let i = 0; i < rawHeaders.length; i += 2) { + const headerName = rawHeaders[i]; + const name = Buffer.isBuffer(headerName) ? headerName.toString("latin1") : `${headerName}`; + const lowerName = name.toLowerCase(); + if (lowerName === "content-encoding" || lowerName === "content-length") { + continue; + } + filteredHeaders.push(rawHeaders[i], rawHeaders[i + 1]); + } + rawHeaders.splice(0, rawHeaders.length, ...filteredHeaders); + } else if (typeof rawHeaders === "object") { + for (const name of Object.keys(rawHeaders)) { + const lowerName = name.toLowerCase(); + if (lowerName === "content-encoding" || lowerName === "content-length") { + delete rawHeaders[name]; + } + } } - const redirectHandler = new RedirectHandler( - dispatch, - maxRedirections, - opts2, - handler2 - ); - return dispatch(baseOpts, redirectHandler); - }; - }; + } + this.#setupInputBackpressure(); + if (this.#decompressors.length === 1) { + this.#setupSingleDecompressor(); + } else { + this.#setupMultipleDecompressors(); + } + return super.onResponseStart(this.#controller, statusCode, newHeaders, statusMessage); + } + /** + * @param {Controller} controller + * @param {Buffer} chunk + * @returns {void} + */ + onResponseData(controller, chunk) { + if (this.#decompressors.length > 0) { + if (!this.#decompressors[0].write(chunk)) { + this.#inputBackpressured = true; + this.#pauseUpstream(); + } + return; + } + return super.onResponseData(this.#controller, chunk); + } + /** + * @param {Controller} controller + * @param {Record | undefined} trailers + * @returns {void} + */ + onResponseEnd(controller, trailers) { + if (this.#decompressors.length > 0) { + this.#inputEnded = true; + this.#trailers = trailers; + this.#decompressors[0].end(); + return; + } + return super.onResponseEnd(this.#controller, trailers); + } + /** + * @param {Controller} controller + * @param {Error} err + * @returns {void} + */ + onResponseError(controller, err) { + if (this.#terminated) { + return; + } + this.#terminated = true; + for (const decompressor of this.#decompressors) { + decompressor.destroy(); + } + this.#cleanupDecompressors(); + super.onResponseError(this.#controller, err); + } }; - } -}); - -// node_modules/undici/lib/interceptor/retry.js -var require_retry = __commonJS({ - "node_modules/undici/lib/interceptor/retry.js"(exports2, module2) { - "use strict"; - var RetryHandler = require_retry_handler(); - module2.exports = (globalOpts) => { + function createDecompressInterceptor(options = {}) { + if (!warningEmitted) { + process.emitWarning( + "DecompressInterceptor is experimental and subject to change", + "ExperimentalWarning" + ); + warningEmitted = true; + } return (dispatch) => { - return function retryInterceptor(opts, handler2) { - return dispatch( - opts, - new RetryHandler( - { ...opts, retryOptions: { ...globalOpts, ...opts.retryOptions } }, - { - handler: handler2, - dispatch - } - ) - ); + return (opts, handler2) => { + const decompressHandler = new DecompressHandler(handler2, options); + return dispatch(opts, decompressHandler); }; }; - }; + } + module2.exports = createDecompressInterceptor; } }); -// node_modules/undici/lib/interceptor/dump.js -var require_dump = __commonJS({ - "node_modules/undici/lib/interceptor/dump.js"(exports2, module2) { +// node_modules/undici/lib/handler/deduplication-handler.js +var require_deduplication_handler = __commonJS({ + "node_modules/undici/lib/handler/deduplication-handler.js"(exports2, module2) { "use strict"; - var util4 = require_util(); - var { InvalidArgumentError, RequestAbortedError } = require_errors(); - var DecoratorHandler = require_decorator_handler(); - var DumpHandler = class extends DecoratorHandler { - #maxSize = 1024 * 1024; - #abort = null; - #dumped = false; + var { RequestAbortedError } = require_errors(); + var DEFAULT_MAX_BUFFER_SIZE = 5 * 1024 * 1024; + var DeduplicationHandler = class { + /** + * @type {DispatchHandler} + */ + #primaryHandler; + /** + * Whether the primary request has started (onRequestStart received). Until + * then the request context is unknown and cannot be given to waiting handlers. + * @type {boolean} + */ + #requestStarted = false; + /** + * The primary request context, replayed to waiting handlers so they observe + * the same redirect history as the primary. + * @type {any} + */ + #context = null; + /** + * @type {WaitingHandler[]} + */ + #waitingHandlers = []; + /** + * @type {number} + */ + #maxBufferSize = DEFAULT_MAX_BUFFER_SIZE; + /** + * @type {number} + */ + #statusCode = 0; + /** + * @type {Record} + */ + #headers = {}; + /** + * @type {string} + */ + #statusMessage = ""; + /** + * @type {boolean} + */ #aborted = false; - #size = 0; - #reason = null; - #handler = null; - constructor({ maxSize }, handler2) { - super(handler2); - if (maxSize != null && (!Number.isFinite(maxSize) || maxSize < 1)) { - throw new InvalidArgumentError("maxSize must be a number greater than 0"); + /** + * @type {boolean} + */ + #responseStarted = false; + /** + * @type {boolean} + */ + #responseDataStarted = false; + /** + * @type {boolean} + */ + #completed = false; + /** + * @type {import('../../types/dispatcher.d.ts').default.DispatchController | null} + */ + #controller = null; + /** + * @type {(() => void) | null} + */ + #onComplete = null; + /** + * @param {DispatchHandler} primaryHandler The primary handler + * @param {() => void} onComplete Callback when request completes + * @param {number} [maxBufferSize] Maximum paused buffer size per waiting handler + */ + constructor(primaryHandler, onComplete, maxBufferSize = DEFAULT_MAX_BUFFER_SIZE) { + this.#primaryHandler = primaryHandler; + this.#onComplete = onComplete; + this.#maxBufferSize = maxBufferSize; + } + /** + * Add a waiting handler that will receive response events. + * Returns false if deduplication can no longer safely attach this handler. + * + * @param {DispatchHandler} handler + * @returns {boolean} + */ + addWaitingHandler(handler2) { + if (this.#completed || this.#responseDataStarted) { + return false; } - this.#maxSize = maxSize ?? this.#maxSize; - this.#handler = handler2; + const waitingHandler = this.#createWaitingHandler(handler2); + const waitingController = waitingHandler.controller; + try { + if (this.#requestStarted) { + handler2.onRequestStart?.(waitingController, this.#context); + if (waitingController.aborted) { + waitingHandler.done = true; + return true; + } + if (this.#responseStarted) { + handler2.onResponseStart?.( + waitingController, + this.#statusCode, + this.#headers, + this.#statusMessage + ); + } + } else { + waitingHandler.pendingStart = true; + } + } catch { + waitingHandler.done = true; + return true; + } + if (!waitingController.aborted) { + this.#waitingHandlers.push(waitingHandler); + } + return true; } - onConnect(abort) { - this.#abort = abort; - this.#handler.onConnect(this.#customAbort.bind(this)); + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {any} context + */ + onRequestStart(controller, context5) { + this.#controller = controller; + if (!this.#requestStarted) { + this.#requestStarted = true; + this.#context = context5; + for (const waitingHandler of this.#waitingHandlers) { + if (waitingHandler.pendingStart && !waitingHandler.done && !waitingHandler.controller.aborted) { + waitingHandler.pendingStart = false; + try { + waitingHandler.handler.onRequestStart?.(waitingHandler.controller, context5); + } catch { + waitingHandler.done = true; + } + } + } + this.#pruneDoneWaitingHandlers(); + } + this.#primaryHandler.onRequestStart?.(controller, context5); } - #customAbort(reason) { - this.#aborted = true; - this.#reason = reason; + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {number} statusCode + * @param {import('../../types/header.d.ts').IncomingHttpHeaders} headers + * @param {Socket} socket + */ + onRequestUpgrade(controller, statusCode, headers, socket) { + this.#primaryHandler.onRequestUpgrade?.(controller, statusCode, headers, socket); } - // TODO: will require adjustment after new hooks are out - onHeaders(statusCode, rawHeaders, resume, statusMessage) { - const headers = util4.parseHeaders(rawHeaders); - const contentLength = headers["content-length"]; - if (contentLength != null && contentLength > this.#maxSize) { - throw new RequestAbortedError( - `Response size (${contentLength}) larger than maxSize (${this.#maxSize})` - ); - } - if (this.#aborted) { - return true; + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {number} statusCode + * @param {Record} headers + * @param {string} statusMessage + */ + onResponseStart(controller, statusCode, headers, statusMessage) { + this.#responseStarted = true; + this.#statusCode = statusCode; + this.#headers = headers; + this.#statusMessage = statusMessage; + this.#primaryHandler.onResponseStart?.(controller, statusCode, headers, statusMessage); + for (const waitingHandler of this.#waitingHandlers) { + const { handler: handler2, controller: waitingController } = waitingHandler; + if (waitingHandler.done || waitingController.aborted) { + waitingHandler.done = true; + continue; + } + try { + handler2.onResponseStart?.( + waitingController, + statusCode, + headers, + statusMessage + ); + } catch { + } + if (waitingController.aborted) { + waitingHandler.done = true; + } } - return this.#handler.onHeaders( - statusCode, - rawHeaders, - resume, - statusMessage - ); + this.#pruneDoneWaitingHandlers(); } - onError(err) { - if (this.#dumped) { + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {Buffer} chunk + */ + onResponseData(controller, chunk) { + if (this.#aborted || this.#completed) { return; } - err = this.#reason ?? err; - this.#handler.onError(err); + this.#responseDataStarted = true; + this.#primaryHandler.onResponseData?.(controller, chunk); + for (const waitingHandler of this.#waitingHandlers) { + const { handler: handler2, controller: waitingController } = waitingHandler; + if (waitingHandler.done || waitingController.aborted) { + waitingHandler.done = true; + continue; + } + if (waitingController.paused) { + this.#bufferWaitingChunk(waitingHandler, chunk); + continue; + } + try { + handler2.onResponseData?.(waitingController, chunk); + } catch { + } + if (waitingController.aborted) { + waitingHandler.done = true; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + } + } + this.#pruneDoneWaitingHandlers(); } - onData(chunk) { - this.#size = this.#size + chunk.length; - if (this.#size >= this.#maxSize) { - this.#dumped = true; - if (this.#aborted) { - this.#handler.onError(this.#reason); - } else { - this.#handler.onComplete([]); + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {object} trailers + */ + onResponseEnd(controller, trailers) { + if (this.#aborted || this.#completed) { + return; + } + this.#completed = true; + this.#primaryHandler.onResponseEnd?.(controller, trailers); + for (const waitingHandler of this.#waitingHandlers) { + if (waitingHandler.done || waitingHandler.controller.aborted) { + waitingHandler.done = true; + continue; } + this.#flushWaitingHandler(waitingHandler); + if (waitingHandler.done || waitingHandler.controller.aborted) { + waitingHandler.done = true; + continue; + } + if (waitingHandler.controller.paused && waitingHandler.bufferedChunks.length > 0) { + waitingHandler.pendingTrailers = trailers; + continue; + } + try { + waitingHandler.handler.onResponseEnd?.(waitingHandler.controller, trailers); + } catch { + } + waitingHandler.done = true; } - return true; + this.#pruneDoneWaitingHandlers(); + this.#onComplete?.(); } - onComplete(trailers) { - if (this.#dumped) { + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {Error} err + */ + onResponseError(controller, err) { + if (this.#completed) { + return; + } + this.#aborted = true; + this.#completed = true; + this.#primaryHandler.onResponseError?.(controller, err); + for (const waitingHandler of this.#waitingHandlers) { + this.#errorWaitingHandler(waitingHandler, err); + } + this.#waitingHandlers = []; + this.#onComplete?.(); + } + /** + * @param {DispatchHandler} handler + * @returns {WaitingHandler} + */ + #createWaitingHandler(handler2) { + const waitingHandler = { + handler: handler2, + controller: null, + bufferedChunks: [], + bufferedBytes: 0, + pendingTrailers: null, + done: false, + pendingStart: false + }; + const state = { + aborted: false, + paused: false, + reason: null + }; + waitingHandler.controller = { + resume: () => { + if (state.aborted) { + return; + } + state.paused = false; + this.#flushWaitingHandler(waitingHandler); + if (this.#completed && waitingHandler.pendingTrailers && waitingHandler.bufferedChunks.length === 0 && !state.paused && !state.aborted) { + try { + waitingHandler.handler.onResponseEnd?.(waitingHandler.controller, waitingHandler.pendingTrailers); + } catch { + } + waitingHandler.pendingTrailers = null; + waitingHandler.done = true; + } + this.#pruneDoneWaitingHandlers(); + }, + pause: () => { + if (!state.aborted) { + state.paused = true; + } + }, + get paused() { + return state.paused; + }, + get aborted() { + return state.aborted; + }, + get reason() { + return state.reason; + }, + abort: (reason) => { + state.aborted = true; + state.reason = reason ?? null; + waitingHandler.done = true; + waitingHandler.pendingTrailers = null; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + } + }; + return waitingHandler; + } + /** + * @param {WaitingHandler} waitingHandler + * @param {Buffer} chunk + */ + #bufferWaitingChunk(waitingHandler, chunk) { + if (waitingHandler.done || waitingHandler.controller.aborted) { + waitingHandler.done = true; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; return; } - if (this.#aborted) { - this.#handler.onError(this.reason); + const bufferedChunk = Buffer.from(chunk); + waitingHandler.bufferedChunks.push(bufferedChunk); + waitingHandler.bufferedBytes += bufferedChunk.length; + if (waitingHandler.bufferedBytes > this.#maxBufferSize) { + const err = new RequestAbortedError(`Deduplicated waiting handler exceeded maxBufferSize (${this.#maxBufferSize} bytes) while paused`); + this.#errorWaitingHandler(waitingHandler, err); + } + } + /** + * @param {WaitingHandler} waitingHandler + */ + #flushWaitingHandler(waitingHandler) { + const { handler: handler2, controller } = waitingHandler; + while (!waitingHandler.done && !controller.aborted && !controller.paused && waitingHandler.bufferedChunks.length > 0) { + const bufferedChunk = waitingHandler.bufferedChunks.shift(); + waitingHandler.bufferedBytes -= bufferedChunk.length; + try { + handler2.onResponseData?.(controller, bufferedChunk); + } catch { + } + if (controller.aborted) { + waitingHandler.done = true; + waitingHandler.pendingTrailers = null; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + break; + } + } + } + /** + * @param {WaitingHandler} waitingHandler + * @param {Error} err + */ + #errorWaitingHandler(waitingHandler, err) { + if (waitingHandler.done) { return; } - this.#handler.onComplete(trailers); + waitingHandler.done = true; + waitingHandler.pendingTrailers = null; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + try { + waitingHandler.controller.abort(err); + waitingHandler.handler.onResponseError?.(waitingHandler.controller, err); + } catch { + } + } + #pruneDoneWaitingHandlers() { + this.#waitingHandlers = this.#waitingHandlers.filter((waitingHandler) => waitingHandler.done === false); } }; - function createDumpInterceptor({ maxSize: defaultMaxSize } = { - maxSize: 1024 * 1024 - }) { + module2.exports = DeduplicationHandler; + } +}); + +// node_modules/undici/lib/interceptor/deduplicate.js +var require_deduplicate = __commonJS({ + "node_modules/undici/lib/interceptor/deduplicate.js"(exports2, module2) { + "use strict"; + var diagnosticsChannel = require("node:diagnostics_channel"); + var util4 = require_util(); + var DeduplicationHandler = require_deduplication_handler(); + var { normalizeHeaders, makeCacheKey, makeDeduplicationKey } = require_cache(); + var pendingRequestsChannel = diagnosticsChannel.channel("undici:request:pending-requests"); + module2.exports = (opts = {}) => { + const { + methods = ["GET"], + skipHeaderNames = [], + excludeHeaderNames = [], + maxBufferSize = 5 * 1024 * 1024 + } = opts; + if (typeof opts !== "object" || opts === null) { + throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? "null" : typeof opts}`); + } + if (!Array.isArray(methods)) { + throw new TypeError(`expected opts.methods to be an array, got ${typeof methods}`); + } + for (const method of methods) { + if (!util4.safeHTTPMethods.includes(method)) { + throw new TypeError(`expected opts.methods to only contain safe HTTP methods, got ${method}`); + } + } + if (!Array.isArray(skipHeaderNames)) { + throw new TypeError(`expected opts.skipHeaderNames to be an array, got ${typeof skipHeaderNames}`); + } + if (!Array.isArray(excludeHeaderNames)) { + throw new TypeError(`expected opts.excludeHeaderNames to be an array, got ${typeof excludeHeaderNames}`); + } + if (!Number.isFinite(maxBufferSize) || maxBufferSize <= 0) { + throw new TypeError(`expected opts.maxBufferSize to be a positive finite number, got ${maxBufferSize}`); + } + const skipHeaderNamesSet = new Set(skipHeaderNames.map((name) => name.toLowerCase())); + const excludeHeaderNamesSet = new Set(excludeHeaderNames.map((name) => name.toLowerCase())); + const pendingRequests = /* @__PURE__ */ new Map(); return (dispatch) => { - return function Intercept(opts, handler2) { - const { dumpMaxSize = defaultMaxSize } = opts; - const dumpHandler = new DumpHandler( - { maxSize: dumpMaxSize }, - handler2 + return (opts2, handler2) => { + if (!opts2.origin || methods.includes(opts2.method) === false) { + return dispatch(opts2, handler2); + } + opts2 = { + ...opts2, + headers: normalizeHeaders(opts2) + }; + if (skipHeaderNamesSet.size > 0) { + for (const headerName of Object.keys(opts2.headers)) { + if (skipHeaderNamesSet.has(headerName.toLowerCase())) { + return dispatch(opts2, handler2); + } + } + } + const cacheKey3 = makeCacheKey(opts2); + const dedupeKey = makeDeduplicationKey(cacheKey3, excludeHeaderNamesSet); + const pendingHandler = pendingRequests.get(dedupeKey); + if (pendingHandler) { + if (pendingHandler.addWaitingHandler(handler2)) { + return true; + } + return dispatch(opts2, handler2); + } + const deduplicationHandler = new DeduplicationHandler( + handler2, + () => { + pendingRequests.delete(dedupeKey); + if (pendingRequestsChannel.hasSubscribers) { + pendingRequestsChannel.publish({ size: pendingRequests.size, key: dedupeKey, type: "removed" }); + } + }, + maxBufferSize ); - return dispatch(opts, dumpHandler); + pendingRequests.set(dedupeKey, deduplicationHandler); + if (pendingRequestsChannel.hasSubscribers) { + pendingRequestsChannel.publish({ size: pendingRequests.size, key: dedupeKey, type: "added" }); + } + return dispatch(opts2, deduplicationHandler); }; }; - } - module2.exports = createDumpInterceptor; + }; } }); -// node_modules/undici/lib/interceptor/dns.js -var require_dns = __commonJS({ - "node_modules/undici/lib/interceptor/dns.js"(exports2, module2) { +// node_modules/undici/lib/cache/sqlite-cache-store.js +var require_sqlite_cache_store = __commonJS({ + "node_modules/undici/lib/cache/sqlite-cache-store.js"(exports2, module2) { "use strict"; - var { isIP } = require("node:net"); - var { lookup } = require("node:dns"); - var DecoratorHandler = require_decorator_handler(); - var { InvalidArgumentError, InformationalError } = require_errors(); - var maxInt = Math.pow(2, 31) - 1; - var DNSInstance = class { - #maxTTL = 0; - #maxItems = 0; - #records = /* @__PURE__ */ new Map(); - dualStack = true; - affinity = null; - lookup = null; - pick = null; + var { Writable } = require("node:stream"); + var { assertCacheKey, assertCacheValue } = require_cache(); + var DatabaseSync; + var VERSION8 = 3; + var MAX_ENTRY_SIZE = 2 * 1e3 * 1e3 * 1e3; + module2.exports = class SqliteCacheStore { + #maxEntrySize = MAX_ENTRY_SIZE; + #maxCount = Infinity; + /** + * @type {import('node:sqlite').DatabaseSync} + */ + #db; + /** + * @type {import('node:sqlite').StatementSync} + */ + #getValuesQuery; + /** + * @type {import('node:sqlite').StatementSync} + */ + #updateValueQuery; + /** + * @type {import('node:sqlite').StatementSync} + */ + #insertValueQuery; + /** + * @type {import('node:sqlite').StatementSync} + */ + #deleteExpiredValuesQuery; + /** + * @type {import('node:sqlite').StatementSync} + */ + #deleteByUrlQuery; + /** + * @type {import('node:sqlite').StatementSync} + */ + #countEntriesQuery; + /** + * @type {import('node:sqlite').StatementSync | null} + */ + #deleteOldValuesQuery; + /** + * @param {import('../../types/cache-interceptor.d.ts').default.SqliteCacheStoreOpts | undefined} opts + */ constructor(opts) { - this.#maxTTL = opts.maxTTL; - this.#maxItems = opts.maxItems; - this.dualStack = opts.dualStack; - this.affinity = opts.affinity; - this.lookup = opts.lookup ?? this.#defaultLookup; - this.pick = opts.pick ?? this.#defaultPick; + if (opts) { + if (typeof opts !== "object") { + throw new TypeError("SqliteCacheStore options must be an object"); + } + if (opts.maxEntrySize !== void 0) { + if (typeof opts.maxEntrySize !== "number" || !Number.isInteger(opts.maxEntrySize) || opts.maxEntrySize < 0) { + throw new TypeError("SqliteCacheStore options.maxEntrySize must be a non-negative integer"); + } + if (opts.maxEntrySize > MAX_ENTRY_SIZE) { + throw new TypeError("SqliteCacheStore options.maxEntrySize must be less than 2gb"); + } + this.#maxEntrySize = opts.maxEntrySize; + } + if (opts.maxCount !== void 0) { + if (typeof opts.maxCount !== "number" || !Number.isInteger(opts.maxCount) || opts.maxCount < 0) { + throw new TypeError("SqliteCacheStore options.maxCount must be a non-negative integer"); + } + this.#maxCount = opts.maxCount; + } + } + if (!DatabaseSync) { + DatabaseSync = require("node:sqlite").DatabaseSync; + } + this.#db = new DatabaseSync(opts?.location ?? ":memory:"); + this.#db.exec(` + PRAGMA journal_mode = WAL; + PRAGMA synchronous = NORMAL; + PRAGMA temp_store = memory; + PRAGMA optimize; + + CREATE TABLE IF NOT EXISTS cacheInterceptorV${VERSION8} ( + -- Data specific to us + id INTEGER PRIMARY KEY AUTOINCREMENT, + url TEXT NOT NULL, + method TEXT NOT NULL, + + -- Data returned to the interceptor + body BUF NULL, + deleteAt INTEGER NOT NULL, + statusCode INTEGER NOT NULL, + statusMessage TEXT NOT NULL, + headers TEXT NULL, + cacheControlDirectives TEXT NULL, + etag TEXT NULL, + vary TEXT NULL, + cachedAt INTEGER NOT NULL, + staleAt INTEGER NOT NULL + ); + + CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION8}_getValuesQuery ON cacheInterceptorV${VERSION8}(url, method, deleteAt); + CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION8}_deleteByUrlQuery ON cacheInterceptorV${VERSION8}(deleteAt); + `); + this.#getValuesQuery = this.#db.prepare(` + SELECT + id, + body, + deleteAt, + statusCode, + statusMessage, + headers, + etag, + cacheControlDirectives, + vary, + cachedAt, + staleAt + FROM cacheInterceptorV${VERSION8} + WHERE + url = ? + AND method = ? + ORDER BY + deleteAt ASC + `); + this.#updateValueQuery = this.#db.prepare(` + UPDATE cacheInterceptorV${VERSION8} SET + body = ?, + deleteAt = ?, + statusCode = ?, + statusMessage = ?, + headers = ?, + etag = ?, + cacheControlDirectives = ?, + cachedAt = ?, + staleAt = ? + WHERE + id = ? + `); + this.#insertValueQuery = this.#db.prepare(` + INSERT INTO cacheInterceptorV${VERSION8} ( + url, + method, + body, + deleteAt, + statusCode, + statusMessage, + headers, + etag, + cacheControlDirectives, + vary, + cachedAt, + staleAt + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `); + this.#deleteByUrlQuery = this.#db.prepare( + `DELETE FROM cacheInterceptorV${VERSION8} WHERE url = ?` + ); + this.#countEntriesQuery = this.#db.prepare( + `SELECT COUNT(*) AS total FROM cacheInterceptorV${VERSION8}` + ); + this.#deleteExpiredValuesQuery = this.#db.prepare( + `DELETE FROM cacheInterceptorV${VERSION8} WHERE deleteAt <= ?` + ); + this.#deleteOldValuesQuery = this.#maxCount === Infinity ? null : this.#db.prepare(` + DELETE FROM cacheInterceptorV${VERSION8} + WHERE id IN ( + SELECT + id + FROM cacheInterceptorV${VERSION8} + ORDER BY cachedAt ASC + LIMIT ? + ) + `); } - get full() { - return this.#records.size === this.#maxItems; + close() { + this.#db.close(); } - runLookup(origin, opts, cb) { - const ips = this.#records.get(origin.hostname); - if (ips == null && this.full) { - cb(null, origin.origin); + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @returns {(import('../../types/cache-interceptor.d.ts').default.GetResult & { body?: Buffer }) | undefined} + */ + get(key) { + assertCacheKey(key); + const value = this.#findValue(key); + return value ? { + body: value.body ? Buffer.from(value.body.buffer, value.body.byteOffset, value.body.byteLength) : void 0, + statusCode: value.statusCode, + statusMessage: value.statusMessage, + headers: value.headers ? JSON.parse(value.headers) : void 0, + etag: value.etag ? value.etag : void 0, + vary: value.vary ? JSON.parse(value.vary) : void 0, + cacheControlDirectives: value.cacheControlDirectives ? JSON.parse(value.cacheControlDirectives) : void 0, + cachedAt: value.cachedAt, + staleAt: value.staleAt, + deleteAt: value.deleteAt + } : void 0; + } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @param {import('../../types/cache-interceptor.d.ts').default.CacheValue & { body: null | Buffer | Array}} value + */ + set(key, value) { + assertCacheKey(key); + const url2 = this.#makeValueUrl(key); + const body = Array.isArray(value.body) ? Buffer.concat(value.body) : value.body; + const size = body?.byteLength; + if (size && size > this.#maxEntrySize) { return; } - const newOpts = { - affinity: this.affinity, - dualStack: this.dualStack, - lookup: this.lookup, - pick: this.pick, - ...opts.dns, - maxTTL: this.#maxTTL, - maxItems: this.#maxItems - }; - if (ips == null) { - this.lookup(origin, newOpts, (err, addresses) => { - if (err || addresses == null || addresses.length === 0) { - cb(err ?? new InformationalError("No DNS entries found")); - return; - } - this.setRecords(origin, addresses); - const records = this.#records.get(origin.hostname); - const ip = this.pick( - origin, - records, - newOpts.affinity - ); - let port; - if (typeof ip.port === "number") { - port = `:${ip.port}`; - } else if (origin.port !== "") { - port = `:${origin.port}`; - } else { - port = ""; - } - cb( - null, - `${origin.protocol}//${ip.family === 6 ? `[${ip.address}]` : ip.address}${port}` - ); - }); - } else { - const ip = this.pick( - origin, - ips, - newOpts.affinity + const existingValue = this.#findValue(key, true); + if (existingValue) { + this.#updateValueQuery.run( + body, + value.deleteAt, + value.statusCode, + value.statusMessage, + value.headers ? JSON.stringify(value.headers) : null, + value.etag ? value.etag : null, + value.cacheControlDirectives ? JSON.stringify(value.cacheControlDirectives) : null, + value.cachedAt, + value.staleAt, + existingValue.id ); - if (ip == null) { - this.#records.delete(origin.hostname); - this.runLookup(origin, opts, cb); - return; - } - let port; - if (typeof ip.port === "number") { - port = `:${ip.port}`; - } else if (origin.port !== "") { - port = `:${origin.port}`; - } else { - port = ""; - } - cb( - null, - `${origin.protocol}//${ip.family === 6 ? `[${ip.address}]` : ip.address}${port}` + } else { + this.#insertValueQuery.run( + url2, + key.method, + body, + value.deleteAt, + value.statusCode, + value.statusMessage, + value.headers ? JSON.stringify(value.headers) : null, + value.etag ? value.etag : null, + value.cacheControlDirectives ? JSON.stringify(value.cacheControlDirectives) : null, + value.vary ? JSON.stringify(value.vary) : null, + value.cachedAt, + value.staleAt ); + this.#prune(); } } - #defaultLookup(origin, opts, cb) { - lookup( - origin.hostname, - { - all: true, - family: this.dualStack === false ? this.affinity : 0, - order: "ipv4first" - }, - (err, addresses) => { - if (err) { - return cb(err); - } - const results = /* @__PURE__ */ new Map(); - for (const addr of addresses) { - results.set(`${addr.address}:${addr.family}`, addr); - } - cb(null, results.values()); - } - ); - } - #defaultPick(origin, hostnameRecords, affinity) { - let ip = null; - const { records, offset } = hostnameRecords; - let family; - if (this.dualStack) { - if (affinity == null) { - if (offset == null || offset === maxInt) { - hostnameRecords.offset = 0; - affinity = 4; + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @param {import('../../types/cache-interceptor.d.ts').default.CacheValue} value + * @returns {Writable | undefined} + */ + createWriteStream(key, value) { + assertCacheKey(key); + assertCacheValue(value); + let size = 0; + const body = []; + const store = this; + return new Writable({ + decodeStrings: true, + write(chunk, encoding, callback) { + size += chunk.byteLength; + if (size < store.#maxEntrySize) { + body.push(chunk); } else { - hostnameRecords.offset++; - affinity = (hostnameRecords.offset & 1) === 1 ? 6 : 4; + this.destroy(); } + callback(); + }, + final(callback) { + store.set(key, { ...value, body }); + callback(); } - if (records[affinity] != null && records[affinity].ips.length > 0) { - family = records[affinity]; - } else { - family = records[affinity === 4 ? 6 : 4]; - } - } else { - family = records[affinity]; - } - if (family == null || family.ips.length === 0) { - return ip; - } - if (family.offset == null || family.offset === maxInt) { - family.offset = 0; - } else { - family.offset++; + }); + } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + */ + delete(key) { + if (typeof key !== "object") { + throw new TypeError(`expected key to be object, got ${typeof key}`); } - const position = family.offset % family.ips.length; - ip = family.ips[position] ?? null; - if (ip == null) { - return ip; + this.#deleteByUrlQuery.run(this.#makeValueUrl(key)); + } + #prune() { + if (Number.isFinite(this.#maxCount) && this.size <= this.#maxCount) { + return 0; } - if (Date.now() - ip.timestamp > ip.ttl) { - family.ips.splice(position, 1); - return this.pick(origin, hostnameRecords, affinity); + { + const removed = this.#deleteExpiredValuesQuery.run(Date.now()).changes; + if (removed) { + return removed; + } } - return ip; - } - setRecords(origin, addresses) { - const timestamp = Date.now(); - const records = { records: { 4: null, 6: null } }; - for (const record of addresses) { - record.timestamp = timestamp; - if (typeof record.ttl === "number") { - record.ttl = Math.min(record.ttl, this.#maxTTL); - } else { - record.ttl = this.#maxTTL; + { + const removed = this.#deleteOldValuesQuery?.run(Math.max(Math.floor(this.#maxCount * 0.1), 1)).changes; + if (removed) { + return removed; } - const familyRecords = records.records[record.family] ?? { ips: [] }; - familyRecords.ips.push(record); - records.records[record.family] = familyRecords; } - this.#records.set(origin.hostname, records); + return 0; } - getHandler(meta, opts) { - return new DNSDispatchHandler(this, meta, opts); + /** + * Counts the number of rows in the cache + * @returns {Number} + */ + get size() { + const { total } = this.#countEntriesQuery.get(); + return total; } - }; - var DNSDispatchHandler = class extends DecoratorHandler { - #state = null; - #opts = null; - #dispatch = null; - #handler = null; - #origin = null; - constructor(state, { origin, handler: handler2, dispatch }, opts) { - super(handler2); - this.#origin = origin; - this.#handler = handler2; - this.#opts = { ...opts }; - this.#state = state; - this.#dispatch = dispatch; + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @returns {string} + */ + #makeValueUrl(key) { + return `${key.origin}/${key.path}`; } - onError(err) { - switch (err.code) { - case "ETIMEDOUT": - case "ECONNREFUSED": { - if (this.#state.dualStack) { - this.#state.runLookup(this.#origin, this.#opts, (err2, newOrigin) => { - if (err2) { - return this.#handler.onError(err2); - } - const dispatchOpts = { - ...this.#opts, - origin: newOrigin - }; - this.#dispatch(dispatchOpts, this); - }); - return; + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @param {boolean} [canBeExpired=false] + * @returns {SqliteStoreValue | undefined} + */ + #findValue(key, canBeExpired = false) { + const url2 = this.#makeValueUrl(key); + const { headers, method } = key; + const values = this.#getValuesQuery.all(url2, method); + if (values.length === 0) { + return void 0; + } + const now = Date.now(); + for (const value of values) { + if (now >= value.deleteAt && !canBeExpired) { + continue; + } + let matches = true; + if (value.vary) { + const vary = JSON.parse(value.vary); + for (const header in vary) { + if (!headerValueEquals(headers[header], vary[header])) { + matches = false; + break; + } } - this.#handler.onError(err); - return; } - case "ENOTFOUND": - this.#state.deleteRecord(this.#origin); - // eslint-disable-next-line no-fallthrough - default: - this.#handler.onError(err); - break; + if (matches) { + return value; + } } + return void 0; } }; - module2.exports = (interceptorOpts) => { - if (interceptorOpts?.maxTTL != null && (typeof interceptorOpts?.maxTTL !== "number" || interceptorOpts?.maxTTL < 0)) { - throw new InvalidArgumentError("Invalid maxTTL. Must be a positive number"); - } - if (interceptorOpts?.maxItems != null && (typeof interceptorOpts?.maxItems !== "number" || interceptorOpts?.maxItems < 1)) { - throw new InvalidArgumentError( - "Invalid maxItems. Must be a positive number and greater than zero" - ); - } - if (interceptorOpts?.affinity != null && interceptorOpts?.affinity !== 4 && interceptorOpts?.affinity !== 6) { - throw new InvalidArgumentError("Invalid affinity. Must be either 4 or 6"); - } - if (interceptorOpts?.dualStack != null && typeof interceptorOpts?.dualStack !== "boolean") { - throw new InvalidArgumentError("Invalid dualStack. Must be a boolean"); - } - if (interceptorOpts?.lookup != null && typeof interceptorOpts?.lookup !== "function") { - throw new InvalidArgumentError("Invalid lookup. Must be a function"); - } - if (interceptorOpts?.pick != null && typeof interceptorOpts?.pick !== "function") { - throw new InvalidArgumentError("Invalid pick. Must be a function"); + function headerValueEquals(lhs, rhs) { + if (lhs == null && rhs == null) { + return true; } - const dualStack = interceptorOpts?.dualStack ?? true; - let affinity; - if (dualStack) { - affinity = interceptorOpts?.affinity ?? null; - } else { - affinity = interceptorOpts?.affinity ?? 4; + if (lhs == null && rhs != null || lhs != null && rhs == null) { + return false; } - const opts = { - maxTTL: interceptorOpts?.maxTTL ?? 1e4, - // Expressed in ms - lookup: interceptorOpts?.lookup ?? null, - pick: interceptorOpts?.pick ?? null, - dualStack, - affinity, - maxItems: interceptorOpts?.maxItems ?? Infinity - }; - const instance8 = new DNSInstance(opts); - return (dispatch) => { - return function dnsInterceptor(origDispatchOpts, handler2) { - const origin = origDispatchOpts.origin.constructor === URL ? origDispatchOpts.origin : new URL(origDispatchOpts.origin); - if (isIP(origin.hostname) !== 0) { - return dispatch(origDispatchOpts, handler2); + if (Array.isArray(lhs) && Array.isArray(rhs)) { + if (lhs.length !== rhs.length) { + return false; + } + for (let i = 0; i < lhs.length; i++) { + if (lhs[i] !== rhs[i]) { + return false; } - instance8.runLookup(origin, origDispatchOpts, (err, newOrigin) => { - if (err) { - return handler2.onError(err); - } - let dispatchOpts = null; - dispatchOpts = { - ...origDispatchOpts, - servername: origin.hostname, - // For SNI on TLS - origin: newOrigin, - headers: { - host: origin.hostname, - ...origDispatchOpts.headers - } - }; - dispatch( - dispatchOpts, - instance8.getHandler({ origin, dispatch, handler: handler2 }, origDispatchOpts) - ); - }); - return true; - }; - }; - }; + } + return true; + } + return lhs === rhs; + } } }); @@ -12098,8 +19611,6 @@ var require_headers = __commonJS({ var { webidl } = require_webidl(); var assert = require("node:assert"); var util4 = require("node:util"); - var kHeadersMap = /* @__PURE__ */ Symbol("headers map"); - var kHeadersSortedMap = /* @__PURE__ */ Symbol("headers map sorted"); function isHTTPWhiteSpaceCharCode(code) { return code === 10 || code === 13 || code === 9 || code === 32; } @@ -12155,20 +19666,48 @@ var require_headers = __commonJS({ } return getHeadersList(headers).append(name, value, false); } + function headersListSortAndCombine(target) { + const headersList = getHeadersList(target); + if (!headersList) { + return []; + } + if (headersList.sortedMap) { + return headersList.sortedMap; + } + const headers = []; + const names = headersList.toSortedArray(); + const cookies = headersList.cookies; + if (cookies === null || cookies.length === 1) { + return headersList.sortedMap = names; + } + for (let i = 0; i < names.length; ++i) { + const { 0: name, 1: value } = names[i]; + if (name === "set-cookie") { + for (let j = 0; j < cookies.length; ++j) { + headers.push([name, cookies[j]]); + } + } else { + headers.push([name, value]); + } + } + return headersList.sortedMap = headers; + } function compareHeaderName(a, b) { return a[0] < b[0] ? -1 : 1; } var HeadersList = class _HeadersList { /** @type {[string, string][]|null} */ cookies = null; + sortedMap; + headersMap; constructor(init2) { if (init2 instanceof _HeadersList) { - this[kHeadersMap] = new Map(init2[kHeadersMap]); - this[kHeadersSortedMap] = init2[kHeadersSortedMap]; + this.headersMap = new Map(init2.headersMap); + this.sortedMap = init2.sortedMap; this.cookies = init2.cookies === null ? null : [...init2.cookies]; } else { - this[kHeadersMap] = new Map(init2); - this[kHeadersSortedMap] = null; + this.headersMap = new Map(init2); + this.sortedMap = null; } } /** @@ -12177,11 +19716,11 @@ var require_headers = __commonJS({ * @param {boolean} isLowerCase */ contains(name, isLowerCase) { - return this[kHeadersMap].has(isLowerCase ? name : name.toLowerCase()); + return this.headersMap.has(isLowerCase ? name : name.toLowerCase()); } clear() { - this[kHeadersMap].clear(); - this[kHeadersSortedMap] = null; + this.headersMap.clear(); + this.sortedMap = null; this.cookies = null; } /** @@ -12191,17 +19730,17 @@ var require_headers = __commonJS({ * @param {boolean} isLowerCase */ append(name, value, isLowerCase) { - this[kHeadersSortedMap] = null; + this.sortedMap = null; const lowercaseName = isLowerCase ? name : name.toLowerCase(); - const exists = this[kHeadersMap].get(lowercaseName); + const exists = this.headersMap.get(lowercaseName); if (exists) { const delimiter = lowercaseName === "cookie" ? "; " : ", "; - this[kHeadersMap].set(lowercaseName, { + this.headersMap.set(lowercaseName, { name: exists.name, value: `${exists.value}${delimiter}${value}` }); } else { - this[kHeadersMap].set(lowercaseName, { name, value }); + this.headersMap.set(lowercaseName, { name, value }); } if (lowercaseName === "set-cookie") { (this.cookies ??= []).push(value); @@ -12214,12 +19753,12 @@ var require_headers = __commonJS({ * @param {boolean} isLowerCase */ set(name, value, isLowerCase) { - this[kHeadersSortedMap] = null; + this.sortedMap = null; const lowercaseName = isLowerCase ? name : name.toLowerCase(); if (lowercaseName === "set-cookie") { this.cookies = [value]; } - this[kHeadersMap].set(lowercaseName, { name, value }); + this.headersMap.set(lowercaseName, { name, value }); } /** * @see https://fetch.spec.whatwg.org/#concept-header-list-delete @@ -12227,12 +19766,12 @@ var require_headers = __commonJS({ * @param {boolean} isLowerCase */ delete(name, isLowerCase) { - this[kHeadersSortedMap] = null; + this.sortedMap = null; if (!isLowerCase) name = name.toLowerCase(); if (name === "set-cookie") { this.cookies = null; } - this[kHeadersMap].delete(name); + this.headersMap.delete(name); } /** * @see https://fetch.spec.whatwg.org/#concept-header-list-get @@ -12241,29 +19780,29 @@ var require_headers = __commonJS({ * @returns {string | null} */ get(name, isLowerCase) { - return this[kHeadersMap].get(isLowerCase ? name : name.toLowerCase())?.value ?? null; + return this.headersMap.get(isLowerCase ? name : name.toLowerCase())?.value ?? null; } *[Symbol.iterator]() { - for (const { 0: name, 1: { value } } of this[kHeadersMap]) { + for (const { 0: name, 1: { value } } of this.headersMap) { yield [name, value]; } } get entries() { const headers = {}; - if (this[kHeadersMap].size !== 0) { - for (const { name, value } of this[kHeadersMap].values()) { + if (this.headersMap.size !== 0) { + for (const { name, value } of this.headersMap.values()) { headers[name] = value; } } return headers; } rawValues() { - return this[kHeadersMap].values(); + return this.headersMap.values(); } get entriesList() { const headers = []; - if (this[kHeadersMap].size !== 0) { - for (const { 0: lowerName, 1: { name, value } } of this[kHeadersMap]) { + if (this.headersMap.size !== 0) { + for (const { 0: lowerName, 1: { name, value } } of this.headersMap) { if (lowerName === "set-cookie") { for (const cookie of this.cookies) { headers.push([name, cookie]); @@ -12277,13 +19816,13 @@ var require_headers = __commonJS({ } // https://fetch.spec.whatwg.org/#convert-header-names-to-a-sorted-lowercase-set toSortedArray() { - const size = this[kHeadersMap].size; + const size = this.headersMap.size; const array2 = new Array(size); if (size <= 32) { if (size === 0) { return array2; } - const iterator2 = this[kHeadersMap][Symbol.iterator](); + const iterator2 = this.headersMap[Symbol.iterator](); const firstValue = iterator2.next().value; array2[0] = [firstValue[0], firstValue[1].value]; assert(firstValue[1].value !== null); @@ -12315,7 +19854,7 @@ var require_headers = __commonJS({ return array2; } else { let i = 0; - for (const { 0: name, 1: { value } } of this[kHeadersMap]) { + for (const { 0: name, 1: { value } } of this.headersMap) { array2[i++] = [name, value]; assert(value !== null); } @@ -12325,7 +19864,14 @@ var require_headers = __commonJS({ }; var Headers = class _Headers { #guard; + /** + * @type {HeadersList} + */ #headersList; + /** + * @param {HeadersInit|Symbol} [init] + * @returns + */ constructor(init2 = void 0) { webidl.util.markAsUncloneable(this); if (init2 === kConstruct) { @@ -12334,7 +19880,7 @@ var require_headers = __commonJS({ this.#headersList = new HeadersList(); this.#guard = "none"; if (init2 !== void 0) { - init2 = webidl.converters.HeadersInit(init2, "Headers contructor", "init"); + init2 = webidl.converters.HeadersInit(init2, "Headers constructor", "init"); fill(this, init2); } } @@ -12433,29 +19979,6 @@ var require_headers = __commonJS({ } return []; } - // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine - get [kHeadersSortedMap]() { - if (this.#headersList[kHeadersSortedMap]) { - return this.#headersList[kHeadersSortedMap]; - } - const headers = []; - const names = this.#headersList.toSortedArray(); - const cookies = this.#headersList.cookies; - if (cookies === null || cookies.length === 1) { - return this.#headersList[kHeadersSortedMap] = names; - } - for (let i = 0; i < names.length; ++i) { - const { 0: name, 1: value } = names[i]; - if (name === "set-cookie") { - for (let j = 0; j < cookies.length; ++j) { - headers.push([name, cookies[j]]); - } - } else { - headers.push([name, value]); - } - } - return this.#headersList[kHeadersSortedMap] = headers; - } [util4.inspect.custom](depth, options) { options.depth ??= depth; return `Headers ${util4.formatWithOptions(options, this.#headersList.entries)}`; @@ -12466,11 +19989,18 @@ var require_headers = __commonJS({ static setHeadersGuard(o, guard) { o.#guard = guard; } + /** + * @param {Headers} o + */ static getHeadersList(o) { return o.#headersList; } - static setHeadersList(o, list) { - o.#headersList = list; + /** + * @param {Headers} target + * @param {HeadersList} list + */ + static setHeadersList(target, list) { + target.#headersList = list; } }; var { getHeadersGuard, setHeadersGuard, getHeadersList, setHeadersList } = Headers; @@ -12478,7 +20008,7 @@ var require_headers = __commonJS({ Reflect.deleteProperty(Headers, "setHeadersGuard"); Reflect.deleteProperty(Headers, "getHeadersList"); Reflect.deleteProperty(Headers, "setHeadersList"); - iteratorMixin("Headers", Headers, kHeadersSortedMap, 0, 1); + iteratorMixin("Headers", Headers, headersListSortAndCombine, 0, 1); Object.defineProperties(Headers.prototype, { append: kEnumerableProperty, delete: kEnumerableProperty, @@ -12495,7 +20025,7 @@ var require_headers = __commonJS({ } }); webidl.converters.HeadersInit = function(V, prefix, argument) { - if (webidl.util.Type(V) === "Object") { + if (webidl.util.Type(V) === webidl.util.Types.OBJECT) { const iterator2 = Reflect.get(V, Symbol.iterator); if (!util4.types.isProxy(V) && iterator2 === Headers.prototype.entries) { try { @@ -12533,7 +20063,7 @@ var require_response = __commonJS({ "node_modules/undici/lib/web/fetch/response.js"(exports2, module2) { "use strict"; var { Headers, HeadersList, fill, getHeadersGuard, setHeadersGuard, setHeadersList } = require_headers(); - var { extractBody, cloneBody, mixinBody, hasFinalizationRegistry, streamRegistry, bodyUnusable } = require_body(); + var { extractBody, cloneBody, mixinBody, streamRegistry, bodyUnusable } = require_body(); var util4 = require_util(); var nodeUtil = require("node:util"); var { kEnumerableProperty } = util4; @@ -12541,32 +20071,30 @@ var require_response = __commonJS({ isValidReasonPhrase, isCancelled, isAborted, - isBlobLike, - serializeJavascriptValueToJSONString, isErrorLike, - isomorphicEncode, environmentSettingsObject: relevantRealm } = require_util2(); var { redirectStatusSet, nullBodyStatus } = require_constants3(); - var { kState, kHeaders } = require_symbols2(); var { webidl } = require_webidl(); - var { FormData: FormData2 } = require_formdata(); var { URLSerializer } = require_data_url(); var { kConstruct } = require_symbols(); var assert = require("node:assert"); - var { types: types2 } = require("node:util"); + var { isomorphicEncode, serializeJavascriptValueToJSONString } = require_infra(); var textEncoder = new TextEncoder("utf-8"); var Response2 = class _Response { + /** @type {Headers} */ + #headers; + #state; // Creates network error Response. static error() { const responseObject = fromInnerResponse(makeNetworkError(), "immutable"); return responseObject; } // https://fetch.spec.whatwg.org/#dom-response-json - static json(data, init2 = {}) { + static json(data, init2 = void 0) { webidl.argumentLengthCheck(arguments, 1, "Response.json"); if (init2 !== null) { init2 = webidl.converters.ResponseInit(init2); @@ -12594,25 +20122,25 @@ var require_response = __commonJS({ throw new RangeError(`Invalid status code ${status}`); } const responseObject = fromInnerResponse(makeResponse({}), "immutable"); - responseObject[kState].status = status; + responseObject.#state.status = status; const value = isomorphicEncode(URLSerializer(parsedURL)); - responseObject[kState].headersList.append("location", value, true); + responseObject.#state.headersList.append("location", value, true); return responseObject; } // https://fetch.spec.whatwg.org/#dom-response - constructor(body = null, init2 = {}) { + constructor(body = null, init2 = void 0) { webidl.util.markAsUncloneable(this); if (body === kConstruct) { return; } if (body !== null) { - body = webidl.converters.BodyInit(body); + body = webidl.converters.BodyInit(body, "Response", "body"); } init2 = webidl.converters.ResponseInit(init2); - this[kState] = makeResponse({}); - this[kHeaders] = new Headers(kConstruct); - setHeadersGuard(this[kHeaders], "response"); - setHeadersList(this[kHeaders], this[kState].headersList); + this.#state = makeResponse({}); + this.#headers = new Headers(kConstruct); + setHeadersGuard(this.#headers, "response"); + setHeadersList(this.#headers, this.#state.headersList); let bodyWithType = null; if (body != null) { const [extractedBody, type] = extractBody(body); @@ -12623,12 +20151,12 @@ var require_response = __commonJS({ // Returns response’s type, e.g., "cors". get type() { webidl.brandCheck(this, _Response); - return this[kState].type; + return this.#state.type; } // Returns response’s URL, if it has one; otherwise the empty string. get url() { webidl.brandCheck(this, _Response); - const urlList = this[kState].urlList; + const urlList = this.#state.urlList; const url2 = urlList[urlList.length - 1] ?? null; if (url2 === null) { return ""; @@ -12638,50 +20166,50 @@ var require_response = __commonJS({ // Returns whether response was obtained through a redirect. get redirected() { webidl.brandCheck(this, _Response); - return this[kState].urlList.length > 1; + return this.#state.urlList.length > 1; } // Returns response’s status. get status() { webidl.brandCheck(this, _Response); - return this[kState].status; + return this.#state.status; } // Returns whether response’s status is an ok status. get ok() { webidl.brandCheck(this, _Response); - return this[kState].status >= 200 && this[kState].status <= 299; + return this.#state.status >= 200 && this.#state.status <= 299; } // Returns response’s status message. get statusText() { webidl.brandCheck(this, _Response); - return this[kState].statusText; + return this.#state.statusText; } // Returns response’s headers as Headers. get headers() { webidl.brandCheck(this, _Response); - return this[kHeaders]; + return this.#headers; } get body() { webidl.brandCheck(this, _Response); - return this[kState].body ? this[kState].body.stream : null; + return this.#state.body ? this.#state.body.stream : null; } get bodyUsed() { webidl.brandCheck(this, _Response); - return !!this[kState].body && util4.isDisturbed(this[kState].body.stream); + return !!this.#state.body && util4.isDisturbed(this.#state.body.stream); } // Returns a clone of response. clone() { webidl.brandCheck(this, _Response); - if (bodyUnusable(this)) { + if (bodyUnusable(this.#state)) { throw webidl.errors.exception({ header: "Response.clone", message: "Body has already been consumed." }); } - const clonedResponse = cloneResponse(this[kState]); - if (hasFinalizationRegistry && this[kState].body?.stream) { - streamRegistry.register(this, new WeakRef(this[kState].body.stream)); + const clonedResponse = cloneResponse(this.#state); + if (this.#state.urlList.length !== 0 && this.#state.body?.stream) { + streamRegistry.register(this, new WeakRef(this.#state.body.stream)); } - return fromInnerResponse(clonedResponse, getHeadersGuard(this[kHeaders])); + return fromInnerResponse(clonedResponse, getHeadersGuard(this.#headers)); } [nodeUtil.inspect.custom](depth, options) { if (options.depth === null) { @@ -12701,8 +20229,39 @@ var require_response = __commonJS({ }; return `Response ${nodeUtil.formatWithOptions(options, properties)}`; } + /** + * @param {Response} response + */ + static getResponseHeaders(response) { + return response.#headers; + } + /** + * @param {Response} response + * @param {Headers} newHeaders + */ + static setResponseHeaders(response, newHeaders) { + response.#headers = newHeaders; + } + /** + * @param {Response} response + */ + static getResponseState(response) { + return response.#state; + } + /** + * @param {Response} response + * @param {any} newState + */ + static setResponseState(response, newState) { + response.#state = newState; + } }; - mixinBody(Response2); + var { getResponseHeaders, setResponseHeaders, getResponseState, setResponseState } = Response2; + Reflect.deleteProperty(Response2, "getResponseHeaders"); + Reflect.deleteProperty(Response2, "setResponseHeaders"); + Reflect.deleteProperty(Response2, "getResponseState"); + Reflect.deleteProperty(Response2, "setResponseState"); + mixinBody(Response2, getResponseState); Object.defineProperties(Response2.prototype, { type: kEnumerableProperty, url: kEnumerableProperty, @@ -12733,7 +20292,7 @@ var require_response = __commonJS({ } const newResponse = makeResponse({ ...response, body: null }); if (response.body != null) { - newResponse.body = cloneBody(newResponse, response.body); + newResponse.body = cloneBody(response.body); } return newResponse; } @@ -12799,7 +20358,7 @@ var require_response = __commonJS({ } else if (type === "opaque") { return makeFilteredResponse(response, { type: "opaque", - urlList: Object.freeze([]), + urlList: [], status: 0, statusText: "", body: null @@ -12830,13 +20389,13 @@ var require_response = __commonJS({ } } if ("status" in init2 && init2.status != null) { - response[kState].status = init2.status; + getResponseState(response).status = init2.status; } if ("statusText" in init2 && init2.statusText != null) { - response[kState].statusText = init2.statusText; + getResponseState(response).statusText = init2.statusText; } if ("headers" in init2 && init2.headers != null) { - fill(response[kHeaders], init2.headers); + fill(getResponseHeaders(response), init2.headers); } if (body) { if (nullBodyStatus.includes(response.status)) { @@ -12845,53 +20404,45 @@ var require_response = __commonJS({ message: `Invalid response status code ${response.status}` }); } - response[kState].body = body.body; - if (body.type != null && !response[kState].headersList.contains("content-type", true)) { - response[kState].headersList.append("content-type", body.type, true); + getResponseState(response).body = body.body; + if (body.type != null && !getResponseState(response).headersList.contains("content-type", true)) { + getResponseState(response).headersList.append("content-type", body.type, true); } } } function fromInnerResponse(innerResponse, guard) { const response = new Response2(kConstruct); - response[kState] = innerResponse; - response[kHeaders] = new Headers(kConstruct); - setHeadersList(response[kHeaders], innerResponse.headersList); - setHeadersGuard(response[kHeaders], guard); - if (hasFinalizationRegistry && innerResponse.body?.stream) { + setResponseState(response, innerResponse); + const headers = new Headers(kConstruct); + setResponseHeaders(response, headers); + setHeadersList(headers, innerResponse.headersList); + setHeadersGuard(headers, guard); + if (innerResponse.urlList.length !== 0 && innerResponse.body?.stream) { streamRegistry.register(response, new WeakRef(innerResponse.body.stream)); } return response; } - webidl.converters.ReadableStream = webidl.interfaceConverter( - ReadableStream - ); - webidl.converters.FormData = webidl.interfaceConverter( - FormData2 - ); - webidl.converters.URLSearchParams = webidl.interfaceConverter( - URLSearchParams - ); webidl.converters.XMLHttpRequestBodyInit = function(V, prefix, name) { if (typeof V === "string") { return webidl.converters.USVString(V, prefix, name); } - if (isBlobLike(V)) { - return webidl.converters.Blob(V, prefix, name, { strict: false }); + if (webidl.is.Blob(V)) { + return V; } - if (ArrayBuffer.isView(V) || types2.isArrayBuffer(V)) { - return webidl.converters.BufferSource(V, prefix, name); + if (webidl.is.BufferSource(V)) { + return V; } - if (util4.isFormDataLike(V)) { - return webidl.converters.FormData(V, prefix, name, { strict: false }); + if (webidl.is.FormData(V)) { + return V; } - if (V instanceof URLSearchParams) { - return webidl.converters.URLSearchParams(V, prefix, name); + if (webidl.is.URLSearchParams(V)) { + return V; } return webidl.converters.DOMString(V, prefix, name); }; webidl.converters.BodyInit = function(V, prefix, argument) { - if (V instanceof ReadableStream) { - return webidl.converters.ReadableStream(V, prefix, argument); + if (webidl.is.ReadableStream(V)) { + return V; } if (V?.[Symbol.asyncIterator]) { return V; @@ -12914,6 +20465,7 @@ var require_response = __commonJS({ converter: webidl.converters.HeadersInit } ]); + webidl.is.Response = webidl.util.MakeTypeAssertion(Response2); module2.exports = { isNetworkError, makeNetworkError, @@ -12922,49 +20474,8 @@ var require_response = __commonJS({ filterResponse, Response: Response2, cloneResponse, - fromInnerResponse - }; - } -}); - -// node_modules/undici/lib/web/fetch/dispatcher-weakref.js -var require_dispatcher_weakref = __commonJS({ - "node_modules/undici/lib/web/fetch/dispatcher-weakref.js"(exports2, module2) { - "use strict"; - var { kConnected, kSize } = require_symbols(); - var CompatWeakRef = class { - constructor(value) { - this.value = value; - } - deref() { - return this.value[kConnected] === 0 && this.value[kSize] === 0 ? void 0 : this.value; - } - }; - var CompatFinalizer = class { - constructor(finalizer) { - this.finalizer = finalizer; - } - register(dispatcher, key) { - if (dispatcher.on) { - dispatcher.on("disconnect", () => { - if (dispatcher[kConnected] === 0 && dispatcher[kSize] === 0) { - this.finalizer(key); - } - }); - } - } - unregister(key) { - } - }; - module2.exports = function() { - if (process.env.NODE_V8_COVERAGE && process.version.startsWith("v18")) { - process._rawDebug("Using compatibility WeakRef and FinalizationRegistry"); - return { - WeakRef: CompatWeakRef, - FinalizationRegistry: CompatFinalizer - }; - } - return { WeakRef, FinalizationRegistry }; + fromInnerResponse, + getResponseState }; } }); @@ -12975,7 +20486,6 @@ var require_request2 = __commonJS({ "use strict"; var { extractBody, mixinBody, cloneBody, bodyUnusable } = require_body(); var { Headers, fill: fillHeaders, HeadersList, setHeadersGuard, getHeadersGuard, setHeadersList, getHeadersList } = require_headers(); - var { FinalizationRegistry: FinalizationRegistry2 } = require_dispatcher_weakref()(); var util4 = require_util(); var nodeUtil = require("node:util"); var { @@ -12994,17 +20504,22 @@ var require_request2 = __commonJS({ requestDuplex } = require_constants3(); var { kEnumerableProperty, normalizedMethodRecordsBase, normalizedMethodRecords } = util4; - var { kHeaders, kSignal, kState, kDispatcher } = require_symbols2(); var { webidl } = require_webidl(); var { URLSerializer } = require_data_url(); var { kConstruct } = require_symbols(); var assert = require("node:assert"); - var { getMaxListeners, setMaxListeners, getEventListeners, defaultMaxListeners } = require("node:events"); + var { getMaxListeners, setMaxListeners, defaultMaxListeners } = require("node:events"); var kAbortController = /* @__PURE__ */ Symbol("abortController"); - var requestFinalizer = new FinalizationRegistry2(({ signal, abort }) => { + var requestFinalizer = new FinalizationRegistry(({ signal, abort }) => { signal.removeEventListener("abort", abort); }); var dependentControllerMap = /* @__PURE__ */ new WeakMap(); + var abortSignalHasEventHandlerLeakWarning; + try { + abortSignalHasEventHandlerLeakWarning = getMaxListeners(new AbortController().signal) > 0; + } catch { + abortSignalHasEventHandlerLeakWarning = false; + } function buildAbort(acRef) { return abort; function abort() { @@ -13031,22 +20546,29 @@ var require_request2 = __commonJS({ } var patchMethodWarning = false; var Request = class _Request { + /** @type {AbortSignal} */ + #signal; + /** @type {import('../../dispatcher/dispatcher')} */ + #dispatcher; + /** @type {Headers} */ + #headers; + #state; // https://fetch.spec.whatwg.org/#dom-request - constructor(input, init2 = {}) { + constructor(input, init2 = void 0) { webidl.util.markAsUncloneable(this); if (input === kConstruct) { return; } const prefix = "Request constructor"; webidl.argumentLengthCheck(arguments, 1, prefix); - input = webidl.converters.RequestInfo(input, prefix, "input"); - init2 = webidl.converters.RequestInit(init2, prefix, "init"); + input = webidl.converters.RequestInfo(input); + init2 = webidl.converters.RequestInit(init2); let request3 = null; let fallbackMode = null; const baseUrl = environmentSettingsObject.settingsObject.baseUrl; let signal = null; if (typeof input === "string") { - this[kDispatcher] = init2.dispatcher; + this.#dispatcher = init2.dispatcher; let parsedURL; try { parsedURL = new URL(input, baseUrl); @@ -13061,10 +20583,10 @@ var require_request2 = __commonJS({ request3 = makeRequest({ urlList: [parsedURL] }); fallbackMode = "cors"; } else { - this[kDispatcher] = init2.dispatcher || input[kDispatcher]; - assert(input instanceof _Request); - request3 = input[kState]; - signal = input[kSignal]; + assert(webidl.is.Request(input)); + request3 = input.#state; + signal = input.#signal; + this.#dispatcher = init2.dispatcher || input.#dispatcher; } const origin = environmentSettingsObject.settingsObject.origin; let window2 = "client"; @@ -13215,46 +20737,36 @@ var require_request2 = __commonJS({ if (init2.signal !== void 0) { signal = init2.signal; } - this[kState] = request3; + this.#state = request3; const ac = new AbortController(); - this[kSignal] = ac.signal; + this.#signal = ac.signal; if (signal != null) { - if (!signal || typeof signal.aborted !== "boolean" || typeof signal.addEventListener !== "function") { - throw new TypeError( - "Failed to construct 'Request': member signal is not of type AbortSignal." - ); - } if (signal.aborted) { ac.abort(signal.reason); } else { this[kAbortController] = ac; const acRef = new WeakRef(ac); const abort = buildAbort(acRef); - try { - if (typeof getMaxListeners === "function" && getMaxListeners(signal) === defaultMaxListeners) { - setMaxListeners(1500, signal); - } else if (getEventListeners(signal, "abort").length >= defaultMaxListeners) { - setMaxListeners(1500, signal); - } - } catch { + if (abortSignalHasEventHandlerLeakWarning && getMaxListeners(signal) === defaultMaxListeners) { + setMaxListeners(1500, signal); } util4.addAbortListener(signal, abort); requestFinalizer.register(ac, { signal, abort }, abort); } } - this[kHeaders] = new Headers(kConstruct); - setHeadersList(this[kHeaders], request3.headersList); - setHeadersGuard(this[kHeaders], "request"); + this.#headers = new Headers(kConstruct); + setHeadersList(this.#headers, request3.headersList); + setHeadersGuard(this.#headers, "request"); if (mode === "no-cors") { if (!corsSafeListedMethodsSet.has(request3.method)) { throw new TypeError( `'${request3.method} is unsupported in no-cors mode.` ); } - setHeadersGuard(this[kHeaders], "request-no-cors"); + setHeadersGuard(this.#headers, "request-no-cors"); } if (initHasKey) { - const headersList = getHeadersList(this[kHeaders]); + const headersList = getHeadersList(this.#headers); const headers = init2.headers !== void 0 ? init2.headers : new HeadersList(headersList); headersList.clear(); if (headers instanceof HeadersList) { @@ -13263,10 +20775,10 @@ var require_request2 = __commonJS({ } headersList.cookies = headers.cookies; } else { - fillHeaders(this[kHeaders], headers); + fillHeaders(this.#headers, headers); } } - const inputBody = input instanceof _Request ? input[kState].body : null; + const inputBody = webidl.is.Request(input) ? input.#state.body : null; if ((init2.body != null || inputBody != null) && (request3.method === "GET" || request3.method === "HEAD")) { throw new TypeError("Request with GET/HEAD method cannot have body."); } @@ -13277,8 +20789,8 @@ var require_request2 = __commonJS({ request3.keepalive ); initBody = extractedBody; - if (contentType && !getHeadersList(this[kHeaders]).contains("content-type", true)) { - this[kHeaders].append("content-type", contentType); + if (contentType && !getHeadersList(this.#headers).contains("content-type", true)) { + this.#headers.append("content-type", contentType, true); } } const inputOrInitBody = initBody ?? inputBody; @@ -13295,7 +20807,7 @@ var require_request2 = __commonJS({ } let finalBody = inputOrInitBody; if (initBody == null && inputBody != null) { - if (bodyUnusable(input)) { + if (bodyUnusable(input.#state)) { throw new TypeError( "Cannot construct a Request with a Request object that has already been used." ); @@ -13308,30 +20820,30 @@ var require_request2 = __commonJS({ stream: identityTransform.readable }; } - this[kState].body = finalBody; + this.#state.body = finalBody; } // Returns request’s HTTP method, which is "GET" by default. get method() { webidl.brandCheck(this, _Request); - return this[kState].method; + return this.#state.method; } // Returns the URL of request as a string. get url() { webidl.brandCheck(this, _Request); - return URLSerializer(this[kState].url); + return URLSerializer(this.#state.url); } // Returns a Headers object consisting of the headers associated with request. // Note that headers added in the network layer by the user agent will not // be accounted for in this object, e.g., the "Host" header. get headers() { webidl.brandCheck(this, _Request); - return this[kHeaders]; + return this.#headers; } // Returns the kind of resource requested by request, e.g., "document" // or "script". get destination() { webidl.brandCheck(this, _Request); - return this[kState].destination; + return this.#state.destination; } // Returns the referrer of request. Its value can be a same-origin URL if // explicitly set in init, the empty string to indicate no referrer, and @@ -13340,40 +20852,41 @@ var require_request2 = __commonJS({ // request being made. get referrer() { webidl.brandCheck(this, _Request); - if (this[kState].referrer === "no-referrer") { + if (this.#state.referrer === "no-referrer") { return ""; } - if (this[kState].referrer === "client") { + if (this.#state.referrer === "client") { return "about:client"; } - return this[kState].referrer.toString(); + return this.#state.referrer.toString(); } // Returns the referrer policy associated with request. // This is used during fetching to compute the value of the request’s // referrer. get referrerPolicy() { webidl.brandCheck(this, _Request); - return this[kState].referrerPolicy; + return this.#state.referrerPolicy; } // Returns the mode associated with request, which is a string indicating // whether the request will use CORS, or will be restricted to same-origin // URLs. get mode() { webidl.brandCheck(this, _Request); - return this[kState].mode; + return this.#state.mode; } // Returns the credentials mode associated with request, // which is a string indicating whether credentials will be sent with the // request always, never, or only when sent to a same-origin URL. get credentials() { - return this[kState].credentials; + webidl.brandCheck(this, _Request); + return this.#state.credentials; } // Returns the cache mode associated with request, // which is a string indicating how the request will // interact with the browser’s cache when fetching. get cache() { webidl.brandCheck(this, _Request); - return this[kState].cache; + return this.#state.cache; } // Returns the redirect mode associated with request, // which is a string indicating how redirects for the @@ -13381,47 +20894,47 @@ var require_request2 = __commonJS({ // will follow redirects by default. get redirect() { webidl.brandCheck(this, _Request); - return this[kState].redirect; + return this.#state.redirect; } // Returns request’s subresource integrity metadata, which is a // cryptographic hash of the resource being fetched. Its value // consists of multiple hashes separated by whitespace. [SRI] get integrity() { webidl.brandCheck(this, _Request); - return this[kState].integrity; + return this.#state.integrity; } // Returns a boolean indicating whether or not request can outlive the // global in which it was created. get keepalive() { webidl.brandCheck(this, _Request); - return this[kState].keepalive; + return this.#state.keepalive; } // Returns a boolean indicating whether or not request is for a reload // navigation. get isReloadNavigation() { webidl.brandCheck(this, _Request); - return this[kState].reloadNavigation; + return this.#state.reloadNavigation; } // Returns a boolean indicating whether or not request is for a history // navigation (a.k.a. back-forward navigation). get isHistoryNavigation() { webidl.brandCheck(this, _Request); - return this[kState].historyNavigation; + return this.#state.historyNavigation; } // Returns the signal associated with request, which is an AbortSignal // object indicating whether or not request has been aborted, and its // abort event handler. get signal() { webidl.brandCheck(this, _Request); - return this[kSignal]; + return this.#signal; } get body() { webidl.brandCheck(this, _Request); - return this[kState].body ? this[kState].body.stream : null; + return this.#state.body ? this.#state.body.stream : null; } get bodyUsed() { webidl.brandCheck(this, _Request); - return !!this[kState].body && util4.isDisturbed(this[kState].body.stream); + return !!this.#state.body && util4.isDisturbed(this.#state.body.stream); } get duplex() { webidl.brandCheck(this, _Request); @@ -13430,10 +20943,10 @@ var require_request2 = __commonJS({ // Returns a clone of request. clone() { webidl.brandCheck(this, _Request); - if (bodyUnusable(this)) { + if (bodyUnusable(this.#state)) { throw new TypeError("unusable"); } - const clonedRequest = cloneRequest(this[kState]); + const clonedRequest = cloneRequest(this.#state); const ac = new AbortController(); if (this.signal.aborted) { ac.abort(this.signal.reason); @@ -13450,7 +20963,7 @@ var require_request2 = __commonJS({ buildAbort(acRef) ); } - return fromInnerRequest(clonedRequest, ac.signal, getHeadersGuard(this[kHeaders])); + return fromInnerRequest(clonedRequest, this.#dispatcher, ac.signal, getHeadersGuard(this.#headers)); } [nodeUtil.inspect.custom](depth, options) { if (options.depth === null) { @@ -13476,8 +20989,56 @@ var require_request2 = __commonJS({ }; return `Request ${nodeUtil.formatWithOptions(options, properties)}`; } + /** + * @param {Request} request + * @param {AbortSignal} newSignal + */ + static setRequestSignal(request3, newSignal) { + request3.#signal = newSignal; + return request3; + } + /** + * @param {Request} request + */ + static getRequestDispatcher(request3) { + return request3.#dispatcher; + } + /** + * @param {Request} request + * @param {import('../../dispatcher/dispatcher')} newDispatcher + */ + static setRequestDispatcher(request3, newDispatcher) { + request3.#dispatcher = newDispatcher; + } + /** + * @param {Request} request + * @param {Headers} newHeaders + */ + static setRequestHeaders(request3, newHeaders) { + request3.#headers = newHeaders; + } + /** + * @param {Request} request + */ + static getRequestState(request3) { + return request3.#state; + } + /** + * @param {Request} request + * @param {any} newState + */ + static setRequestState(request3, newState) { + request3.#state = newState; + } }; - mixinBody(Request); + var { setRequestSignal, getRequestDispatcher, setRequestDispatcher, setRequestHeaders, getRequestState, setRequestState } = Request; + Reflect.deleteProperty(Request, "setRequestSignal"); + Reflect.deleteProperty(Request, "getRequestDispatcher"); + Reflect.deleteProperty(Request, "setRequestDispatcher"); + Reflect.deleteProperty(Request, "setRequestHeaders"); + Reflect.deleteProperty(Request, "getRequestState"); + Reflect.deleteProperty(Request, "setRequestState"); + mixinBody(Request, getRequestState); function makeRequest(init2) { return { method: init2.method ?? "GET", @@ -13515,6 +21076,8 @@ var require_request2 = __commonJS({ preventNoCacheCacheControlHeaderModification: init2.preventNoCacheCacheControlHeaderModification ?? false, done: init2.done ?? false, timingAllowFailed: init2.timingAllowFailed ?? false, + useURLCredentials: init2.useURLCredentials ?? void 0, + traversableForUserPrompts: init2.traversableForUserPrompts ?? "client", urlList: init2.urlList, url: init2.urlList[0], headersList: init2.headersList ? new HeadersList(init2.headersList) : new HeadersList() @@ -13523,17 +21086,19 @@ var require_request2 = __commonJS({ function cloneRequest(request3) { const newRequest = makeRequest({ ...request3, body: null }); if (request3.body != null) { - newRequest.body = cloneBody(newRequest, request3.body); + newRequest.body = cloneBody(request3.body); } return newRequest; } - function fromInnerRequest(innerRequest, signal, guard) { + function fromInnerRequest(innerRequest, dispatcher, signal, guard) { const request3 = new Request(kConstruct); - request3[kState] = innerRequest; - request3[kSignal] = signal; - request3[kHeaders] = new Headers(kConstruct); - setHeadersList(request3[kHeaders], innerRequest.headersList); - setHeadersGuard(request3[kHeaders], guard); + setRequestState(request3, innerRequest); + setRequestDispatcher(request3, dispatcher); + setRequestSignal(request3, signal); + const headers = new Headers(kConstruct); + setRequestHeaders(request3, headers); + setHeadersList(headers, innerRequest.headersList); + setHeadersGuard(headers, guard); return request3; } Object.defineProperties(Request.prototype, { @@ -13562,21 +21127,16 @@ var require_request2 = __commonJS({ configurable: true } }); - webidl.converters.Request = webidl.interfaceConverter( - Request - ); - webidl.converters.RequestInfo = function(V, prefix, argument) { + webidl.is.Request = webidl.util.MakeTypeAssertion(Request); + webidl.converters.RequestInfo = function(V) { if (typeof V === "string") { - return webidl.converters.USVString(V, prefix, argument); + return webidl.converters.USVString(V); } - if (V instanceof Request) { - return webidl.converters.Request(V, prefix, argument); + if (webidl.is.Request(V)) { + return V; } - return webidl.converters.USVString(V, prefix, argument); + return webidl.converters.USVString(V); }; - webidl.converters.AbortSignal = webidl.interfaceConverter( - AbortSignal - ); webidl.converters.RequestInit = webidl.dictionaryConverter([ { key: "method", @@ -13640,8 +21200,7 @@ var require_request2 = __commonJS({ (signal) => webidl.converters.AbortSignal( signal, "RequestInit", - "signal", - { strict: false } + "signal" ) ) }, @@ -13658,9 +21217,160 @@ var require_request2 = __commonJS({ key: "dispatcher", // undici specific option converter: webidl.converters.any + }, + { + key: "priority", + converter: webidl.converters.DOMString, + allowedValues: ["high", "low", "auto"], + defaultValue: () => "auto" } ]); - module2.exports = { Request, makeRequest, fromInnerRequest, cloneRequest }; + module2.exports = { + Request, + makeRequest, + fromInnerRequest, + cloneRequest, + getRequestDispatcher, + getRequestState + }; + } +}); + +// node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js +var require_subresource_integrity = __commonJS({ + "node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { runtimeFeatures } = require_runtime_features(); + var { asciiLowercase } = require_infra(); + var validSRIHashAlgorithmTokenSet = /* @__PURE__ */ new Map([["sha256", 0], ["sha384", 1], ["sha512", 2]]); + var crypto3; + if (runtimeFeatures.has("crypto")) { + crypto3 = require("node:crypto"); + const cryptoHashes = crypto3.getHashes(); + if (cryptoHashes.length === 0) { + validSRIHashAlgorithmTokenSet.clear(); + } + for (const algorithm of validSRIHashAlgorithmTokenSet.keys()) { + if (cryptoHashes.includes(algorithm) === false) { + validSRIHashAlgorithmTokenSet.delete(algorithm); + } + } + } else { + validSRIHashAlgorithmTokenSet.clear(); + } + var getSRIHashAlgorithmIndex = ( + /** @type {GetSRIHashAlgorithmIndex} */ + Map.prototype.get.bind( + validSRIHashAlgorithmTokenSet + ) + ); + var isValidSRIHashAlgorithm = (algorithm) => validSRIHashAlgorithmTokenSet.has(asciiLowercase(algorithm)); + var bytesMatch = runtimeFeatures.has("crypto") === false || validSRIHashAlgorithmTokenSet.size === 0 ? () => true : (bytes, metadataList) => { + const parsedMetadata = parseMetadata(metadataList); + if (parsedMetadata.length === 0) { + return true; + } + const metadata = getStrongestMetadata(parsedMetadata); + for (const item of metadata) { + const algorithm = item.alg; + const expectedValue = item.val; + const actualValue = applyAlgorithmToBytes(algorithm, bytes); + if (caseSensitiveMatch(actualValue, expectedValue)) { + return true; + } + } + return false; + }; + function getStrongestMetadata(metadataList) { + const result = []; + let strongest = null; + for (const item of metadataList) { + assert(isValidSRIHashAlgorithm(item.alg), "Invalid SRI hash algorithm token"); + if (result.length === 0) { + result.push(item); + strongest = item; + continue; + } + const currentAlgorithm = ( + /** @type {Metadata} */ + strongest.alg + ); + const currentAlgorithmIndex = getSRIHashAlgorithmIndex(currentAlgorithm); + const newAlgorithm = item.alg; + const newAlgorithmIndex = getSRIHashAlgorithmIndex(newAlgorithm); + if (newAlgorithmIndex < currentAlgorithmIndex) { + continue; + } else if (newAlgorithmIndex > currentAlgorithmIndex) { + strongest = item; + result[0] = item; + result.length = 1; + } else { + result.push(item); + } + } + return result; + } + function parseMetadata(metadata) { + const result = []; + for (const item of metadata.split(" ")) { + const expressionAndOptions = item.split("?", 1); + const algorithmExpression = expressionAndOptions[0]; + let base64Value = ""; + const algorithmAndValue = [algorithmExpression.slice(0, 6), algorithmExpression.slice(7)]; + const algorithm = algorithmAndValue[0]; + if (!isValidSRIHashAlgorithm(algorithm)) { + continue; + } + if (algorithmAndValue[1]) { + base64Value = algorithmAndValue[1]; + } + const metadata2 = { + // Possible spec bug? + alg: asciiLowercase(algorithm), + val: base64Value + }; + result.push(metadata2); + } + return result; + } + var applyAlgorithmToBytes = (algorithm, bytes) => { + return crypto3.hash(algorithm, bytes, "base64"); + }; + function caseSensitiveMatch(actualValue, expectedValue) { + let actualValueLength = actualValue.length; + if (actualValueLength !== 0 && actualValue[actualValueLength - 1] === "=") { + actualValueLength -= 1; + } + if (actualValueLength !== 0 && actualValue[actualValueLength - 1] === "=") { + actualValueLength -= 1; + } + let expectedValueLength = expectedValue.length; + if (expectedValueLength !== 0 && expectedValue[expectedValueLength - 1] === "=") { + expectedValueLength -= 1; + } + if (expectedValueLength !== 0 && expectedValue[expectedValueLength - 1] === "=") { + expectedValueLength -= 1; + } + if (actualValueLength !== expectedValueLength) { + return false; + } + for (let i = 0; i < actualValueLength; ++i) { + if (actualValue[i] === expectedValue[i] || actualValue[i] === "+" && expectedValue[i] === "-" || actualValue[i] === "/" && expectedValue[i] === "_") { + continue; + } + return false; + } + return true; + } + module2.exports = { + applyAlgorithmToBytes, + bytesMatch, + caseSensitiveMatch, + isValidSRIHashAlgorithm, + getStrongestMetadata, + parseMetadata + }; } }); @@ -13673,13 +21383,13 @@ var require_fetch = __commonJS({ makeAppropriateNetworkError, filterResponse, makeResponse, - fromInnerResponse + fromInnerResponse, + getResponseState } = require_response(); var { HeadersList } = require_headers(); - var { Request, cloneRequest } = require_request2(); + var { Request, cloneRequest, getRequestDispatcher, getRequestState } = require_request2(); var zlib3 = require("node:zlib"); var { - bytesMatch, makePolicyContainer, clonePolicyContainer, requestBadPort, @@ -13695,15 +21405,12 @@ var require_fetch = __commonJS({ crossOriginResourcePolicyCheck, determineRequestsReferrer, coarsenedSharedCurrentTime, - createDeferredPromise, - isBlobLike, sameOrigin, isCancelled, isAborted, isErrorLike, fullyReadBody, readableStreamClose, - isomorphicEncode, urlIsLocal, urlIsHttpHttpsScheme, urlHasHttpsScheme, @@ -13711,9 +21418,11 @@ var require_fetch = __commonJS({ simpleRangeHeaderValue, buildContentRange, createInflate, - extractMimeType + extractMimeType, + hasAuthenticationEntry, + includesCredentials, + isTraversableNavigable } = require_util2(); - var { kState, kDispatcher } = require_symbols2(); var assert = require("node:assert"); var { safelyExtractBody, extractBody } = require_body(); var { @@ -13724,12 +21433,17 @@ var require_fetch = __commonJS({ subresourceSet } = require_constants3(); var EE = require("node:events"); - var { Readable: Readable4, pipeline: pipeline2, finished } = require("node:stream"); - var { addAbortListener, isErrored, isReadable, bufferToLowerCasedHeaderName } = require_util(); + var { Readable: Readable4, pipeline: pipeline2, finished, isErrored, isReadable } = require("node:stream"); + var { addAbortListener, bufferToLowerCasedHeaderName } = require_util(); var { dataURLProcessor, serializeAMimeType, minimizeSupportedMimeType } = require_data_url(); var { getGlobalDispatcher } = require_global2(); var { webidl } = require_webidl(); var { STATUS_CODES } = require("node:http"); + var { bytesMatch } = require_subresource_integrity(); + var { createDeferredPromise } = require_promise(); + var { isomorphicEncode } = require_infra(); + var { runtimeFeatures } = require_runtime_features(); + var hasZstd = runtimeFeatures.has("zstd"); var GET_OR_HEAD = ["GET", "HEAD"]; var defaultUserAgent = typeof __UNDICI_IS_NODE__ !== "undefined" || typeof esbuildDetection !== "undefined" ? "node" : "undici"; var resolveObjectURL; @@ -13776,9 +21490,9 @@ var require_fetch = __commonJS({ p.reject(e); return p.promise; } - const request3 = requestObject[kState]; + const request3 = getRequestState(requestObject); if (requestObject.signal.aborted) { - abortFetch(p, request3, null, requestObject.signal.reason); + abortFetch(p, request3, null, requestObject.signal.reason, null); return p.promise; } const globalObject = request3.client.globalObject; @@ -13795,7 +21509,7 @@ var require_fetch = __commonJS({ assert(controller != null); controller.abort(requestObject.signal.reason); const realResponse = responseObject?.deref(); - abortFetch(p, request3, realResponse, requestObject.signal.reason); + abortFetch(p, request3, realResponse, requestObject.signal.reason, controller.controller); } ); const processResponse = (response) => { @@ -13803,7 +21517,7 @@ var require_fetch = __commonJS({ return; } if (response.aborted) { - abortFetch(p, request3, responseObject, controller.serializedAbortReason); + abortFetch(p, request3, responseObject, controller.serializedAbortReason, controller.controller); return; } if (response.type === "error") { @@ -13818,8 +21532,11 @@ var require_fetch = __commonJS({ request: request3, processResponseEndOfBody: handleFetchDone, processResponse, - dispatcher: requestObject[kDispatcher] + dispatcher: getRequestDispatcher(requestObject), // undici + // Keep requestObject alive to prevent its AbortController from being GC'd + // See https://github.com/nodejs/undici/issues/4627 + requestObject }); return p.promise; } @@ -13852,15 +21569,18 @@ var require_fetch = __commonJS({ originalURL.href, initiatorType, globalThis, - cacheState + cacheState, + "", + // bodyType + response.status ); } var markResourceTiming = performance.markResourceTiming; - function abortFetch(p, request3, responseObject, error3) { + function abortFetch(p, request3, responseObject, error3, controller) { if (p) { p.reject(error3); } - if (request3.body != null && isReadable(request3.body?.stream)) { + if (request3.body?.stream != null && isReadable(request3.body.stream)) { request3.body.stream.cancel(error3).catch((err) => { if (err.code === "ERR_INVALID_STATE") { return; @@ -13871,14 +21591,9 @@ var require_fetch = __commonJS({ if (responseObject == null) { return; } - const response = responseObject[kState]; - if (response.body != null && isReadable(response.body?.stream)) { - response.body.stream.cancel(error3).catch((err) => { - if (err.code === "ERR_INVALID_STATE") { - return; - } - throw err; - }); + const response = getResponseState(responseObject); + if (response.body?.stream != null && isReadable(response.body.stream)) { + controller.error(error3); } } function fetching({ @@ -13889,8 +21604,10 @@ var require_fetch = __commonJS({ processResponseEndOfBody, processResponseConsumeBody, useParallelQueue = false, - dispatcher = getGlobalDispatcher() + dispatcher = getGlobalDispatcher(), // undici + requestObject = null + // Keep alive to prevent AbortController GC, see #4627 }) { assert(dispatcher); let taskDestination = null; @@ -13913,7 +21630,9 @@ var require_fetch = __commonJS({ processResponseConsumeBody, processResponseEndOfBody, taskDestination, - crossOriginIsolatedCapability + crossOriginIsolatedCapability, + // Keep requestObject alive to prevent its AbortController from being GC'd + requestObject }; assert(!request3.body || request3.body.stream); if (request3.window === "client") { @@ -13942,29 +21661,27 @@ var require_fetch = __commonJS({ } if (subresourceSet.has(request3.destination)) { } - mainFetch(fetchParams).catch((err) => { - fetchParams.controller.terminate(err); - }); + mainFetch(fetchParams, false); return fetchParams.controller; } - async function mainFetch(fetchParams, recursive = false) { - const request3 = fetchParams.request; - let response = null; - if (request3.localURLsOnly && !urlIsLocal(requestCurrentURL(request3))) { - response = makeNetworkError("local URLs only"); - } - tryUpgradeRequestToAPotentiallyTrustworthyURL(request3); - if (requestBadPort(request3) === "blocked") { - response = makeNetworkError("bad port"); - } - if (request3.referrerPolicy === "") { - request3.referrerPolicy = request3.policyContainer.referrerPolicy; - } - if (request3.referrer !== "no-referrer") { - request3.referrer = determineRequestsReferrer(request3); - } - if (response === null) { - response = await (async () => { + async function mainFetch(fetchParams, recursive) { + try { + const request3 = fetchParams.request; + let response = null; + if (request3.localURLsOnly && !urlIsLocal(requestCurrentURL(request3))) { + response = makeNetworkError("local URLs only"); + } + tryUpgradeRequestToAPotentiallyTrustworthyURL(request3); + if (requestBadPort(request3) === "blocked") { + response = makeNetworkError("bad port"); + } + if (request3.referrerPolicy === "") { + request3.referrerPolicy = request3.policyContainer.referrerPolicy; + } + if (request3.referrer !== "no-referrer") { + request3.referrer = determineRequestsReferrer(request3); + } + if (response === null) { const currentURL = requestCurrentURL(request3); if ( // - request’s current URL’s origin is same origin with request’s origin, @@ -13974,74 +21691,75 @@ var require_fetch = __commonJS({ (request3.mode === "navigate" || request3.mode === "websocket") ) { request3.responseTainting = "basic"; - return await schemeFetch(fetchParams); - } - if (request3.mode === "same-origin") { - return makeNetworkError('request mode cannot be "same-origin"'); - } - if (request3.mode === "no-cors") { + response = await schemeFetch(fetchParams); + } else if (request3.mode === "same-origin") { + response = makeNetworkError('request mode cannot be "same-origin"'); + } else if (request3.mode === "no-cors") { if (request3.redirect !== "follow") { - return makeNetworkError( + response = makeNetworkError( 'redirect mode cannot be "follow" for "no-cors" request' ); + } else { + request3.responseTainting = "opaque"; + response = await schemeFetch(fetchParams); } - request3.responseTainting = "opaque"; - return await schemeFetch(fetchParams); + } else if (!urlIsHttpHttpsScheme(requestCurrentURL(request3))) { + response = makeNetworkError("URL scheme must be a HTTP(S) scheme"); + } else { + request3.responseTainting = "cors"; + response = await httpFetch(fetchParams); } - if (!urlIsHttpHttpsScheme(requestCurrentURL(request3))) { - return makeNetworkError("URL scheme must be a HTTP(S) scheme"); + } + if (recursive) { + return response; + } + if (response.status !== 0 && !response.internalResponse) { + if (request3.responseTainting === "cors") { + } + if (request3.responseTainting === "basic") { + response = filterResponse(response, "basic"); + } else if (request3.responseTainting === "cors") { + response = filterResponse(response, "cors"); + } else if (request3.responseTainting === "opaque") { + response = filterResponse(response, "opaque"); + } else { + assert(false); } - request3.responseTainting = "cors"; - return await httpFetch(fetchParams); - })(); - } - if (recursive) { - return response; - } - if (response.status !== 0 && !response.internalResponse) { - if (request3.responseTainting === "cors") { } - if (request3.responseTainting === "basic") { - response = filterResponse(response, "basic"); - } else if (request3.responseTainting === "cors") { - response = filterResponse(response, "cors"); - } else if (request3.responseTainting === "opaque") { - response = filterResponse(response, "opaque"); - } else { - assert(false); + let internalResponse = response.status === 0 ? response : response.internalResponse; + if (internalResponse.urlList.length === 0) { + internalResponse.urlList.push(...request3.urlList); } - } - let internalResponse = response.status === 0 ? response : response.internalResponse; - if (internalResponse.urlList.length === 0) { - internalResponse.urlList.push(...request3.urlList); - } - if (!request3.timingAllowFailed) { - response.timingAllowPassed = true; - } - if (response.type === "opaque" && internalResponse.status === 206 && internalResponse.rangeRequested && !request3.headers.contains("range", true)) { - response = internalResponse = makeNetworkError(); - } - if (response.status !== 0 && (request3.method === "HEAD" || request3.method === "CONNECT" || nullBodyStatus.includes(internalResponse.status))) { - internalResponse.body = null; - fetchParams.controller.dump = true; - } - if (request3.integrity) { - const processBodyError = (reason) => fetchFinale(fetchParams, makeNetworkError(reason)); - if (request3.responseTainting === "opaque" || response.body == null) { - processBodyError(response.error); - return; + if (!request3.timingAllowFailed) { + response.timingAllowPassed = true; + } + if (response.type === "opaque" && internalResponse.status === 206 && internalResponse.rangeRequested && !request3.headers.contains("range", true)) { + response = internalResponse = makeNetworkError(); } - const processBody = (bytes) => { - if (!bytesMatch(bytes, request3.integrity)) { - processBodyError("integrity mismatch"); + if (response.status !== 0 && (request3.method === "HEAD" || request3.method === "CONNECT" || nullBodyStatus.includes(internalResponse.status))) { + internalResponse.body = null; + fetchParams.controller.dump = true; + } + if (request3.integrity) { + const processBodyError = (reason) => fetchFinale(fetchParams, makeNetworkError(reason)); + if (request3.responseTainting === "opaque" || response.body == null) { + processBodyError(response.error); return; } - response.body = safelyExtractBody(bytes)[0]; + const processBody = (bytes) => { + if (!bytesMatch(bytes, request3.integrity)) { + processBodyError("integrity mismatch"); + return; + } + response.body = safelyExtractBody(bytes)[0]; + fetchFinale(fetchParams, response); + }; + fullyReadBody(response.body, processBody, processBodyError); + } else { fetchFinale(fetchParams, response); - }; - await fullyReadBody(response.body, processBody, processBodyError); - } else { - fetchFinale(fetchParams, response); + } + } catch (err) { + fetchParams.controller.terminate(err); } } function schemeFetch(fetchParams) { @@ -14063,7 +21781,7 @@ var require_fetch = __commonJS({ return Promise.resolve(makeNetworkError("NetworkError when attempting to fetch resource.")); } const blob = resolveObjectURL(blobURLEntry.toString()); - if (request3.method !== "GET" || !isBlobLike(blob)) { + if (request3.method !== "GET" || !webidl.is.Blob(blob)) { return Promise.resolve(makeNetworkError("invalid method")); } const response = makeResponse(); @@ -14095,7 +21813,7 @@ var require_fetch = __commonJS({ rangeEnd = fullLength - 1; } } - const slicedBlob = blob.slice(rangeStart, rangeEnd, type); + const slicedBlob = blob.slice(rangeStart, rangeEnd + 1, type); const slicedBodyWithType = extractBody(slicedBlob); response.body = slicedBodyWithType[0]; const serializedSlicedLength = isomorphicEncode(`${slicedBlob.size}`); @@ -14149,7 +21867,7 @@ var require_fetch = __commonJS({ fetchParams.controller.fullTimingInfo = timingInfo; } fetchParams.controller.reportTimingSteps = () => { - if (fetchParams.request.url.protocol !== "https:") { + if (!urlIsHttpHttpsScheme(fetchParams.request.url)) { return; } timingInfo.endTime = unsafeEndTime; @@ -14160,7 +21878,7 @@ var require_fetch = __commonJS({ cacheState = ""; } let responseStatus = 0; - if (fetchParams.request.mode !== "navigator" || !response.hasCrossOriginRedirects) { + if (fetchParams.request.mode !== "navigate" || !response.hasCrossOriginRedirects) { responseStatus = response.status; const mimeType = extractMimeType(response.headersList); if (mimeType !== "failure") { @@ -14324,18 +22042,18 @@ var require_fetch = __commonJS({ if (contentLength != null) { contentLengthHeaderValue = isomorphicEncode(`${contentLength}`); } - if (contentLengthHeaderValue != null) { + if (contentLengthHeaderValue != null && !httpRequest.headersList.contains("content-length", true)) { httpRequest.headersList.append("content-length", contentLengthHeaderValue, true); } if (contentLength != null && httpRequest.keepalive) { } - if (httpRequest.referrer instanceof URL) { + if (webidl.is.URL(httpRequest.referrer)) { httpRequest.headersList.append("referer", isomorphicEncode(httpRequest.referrer.href), true); } appendRequestOriginHeader(httpRequest); appendFetchMetadata(httpRequest); if (!httpRequest.headersList.contains("user-agent", true)) { - httpRequest.headersList.append("user-agent", defaultUserAgent); + httpRequest.headersList.append("user-agent", defaultUserAgent, true); } if (httpRequest.cache === "default" && (httpRequest.headersList.contains("if-modified-since", true) || httpRequest.headersList.contains("if-none-match", true) || httpRequest.headersList.contains("if-unmodified-since", true) || httpRequest.headersList.contains("if-match", true) || httpRequest.headersList.contains("if-range", true))) { httpRequest.cache = "no-store"; @@ -14363,6 +22081,17 @@ var require_fetch = __commonJS({ } httpRequest.headersList.delete("host", true); if (includeCredentials) { + if (!httpRequest.headersList.contains("authorization", true)) { + let authorizationValue = null; + if (hasAuthenticationEntry(httpRequest) && (httpRequest.useURLCredentials === void 0 || !includesCredentials(requestCurrentURL(httpRequest)))) { + } else if (includesCredentials(requestCurrentURL(httpRequest)) && isAuthenticationFetch) { + const { username, password } = requestCurrentURL(httpRequest); + authorizationValue = `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`; + } + if (authorizationValue !== null) { + httpRequest.headersList.append("Authorization", authorizationValue, false); + } + } } if (httpCache == null) { httpRequest.cache = "no-store"; @@ -14391,6 +22120,22 @@ var require_fetch = __commonJS({ response.rangeRequested = true; } response.requestIncludesCredentials = includeCredentials; + if (response.status === 401 && httpRequest.responseTainting !== "cors" && includeCredentials && (request3.useURLCredentials !== void 0 || isTraversableNavigable(request3.traversableForUserPrompts))) { + if (request3.body != null) { + if (request3.body.source == null) { + return response; + } + request3.body = safelyExtractBody(request3.body.source)[0]; + } + if (request3.useURLCredentials === void 0 || isAuthenticationFetch) { + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams); + } + return response; + } + fetchParams.controller.connection.destroy(); + response = await httpNetworkOrCacheFetch(fetchParams, true); + } if (response.status === 407) { if (request3.window === "no-window") { return makeNetworkError(); @@ -14501,8 +22246,8 @@ var require_fetch = __commonJS({ } return makeNetworkError(err); } - const pullAlgorithm = async () => { - await fetchParams.controller.resume(); + const pullAlgorithm = () => { + return fetchParams.controller.resume(); }; const cancelAlgorithm = (reason) => { if (!isCancelled(fetchParams)) { @@ -14511,21 +22256,18 @@ var require_fetch = __commonJS({ }; const stream2 = new ReadableStream( { - async start(controller) { + start(controller) { fetchParams.controller.controller = controller; }, - async pull(controller) { - await pullAlgorithm(controller); - }, - async cancel(reason) { - await cancelAlgorithm(reason); - }, + pull: pullAlgorithm, + cancel: cancelAlgorithm, type: "bytes" } ); response.body = { stream: stream2, source: null, length: null }; - fetchParams.controller.onAborted = onAborted; - fetchParams.controller.on("terminated", onAborted); + if (!fetchParams.controller.resume) { + fetchParams.controller.on("terminated", onAborted); + } fetchParams.controller.resume = async () => { while (true) { let bytes; @@ -14588,9 +22330,11 @@ var require_fetch = __commonJS({ function dispatch({ body }) { const url2 = requestCurrentURL(request3); const agent = fetchParams.controller.dispatcher; + const path30 = url2.pathname + url2.search; + const hasTrailingQuestionMark = url2.search.length === 0 && url2.href[url2.href.length - url2.hash.length - 1] === "?"; return new Promise((resolve15, reject) => agent.dispatch( { - path: url2.pathname + url2.search, + path: hasTrailingQuestionMark ? `${path30}?` : path30, origin: url2.origin, method: request3.method, body: agent.isMockActive ? request3.body && (request3.body.source || request3.body.stream) : body, @@ -14617,23 +22361,29 @@ var require_fetch = __commonJS({ }, onHeaders(status, rawHeaders, resume, statusText) { if (status < 200) { - return; + return false; } - let location = ""; const headersList = new HeadersList(); for (let i = 0; i < rawHeaders.length; i += 2) { - headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString("latin1"), true); + const nameStr = bufferToLowerCasedHeaderName(rawHeaders[i]); + const value = rawHeaders[i + 1]; + if (Array.isArray(value) && !Buffer.isBuffer(rawHeaders[i + 1])) { + for (const val of value) { + headersList.append(nameStr, val.toString("latin1"), true); + } + } else { + headersList.append(nameStr, value.toString("latin1"), true); + } } - location = headersList.get("location", true); - this.body = new Readable4({ read: resume }); - const decoders = []; + const location = headersList.get("location", true); const willFollow = location && request3.redirect === "follow" && redirectStatusSet.has(status); + const decoders = []; if (request3.method !== "HEAD" && request3.method !== "CONNECT" && !nullBodyStatus.includes(status) && !willFollow) { const contentEncoding = headersList.get("content-encoding", true); const codings = contentEncoding ? contentEncoding.toLowerCase().split(",") : []; const maxContentEncodings = 5; if (codings.length > maxContentEncodings) { - reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); + this.abort(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); return true; } for (let i = codings.length - 1; i >= 0; --i) { @@ -14657,12 +22407,18 @@ var require_fetch = __commonJS({ flush: zlib3.constants.BROTLI_OPERATION_FLUSH, finishFlush: zlib3.constants.BROTLI_OPERATION_FLUSH })); + } else if (coding === "zstd" && hasZstd) { + decoders.push(zlib3.createZstdDecompress({ + flush: zlib3.constants.ZSTD_e_continue, + finishFlush: zlib3.constants.ZSTD_e_end + })); } else { decoders.length = 0; break; } } } + this.body = new Readable4({ read: resume }); const onError = this.onError.bind(this); resolve15({ status, @@ -14688,9 +22444,6 @@ var require_fetch = __commonJS({ if (this.abort) { fetchParams.controller.off("terminated", this.abort); } - if (fetchParams.controller.onAborted) { - fetchParams.controller.off("terminated", fetchParams.controller.onAborted); - } fetchParams.controller.ended = true; this.body.push(null); }, @@ -14702,13 +22455,47 @@ var require_fetch = __commonJS({ fetchParams.controller.terminate(error3); reject(error3); }, + onRequestUpgrade(_controller, status, headers, socket) { + if (socket.session != null && status !== 200 || socket.session == null && status !== 101) { + return false; + } + const headersList = new HeadersList(); + for (const [name, value] of Object.entries(headers)) { + if (value == null) { + continue; + } + const headerName = name.toLowerCase(); + if (Array.isArray(value)) { + for (const entry of value) { + headersList.append(headerName, String(entry), true); + } + } else { + headersList.append(headerName, String(value), true); + } + } + resolve15({ + status, + statusText: STATUS_CODES[status], + headersList, + socket + }); + return true; + }, onUpgrade(status, rawHeaders, socket) { - if (status !== 101) { - return; + if (socket.session != null && status !== 200 || socket.session == null && status !== 101) { + return false; } const headersList = new HeadersList(); for (let i = 0; i < rawHeaders.length; i += 2) { - headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString("latin1"), true); + const nameStr = bufferToLowerCasedHeaderName(rawHeaders[i]); + const value = rawHeaders[i + 1]; + if (Array.isArray(value) && !Buffer.isBuffer(rawHeaders[i + 1])) { + for (const val of value) { + headersList.append(nameStr, val.toString("latin1"), true); + } + } else { + headersList.append(nameStr, value.toString("latin1"), true); + } } resolve15({ status, @@ -14731,831 +22518,8 @@ var require_fetch = __commonJS({ } }); -// node_modules/undici/lib/web/fileapi/symbols.js -var require_symbols3 = __commonJS({ - "node_modules/undici/lib/web/fileapi/symbols.js"(exports2, module2) { - "use strict"; - module2.exports = { - kState: /* @__PURE__ */ Symbol("FileReader state"), - kResult: /* @__PURE__ */ Symbol("FileReader result"), - kError: /* @__PURE__ */ Symbol("FileReader error"), - kLastProgressEventFired: /* @__PURE__ */ Symbol("FileReader last progress event fired timestamp"), - kEvents: /* @__PURE__ */ Symbol("FileReader events"), - kAborted: /* @__PURE__ */ Symbol("FileReader aborted") - }; - } -}); - -// node_modules/undici/lib/web/fileapi/progressevent.js -var require_progressevent = __commonJS({ - "node_modules/undici/lib/web/fileapi/progressevent.js"(exports2, module2) { - "use strict"; - var { webidl } = require_webidl(); - var kState = /* @__PURE__ */ Symbol("ProgressEvent state"); - var ProgressEvent = class _ProgressEvent extends Event { - constructor(type, eventInitDict = {}) { - type = webidl.converters.DOMString(type, "ProgressEvent constructor", "type"); - eventInitDict = webidl.converters.ProgressEventInit(eventInitDict ?? {}); - super(type, eventInitDict); - this[kState] = { - lengthComputable: eventInitDict.lengthComputable, - loaded: eventInitDict.loaded, - total: eventInitDict.total - }; - } - get lengthComputable() { - webidl.brandCheck(this, _ProgressEvent); - return this[kState].lengthComputable; - } - get loaded() { - webidl.brandCheck(this, _ProgressEvent); - return this[kState].loaded; - } - get total() { - webidl.brandCheck(this, _ProgressEvent); - return this[kState].total; - } - }; - webidl.converters.ProgressEventInit = webidl.dictionaryConverter([ - { - key: "lengthComputable", - converter: webidl.converters.boolean, - defaultValue: () => false - }, - { - key: "loaded", - converter: webidl.converters["unsigned long long"], - defaultValue: () => 0 - }, - { - key: "total", - converter: webidl.converters["unsigned long long"], - defaultValue: () => 0 - }, - { - key: "bubbles", - converter: webidl.converters.boolean, - defaultValue: () => false - }, - { - key: "cancelable", - converter: webidl.converters.boolean, - defaultValue: () => false - }, - { - key: "composed", - converter: webidl.converters.boolean, - defaultValue: () => false - } - ]); - module2.exports = { - ProgressEvent - }; - } -}); - -// node_modules/undici/lib/web/fileapi/encoding.js -var require_encoding = __commonJS({ - "node_modules/undici/lib/web/fileapi/encoding.js"(exports2, module2) { - "use strict"; - function getEncoding(label) { - if (!label) { - return "failure"; - } - switch (label.trim().toLowerCase()) { - case "unicode-1-1-utf-8": - case "unicode11utf8": - case "unicode20utf8": - case "utf-8": - case "utf8": - case "x-unicode20utf8": - return "UTF-8"; - case "866": - case "cp866": - case "csibm866": - case "ibm866": - return "IBM866"; - case "csisolatin2": - case "iso-8859-2": - case "iso-ir-101": - case "iso8859-2": - case "iso88592": - case "iso_8859-2": - case "iso_8859-2:1987": - case "l2": - case "latin2": - return "ISO-8859-2"; - case "csisolatin3": - case "iso-8859-3": - case "iso-ir-109": - case "iso8859-3": - case "iso88593": - case "iso_8859-3": - case "iso_8859-3:1988": - case "l3": - case "latin3": - return "ISO-8859-3"; - case "csisolatin4": - case "iso-8859-4": - case "iso-ir-110": - case "iso8859-4": - case "iso88594": - case "iso_8859-4": - case "iso_8859-4:1988": - case "l4": - case "latin4": - return "ISO-8859-4"; - case "csisolatincyrillic": - case "cyrillic": - case "iso-8859-5": - case "iso-ir-144": - case "iso8859-5": - case "iso88595": - case "iso_8859-5": - case "iso_8859-5:1988": - return "ISO-8859-5"; - case "arabic": - case "asmo-708": - case "csiso88596e": - case "csiso88596i": - case "csisolatinarabic": - case "ecma-114": - case "iso-8859-6": - case "iso-8859-6-e": - case "iso-8859-6-i": - case "iso-ir-127": - case "iso8859-6": - case "iso88596": - case "iso_8859-6": - case "iso_8859-6:1987": - return "ISO-8859-6"; - case "csisolatingreek": - case "ecma-118": - case "elot_928": - case "greek": - case "greek8": - case "iso-8859-7": - case "iso-ir-126": - case "iso8859-7": - case "iso88597": - case "iso_8859-7": - case "iso_8859-7:1987": - case "sun_eu_greek": - return "ISO-8859-7"; - case "csiso88598e": - case "csisolatinhebrew": - case "hebrew": - case "iso-8859-8": - case "iso-8859-8-e": - case "iso-ir-138": - case "iso8859-8": - case "iso88598": - case "iso_8859-8": - case "iso_8859-8:1988": - case "visual": - return "ISO-8859-8"; - case "csiso88598i": - case "iso-8859-8-i": - case "logical": - return "ISO-8859-8-I"; - case "csisolatin6": - case "iso-8859-10": - case "iso-ir-157": - case "iso8859-10": - case "iso885910": - case "l6": - case "latin6": - return "ISO-8859-10"; - case "iso-8859-13": - case "iso8859-13": - case "iso885913": - return "ISO-8859-13"; - case "iso-8859-14": - case "iso8859-14": - case "iso885914": - return "ISO-8859-14"; - case "csisolatin9": - case "iso-8859-15": - case "iso8859-15": - case "iso885915": - case "iso_8859-15": - case "l9": - return "ISO-8859-15"; - case "iso-8859-16": - return "ISO-8859-16"; - case "cskoi8r": - case "koi": - case "koi8": - case "koi8-r": - case "koi8_r": - return "KOI8-R"; - case "koi8-ru": - case "koi8-u": - return "KOI8-U"; - case "csmacintosh": - case "mac": - case "macintosh": - case "x-mac-roman": - return "macintosh"; - case "iso-8859-11": - case "iso8859-11": - case "iso885911": - case "tis-620": - case "windows-874": - return "windows-874"; - case "cp1250": - case "windows-1250": - case "x-cp1250": - return "windows-1250"; - case "cp1251": - case "windows-1251": - case "x-cp1251": - return "windows-1251"; - case "ansi_x3.4-1968": - case "ascii": - case "cp1252": - case "cp819": - case "csisolatin1": - case "ibm819": - case "iso-8859-1": - case "iso-ir-100": - case "iso8859-1": - case "iso88591": - case "iso_8859-1": - case "iso_8859-1:1987": - case "l1": - case "latin1": - case "us-ascii": - case "windows-1252": - case "x-cp1252": - return "windows-1252"; - case "cp1253": - case "windows-1253": - case "x-cp1253": - return "windows-1253"; - case "cp1254": - case "csisolatin5": - case "iso-8859-9": - case "iso-ir-148": - case "iso8859-9": - case "iso88599": - case "iso_8859-9": - case "iso_8859-9:1989": - case "l5": - case "latin5": - case "windows-1254": - case "x-cp1254": - return "windows-1254"; - case "cp1255": - case "windows-1255": - case "x-cp1255": - return "windows-1255"; - case "cp1256": - case "windows-1256": - case "x-cp1256": - return "windows-1256"; - case "cp1257": - case "windows-1257": - case "x-cp1257": - return "windows-1257"; - case "cp1258": - case "windows-1258": - case "x-cp1258": - return "windows-1258"; - case "x-mac-cyrillic": - case "x-mac-ukrainian": - return "x-mac-cyrillic"; - case "chinese": - case "csgb2312": - case "csiso58gb231280": - case "gb2312": - case "gb_2312": - case "gb_2312-80": - case "gbk": - case "iso-ir-58": - case "x-gbk": - return "GBK"; - case "gb18030": - return "gb18030"; - case "big5": - case "big5-hkscs": - case "cn-big5": - case "csbig5": - case "x-x-big5": - return "Big5"; - case "cseucpkdfmtjapanese": - case "euc-jp": - case "x-euc-jp": - return "EUC-JP"; - case "csiso2022jp": - case "iso-2022-jp": - return "ISO-2022-JP"; - case "csshiftjis": - case "ms932": - case "ms_kanji": - case "shift-jis": - case "shift_jis": - case "sjis": - case "windows-31j": - case "x-sjis": - return "Shift_JIS"; - case "cseuckr": - case "csksc56011987": - case "euc-kr": - case "iso-ir-149": - case "korean": - case "ks_c_5601-1987": - case "ks_c_5601-1989": - case "ksc5601": - case "ksc_5601": - case "windows-949": - return "EUC-KR"; - case "csiso2022kr": - case "hz-gb-2312": - case "iso-2022-cn": - case "iso-2022-cn-ext": - case "iso-2022-kr": - case "replacement": - return "replacement"; - case "unicodefffe": - case "utf-16be": - return "UTF-16BE"; - case "csunicode": - case "iso-10646-ucs-2": - case "ucs-2": - case "unicode": - case "unicodefeff": - case "utf-16": - case "utf-16le": - return "UTF-16LE"; - case "x-user-defined": - return "x-user-defined"; - default: - return "failure"; - } - } - module2.exports = { - getEncoding - }; - } -}); - -// node_modules/undici/lib/web/fileapi/util.js -var require_util4 = __commonJS({ - "node_modules/undici/lib/web/fileapi/util.js"(exports2, module2) { - "use strict"; - var { - kState, - kError, - kResult, - kAborted, - kLastProgressEventFired - } = require_symbols3(); - var { ProgressEvent } = require_progressevent(); - var { getEncoding } = require_encoding(); - var { serializeAMimeType, parseMIMEType } = require_data_url(); - var { types: types2 } = require("node:util"); - var { StringDecoder } = require("string_decoder"); - var { btoa: btoa2 } = require("node:buffer"); - var staticPropertyDescriptors = { - enumerable: true, - writable: false, - configurable: false - }; - function readOperation(fr, blob, type, encodingName) { - if (fr[kState] === "loading") { - throw new DOMException("Invalid state", "InvalidStateError"); - } - fr[kState] = "loading"; - fr[kResult] = null; - fr[kError] = null; - const stream2 = blob.stream(); - const reader = stream2.getReader(); - const bytes = []; - let chunkPromise = reader.read(); - let isFirstChunk = true; - (async () => { - while (!fr[kAborted]) { - try { - const { done, value } = await chunkPromise; - if (isFirstChunk && !fr[kAborted]) { - queueMicrotask(() => { - fireAProgressEvent("loadstart", fr); - }); - } - isFirstChunk = false; - if (!done && types2.isUint8Array(value)) { - bytes.push(value); - if ((fr[kLastProgressEventFired] === void 0 || Date.now() - fr[kLastProgressEventFired] >= 50) && !fr[kAborted]) { - fr[kLastProgressEventFired] = Date.now(); - queueMicrotask(() => { - fireAProgressEvent("progress", fr); - }); - } - chunkPromise = reader.read(); - } else if (done) { - queueMicrotask(() => { - fr[kState] = "done"; - try { - const result = packageData(bytes, type, blob.type, encodingName); - if (fr[kAborted]) { - return; - } - fr[kResult] = result; - fireAProgressEvent("load", fr); - } catch (error3) { - fr[kError] = error3; - fireAProgressEvent("error", fr); - } - if (fr[kState] !== "loading") { - fireAProgressEvent("loadend", fr); - } - }); - break; - } - } catch (error3) { - if (fr[kAborted]) { - return; - } - queueMicrotask(() => { - fr[kState] = "done"; - fr[kError] = error3; - fireAProgressEvent("error", fr); - if (fr[kState] !== "loading") { - fireAProgressEvent("loadend", fr); - } - }); - break; - } - } - })(); - } - function fireAProgressEvent(e, reader) { - const event = new ProgressEvent(e, { - bubbles: false, - cancelable: false - }); - reader.dispatchEvent(event); - } - function packageData(bytes, type, mimeType, encodingName) { - switch (type) { - case "DataURL": { - let dataURL = "data:"; - const parsed = parseMIMEType(mimeType || "application/octet-stream"); - if (parsed !== "failure") { - dataURL += serializeAMimeType(parsed); - } - dataURL += ";base64,"; - const decoder2 = new StringDecoder("latin1"); - for (const chunk of bytes) { - dataURL += btoa2(decoder2.write(chunk)); - } - dataURL += btoa2(decoder2.end()); - return dataURL; - } - case "Text": { - let encoding = "failure"; - if (encodingName) { - encoding = getEncoding(encodingName); - } - if (encoding === "failure" && mimeType) { - const type2 = parseMIMEType(mimeType); - if (type2 !== "failure") { - encoding = getEncoding(type2.parameters.get("charset")); - } - } - if (encoding === "failure") { - encoding = "UTF-8"; - } - return decode(bytes, encoding); - } - case "ArrayBuffer": { - const sequence = combineByteSequences(bytes); - return sequence.buffer; - } - case "BinaryString": { - let binaryString = ""; - const decoder2 = new StringDecoder("latin1"); - for (const chunk of bytes) { - binaryString += decoder2.write(chunk); - } - binaryString += decoder2.end(); - return binaryString; - } - } - } - function decode(ioQueue, encoding) { - const bytes = combineByteSequences(ioQueue); - const BOMEncoding = BOMSniffing(bytes); - let slice = 0; - if (BOMEncoding !== null) { - encoding = BOMEncoding; - slice = BOMEncoding === "UTF-8" ? 3 : 2; - } - const sliced = bytes.slice(slice); - return new TextDecoder(encoding).decode(sliced); - } - function BOMSniffing(ioQueue) { - const [a, b, c] = ioQueue; - if (a === 239 && b === 187 && c === 191) { - return "UTF-8"; - } else if (a === 254 && b === 255) { - return "UTF-16BE"; - } else if (a === 255 && b === 254) { - return "UTF-16LE"; - } - return null; - } - function combineByteSequences(sequences) { - const size = sequences.reduce((a, b) => { - return a + b.byteLength; - }, 0); - let offset = 0; - return sequences.reduce((a, b) => { - a.set(b, offset); - offset += b.byteLength; - return a; - }, new Uint8Array(size)); - } - module2.exports = { - staticPropertyDescriptors, - readOperation, - fireAProgressEvent - }; - } -}); - -// node_modules/undici/lib/web/fileapi/filereader.js -var require_filereader = __commonJS({ - "node_modules/undici/lib/web/fileapi/filereader.js"(exports2, module2) { - "use strict"; - var { - staticPropertyDescriptors, - readOperation, - fireAProgressEvent - } = require_util4(); - var { - kState, - kError, - kResult, - kEvents, - kAborted - } = require_symbols3(); - var { webidl } = require_webidl(); - var { kEnumerableProperty } = require_util(); - var FileReader = class _FileReader extends EventTarget { - constructor() { - super(); - this[kState] = "empty"; - this[kResult] = null; - this[kError] = null; - this[kEvents] = { - loadend: null, - error: null, - abort: null, - load: null, - progress: null, - loadstart: null - }; - } - /** - * @see https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer - * @param {import('buffer').Blob} blob - */ - readAsArrayBuffer(blob) { - webidl.brandCheck(this, _FileReader); - webidl.argumentLengthCheck(arguments, 1, "FileReader.readAsArrayBuffer"); - blob = webidl.converters.Blob(blob, { strict: false }); - readOperation(this, blob, "ArrayBuffer"); - } - /** - * @see https://w3c.github.io/FileAPI/#readAsBinaryString - * @param {import('buffer').Blob} blob - */ - readAsBinaryString(blob) { - webidl.brandCheck(this, _FileReader); - webidl.argumentLengthCheck(arguments, 1, "FileReader.readAsBinaryString"); - blob = webidl.converters.Blob(blob, { strict: false }); - readOperation(this, blob, "BinaryString"); - } - /** - * @see https://w3c.github.io/FileAPI/#readAsDataText - * @param {import('buffer').Blob} blob - * @param {string?} encoding - */ - readAsText(blob, encoding = void 0) { - webidl.brandCheck(this, _FileReader); - webidl.argumentLengthCheck(arguments, 1, "FileReader.readAsText"); - blob = webidl.converters.Blob(blob, { strict: false }); - if (encoding !== void 0) { - encoding = webidl.converters.DOMString(encoding, "FileReader.readAsText", "encoding"); - } - readOperation(this, blob, "Text", encoding); - } - /** - * @see https://w3c.github.io/FileAPI/#dfn-readAsDataURL - * @param {import('buffer').Blob} blob - */ - readAsDataURL(blob) { - webidl.brandCheck(this, _FileReader); - webidl.argumentLengthCheck(arguments, 1, "FileReader.readAsDataURL"); - blob = webidl.converters.Blob(blob, { strict: false }); - readOperation(this, blob, "DataURL"); - } - /** - * @see https://w3c.github.io/FileAPI/#dfn-abort - */ - abort() { - if (this[kState] === "empty" || this[kState] === "done") { - this[kResult] = null; - return; - } - if (this[kState] === "loading") { - this[kState] = "done"; - this[kResult] = null; - } - this[kAborted] = true; - fireAProgressEvent("abort", this); - if (this[kState] !== "loading") { - fireAProgressEvent("loadend", this); - } - } - /** - * @see https://w3c.github.io/FileAPI/#dom-filereader-readystate - */ - get readyState() { - webidl.brandCheck(this, _FileReader); - switch (this[kState]) { - case "empty": - return this.EMPTY; - case "loading": - return this.LOADING; - case "done": - return this.DONE; - } - } - /** - * @see https://w3c.github.io/FileAPI/#dom-filereader-result - */ - get result() { - webidl.brandCheck(this, _FileReader); - return this[kResult]; - } - /** - * @see https://w3c.github.io/FileAPI/#dom-filereader-error - */ - get error() { - webidl.brandCheck(this, _FileReader); - return this[kError]; - } - get onloadend() { - webidl.brandCheck(this, _FileReader); - return this[kEvents].loadend; - } - set onloadend(fn) { - webidl.brandCheck(this, _FileReader); - if (this[kEvents].loadend) { - this.removeEventListener("loadend", this[kEvents].loadend); - } - if (typeof fn === "function") { - this[kEvents].loadend = fn; - this.addEventListener("loadend", fn); - } else { - this[kEvents].loadend = null; - } - } - get onerror() { - webidl.brandCheck(this, _FileReader); - return this[kEvents].error; - } - set onerror(fn) { - webidl.brandCheck(this, _FileReader); - if (this[kEvents].error) { - this.removeEventListener("error", this[kEvents].error); - } - if (typeof fn === "function") { - this[kEvents].error = fn; - this.addEventListener("error", fn); - } else { - this[kEvents].error = null; - } - } - get onloadstart() { - webidl.brandCheck(this, _FileReader); - return this[kEvents].loadstart; - } - set onloadstart(fn) { - webidl.brandCheck(this, _FileReader); - if (this[kEvents].loadstart) { - this.removeEventListener("loadstart", this[kEvents].loadstart); - } - if (typeof fn === "function") { - this[kEvents].loadstart = fn; - this.addEventListener("loadstart", fn); - } else { - this[kEvents].loadstart = null; - } - } - get onprogress() { - webidl.brandCheck(this, _FileReader); - return this[kEvents].progress; - } - set onprogress(fn) { - webidl.brandCheck(this, _FileReader); - if (this[kEvents].progress) { - this.removeEventListener("progress", this[kEvents].progress); - } - if (typeof fn === "function") { - this[kEvents].progress = fn; - this.addEventListener("progress", fn); - } else { - this[kEvents].progress = null; - } - } - get onload() { - webidl.brandCheck(this, _FileReader); - return this[kEvents].load; - } - set onload(fn) { - webidl.brandCheck(this, _FileReader); - if (this[kEvents].load) { - this.removeEventListener("load", this[kEvents].load); - } - if (typeof fn === "function") { - this[kEvents].load = fn; - this.addEventListener("load", fn); - } else { - this[kEvents].load = null; - } - } - get onabort() { - webidl.brandCheck(this, _FileReader); - return this[kEvents].abort; - } - set onabort(fn) { - webidl.brandCheck(this, _FileReader); - if (this[kEvents].abort) { - this.removeEventListener("abort", this[kEvents].abort); - } - if (typeof fn === "function") { - this[kEvents].abort = fn; - this.addEventListener("abort", fn); - } else { - this[kEvents].abort = null; - } - } - }; - FileReader.EMPTY = FileReader.prototype.EMPTY = 0; - FileReader.LOADING = FileReader.prototype.LOADING = 1; - FileReader.DONE = FileReader.prototype.DONE = 2; - Object.defineProperties(FileReader.prototype, { - EMPTY: staticPropertyDescriptors, - LOADING: staticPropertyDescriptors, - DONE: staticPropertyDescriptors, - readAsArrayBuffer: kEnumerableProperty, - readAsBinaryString: kEnumerableProperty, - readAsText: kEnumerableProperty, - readAsDataURL: kEnumerableProperty, - abort: kEnumerableProperty, - readyState: kEnumerableProperty, - result: kEnumerableProperty, - error: kEnumerableProperty, - onloadstart: kEnumerableProperty, - onprogress: kEnumerableProperty, - onload: kEnumerableProperty, - onabort: kEnumerableProperty, - onerror: kEnumerableProperty, - onloadend: kEnumerableProperty, - [Symbol.toStringTag]: { - value: "FileReader", - writable: false, - enumerable: false, - configurable: true - } - }); - Object.defineProperties(FileReader, { - EMPTY: staticPropertyDescriptors, - LOADING: staticPropertyDescriptors, - DONE: staticPropertyDescriptors - }); - module2.exports = { - FileReader - }; - } -}); - -// node_modules/undici/lib/web/cache/symbols.js -var require_symbols4 = __commonJS({ - "node_modules/undici/lib/web/cache/symbols.js"(exports2, module2) { - "use strict"; - module2.exports = { - kConstruct: require_symbols().kConstruct - }; - } -}); - // node_modules/undici/lib/web/cache/util.js -var require_util5 = __commonJS({ +var require_util3 = __commonJS({ "node_modules/undici/lib/web/cache/util.js"(exports2, module2) { "use strict"; var assert = require("node:assert"); @@ -15585,19 +22549,19 @@ var require_util5 = __commonJS({ }); // node_modules/undici/lib/web/cache/cache.js -var require_cache = __commonJS({ +var require_cache3 = __commonJS({ "node_modules/undici/lib/web/cache/cache.js"(exports2, module2) { "use strict"; - var { kConstruct } = require_symbols4(); - var { urlEquals, getFieldValues } = require_util5(); + var assert = require("node:assert"); + var { kConstruct } = require_symbols(); + var { urlEquals, getFieldValues } = require_util3(); var { kEnumerableProperty, isDisturbed } = require_util(); var { webidl } = require_webidl(); - var { Response: Response2, cloneResponse, fromInnerResponse } = require_response(); - var { Request, fromInnerRequest } = require_request2(); - var { kState } = require_symbols2(); + var { cloneResponse, fromInnerResponse, getResponseState } = require_response(); + var { Request, fromInnerRequest, getRequestState } = require_request2(); var { fetching } = require_fetch(); - var { urlIsHttpHttpsScheme, createDeferredPromise, readAllBytes } = require_util2(); - var assert = require("node:assert"); + var { urlIsHttpHttpsScheme, readAllBytes } = require_util2(); + var { createDeferredPromise } = require_promise(); var Cache = class _Cache { /** * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-request-response-list @@ -15615,7 +22579,7 @@ var require_cache = __commonJS({ webidl.brandCheck(this, _Cache); const prefix = "Cache.match"; webidl.argumentLengthCheck(arguments, 1, prefix); - request3 = webidl.converters.RequestInfo(request3, prefix, "request"); + request3 = webidl.converters.RequestInfo(request3); options = webidl.converters.CacheQueryOptions(options, prefix, "options"); const p = this.#internalMatchAll(request3, options, 1); if (p.length === 0) { @@ -15626,7 +22590,7 @@ var require_cache = __commonJS({ async matchAll(request3 = void 0, options = {}) { webidl.brandCheck(this, _Cache); const prefix = "Cache.matchAll"; - if (request3 !== void 0) request3 = webidl.converters.RequestInfo(request3, prefix, "request"); + if (request3 !== void 0) request3 = webidl.converters.RequestInfo(request3); options = webidl.converters.CacheQueryOptions(options, prefix, "options"); return this.#internalMatchAll(request3, options); } @@ -15634,7 +22598,7 @@ var require_cache = __commonJS({ webidl.brandCheck(this, _Cache); const prefix = "Cache.add"; webidl.argumentLengthCheck(arguments, 1, prefix); - request3 = webidl.converters.RequestInfo(request3, prefix, "request"); + request3 = webidl.converters.RequestInfo(request3); const requests = [request3]; const responseArrayPromise = this.addAll(requests); return await responseArrayPromise; @@ -15657,7 +22621,7 @@ var require_cache = __commonJS({ if (typeof request3 === "string") { continue; } - const r = request3[kState]; + const r = getRequestState(request3); if (!urlIsHttpHttpsScheme(r.url) || r.method !== "GET") { throw webidl.errors.exception({ header: prefix, @@ -15667,7 +22631,7 @@ var require_cache = __commonJS({ } const fetchControllers = []; for (const request3 of requests) { - const r = new Request(request3)[kState]; + const r = getRequestState(new Request(request3)); if (!urlIsHttpHttpsScheme(r.url)) { throw webidl.errors.exception({ header: prefix, @@ -15748,13 +22712,13 @@ var require_cache = __commonJS({ webidl.brandCheck(this, _Cache); const prefix = "Cache.put"; webidl.argumentLengthCheck(arguments, 2, prefix); - request3 = webidl.converters.RequestInfo(request3, prefix, "request"); + request3 = webidl.converters.RequestInfo(request3); response = webidl.converters.Response(response, prefix, "response"); let innerRequest = null; - if (request3 instanceof Request) { - innerRequest = request3[kState]; + if (webidl.is.Request(request3)) { + innerRequest = getRequestState(request3); } else { - innerRequest = new Request(request3)[kState]; + innerRequest = getRequestState(new Request(request3)); } if (!urlIsHttpHttpsScheme(innerRequest.url) || innerRequest.method !== "GET") { throw webidl.errors.exception({ @@ -15762,7 +22726,7 @@ var require_cache = __commonJS({ message: "Expected an http/s scheme when method is not GET" }); } - const innerResponse = response[kState]; + const innerResponse = getResponseState(response); if (innerResponse.status === 206) { throw webidl.errors.exception({ header: prefix, @@ -15791,7 +22755,7 @@ var require_cache = __commonJS({ if (innerResponse.body != null) { const stream2 = innerResponse.body.stream; const reader = stream2.getReader(); - readAllBytes(reader).then(bodyReadPromise.resolve, bodyReadPromise.reject); + readAllBytes(reader, bodyReadPromise.resolve, bodyReadPromise.reject); } else { bodyReadPromise.resolve(void 0); } @@ -15829,17 +22793,17 @@ var require_cache = __commonJS({ webidl.brandCheck(this, _Cache); const prefix = "Cache.delete"; webidl.argumentLengthCheck(arguments, 1, prefix); - request3 = webidl.converters.RequestInfo(request3, prefix, "request"); + request3 = webidl.converters.RequestInfo(request3); options = webidl.converters.CacheQueryOptions(options, prefix, "options"); let r = null; - if (request3 instanceof Request) { - r = request3[kState]; + if (webidl.is.Request(request3)) { + r = getRequestState(request3); if (r.method !== "GET" && !options.ignoreMethod) { return false; } } else { assert(typeof request3 === "string"); - r = new Request(request3)[kState]; + r = getRequestState(new Request(request3)); } const operations = []; const operation = { @@ -15868,23 +22832,23 @@ var require_cache = __commonJS({ /** * @see https://w3c.github.io/ServiceWorker/#dom-cache-keys * @param {any} request - * @param {import('../../types/cache').CacheQueryOptions} options + * @param {import('../../../types/cache').CacheQueryOptions} options * @returns {Promise} */ async keys(request3 = void 0, options = {}) { webidl.brandCheck(this, _Cache); const prefix = "Cache.keys"; - if (request3 !== void 0) request3 = webidl.converters.RequestInfo(request3, prefix, "request"); + if (request3 !== void 0) request3 = webidl.converters.RequestInfo(request3); options = webidl.converters.CacheQueryOptions(options, prefix, "options"); let r = null; if (request3 !== void 0) { - if (request3 instanceof Request) { - r = request3[kState]; + if (webidl.is.Request(request3)) { + r = getRequestState(request3); if (r.method !== "GET" && !options.ignoreMethod) { return []; } } else if (typeof request3 === "string") { - r = new Request(request3)[kState]; + r = getRequestState(new Request(request3)); } } const promise = createDeferredPromise(); @@ -15904,6 +22868,7 @@ var require_cache = __commonJS({ for (const request4 of requests) { const requestObject = fromInnerRequest( request4, + void 0, new AbortController().signal, "immutable" ); @@ -15998,7 +22963,7 @@ var require_cache = __commonJS({ /** * @see https://w3c.github.io/ServiceWorker/#query-cache * @param {any} requestQuery - * @param {import('../../types/cache').CacheQueryOptions} options + * @param {import('../../../types/cache').CacheQueryOptions} options * @param {requestResponseList} targetStorage * @returns {requestResponseList} */ @@ -16018,7 +22983,7 @@ var require_cache = __commonJS({ * @param {any} requestQuery * @param {any} request * @param {any | null} response - * @param {import('../../types/cache').CacheQueryOptions | undefined} options + * @param {import('../../../types/cache').CacheQueryOptions | undefined} options * @returns {boolean} */ #requestMatchesCachedItem(requestQuery, request3, response = null, options) { @@ -16050,13 +23015,13 @@ var require_cache = __commonJS({ #internalMatchAll(request3, options, maxResponses = Infinity) { let r = null; if (request3 !== void 0) { - if (request3 instanceof Request) { - r = request3[kState]; + if (webidl.is.Request(request3)) { + r = getRequestState(request3); if (r.method !== "GET" && !options.ignoreMethod) { return []; } } else if (typeof request3 === "string") { - r = new Request(request3)[kState]; + r = getRequestState(new Request(request3)); } } const responses = []; @@ -16072,8 +23037,8 @@ var require_cache = __commonJS({ } const responseList = []; for (const response of responses) { - const responseObject = fromInnerResponse(response, "immutable"); - responseList.push(responseObject.clone()); + const responseObject = fromInnerResponse(cloneResponse(response), "immutable"); + responseList.push(responseObject); if (responseList.length >= maxResponses) { break; } @@ -16119,7 +23084,10 @@ var require_cache = __commonJS({ converter: webidl.converters.DOMString } ]); - webidl.converters.Response = webidl.interfaceConverter(Response2); + webidl.converters.Response = webidl.interfaceConverter( + webidl.is.Response, + "Response" + ); webidl.converters["sequence"] = webidl.sequenceConverter( webidl.converters.RequestInfo ); @@ -16133,10 +23101,10 @@ var require_cache = __commonJS({ var require_cachestorage = __commonJS({ "node_modules/undici/lib/web/cache/cachestorage.js"(exports2, module2) { "use strict"; - var { kConstruct } = require_symbols4(); - var { Cache } = require_cache(); + var { Cache } = require_cache3(); var { webidl } = require_webidl(); var { kEnumerableProperty } = require_util(); + var { kConstruct } = require_symbols(); var CacheStorage = class _CacheStorage { /** * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-name-to-cache-map @@ -16253,7 +23221,7 @@ var require_constants4 = __commonJS({ }); // node_modules/undici/lib/web/cookies/util.js -var require_util6 = __commonJS({ +var require_util4 = __commonJS({ "node_modules/undici/lib/web/cookies/util.js"(exports2, module2) { "use strict"; function isCTLExcludingHtab(value) { @@ -16430,8 +23398,12 @@ var require_util6 = __commonJS({ validateCookiePath(cookie.path); out.push(`Path=${cookie.path}`); } - if (cookie.expires && cookie.expires.toString() !== "Invalid Date") { - out.push(`Expires=${toIMFDate(cookie.expires)}`); + if (cookie.expires != null) { + const expiresMs = cookie.expires instanceof Date ? cookie.expires.getTime() : cookie.expires; + const maxTimeValue = 864e13; + if (typeof expiresMs === "number" && Number.isFinite(expiresMs) && Math.abs(expiresMs) <= maxTimeValue) { + out.push(`Expires=${toIMFDate(cookie.expires)}`); + } } if (cookie.sameSite) { out.push(`SameSite=${cookie.sameSite}`); @@ -16464,9 +23436,9 @@ var require_util6 = __commonJS({ var require_parse = __commonJS({ "node_modules/undici/lib/web/cookies/parse.js"(exports2, module2) { "use strict"; + var { collectASequenceOfCodePointsFast } = require_infra(); var { maxNameValuePairSize, maxAttributeValueSize } = require_constants4(); - var { isCTLExcludingHtab } = require_util6(); - var { collectASequenceOfCodePointsFast } = require_data_url(); + var { isCTLExcludingHtab } = require_util4(); var assert = require("node:assert"); function parseSetCookie(header) { if (isCTLExcludingHtab(header)) { @@ -16506,88 +23478,89 @@ var require_parse = __commonJS({ }; } function parseUnparsedAttributes(unparsedAttributes, cookieAttributeList = {}) { - if (unparsedAttributes.length === 0) { - return cookieAttributeList; - } - assert(unparsedAttributes[0] === ";"); - unparsedAttributes = unparsedAttributes.slice(1); - let cookieAv = ""; - if (unparsedAttributes.includes(";")) { - cookieAv = collectASequenceOfCodePointsFast( - ";", - unparsedAttributes, - { position: 0 } - ); - unparsedAttributes = unparsedAttributes.slice(cookieAv.length); - } else { - cookieAv = unparsedAttributes; - unparsedAttributes = ""; - } - let attributeName = ""; - let attributeValue = ""; - if (cookieAv.includes("=")) { - const position = { position: 0 }; - attributeName = collectASequenceOfCodePointsFast( - "=", - cookieAv, - position - ); - attributeValue = cookieAv.slice(position.position + 1); - } else { - attributeName = cookieAv; - } - attributeName = attributeName.trim(); - attributeValue = attributeValue.trim(); - if (attributeValue.length > maxAttributeValueSize) { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); - } - const attributeNameLowercase = attributeName.toLowerCase(); - if (attributeNameLowercase === "expires") { - const expiryTime = new Date(attributeValue); - cookieAttributeList.expires = expiryTime; - } else if (attributeNameLowercase === "max-age") { - const charCode = attributeValue.charCodeAt(0); - if ((charCode < 48 || charCode > 57) && attributeValue[0] !== "-") { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); - } - if (!/^\d+$/.test(attributeValue)) { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); - } - const deltaSeconds = Number(attributeValue); - cookieAttributeList.maxAge = deltaSeconds; - } else if (attributeNameLowercase === "domain") { - let cookieDomain = attributeValue; - if (cookieDomain[0] === ".") { - cookieDomain = cookieDomain.slice(1); - } - cookieDomain = cookieDomain.toLowerCase(); - cookieAttributeList.domain = cookieDomain; - } else if (attributeNameLowercase === "path") { - let cookiePath = ""; - if (attributeValue.length === 0 || attributeValue[0] !== "/") { - cookiePath = "/"; + while (true) { + if (unparsedAttributes.length === 0) { + return cookieAttributeList; + } + assert(unparsedAttributes[0] === ";"); + unparsedAttributes = unparsedAttributes.slice(1); + let cookieAv = ""; + if (unparsedAttributes.includes(";")) { + cookieAv = collectASequenceOfCodePointsFast( + ";", + unparsedAttributes, + { position: 0 } + ); + unparsedAttributes = unparsedAttributes.slice(cookieAv.length); + } else { + cookieAv = unparsedAttributes; + unparsedAttributes = ""; + } + let attributeName = ""; + let attributeValue = ""; + if (cookieAv.includes("=")) { + const position = { position: 0 }; + attributeName = collectASequenceOfCodePointsFast( + "=", + cookieAv, + position + ); + attributeValue = cookieAv.slice(position.position + 1); } else { - cookiePath = attributeValue; - } - cookieAttributeList.path = cookiePath; - } else if (attributeNameLowercase === "secure") { - cookieAttributeList.secure = true; - } else if (attributeNameLowercase === "httponly") { - cookieAttributeList.httpOnly = true; - } else if (attributeNameLowercase === "samesite") { - const attributeValueLowercase = attributeValue.toLowerCase(); - if (attributeValueLowercase === "none") { - cookieAttributeList.sameSite = "None"; - } else if (attributeValueLowercase === "strict") { - cookieAttributeList.sameSite = "Strict"; - } else if (attributeValueLowercase === "lax") { - cookieAttributeList.sameSite = "Lax"; + attributeName = cookieAv; + } + attributeName = attributeName.trim(); + attributeValue = attributeValue.trim(); + if (attributeValue.length > maxAttributeValueSize) { + continue; + } + const attributeNameLowercase = attributeName.toLowerCase(); + if (attributeNameLowercase === "expires") { + const expiryTime = new Date(attributeValue); + cookieAttributeList.expires = expiryTime; + } else if (attributeNameLowercase === "max-age") { + const charCode = attributeValue.charCodeAt(0); + if ((charCode < 48 || charCode > 57) && attributeValue[0] !== "-") { + continue; + } + if (!/^\d+$/.test(attributeValue)) { + continue; + } + const deltaSeconds = Number(attributeValue); + cookieAttributeList.maxAge = deltaSeconds; + } else if (attributeNameLowercase === "domain") { + let cookieDomain = attributeValue; + if (cookieDomain[0] === ".") { + cookieDomain = cookieDomain.slice(1); + } + cookieDomain = cookieDomain.toLowerCase(); + cookieAttributeList.domain = cookieDomain; + } else if (attributeNameLowercase === "path") { + let cookiePath = ""; + if (attributeValue.length === 0 || attributeValue[0] !== "/") { + cookiePath = "/"; + } else { + cookiePath = attributeValue; + } + cookieAttributeList.path = cookiePath; + } else if (attributeNameLowercase === "secure") { + cookieAttributeList.secure = true; + } else if (attributeNameLowercase === "httponly") { + cookieAttributeList.httpOnly = true; + } else if (attributeNameLowercase === "samesite") { + const attributeValueLowercase = attributeValue.toLowerCase(); + if (attributeValueLowercase === "none") { + cookieAttributeList.sameSite = "None"; + } else if (attributeValueLowercase === "strict") { + cookieAttributeList.sameSite = "Strict"; + } else if (attributeValueLowercase === "lax") { + cookieAttributeList.sameSite = "Lax"; + } + } else { + cookieAttributeList.unparsed ??= []; + cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`); } - } else { - cookieAttributeList.unparsed ??= []; - cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`); } - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); } module2.exports = { parseSetCookie, @@ -16601,14 +23574,15 @@ var require_cookies = __commonJS({ "node_modules/undici/lib/web/cookies/index.js"(exports2, module2) { "use strict"; var { parseSetCookie } = require_parse(); - var { stringify } = require_util6(); + var { stringify } = require_util4(); var { webidl } = require_webidl(); var { Headers } = require_headers(); + var brandChecks = webidl.brandCheckMultiple([Headers, globalThis.Headers].filter(Boolean)); function getCookies(headers) { webidl.argumentLengthCheck(arguments, 1, "getCookies"); - webidl.brandCheck(headers, Headers, { strict: false }); + brandChecks(headers); const cookie = headers.get("cookie"); - const out = {}; + const out = { __proto__: null }; if (!cookie) { return out; } @@ -16619,7 +23593,7 @@ var require_cookies = __commonJS({ return out; } function deleteCookie(headers, name, attributes) { - webidl.brandCheck(headers, Headers, { strict: false }); + brandChecks(headers); const prefix = "deleteCookie"; webidl.argumentLengthCheck(arguments, 2, prefix); name = webidl.converters.DOMString(name, prefix, "name"); @@ -16633,20 +23607,24 @@ var require_cookies = __commonJS({ } function getSetCookies(headers) { webidl.argumentLengthCheck(arguments, 1, "getSetCookies"); - webidl.brandCheck(headers, Headers, { strict: false }); + brandChecks(headers); const cookies = headers.getSetCookie(); if (!cookies) { return []; } return cookies.map((pair) => parseSetCookie(pair)); } + function parseCookie(cookie) { + cookie = webidl.converters.DOMString(cookie); + return parseSetCookie(cookie); + } function setCookie(headers, cookie) { webidl.argumentLengthCheck(arguments, 2, "setCookie"); - webidl.brandCheck(headers, Headers, { strict: false }); + brandChecks(headers); cookie = webidl.converters.Cookie(cookie); const str = stringify(cookie); if (str) { - headers.append("Set-Cookie", str); + headers.append("set-cookie", str, true); } } webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([ @@ -16713,14 +23691,15 @@ var require_cookies = __commonJS({ { converter: webidl.sequenceConverter(webidl.converters.DOMString), key: "unparsed", - defaultValue: () => new Array(0) + defaultValue: () => [] } ]); module2.exports = { getCookies, deleteCookie, getSetCookies, - setCookie + setCookie, + parseCookie }; } }); @@ -16732,7 +23711,6 @@ var require_events = __commonJS({ var { webidl } = require_webidl(); var { kEnumerableProperty } = require_util(); var { kConstruct } = require_symbols(); - var { MessagePort } = require("node:worker_threads"); var MessageEvent = class _MessageEvent extends Event { #eventInit; constructor(type, eventInitDict = {}) { @@ -16886,7 +23864,10 @@ var require_events = __commonJS({ colno: kEnumerableProperty, error: kEnumerableProperty }); - webidl.converters.MessagePort = webidl.interfaceConverter(MessagePort); + webidl.converters.MessagePort = webidl.interfaceConverter( + webidl.is.MessagePort, + "MessagePort" + ); webidl.converters["sequence"] = webidl.sequenceConverter( webidl.converters.MessagePort ); @@ -16934,7 +23915,7 @@ var require_events = __commonJS({ { key: "ports", converter: webidl.converters["sequence"], - defaultValue: () => new Array(0) + defaultValue: () => [] } ]); webidl.converters.CloseEventInit = webidl.dictionaryConverter([ @@ -17008,9 +23989,8 @@ var require_constants5 = __commonJS({ CLOSED: 3 }; var sentCloseFrameState = { - NOT_SENT: 0, - PROCESSING: 1, - SENT: 2 + SENT: 1, + RECEIVED: 2 }; var opcodes = { CONTINUATION: 0, @@ -17020,7 +24000,7 @@ var require_constants5 = __commonJS({ PING: 9, PONG: 10 }; - var maxUnsigned16Bit = 2 ** 16 - 1; + var maxUnsigned16Bit = 65535; var parserStates = { INFO: 0, PAYLOADLENGTH_16: 2, @@ -17029,7 +24009,7 @@ var require_constants5 = __commonJS({ }; var emptyBuffer = Buffer.allocUnsafe(0); var sendHints = { - string: 1, + text: 1, typedArray: 2, arrayBuffer: 3, blob: 4 @@ -17048,77 +24028,38 @@ var require_constants5 = __commonJS({ } }); -// node_modules/undici/lib/web/websocket/symbols.js -var require_symbols5 = __commonJS({ - "node_modules/undici/lib/web/websocket/symbols.js"(exports2, module2) { - "use strict"; - module2.exports = { - kWebSocketURL: /* @__PURE__ */ Symbol("url"), - kReadyState: /* @__PURE__ */ Symbol("ready state"), - kController: /* @__PURE__ */ Symbol("controller"), - kResponse: /* @__PURE__ */ Symbol("response"), - kBinaryType: /* @__PURE__ */ Symbol("binary type"), - kSentClose: /* @__PURE__ */ Symbol("sent close"), - kReceivedClose: /* @__PURE__ */ Symbol("received close"), - kByteParser: /* @__PURE__ */ Symbol("byte parser") - }; - } -}); - // node_modules/undici/lib/web/websocket/util.js -var require_util7 = __commonJS({ +var require_util5 = __commonJS({ "node_modules/undici/lib/web/websocket/util.js"(exports2, module2) { "use strict"; - var { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL } = require_symbols5(); var { states, opcodes } = require_constants5(); - var { ErrorEvent, createFastMessageEvent } = require_events(); var { isUtf8 } = require("node:buffer"); - var { collectASequenceOfCodePointsFast, removeHTTPWhitespace } = require_data_url(); - function isConnecting(ws) { - return ws[kReadyState] === states.CONNECTING; + var { removeHTTPWhitespace } = require_data_url(); + var { collectASequenceOfCodePointsFast } = require_infra(); + function isConnecting(readyState) { + return readyState === states.CONNECTING; } - function isEstablished(ws) { - return ws[kReadyState] === states.OPEN; + function isEstablished(readyState) { + return readyState === states.OPEN; } - function isClosing(ws) { - return ws[kReadyState] === states.CLOSING; + function isClosing(readyState) { + return readyState === states.CLOSING; } - function isClosed(ws) { - return ws[kReadyState] === states.CLOSED; + function isClosed(readyState) { + return readyState === states.CLOSED; } function fireEvent(e, target, eventFactory = (type, init2) => new Event(type, init2), eventInitDict = {}) { const event = eventFactory(e, eventInitDict); target.dispatchEvent(event); } - function websocketMessageReceived(ws, type, data) { - if (ws[kReadyState] !== states.OPEN) { - return; - } - let dataForEvent; - if (type === opcodes.TEXT) { - try { - dataForEvent = utf8Decode(data); - } catch { - failWebsocketConnection(ws, "Received invalid UTF-8 in text frame."); - return; - } - } else if (type === opcodes.BINARY) { - if (ws[kBinaryType] === "blob") { - dataForEvent = new Blob([data]); - } else { - dataForEvent = toArrayBuffer(data); - } - } - fireEvent("message", ws, createFastMessageEvent, { - origin: ws[kWebSocketURL].origin, - data: dataForEvent - }); + function websocketMessageReceived(handler2, type, data) { + handler2.onMessage(type, data); } function toArrayBuffer(buffer) { if (buffer.byteLength === buffer.buffer.byteLength) { return buffer.buffer; } - return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength); + return new Uint8Array(buffer).buffer; } function isValidSubprotocol(protocol) { if (protocol.length === 0) { @@ -17157,19 +24098,6 @@ var require_util7 = __commonJS({ } return code >= 3e3 && code <= 4999; } - function failWebsocketConnection(ws, reason) { - const { [kController]: controller, [kResponse]: response } = ws; - controller.abort(); - if (response?.socket && !response.socket.destroyed) { - response.socket.destroy(); - } - if (reason) { - fireEvent("error", ws, (type, init2) => new ErrorEvent(type, init2), { - error: new Error(reason), - message: reason - }); - } - } function isControlFrame(opcode) { return opcode === opcodes.CLOSE || opcode === opcodes.PING || opcode === opcodes.PONG; } @@ -17187,7 +24115,7 @@ var require_util7 = __commonJS({ const extensionList = /* @__PURE__ */ new Map(); while (position.position < extensions.length) { const pair = collectASequenceOfCodePointsFast(";", extensions, position); - const [name, value = ""] = pair.split("="); + const [name, value = ""] = pair.split("=", 2); extensionList.set( removeHTTPWhitespace(name, true, false), removeHTTPWhitespace(value, false, true) @@ -17209,14 +24137,51 @@ var require_util7 = __commonJS({ const num = Number.parseInt(value, 10); return num >= 8 && num <= 15; } - var hasIntl = typeof process.versions.icu === "string"; - var fatalDecoder = hasIntl ? new TextDecoder("utf-8", { fatal: true }) : void 0; - var utf8Decode = hasIntl ? fatalDecoder.decode.bind(fatalDecoder) : function(buffer) { - if (isUtf8(buffer)) { - return buffer.toString("utf-8"); + function getURLRecord(url2, baseURL) { + let urlRecord; + try { + urlRecord = new URL(url2, baseURL); + } catch (e) { + throw new DOMException(e, "SyntaxError"); } - throw new TypeError("Invalid utf-8 received."); - }; + if (urlRecord.protocol === "http:") { + urlRecord.protocol = "ws:"; + } else if (urlRecord.protocol === "https:") { + urlRecord.protocol = "wss:"; + } + if (urlRecord.protocol !== "ws:" && urlRecord.protocol !== "wss:") { + throw new DOMException("expected a ws: or wss: url", "SyntaxError"); + } + if (urlRecord.hash.length || urlRecord.href.endsWith("#")) { + throw new DOMException("hash", "SyntaxError"); + } + return urlRecord; + } + function validateCloseCodeAndReason(code, reason) { + if (code !== null) { + if (code !== 1e3 && (code < 3e3 || code > 4999)) { + throw new DOMException("invalid code", "InvalidAccessError"); + } + } + if (reason !== null) { + const reasonBytesLength = Buffer.byteLength(reason); + if (reasonBytesLength > 123) { + throw new DOMException(`Reason must be less than 123 bytes; received ${reasonBytesLength}`, "SyntaxError"); + } + } + } + var utf8Decode = (() => { + if (typeof process.versions.icu === "string") { + const fatalDecoder = new TextDecoder("utf-8", { fatal: true }); + return fatalDecoder.decode.bind(fatalDecoder); + } + return function(buffer) { + if (isUtf8(buffer)) { + return buffer.toString("utf-8"); + } + throw new TypeError("Invalid utf-8 received."); + }; + })(); module2.exports = { isConnecting, isEstablished, @@ -17225,7 +24190,6 @@ var require_util7 = __commonJS({ fireEvent, isValidSubprotocol, isValidStatusCode, - failWebsocketConnection, websocketMessageReceived, utf8Decode, isControlFrame, @@ -17233,7 +24197,10 @@ var require_util7 = __commonJS({ isTextBinaryFrame, isValidOpcode, parseExtensions, - isValidClientWindowBits + isValidClientWindowBits, + toArrayBuffer, + getURLRecord, + validateCloseCodeAndReason }; } }); @@ -17242,28 +24209,21 @@ var require_util7 = __commonJS({ var require_frame = __commonJS({ "node_modules/undici/lib/web/websocket/frame.js"(exports2, module2) { "use strict"; - var { maxUnsigned16Bit } = require_constants5(); - var BUFFER_SIZE = 16386; - var crypto3; + var { runtimeFeatures } = require_runtime_features(); + var { maxUnsigned16Bit, opcodes } = require_constants5(); + var BUFFER_SIZE = 8 * 1024; var buffer = null; var bufIdx = BUFFER_SIZE; - try { - crypto3 = require("node:crypto"); - } catch { - crypto3 = { - // not full compatibility, but minimum. - randomFillSync: function randomFillSync(buffer2, _offset, _size) { - for (let i = 0; i < buffer2.length; ++i) { - buffer2[i] = Math.random() * 255 | 0; - } - return buffer2; - } - }; - } + var randomFillSync = runtimeFeatures.has("crypto") ? require("node:crypto").randomFillSync : function randomFillSync2(buffer2, _offset, _size) { + for (let i = 0; i < buffer2.length; ++i) { + buffer2[i] = Math.random() * 255 | 0; + } + return buffer2; + }; function generateMask() { if (bufIdx === BUFFER_SIZE) { bufIdx = 0; - crypto3.randomFillSync(buffer ??= Buffer.allocUnsafe(BUFFER_SIZE), 0, BUFFER_SIZE); + randomFillSync(buffer ??= Buffer.allocUnsafeSlow(BUFFER_SIZE), 0, BUFFER_SIZE); } return [buffer[bufIdx++], buffer[bufIdx++], buffer[bufIdx++], buffer[bufIdx++]]; } @@ -17308,9 +24268,44 @@ var require_frame = __commonJS({ } return buffer2; } + /** + * @param {Uint8Array} buffer + */ + static createFastTextFrame(buffer2) { + const maskKey = generateMask(); + const bodyLength = buffer2.length; + for (let i = 0; i < bodyLength; ++i) { + buffer2[i] ^= maskKey[i & 3]; + } + let payloadLength = bodyLength; + let offset = 6; + if (bodyLength > maxUnsigned16Bit) { + offset += 8; + payloadLength = 127; + } else if (bodyLength > 125) { + offset += 2; + payloadLength = 126; + } + const head = Buffer.allocUnsafeSlow(offset); + head[0] = 128 | opcodes.TEXT; + head[1] = payloadLength | 128; + head[offset - 4] = maskKey[0]; + head[offset - 3] = maskKey[1]; + head[offset - 2] = maskKey[2]; + head[offset - 1] = maskKey[3]; + if (payloadLength === 126) { + head.writeUInt16BE(bodyLength, 2); + } else if (payloadLength === 127) { + head[2] = head[3] = 0; + head.writeUIntBE(bodyLength, 4, 6); + } + return [head, buffer2]; + } }; module2.exports = { - WebsocketFrameSend + WebsocketFrameSend, + generateMask + // for benchmark }; } }); @@ -17320,27 +24315,17 @@ var require_connection = __commonJS({ "node_modules/undici/lib/web/websocket/connection.js"(exports2, module2) { "use strict"; var { uid, states, sentCloseFrameState, emptyBuffer, opcodes } = require_constants5(); - var { - kReadyState, - kSentClose, - kByteParser, - kReceivedClose, - kResponse - } = require_symbols5(); - var { fireEvent, failWebsocketConnection, isClosing, isClosed, isEstablished, parseExtensions } = require_util7(); - var { channels } = require_diagnostics(); - var { CloseEvent } = require_events(); + var { parseExtensions, isClosed, isClosing, isEstablished, isConnecting, validateCloseCodeAndReason } = require_util5(); var { makeRequest } = require_request2(); var { fetching } = require_fetch(); var { Headers, getHeadersList } = require_headers(); var { getDecodeSplit } = require_util2(); var { WebsocketFrameSend } = require_frame(); - var crypto3; - try { - crypto3 = require("node:crypto"); - } catch { - } - function establishWebSocketConnection(url2, protocols, client, ws, onEstablish, options) { + var assert = require("node:assert"); + var { runtimeFeatures } = require_runtime_features(); + var crypto3 = runtimeFeatures.has("crypto") ? require("node:crypto") : null; + var warningEmitted = false; + function establishWebSocketConnection(url2, protocols, client, handler2, options) { const requestURL = url2; requestURL.protocol = url2.protocol === "ws:" ? "http:" : "https:"; const request3 = makeRequest({ @@ -17351,45 +24336,56 @@ var require_connection = __commonJS({ mode: "websocket", credentials: "include", cache: "no-store", - redirect: "error" + redirect: "error", + useURLCredentials: true }); if (options.headers) { const headersList = getHeadersList(new Headers(options.headers)); request3.headersList = headersList; } const keyValue = crypto3.randomBytes(16).toString("base64"); - request3.headersList.append("sec-websocket-key", keyValue); - request3.headersList.append("sec-websocket-version", "13"); + request3.headersList.append("sec-websocket-key", keyValue, true); + request3.headersList.append("sec-websocket-version", "13", true); for (const protocol of protocols) { - request3.headersList.append("sec-websocket-protocol", protocol); + request3.headersList.append("sec-websocket-protocol", protocol, true); } const permessageDeflate = "permessage-deflate; client_max_window_bits"; - request3.headersList.append("sec-websocket-extensions", permessageDeflate); + request3.headersList.append("sec-websocket-extensions", permessageDeflate, true); const controller = fetching({ request: request3, useParallelQueue: true, dispatcher: options.dispatcher, processResponse(response) { if (response.type === "error" || response.status !== 101) { - failWebsocketConnection(ws, "Received network error or non-101 status code."); - return; + if (response.socket?.session == null) { + failHandshake(handler2, response, 1002, "Received network error or non-101 status code.", response.error); + return; + } + if (response.status !== 200) { + failHandshake(handler2, response, 1002, "Received network error or non-200 status code.", response.error); + return; + } + } + if (warningEmitted === false && response.socket?.session != null) { + process.emitWarning("WebSocket over HTTP2 is experimental, and subject to change.", "ExperimentalWarning"); + warningEmitted = true; } if (protocols.length !== 0 && !response.headersList.get("Sec-WebSocket-Protocol")) { - failWebsocketConnection(ws, "Server did not respond with sent protocols."); + failHandshake(handler2, response, 1002, "Server did not respond with sent protocols."); return; } - if (response.headersList.get("Upgrade")?.toLowerCase() !== "websocket") { - failWebsocketConnection(ws, 'Server did not set Upgrade header to "websocket".'); + if (response.socket.session == null && response.headersList.get("Upgrade")?.toLowerCase() !== "websocket") { + failHandshake(handler2, response, 1002, 'Server did not set Upgrade header to "websocket".'); return; } - if (response.headersList.get("Connection")?.toLowerCase() !== "upgrade") { - failWebsocketConnection(ws, 'Server did not set Connection header to "upgrade".'); + if (response.socket.session == null && response.headersList.get("Connection")?.toLowerCase() !== "upgrade") { + failHandshake(handler2, response, 1002, 'Server did not set Connection header to "upgrade".'); return; } const secWSAccept = response.headersList.get("Sec-WebSocket-Accept"); - const digest = crypto3.createHash("sha1").update(keyValue + uid).digest("base64"); + const digest = crypto3.hash("sha1", keyValue + uid, "base64"); if (secWSAccept !== digest) { - failWebsocketConnection(ws, "Incorrect hash received in Sec-WebSocket-Accept header."); + failHandshake(handler2, response, 1002, "Incorrect hash received in Sec-WebSocket-Accept header."); return; } const secExtension = response.headersList.get("Sec-WebSocket-Extensions"); @@ -17397,104 +24393,80 @@ var require_connection = __commonJS({ if (secExtension !== null) { extensions = parseExtensions(secExtension); if (!extensions.has("permessage-deflate")) { - failWebsocketConnection(ws, "Sec-WebSocket-Extensions header does not match."); + failHandshake(handler2, response, 1002, "Sec-WebSocket-Extensions header does not match."); return; } } const secProtocol = response.headersList.get("Sec-WebSocket-Protocol"); if (secProtocol !== null) { const requestProtocols = getDecodeSplit("sec-websocket-protocol", request3.headersList); - if (!requestProtocols.includes(secProtocol)) { - failWebsocketConnection(ws, "Protocol was not set in the opening handshake."); + if (requestProtocols === null || !requestProtocols.includes(secProtocol)) { + failHandshake(handler2, response, 1002, "Protocol was not set in the opening handshake."); return; } } - response.socket.on("data", onSocketData); - response.socket.on("close", onSocketClose); - response.socket.on("error", onSocketError); - if (channels.open.hasSubscribers) { - channels.open.publish({ - address: response.socket.address(), - protocol: secProtocol, - extensions: secExtension - }); - } - onEstablish(response, extensions); + response.socket.on("data", handler2.onSocketData); + response.socket.on("close", handler2.onSocketClose); + response.socket.on("error", handler2.onSocketError); + handler2.wasEverConnected = true; + handler2.onConnectionEstablished(response, extensions); } }); return controller; } - function closeWebSocketConnection(ws, code, reason, reasonByteLength) { - if (isClosing(ws) || isClosed(ws)) { - } else if (!isEstablished(ws)) { - failWebsocketConnection(ws, "Connection was closed before it was established."); - ws[kReadyState] = states.CLOSING; - } else if (ws[kSentClose] === sentCloseFrameState.NOT_SENT) { - ws[kSentClose] = sentCloseFrameState.PROCESSING; + function closeWebSocketConnection(object2, code, reason, validate2 = false) { + code ??= null; + reason ??= ""; + if (validate2) validateCloseCodeAndReason(code, reason); + if (isClosed(object2.readyState) || isClosing(object2.readyState)) { + } else if (!isEstablished(object2.readyState)) { + failWebsocketConnection(object2); + object2.readyState = states.CLOSING; + } else if (!object2.closeState.has(sentCloseFrameState.SENT) && !object2.closeState.has(sentCloseFrameState.RECEIVED)) { const frame = new WebsocketFrameSend(); - if (code !== void 0 && reason === void 0) { + if (reason.length !== 0 && code === null) { + code = 1e3; + } + assert(code === null || Number.isInteger(code)); + if (code === null && reason.length === 0) { + frame.frameData = emptyBuffer; + } else if (code !== null && reason === null) { frame.frameData = Buffer.allocUnsafe(2); frame.frameData.writeUInt16BE(code, 0); - } else if (code !== void 0 && reason !== void 0) { - frame.frameData = Buffer.allocUnsafe(2 + reasonByteLength); + } else if (code !== null && reason !== null) { + frame.frameData = Buffer.allocUnsafe(2 + Buffer.byteLength(reason)); frame.frameData.writeUInt16BE(code, 0); frame.frameData.write(reason, 2, "utf-8"); } else { frame.frameData = emptyBuffer; } - const socket = ws[kResponse].socket; - socket.write(frame.createFrame(opcodes.CLOSE)); - ws[kSentClose] = sentCloseFrameState.SENT; - ws[kReadyState] = states.CLOSING; + object2.socket.write(frame.createFrame(opcodes.CLOSE)); + object2.closeState.add(sentCloseFrameState.SENT); + object2.readyState = states.CLOSING; } else { - ws[kReadyState] = states.CLOSING; + object2.readyState = states.CLOSING; } } - function onSocketData(chunk) { - if (!this.ws[kByteParser].write(chunk)) { - this.pause(); + function failHandshake(handler2, response, code, reason, cause) { + if (response.socket?.session != null && !response.socket.destroyed) { + response.socket.destroy(); } + failWebsocketConnection(handler2, code, reason, cause); } - function onSocketClose() { - const { ws } = this; - const { [kResponse]: response } = ws; - response.socket.off("data", onSocketData); - response.socket.off("close", onSocketClose); - response.socket.off("error", onSocketError); - const wasClean = ws[kSentClose] === sentCloseFrameState.SENT && ws[kReceivedClose]; - let code = 1005; - let reason = ""; - const result = ws[kByteParser].closingInfo; - if (result && !result.error) { - code = result.code ?? 1005; - reason = result.reason; - } else if (!ws[kReceivedClose]) { - code = 1006; - } - ws[kReadyState] = states.CLOSED; - fireEvent("close", ws, (type, init2) => new CloseEvent(type, init2), { - wasClean, - code, - reason - }); - if (channels.close.hasSubscribers) { - channels.close.publish({ - websocket: ws, - code, - reason - }); + function failWebsocketConnection(handler2, code, reason, cause) { + if (isEstablished(handler2.readyState)) { + closeWebSocketConnection(handler2, code, reason, false); } - } - function onSocketError(error3) { - const { ws } = this; - ws[kReadyState] = states.CLOSING; - if (channels.socketError.hasSubscribers) { - channels.socketError.publish(error3); + handler2.controller.abort(); + if (isConnecting(handler2.readyState)) { + handler2.onSocketClose(); + } else if (handler2.socket?.destroyed === false) { + handler2.socket.destroy(); } - this.destroy(); } module2.exports = { establishWebSocketConnection, + failWebsocketConnection, closeWebSocketConnection }; } @@ -17505,7 +24477,7 @@ var require_permessage_deflate = __commonJS({ "node_modules/undici/lib/web/websocket/permessage-deflate.js"(exports2, module2) { "use strict"; var { createInflateRaw, Z_DEFAULT_WINDOWBITS } = require("node:zlib"); - var { isValidClientWindowBits } = require_util7(); + var { isValidClientWindowBits } = require_util5(); var { MessageSizeExceededError } = require_errors(); var tail = Buffer.from([0, 0, 255, 255]); var kBuffer = /* @__PURE__ */ Symbol("kBuffer"); @@ -17552,6 +24524,7 @@ var require_permessage_deflate = __commonJS({ if (this.#maxPayloadSize > 0 && this.#inflate[kLength] > this.#maxPayloadSize) { callback(new MessageSizeExceededError()); this.#inflate.removeAllListeners(); + this.#inflate.destroy(); this.#inflate = null; return; } @@ -17588,26 +24561,19 @@ var require_receiver = __commonJS({ var { Writable } = require("node:stream"); var assert = require("node:assert"); var { parserStates, opcodes, states, emptyBuffer, sentCloseFrameState } = require_constants5(); - var { kReadyState, kSentClose, kResponse, kReceivedClose } = require_symbols5(); - var { channels } = require_diagnostics(); var { isValidStatusCode, isValidOpcode, - failWebsocketConnection, websocketMessageReceived, utf8Decode, isControlFrame, isTextBinaryFrame, isContinuationFrame - } = require_util7(); + } = require_util5(); + var { failWebsocketConnection } = require_connection(); var { WebsocketFrameSend } = require_frame(); - var { closeWebSocketConnection } = require_connection(); var { PerMessageDeflate } = require_permessage_deflate(); var { MessageSizeExceededError } = require_errors(); - function failWebsocketConnectionWithCode(ws, code, reason) { - closeWebSocketConnection(ws, code, reason, Buffer.byteLength(reason)); - failWebsocketConnection(ws, reason); - } var ByteParser = class extends Writable { #buffers = []; #fragmentsBytes = 0; @@ -17618,18 +24584,20 @@ var require_receiver = __commonJS({ #fragments = []; /** @type {Map} */ #extensions; + /** @type {import('./websocket').Handler} */ + #handler; /** @type {number} */ #maxFragments; /** @type {number} */ #maxPayloadSize; /** - * @param {import('./websocket').WebSocket} ws + * @param {import('./websocket').Handler} handler * @param {Map|null} extensions * @param {{ maxFragments?: number, maxPayloadSize?: number }} [options] */ - constructor(ws, extensions, options = {}) { + constructor(handler2, extensions, options = {}) { super(); - this.ws = ws; + this.#handler = handler2; this.#extensions = extensions == null ? /* @__PURE__ */ new Map() : extensions; this.#maxFragments = options.maxFragments ?? 0; this.#maxPayloadSize = options.maxPayloadSize ?? 0; @@ -17649,7 +24617,7 @@ var require_receiver = __commonJS({ } #validatePayloadLength() { if (this.#maxPayloadSize > 0 && !isControlFrame(this.#info.opcode) && this.#info.payloadLength + this.#fragmentsBytes > this.#maxPayloadSize) { - failWebsocketConnectionWithCode(this.ws, 1009, "Payload size exceeds maximum allowed size"); + failWebsocketConnection(this.#handler, 1009, "Payload size exceeds maximum allowed size"); return false; } return true; @@ -17675,39 +24643,39 @@ var require_receiver = __commonJS({ const rsv2 = buffer[0] & 32; const rsv3 = buffer[0] & 16; if (!isValidOpcode(opcode)) { - failWebsocketConnection(this.ws, "Invalid opcode received"); + failWebsocketConnection(this.#handler, 1002, "Invalid opcode received"); return callback(); } if (masked) { - failWebsocketConnection(this.ws, "Frame cannot be masked"); + failWebsocketConnection(this.#handler, 1002, "Frame cannot be masked"); return callback(); } if (rsv1 !== 0 && !this.#extensions.has("permessage-deflate")) { - failWebsocketConnection(this.ws, "Expected RSV1 to be clear."); + failWebsocketConnection(this.#handler, 1002, "Expected RSV1 to be clear."); return; } if (rsv2 !== 0 || rsv3 !== 0) { - failWebsocketConnection(this.ws, "RSV1, RSV2, RSV3 must be clear"); + failWebsocketConnection(this.#handler, 1002, "RSV1, RSV2, RSV3 must be clear"); return; } if (fragmented && !isTextBinaryFrame(opcode)) { - failWebsocketConnection(this.ws, "Invalid frame type was fragmented."); + failWebsocketConnection(this.#handler, 1002, "Invalid frame type was fragmented."); return; } if (isTextBinaryFrame(opcode) && this.#fragments.length > 0) { - failWebsocketConnection(this.ws, "Expected continuation frame"); + failWebsocketConnection(this.#handler, 1002, "Expected continuation frame"); return; } if (this.#info.fragmented && fragmented) { - failWebsocketConnection(this.ws, "Fragmented frame exceeded 125 bytes."); + failWebsocketConnection(this.#handler, 1002, "Fragmented frame exceeded 125 bytes."); return; } if ((payloadLength > 125 || fragmented) && isControlFrame(opcode)) { - failWebsocketConnection(this.ws, "Control frame either too large or fragmented"); + failWebsocketConnection(this.#handler, 1002, "Control frame either too large or fragmented"); return; } if (isContinuationFrame(opcode) && this.#fragments.length === 0 && !this.#info.compressed) { - failWebsocketConnection(this.ws, "Unexpected continuation frame"); + failWebsocketConnection(this.#handler, 1002, "Unexpected continuation frame"); return; } if (payloadLength <= 125) { @@ -17747,7 +24715,7 @@ var require_receiver = __commonJS({ const upper = buffer.readUInt32BE(0); const lower = buffer.readUInt32BE(4); if (upper !== 0 || lower > 2 ** 31 - 1) { - failWebsocketConnection(this.ws, "Received payload length > 2^31 bytes."); + failWebsocketConnection(this.#handler, 1009, "Received payload length > 2^31 bytes."); return; } this.#info.payloadLength = lower; @@ -17763,17 +24731,22 @@ var require_receiver = __commonJS({ if (isControlFrame(this.#info.opcode)) { this.#loop = this.parseControlFrame(body); this.#state = parserStates.INFO; + if (this.#loop && this.#handler.socket.writableNeedDrain) { + this.#loop = false; + this.#handler.socket.once("drain", () => { + if (this.destroyed) return; + this.#loop = true; + this.run(callback); + }); + return; + } } else { if (!this.#info.compressed) { if (!this.writeFragments(body)) { return; } - if (this.#maxPayloadSize > 0 && this.#fragmentsBytes > this.#maxPayloadSize) { - failWebsocketConnectionWithCode(this.ws, 1009, new MessageSizeExceededError().message); - return; - } if (!this.#info.fragmented && this.#info.fin) { - websocketMessageReceived(this.ws, this.#info.binaryType, this.consumeFragments()); + websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments()); } this.#state = parserStates.INFO; } else { @@ -17783,14 +24756,14 @@ var require_receiver = __commonJS({ (error3, data) => { if (error3) { const code = error3 instanceof MessageSizeExceededError ? 1009 : 1007; - failWebsocketConnectionWithCode(this.ws, code, error3.message); + failWebsocketConnection(this.#handler, code, error3.message); return; } if (!this.writeFragments(data)) { return; } if (this.#maxPayloadSize > 0 && this.#fragmentsBytes > this.#maxPayloadSize) { - failWebsocketConnectionWithCode(this.ws, 1009, new MessageSizeExceededError().message); + failWebsocketConnection(this.#handler, 1009, new MessageSizeExceededError().message); return; } if (!this.#info.fin) { @@ -17799,11 +24772,12 @@ var require_receiver = __commonJS({ this.run(callback); return; } - websocketMessageReceived(this.ws, this.#info.binaryType, this.consumeFragments()); + websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments()); this.#loop = true; this.#state = parserStates.INFO; this.run(callback); - } + }, + this.#fragmentsBytes ); this.#loop = false; break; @@ -17823,33 +24797,37 @@ var require_receiver = __commonJS({ } else if (n === 0) { return emptyBuffer; } - if (this.#buffers[0].length === n) { - this.#byteOffset -= this.#buffers[0].length; + this.#byteOffset -= n; + const first = this.#buffers[0]; + if (first.length > n) { + this.#buffers[0] = first.subarray(n, first.length); + return first.subarray(0, n); + } else if (first.length === n) { return this.#buffers.shift(); - } - const buffer = Buffer.allocUnsafe(n); - let offset = 0; - while (offset !== n) { - const next = this.#buffers[0]; - const { length } = next; - if (length + offset === n) { - buffer.set(this.#buffers.shift(), offset); - break; - } else if (length + offset > n) { - buffer.set(next.subarray(0, n - offset), offset); - this.#buffers[0] = next.subarray(n - offset); - break; - } else { - buffer.set(this.#buffers.shift(), offset); - offset += next.length; + } else { + let offset = 0; + const buffer = Buffer.allocUnsafeSlow(n); + while (offset !== n) { + const next = this.#buffers[0]; + const length = next.length; + if (length + offset === n) { + buffer.set(this.#buffers.shift(), offset); + break; + } else if (length + offset > n) { + buffer.set(next.subarray(0, n - offset), offset); + this.#buffers[0] = next.subarray(n - offset); + break; + } else { + buffer.set(this.#buffers.shift(), offset); + offset += length; + } } + return buffer; } - this.#byteOffset -= n; - return buffer; } writeFragments(fragment) { if (this.#maxFragments > 0 && this.#fragments.length === this.#maxFragments) { - failWebsocketConnectionWithCode(this.ws, 1008, "Too many message fragments"); + failWebsocketConnection(this.#handler, 1008, "Too many message fragments"); return false; } this.#fragmentsBytes += fragment.length; @@ -17862,7 +24840,13 @@ var require_receiver = __commonJS({ this.#fragmentsBytes = 0; return fragments.shift(); } - const output = Buffer.concat(fragments, this.#fragmentsBytes); + let offset = 0; + const output = Buffer.allocUnsafeSlow(this.#fragmentsBytes); + for (let i = 0; i < fragments.length; ++i) { + const buffer = fragments[i]; + output.set(buffer, offset); + offset += buffer.length; + } this.#fragments = []; this.#fragmentsBytes = 0; return output; @@ -17895,51 +24879,36 @@ var require_receiver = __commonJS({ const { opcode, payloadLength } = this.#info; if (opcode === opcodes.CLOSE) { if (payloadLength === 1) { - failWebsocketConnection(this.ws, "Received close frame with a 1-byte body."); + failWebsocketConnection(this.#handler, 1002, "Received close frame with a 1-byte body."); return false; } this.#info.closeInfo = this.parseCloseBody(body); if (this.#info.closeInfo.error) { const { code, reason } = this.#info.closeInfo; - closeWebSocketConnection(this.ws, code, reason, reason.length); - failWebsocketConnection(this.ws, reason); + failWebsocketConnection(this.#handler, code, reason); return false; } - if (this.ws[kSentClose] !== sentCloseFrameState.SENT) { + if (!this.#handler.closeState.has(sentCloseFrameState.SENT) && !this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { let body2 = emptyBuffer; if (this.#info.closeInfo.code) { body2 = Buffer.allocUnsafe(2); body2.writeUInt16BE(this.#info.closeInfo.code, 0); } const closeFrame = new WebsocketFrameSend(body2); - this.ws[kResponse].socket.write( - closeFrame.createFrame(opcodes.CLOSE), - (err) => { - if (!err) { - this.ws[kSentClose] = sentCloseFrameState.SENT; - } - } - ); + this.#handler.socket.write(closeFrame.createFrame(opcodes.CLOSE)); + this.#handler.closeState.add(sentCloseFrameState.SENT); } - this.ws[kReadyState] = states.CLOSING; - this.ws[kReceivedClose] = true; + this.#handler.readyState = states.CLOSING; + this.#handler.closeState.add(sentCloseFrameState.RECEIVED); return false; } else if (opcode === opcodes.PING) { - if (!this.ws[kReceivedClose]) { + if (!this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { const frame = new WebsocketFrameSend(body); - this.ws[kResponse].socket.write(frame.createFrame(opcodes.PONG)); - if (channels.ping.hasSubscribers) { - channels.ping.publish({ - payload: body - }); - } + this.#handler.socket.write(frame.createFrame(opcodes.PONG)); + this.#handler.onPing(body); } } else if (opcode === opcodes.PONG) { - if (channels.pong.hasSubscribers) { - channels.pong.publish({ - payload: body - }); - } + this.#handler.onPong(body); } return true; } @@ -17960,7 +24929,6 @@ var require_sender = __commonJS({ var { WebsocketFrameSend } = require_frame(); var { opcodes, sendHints } = require_constants5(); var FixedQueue = require_fixed_queue(); - var FastBuffer = Buffer[Symbol.species]; var SendQueue = class { /** * @type {FixedQueue} @@ -17977,14 +24945,21 @@ var require_sender = __commonJS({ } add(item, cb, hint) { if (hint !== sendHints.blob) { - const frame = createFrame(item, hint); if (!this.#running) { - this.#socket.write(frame, cb); + if (hint === sendHints.text) { + const { 0: head, 1: body } = WebsocketFrameSend.createFastTextFrame(item); + this.#socket.cork(); + this.#socket.write(head); + this.#socket.write(body, cb); + this.#socket.uncork(); + } else { + this.#socket.write(createFrame(item, hint), cb); + } } else { const node2 = { promise: null, callback: cb, - frame + frame: createFrame(item, hint) }; this.#queue.push(node2); } @@ -18018,17 +24993,16 @@ var require_sender = __commonJS({ } }; function createFrame(data, hint) { - return new WebsocketFrameSend(toBuffer(data, hint)).createFrame(hint === sendHints.string ? opcodes.TEXT : opcodes.BINARY); + return new WebsocketFrameSend(toBuffer(data, hint)).createFrame(hint === sendHints.text ? opcodes.TEXT : opcodes.BINARY); } function toBuffer(data, hint) { switch (hint) { - case sendHints.string: - return Buffer.from(data); + case sendHints.text: + case sendHints.typedArray: + return new Uint8Array(data.buffer, data.byteOffset, data.byteLength); case sendHints.arrayBuffer: case sendHints.blob: - return new FastBuffer(data); - case sendHints.typedArray: - return new FastBuffer(data.buffer, data.byteOffset, data.byteLength); + return new Uint8Array(data); } } module2.exports = { SendQueue }; @@ -18039,33 +25013,39 @@ var require_sender = __commonJS({ var require_websocket = __commonJS({ "node_modules/undici/lib/web/websocket/websocket.js"(exports2, module2) { "use strict"; + var { isArrayBuffer } = require("node:util/types"); var { webidl } = require_webidl(); var { URLSerializer } = require_data_url(); var { environmentSettingsObject } = require_util2(); - var { staticPropertyDescriptors, states, sentCloseFrameState, sendHints } = require_constants5(); - var { - kWebSocketURL, - kReadyState, - kController, - kBinaryType, - kResponse, - kSentClose, - kByteParser - } = require_symbols5(); + var { staticPropertyDescriptors, states, sentCloseFrameState, sendHints, opcodes } = require_constants5(); var { isConnecting, isEstablished, isClosing, + isClosed, isValidSubprotocol, - fireEvent - } = require_util7(); - var { establishWebSocketConnection, closeWebSocketConnection } = require_connection(); + fireEvent, + utf8Decode, + toArrayBuffer, + getURLRecord + } = require_util5(); + var { establishWebSocketConnection, closeWebSocketConnection, failWebsocketConnection } = require_connection(); var { ByteParser } = require_receiver(); - var { kEnumerableProperty, isBlobLike } = require_util(); + var { kEnumerableProperty } = require_util(); var { getGlobalDispatcher } = require_global2(); - var { types: types2 } = require("node:util"); - var { ErrorEvent, CloseEvent } = require_events(); + var { ErrorEvent, CloseEvent, createFastMessageEvent } = require_events(); var { SendQueue } = require_sender(); + var { WebsocketFrameSend } = require_frame(); + var { channels } = require_diagnostics(); + function getSocketAddress(socket) { + if (typeof socket?.address === "function") { + return socket.address(); + } + if (typeof socket?.session?.socket?.address === "function") { + return socket.session.socket.address(); + } + return null; + } var WebSocket = class _WebSocket extends EventTarget { #events = { open: null, @@ -18078,6 +25058,51 @@ var require_websocket = __commonJS({ #extensions = ""; /** @type {SendQueue} */ #sendQueue; + /** @type {Handler} */ + #handler = { + onConnectionEstablished: (response, extensions) => this.#onConnectionEstablished(response, extensions), + onMessage: (opcode, data) => this.#onMessage(opcode, data), + onParserError: (err) => failWebsocketConnection(this.#handler, null, err.message), + onParserDrain: () => this.#onParserDrain(), + onSocketData: (chunk) => { + if (!this.#parser.write(chunk)) { + this.#handler.socket.pause(); + } + }, + onSocketError: (err) => { + this.#handler.readyState = states.CLOSING; + if (channels.socketError.hasSubscribers) { + channels.socketError.publish(err); + } + this.#handler.socket.destroy(); + }, + onSocketClose: () => this.#onSocketClose(), + onPing: (body) => { + if (channels.ping.hasSubscribers) { + channels.ping.publish({ + payload: body, + websocket: this + }); + } + }, + onPong: (body) => { + if (channels.pong.hasSubscribers) { + channels.pong.publish({ + payload: body, + websocket: this + }); + } + }, + readyState: states.CONNECTING, + socket: null, + closeState: /* @__PURE__ */ new Set(), + controller: null, + wasEverConnected: false + }; + #url; + #binaryType; + /** @type {import('./receiver').ByteParser} */ + #parser; /** * @param {string} url * @param {string|string[]} protocols @@ -18088,29 +25113,10 @@ var require_websocket = __commonJS({ const prefix = "WebSocket constructor"; webidl.argumentLengthCheck(arguments, 1, prefix); const options = webidl.converters["DOMString or sequence or WebSocketInit"](protocols, prefix, "options"); - url2 = webidl.converters.USVString(url2, prefix, "url"); + url2 = webidl.converters.USVString(url2); protocols = options.protocols; const baseURL = environmentSettingsObject.settingsObject.baseUrl; - let urlRecord; - try { - urlRecord = new URL(url2, baseURL); - } catch (e) { - throw new DOMException(e, "SyntaxError"); - } - if (urlRecord.protocol === "http:") { - urlRecord.protocol = "ws:"; - } else if (urlRecord.protocol === "https:") { - urlRecord.protocol = "wss:"; - } - if (urlRecord.protocol !== "ws:" && urlRecord.protocol !== "wss:") { - throw new DOMException( - `Expected a ws: or wss: protocol, got ${urlRecord.protocol}`, - "SyntaxError" - ); - } - if (urlRecord.hash || urlRecord.href.endsWith("#")) { - throw new DOMException("Got fragment", "SyntaxError"); - } + const urlRecord = getURLRecord(url2, baseURL); if (typeof protocols === "string") { protocols = [protocols]; } @@ -18120,19 +25126,17 @@ var require_websocket = __commonJS({ if (protocols.length > 0 && !protocols.every((p) => isValidSubprotocol(p))) { throw new DOMException("Invalid Sec-WebSocket-Protocol value", "SyntaxError"); } - this[kWebSocketURL] = new URL(urlRecord.href); + this.#url = new URL(urlRecord.href); const client = environmentSettingsObject.settingsObject; - this[kController] = establishWebSocketConnection( + this.#handler.controller = establishWebSocketConnection( urlRecord, protocols, client, - this, - (response, extensions) => this.#onConnectionEstablished(response, extensions), + this.#handler, options ); - this[kReadyState] = _WebSocket.CONNECTING; - this[kSentClose] = sentCloseFrameState.NOT_SENT; - this[kBinaryType] = "blob"; + this.#handler.readyState = _WebSocket.CONNECTING; + this.#binaryType = "blob"; } /** * @see https://websockets.spec.whatwg.org/#dom-websocket-close @@ -18143,27 +25147,14 @@ var require_websocket = __commonJS({ webidl.brandCheck(this, _WebSocket); const prefix = "WebSocket.close"; if (code !== void 0) { - code = webidl.converters["unsigned short"](code, prefix, "code", { clamp: true }); + code = webidl.converters["unsigned short"](code, prefix, "code", webidl.attributes.Clamp); } if (reason !== void 0) { - reason = webidl.converters.USVString(reason, prefix, "reason"); + reason = webidl.converters.USVString(reason); } - if (code !== void 0) { - if (code !== 1e3 && (code < 3e3 || code > 4999)) { - throw new DOMException("invalid code", "InvalidAccessError"); - } - } - let reasonByteLength = 0; - if (reason !== void 0) { - reasonByteLength = Buffer.byteLength(reason); - if (reasonByteLength > 123) { - throw new DOMException( - `Reason must be less than 123 bytes; received ${reasonByteLength}`, - "SyntaxError" - ); - } - } - closeWebSocketConnection(this, code, reason, reasonByteLength); + code ??= null; + reason ??= ""; + closeWebSocketConnection(this.#handler, code, reason, true); } /** * @see https://websockets.spec.whatwg.org/#dom-websocket-send @@ -18174,19 +25165,19 @@ var require_websocket = __commonJS({ const prefix = "WebSocket.send"; webidl.argumentLengthCheck(arguments, 1, prefix); data = webidl.converters.WebSocketSendData(data, prefix, "data"); - if (isConnecting(this)) { + if (isConnecting(this.#handler.readyState)) { throw new DOMException("Sent before connected.", "InvalidStateError"); } - if (!isEstablished(this) || isClosing(this)) { + if (!isEstablished(this.#handler.readyState) || isClosing(this.#handler.readyState)) { return; } if (typeof data === "string") { - const length = Buffer.byteLength(data); - this.#bufferedAmount += length; - this.#sendQueue.add(data, () => { - this.#bufferedAmount -= length; - }, sendHints.string); - } else if (types2.isArrayBuffer(data)) { + const buffer = Buffer.from(data); + this.#bufferedAmount += buffer.byteLength; + this.#sendQueue.add(buffer, () => { + this.#bufferedAmount -= buffer.byteLength; + }, sendHints.text); + } else if (isArrayBuffer(data)) { this.#bufferedAmount += data.byteLength; this.#sendQueue.add(data, () => { this.#bufferedAmount -= data.byteLength; @@ -18196,7 +25187,7 @@ var require_websocket = __commonJS({ this.#sendQueue.add(data, () => { this.#bufferedAmount -= data.byteLength; }, sendHints.typedArray); - } else if (isBlobLike(data)) { + } else if (webidl.is.Blob(data)) { this.#bufferedAmount += data.size; this.#sendQueue.add(data, () => { this.#bufferedAmount -= data.size; @@ -18205,7 +25196,7 @@ var require_websocket = __commonJS({ } get readyState() { webidl.brandCheck(this, _WebSocket); - return this[kReadyState]; + return this.#handler.readyState; } get bufferedAmount() { webidl.brandCheck(this, _WebSocket); @@ -18213,7 +25204,7 @@ var require_websocket = __commonJS({ } get url() { webidl.brandCheck(this, _WebSocket); - return URLSerializer(this[kWebSocketURL]); + return URLSerializer(this.#url); } get extensions() { webidl.brandCheck(this, _WebSocket); @@ -18232,9 +25223,10 @@ var require_websocket = __commonJS({ if (this.#events.open) { this.removeEventListener("open", this.#events.open); } - if (typeof fn === "function") { + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("open", listener); this.#events.open = fn; - this.addEventListener("open", fn); } else { this.#events.open = null; } @@ -18248,9 +25240,10 @@ var require_websocket = __commonJS({ if (this.#events.error) { this.removeEventListener("error", this.#events.error); } - if (typeof fn === "function") { + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("error", listener); this.#events.error = fn; - this.addEventListener("error", fn); } else { this.#events.error = null; } @@ -18264,9 +25257,10 @@ var require_websocket = __commonJS({ if (this.#events.close) { this.removeEventListener("close", this.#events.close); } - if (typeof fn === "function") { + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("close", listener); this.#events.close = fn; - this.addEventListener("close", fn); } else { this.#events.close = null; } @@ -18280,43 +25274,43 @@ var require_websocket = __commonJS({ if (this.#events.message) { this.removeEventListener("message", this.#events.message); } - if (typeof fn === "function") { + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("message", listener); this.#events.message = fn; - this.addEventListener("message", fn); } else { this.#events.message = null; } } get binaryType() { webidl.brandCheck(this, _WebSocket); - return this[kBinaryType]; + return this.#binaryType; } set binaryType(type) { webidl.brandCheck(this, _WebSocket); if (type !== "blob" && type !== "arraybuffer") { - this[kBinaryType] = "blob"; + this.#binaryType = "blob"; } else { - this[kBinaryType] = type; + this.#binaryType = type; } } /** * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol */ #onConnectionEstablished(response, parsedExtensions) { - this[kResponse] = response; - const webSocketOptions = this[kController]?.dispatcher?.webSocketOptions; + this.#handler.socket = response.socket; + const webSocketOptions = this.#handler.controller.dispatcher?.webSocketOptions; const maxFragments = webSocketOptions?.maxFragments; const maxPayloadSize = webSocketOptions?.maxPayloadSize; - const parser = new ByteParser(this, parsedExtensions, { + const parser = new ByteParser(this.#handler, parsedExtensions, { maxFragments, maxPayloadSize }); - parser.on("drain", onParserDrain); - parser.on("error", onParserError.bind(this)); - response.socket.ws = this; - this[kByteParser] = parser; + parser.on("drain", () => this.#handler.onParserDrain()); + parser.on("error", (err) => this.#handler.onParserError(err)); + this.#parser = parser; this.#sendQueue = new SendQueue(response.socket); - this[kReadyState] = states.OPEN; + this.#handler.readyState = states.OPEN; const extensions = response.headersList.get("sec-websocket-extensions"); if (extensions !== null) { this.#extensions = extensions; @@ -18326,8 +25320,102 @@ var require_websocket = __commonJS({ this.#protocol = protocol; } fireEvent("open", this); + if (channels.open.hasSubscribers) { + const headers = response.headersList.entries; + channels.open.publish({ + address: getSocketAddress(response.socket), + protocol: this.#protocol, + extensions: this.#extensions, + websocket: this, + handshakeResponse: { + status: response.status, + statusText: response.statusText, + headers + } + }); + } + } + #onMessage(type, data) { + if (this.#handler.readyState !== states.OPEN) { + return; + } + let dataForEvent; + if (type === opcodes.TEXT) { + try { + dataForEvent = utf8Decode(data); + } catch { + failWebsocketConnection(this.#handler, 1007, "Received invalid UTF-8 in text frame."); + return; + } + } else if (type === opcodes.BINARY) { + if (this.#binaryType === "blob") { + dataForEvent = new Blob([data]); + } else { + dataForEvent = toArrayBuffer(data); + } + } + fireEvent("message", this, createFastMessageEvent, { + origin: this.#url.origin, + data: dataForEvent + }); + } + #onParserDrain() { + this.#handler.socket.resume(); + } + /** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.4 + */ + #onSocketClose() { + const wasClean = this.#handler.closeState.has(sentCloseFrameState.SENT) && this.#handler.closeState.has(sentCloseFrameState.RECEIVED); + let code = 1005; + let reason = ""; + const result = this.#parser?.closingInfo; + if (result && !result.error) { + code = result.code ?? 1005; + reason = result.reason; + } + this.#handler.readyState = states.CLOSED; + if (!this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { + code = 1006; + fireEvent("error", this, (type, init2) => new ErrorEvent(type, init2), { + error: new TypeError(reason) + }); + } + fireEvent("close", this, (type, init2) => new CloseEvent(type, init2), { + wasClean, + code, + reason + }); + if (channels.close.hasSubscribers) { + channels.close.publish({ + websocket: this, + code, + reason + }); + } + } + /** + * @param {WebSocket} ws + * @param {Buffer|undefined} buffer + */ + static ping(ws, buffer) { + if (Buffer.isBuffer(buffer)) { + if (buffer.length > 125) { + throw new TypeError("A PING frame cannot have a body larger than 125 bytes."); + } + } else if (buffer !== void 0) { + throw new TypeError("Expected buffer payload"); + } + const readyState = ws.#handler.readyState; + if (isEstablished(readyState) && !isClosing(readyState) && !isClosed(readyState)) { + const frame = new WebsocketFrameSend(buffer); + ws.#handler.socket.write(frame.createFrame(opcodes.PING)); + } } }; + var { ping } = WebSocket; + Reflect.deleteProperty(WebSocket, "ping"); WebSocket.CONNECTING = WebSocket.prototype.CONNECTING = states.CONNECTING; WebSocket.OPEN = WebSocket.prototype.OPEN = states.OPEN; WebSocket.CLOSING = WebSocket.prototype.CLOSING = states.CLOSING; @@ -18366,7 +25454,7 @@ var require_websocket = __commonJS({ webidl.converters.DOMString ); webidl.converters["DOMString or sequence"] = function(V, prefix, argument) { - if (webidl.util.Type(V) === "Object" && Symbol.iterator in V) { + if (webidl.util.Type(V) === webidl.util.Types.OBJECT && Symbol.iterator in V) { return webidl.converters["sequence"](V); } return webidl.converters.DOMString(V, prefix, argument); @@ -18375,7 +25463,7 @@ var require_websocket = __commonJS({ { key: "protocols", converter: webidl.converters["DOMString or sequence"], - defaultValue: () => new Array(0) + defaultValue: () => [] }, { key: "dispatcher", @@ -18388,45 +25476,422 @@ var require_websocket = __commonJS({ } ]); webidl.converters["DOMString or sequence or WebSocketInit"] = function(V) { - if (webidl.util.Type(V) === "Object" && !(Symbol.iterator in V)) { + if (webidl.util.Type(V) === webidl.util.Types.OBJECT && !(Symbol.iterator in V)) { return webidl.converters.WebSocketInit(V); } return { protocols: webidl.converters["DOMString or sequence"](V) }; }; webidl.converters.WebSocketSendData = function(V) { - if (webidl.util.Type(V) === "Object") { - if (isBlobLike(V)) { - return webidl.converters.Blob(V, { strict: false }); + if (webidl.util.Type(V) === webidl.util.Types.OBJECT) { + if (webidl.is.Blob(V)) { + return V; } - if (ArrayBuffer.isView(V) || types2.isArrayBuffer(V)) { - return webidl.converters.BufferSource(V); + if (webidl.is.BufferSource(V)) { + return V; } } return webidl.converters.USVString(V); }; - function onParserDrain() { - this.ws[kResponse].socket.resume(); - } - function onParserError(err) { - let message; - let code; - if (err instanceof CloseEvent) { - message = err.reason; - code = err.code; - } else { - message = err.message; + module2.exports = { + WebSocket, + ping + }; + } +}); + +// node_modules/undici/lib/web/websocket/stream/websocketerror.js +var require_websocketerror = __commonJS({ + "node_modules/undici/lib/web/websocket/stream/websocketerror.js"(exports2, module2) { + "use strict"; + var { webidl } = require_webidl(); + var { validateCloseCodeAndReason } = require_util5(); + var { kConstruct } = require_symbols(); + var { kEnumerableProperty } = require_util(); + function createInheritableDOMException() { + class Test extends DOMException { + get reason() { + return ""; + } } - fireEvent("error", this, () => new ErrorEvent("error", { error: err, message })); - closeWebSocketConnection(this, code); + if (new Test().reason !== void 0) { + return DOMException; + } + return new Proxy(DOMException, { + construct(target, args, newTarget) { + const instance8 = Reflect.construct(target, args, target); + Object.setPrototypeOf(instance8, newTarget.prototype); + return instance8; + } + }); } - module2.exports = { - WebSocket + var WebSocketError = class _WebSocketError extends createInheritableDOMException() { + #closeCode; + #reason; + constructor(message = "", init2 = void 0) { + message = webidl.converters.DOMString(message, "WebSocketError", "message"); + super(message, "WebSocketError"); + if (init2 === kConstruct) { + return; + } else if (init2 !== null) { + init2 = webidl.converters.WebSocketCloseInfo(init2); + } + let code = init2.closeCode ?? null; + const reason = init2.reason ?? ""; + validateCloseCodeAndReason(code, reason); + if (reason.length !== 0 && code === null) { + code = 1e3; + } + this.#closeCode = code; + this.#reason = reason; + } + get closeCode() { + return this.#closeCode; + } + get reason() { + return this.#reason; + } + /** + * @param {string} message + * @param {number|null} code + * @param {string} reason + */ + static createUnvalidatedWebSocketError(message, code, reason) { + const error3 = new _WebSocketError(message, kConstruct); + error3.#closeCode = code; + error3.#reason = reason; + return error3; + } }; + var { createUnvalidatedWebSocketError } = WebSocketError; + delete WebSocketError.createUnvalidatedWebSocketError; + Object.defineProperties(WebSocketError.prototype, { + closeCode: kEnumerableProperty, + reason: kEnumerableProperty, + [Symbol.toStringTag]: { + value: "WebSocketError", + writable: false, + enumerable: false, + configurable: true + } + }); + webidl.is.WebSocketError = webidl.util.MakeTypeAssertion(WebSocketError); + module2.exports = { WebSocketError, createUnvalidatedWebSocketError }; + } +}); + +// node_modules/undici/lib/web/websocket/stream/websocketstream.js +var require_websocketstream = __commonJS({ + "node_modules/undici/lib/web/websocket/stream/websocketstream.js"(exports2, module2) { + "use strict"; + var { createDeferredPromise } = require_promise(); + var { environmentSettingsObject } = require_util2(); + var { states, opcodes, sentCloseFrameState } = require_constants5(); + var { webidl } = require_webidl(); + var { getURLRecord, isValidSubprotocol, isEstablished, utf8Decode } = require_util5(); + var { establishWebSocketConnection, failWebsocketConnection, closeWebSocketConnection } = require_connection(); + var { channels } = require_diagnostics(); + var { WebsocketFrameSend } = require_frame(); + var { ByteParser } = require_receiver(); + var { WebSocketError, createUnvalidatedWebSocketError } = require_websocketerror(); + var { kEnumerableProperty } = require_util(); + var { utf8DecodeBytes } = require_encoding(); + var emittedExperimentalWarning = false; + var WebSocketStream = class { + // Each WebSocketStream object has an associated url , which is a URL record . + /** @type {URL} */ + #url; + // Each WebSocketStream object has an associated opened promise , which is a promise. + /** @type {import('../../../util/promise').DeferredPromise} */ + #openedPromise; + // Each WebSocketStream object has an associated closed promise , which is a promise. + /** @type {import('../../../util/promise').DeferredPromise} */ + #closedPromise; + // Each WebSocketStream object has an associated readable stream , which is a ReadableStream . + /** @type {ReadableStream} */ + #readableStream; + /** @type {ReadableStreamDefaultController} */ + #readableStreamController; + // Retain the controller so the writable stream can be errored while locked. + /** @type {WritableStreamDefaultController} */ + #writableStreamController; + // Each WebSocketStream object has an associated boolean handshake aborted , which is initially false. + #handshakeAborted = false; + /** @type {import('../websocket').Handler} */ + #handler = { + // https://whatpr.org/websockets/48/7b748d3...d5570f3.html#feedback-to-websocket-stream-from-the-protocol + onConnectionEstablished: (response, extensions) => this.#onConnectionEstablished(response, extensions), + onMessage: (opcode, data) => this.#onMessage(opcode, data), + onParserError: (err) => failWebsocketConnection(this.#handler, null, err.message), + onParserDrain: () => this.#handler.socket.resume(), + onSocketData: (chunk) => { + if (!this.#parser.write(chunk)) { + this.#handler.socket.pause(); + } + }, + onSocketError: (err) => { + this.#handler.readyState = states.CLOSING; + if (channels.socketError.hasSubscribers) { + channels.socketError.publish(err); + } + this.#handler.socket.destroy(); + }, + onSocketClose: () => this.#onSocketClose(), + onPing: () => { + }, + onPong: () => { + }, + readyState: states.CONNECTING, + socket: null, + closeState: /* @__PURE__ */ new Set(), + controller: null, + wasEverConnected: false + }; + /** @type {import('../receiver').ByteParser} */ + #parser; + constructor(url2, options = void 0) { + if (!emittedExperimentalWarning) { + process.emitWarning("WebSocketStream is experimental! Expect it to change at any time.", { + code: "UNDICI-WSS" + }); + emittedExperimentalWarning = true; + } + webidl.argumentLengthCheck(arguments, 1, "WebSocket"); + url2 = webidl.converters.USVString(url2); + if (options !== null) { + options = webidl.converters.WebSocketStreamOptions(options); + } + const baseURL = environmentSettingsObject.settingsObject.baseUrl; + const urlRecord = getURLRecord(url2, baseURL); + const protocols = options.protocols; + if (protocols.length !== new Set(protocols.map((p) => p.toLowerCase())).size) { + throw new DOMException("Invalid Sec-WebSocket-Protocol value", "SyntaxError"); + } + if (protocols.length > 0 && !protocols.every((p) => isValidSubprotocol(p))) { + throw new DOMException("Invalid Sec-WebSocket-Protocol value", "SyntaxError"); + } + this.#url = urlRecord.toString(); + this.#openedPromise = createDeferredPromise(); + this.#closedPromise = createDeferredPromise(); + if (options.signal != null) { + const signal = options.signal; + if (signal.aborted) { + this.#openedPromise.reject(signal.reason); + this.#closedPromise.reject(signal.reason); + return; + } + signal.addEventListener("abort", () => { + if (!isEstablished(this.#handler.readyState)) { + failWebsocketConnection(this.#handler); + this.#handler.readyState = states.CLOSING; + this.#openedPromise.reject(signal.reason); + this.#closedPromise.reject(signal.reason); + this.#handshakeAborted = true; + } + }, { once: true }); + } + const client = environmentSettingsObject.settingsObject; + this.#handler.controller = establishWebSocketConnection( + urlRecord, + protocols, + client, + this.#handler, + options + ); + } + // The url getter steps are to return this 's url , serialized . + get url() { + return this.#url.toString(); + } + // The opened getter steps are to return this 's opened promise . + get opened() { + return this.#openedPromise.promise; + } + // The closed getter steps are to return this 's closed promise . + get closed() { + return this.#closedPromise.promise; + } + // The close( closeInfo ) method steps are: + close(closeInfo = void 0) { + if (closeInfo !== null) { + closeInfo = webidl.converters.WebSocketCloseInfo(closeInfo); + } + const code = closeInfo.closeCode ?? null; + const reason = closeInfo.reason; + closeWebSocketConnection(this.#handler, code, reason, true); + } + #write(chunk) { + chunk = webidl.converters.WebSocketStreamWrite(chunk); + const promise = createDeferredPromise(); + let data = null; + let opcode = null; + if (webidl.is.BufferSource(chunk)) { + data = new Uint8Array(ArrayBuffer.isView(chunk) ? new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength) : chunk.slice()); + opcode = opcodes.BINARY; + } else { + let string2; + try { + string2 = webidl.converters.DOMString(chunk); + } catch (e) { + promise.reject(e); + return promise.promise; + } + data = new TextEncoder().encode(string2); + opcode = opcodes.TEXT; + } + if (!this.#handler.closeState.has(sentCloseFrameState.SENT) && !this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { + const frame = new WebsocketFrameSend(data); + this.#handler.socket.write(frame.createFrame(opcode), () => { + promise.resolve(void 0); + }); + } + return promise.promise; + } + /** @type {import('../websocket').Handler['onConnectionEstablished']} */ + #onConnectionEstablished(response, parsedExtensions) { + this.#handler.socket = response.socket; + const maxFragments = this.#handler.controller.dispatcher?.webSocketOptions?.maxFragments; + const maxPayloadSize = this.#handler.controller.dispatcher?.webSocketOptions?.maxPayloadSize; + const parser = new ByteParser(this.#handler, parsedExtensions, { + maxFragments, + maxPayloadSize + }); + parser.on("drain", () => this.#handler.onParserDrain()); + parser.on("error", (err) => this.#handler.onParserError(err)); + this.#parser = parser; + this.#handler.readyState = states.OPEN; + const extensions = parsedExtensions ?? ""; + const protocol = response.headersList.get("sec-websocket-protocol") ?? ""; + const readable = new ReadableStream({ + start: (controller) => { + this.#readableStreamController = controller; + }, + cancel: (reason) => this.#cancel(reason) + }); + const writable = new WritableStream({ + start: (controller) => { + this.#writableStreamController = controller; + }, + write: (chunk) => this.#write(chunk), + close: () => closeWebSocketConnection(this.#handler, null, null), + abort: (reason) => this.#closeUsingReason(reason) + }); + this.#readableStream = readable; + this.#openedPromise.resolve({ + extensions, + protocol, + readable, + writable + }); + } + /** @type {import('../websocket').Handler['onMessage']} */ + #onMessage(type, data) { + if (this.#handler.readyState !== states.OPEN) { + return; + } + let chunk; + if (type === opcodes.TEXT) { + try { + chunk = utf8Decode(data); + } catch { + failWebsocketConnection(this.#handler, 1007, "Received invalid UTF-8 in text frame."); + return; + } + } else if (type === opcodes.BINARY) { + chunk = new Uint8Array(data.buffer, data.byteOffset, data.byteLength); + } + this.#readableStreamController.enqueue(chunk); + } + /** @type {import('../websocket').Handler['onSocketClose']} */ + #onSocketClose() { + const wasClean = this.#handler.closeState.has(sentCloseFrameState.SENT) && this.#handler.closeState.has(sentCloseFrameState.RECEIVED); + this.#handler.readyState = states.CLOSED; + if (this.#handshakeAborted) { + return; + } + if (!this.#handler.wasEverConnected) { + this.#openedPromise.reject(new WebSocketError("Socket never opened")); + } + const result = this.#parser?.closingInfo; + let code = result?.code ?? 1005; + if (!this.#handler.closeState.has(sentCloseFrameState.SENT) && !this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { + code = 1006; + } + const reason = result?.reason == null ? "" : utf8DecodeBytes(Buffer.from(result.reason)); + if (wasClean) { + this.#readableStreamController.close(); + this.#writableStreamController.error(new DOMException("A closed WebSocketStream cannot be written to", "InvalidStateError")); + this.#closedPromise.resolve({ + closeCode: code, + reason + }); + } else { + const error3 = createUnvalidatedWebSocketError("unclean close", code, reason); + this.#readableStreamController?.error(error3); + this.#writableStreamController?.error(error3); + this.#closedPromise.reject(error3); + } + } + #closeUsingReason(reason) { + let code = null; + let reasonString = ""; + if (webidl.is.WebSocketError(reason)) { + code = reason.closeCode; + reasonString = reason.reason; + } + closeWebSocketConnection(this.#handler, code, reasonString); + } + // To cancel a WebSocketStream stream given reason , close using reason giving stream and reason . + #cancel(reason) { + this.#closeUsingReason(reason); + } + }; + Object.defineProperties(WebSocketStream.prototype, { + url: kEnumerableProperty, + opened: kEnumerableProperty, + closed: kEnumerableProperty, + close: kEnumerableProperty, + [Symbol.toStringTag]: { + value: "WebSocketStream", + writable: false, + enumerable: false, + configurable: true + } + }); + webidl.converters.WebSocketStreamOptions = webidl.dictionaryConverter([ + { + key: "protocols", + converter: webidl.sequenceConverter(webidl.converters.USVString), + defaultValue: () => [] + }, + { + key: "signal", + converter: webidl.nullableConverter(webidl.converters.AbortSignal), + defaultValue: () => null + } + ]); + webidl.converters.WebSocketCloseInfo = webidl.dictionaryConverter([ + { + key: "closeCode", + converter: (V) => webidl.converters["unsigned short"](V, webidl.attributes.EnforceRange) + }, + { + key: "reason", + converter: webidl.converters.USVString, + defaultValue: () => "" + } + ]); + webidl.converters.WebSocketStreamWrite = function(V) { + if (typeof V === "string") { + return webidl.converters.USVString(V); + } + return webidl.converters.BufferSource(V); + }; + module2.exports = { WebSocketStream }; } }); // node_modules/undici/lib/web/eventsource/util.js -var require_util8 = __commonJS({ +var require_util6 = __commonJS({ "node_modules/undici/lib/web/eventsource/util.js"(exports2, module2) { "use strict"; function isValidLastEventId(value) { @@ -18439,15 +25904,9 @@ var require_util8 = __commonJS({ } return true; } - function delay2(ms) { - return new Promise((resolve15) => { - setTimeout(resolve15, ms).unref(); - }); - } module2.exports = { isValidLastEventId, - isASCIINumber, - delay: delay2 + isASCIINumber }; } }); @@ -18456,18 +25915,62 @@ var require_util8 = __commonJS({ var require_eventsource_stream = __commonJS({ "node_modules/undici/lib/web/eventsource/eventsource-stream.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var { Transform: Transform5 } = require("node:stream"); - var { isASCIINumber, isValidLastEventId } = require_util8(); + var { isASCIINumber, isValidLastEventId } = require_util6(); var BOM = [239, 187, 191]; var LF = 10; var CR = 13; var COLON = 58; var SPACE = 32; + var defaultMaxEventSize = buffer.kStringMaxLength; + var DATA = Buffer.from("data"); + var EVENT = Buffer.from("event"); + var ID2 = Buffer.from("id"); + var RETRY = Buffer.from("retry"); + var minParserItems = 1024; + var maxParserItems = 131072; + var bytesPerParserItem = 128; + function isASCIINumberBytes(buffer2, start) { + if (start >= buffer2.length) { + return false; + } + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] < 48 || buffer2[i] > 57) { + return false; + } + } + return true; + } + function isValidLastEventIdBytes(buffer2, start) { + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] === 0) { + return false; + } + } + return true; + } + function isFieldName(line, length, field) { + if (length !== field.length) { + return false; + } + for (let i = 0; i < length; i++) { + if (line[i] !== field[i]) { + return false; + } + } + return true; + } + function createMaxEventSizeExceededError() { + const error3 = new Error("EventSource message size exceeded"); + error3.aborted = false; + return error3; + } var EventSourceStream = class extends Transform5 { /** * @type {eventSourceSettings} */ - state = null; + state; /** * Leading byte-order-mark check. * @type {boolean} @@ -18482,10 +25985,20 @@ var require_eventsource_stream = __commonJS({ */ eventEndCheck = false; /** - * @type {Buffer} + * @type {Buffer[]} */ - buffer = null; + chunks = []; + chunkIndex = 0; pos = 0; + lineChunkIndex = 0; + linePos = 0; + lineLength = 0; + eventSize = 0; + eventFieldSizes = { data: 0, event: 0, id: 0, retry: 0 }; + dataLineCount = 0; + maxEventSize; + maxDataLines; + maxBufferedChunks; event = { data: void 0, event: void 0, @@ -18494,13 +26007,19 @@ var require_eventsource_stream = __commonJS({ }; /** * @param {object} options - * @param {eventSourceSettings} options.eventSourceSettings - * @param {Function} [options.push] + * @param {boolean} [options.readableObjectMode] + * @param {number} [options.maxEventSize] + * @param {eventSourceSettings} [options.eventSourceSettings] + * @param {(chunk: any, encoding?: BufferEncoding | undefined) => boolean} [options.push] */ constructor(options = {}) { options.readableObjectMode = true; super(options); this.state = options.eventSourceSettings || {}; + this.maxEventSize = options.maxEventSize ?? defaultMaxEventSize; + const parserItemLimit = this.maxEventSize > 0 ? Math.min(maxParserItems, Math.max(minParserItems, Math.floor(this.maxEventSize / bytesPerParserItem))) : 0; + this.maxDataLines = parserItemLimit; + this.maxBufferedChunks = parserItemLimit; if (options.push) { this.push = options.push; } @@ -18516,63 +26035,34 @@ var require_eventsource_stream = __commonJS({ callback(); return; } - if (this.buffer) { - this.buffer = Buffer.concat([this.buffer, chunk]); - } else { - this.buffer = chunk; + if (this.maxEventSize > 0 && this.chunks.length >= this.maxBufferedChunks && chunk[0] !== LF && chunk[0] !== CR) { + callback(createMaxEventSizeExceededError()); + return; } + this.chunks.push(chunk); if (this.checkBOM) { - switch (this.buffer.length) { - case 1: - if (this.buffer[0] === BOM[0]) { - callback(); - return; - } - this.checkBOM = false; - callback(); - return; - case 2: - if (this.buffer[0] === BOM[0] && this.buffer[1] === BOM[1]) { - callback(); - return; - } - this.checkBOM = false; - break; - case 3: - if (this.buffer[0] === BOM[0] && this.buffer[1] === BOM[1] && this.buffer[2] === BOM[2]) { - this.buffer = Buffer.alloc(0); - this.checkBOM = false; - callback(); - return; - } - this.checkBOM = false; - break; - default: - if (this.buffer[0] === BOM[0] && this.buffer[1] === BOM[1] && this.buffer[2] === BOM[2]) { - this.buffer = this.buffer.subarray(3); - } - this.checkBOM = false; - break; + if (this.handleBOM()) { + callback(); + return; } } - while (this.pos < this.buffer.length) { + while (this.hasCurrentByte()) { + const byte = this.currentByte(); if (this.eventEndCheck) { if (this.crlfCheck) { - if (this.buffer[this.pos] === LF) { - this.buffer = this.buffer.subarray(this.pos + 1); - this.pos = 0; + if (byte === LF) { this.crlfCheck = false; + this.consumeCurrentByte(); continue; } this.crlfCheck = false; } - if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) { - if (this.buffer[this.pos] === CR) { + if (byte === LF || byte === CR) { + if (byte === CR) { this.crlfCheck = true; } - this.buffer = this.buffer.subarray(this.pos + 1); - this.pos = 0; - if (this.event.data !== void 0 || this.event.event || this.event.id || this.event.retry) { + this.consumeCurrentByte(); + if (this.hasPendingEvent()) { this.processEvent(this.event); } this.clearEvent(); @@ -18581,23 +26071,36 @@ var require_eventsource_stream = __commonJS({ this.eventEndCheck = false; continue; } - if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) { - if (this.buffer[this.pos] === CR) { + if (byte === LF || byte === CR) { + if (byte === CR) { this.crlfCheck = true; } - this.parseLine(this.buffer.subarray(0, this.pos), this.event); - this.buffer = this.buffer.subarray(this.pos + 1); - this.pos = 0; + try { + this.parseLine(this.readLine(), this.event); + } catch (error3) { + callback(error3); + return; + } + this.consumeCurrentByte(); this.eventEndCheck = true; continue; } - this.pos++; + if (this.maxEventSize > 0 && ++this.lineLength > this.maxEventSize + 7) { + callback(createMaxEventSizeExceededError()); + return; + } + this.advanceCursor(); } callback(); } + _destroy(error3, callback) { + this.chunks.length = 0; + this.clearEvent(); + super._destroy(error3, callback); + } /** * @param {Buffer} line - * @param {EventStreamEvent} event + * @param {EventSourceStreamEvent} event */ parseLine(line, event) { if (line.length === 0) { @@ -18607,44 +26110,60 @@ var require_eventsource_stream = __commonJS({ if (colonPosition === 0) { return; } - let field = ""; - let value = ""; + let fieldLength = line.length; + let valueStart = line.length; if (colonPosition !== -1) { - field = line.subarray(0, colonPosition).toString("utf8"); - let valueStart = colonPosition + 1; + fieldLength = colonPosition; + valueStart = colonPosition + 1; if (line[valueStart] === SPACE) { ++valueStart; } - value = line.subarray(valueStart).toString("utf8"); - } else { - field = line.toString("utf8"); - value = ""; } - switch (field) { - case "data": - if (event[field] === void 0) { - event[field] = value; - } else { - event[field] += ` + if (isFieldName(line, fieldLength, DATA)) { + if (this.maxEventSize > 0 && this.dataLineCount >= this.maxDataLines) { + throw createMaxEventSizeExceededError(); + } + const valueBytes = line.length - valueStart; + const dataSize = this.eventFieldSizes.data + (event.data === void 0 ? 0 : 1) + valueBytes; + this.setEventFieldSize("data", dataSize); + const value = line.toString("utf8", valueStart); + if (event.data === void 0) { + event.data = value; + } else { + event.data += ` ${value}`; - } - break; - case "retry": - if (isASCIINumber(value)) { - event[field] = value; - } - break; - case "id": - if (isValidLastEventId(value)) { - event[field] = value; - } - break; - case "event": - if (value.length > 0) { - event[field] = value; - } - break; + } + this.dataLineCount++; + return; + } + if (isFieldName(line, fieldLength, RETRY)) { + if (isASCIINumberBytes(line, valueStart)) { + this.setEventFieldSize("retry", line.length - valueStart); + event.retry = line.toString("utf8", valueStart); + } + return; + } + if (isFieldName(line, fieldLength, ID2)) { + if (isValidLastEventIdBytes(line, valueStart)) { + this.setEventFieldSize("id", line.length - valueStart); + event.id = line.toString("utf8", valueStart); + } + return; + } + if (isFieldName(line, fieldLength, EVENT)) { + if (valueStart < line.length) { + this.setEventFieldSize("event", line.length - valueStart); + event.event = line.toString("utf8", valueStart); + } + } + } + setEventFieldSize(field, size) { + const eventSize = this.eventSize - this.eventFieldSizes[field] + size; + if (this.maxEventSize > 0 && eventSize > this.maxEventSize) { + throw createMaxEventSizeExceededError(); } + this.eventSize = eventSize; + this.eventFieldSizes[field] = size; } /** * @param {EventSourceStreamEvent} event @@ -18653,7 +26172,7 @@ ${value}`; if (event.retry && isASCIINumber(event.retry)) { this.state.reconnectionTime = parseInt(event.retry, 10); } - if (event.id && isValidLastEventId(event.id)) { + if (event.id !== void 0 && isValidLastEventId(event.id)) { this.state.lastEventId = event.id; } if (event.data !== void 0) { @@ -18668,12 +26187,128 @@ ${value}`; } } clearEvent() { - this.event = { - data: void 0, - event: void 0, - id: void 0, - retry: void 0 - }; + this.event.data = void 0; + this.event.event = void 0; + this.event.id = void 0; + this.event.retry = void 0; + this.eventSize = 0; + this.dataLineCount = 0; + this.eventFieldSizes.data = 0; + this.eventFieldSizes.event = 0; + this.eventFieldSizes.id = 0; + this.eventFieldSizes.retry = 0; + } + hasPendingEvent() { + return this.event.data !== void 0 || this.event.event !== void 0 || this.event.id !== void 0 || this.event.retry !== void 0; + } + hasCurrentByte() { + return this.chunkIndex < this.chunks.length && this.pos < this.chunks[this.chunkIndex].length; + } + currentByte() { + return this.chunks[this.chunkIndex][this.pos]; + } + consumeCurrentByte() { + this.advanceCursor(); + this.syncLineStartToCursor(); + } + advanceCursor() { + this.pos++; + while (this.chunkIndex < this.chunks.length && this.pos >= this.chunks[this.chunkIndex].length) { + this.chunkIndex++; + this.pos = 0; + } + } + syncLineStartToCursor() { + this.lineChunkIndex = this.chunkIndex; + this.linePos = this.pos; + this.lineLength = 0; + this.dropConsumedChunks(); + } + dropConsumedChunks() { + if (this.lineChunkIndex > 0) { + const consumed = this.lineChunkIndex; + this.chunks.splice(0, consumed); + this.lineChunkIndex = 0; + this.chunkIndex -= consumed; + } + if (this.chunkIndex === this.chunks.length) { + this.chunks.length = 0; + this.chunkIndex = 0; + this.pos = 0; + this.lineChunkIndex = 0; + this.linePos = 0; + } + } + readLine() { + if (this.lineChunkIndex === this.chunkIndex) { + return this.chunks[this.chunkIndex].subarray(this.linePos, this.pos); + } + const chunks = []; + let length = 0; + for (let i = this.lineChunkIndex; i <= this.chunkIndex; i++) { + const chunk = this.chunks[i]; + const start = i === this.lineChunkIndex ? this.linePos : 0; + const end = i === this.chunkIndex ? this.pos : chunk.length; + const slice = chunk.subarray(start, end); + length += slice.length; + chunks.push(slice); + } + return Buffer.concat(chunks, length); + } + peekBufferedByte(offset) { + let chunkIndex = this.lineChunkIndex; + let pos = this.linePos; + while (chunkIndex < this.chunks.length) { + const chunk = this.chunks[chunkIndex]; + const remaining = chunk.length - pos; + if (offset < remaining) { + return chunk[pos + offset]; + } + offset -= remaining; + chunkIndex++; + pos = 0; + } + } + discardLeadingBytes(count) { + while (count > 0 && this.lineChunkIndex < this.chunks.length) { + const chunk = this.chunks[this.lineChunkIndex]; + const remaining = chunk.length - this.linePos; + if (count < remaining) { + this.linePos += count; + count = 0; + } else { + count -= remaining; + this.lineChunkIndex++; + this.linePos = 0; + } + } + this.chunkIndex = this.lineChunkIndex; + this.pos = this.linePos; + this.dropConsumedChunks(); + } + handleBOM() { + const first = this.peekBufferedByte(0); + const second = this.peekBufferedByte(1); + const third = this.peekBufferedByte(2); + if (second === void 0) { + if (first === BOM[0]) { + return true; + } + this.checkBOM = false; + return true; + } + if (third === void 0) { + if (first === BOM[0] && second === BOM[1]) { + return true; + } + this.checkBOM = false; + return false; + } + if (first === BOM[0] && second === BOM[1] && third === BOM[2]) { + this.discardLeadingBytes(3); + } + this.checkBOM = false; + return !this.hasCurrentByte(); } }; module2.exports = { @@ -18694,9 +26329,9 @@ var require_eventsource = __commonJS({ var { parseMIMEType } = require_data_url(); var { createFastMessageEvent } = require_events(); var { isNetworkError } = require_response(); - var { delay: delay2 } = require_util8(); var { kEnumerableProperty } = require_util(); var { environmentSettingsObject } = require_util2(); + var { getGlobalDispatcher } = require_global2(); var experimentalWarned = false; var defaultReconnectionTime = 3e3; var CONNECTING = 0; @@ -18710,8 +26345,11 @@ var require_eventsource = __commonJS({ error: null, message: null }; - #url = null; + #url; #withCredentials = false; + /** + * @type {ReadyState} + */ #readyState = CONNECTING; #request = null; #controller = null; @@ -18723,7 +26361,7 @@ var require_eventsource = __commonJS({ /** * Creates a new EventSource object. * @param {string} url - * @param {EventSourceInit} [eventSourceInitDict] + * @param {EventSourceInit} [eventSourceInitDict={}] * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#the-eventsource-interface */ constructor(url2, eventSourceInitDict = {}) { @@ -18737,12 +26375,12 @@ var require_eventsource = __commonJS({ code: "UNDICI-ES" }); } - url2 = webidl.converters.USVString(url2, prefix, "url"); + url2 = webidl.converters.USVString(url2); eventSourceInitDict = webidl.converters.EventSourceInitDict(eventSourceInitDict, prefix, "eventSourceInitDict"); - this.#dispatcher = eventSourceInitDict.dispatcher; + this.#dispatcher = eventSourceInitDict.node.dispatcher || eventSourceInitDict.dispatcher; this.#state = { lastEventId: "", - reconnectionTime: defaultReconnectionTime + reconnectionTime: eventSourceInitDict.node.reconnectionTime }; const settings = environmentSettingsObject; let urlRecord; @@ -18754,7 +26392,7 @@ var require_eventsource = __commonJS({ } this.#url = urlRecord.href; let corsAttributeState = ANONYMOUS; - if (eventSourceInitDict.withCredentials) { + if (eventSourceInitDict.withCredentials === true) { corsAttributeState = USE_CREDENTIALS; this.#withCredentials = true; } @@ -18777,7 +26415,7 @@ var require_eventsource = __commonJS({ /** * Returns the state of this EventSource object's connection. It can have the * values described below. - * @returns {0|1|2} + * @returns {ReadyState} * @readonly */ get readyState() { @@ -18806,11 +26444,9 @@ var require_eventsource = __commonJS({ dispatcher: this.#dispatcher }; const processEventSourceEndOfBody = (response) => { - if (isNetworkError(response)) { - this.dispatchEvent(new Event("error")); - this.close(); + if (!isNetworkError(response)) { + return this.#reconnect(); } - this.#reconnect(); }; fetchParams.processResponseEndOfBody = processEventSourceEndOfBody; fetchParams.processResponse = (response) => { @@ -18837,6 +26473,7 @@ var require_eventsource = __commonJS({ this.#state.origin = response.urlList[response.urlList.length - 1].origin; const eventSourceStream = new EventSourceStream({ eventSourceSettings: this.#state, + maxEventSize: this.#dispatcher.eventSourceOptions?.maxEventSize, push: (event) => { this.dispatchEvent(createFastMessageEvent( event.type, @@ -18859,18 +26496,19 @@ var require_eventsource = __commonJS({ } /** * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#sse-processing-model - * @returns {Promise} + * @returns {void} */ - async #reconnect() { + #reconnect() { if (this.#readyState === CLOSED) return; this.#readyState = CONNECTING; this.dispatchEvent(new Event("error")); - await delay2(this.#state.reconnectionTime); - if (this.#readyState !== CONNECTING) return; - if (this.#state.lastEventId.length) { - this.#request.headersList.set("last-event-id", this.#state.lastEventId, true); - } - this.#connect(); + setTimeout(() => { + if (this.#readyState !== CONNECTING) return; + if (this.#state.lastEventId.length) { + this.#request.headersList.set("last-event-id", this.#state.lastEventId, true); + } + this.#connect(); + }, this.#state.reconnectionTime)?.unref(); } /** * Closes the connection, if any, and sets the readyState attribute to @@ -18890,9 +26528,10 @@ var require_eventsource = __commonJS({ if (this.#events.open) { this.removeEventListener("open", this.#events.open); } - if (typeof fn === "function") { + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("open", listener); this.#events.open = fn; - this.addEventListener("open", fn); } else { this.#events.open = null; } @@ -18904,9 +26543,10 @@ var require_eventsource = __commonJS({ if (this.#events.message) { this.removeEventListener("message", this.#events.message); } - if (typeof fn === "function") { + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("message", listener); this.#events.message = fn; - this.addEventListener("message", fn); } else { this.#events.message = null; } @@ -18918,9 +26558,10 @@ var require_eventsource = __commonJS({ if (this.#events.error) { this.removeEventListener("error", this.#events.error); } - if (typeof fn === "function") { + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("error", listener); this.#events.error = fn; - this.addEventListener("error", fn); } else { this.#events.error = null; } @@ -18969,7 +26610,24 @@ var require_eventsource = __commonJS({ { key: "dispatcher", // undici only - converter: webidl.converters.any + converter: webidl.converters.any, + defaultValue: () => getGlobalDispatcher() + }, + { + key: "node", + // undici only + converter: webidl.dictionaryConverter([ + { + key: "reconnectionTime", + converter: webidl.converters["unsigned long"], + defaultValue: () => defaultReconnectionTime + }, + { + key: "dispatcher", + converter: webidl.converters.any + } + ]), + defaultValue: () => ({}) } ]); module2.exports = { @@ -18987,43 +26645,58 @@ var require_undici = __commonJS({ var Dispatcher = require_dispatcher(); var Pool = require_pool(); var BalancedPool = require_balanced_pool(); + var RoundRobinPool = require_round_robin_pool(); var Agent = require_agent(); var ProxyAgent2 = require_proxy_agent(); + var Socks5ProxyAgent = require_socks5_proxy_agent(); var EnvHttpProxyAgent = require_env_http_proxy_agent(); var RetryAgent = require_retry_agent(); + var H2CClient = require_h2c_client(); var errors = require_errors(); var util4 = require_util(); var { InvalidArgumentError } = errors; var api = require_api(); var buildConnector = require_connect(); var MockClient = require_mock_client(); + var { MockCallHistory, MockCallHistoryLog } = require_mock_call_history(); var MockAgent = require_mock_agent(); var MockPool = require_mock_pool(); + var SnapshotAgent = require_snapshot_agent(); var mockErrors = require_mock_errors(); var RetryHandler = require_retry_handler(); var { getGlobalDispatcher, setGlobalDispatcher } = require_global2(); var DecoratorHandler = require_decorator_handler(); var RedirectHandler = require_redirect_handler(); - var createRedirectInterceptor = require_redirect_interceptor(); Object.assign(Dispatcher.prototype, api); module2.exports.Dispatcher = Dispatcher; module2.exports.Client = Client; module2.exports.Pool = Pool; module2.exports.BalancedPool = BalancedPool; + module2.exports.RoundRobinPool = RoundRobinPool; module2.exports.Agent = Agent; module2.exports.ProxyAgent = ProxyAgent2; + module2.exports.Socks5ProxyAgent = Socks5ProxyAgent; module2.exports.EnvHttpProxyAgent = EnvHttpProxyAgent; module2.exports.RetryAgent = RetryAgent; + module2.exports.H2CClient = H2CClient; module2.exports.RetryHandler = RetryHandler; module2.exports.DecoratorHandler = DecoratorHandler; module2.exports.RedirectHandler = RedirectHandler; - module2.exports.createRedirectInterceptor = createRedirectInterceptor; module2.exports.interceptors = { redirect: require_redirect(), + responseError: require_response_error(), retry: require_retry(), dump: require_dump(), - dns: require_dns() + dns: require_dns(), + cache: require_cache2(), + decompress: require_decompress(), + deduplicate: require_deduplicate() }; + module2.exports.cacheStores = { + MemoryCacheStore: require_memory_cache_store() + }; + var SqliteCacheStore = require_sqlite_cache_store(); + module2.exports.cacheStores.SqliteCacheStore = SqliteCacheStore; module2.exports.buildConnector = buildConnector; module2.exports.errors = errors; module2.exports.util = { @@ -19072,52 +26745,90 @@ var require_undici = __commonJS({ module2.exports.setGlobalDispatcher = setGlobalDispatcher; module2.exports.getGlobalDispatcher = getGlobalDispatcher; var fetchImpl = require_fetch().fetch; - module2.exports.fetch = async function fetch(init2, options = void 0) { - try { - return await fetchImpl(init2, options); - } catch (err) { - if (err && typeof err === "object") { - Error.captureStackTrace(err); + var currentFilename = typeof __filename !== "undefined" ? __filename : void 0; + function appendFetchStackTrace(err, filename) { + if (!err || typeof err !== "object") { + return; + } + const stack = typeof err.stack === "string" ? err.stack : ""; + const normalizedFilename = filename.replace(/\\/g, "/"); + if (stack && (stack.includes(filename) || stack.includes(normalizedFilename))) { + return; + } + const capture = {}; + Error.captureStackTrace(capture, appendFetchStackTrace); + if (!capture.stack) { + return; + } + const captureLines = capture.stack.split("\n").slice(1).join("\n"); + err.stack = stack ? `${stack} +${captureLines}` : capture.stack; + } + module2.exports.fetch = function fetch(init2, options = void 0) { + return fetchImpl(init2, options).catch((err) => { + if (currentFilename) { + appendFetchStackTrace(err, currentFilename); + } else if (err && typeof err === "object") { + Error.captureStackTrace(err, module2.exports.fetch); } throw err; - } + }); }; module2.exports.Headers = require_headers().Headers; module2.exports.Response = require_response().Response; module2.exports.Request = require_request2().Request; module2.exports.FormData = require_formdata().FormData; - module2.exports.File = globalThis.File ?? require("node:buffer").File; - module2.exports.FileReader = require_filereader().FileReader; var { setGlobalOrigin, getGlobalOrigin } = require_global(); module2.exports.setGlobalOrigin = setGlobalOrigin; module2.exports.getGlobalOrigin = getGlobalOrigin; var { CacheStorage } = require_cachestorage(); - var { kConstruct } = require_symbols4(); + var { kConstruct } = require_symbols(); module2.exports.caches = new CacheStorage(kConstruct); - var { deleteCookie, getCookies, getSetCookies, setCookie } = require_cookies(); + var { deleteCookie, getCookies, getSetCookies, setCookie, parseCookie } = require_cookies(); module2.exports.deleteCookie = deleteCookie; module2.exports.getCookies = getCookies; module2.exports.getSetCookies = getSetCookies; module2.exports.setCookie = setCookie; + module2.exports.parseCookie = parseCookie; var { parseMIMEType, serializeAMimeType } = require_data_url(); module2.exports.parseMIMEType = parseMIMEType; module2.exports.serializeAMimeType = serializeAMimeType; var { CloseEvent, ErrorEvent, MessageEvent } = require_events(); - module2.exports.WebSocket = require_websocket().WebSocket; + var { WebSocket, ping } = require_websocket(); + module2.exports.WebSocket = WebSocket; module2.exports.CloseEvent = CloseEvent; module2.exports.ErrorEvent = ErrorEvent; module2.exports.MessageEvent = MessageEvent; + module2.exports.ping = ping; + module2.exports.WebSocketStream = require_websocketstream().WebSocketStream; + module2.exports.WebSocketError = require_websocketerror().WebSocketError; module2.exports.request = makeDispatcher(api.request); module2.exports.stream = makeDispatcher(api.stream); module2.exports.pipeline = makeDispatcher(api.pipeline); module2.exports.connect = makeDispatcher(api.connect); module2.exports.upgrade = makeDispatcher(api.upgrade); module2.exports.MockClient = MockClient; + module2.exports.MockCallHistory = MockCallHistory; + module2.exports.MockCallHistoryLog = MockCallHistoryLog; module2.exports.MockPool = MockPool; module2.exports.MockAgent = MockAgent; + module2.exports.SnapshotAgent = SnapshotAgent; module2.exports.mockErrors = mockErrors; var { EventSource } = require_eventsource(); module2.exports.EventSource = EventSource; + function install() { + globalThis.fetch = module2.exports.fetch; + globalThis.Headers = module2.exports.Headers; + globalThis.Response = module2.exports.Response; + globalThis.Request = module2.exports.Request; + globalThis.FormData = module2.exports.FormData; + globalThis.WebSocket = module2.exports.WebSocket; + globalThis.CloseEvent = module2.exports.CloseEvent; + globalThis.ErrorEvent = module2.exports.ErrorEvent; + globalThis.MessageEvent = module2.exports.MessageEvent; + globalThis.EventSource = module2.exports.EventSource; + } + module2.exports.install = install; } }); @@ -41424,7 +49135,7 @@ var require_createFile = __commonJS({ createFile: () => createFile2 }); module2.exports = __toCommonJS2(createFile_exports); - var import_file7 = require_file2(); + var import_file7 = require_file(); function createFile2(content, name, options = {}) { return (0, import_file7.createRawFile)(content, name, options); } @@ -41432,7 +49143,7 @@ var require_createFile = __commonJS({ }); // node_modules/@azure/core-rest-pipeline/dist/commonjs/util/file.js -var require_file2 = __commonJS({ +var require_file = __commonJS({ "node_modules/@azure/core-rest-pipeline/dist/commonjs/util/file.js"(exports2, module2) { var __defProp2 = Object.defineProperty; var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor; @@ -41564,7 +49275,7 @@ var require_multipartPolicy2 = __commonJS({ }); module2.exports = __toCommonJS2(multipartPolicy_exports); var import_policies = require_internal2(); - var import_file7 = require_file2(); + var import_file7 = require_file(); var multipartPolicyName2 = import_policies.multipartPolicyName; function multipartPolicy2() { const tspPolicy = (0, import_policies.multipartPolicy)(); @@ -44079,7 +51790,7 @@ var require_commonjs6 = __commonJS({ var import_ndJsonPolicy = require_ndJsonPolicy(); var import_auxiliaryAuthenticationHeaderPolicy = require_auxiliaryAuthenticationHeaderPolicy(); var import_agentPolicy = require_agentPolicy2(); - var import_file7 = require_file2(); + var import_file7 = require_file(); } }); @@ -46306,7 +54017,7 @@ var require_commonjs8 = __commonJS({ }); // node_modules/@azure/core-http-compat/dist/commonjs/util.js -var require_util9 = __commonJS({ +var require_util7 = __commonJS({ "node_modules/@azure/core-http-compat/dist/commonjs/util.js"(exports2, module2) { var __defProp2 = Object.defineProperty; var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor; @@ -46597,7 +54308,7 @@ var require_response2 = __commonJS({ }); module2.exports = __toCommonJS2(response_exports); var import_core_rest_pipeline = require_commonjs6(); - var import_util59 = require_util9(); + var import_util59 = require_util7(); var originalResponse = /* @__PURE__ */ Symbol("Original FullOperationResponse"); function toCompatResponse2(response, options) { let request3 = (0, import_util59.toWebResourceLike)(response.request); @@ -46749,7 +54460,7 @@ var require_requestPolicyFactoryPolicy = __commonJS({ requestPolicyFactoryPolicyName: () => requestPolicyFactoryPolicyName2 }); module2.exports = __toCommonJS2(requestPolicyFactoryPolicy_exports); - var import_util59 = require_util9(); + var import_util59 = require_util7(); var import_response = require_response2(); var HttpPipelineLogLevel2 = /* @__PURE__ */ ((HttpPipelineLogLevel22) => { HttpPipelineLogLevel22[HttpPipelineLogLevel22["ERROR"] = 1] = "ERROR"; @@ -46815,7 +54526,7 @@ var require_httpClientAdapter = __commonJS({ }); module2.exports = __toCommonJS2(httpClientAdapter_exports); var import_response = require_response2(); - var import_util59 = require_util9(); + var import_util59 = require_util7(); function convertHttpClient2(requestPolicyClient) { return { sendRequest: async (request3) => { @@ -46866,7 +54577,7 @@ var require_commonjs9 = __commonJS({ var import_requestPolicyFactoryPolicy = require_requestPolicyFactoryPolicy(); var import_disableKeepAlivePolicy = require_disableKeepAlivePolicy(); var import_httpClientAdapter = require_httpClientAdapter(); - var import_util59 = require_util9(); + var import_util59 = require_util7(); } }); @@ -52145,7 +59856,7 @@ var require_StructuredMessageDecodingStream = __commonJS({ }); // node_modules/@azure/storage-common/dist/commonjs/cache.js -var require_cache2 = __commonJS({ +var require_cache4 = __commonJS({ "node_modules/@azure/storage-common/dist/commonjs/cache.js"(exports2, module2) { var __defProp2 = Object.defineProperty; var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor; @@ -54584,7 +62295,7 @@ var require_indexPlatform = __commonJS({ __reExport(indexPlatform_exports, require_StructuredMessageEncodingStream(), module2.exports); __reExport(indexPlatform_exports, require_StructuredMessageDecodingStream(), module2.exports); __reExport(indexPlatform_exports, require_StorageCRC64Calculator(), module2.exports); - var import_cache = require_cache2(); + var import_cache = require_cache4(); __reExport(indexPlatform_exports, require_StorageResponseFormat(), module2.exports); __reExport(indexPlatform_exports, require_StorageBrowserPolicyFactory(), module2.exports); __reExport(indexPlatform_exports, require_AnonymousCredential(), module2.exports); @@ -104743,7 +112454,7 @@ var require_cachemetadata = __commonJS({ }); // node_modules/@actions/cache/lib/generated/results/api/v1/cache.js -var require_cache3 = __commonJS({ +var require_cache5 = __commonJS({ "node_modules/@actions/cache/lib/generated/results/api/v1/cache.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); @@ -105228,7 +112939,7 @@ var require_cache_twirp_client = __commonJS({ "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.CacheServiceClientProtobuf = exports2.CacheServiceClientJSON = void 0; - var cache_1 = require_cache3(); + var cache_1 = require_cache5(); var CacheServiceClientJSON = class { constructor(rpc) { this.rpc = rpc; @@ -105296,7 +113007,7 @@ var require_cache_twirp_client = __commonJS({ }); // node_modules/@actions/cache/lib/internal/shared/util.js -var require_util10 = __commonJS({ +var require_util8 = __commonJS({ "node_modules/@actions/cache/lib/internal/shared/util.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); @@ -105373,7 +113084,7 @@ var require_cacheTwirpClient = __commonJS({ var auth_1 = require_auth(); var http_client_1 = require_lib(); var cache_twirp_client_1 = require_cache_twirp_client(); - var util_1 = require_util10(); + var util_1 = require_util8(); var CacheServiceClient = class { constructor(userAgent2, maxAttempts, baseRetryIntervalMilliseconds, retryMultiplier) { this.maxAttempts = 5; @@ -105788,7 +113499,7 @@ var require_tar = __commonJS({ }); // node_modules/@actions/cache/lib/cache.js -var require_cache4 = __commonJS({ +var require_cache6 = __commonJS({ "node_modules/@actions/cache/lib/cache.js"(exports2) { "use strict"; var __createBinding2 = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) { @@ -112961,7 +120672,7 @@ var require_jwt_decode_cjs = __commonJS({ }); // node_modules/@actions/artifact/lib/internal/shared/util.js -var require_util11 = __commonJS({ +var require_util9 = __commonJS({ "node_modules/@actions/artifact/lib/internal/shared/util.js"(exports2) { "use strict"; var __createBinding2 = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) { @@ -113101,7 +120812,7 @@ var require_artifact_twirp_client2 = __commonJS({ var config_1 = require_config2(); var user_agent_1 = require_user_agent2(); var errors_1 = require_errors3(); - var util_1 = require_util11(); + var util_1 = require_util9(); var ArtifactHttpClient = class { constructor(userAgent2, maxAttempts, baseRetryIntervalMilliseconds, retryMultiplier) { this.maxAttempts = 5; @@ -117352,7 +125063,7 @@ var require_safe_buffer = __commonJS({ }); // node_modules/core-util-is/lib/util.js -var require_util12 = __commonJS({ +var require_util10 = __commonJS({ "node_modules/core-util-is/lib/util.js"(exports2) { function isArray2(arg) { if (Array.isArray) { @@ -117638,7 +125349,7 @@ var require_stream_writable = __commonJS({ var asyncWrite = !process.browser && ["v0.10", "v0.9."].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick; var Duplex4; Writable.WritableState = WritableState; - var util4 = Object.create(require_util12()); + var util4 = Object.create(require_util10()); util4.inherits = require_inherits(); var internalUtil = { deprecate: require_node2() @@ -118074,7 +125785,7 @@ var require_stream_duplex = __commonJS({ return keys2; }; module2.exports = Duplex4; - var util4 = Object.create(require_util12()); + var util4 = Object.create(require_util10()); util4.inherits = require_inherits(); var Readable4 = require_stream_readable(); var Writable = require_stream_writable(); @@ -118399,7 +126110,7 @@ var require_stream_readable = __commonJS({ function _isUint8Array(obj) { return Buffer3.isBuffer(obj) || obj instanceof OurUint8Array; } - var util4 = Object.create(require_util12()); + var util4 = Object.create(require_util10()); util4.inherits = require_inherits(); var debugUtil = require("util"); var debug6 = void 0; @@ -119068,7 +126779,7 @@ var require_stream_transform = __commonJS({ "use strict"; module2.exports = Transform5; var Duplex4 = require_stream_duplex(); - var util4 = Object.create(require_util12()); + var util4 = Object.create(require_util10()); util4.inherits = require_inherits(); util4.inherits(Transform5, Duplex4); function afterTransform(er, data) { @@ -119168,7 +126879,7 @@ var require_stream_passthrough = __commonJS({ "use strict"; module2.exports = PassThrough3; var Transform5 = require_stream_transform(); - var util4 = Object.create(require_util12()); + var util4 = Object.create(require_util10()); util4.inherits = require_inherits(); util4.inherits(PassThrough3, Transform5); function PassThrough3(options) { @@ -121177,7 +128888,7 @@ var require_abort_controller = __commonJS({ }); // node_modules/readable-stream/lib/ours/util.js -var require_util13 = __commonJS({ +var require_util11 = __commonJS({ "node_modules/readable-stream/lib/ours/util.js"(exports2, module2) { "use strict"; var bufferModule = require("buffer"); @@ -121339,8 +129050,8 @@ var require_validators = __commonJS({ hideStackFrames, codes: { ERR_SOCKET_BAD_PORT, ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_VALUE, ERR_OUT_OF_RANGE, ERR_UNKNOWN_SIGNAL } } = require_errors4(); - var { normalizeEncoding } = require_util13(); - var { isAsyncFunction, isArrayBufferView } = require_util13().types; + var { normalizeEncoding } = require_util11(); + var { isAsyncFunction, isArrayBufferView } = require_util11().types; var signals = {}; function isInt32(value) { return value === (value | 0); @@ -121802,7 +129513,7 @@ var require_end_of_stream = __commonJS({ var process2 = require_process(); var { AbortError: AbortError2, codes } = require_errors4(); var { ERR_INVALID_ARG_TYPE, ERR_STREAM_PREMATURE_CLOSE } = codes; - var { kEmptyObject, once } = require_util13(); + var { kEmptyObject, once } = require_util11(); var { validateAbortSignal, validateFunction, validateObject, validateBoolean } = require_validators(); var { Promise: Promise2, PromisePrototypeThen, SymbolDispose } = require_primordials(); var { @@ -121975,7 +129686,7 @@ var require_end_of_stream = __commonJS({ if (options.signal.aborted) { process2.nextTick(abort); } else { - addAbortListener = addAbortListener || require_util13().addAbortListener; + addAbortListener = addAbortListener || require_util11().addAbortListener; const disposable = addAbortListener(options.signal, abort); const originalCallback = callback; callback = once((...args) => { @@ -122002,7 +129713,7 @@ var require_end_of_stream = __commonJS({ if (options.signal.aborted) { process2.nextTick(abort); } else { - addAbortListener = addAbortListener || require_util13().addAbortListener; + addAbortListener = addAbortListener || require_util11().addAbortListener; const disposable = addAbortListener(options.signal, abort); const originalCallback = callback; callback = once((...args) => { @@ -122432,7 +130143,7 @@ var require_add_abort_signal = __commonJS({ if (signal.aborted) { onAbort(); } else { - addAbortListener = addAbortListener || require_util13().addAbortListener; + addAbortListener = addAbortListener || require_util11().addAbortListener; const disposable = addAbortListener(signal, onAbort); eos(stream2, disposable[SymbolDispose]); } @@ -122447,7 +130158,7 @@ var require_buffer_list = __commonJS({ "use strict"; var { StringPrototypeSlice, SymbolIterator, TypedArrayPrototypeSet, Uint8Array: Uint8Array2 } = require_primordials(); var { Buffer: Buffer3 } = require("buffer"); - var { inspect } = require_util13(); + var { inspect } = require_util11(); module2.exports = class BufferList { constructor() { this.head = null; @@ -123055,7 +130766,7 @@ var require_readable3 = __commonJS({ var { Buffer: Buffer3 } = require("buffer"); var { addAbortSignal } = require_add_abort_signal(); var eos = require_end_of_stream(); - var debug6 = require_util13().debuglog("stream", (fn) => { + var debug6 = require_util11().debuglog("stream", (fn) => { debug6 = fn; }); var BufferList = require_buffer_list(); @@ -124641,7 +132352,7 @@ var require_duplexify = __commonJS({ var Duplex4 = require_duplex(); var Readable4 = require_readable3(); var Writable = require_writable(); - var { createDeferredPromise } = require_util13(); + var { createDeferredPromise } = require_util11(); var from = require_from(); var Blob2 = globalThis.Blob || bufferModule.Blob; var isBlob = typeof Blob2 !== "undefined" ? function isBlob2(b) { @@ -125207,7 +132918,7 @@ var require_pipeline4 = __commonJS({ var process2 = require_process(); var { ArrayIsArray, Promise: Promise2, SymbolAsyncIterator, SymbolDispose } = require_primordials(); var eos = require_end_of_stream(); - var { once } = require_util13(); + var { once } = require_util11(); var destroyImpl = require_destroy2(); var Duplex4 = require_duplex(); var { @@ -125376,7 +133087,7 @@ var require_pipeline4 = __commonJS({ function abort() { finishImpl(new AbortError2()); } - addAbortListener = addAbortListener || require_util13().addAbortListener; + addAbortListener = addAbortListener || require_util11().addAbortListener; let disposable; if (outerSignal) { disposable = addAbortListener(outerSignal, abort); @@ -125838,7 +133549,7 @@ var require_operators = __commonJS({ var staticCompose = require_compose(); var { addAbortSignalNoValidate } = require_add_abort_signal(); var { isWritable, isNodeStream } = require_utils8(); - var { deprecate } = require_util13(); + var { deprecate } = require_util11(); var { ArrayPrototypePush, Boolean: Boolean2, @@ -125891,7 +133602,7 @@ var require_operators = __commonJS({ validateInteger(highWaterMark, "options.highWaterMark", 0); highWaterMark += concurrency; return async function* map2() { - const signal = require_util13().AbortSignalAny( + const signal = require_util11().AbortSignalAny( [options === null || options === void 0 ? void 0 : options.signal].filter(Boolean2) ); const stream2 = this; @@ -126277,7 +133988,7 @@ var require_stream2 = __commonJS({ var { ObjectDefineProperty, ObjectKeys, ReflectApply } = require_primordials(); var { promisify: { custom: customPromisify } - } = require_util13(); + } = require_util11(); var { streamReturningOperators, promiseReturningOperators } = require_operators(); var { codes: { ERR_ILLEGAL_CONSTRUCTOR } @@ -130277,7 +137988,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s)) retur }); // node_modules/archiver-utils/file.js -var require_file3 = __commonJS({ +var require_file2 = __commonJS({ "node_modules/archiver-utils/file.js"(exports2, module2) { var fs33 = require_graceful_fs(); var path30 = require("path"); @@ -130441,7 +138152,7 @@ var require_archiver_utils = __commonJS({ var Stream = require("stream").Stream; var PassThrough3 = require_ours().PassThrough; var utils = module2.exports = {}; - utils.file = require_file3(); + utils.file = require_file2(); utils.collectStream = function(source, callback) { var collection = []; var size = 0; @@ -131133,7 +138844,7 @@ var require_archive_entry = __commonJS({ }); // node_modules/@actions/artifact/node_modules/compress-commons/lib/archivers/zip/util.js -var require_util14 = __commonJS({ +var require_util12 = __commonJS({ "node_modules/@actions/artifact/node_modules/compress-commons/lib/archivers/zip/util.js"(exports2, module2) { var util4 = module2.exports = {}; util4.dateToDos = function(d, forceLocalTime) { @@ -131191,7 +138902,7 @@ var require_util14 = __commonJS({ // node_modules/@actions/artifact/node_modules/compress-commons/lib/archivers/zip/general-purpose-bit.js var require_general_purpose_bit = __commonJS({ "node_modules/@actions/artifact/node_modules/compress-commons/lib/archivers/zip/general-purpose-bit.js"(exports2, module2) { - var zipUtil = require_util14(); + var zipUtil = require_util12(); var DATA_DESCRIPTOR_FLAG2 = 1 << 3; var ENCRYPTION_FLAG2 = 1 << 0; var NUMBER_OF_SHANNON_FANO_TREES_FLAG2 = 1 << 2; @@ -131403,7 +139114,7 @@ var require_zip_archive_entry = __commonJS({ var GeneralPurposeBit2 = require_general_purpose_bit(); var UnixStat = require_unix_stat(); var constants = require_constants14(); - var zipUtil = require_util14(); + var zipUtil = require_util12(); var ZipArchiveEntry2 = module2.exports = function(name) { if (!(this instanceof ZipArchiveEntry2)) { return new ZipArchiveEntry2(name); @@ -131583,7 +139294,7 @@ var require_is_stream2 = __commonJS({ }); // node_modules/@actions/artifact/node_modules/compress-commons/lib/util/index.js -var require_util15 = __commonJS({ +var require_util13 = __commonJS({ "node_modules/@actions/artifact/node_modules/compress-commons/lib/util/index.js"(exports2, module2) { var Stream = require("stream").Stream; var PassThrough3 = require_ours().PassThrough; @@ -131611,7 +139322,7 @@ var require_archive_output_stream = __commonJS({ var isStream2 = require_is_stream2(); var Transform5 = require_ours().Transform; var ArchiveEntry2 = require_archive_entry(); - var util4 = require_util15(); + var util4 = require_util13(); var ArchiveOutputStream2 = module2.exports = function(options) { if (!(this instanceof ArchiveOutputStream2)) { return new ArchiveOutputStream2(options); @@ -131895,8 +139606,8 @@ var require_zip_archive_output_stream = __commonJS({ var ZipArchiveEntry2 = require_zip_archive_entry(); var GeneralPurposeBit2 = require_general_purpose_bit(); var constants = require_constants14(); - var util4 = require_util15(); - var zipUtil = require_util14(); + var util4 = require_util13(); + var zipUtil = require_util12(); var ZipArchiveOutputStream2 = module2.exports = function(options) { if (!(this instanceof ZipArchiveOutputStream2)) { return new ZipArchiveOutputStream2(options); @@ -135236,7 +142947,7 @@ var require_upload_artifact = __commonJS({ var path_and_artifact_name_validation_1 = require_path_and_artifact_name_validation(); var artifact_twirp_client_1 = require_artifact_twirp_client2(); var upload_zip_specification_1 = require_upload_zip_specification(); - var util_1 = require_util11(); + var util_1 = require_util9(); var blob_upload_1 = require_blob_upload(); var zip_1 = require_zip2(); var generated_1 = require_generated(); @@ -142015,7 +149726,7 @@ var require_download_artifact = __commonJS({ var config_1 = require_config2(); var artifact_twirp_client_1 = require_artifact_twirp_client2(); var generated_1 = require_generated(); - var util_1 = require_util11(); + var util_1 = require_util9(); var errors_1 = require_errors3(); var scrubQueryParameters = (url2) => { const parsed = new URL(url2); @@ -142400,7 +150111,7 @@ var require_get_artifact = __commonJS({ var utils_1 = require_utils10(); var retry_options_1 = require_retry_options(); var plugin_request_log_1 = require_dist_node11(); - var util_1 = require_util11(); + var util_1 = require_util9(); var user_agent_1 = require_user_agent2(); var artifact_twirp_client_1 = require_artifact_twirp_client2(); var generated_1 = require_generated(); @@ -142525,7 +150236,7 @@ var require_delete_artifact = __commonJS({ var plugin_request_log_1 = require_dist_node11(); var plugin_retry_1 = require_dist_node12(); var artifact_twirp_client_1 = require_artifact_twirp_client2(); - var util_1 = require_util11(); + var util_1 = require_util9(); var generated_1 = require_generated(); var get_artifact_1 = require_get_artifact(); var errors_1 = require_errors3(); @@ -142631,7 +150342,7 @@ var require_list_artifacts = __commonJS({ var plugin_request_log_1 = require_dist_node11(); var plugin_retry_1 = require_dist_node12(); var artifact_twirp_client_1 = require_artifact_twirp_client2(); - var util_1 = require_util11(); + var util_1 = require_util9(); var config_1 = require_config2(); var generated_1 = require_generated(); var maximumArtifactCount = (0, config_1.getMaxArtifactListCount)(); @@ -148351,7 +156062,7 @@ var require_baseN = __commonJS({ }); // node_modules/node-forge/lib/util.js -var require_util16 = __commonJS({ +var require_util14 = __commonJS({ "node_modules/node-forge/lib/util.js"(exports2, module2) { var forge = require_forge(); var baseN = require_baseN(); @@ -149735,7 +157446,7 @@ var require_util16 = __commonJS({ var require_cipher = __commonJS({ "node_modules/node-forge/lib/cipher.js"(exports2, module2) { var forge = require_forge(); - require_util16(); + require_util14(); module2.exports = forge.cipher = forge.cipher || {}; forge.cipher.algorithms = forge.cipher.algorithms || {}; forge.cipher.createCipher = function(algorithm, key) { @@ -149852,7 +157563,7 @@ var require_cipher = __commonJS({ var require_cipherModes = __commonJS({ "node_modules/node-forge/lib/cipherModes.js"(exports2, module2) { var forge = require_forge(); - require_util16(); + require_util14(); forge.cipher = forge.cipher || {}; var modes = module2.exports = forge.cipher.modes = forge.cipher.modes || {}; modes.ecb = function(options) { @@ -150504,7 +158215,7 @@ var require_aes = __commonJS({ var forge = require_forge(); require_cipher(); require_cipherModes(); - require_util16(); + require_util14(); module2.exports = forge.aes = forge.aes || {}; forge.aes.startEncrypting = function(key, iv, output, mode) { var cipher = _createCipher({ @@ -150922,7 +158633,7 @@ var require_oids = __commonJS({ var require_asn1 = __commonJS({ "node_modules/node-forge/lib/asn1.js"(exports2, module2) { var forge = require_forge(); - require_util16(); + require_util14(); require_oids(); var asn1 = module2.exports = forge.asn1 = forge.asn1 || {}; asn1.Class = { @@ -151751,7 +159462,7 @@ var require_hmac = __commonJS({ "node_modules/node-forge/lib/hmac.js"(exports2, module2) { var forge = require_forge(); require_md(); - require_util16(); + require_util14(); var hmac = module2.exports = forge.hmac = forge.hmac || {}; hmac.create = function() { var _key = null; @@ -151833,7 +159544,7 @@ var require_md5 = __commonJS({ "node_modules/node-forge/lib/md5.js"(exports2, module2) { var forge = require_forge(); require_md(); - require_util16(); + require_util14(); var md5 = module2.exports = forge.md5 = forge.md5 || {}; forge.md.md5 = forge.md.algorithms.md5 = md5; md5.create = function() { @@ -152124,7 +159835,7 @@ var require_md5 = __commonJS({ var require_pem = __commonJS({ "node_modules/node-forge/lib/pem.js"(exports2, module2) { var forge = require_forge(); - require_util16(); + require_util14(); var pem = module2.exports = forge.pem = forge.pem || {}; pem.encode = function(msg, options) { options = options || {}; @@ -152277,7 +159988,7 @@ var require_des = __commonJS({ var forge = require_forge(); require_cipher(); require_cipherModes(); - require_util16(); + require_util14(); module2.exports = forge.des = forge.des || {}; forge.des.startEncrypting = function(key, iv, output, mode) { var cipher = _createCipher({ @@ -152515,7 +160226,7 @@ var require_pbkdf2 = __commonJS({ var forge = require_forge(); require_hmac(); require_md(); - require_util16(); + require_util14(); var pkcs5 = forge.pkcs5 = forge.pkcs5 || {}; var crypto3; if (forge.util.isNodejs && !forge.options.usePureJavaScript) { @@ -152629,7 +160340,7 @@ var require_sha2562 = __commonJS({ "node_modules/node-forge/lib/sha256.js"(exports2, module2) { var forge = require_forge(); require_md(); - require_util16(); + require_util14(); var sha256 = module2.exports = forge.sha256 = forge.sha256 || {}; forge.md.sha256 = forge.md.algorithms.sha256 = sha256; sha256.create = function() { @@ -152861,7 +160572,7 @@ var require_sha2562 = __commonJS({ var require_prng = __commonJS({ "node_modules/node-forge/lib/prng.js"(exports2, module2) { var forge = require_forge(); - require_util16(); + require_util14(); var _crypto = null; if (forge.util.isNodejs && !forge.options.usePureJavaScript && !process.versions["node-webkit"]) { _crypto = require("crypto"); @@ -153104,7 +160815,7 @@ var require_random2 = __commonJS({ require_aes(); require_sha2562(); require_prng(); - require_util16(); + require_util14(); (function() { if (forge.random && forge.random.getBytes) { module2.exports = forge.random; @@ -153209,7 +160920,7 @@ var require_random2 = __commonJS({ var require_rc2 = __commonJS({ "node_modules/node-forge/lib/rc2.js"(exports2, module2) { var forge = require_forge(); - require_util16(); + require_util14(); var piTable = [ 217, 120, @@ -154859,7 +162570,7 @@ var require_sha1 = __commonJS({ "node_modules/node-forge/lib/sha1.js"(exports2, module2) { var forge = require_forge(); require_md(); - require_util16(); + require_util14(); var sha1 = module2.exports = forge.sha1 = forge.sha1 || {}; forge.md.sha1 = forge.md.algorithms.sha1 = sha1; sha1.create = function() { @@ -155054,7 +162765,7 @@ var require_sha1 = __commonJS({ var require_pkcs1 = __commonJS({ "node_modules/node-forge/lib/pkcs1.js"(exports2, module2) { var forge = require_forge(); - require_util16(); + require_util14(); require_random2(); require_sha1(); var pkcs1 = module2.exports = forge.pkcs1 = forge.pkcs1 || {}; @@ -155206,7 +162917,7 @@ var require_pkcs1 = __commonJS({ var require_prime = __commonJS({ "node_modules/node-forge/lib/prime.js"(exports2, module2) { var forge = require_forge(); - require_util16(); + require_util14(); require_jsbn(); require_random2(); (function() { @@ -155374,7 +163085,7 @@ var require_rsa = __commonJS({ require_pkcs1(); require_prime(); require_random2(); - require_util16(); + require_util14(); if (typeof BigInteger === "undefined") { BigInteger = forge.jsbn.BigInteger; } @@ -156579,7 +164290,7 @@ var require_pbe = __commonJS({ require_random2(); require_rc2(); require_rsa(); - require_util16(); + require_util14(); if (typeof BigInteger === "undefined") { BigInteger = forge.jsbn.BigInteger; } @@ -157347,7 +165058,7 @@ var require_pkcs7asn1 = __commonJS({ "node_modules/node-forge/lib/pkcs7asn1.js"(exports2, module2) { var forge = require_forge(); require_asn1(); - require_util16(); + require_util14(); var asn1 = forge.asn1; var p7v = module2.exports = forge.pkcs7asn1 = forge.pkcs7asn1 || {}; forge.pkcs7 = forge.pkcs7 || {}; @@ -157647,7 +165358,7 @@ var require_pkcs7asn1 = __commonJS({ var require_mgf1 = __commonJS({ "node_modules/node-forge/lib/mgf1.js"(exports2, module2) { var forge = require_forge(); - require_util16(); + require_util14(); forge.mgf = forge.mgf || {}; var mgf1 = module2.exports = forge.mgf.mgf1 = forge.mgf1 = forge.mgf1 || {}; mgf1.create = function(md2) { @@ -157693,7 +165404,7 @@ var require_pss = __commonJS({ "node_modules/node-forge/lib/pss.js"(exports2, module2) { var forge = require_forge(); require_random2(); - require_util16(); + require_util14(); var pss = module2.exports = forge.pss = forge.pss || {}; pss.create = function(options) { if (arguments.length === 3) { @@ -157820,7 +165531,7 @@ var require_x509 = __commonJS({ require_pem(); require_pss(); require_rsa(); - require_util16(); + require_util14(); var asn1 = forge.asn1; var pki2 = module2.exports = forge.pki = forge.pki || {}; var oids = pki2.oids; @@ -159949,7 +167660,7 @@ var require_pkcs12 = __commonJS({ require_random2(); require_rsa(); require_sha1(); - require_util16(); + require_util14(); require_x509(); var asn1 = forge.asn1; var pki2 = forge.pki; @@ -160812,7 +168523,7 @@ var require_pki = __commonJS({ require_pkcs12(); require_pss(); require_rsa(); - require_util16(); + require_util14(); require_x509(); var asn1 = forge.asn1; var pki2 = module2.exports = forge.pki = forge.pki || {}; @@ -160864,7 +168575,7 @@ var require_tls = __commonJS({ require_pki(); require_random2(); require_sha1(); - require_util16(); + require_util14(); var prf_TLS1 = function(secret, label, seed, length) { var rval = forge.util.createBuffer(); var idx = secret.length >> 1; @@ -163035,7 +170746,7 @@ var require_sha512 = __commonJS({ "node_modules/node-forge/lib/sha512.js"(exports2, module2) { var forge = require_forge(); require_md(); - require_util16(); + require_util14(); var sha512 = module2.exports = forge.sha512 = forge.sha512 || {}; forge.md.sha512 = forge.md.algorithms.sha512 = sha512; var sha384 = forge.sha384 = forge.sha512.sha384 = forge.sha512.sha384 || {}; @@ -163537,7 +171248,7 @@ var require_ed25519 = __commonJS({ require_jsbn(); require_random2(); require_sha512(); - require_util16(); + require_util14(); var asn1Validator = require_asn1_validator(); var publicKeyValidator = asn1Validator.publicKeyValidator; var privateKeyValidator = asn1Validator.privateKeyValidator; @@ -164647,7 +172358,7 @@ var require_ed25519 = __commonJS({ var require_kem = __commonJS({ "node_modules/node-forge/lib/kem.js"(exports2, module2) { var forge = require_forge(); - require_util16(); + require_util14(); require_random2(); require_jsbn(); module2.exports = forge.kem = forge.kem || {}; @@ -164710,7 +172421,7 @@ var require_kem = __commonJS({ var require_log7 = __commonJS({ "node_modules/node-forge/lib/log.js"(exports2, module2) { var forge = require_forge(); - require_util16(); + require_util14(); module2.exports = forge.log = forge.log || {}; forge.log.levels = [ "none", @@ -164903,7 +172614,7 @@ var require_pkcs7 = __commonJS({ require_pem(); require_pkcs7asn1(); require_random2(); - require_util16(); + require_util14(); require_x509(); var asn1 = forge.asn1; var p7 = module2.exports = forge.pkcs7 = forge.pkcs7 || {}; @@ -165889,7 +173600,7 @@ var require_ssh = __commonJS({ require_hmac(); require_md5(); require_sha1(); - require_util16(); + require_util14(); var ssh = module2.exports = forge.ssh = forge.ssh || {}; ssh.privateKeyToPutty = function(privateKey, passphrase, comment) { comment = comment || ""; @@ -166045,7 +173756,7 @@ var require_lib6 = __commonJS({ require_rc2(); require_ssh(); require_tls(); - require_util16(); + require_util14(); } }); @@ -174098,7 +181809,7 @@ Improved incremental analysis will be automatically retried when the next versio // src/overlay/status.ts var fs9 = __toESM(require("fs")); var path9 = __toESM(require("path")); -var actionsCache = __toESM(require_cache4()); +var actionsCache = __toESM(require_cache6()); var MAX_CACHE_OPERATION_MS = 3e4; var STATUS_FILE_NAME = "overlay-status.json"; function getStatusFilePath(languages) { @@ -174208,7 +181919,7 @@ async function getCacheKey(codeql, languages, diskUsage) { // src/trap-caching.ts var fs10 = __toESM(require("fs")); var path10 = __toESM(require("path")); -var actionsCache2 = __toESM(require_cache4()); +var actionsCache2 = __toESM(require_cache6()); var CACHE_VERSION = 1; var CODEQL_TRAP_CACHE_PREFIX = "codeql-trap"; var MINIMUM_CACHE_MB_TO_UPLOAD = 10; @@ -175330,7 +183041,7 @@ function getCodeQLBundleFromUrl(url2) { // src/overlay/caching.ts var fs12 = __toESM(require("fs")); -var actionsCache3 = __toESM(require_cache4()); +var actionsCache3 = __toESM(require_cache6()); var semver5 = __toESM(require_semver2()); var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES = OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB * 1e6; @@ -177647,7 +185358,7 @@ async function runAutobuild(config, language, logger2) { // src/dependency-caching.ts var os5 = __toESM(require("os")); var import_path3 = require("path"); -var actionsCache4 = __toESM(require_cache4()); +var actionsCache4 = __toESM(require_cache6()); var glob = __toESM(require_glob()); var CODEQL_DEPENDENCY_CACHE_PREFIX = "codeql-dependencies"; var CODEQL_DEPENDENCY_CACHE_VERSION = 1; diff --git a/package-lock.json b/package-lock.json index c06678b604..85bc9b6e02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,7 @@ "long": "^5.3.2", "node-forge": "^1.4.0", "semver": "^7.8.5", - "undici": "^6.28.0", + "undici": "^7.30.1", "uuid": "^14.0.3" }, "devDependencies": { @@ -10024,12 +10024,12 @@ } }, "node_modules/undici": { - "version": "6.28.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", - "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==", + "version": "7.30.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.30.1.tgz", + "integrity": "sha512-03KrMbjIFDWQR5RNPrSw3bd1r12JpyFQl9/yxjUbJtqkjmllqC5lFjZh6ujeuJCKr8EOQvRW872Oy/az+nLYxg==", "license": "MIT", "engines": { - "node": ">=18.17" + "node": ">=20.18.1" } }, "node_modules/undici-types": { diff --git a/package.json b/package.json index 76ac14cf2d..d5ef45448a 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "long": "^5.3.2", "node-forge": "^1.4.0", "semver": "^7.8.5", - "undici": "^6.28.0", + "undici": "^7.30.1", "uuid": "^14.0.3" }, "devDependencies": { @@ -94,6 +94,6 @@ "semver": ">=6.3.1" }, "glob": "^13.0.6", - "undici": "^6.28.0" + "undici": "^7.30.1" } } From 515fac0ed05bbb94fd6f24a99f8d2e47c2c8f909 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 26 Oct 2026 13:00:49 +0000 Subject: [PATCH 086/174] Configure Dependabot to ignore `undici` for the moment --- .github/dependabot.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0e0dd0cce1..9a647b1824 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -16,6 +16,14 @@ updates: # This might be fixed when we move to eslint v9. - dependency-name: "eslint-plugin-import" versions: [">=2.30.0"] + + # Some of our dependencies are lagging behind with support for new versions of + # `undici` which is why we have to override it in `package.json`. Dependabot + # workflows fail when they try to update a dependency that is explicitly + # overriden. Since this happens somewhat routinely at the moment, we are + # excluding `undici` here and have to manually update it when needed. + - dependency-name: "undici" + versions: [">=7.30.1"] groups: npm-minor: patterns: From ce7d3f77388f81bd5b1be6172533542b055f88de Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 26 Oct 2026 13:04:50 +0000 Subject: [PATCH 087/174] Install newer Kotlin version --- .github/actions/prepare-test/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/prepare-test/action.yml b/.github/actions/prepare-test/action.yml index 4eb840d2d8..e2a55a24e4 100644 --- a/.github/actions/prepare-test/action.yml +++ b/.github/actions/prepare-test/action.yml @@ -76,4 +76,4 @@ runs: - uses: fwilhe2/setup-kotlin@b325539ca8f6e1d9ee04efed06f49bdbf5426dbb # v2.1 if: ${{ inputs.setup-kotlin == 'true' }} with: - version: 1.8.21 + version: 2.1.20 From dd68f130c6e73ecc739579bdc27ccfae957da78a Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 26 Oct 2026 13:10:50 +0000 Subject: [PATCH 088/174] Install a newer Ruby version --- .github/workflows/__rubocop-multi-language.yml | 3 ++- pr-checks/checks/rubocop-multi-language.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/__rubocop-multi-language.yml b/.github/workflows/__rubocop-multi-language.yml index c3348db6cf..f2c1c3e401 100644 --- a/.github/workflows/__rubocop-multi-language.yml +++ b/.github/workflows/__rubocop-multi-language.yml @@ -56,7 +56,8 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@651ff0d62c5c79bed6d53ec518387aae20e72c1a # v1.329.0 with: - ruby-version: 2.6 + ruby-version: 3.4 + - name: Install Code Scanning integration run: bundle add code-scanning-rubocop --version 0.3.0 --skip-install - name: Install dependencies diff --git a/pr-checks/checks/rubocop-multi-language.yml b/pr-checks/checks/rubocop-multi-language.yml index eec3aa8335..cc0e493a80 100644 --- a/pr-checks/checks/rubocop-multi-language.yml +++ b/pr-checks/checks/rubocop-multi-language.yml @@ -7,7 +7,8 @@ steps: - name: Set up Ruby uses: ruby/setup-ruby@651ff0d62c5c79bed6d53ec518387aae20e72c1a # v1.329.0 with: - ruby-version: 2.6 + ruby-version: 3.4 + - name: Install Code Scanning integration run: bundle add code-scanning-rubocop --version 0.3.0 --skip-install - name: Install dependencies From eac0005d0c1946432e5427f1fa0eb3abfccb84ee Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 26 Oct 2026 13:15:15 +0000 Subject: [PATCH 089/174] Temporarily switch old CLI checks to older Ubuntu runner --- .github/workflows/__go-tracing-autobuilder.yml | 2 +- .../__go-tracing-custom-build-steps.yml | 2 +- .../workflows/__go-tracing-legacy-workflow.yml | 2 +- .../workflows/__multi-language-autodetect.yml | 2 +- .github/workflows/__rust.yml | 2 +- .../workflows/debug-artifacts-failure-safe.yml | 18 +++++++++--------- .github/workflows/debug-artifacts-safe.yml | 18 +++++++++--------- pr-checks/sync.ts | 12 ++++++++---- 8 files changed, 31 insertions(+), 27 deletions(-) diff --git a/.github/workflows/__go-tracing-autobuilder.yml b/.github/workflows/__go-tracing-autobuilder.yml index fb471c5eac..a36cc43a7b 100644 --- a/.github/workflows/__go-tracing-autobuilder.yml +++ b/.github/workflows/__go-tracing-autobuilder.yml @@ -44,7 +44,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-24.04 version: stable-v2.20.7 - os: ubuntu-latest version: stable-v2.21.4 diff --git a/.github/workflows/__go-tracing-custom-build-steps.yml b/.github/workflows/__go-tracing-custom-build-steps.yml index b3b043def9..05fedfb035 100644 --- a/.github/workflows/__go-tracing-custom-build-steps.yml +++ b/.github/workflows/__go-tracing-custom-build-steps.yml @@ -44,7 +44,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-24.04 version: stable-v2.20.7 - os: ubuntu-latest version: stable-v2.21.4 diff --git a/.github/workflows/__go-tracing-legacy-workflow.yml b/.github/workflows/__go-tracing-legacy-workflow.yml index 20bdea6955..276d4cfda5 100644 --- a/.github/workflows/__go-tracing-legacy-workflow.yml +++ b/.github/workflows/__go-tracing-legacy-workflow.yml @@ -44,7 +44,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-24.04 version: stable-v2.20.7 - os: ubuntu-latest version: stable-v2.21.4 diff --git a/.github/workflows/__multi-language-autodetect.yml b/.github/workflows/__multi-language-autodetect.yml index a388e57342..d54b24a1ef 100644 --- a/.github/workflows/__multi-language-autodetect.yml +++ b/.github/workflows/__multi-language-autodetect.yml @@ -54,7 +54,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-24.04 version: stable-v2.20.7 - os: macos-15-xlarge version: stable-v2.20.7 diff --git a/.github/workflows/__rust.yml b/.github/workflows/__rust.yml index f26b4eb2eb..d3b5a8a5b8 100644 --- a/.github/workflows/__rust.yml +++ b/.github/workflows/__rust.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-24.04 version: stable-v2.20.7 - os: ubuntu-latest version: stable-v2.22.1 diff --git a/.github/workflows/debug-artifacts-failure-safe.yml b/.github/workflows/debug-artifacts-failure-safe.yml index c61bd6b177..dd4e98797d 100644 --- a/.github/workflows/debug-artifacts-failure-safe.yml +++ b/.github/workflows/debug-artifacts-failure-safe.yml @@ -6,13 +6,13 @@ env: on: push: branches: - - main - - releases/v* + - main + - releases/v* pull_request: merge_group: types: [checks_requested] schedule: - - cron: '0 5 * * *' + - cron: "0 5 * * *" workflow_dispatch: concurrency: @@ -30,10 +30,10 @@ jobs: fail-fast: false matrix: version: - - stable-v2.20.7 - - default - - linked - - nightly-latest + - stable-v2.20.7 + - default + - linked + - nightly-latest name: Upload debug artifacts after failure in analyze continue-on-error: true env: @@ -43,7 +43,7 @@ jobs: # We currently need `security-events: read` to access feature flags. security-events: read timeout-minutes: 45 - runs-on: ubuntu-latest + runs-on: ${{ case(matrix.version == 'stable-v2.20.7', 'ubuntu-24.04', 'ubuntu-latest') }} steps: - name: Dump GitHub event run: cat "${GITHUB_EVENT_PATH}" @@ -60,7 +60,7 @@ jobs: - name: Install .NET uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: - dotnet-version: '9.x' + dotnet-version: "9.x" - name: Assert best-effort artifact scan completed uses: ./../action/.github/actions/verify-debug-artifact-scan-completed - uses: ./../action/init diff --git a/.github/workflows/debug-artifacts-safe.yml b/.github/workflows/debug-artifacts-safe.yml index 6d162d9c0c..1e723a45c0 100644 --- a/.github/workflows/debug-artifacts-safe.yml +++ b/.github/workflows/debug-artifacts-safe.yml @@ -5,13 +5,13 @@ env: on: push: branches: - - main - - releases/v* + - main + - releases/v* pull_request: merge_group: types: [checks_requested] schedule: - - cron: '0 5 * * *' + - cron: "0 5 * * *" workflow_dispatch: concurrency: @@ -29,10 +29,10 @@ jobs: fail-fast: false matrix: version: - - stable-v2.20.7 - - default - - linked - - nightly-latest + - stable-v2.20.7 + - default + - linked + - nightly-latest name: Upload debug artifacts env: CODEQL_ACTION_TEST_MODE: true @@ -41,7 +41,7 @@ jobs: contents: read # We currently need `security-events: read` to access feature flags. security-events: read - runs-on: ubuntu-latest + runs-on: ${{ case(matrix.version == 'stable-v2.20.7', 'ubuntu-24.04', 'ubuntu-latest') }} steps: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -56,7 +56,7 @@ jobs: - name: Install .NET uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: - dotnet-version: '9.x' + dotnet-version: "9.x" - name: Assert best-effort artifact scan completed uses: ./../action/.github/actions/verify-debug-artifact-scan-completed - uses: ./../action/init diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index 1729f5409b..afbc7fc43d 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -442,10 +442,14 @@ function generateJobMatrix( : [operatingSystemConfig["runner-image"]]; for (const runnerImage of runnerImagesForOs) { - matrix.push({ - os: runnerImage, - version, - }); + if (runnerImage === "ubuntu-latest" && version === "stable-v2.20.7") { + matrix.push({ os: "ubuntu-24.04", version }); + } else { + matrix.push({ + os: runnerImage, + version, + }); + } } } } From ab743b6301b244dcdfa64cde84442cc86b5ebf11 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 26 Oct 2026 13:29:56 +0000 Subject: [PATCH 090/174] Install newer version of `code-scanning-rubocop` --- .github/workflows/__rubocop-multi-language.yml | 5 ++++- pr-checks/checks/rubocop-multi-language.yml | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/__rubocop-multi-language.yml b/.github/workflows/__rubocop-multi-language.yml index f2c1c3e401..6128561335 100644 --- a/.github/workflows/__rubocop-multi-language.yml +++ b/.github/workflows/__rubocop-multi-language.yml @@ -59,15 +59,18 @@ jobs: ruby-version: 3.4 - name: Install Code Scanning integration - run: bundle add code-scanning-rubocop --version 0.3.0 --skip-install + run: bundle add code-scanning-rubocop --version 0.6.1 --skip-install + - name: Install dependencies run: bundle install + - name: RuboCop run run: | bash -c " bundle exec rubocop --require code_scanning --format CodeScanning::SarifFormatter -o rubocop.sarif [[ $? -ne 2 ]] " + - uses: ./../action/upload-sarif with: sarif_file: rubocop.sarif diff --git a/pr-checks/checks/rubocop-multi-language.yml b/pr-checks/checks/rubocop-multi-language.yml index cc0e493a80..0839d38b0b 100644 --- a/pr-checks/checks/rubocop-multi-language.yml +++ b/pr-checks/checks/rubocop-multi-language.yml @@ -10,15 +10,18 @@ steps: ruby-version: 3.4 - name: Install Code Scanning integration - run: bundle add code-scanning-rubocop --version 0.3.0 --skip-install + run: bundle add code-scanning-rubocop --version 0.6.1 --skip-install + - name: Install dependencies run: bundle install + - name: RuboCop run run: | bash -c " bundle exec rubocop --require code_scanning --format CodeScanning::SarifFormatter -o rubocop.sarif [[ $? -ne 2 ]] " + - uses: ./../action/upload-sarif with: sarif_file: rubocop.sarif From 171607b66f68b1dc4e7dc4358bdf3ad2b4009abb Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 26 Oct 2026 13:45:49 +0000 Subject: [PATCH 091/174] Remove Rubocop workflow --- .../workflows/__rubocop-multi-language.yml | 78 ------------------- pr-checks/checks/rubocop-multi-language.yml | 27 ------- 2 files changed, 105 deletions(-) delete mode 100644 .github/workflows/__rubocop-multi-language.yml delete mode 100644 pr-checks/checks/rubocop-multi-language.yml diff --git a/.github/workflows/__rubocop-multi-language.yml b/.github/workflows/__rubocop-multi-language.yml deleted file mode 100644 index 6128561335..0000000000 --- a/.github/workflows/__rubocop-multi-language.yml +++ /dev/null @@ -1,78 +0,0 @@ -# Warning: This file is generated automatically, and should not be modified. -# Instead, please modify the template in the pr-checks directory and run: -# pr-checks/sync.sh -# to regenerate this file. - -name: PR Check - RuboCop multi-language -env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GO111MODULE: auto -on: - push: - branches: - - main - - releases/v* - pull_request: {} - merge_group: - types: - - checks_requested - schedule: - - cron: '0 5 * * *' - workflow_dispatch: - inputs: {} - workflow_call: - inputs: {} -defaults: - run: - shell: bash -concurrency: - cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: rubocop-multi-language-${{github.ref}} -jobs: - rubocop-multi-language: - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-latest - version: default - name: RuboCop multi-language - if: github.triggering_actor != 'dependabot[bot]' - permissions: - contents: read - security-events: read - timeout-minutes: 45 - runs-on: ${{ matrix.os }} - steps: - - name: Check out repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - name: Prepare test - id: prepare-test - uses: ./.github/actions/prepare-test - with: - version: ${{ matrix.version }} - use-all-platform-bundle: 'false' - setup-kotlin: 'true' - - name: Set up Ruby - uses: ruby/setup-ruby@651ff0d62c5c79bed6d53ec518387aae20e72c1a # v1.329.0 - with: - ruby-version: 3.4 - - - name: Install Code Scanning integration - run: bundle add code-scanning-rubocop --version 0.6.1 --skip-install - - - name: Install dependencies - run: bundle install - - - name: RuboCop run - run: | - bash -c " - bundle exec rubocop --require code_scanning --format CodeScanning::SarifFormatter -o rubocop.sarif - [[ $? -ne 2 ]] - " - - - uses: ./../action/upload-sarif - with: - sarif_file: rubocop.sarif - env: - CODEQL_ACTION_TEST_MODE: true diff --git a/pr-checks/checks/rubocop-multi-language.yml b/pr-checks/checks/rubocop-multi-language.yml deleted file mode 100644 index 0839d38b0b..0000000000 --- a/pr-checks/checks/rubocop-multi-language.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: "RuboCop multi-language" -description: "Tests using RuboCop to analyze a multi-language repository and then using the CodeQL Action to upload the resulting SARIF" -# This check doesn't use CodeQL, so the `version` matrix variable is unused. -versions: - - default -steps: - - name: Set up Ruby - uses: ruby/setup-ruby@651ff0d62c5c79bed6d53ec518387aae20e72c1a # v1.329.0 - with: - ruby-version: 3.4 - - - name: Install Code Scanning integration - run: bundle add code-scanning-rubocop --version 0.6.1 --skip-install - - - name: Install dependencies - run: bundle install - - - name: RuboCop run - run: | - bash -c " - bundle exec rubocop --require code_scanning --format CodeScanning::SarifFormatter -o rubocop.sarif - [[ $? -ne 2 ]] - " - - - uses: ./../action/upload-sarif - with: - sarif_file: rubocop.sarif From 34b4917832d4628b18fa4a53cb09fec2677d4207 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 26 Oct 2026 14:26:53 +0000 Subject: [PATCH 092/174] Add comment to `sync.ts` --- pr-checks/sync.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index afbc7fc43d..25b4623587 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -442,6 +442,9 @@ function generateJobMatrix( : [operatingSystemConfig["runner-image"]]; for (const runnerImage of runnerImagesForOs) { + // stable-v2.20.7 requires an older version of Java than the default on `ubuntu-latest`. + // We could install that older version on the newer runners, or use the older runner. + // We do the latter here. This can be removed once we stop supporting `v2.20.7`. if (runnerImage === "ubuntu-latest" && version === "stable-v2.20.7") { matrix.push({ os: "ubuntu-24.04", version }); } else { From 63b184d4bcdf843072170158e7f3902930d3a50d Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 26 Oct 2026 14:33:26 +0000 Subject: [PATCH 093/174] Improve `sync.ts` version typing so that check constant becomes an error once removed --- pr-checks/sync.ts | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index 25b4623587..7824ef890b 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -137,6 +137,14 @@ interface LanguageSetup { /** Describes partial mappings from built-in languages to their specific setup information. */ type LanguageSetups = Partial>; +// A type representing version identifiers. +type Version = + | "default" + | "linked" + | "nightly-latest" + // This is an approximation, but sufficient validation for our needs here. + | `stable-v${number}.${number}.${number}`; + // The default set of CodeQL Bundle versions to use for the PR checks. const defaultTestVersions = [ // The oldest supported CodeQL version. If bumping, update `CODEQL_MINIMUM_VERSION` in `codeql.ts` @@ -159,7 +167,10 @@ const defaultTestVersions = [ "linked", // A nightly build directly from the our private repo, built in the last 24 hours. "nightly-latest", -]; +] as const satisfies Version[]; + +/** A type representing the default test versions. */ +type DefaultTestVersion = (typeof defaultTestVersions)[number]; /** The default versions we use for languages / frameworks, if not specified as a workflow input. */ const defaultLanguageVersions = { @@ -445,7 +456,13 @@ function generateJobMatrix( // stable-v2.20.7 requires an older version of Java than the default on `ubuntu-latest`. // We could install that older version on the newer runners, or use the older runner. // We do the latter here. This can be removed once we stop supporting `v2.20.7`. - if (runnerImage === "ubuntu-latest" && version === "stable-v2.20.7") { + // Since this is typed as `DefaultTestVersion`, it will become an error once `stable-v2.20.7` + // is removed from `defaultTestVersions`. + const requiresOlderRunnerImage: DefaultTestVersion = "stable-v2.20.7"; + if ( + runnerImage === "ubuntu-latest" && + version === requiresOlderRunnerImage + ) { matrix.push({ os: "ubuntu-24.04", version }); } else { matrix.push({ From bfac910f062c231a0c79c6b518252b3e5c1e1433 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Mon, 26 Oct 2026 16:43:13 +0000 Subject: [PATCH 094/174] Update CodeQL deprecation warning for GHES 3.18 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 6 +++--- src/codeql.ts | 6 +++--- unreleased-change-notes/ghes-3-18-deprecation.md | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 unreleased-change-notes/ghes-3-18-deprecation.md diff --git a/lib/entry-points.js b/lib/entry-points.js index 2e8b97e41b..196ca5584f 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -176948,9 +176948,9 @@ async function getCombinedTracerConfig(logger2, codeql, config) { // src/codeql.ts var cachedCodeQL = void 0; var CODEQL_MINIMUM_VERSION = "2.20.7"; -var CODEQL_NEXT_MINIMUM_VERSION = "2.21.3"; -var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.17"; -var GHES_MOST_RECENT_DEPRECATION_DATE = "2026-09-24"; +var CODEQL_NEXT_MINIMUM_VERSION = "2.22.4"; +var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.18"; +var GHES_MOST_RECENT_DEPRECATION_DATE = "2026-10-16"; var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; function isDiskConfigurationError(e) { if (!(e instanceof Error)) { diff --git a/src/codeql.ts b/src/codeql.ts index 28ba2243e9..c1a8f4f340 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -260,17 +260,17 @@ const CODEQL_MINIMUM_VERSION = "2.20.7"; /** * This version will shortly become the oldest version of CodeQL that the Action will run with. */ -const CODEQL_NEXT_MINIMUM_VERSION = "2.21.3"; +const CODEQL_NEXT_MINIMUM_VERSION = "2.22.4"; /** * This is the version of GHES that was most recently deprecated. */ -const GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.17"; +const GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.18"; /** * This is the deprecation date for the version of GHES that was most recently deprecated. */ -const GHES_MOST_RECENT_DEPRECATION_DATE = "2026-09-24"; +const GHES_MOST_RECENT_DEPRECATION_DATE = "2026-10-16"; /** The CLI verbosity level to use for extraction in debug mode. */ const EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; diff --git a/unreleased-change-notes/ghes-3-18-deprecation.md b/unreleased-change-notes/ghes-3-18-deprecation.md new file mode 100644 index 0000000000..0e33d39327 --- /dev/null +++ b/unreleased-change-notes/ghes-3-18-deprecation.md @@ -0,0 +1 @@ +- _Upcoming breaking change_: CodeQL version 2.22.3 and earlier were discontinued on 16 October 2026 alongside GitHub Enterprise Server 3.18, and will be unsupported by the next minor release of the CodeQL Action. Added a deprecation warning for customers using these versions of CodeQL. [#4266](https://github.com/github/codeql-action/pull/4266) From 4a890e46e0120cbc79363f096897ef7861ea7831 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Mon, 26 Oct 2026 16:43:21 +0000 Subject: [PATCH 095/174] Remove GHES 3.18 from compatibility table Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 8c4fc46631..d738adcab6 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,6 @@ We typically release new minor versions of the CodeQL Action and Bundle when a n | `v4.33.0` | `2.24.3` | Enterprise Server 3.21 | | | `v4.31.10` | `2.23.9` | Enterprise Server 3.20 | | | `v3.29.11` | `2.22.4` | Enterprise Server 3.19 | | -| `v3.28.21` | `2.21.3` | Enterprise Server 3.18 | | See the full list of GHES release and deprecation dates at [GitHub Enterprise Server releases](https://docs.github.com/en/enterprise-server/admin/all-releases#releases-of-github-enterprise-server). From 8fb8b475a9e826e5dafd0d7d8e4623b75d23364e Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 27 Oct 2026 10:20:12 +0000 Subject: [PATCH 096/174] Consistently use JSDocs in `sync.ts` --- pr-checks/sync.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index 7824ef890b..c205e94a72 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -137,7 +137,7 @@ interface LanguageSetup { /** Describes partial mappings from built-in languages to their specific setup information. */ type LanguageSetups = Partial>; -// A type representing version identifiers. +/** A type representing version identifiers. */ type Version = | "default" | "linked" @@ -145,7 +145,7 @@ type Version = // This is an approximation, but sufficient validation for our needs here. | `stable-v${number}.${number}.${number}`; -// The default set of CodeQL Bundle versions to use for the PR checks. +/** The default set of CodeQL Bundle versions to use for the PR checks. */ const defaultTestVersions = [ // The oldest supported CodeQL version. If bumping, update `CODEQL_MINIMUM_VERSION` in `codeql.ts` "stable-v2.20.7", @@ -324,9 +324,11 @@ const languageSetups: LanguageSetups = { }, }; -// This is essentially an arbitrary version of `yq`, which happened to be the one that -// `choco` fetched when we moved away from using that here. -// See https://github.com/github/codeql-action/pull/3423 +/** + * This is essentially an arbitrary version of `yq`, which happened to be the one that + * `choco` fetched when we moved away from using that here. + * See https://github.com/github/codeql-action/pull/3423 + */ const YQ_VERSION = "v4.50.1"; const CHECKS_DIR = path.join(PR_CHECKS_DIR, "checks"); From 0b8f4560ec77a80d118a37596c7573e5dbd0a20b Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 27 Oct 2026 10:23:02 +0000 Subject: [PATCH 097/174] Add comment for the Kotlin version --- .github/actions/prepare-test/action.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/actions/prepare-test/action.yml b/.github/actions/prepare-test/action.yml index e2a55a24e4..4c11ec4929 100644 --- a/.github/actions/prepare-test/action.yml +++ b/.github/actions/prepare-test/action.yml @@ -76,4 +76,7 @@ runs: - uses: fwilhe2/setup-kotlin@b325539ca8f6e1d9ee04efed06f49bdbf5426dbb # v2.1 if: ${{ inputs.setup-kotlin == 'true' }} with: + # Kotlin is installed on the runners by default, but the version that is pre-installed is too new + # to be supported by CodeQL. This Kotlin version is selected to be compatible with both the default Java + # version on the `ubuntu-latest` runners and CodeQL. version: 2.1.20 From bcc1fbe153f97bb8a2de9b8a418983821c22a678 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 27 Oct 2026 11:18:33 +0000 Subject: [PATCH 098/174] Add comment to `debug-artifacts` workflows --- .github/workflows/debug-artifacts-failure-safe.yml | 5 +++++ .github/workflows/debug-artifacts-safe.yml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/.github/workflows/debug-artifacts-failure-safe.yml b/.github/workflows/debug-artifacts-failure-safe.yml index dd4e98797d..4f9082acd2 100644 --- a/.github/workflows/debug-artifacts-failure-safe.yml +++ b/.github/workflows/debug-artifacts-failure-safe.yml @@ -43,7 +43,12 @@ jobs: # We currently need `security-events: read` to access feature flags. security-events: read timeout-minutes: 45 + + # stable-v2.20.7 requires an older version of Java than the default on `ubuntu-latest` (`ubuntu-26.04`). + # We could install that older version on the newer runners, or use the older runner. + # We do the latter here. This can be removed once we stop supporting `v2.20.7`. runs-on: ${{ case(matrix.version == 'stable-v2.20.7', 'ubuntu-24.04', 'ubuntu-latest') }} + steps: - name: Dump GitHub event run: cat "${GITHUB_EVENT_PATH}" diff --git a/.github/workflows/debug-artifacts-safe.yml b/.github/workflows/debug-artifacts-safe.yml index 1e723a45c0..610e1aab8a 100644 --- a/.github/workflows/debug-artifacts-safe.yml +++ b/.github/workflows/debug-artifacts-safe.yml @@ -41,7 +41,12 @@ jobs: contents: read # We currently need `security-events: read` to access feature flags. security-events: read + + # stable-v2.20.7 requires an older version of Java than the default on `ubuntu-latest` (`ubuntu-26.04`). + # We could install that older version on the newer runners, or use the older runner. + # We do the latter here. This can be removed once we stop supporting `v2.20.7`. runs-on: ${{ case(matrix.version == 'stable-v2.20.7', 'ubuntu-24.04', 'ubuntu-latest') }} + steps: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 From 2908c78a829e4056d419fed8aadbf64237c9023e Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 27 Oct 2026 11:19:11 +0000 Subject: [PATCH 099/174] Remove Rubocop from deflake workflow --- .github/workflows/deflake.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/deflake.yml b/.github/workflows/deflake.yml index 158dc6c96d..27024b3780 100644 --- a/.github/workflows/deflake.yml +++ b/.github/workflows/deflake.yml @@ -60,7 +60,6 @@ on: - "PR Check - Proxy test" - "PR Check - Remote config file" - "PR Check - Resolve environment" - - "PR Check - RuboCop multi-language" - "PR Check - Ruby analysis" - "PR Check - Rust analysis" - "PR Check - Split workflow" From edc50a623cf3542af2e1b30b501bb371f9439fd2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Oct 2026 11:54:12 +0000 Subject: [PATCH 100/174] Bump the npm-minor group across 1 directory with 3 updates Bumps the npm-minor group with 3 updates in the / directory: [js-yaml](https://github.com/nodeca/js-yaml), [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint). Updates `js-yaml` from 5.4.3 to 5.5.0 - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/5.4.3...5.5.0) Updates `eslint-plugin-jsdoc` from 65.3.4 to 65.3.15 - [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases) - [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v65.3.4...v65.3.15) Updates `typescript-eslint` from 8.71.2 to 8.72.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.72.0/packages/typescript-eslint) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 5.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor - dependency-name: eslint-plugin-jsdoc dependency-version: 65.3.15 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-minor - dependency-name: typescript-eslint dependency-version: 8.72.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 159 +++++++++++++++++++++++++--------------------- package.json | 6 +- 2 files changed, 91 insertions(+), 74 deletions(-) diff --git a/package-lock.json b/package-lock.json index c06678b604..a3f7e2eb94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,7 @@ "follow-redirects": "^1.16.1", "get-folder-size": "^5.0.0", "https-proxy-agent": "^7.0.6", - "js-yaml": "^5.4.3", + "js-yaml": "^5.5.0", "jsonschema": "1.5.0", "long": "^5.3.2", "node-forge": "^1.4.0", @@ -57,14 +57,14 @@ "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-github": "^6.1.2", "eslint-plugin-import-x": "^4.17.1", - "eslint-plugin-jsdoc": "^65.3.4", + "eslint-plugin-jsdoc": "^65.3.15", "eslint-plugin-no-async-foreach": "^0.1.1", "glob": "^13.0.6", "globals": "^17.13.0", "nock": "^14.0.17", "sinon": "^22.1.0", "typescript": "^6.0.3", - "typescript-eslint": "^8.71.2" + "typescript-eslint": "^8.72.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -2702,17 +2702,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.2.tgz", - "integrity": "sha512-K72/pvT7qpm8q3k8G5u93NCSN1RcLxX5h7Gw0bQpbMXviBHeY6Nx1WEwmk9wP+eKTSQ8ecxvcgt/ZX/rB938xQ==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.72.0.tgz", + "integrity": "sha512-aysKgysPX9XOv/dk95UkvUDe++Q3n3dJPG9CEWT3RUccxfkPJ+Qn6nhKPDhZXU6Ofo9kgwGWwKyQCnZIXTgngg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/type-utils": "8.71.2", - "@typescript-eslint/utils": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", + "@typescript-eslint/scope-manager": "8.72.0", + "@typescript-eslint/type-utils": "8.72.0", + "@typescript-eslint/utils": "8.72.0", + "@typescript-eslint/visitor-keys": "8.72.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -2725,7 +2725,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.71.2", + "@typescript-eslint/parser": "^8.72.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } @@ -2741,16 +2741,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.2.tgz", - "integrity": "sha512-aTtmZjp/x3gsGHkDs04/1I8kNogBJkpQaeGaN0PfiG43NzDEmW2n+OP5im9wfsvyX0yP1UZWBrAGtDBfH9jEVw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.72.0.tgz", + "integrity": "sha512-0O+x3ynciD6zuXb1CKSu165haQV6ey53DKhHHUnujP7U+XlltJG+/keT0Xhd1HXCze+IHf7Tvt39ovyepX/LNw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", + "@typescript-eslint/scope-manager": "8.72.0", + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/typescript-estree": "8.72.0", + "@typescript-eslint/visitor-keys": "8.72.0", "debug": "^4.4.3" }, "engines": { @@ -2784,14 +2784,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.2.tgz", - "integrity": "sha512-Pd68GsLVh5ZXlcEccFPdhSOvtHZ/2WU0XsA8zmXOS3F158lVlcTLhfQ6qvtL1RzbMie0Kp8xtbVwAg4nejKPHw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.72.0.tgz", + "integrity": "sha512-bzHngBbmIgzj6TsTjVUCntGx6FFLgE7mPjpO0PzHycOaZHXqS43XnrkFIHRS16LLr/xO6FHSXG3GJFo/F4bSBQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.71.2", - "@typescript-eslint/types": "^8.71.2", + "@typescript-eslint/tsconfig-utils": "^8.72.0", + "@typescript-eslint/types": "^8.72.0", "debug": "^4.4.3" }, "engines": { @@ -2824,14 +2824,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.2.tgz", - "integrity": "sha512-YF4wgg5iUX5Obywoac27B56FhozMNFhdJSbh11H5GBAwmBtfyRhmgTQqW9tRNNmHDvsZ2CX6UGzoz+YfYn2Leg==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.72.0.tgz", + "integrity": "sha512-JewPyJOYcXBSAS7PIgufscHOwZqhTGyBRiQJhhuDln66tMchxvvt7nJ90JKKIoOelmdHA3kAQbm9cEUHc4JSEA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2" + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/visitor-keys": "8.72.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2842,9 +2842,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.2.tgz", - "integrity": "sha512-jz49TAWokm/7yWD9/o837nYax9DyALxIPOImdImvVzo6canBCZYzin8zJyqNR5k1j9K1DE0bVvr0XYB+99uAdg==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.72.0.tgz", + "integrity": "sha512-0vbxCf7xLVPSjcOdm6eQbgViH8EDJ8xnl1laLT9yoqSz2YmcSfSg5Vdl0JUvZf6rcuJ0ZivJIuMD4edTg8obaA==", "dev": true, "license": "MIT", "engines": { @@ -2859,15 +2859,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.2.tgz", - "integrity": "sha512-cC8UaalCViJkb3rH/xLIvidEwoFRtMZMUqDjjJMGEKaTFwYRHYBcoczlEGHuvkHEO8svRDrgZ0yQgOArFmwang==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.72.0.tgz", + "integrity": "sha512-gEXxmmbSTSOVTC37IYYvremOM31v+UN2W772bJxmVYPhAOPSUxtacyb7wkm1EhkYKU6KzFJsdU44DCV4to0LWw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2", - "@typescript-eslint/utils": "8.71.2", + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/typescript-estree": "8.72.0", + "@typescript-eslint/utils": "8.72.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -2902,9 +2902,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.2.tgz", - "integrity": "sha512-y5Ukl3oVp7e/VGxqIoEXoeb/Roj71PAJ4WG/N/RGj+eeDvKRLM15kGr9MijLbN0i03S52zxu31Z98E5gWChJKw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.72.0.tgz", + "integrity": "sha512-Adfoy59kxNEjT5E5fnyrp7GpHYuWs8ONbdohu4ez6IU46qDq8LltG90tLmkucZB2uhYL8mqBjtXqGd8yhfjXqQ==", "dev": true, "license": "MIT", "engines": { @@ -2916,16 +2916,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.2.tgz", - "integrity": "sha512-DgNOEsl4pdYzwSL+N/Cl33tX1Hlw3FvId73LnKXfq7jnrF2viOEn7X+P7RBkkSWCVm92gnWd28GIC5vJuLREeA==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.72.0.tgz", + "integrity": "sha512-gwLfFgWcw15tN2KXDCJvxEOQjPn+P3j/n3eSqkZ5sX4VpW9Cosodr+tWwBZRvJT3TcKx6HnPRGZMCNAiP1Xhug==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.71.2", - "@typescript-eslint/tsconfig-utils": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", + "@typescript-eslint/project-service": "8.72.0", + "@typescript-eslint/tsconfig-utils": "8.72.0", + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/visitor-keys": "8.72.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -3001,16 +3001,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.2.tgz", - "integrity": "sha512-RyKa1G1M9rKHDhrk+HJtiF1MvLD5Ux2JW3TSkzw+02pRALdpJb+QzG1Y5em+LvCgzGwgg8H7mBRFKljNz7ImPw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.72.0.tgz", + "integrity": "sha512-0up3oArJZBYnzOaEXKo8DmI43QvMZyPoFEt9LWzRJcyl/RcJjfKKPebknN1VbTgXBf3M/KggUh5uUMdURLnseg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2" + "@typescript-eslint/scope-manager": "8.72.0", + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/typescript-estree": "8.72.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3025,13 +3025,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.2.tgz", - "integrity": "sha512-zozlN0UA32bSG2zkKAgQyRYSbEISVoyU6vvkKYo2aSny74D8Jh4e+POkJ6Lk0dlezZi5x7TtD+88Xb06IB8nhg==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.72.0.tgz", + "integrity": "sha512-E2mroviasaWecDzTGiGMtuEguuLVOeRggnrIn93CJuxYJzQBHbyymlT08aVQydbBal5538o+JkBKXh2sRuCyIA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/types": "8.72.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -3576,6 +3576,7 @@ }, "node_modules/argparse": { "version": "2.0.1", + "dev": true, "license": "Python-2.0" }, "node_modules/aria-query": { @@ -5365,9 +5366,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "65.3.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-65.3.4.tgz", - "integrity": "sha512-Z3/ro8sZPqnXKhyAzCNa3F7KCZ3js5xVx/q9BEvTjUGzN6OIQfdb+q3Sc9lJ3zCfyPnN0tI524ulZjYRxAwnAw==", + "version": "65.3.15", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-65.3.15.tgz", + "integrity": "sha512-cpU66X+daaX2X6cndE0grdLAIlodysI3KuUEdrJd6FvQHuuYOOvMRAdy8ToYjyJrsoUv0fXkMclA5RM5kaipMw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -7121,9 +7122,9 @@ } }, "node_modules/js-yaml": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.4.3.tgz", - "integrity": "sha512-yzzNtgczwgoVHNigCyKTXcQJU4Y8t/ikU4UxXW0BvrLfHTGWZhsNcOT2s/a7vn81/4KqVnNmHjaUEPlvWnNwVw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.5.0.tgz", + "integrity": "sha512-paNr4LFIFPjeeSmwNYdrb8FafLLG/Cr2Af3GjbsHJ5CxIjH4r0c2emlmRdAtpPAieP1gRVzk6buBbVP5gBMGAg==", "funding": [ { "type": "github", @@ -7136,12 +7137,28 @@ ], "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "argparse": "^3.0.3" }, "bin": { "js-yaml": "bin/js-yaml.mjs" } }, + "node_modules/js-yaml/node_modules/argparse": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-3.0.3.tgz", + "integrity": "sha512-Sn98ftV3KfsO8xfLPHG6oT8y+b0yvbrLgZjgPDXsharNY15tTAjqIsIju4S32nl6/iEUNNE4v+yL2Zhm8ooP3w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "PSF-2.0" + }, "node_modules/jschardet": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-3.1.4.tgz", @@ -9981,16 +9998,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.71.2.tgz", - "integrity": "sha512-Rz4effbMy2g9wnvOJZG6SbVavX313Lap1vNEbk1RUochzickvzP8P4HB+bkNg5e50eVz1hQGjh9K1omI1xB4Bw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.72.0.tgz", + "integrity": "sha512-r26Fkc8As+mZvqp7SLsMmNFyYUup/6CjK7/eHBHmhOw6GH6n6YFxHVFrG0jN1c5CMpDzelLPxvgeCOzx7BjN+A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.71.2", - "@typescript-eslint/parser": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2", - "@typescript-eslint/utils": "8.71.2" + "@typescript-eslint/eslint-plugin": "8.72.0", + "@typescript-eslint/parser": "8.72.0", + "@typescript-eslint/typescript-estree": "8.72.0", + "@typescript-eslint/utils": "8.72.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/package.json b/package.json index 76ac14cf2d..589b0f13de 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "follow-redirects": "^1.16.1", "get-folder-size": "^5.0.0", "https-proxy-agent": "^7.0.6", - "js-yaml": "^5.4.3", + "js-yaml": "^5.5.0", "jsonschema": "1.5.0", "long": "^5.3.2", "node-forge": "^1.4.0", @@ -65,14 +65,14 @@ "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-github": "^6.1.2", "eslint-plugin-import-x": "^4.17.1", - "eslint-plugin-jsdoc": "^65.3.4", + "eslint-plugin-jsdoc": "^65.3.15", "eslint-plugin-no-async-foreach": "^0.1.1", "glob": "^13.0.6", "globals": "^17.13.0", "nock": "^14.0.17", "sinon": "^22.1.0", "typescript": "^6.0.3", - "typescript-eslint": "^8.71.2" + "typescript-eslint": "^8.72.0" }, "overrides": { "@actions/tool-cache": { From 483db645dfbdfb5fb4b1d84432090f0df33c75ba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 Oct 2026 11:56:28 +0000 Subject: [PATCH 101/174] Rebuild --- lib/entry-points.js | 154 ++++++++++++++++++++++++++++++-------------- 1 file changed, 105 insertions(+), 49 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 7cea6c0b6d..013ed8f0ee 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -166923,7 +166923,6 @@ var Schema = class Schema2 { case "mapping": if (tag.matchByTagPrefix) prefix.mapping.push(tag); else exact.mapping[tag.tagName] = tag; - break; } } const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); @@ -167433,16 +167432,17 @@ function getBlockValue(input, start, end, indent, chomping, folded) { } const content = line.slice(textIndent); const first = content.charCodeAt(0); - if (folded) if (first === 32 || first === 9) { - atMoreIndented = true; - result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); - } else if (atMoreIndented) { - atMoreIndented = false; - result += "\n".repeat(emptyLines + 1); - } else if (emptyLines === 0) { - if (didReadContent) result += " "; - } else result += "\n".repeat(emptyLines); - else result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + if (folded) { + if (first === 32 || first === 9) { + atMoreIndented = true; + result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + } else if (atMoreIndented) { + atMoreIndented = false; + result += "\n".repeat(emptyLines + 1); + } else if (emptyLines === 0) { + if (didReadContent) result += " "; + } else result += "\n".repeat(emptyLines); + } else result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); result += content; didReadContent = true; emptyLines = 0; @@ -167474,24 +167474,69 @@ var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { "!": "!", "!!": "tag:yaml.org,2002:" }); -function tagPercentEncode(source) { - return encodeURI(source).replace(/!/g, "%21"); +var TAG_SUFFIX_CHARS = "-#;/?:@&=+$_.~*'()"; +var TAG_URI_CHARS = TAG_SUFFIX_CHARS + "!,[]"; +var HEX = "0123456789ABCDEF"; +function percentByte(byte) { + return "%" + HEX[byte >> 4] + HEX[byte & 15]; +} +function tagPercentEncode(source, isSuffix) { + const allowed = isSuffix ? TAG_SUFFIX_CHARS : TAG_URI_CHARS; + let result = ""; + for (let index2 = 0; index2 < source.length; index2++) { + let ch = source.charCodeAt(index2); + if (ch >= 48 && ch <= 57 || ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || allowed.includes(source[index2])) { + result += source[index2]; + continue; + } + if (ch >= 55296 && ch <= 56319) ch = 65536 + ((ch & 1023) << 10) + (source.charCodeAt(++index2) & 1023); + if (ch < 128) result += percentByte(ch); + else if (ch < 2048) result += percentByte(192 | ch >> 6) + percentByte(128 | ch & 63); + else if (ch < 65536) result += percentByte(224 | ch >> 12) + percentByte(128 | ch >> 6 & 63) + percentByte(128 | ch & 63); + else result += percentByte(240 | ch >> 18) + percentByte(128 | ch >> 12 & 63) + percentByte(128 | ch >> 6 & 63) + percentByte(128 | ch & 63); + } + return result; +} +function tagPercentDecode(source) { + let result = ""; + let index2 = 0; + while (index2 < source.length) { + if (source.charCodeAt(index2) !== 37) { + result += source[index2++]; + continue; + } + let ch = parseInt(source.slice(index2 + 1, index2 + 3), 16); + index2 += 3; + if (ch >= 192) { + let remaining = ch < 224 ? 1 : ch < 240 ? 2 : 3; + ch &= (1 << 6 - remaining) - 1; + while (remaining-- > 0) { + ch = ch << 6 | parseInt(source.slice(index2 + 1, index2 + 3), 16) & 63; + index2 += 3; + } + } + if (ch < 65536) result += String.fromCharCode(ch); + else { + ch -= 65536; + result += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023); + } + } + return result; } function tagNameFull(rawTag, tagHandlers) { - if (rawTag.startsWith("!<") && rawTag.endsWith(">")) return decodeURIComponent(rawTag.slice(2, -1)); + if (rawTag.startsWith("!<") && rawTag.endsWith(">")) return tagPercentDecode(rawTag.slice(2, -1)); const handleEnd = rawTag.indexOf("!", 1); const handle = handleEnd === -1 ? "!" : rawTag.slice(0, handleEnd + 1); - const prefix = tagHandlers?.[handle] ?? DEFAULT_TAG_HANDLERS[handle] ?? handle; - return decodeURIComponent(prefix) + decodeURIComponent(rawTag.slice(handle.length)); + return tagPercentDecode(tagHandlers?.[handle] ?? DEFAULT_TAG_HANDLERS[handle] ?? handle) + tagPercentDecode(rawTag.slice(handle.length)); } function tagNameShort(fullTag) { let tag = fullTag; if (tag.charCodeAt(0) === 33) { tag = tag.slice(1); - return `!${tagPercentEncode(tag)}`; + return `!${tagPercentEncode(tag, true)}`; } - if (tag.slice(0, 18) === "tag:yaml.org,2002:") return `!!${tagPercentEncode(tag.slice(18))}`; - return `!<${tagPercentEncode(tag)}>`; + if (tag.slice(0, 18) === "tag:yaml.org,2002:") return `!!${tagPercentEncode(tag.slice(18), true)}`; + return `!<${tagPercentEncode(tag, false)}>`; } var NO_RANGE$2 = -1; var MERGE_TAG_NAME = "tag:yaml.org,2002:merge"; @@ -167954,7 +167999,11 @@ function skipUntilLineEnd(state) { while (ch !== 0 && !isEol(ch)) ch = state.input.charCodeAt(++state.position); } function checkPrintable(state, start, end) { - if (PATTERN_NON_PRINTABLE.test(state.input.slice(start, end))) throwError(state, "the stream contains non-printable characters"); + const match2 = PATTERN_NON_PRINTABLE.exec(state.input.slice(start, end)); + if (match2 !== null) { + state.position = start + match2.index + match2[0].length - 1; + throwError(state, "the stream contains non-printable characters"); + } } function readTagProperty(state, props, inFlow) { if (state.input.charCodeAt(state.position) !== 33) return false; @@ -167981,12 +168030,14 @@ function readTagProperty(state, props, inFlow) { state.position++; } else { while (ch !== 0 && !isWsOrEol(ch) && !(inFlow && isFlowIndicator(ch))) { - if (ch === 33) if (!isNamed) { - tagHandle = state.input.slice(suffixStart - 1, state.position + 1); - if (!PATTERN_TAG_HANDLE.test(tagHandle)) throwError(state, "named tag handle cannot contain such characters"); - isNamed = true; - suffixStart = state.position + 1; - } else throwError(state, "tag suffix cannot contain exclamation marks"); + if (ch === 33) { + if (!isNamed) { + tagHandle = state.input.slice(suffixStart - 1, state.position + 1); + if (!PATTERN_TAG_HANDLE.test(tagHandle)) throwError(state, "named tag handle cannot contain such characters"); + isNamed = true; + suffixStart = state.position + 1; + } else throwError(state, "tag suffix cannot contain exclamation marks"); + } ch = state.input.charCodeAt(++state.position); } tagName = state.input.slice(suffixStart, state.position); @@ -168170,7 +168221,7 @@ function readBlockScalar(state, parentIndent, props) { function canStartPlainScalar(state, nodeContext) { const ch = state.input.charCodeAt(state.position); const inFlow = nodeContext === CONTEXT_FLOW_IN; - if (ch === 0 || isWsOrEol(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96 || inFlow && isFlowIndicator(ch)) return false; + if (ch === 0 || isWsOrEol(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96 || isFlowIndicator(ch)) return false; if (ch === 63 || ch === 45) { const following = state.input.charCodeAt(state.position + 1); if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) return false; @@ -168442,19 +168493,20 @@ function parseNode(state, parentIndent, nodeContext, allowToSeek, allowCompact, if (indentStatus === 1 || nodeContext === CONTEXT_BLOCK_OUT) { const flowIndent = nodeContext === CONTEXT_FLOW_IN || nodeContext === CONTEXT_FLOW_OUT ? parentIndent : parentIndent + 1; const blockIndent = state.position - state.lineStart; - if (indentStatus === 1) if (allowBlockCollections && (readBlockSequence(state, blockIndent, props) || readBlockMapping(state, blockIndent, flowIndent, props)) || readFlowCollection(state, flowIndent, props)) hasContent = true; - else { - const ch = state.input.charCodeAt(state.position); - if (propertyStart !== null && allowPropertyMapping && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62) { - const fallbackState = snapshotState(state); - const propertyIndent = propertyStart.position - propertyStart.lineStart; - restoreState(state, propertyStart); - if (readBlockMapping(state, propertyIndent, flowIndent, emptyProperties()) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) hasContent = true; - else restoreState(state, fallbackState); + if (indentStatus === 1) { + if (allowBlockCollections && (readBlockSequence(state, blockIndent, props) || readBlockMapping(state, blockIndent, flowIndent, props)) || readFlowCollection(state, flowIndent, props)) hasContent = true; + else { + const ch = state.input.charCodeAt(state.position); + if (propertyStart !== null && allowPropertyMapping && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62) { + const fallbackState = snapshotState(state); + const propertyIndent = propertyStart.position - propertyStart.lineStart; + restoreState(state, propertyStart); + if (readBlockMapping(state, propertyIndent, flowIndent, emptyProperties()) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) hasContent = true; + else restoreState(state, fallbackState); + } + if (!hasContent && (allowBlockScalars && readBlockScalar(state, flowIndent, props) || readSingleQuotedScalar(state, flowIndent, props) || readDoubleQuotedScalar(state, flowIndent, props) || readAlias(state, props) || readPlainScalar(state, flowIndent, nodeContext, props))) hasContent = true; } - if (!hasContent && (allowBlockScalars && readBlockScalar(state, flowIndent, props) || readSingleQuotedScalar(state, flowIndent, props) || readDoubleQuotedScalar(state, flowIndent, props) || readAlias(state, props) || readPlainScalar(state, flowIndent, nodeContext, props))) hasContent = true; - } - else if (indentStatus === 0) hasContent = allowBlockCollections && readBlockSequence(state, blockIndent, props); + } else if (indentStatus === 0) hasContent = allowBlockCollections && readBlockSequence(state, blockIndent, props); } allowBlockScalars = allowBlockScalars && !hasContent; if (!hasContent && (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1 || allowBlockScalars)) { @@ -168747,7 +168799,6 @@ function visitNode(node, visitor, ctx) { isKey: false })) return true; } - break; } return false; } @@ -169185,8 +169236,10 @@ function writeBlockMapping(state, level, node, compact) { const keyHasLineBreak = key.kind === "scalar" && key.value.indexOf("\n") !== -1; const keyIsTooLong = keyText.length > 1024 && /^[\s\S]{1025}/u.test(keyText); const explicitPair = keyIsBlock || keyHasLineBreak || keyIsTooLong; - if (explicitPair) if (keyText && CHAR_LINE_FEED === keyText.charCodeAt(0)) pairBuffer += "?"; - else pairBuffer += "? "; + if (explicitPair) { + if (keyText && CHAR_LINE_FEED === keyText.charCodeAt(0)) pairBuffer += "?"; + else pairBuffer += "? "; + } pairBuffer += keyText; if (explicitPair) pairBuffer += generateNextLine(state, level); const valueText = writeNode(state, level + 1, value, node, { @@ -169222,12 +169275,15 @@ function writeNode(state, level, node, parent, ctx) { let body; let shouldPrintTag = node.tagged; const useBlockCollection = block && (node.kind === "mapping" || node.kind === "sequence") && node.style === COLLECTION_STYLE.BLOCK && node.items.length !== 0; - if (node.kind === "mapping") if (useBlockCollection) body = writeBlockMapping(state, level, node, compact); - else body = writeFlowMapping(state, level, node); - else if (node.kind === "sequence") if (useBlockCollection) if (state.seqNoIndent && !isblockseq && level > 0) body = writeBlockSequence(state, level - 1, node, compact); - else body = writeBlockSequence(state, level, node, compact); - else body = writeFlowSequence(state, level, node); - else { + if (node.kind === "mapping") { + if (useBlockCollection) body = writeBlockMapping(state, level, node, compact); + else body = writeFlowMapping(state, level, node); + } else if (node.kind === "sequence") { + if (useBlockCollection) { + if (state.seqNoIndent && !isblockseq && level > 0) body = writeBlockSequence(state, level - 1, node, compact); + else body = writeBlockSequence(state, level, node, compact); + } else body = writeFlowSequence(state, level, node); + } else { const layout = scalarLayout(state, node, parent, level, iskey, !block); detectAllowedStyles(layout); for (const rule of state.scalarStyleRules) rule(layout); @@ -188714,7 +188770,7 @@ tmp/lib/tmp.js: *) js-yaml/dist/js-yaml.mjs: - (*! js-yaml 5.4.3 https://github.com/nodeca/js-yaml @license MIT *) + (*! js-yaml 5.5.0 https://github.com/nodeca/js-yaml @license MIT *) long/index.js: (** From 179d51bf5672d6ae81e3de1d812502a060e2a6a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Oct 2026 11:57:33 +0000 Subject: [PATCH 102/174] Bump actions/download-artifact Bumps the actions-minor group with 1 update in the /.github/workflows directory: [actions/download-artifact](https://github.com/actions/download-artifact). Updates `actions/download-artifact` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v8.0.1...9000827ccba6bdab643e8b6fd33ac0654aef8333) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 8.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/__diagnostics-without-db.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/__diagnostics-without-db.yml b/.github/workflows/__diagnostics-without-db.yml index 28472c95a7..44c24fa683 100644 --- a/.github/workflows/__diagnostics-without-db.yml +++ b/.github/workflows/__diagnostics-without-db.yml @@ -122,7 +122,7 @@ jobs: - name: Install dependencies run: npm ci - name: Download workflow artifact - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: pattern: test-mode-sarif-* path: sarif From 2d923f7a7ef6057de18fc394f31400d393a5037f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Oct 2026 11:57:40 +0000 Subject: [PATCH 103/174] Bump actions/setup-node in /.github/actions/release-initialise Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.4.0 to 7.1.0. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e...949feb2413d6458794dcd2491c4babbbce0c15c1) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: 7.1.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/actions/release-initialise/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/release-initialise/action.yml b/.github/actions/release-initialise/action.yml index 239dfa9428..b734377a76 100644 --- a/.github/actions/release-initialise/action.yml +++ b/.github/actions/release-initialise/action.yml @@ -16,7 +16,7 @@ runs: shell: bash - name: Set up Node - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 24 cache: 'npm' From 05650bc71bb43d7f47620efaa3bc699757f337d0 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Mon, 26 Oct 2026 18:21:56 +0000 Subject: [PATCH 104/174] Fix "Debug artifacts after failure" PR check not checking any artifacts Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/debug-artifacts-failure-safe.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/debug-artifacts-failure-safe.yml b/.github/workflows/debug-artifacts-failure-safe.yml index 4f9082acd2..38c4045d33 100644 --- a/.github/workflows/debug-artifacts-failure-safe.yml +++ b/.github/workflows/debug-artifacts-failure-safe.yml @@ -97,6 +97,7 @@ jobs: uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 - name: Check expected artifacts exist run: | + VERSIONS="stable-v2.20.7 default linked nightly-latest" LANGUAGES="cpp csharp go java javascript python" for version in $VERSIONS; do echo "Artifacts from version $version:" From ab6209be6cc9cf93ad14004d6a84ecd532cb373a Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 27 Oct 2026 11:54:06 +0000 Subject: [PATCH 105/174] Exclude main project tests from `pr-checks/tsconfig.json` --- pr-checks/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr-checks/tsconfig.json b/pr-checks/tsconfig.json index e0a6c856c9..367148ab9a 100644 --- a/pr-checks/tsconfig.json +++ b/pr-checks/tsconfig.json @@ -9,5 +9,5 @@ "noEmit": true }, "include": ["./**/*.ts", "../src/**/*.ts"], - "exclude": ["node_modules"] + "exclude": ["node_modules", "../src/**/*.test.ts"] } From 9b9c8e25e2a1de532783c33b13f01712209663bb Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 27 Oct 2026 11:56:09 +0000 Subject: [PATCH 106/174] Add check commands to `pr-checks/package.json` --- pr-checks/package.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pr-checks/package.json b/pr-checks/package.json index 343f943814..f96b919c15 100644 --- a/pr-checks/package.json +++ b/pr-checks/package.json @@ -2,6 +2,11 @@ "private": true, "description": "Dependencies for codeql-action scripts", "type": "module", + "scripts": { + "typecheck": "tsc --noEmit", + "test": "npx tsx --test", + "checks": "npm run typecheck && npm run test" + }, "dependencies": { "@actions/core": "^2.0.3", "@actions/github": "^8.0.1", From 405433cc6d34f0c9c57178fef0ff71433212695c Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 27 Oct 2026 11:56:52 +0000 Subject: [PATCH 107/174] Add `typecheck` command to `package.json` --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 76ac14cf2d..31607ff78a 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "test": "npm run ava -- src/", "test-debug": "npm run test -- --timeout=20m", "transpile": "tsc --build --verbose tsconfig.json", - "update-pr-checks": "./pr-checks/sync.sh" + "update-pr-checks": "./pr-checks/sync.sh", + "typecheck": "tsc --noEmit" }, "license": "MIT", "workspaces": [ From fe36f120dfa28d8c2fd951bf90ccac2dea5809dd Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 27 Oct 2026 11:57:35 +0000 Subject: [PATCH 108/174] Run `checks` command for `pr-checks` in CI --- .github/workflows/pr-checks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 5d2b1576f7..ba6dfbcdb8 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -126,10 +126,10 @@ jobs: if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }} run: .github/workflows/script/verify-pr-checks.sh - - name: Run pr-checks tests + - name: Run pr-checks checks if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }} working-directory: pr-checks - run: npx tsx --test + run: npm run checks - name: Run `pr-checks/changenotes.ts` to ensure that all unreleased change notes are valid if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }} From d1617c5ce486d0e812456cf82a0ec21dcba77283 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 Oct 2026 11:59:57 +0000 Subject: [PATCH 109/174] Rebuild --- pr-checks/checks/diagnostics-without-db.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr-checks/checks/diagnostics-without-db.yml b/pr-checks/checks/diagnostics-without-db.yml index 0d43f1c628..a7c47a3d73 100644 --- a/pr-checks/checks/diagnostics-without-db.yml +++ b/pr-checks/checks/diagnostics-without-db.yml @@ -53,7 +53,7 @@ validationJobs: installNode: true steps: - name: Download workflow artifact - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: pattern: test-mode-sarif-* path: sarif From 0d774618aa9a151885c6fba30e9bdcf6e919596d Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 28 Oct 2026 12:19:56 +0000 Subject: [PATCH 110/174] Replace `Env` with `ReadOnlyEnv` in the `runTool` chain --- src/actions-util.ts | 2 +- src/codeql.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/actions-util.ts b/src/actions-util.ts index 096bdd8f15..abd29a0522 100644 --- a/src/actions-util.ts +++ b/src/actions-util.ts @@ -364,7 +364,7 @@ const MAX_STDERR_BUFFER_SIZE = 20000; * @throws A {@link CommandInvocationError} if the tool exits with a non-zero status code. */ export async function runTool( - env: Env, + env: ReadOnlyEnv, cmd: string, args: string[] = [], opts: { stdin?: string; noStreamStdout?: boolean } = {}, diff --git a/src/codeql.ts b/src/codeql.ts index 8f2d9843e0..ca93cedf12 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -1166,7 +1166,7 @@ export function getExtraOptions( } async function runCli( - env: Env, + env: ReadOnlyEnv, cmd: string, args: string[] = [], opts: { stdin?: string; noStreamStdout?: boolean } = {}, @@ -1193,7 +1193,7 @@ async function runCli( * @returns The parsed JSON output from the command. */ async function runCliJson( - env: Env, + env: ReadOnlyEnv, cmd: string, args: string[] = [], opts: { stdin?: string; noStreamStdout?: boolean } = {}, From f3641059508e762bb311064d5dad36675743afa7 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 10:38:02 +0100 Subject: [PATCH 111/174] Add `osRelease` to `BaseState` --- lib/entry-points.js | 144 ++++++++++++++++++++++--------------------- src/action-common.ts | 5 ++ src/testing-utils.ts | 2 + 3 files changed, 80 insertions(+), 71 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index c0c40d6ddd..c7c2e2c7f9 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -117,11 +117,11 @@ var require_command = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.issueCommand = issueCommand; exports2.issue = issue; - var os7 = __importStar2(require("os")); + var os8 = __importStar2(require("os")); var utils_1 = require_utils(); function issueCommand(command, properties, message) { const cmd = new Command(command, properties, message); - process.stdout.write(cmd.toString() + os7.EOL); + process.stdout.write(cmd.toString() + os8.EOL); } function issue(name, message = "") { issueCommand(name, {}, message); @@ -214,7 +214,7 @@ var require_file_command = __commonJS({ exports2.prepareKeyValueMessage = prepareKeyValueMessage; var crypto3 = __importStar2(require("crypto")); var fs33 = __importStar2(require("fs")); - var os7 = __importStar2(require("os")); + var os8 = __importStar2(require("os")); var utils_1 = require_utils(); function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; @@ -224,7 +224,7 @@ var require_file_command = __commonJS({ if (!fs33.existsSync(filePath)) { throw new Error(`Missing file at path: ${filePath}`); } - fs33.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os7.EOL}`, { + fs33.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os8.EOL}`, { encoding: "utf8" }); } @@ -237,7 +237,7 @@ var require_file_command = __commonJS({ if (convertedValue.includes(delimiter)) { throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); } - return `${key}<<${delimiter}${os7.EOL}${convertedValue}${os7.EOL}${delimiter}`; + return `${key}<<${delimiter}${os8.EOL}${convertedValue}${os8.EOL}${delimiter}`; } } }); @@ -28606,7 +28606,7 @@ var require_toolrunner = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.ToolRunner = void 0; exports2.argStringToArray = argStringToArray; - var os7 = __importStar2(require("os")); + var os8 = __importStar2(require("os")); var events = __importStar2(require("events")); var child = __importStar2(require("child_process")); var path30 = __importStar2(require("path")); @@ -28661,12 +28661,12 @@ var require_toolrunner = __commonJS({ _processLineBuffer(data, strBuffer, onLine) { try { let s = strBuffer + data.toString(); - let n = s.indexOf(os7.EOL); + let n = s.indexOf(os8.EOL); while (n > -1) { const line = s.substring(0, n); onLine(line); - s = s.substring(n + os7.EOL.length); - n = s.indexOf(os7.EOL); + s = s.substring(n + os8.EOL.length); + n = s.indexOf(os8.EOL); } return s; } catch (err) { @@ -28835,7 +28835,7 @@ var require_toolrunner = __commonJS({ } const optionsNonNull = this._cloneExecOptions(this.options); if (!optionsNonNull.silent && optionsNonNull.outStream) { - optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os7.EOL); + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os8.EOL); } const state = new ExecState(optionsNonNull, this.toolPath); state.on("debug", (message) => { @@ -29376,7 +29376,7 @@ var require_core = __commonJS({ var command_1 = require_command(); var file_command_1 = require_file_command(); var utils_1 = require_utils(); - var os7 = __importStar2(require("os")); + var os8 = __importStar2(require("os")); var path30 = __importStar2(require("path")); var oidc_utils_1 = require_oidc_utils(); var ExitCode; @@ -29438,7 +29438,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); if (filePath) { return (0, file_command_1.issueFileCommand)("OUTPUT", (0, file_command_1.prepareKeyValueMessage)(name, value)); } - process.stdout.write(os7.EOL); + process.stdout.write(os8.EOL); (0, command_1.issueCommand)("set-output", { name }, (0, utils_1.toCommandValue)(value)); } function setCommandEcho(enabled) { @@ -29464,7 +29464,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); (0, command_1.issueCommand)("notice", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); } function info8(message) { - process.stdout.write(message + os7.EOL); + process.stdout.write(message + os8.EOL); } function startGroup3(name) { (0, command_1.issue)("group", name); @@ -34542,8 +34542,8 @@ var require_semver = __commonJS({ } // preminor will bump the version up to the next minor release, and immediately // down to pre-release. premajor and prepatch work the same way. - inc(release2, identifier, identifierBase) { - if (release2.startsWith("pre")) { + inc(release3, identifier, identifierBase) { + if (release3.startsWith("pre")) { if (!identifier && identifierBase === false) { throw new Error("invalid increment argument: identifier is empty"); } @@ -34554,7 +34554,7 @@ var require_semver = __commonJS({ } } } - switch (release2) { + switch (release3) { case "premajor": this.prerelease.length = 0; this.patch = 0; @@ -34646,7 +34646,7 @@ var require_semver = __commonJS({ break; } default: - throw new Error(`invalid increment argument: ${release2}`); + throw new Error(`invalid increment argument: ${release3}`); } this.raw = this.format(); if (this.build.length) { @@ -34712,7 +34712,7 @@ var require_inc = __commonJS({ "node_modules/semver/functions/inc.js"(exports2, module2) { "use strict"; var SemVer = require_semver(); - var inc = (version, release2, options, identifier, identifierBase) => { + var inc = (version, release3, options, identifier, identifierBase) => { if (typeof options === "string") { identifierBase = identifier; identifier = options; @@ -34722,7 +34722,7 @@ var require_inc = __commonJS({ return new SemVer( version instanceof SemVer ? version.version : version, options - ).inc(release2, identifier, identifierBase).version; + ).inc(release3, identifier, identifierBase).version; } catch (er) { return null; } @@ -40457,7 +40457,7 @@ var require_internal_pattern = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.Pattern = void 0; - var os7 = __importStar2(require("os")); + var os8 = __importStar2(require("os")); var path30 = __importStar2(require("path")); var pathHelper = __importStar2(require_internal_path_helper()); var assert_1 = __importDefault2(require("assert")); @@ -40550,7 +40550,7 @@ var require_internal_pattern = __commonJS({ if (pattern === "." || pattern.startsWith(`.${path30.sep}`)) { pattern = _Pattern.globEscape(process.cwd()) + pattern.substr(1); } else if (pattern === "~" || pattern.startsWith(`~${path30.sep}`)) { - homedir2 = homedir2 || os7.homedir(); + homedir2 = homedir2 || os8.homedir(); (0, assert_1.default)(homedir2, "Unable to determine HOME directory"); (0, assert_1.default)(pathHelper.hasAbsoluteRoot(homedir2), `Expected HOME directory to be a rooted path. Actual '${homedir2}'`); pattern = _Pattern.globEscape(homedir2) + pattern.substr(1); @@ -41442,8 +41442,8 @@ var require_semver3 = __commonJS({ } } while (++i2); }; - SemVer.prototype.inc = function(release2, identifier) { - switch (release2) { + SemVer.prototype.inc = function(release3, identifier) { + switch (release3) { case "premajor": this.prerelease.length = 0; this.patch = 0; @@ -41519,20 +41519,20 @@ var require_semver3 = __commonJS({ } break; default: - throw new Error("invalid increment argument: " + release2); + throw new Error("invalid increment argument: " + release3); } this.format(); this.raw = this.version; return this; }; exports2.inc = inc; - function inc(version, release2, loose, identifier) { + function inc(version, release3, loose, identifier) { if (typeof loose === "string") { identifier = loose; loose = void 0; } try { - return new SemVer(version, loose).inc(release2, identifier).version; + return new SemVer(version, loose).inc(release3, identifier).version; } catch (er) { return null; } @@ -45668,7 +45668,7 @@ var require_has_flag = __commonJS({ var require_supports_color = __commonJS({ "node_modules/supports-color/index.js"(exports2, module2) { "use strict"; - var os7 = require("os"); + var os8 = require("os"); var tty = require("tty"); var hasFlag = require_has_flag(); var { env } = process; @@ -45716,7 +45716,7 @@ var require_supports_color = __commonJS({ return min; } if (process.platform === "win32") { - const osRelease = os7.release().split("."); + const osRelease = os8.release().split("."); if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) { return Number(osRelease[2]) >= 14931 ? 3 : 2; } @@ -114074,12 +114074,12 @@ var require_manifest = __commonJS({ exports2._readLinuxVersionFile = _readLinuxVersionFile; var semver11 = __importStar2(require_semver2()); var core_1 = require_core(); - var os7 = require("os"); + var os8 = require("os"); var cp = require("child_process"); var fs33 = require("fs"); function _findMatch(versionSpec, stable, candidates, archFilter) { return __awaiter2(this, void 0, void 0, function* () { - const platFilter = os7.platform(); + const platFilter = os8.platform(); let result; let match2; let file; @@ -114115,7 +114115,7 @@ var require_manifest = __commonJS({ }); } function _getOsVersion() { - const plat = os7.platform(); + const plat = os8.platform(); let version = ""; if (plat === "darwin") { version = cp.execSync("sw_vers -productVersion").toString(); @@ -114352,7 +114352,7 @@ var require_tool_cache = __commonJS({ var crypto3 = __importStar2(require("crypto")); var fs33 = __importStar2(require("fs")); var mm = __importStar2(require_manifest()); - var os7 = __importStar2(require("os")); + var os8 = __importStar2(require("os")); var path30 = __importStar2(require("path")); var httpm = __importStar2(require_lib()); var semver11 = __importStar2(require_semver2()); @@ -114629,7 +114629,7 @@ var require_tool_cache = __commonJS({ function cacheDir2(sourceDir, tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { version = semver11.clean(version) || version; - arch2 = arch2 || os7.arch(); + arch2 = arch2 || os8.arch(); core29.debug(`Caching tool ${tool} ${version} ${arch2}`); core29.debug(`source dir: ${sourceDir}`); if (!fs33.statSync(sourceDir).isDirectory()) { @@ -114647,7 +114647,7 @@ var require_tool_cache = __commonJS({ function cacheFile(sourceFile, targetFile, tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { version = semver11.clean(version) || version; - arch2 = arch2 || os7.arch(); + arch2 = arch2 || os8.arch(); core29.debug(`Caching tool ${tool} ${version} ${arch2}`); core29.debug(`source file: ${sourceFile}`); if (!fs33.statSync(sourceFile).isFile()) { @@ -114668,7 +114668,7 @@ var require_tool_cache = __commonJS({ if (!versionSpec) { throw new Error("versionSpec parameter is required"); } - arch2 = arch2 || os7.arch(); + arch2 = arch2 || os8.arch(); if (!isExplicitVersion(versionSpec)) { const localVersions = findAllVersions2(toolName, arch2); const match2 = evaluateVersions(localVersions, versionSpec); @@ -114690,7 +114690,7 @@ var require_tool_cache = __commonJS({ } function findAllVersions2(toolName, arch2) { const versions = []; - arch2 = arch2 || os7.arch(); + arch2 = arch2 || os8.arch(); const toolPath = path30.join(_getCacheDirectory(), toolName); if (fs33.existsSync(toolPath)) { const children = fs33.readdirSync(toolPath); @@ -114740,7 +114740,7 @@ var require_tool_cache = __commonJS({ }); } function findFromManifest(versionSpec_1, stable_1, manifest_1) { - return __awaiter2(this, arguments, void 0, function* (versionSpec, stable, manifest, archFilter = os7.arch()) { + return __awaiter2(this, arguments, void 0, function* (versionSpec, stable, manifest, archFilter = os8.arch()) { const match2 = yield mm._findMatch(versionSpec, stable, manifest, archFilter); return match2; }); @@ -135749,9 +135749,9 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s)) retur Wt.LRUCache = void 0; var er = typeof performance == "object" && performance && typeof performance.now == "function" ? performance : Date, as = /* @__PURE__ */ new Set(), ge = typeof process == "object" && process ? process : {}, ls = (n, t, e, s) => { typeof ge.emitWarning == "function" ? ge.emitWarning(n, t, e, s) : console.error(`[${e}] ${t}: ${n}`); - }, Lt = globalThis.AbortController, os7 = globalThis.AbortSignal; + }, Lt = globalThis.AbortController, os8 = globalThis.AbortSignal; if (typeof Lt > "u") { - os7 = class { + os8 = class { onabort; _onabort = []; reason; @@ -135763,7 +135763,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s)) retur constructor() { t(); } - signal = new os7(); + signal = new os8(); abort(e) { if (!this.signal.aborted) { this.signal.reason = e, this.signal.aborted = true; @@ -150720,11 +150720,11 @@ var require_command2 = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.issue = exports2.issueCommand = void 0; - var os7 = __importStar2(require("os")); + var os8 = __importStar2(require("os")); var utils_1 = require_utils11(); function issueCommand(command, properties, message) { const cmd = new Command(command, properties, message); - process.stdout.write(cmd.toString() + os7.EOL); + process.stdout.write(cmd.toString() + os8.EOL); } exports2.issueCommand = issueCommand; function issue(name, message = "") { @@ -150808,7 +150808,7 @@ var require_file_command2 = __commonJS({ exports2.prepareKeyValueMessage = exports2.issueFileCommand = void 0; var crypto3 = __importStar2(require("crypto")); var fs33 = __importStar2(require("fs")); - var os7 = __importStar2(require("os")); + var os8 = __importStar2(require("os")); var utils_1 = require_utils11(); function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; @@ -150818,7 +150818,7 @@ var require_file_command2 = __commonJS({ if (!fs33.existsSync(filePath)) { throw new Error(`Missing file at path: ${filePath}`); } - fs33.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os7.EOL}`, { + fs33.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os8.EOL}`, { encoding: "utf8" }); } @@ -150832,7 +150832,7 @@ var require_file_command2 = __commonJS({ if (convertedValue.includes(delimiter)) { throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); } - return `${key}<<${delimiter}${os7.EOL}${convertedValue}${os7.EOL}${delimiter}`; + return `${key}<<${delimiter}${os8.EOL}${convertedValue}${os8.EOL}${delimiter}`; } exports2.prepareKeyValueMessage = prepareKeyValueMessage; } @@ -152561,7 +152561,7 @@ var require_toolrunner2 = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.argStringToArray = exports2.ToolRunner = void 0; - var os7 = __importStar2(require("os")); + var os8 = __importStar2(require("os")); var events = __importStar2(require("events")); var child = __importStar2(require("child_process")); var path30 = __importStar2(require("path")); @@ -152616,12 +152616,12 @@ var require_toolrunner2 = __commonJS({ _processLineBuffer(data, strBuffer, onLine) { try { let s = strBuffer + data.toString(); - let n = s.indexOf(os7.EOL); + let n = s.indexOf(os8.EOL); while (n > -1) { const line = s.substring(0, n); onLine(line); - s = s.substring(n + os7.EOL.length); - n = s.indexOf(os7.EOL); + s = s.substring(n + os8.EOL.length); + n = s.indexOf(os8.EOL); } return s; } catch (err) { @@ -152790,7 +152790,7 @@ var require_toolrunner2 = __commonJS({ } const optionsNonNull = this._cloneExecOptions(this.options); if (!optionsNonNull.silent && optionsNonNull.outStream) { - optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os7.EOL); + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os8.EOL); } const state = new ExecState(optionsNonNull, this.toolPath); state.on("debug", (message) => { @@ -153278,7 +153278,7 @@ var require_core3 = __commonJS({ var command_1 = require_command2(); var file_command_1 = require_file_command2(); var utils_1 = require_utils11(); - var os7 = __importStar2(require("os")); + var os8 = __importStar2(require("os")); var path30 = __importStar2(require("path")); var oidc_utils_1 = require_oidc_utils2(); var ExitCode; @@ -153346,7 +153346,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); if (filePath) { return (0, file_command_1.issueFileCommand)("OUTPUT", (0, file_command_1.prepareKeyValueMessage)(name, value)); } - process.stdout.write(os7.EOL); + process.stdout.write(os8.EOL); (0, command_1.issueCommand)("set-output", { name }, (0, utils_1.toCommandValue)(value)); } exports2.setOutput = setOutput7; @@ -153380,7 +153380,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); } exports2.notice = notice; function info8(message) { - process.stdout.write(message + os7.EOL); + process.stdout.write(message + os8.EOL); } exports2.info = info8; function startGroup3(name) { @@ -153579,15 +153579,15 @@ var require_upload_specification = __commonJS({ var require_tmp = __commonJS({ "node_modules/tmp/lib/tmp.js"(exports2, module2) { var fs33 = require("fs"); - var os7 = require("os"); + var os8 = require("os"); var path30 = require("path"); var crypto3 = require("crypto"); - var _c2 = { fs: fs33.constants, os: os7.constants }; + var _c2 = { fs: fs33.constants, os: os8.constants }; var RANDOM_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; var TEMPLATE_PATTERN = /XXXXXX/; var DEFAULT_TRIES = 3; var CREATE_FLAGS = (_c2.O_CREAT || _c2.fs.O_CREAT) | (_c2.O_EXCL || _c2.fs.O_EXCL) | (_c2.O_RDWR || _c2.fs.O_RDWR); - var IS_WIN32 = os7.platform() === "win32"; + var IS_WIN32 = os8.platform() === "win32"; var EBADF = _c2.EBADF || _c2.os.errno.EBADF; var ENOENT = _c2.ENOENT || _c2.os.errno.ENOENT; var DIR_MODE = 448; @@ -153926,10 +153926,10 @@ var require_tmp = __commonJS({ _gracefulCleanup = true; } function _getTmpDir(options, cb) { - return fs33.realpath(options && options.tmpdir || os7.tmpdir(), cb); + return fs33.realpath(options && options.tmpdir || os8.tmpdir(), cb); } function _getTmpDirSync(options) { - return fs33.realpathSync(options && options.tmpdir || os7.tmpdir()); + return fs33.realpathSync(options && options.tmpdir || os8.tmpdir()); } process.addListener(EXIT, _garbageCollector); Object.defineProperty(module2.exports, "tmpdir", { @@ -173785,6 +173785,7 @@ var import_perf_hooks6 = require("perf_hooks"); var core14 = __toESM(require_core()); // src/action-common.ts +var os4 = __toESM(require("os")); var core9 = __toESM(require_core()); // src/actions-util.ts @@ -179559,6 +179560,7 @@ async function runInActions(action) { startedAt, platform: process.platform, arch: process.arch, + osRelease: os4.release(), logger: logger2, env, actions: actionsEnv @@ -183576,12 +183578,12 @@ async function getCodeQLAssetDownloadURL(action, apiDetails, tagName, assetName, } const { owner: repositoryOwner, repo: repositoryName } = parseRepositoryNwo(repository); try { - const release2 = await getApiClient().rest.repos.getReleaseByTag({ + const release3 = await getApiClient().rest.repos.getReleaseByTag({ owner: repositoryOwner, repo: repositoryName, tag: tagName }); - for (const asset of release2.data.assets) { + for (const asset of release3.data.assets) { if (asset.name === assetName) { action.logger.info( `Found ${assetKind} ${assetName} in ${repository} on ${instanceURL} with URL ${asset.url}.` @@ -183760,7 +183762,7 @@ function inferCompressionMethod(tarPath) { // src/tools-download.ts var fs14 = __toESM(require("fs")); -var os4 = __toESM(require("os")); +var os5 = __toESM(require("os")); var path12 = __toESM(require("path")); var import_perf_hooks3 = require("perf_hooks"); var core11 = __toESM(require_core()); @@ -183899,7 +183901,7 @@ function getToolcacheDirectory(version) { return path12.join( getToolcacheToolDirectory(getEnv()), getToolcacheVersionDirectoryName(version), - os4.arch() || "" + os5.arch() || "" ); } function isToolcacheOnWorkspaceFilesystem(logger2) { @@ -184608,14 +184610,14 @@ async function getLatestNightlyBundle(action, rawLanguages, otherLanguagePacksRe isLatestNightly: true }); try { - const release2 = await getApiClient().rest.repos.listReleases({ + const release3 = await getApiClient().rest.repos.listReleases({ owner: CODEQL_NIGHTLIES_REPOSITORY_OWNER, repo: CODEQL_NIGHTLIES_REPOSITORY_NAME, per_page: 1, page: 1, prerelease: true }); - const latestRelease = release2.data[0]; + const latestRelease = release3.data[0]; if (!latestRelease) { throw new Error("Could not find the latest nightly release."); } @@ -185443,7 +185445,7 @@ async function runAutobuild(config, language, logger2) { } // src/dependency-caching.ts -var os5 = __toESM(require("os")); +var os6 = __toESM(require("os")); var import_path3 = require("path"); var actionsCache4 = __toESM(require_cache6()); var glob = __toESM(require_glob()); @@ -185455,9 +185457,9 @@ function getJavaTempDependencyDir() { async function getJavaDependencyDirs() { return [ // Maven - (0, import_path3.join)(os5.homedir(), ".m2", "repository"), + (0, import_path3.join)(os6.homedir(), ".m2", "repository"), // Gradle - (0, import_path3.join)(os5.homedir(), ".gradle", "caches"), + (0, import_path3.join)(os6.homedir(), ".gradle", "caches"), // CodeQL Java build-mode: none getJavaTempDependencyDir() ]; @@ -185468,7 +185470,7 @@ function getCsharpTempDependencyDir() { async function getCsharpDependencyDirs(codeql, features) { const dirs = [ // Nuget - (0, import_path3.join)(os5.homedir(), ".nuget", "packages") + (0, import_path3.join)(os6.homedir(), ".nuget", "packages") ]; if (await features.getValue("csharp_cache_bmn" /* CsharpCacheBuildModeNone */, codeql)) { dirs.push(getCsharpTempDependencyDir()); @@ -185523,7 +185525,7 @@ var defaultCacheConfigs = { getHashPatterns: getCsharpHashPatterns }, go: { - getDependencyPaths: async () => [(0, import_path3.join)(os5.homedir(), "go", "pkg", "mod")], + getDependencyPaths: async () => [(0, import_path3.join)(os6.homedir(), "go", "pkg", "mod")], getHashPatterns: async () => internal.makePatternCheck(["**/go.sum"]) } }; @@ -193156,7 +193158,7 @@ var ZipArchive = class extends Archiver { // src/artifact-scanner.ts var fs26 = __toESM(require("fs")); -var os6 = __toESM(require("os")); +var os7 = __toESM(require("os")); var path22 = __toESM(require("path")); var exec = __toESM(require_exec()); var GITHUB_PAT_CLASSIC_PATTERN = { @@ -193360,7 +193362,7 @@ async function scanArtifactsForTokens(filesToScan, logger2) { scannedFiles: 0, findings: [] }; - const tempScanDir = fs26.mkdtempSync(path22.join(os6.tmpdir(), "artifact-scan-")); + const tempScanDir = fs26.mkdtempSync(path22.join(os7.tmpdir(), "artifact-scan-")); try { for (const filePath of filesToScan) { const stats = fs26.statSync(filePath); diff --git a/src/action-common.ts b/src/action-common.ts index 79f1901f22..b272869069 100644 --- a/src/action-common.ts +++ b/src/action-common.ts @@ -1,3 +1,5 @@ +import * as os from "os"; + import * as core from "@actions/core"; import { ActionsEnv, getActionsEnv } from "./actions-util"; @@ -23,6 +25,8 @@ export interface BaseState { platform: NodeJS.Platform; /** The architecture of the host. */ arch: NodeJS.Architecture; + /** The version of the operating system. */ + osRelease: string; } /** Describes different state features that an Action may have. */ @@ -173,6 +177,7 @@ export async function runInActions(action: Action) { startedAt, platform: process.platform, arch: process.arch, + osRelease: os.release(), logger, env, actions: actionsEnv, diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 92c77f2bc3..2dc68e2568 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -1,4 +1,5 @@ import { TextDecoder } from "node:util"; +import * as os from "os"; import path from "path"; import * as github from "@actions/github"; @@ -272,6 +273,7 @@ export function initAllState( startedAt: new Date(), platform: process.platform, arch: process.arch, + osRelease: os.release(), logger: new RecordingLogger(), env, actions: getTestActionsEnv(env), From 570e438cccd389884bc0d72493f5c4b368fbb2ec Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 17:28:08 +0100 Subject: [PATCH 112/174] Add `macOSVersion` helper --- src/platform.test.ts | 40 +++++++++++++++++++++++++++++++++++++++- src/platform.ts | 29 +++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/platform.test.ts b/src/platform.test.ts index c8a6a7955d..803e28b903 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -1,6 +1,7 @@ import test from "ava"; -import { BundlePlatform, getBundlePlatform } from "./platform"; +import { BundlePlatform, getBundlePlatform, macOSVersion } from "./platform"; +import { initAllState } from "./testing-utils"; for (const [platform, arch, expected] of [ ["linux", "x64", BundlePlatform.Linux64], @@ -16,3 +17,40 @@ for (const [platform, arch, expected] of [ t.is(getBundlePlatform(platform, arch), expected); }); } + +const platforms: NodeJS.Platform[] = ["linux", "win32", "freebsd"]; +for (const platform of platforms) { + test(`macOSVersion returns undefined on ${platform}`, (t) => { + t.is(macOSVersion(initAllState({ platform })), undefined); + }); +} + +test("macOSVersion returns raw string if semver parsing fails", (t) => { + const invalidSemVer = "sealOS-2026"; + t.is( + macOSVersion( + initAllState({ platform: "darwin", osRelease: invalidSemVer }), + ), + invalidSemVer, + ); +}); + +test("macOSVersion returns semver if parsing succeeds", (t) => { + const validSemVer = "27.0.1"; + + const version = macOSVersion( + initAllState({ platform: "darwin", osRelease: validSemVer }), + ); + + // Check that `version` is not undefined and narrow the type; throws if undefined. + if (t.truthy(version)) { + // Check that it's also not just a string. + t.not(typeof version, "string"); + + // Should be an object with the expected properties. + t.is(typeof version, "object"); + t.is(version["major"], 27); + t.is(version["minor"], 0); + t.is(version["patch"], 1); + } +}); diff --git a/src/platform.ts b/src/platform.ts index 1cc085d6ab..59785d3124 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -1,3 +1,7 @@ +import * as semver from "semver"; + +import type { ActionState } from "./action-common"; + /** Platform identifiers used in CodeQL bundle asset names. */ export enum BundlePlatform { Linux64 = "linux64", @@ -24,3 +28,28 @@ export function getBundlePlatform( return undefined; } } + +/** + * Tries to determine the version of macOS. + * + * @returns + * The version as either a semantic version object, the raw version string + * if it is not a semantic version, or `undefined` if we are not on macOS. + */ +export function macOSVersion( + action: ActionState<["Base"]>, +): semver.SemVer | string | undefined { + // Skip if we are not running on macOS. + if (action.platform !== "darwin") { + return undefined; + } + + // Try to parse the OS version string. + const version = semver.parse(action.osRelease); + + if (version === null) { + return action.osRelease; + } + + return version; +} From e0220172c95ff367ea6e59e82bbfa22c5c4ee62b Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 11:35:54 +0100 Subject: [PATCH 113/174] Use `macOSVersion` in `isSwiftCompatible` --- lib/entry-points.js | 157 ++++++++++++++++++++---------------- src/languages/swift.test.ts | 12 +++ src/languages/swift.ts | 24 ++++-- 3 files changed, 120 insertions(+), 73 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index c7c2e2c7f9..3bd8098e43 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -34664,7 +34664,7 @@ var require_parse2 = __commonJS({ "node_modules/semver/functions/parse.js"(exports2, module2) { "use strict"; var SemVer = require_semver(); - var parse3 = (version, options, throwErrors = false) => { + var parse4 = (version, options, throwErrors = false) => { if (version instanceof SemVer) { return version; } @@ -34677,7 +34677,7 @@ var require_parse2 = __commonJS({ throw er; } }; - module2.exports = parse3; + module2.exports = parse4; } }); @@ -34685,9 +34685,9 @@ var require_parse2 = __commonJS({ var require_valid = __commonJS({ "node_modules/semver/functions/valid.js"(exports2, module2) { "use strict"; - var parse3 = require_parse2(); + var parse4 = require_parse2(); var valid4 = (version, options) => { - const v = parse3(version, options); + const v = parse4(version, options); return v ? v.version : null; }; module2.exports = valid4; @@ -34698,9 +34698,9 @@ var require_valid = __commonJS({ var require_clean = __commonJS({ "node_modules/semver/functions/clean.js"(exports2, module2) { "use strict"; - var parse3 = require_parse2(); + var parse4 = require_parse2(); var clean3 = (version, options) => { - const s = parse3(version.trim().replace(/^[=v]+/, ""), options); + const s = parse4(version.trim().replace(/^[=v]+/, ""), options); return s ? s.version : null; }; module2.exports = clean3; @@ -34735,10 +34735,10 @@ var require_inc = __commonJS({ var require_diff = __commonJS({ "node_modules/semver/functions/diff.js"(exports2, module2) { "use strict"; - var parse3 = require_parse2(); + var parse4 = require_parse2(); var diff = (version1, version2) => { - const v1 = parse3(version1, null, true); - const v2 = parse3(version2, null, true); + const v1 = parse4(version1, null, true); + const v2 = parse4(version2, null, true); const comparison = v1.compare(v2); if (comparison === 0) { return null; @@ -34809,9 +34809,9 @@ var require_patch = __commonJS({ var require_prerelease = __commonJS({ "node_modules/semver/functions/prerelease.js"(exports2, module2) { "use strict"; - var parse3 = require_parse2(); + var parse4 = require_parse2(); var prerelease = (version, options) => { - const parsed = parse3(version, options); + const parsed = parse4(version, options); return parsed && parsed.prerelease.length ? parsed.prerelease : null; }; module2.exports = prerelease; @@ -34997,7 +34997,7 @@ var require_coerce = __commonJS({ "node_modules/semver/functions/coerce.js"(exports2, module2) { "use strict"; var SemVer = require_semver(); - var parse3 = require_parse2(); + var parse4 = require_parse2(); var { safeRe: re, t } = require_re(); var coerce3 = (version, options) => { if (version instanceof SemVer) { @@ -35032,7 +35032,7 @@ var require_coerce = __commonJS({ const patch = match2[4] || "0"; const prerelease = options.includePrerelease && match2[5] ? `-${match2[5]}` : ""; const build2 = options.includePrerelease && match2[6] ? `+${match2[6]}` : ""; - return parse3(`${major}.${minor}.${patch}${prerelease}${build2}`, options); + return parse4(`${major}.${minor}.${patch}${prerelease}${build2}`, options); }; module2.exports = coerce3; } @@ -35042,7 +35042,7 @@ var require_coerce = __commonJS({ var require_truncate = __commonJS({ "node_modules/semver/functions/truncate.js"(exports2, module2) { "use strict"; - var parse3 = require_parse2(); + var parse4 = require_parse2(); var constants = require_constants6(); var SemVer = require_semver(); var truncate = (version, truncation, options) => { @@ -35054,7 +35054,7 @@ var require_truncate = __commonJS({ }; var cloneInputVersion = (version, options) => { const versionStringToParse = version instanceof SemVer ? version.version : version; - return parse3(versionStringToParse, options); + return parse4(versionStringToParse, options); }; var doTruncation = (version, truncation) => { if (isPrerelease(truncation)) { @@ -36098,7 +36098,7 @@ var require_semver2 = __commonJS({ var constants = require_constants6(); var SemVer = require_semver(); var identifiers = require_identifiers(); - var parse3 = require_parse2(); + var parse4 = require_parse2(); var valid4 = require_valid(); var clean3 = require_clean(); var inc = require_inc(); @@ -36137,7 +36137,7 @@ var require_semver2 = __commonJS({ var simplifyRange = require_simplify(); var subset = require_subset(); module2.exports = { - parse: parse3, + parse: parse4, valid: valid4, clean: clean3, inc, @@ -39820,9 +39820,9 @@ var require_minimatch = __commonJS({ throw new TypeError("pattern is too long"); } }; - Minimatch2.prototype.parse = parse3; + Minimatch2.prototype.parse = parse4; var SUBPARSE = {}; - function parse3(pattern, isSub) { + function parse4(pattern, isSub) { assertValidPattern2(pattern); var options = this.options; if (pattern === "**") { @@ -41272,8 +41272,8 @@ var require_semver3 = __commonJS({ } } var i; - exports2.parse = parse3; - function parse3(version, options) { + exports2.parse = parse4; + function parse4(version, options) { if (!options || typeof options !== "object") { options = { loose: !!options, @@ -41301,12 +41301,12 @@ var require_semver3 = __commonJS({ } exports2.valid = valid4; function valid4(version, options) { - var v = parse3(version, options); + var v = parse4(version, options); return v ? v.version : null; } exports2.clean = clean3; function clean3(version, options) { - var s = parse3(version.trim().replace(/^[=v]+/, ""), options); + var s = parse4(version.trim().replace(/^[=v]+/, ""), options); return s ? s.version : null; } exports2.SemVer = SemVer; @@ -41542,8 +41542,8 @@ var require_semver3 = __commonJS({ if (eq(version1, version2)) { return null; } else { - var v1 = parse3(version1); - var v2 = parse3(version2); + var v1 = parse4(version1); + var v2 = parse4(version2); var prefix = ""; if (v1.prerelease.length || v2.prerelease.length) { prefix = "pre"; @@ -42249,7 +42249,7 @@ var require_semver3 = __commonJS({ } exports2.prerelease = prerelease; function prerelease(version, options) { - var parsed = parse3(version, options); + var parsed = parse4(version, options); return parsed && parsed.prerelease.length ? parsed.prerelease : null; } exports2.intersects = intersects; @@ -42286,7 +42286,7 @@ var require_semver3 = __commonJS({ if (match2 === null) { return null; } - return parse3(match2[2] + "." + (match2[3] || "0") + "." + (match2[4] || "0"), options); + return parse4(match2[2] + "." + (match2[3] || "0") + "." + (match2[4] || "0"), options); } } }); @@ -42430,7 +42430,7 @@ var require_cacheUtils = __commonJS({ var crypto3 = __importStar2(require("crypto")); var fs33 = __importStar2(require("fs")); var path30 = __importStar2(require("path")); - var semver11 = __importStar2(require_semver3()); + var semver12 = __importStar2(require_semver3()); var util4 = __importStar2(require("util")); var constants_1 = require_constants7(); var versionSalt = "1.0"; @@ -42523,7 +42523,7 @@ var require_cacheUtils = __commonJS({ function getCompressionMethod() { return __awaiter2(this, void 0, void 0, function* () { const versionOutput = yield getVersion("zstd", ["--quiet"]); - const version = semver11.clean(versionOutput); + const version = semver12.clean(versionOutput); core29.debug(`zstd version: ${version}`); if (versionOutput === "") { return constants_1.CompressionMethod.Gzip; @@ -45201,7 +45201,7 @@ var require_ms = __commonJS({ options = options || {}; var type = typeof val; if (type === "string" && val.length > 0) { - return parse3(val); + return parse4(val); } else if (type === "number" && isFinite(val)) { return options.long ? fmtLong(val) : fmtShort(val); } @@ -45209,7 +45209,7 @@ var require_ms = __commonJS({ "val is not a non-empty string or a valid number. val=" + JSON.stringify(val) ); }; - function parse3(str) { + function parse4(str) { str = String(str); if (str.length > 100) { return; @@ -53110,7 +53110,7 @@ var require_deserializationPolicy = __commonJS({ return result; } async function deserializeResponseBody(jsonContentTypes, xmlContentTypes, response, options, parseXML) { - const parsedResponse = await parse3(jsonContentTypes, xmlContentTypes, response, options, parseXML); + const parsedResponse = await parse4(jsonContentTypes, xmlContentTypes, response, options, parseXML); if (!shouldDeserializeResponse(parsedResponse)) { return parsedResponse; } @@ -53211,7 +53211,7 @@ var require_deserializationPolicy = __commonJS({ } return { error: error3, shouldReturnResponse: false }; } - async function parse3(jsonContentTypes, xmlContentTypes, operationResponse, opts, parseXML) { + async function parse4(jsonContentTypes, xmlContentTypes, operationResponse, opts, parseXML) { if (!operationResponse.request.streamResponseStatusCodes?.has(operationResponse.status) && operationResponse.bodyAsText) { const text = operationResponse.bodyAsText; const contentType = operationResponse.headers.get("Content-Type") || ""; @@ -114072,7 +114072,7 @@ var require_manifest = __commonJS({ exports2._findMatch = _findMatch; exports2._getOsVersion = _getOsVersion; exports2._readLinuxVersionFile = _readLinuxVersionFile; - var semver11 = __importStar2(require_semver2()); + var semver12 = __importStar2(require_semver2()); var core_1 = require_core(); var os8 = require("os"); var cp = require("child_process"); @@ -114086,7 +114086,7 @@ var require_manifest = __commonJS({ for (const candidate of candidates) { const version = candidate.version; (0, core_1.debug)(`check ${version} satisfies ${versionSpec}`); - if (semver11.satisfies(version, versionSpec) && (!stable || candidate.stable === stable)) { + if (semver12.satisfies(version, versionSpec) && (!stable || candidate.stable === stable)) { file = candidate.files.find((item) => { (0, core_1.debug)(`${item.arch}===${archFilter} && ${item.platform}===${platFilter}`); let chk = item.arch === archFilter && item.platform === platFilter; @@ -114095,7 +114095,7 @@ var require_manifest = __commonJS({ if (osVersion === item.platform_version) { chk = true; } else { - chk = semver11.satisfies(osVersion, item.platform_version); + chk = semver12.satisfies(osVersion, item.platform_version); } } return chk; @@ -114355,7 +114355,7 @@ var require_tool_cache = __commonJS({ var os8 = __importStar2(require("os")); var path30 = __importStar2(require("path")); var httpm = __importStar2(require_lib()); - var semver11 = __importStar2(require_semver2()); + var semver12 = __importStar2(require_semver2()); var stream2 = __importStar2(require("stream")); var util4 = __importStar2(require("util")); var assert_1 = require("assert"); @@ -114628,7 +114628,7 @@ var require_tool_cache = __commonJS({ } function cacheDir2(sourceDir, tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { - version = semver11.clean(version) || version; + version = semver12.clean(version) || version; arch2 = arch2 || os8.arch(); core29.debug(`Caching tool ${tool} ${version} ${arch2}`); core29.debug(`source dir: ${sourceDir}`); @@ -114646,7 +114646,7 @@ var require_tool_cache = __commonJS({ } function cacheFile(sourceFile, targetFile, tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { - version = semver11.clean(version) || version; + version = semver12.clean(version) || version; arch2 = arch2 || os8.arch(); core29.debug(`Caching tool ${tool} ${version} ${arch2}`); core29.debug(`source file: ${sourceFile}`); @@ -114676,7 +114676,7 @@ var require_tool_cache = __commonJS({ } let toolPath = ""; if (versionSpec) { - versionSpec = semver11.clean(versionSpec) || ""; + versionSpec = semver12.clean(versionSpec) || ""; const cachePath = path30.join(_getCacheDirectory(), toolName, versionSpec, arch2); core29.debug(`checking cache: ${cachePath}`); if (fs33.existsSync(cachePath) && fs33.existsSync(`${cachePath}.complete`)) { @@ -114756,7 +114756,7 @@ var require_tool_cache = __commonJS({ } function _createToolPath(tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { - const folderPath = path30.join(_getCacheDirectory(), tool, semver11.clean(version) || version, arch2 || ""); + const folderPath = path30.join(_getCacheDirectory(), tool, semver12.clean(version) || version, arch2 || ""); core29.debug(`destination ${folderPath}`); const markerPath = `${folderPath}.complete`; yield io9.rmRF(folderPath); @@ -114766,15 +114766,15 @@ var require_tool_cache = __commonJS({ }); } function _completeToolPath(tool, version, arch2) { - const folderPath = path30.join(_getCacheDirectory(), tool, semver11.clean(version) || version, arch2 || ""); + const folderPath = path30.join(_getCacheDirectory(), tool, semver12.clean(version) || version, arch2 || ""); const markerPath = `${folderPath}.complete`; fs33.writeFileSync(markerPath, ""); core29.debug("finished caching tool"); } function isExplicitVersion(versionSpec) { - const c = semver11.clean(versionSpec) || ""; + const c = semver12.clean(versionSpec) || ""; core29.debug(`isExplicit: ${c}`); - const valid4 = semver11.valid(c) != null; + const valid4 = semver12.valid(c) != null; core29.debug(`explicit? ${valid4}`); return valid4; } @@ -114782,14 +114782,14 @@ var require_tool_cache = __commonJS({ let version = ""; core29.debug(`evaluating ${versions.length} versions`); versions = versions.sort((a, b) => { - if (semver11.gt(a, b)) { + if (semver12.gt(a, b)) { return 1; } return -1; }); for (let i = versions.length - 1; i >= 0; i--) { const potential = versions[i]; - const satisfied = semver11.satisfies(potential, versionSpec); + const satisfied = semver12.satisfies(potential, versionSpec); if (satisfied) { version = potential; break; @@ -144290,7 +144290,7 @@ var require_dist_node2 = __commonJS({ return template.replace(/\/$/, ""); } } - function parse3(options) { + function parse4(options) { let method = options.method.toUpperCase(); let url2 = (options.url || "/").replace(/:([a-z]\w+)/g, "{$1}"); let headers = Object.assign({}, options.headers); @@ -144354,7 +144354,7 @@ var require_dist_node2 = __commonJS({ ); } function endpointWithDefaults2(defaults3, route, options) { - return parse3(merge2(defaults3, route, options)); + return parse4(merge2(defaults3, route, options)); } function withDefaults4(oldDefaults, newDefaults) { const DEFAULTS22 = merge2(oldDefaults, newDefaults); @@ -144363,7 +144363,7 @@ var require_dist_node2 = __commonJS({ DEFAULTS: DEFAULTS22, defaults: withDefaults4.bind(null, DEFAULTS22), merge: merge2.bind(null, DEFAULTS22), - parse: parse3 + parse: parse4 }); } var endpoint2 = withDefaults4(null, DEFAULTS2); @@ -148595,7 +148595,7 @@ var require_binary = __commonJS({ }); return stream2; }; - exports2.parse = function parse3(buffer) { + exports2.parse = function parse4(buffer) { var self2 = words(function(bytes, cb) { return function(name) { if (offset + bytes <= buffer.length) { @@ -183078,7 +183078,7 @@ var fs15 = __toESM(require("fs")); var path13 = __toESM(require("path")); var import_perf_hooks4 = require("perf_hooks"); var toolcache3 = __toESM(require_tool_cache()); -var semver9 = __toESM(require_semver2()); +var semver10 = __toESM(require_semver2()); // src/codeql-bundle.ts function getCodeQLBundleName(compressionMethod, platform2, language) { @@ -183407,9 +183407,10 @@ async function getCodeQlVersionsForOverlayBaseDatabases(rawLanguages, logger2) { } // src/per-language-bundles.ts -var semver6 = __toESM(require_semver2()); +var semver7 = __toESM(require_semver2()); // src/platform.ts +var semver6 = __toESM(require_semver2()); function getBundlePlatform(platform2 = process.platform, arch2 = process.arch) { switch (platform2) { case "win32": @@ -183422,6 +183423,16 @@ function getBundlePlatform(platform2 = process.platform, arch2 = process.arch) { return void 0; } } +function macOSVersion(action) { + if (action.platform !== "darwin") { + return void 0; + } + const version = semver6.parse(action.osRelease); + if (version === null) { + return action.osRelease; + } + return version; +} // src/per-language-bundles.ts var MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION = "2.27.1"; @@ -183509,7 +183520,7 @@ function getPerLanguageBundleLanguage(action, options) { if (cliVersion2 === void 0) { return explain("the requested CLI version is unknown"); } - if (!semver6.gte(cliVersion2, MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION)) { + if (!semver7.gte(cliVersion2, MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION)) { return explain( `the requested CodeQL version ${cliVersion2} is older than ${MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION}, which is the first version for which per-language bundles are published` ); @@ -183607,7 +183618,7 @@ var stream = __toESM(require("stream")); var import_toolrunner = __toESM(require_toolrunner()); var io4 = __toESM(require_io()); var toolcache = __toESM(require_tool_cache()); -var semver7 = __toESM(require_semver2()); +var semver8 = __toESM(require_semver2()); var MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3"; var MIN_REQUIRED_GNU_TAR_VERSION = "1.31"; async function getTarVersion() { @@ -183649,9 +183660,9 @@ async function isZstdAvailable(logger2) { case "gnu": return { available: foundZstdBinary && // GNU tar only uses major and minor version numbers - semver7.gte( - semver7.coerce(version), - semver7.coerce(MIN_REQUIRED_GNU_TAR_VERSION) + semver8.gte( + semver8.coerce(version), + semver8.coerce(MIN_REQUIRED_GNU_TAR_VERSION) ), foundZstdBinary, version: tarVersion @@ -183660,7 +183671,7 @@ async function isZstdAvailable(logger2) { return { available: foundZstdBinary && // Do a loose comparison since these version numbers don't contain // a patch version number. - semver7.gte(version, MIN_REQUIRED_BSD_TAR_VERSION), + semver8.gte(version, MIN_REQUIRED_BSD_TAR_VERSION), foundZstdBinary, version: tarVersion }; @@ -183769,7 +183780,7 @@ var core11 = __toESM(require_core()); var import_http_client = __toESM(require_lib()); var toolcache2 = __toESM(require_tool_cache()); var import_follow_redirects = __toESM(require_follow_redirects()); -var semver8 = __toESM(require_semver2()); +var semver9 = __toESM(require_semver2()); var STREAMING_HIGH_WATERMARK_BYTES = 4 * 1024 * 1024; var STREAMING_STALL_TIMEOUT_MS = 5 * 60 * 1e3; var TOOLCACHE_TOOL_NAME = "CodeQL"; @@ -183895,7 +183906,7 @@ function getToolcacheToolDirectory(env) { ); } function getToolcacheVersionDirectoryName(version) { - return semver8.clean(version) || version; + return semver9.clean(version) || version; } function getToolcacheDirectory(version) { return path12.join( @@ -184022,13 +184033,13 @@ function tryGetTagNameFromUrl(url2, logger2) { return match2[1]; } function convertToSemVer(version, logger2) { - if (!semver9.valid(version)) { + if (!semver10.valid(version)) { logger2.debug( `Bundle version ${version} is not in SemVer format. Will treat it as pre-release 0.0.0-${version}.` ); version = `0.0.0-${version}`; } - const s = semver9.clean(version); + const s = semver10.clean(version); if (!s) { throw new Error(`Bundle version ${version} is not in SemVer format.`); } @@ -184208,7 +184219,7 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, othe url2 = toolsInput; if (tagName) { const bundleVersion3 = tryGetBundleVersionFromTagName(tagName, logger2); - if (bundleVersion3 !== void 0 && semver9.valid(bundleVersion3)) { + if (bundleVersion3 !== void 0 && semver10.valid(bundleVersion3)) { cliVersion2 = convertToSemVer(bundleVersion3, logger2); } } @@ -184586,7 +184597,7 @@ async function downloadCodeQLBundle(action, source, apiDetails, tarVersion, temp async function useZstdBundle(cliVersion2, tarSupportsZstd) { return ( // In testing, gzip performs better than zstd on Windows. - process.platform !== "win32" && tarSupportsZstd && semver9.gte(cliVersion2, CODEQL_VERSION_ZSTD_BUNDLE) + process.platform !== "win32" && tarSupportsZstd && semver10.gte(cliVersion2, CODEQL_VERSION_ZSTD_BUNDLE) ); } function getTempExtractionDir(tempDir) { @@ -184640,7 +184651,7 @@ async function getLatestNightlyBundle(action, rawLanguages, otherLanguagePacksRe } } function getLatestToolcacheVersion(logger2) { - const allVersions = toolcache3.findAllVersions("CodeQL").sort((a, b) => semver9.compare(b, a)); + const allVersions = toolcache3.findAllVersions("CodeQL").sort((a, b) => semver10.compare(b, a)); logger2.debug( `Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify( allVersions @@ -193803,7 +193814,7 @@ var fs30 = __toESM(require("fs")); var path25 = __toESM(require("path")); var core19 = __toESM(require_core()); var io7 = __toESM(require_io()); -var semver10 = __toESM(require_semver2()); +var semver11 = __toESM(require_semver2()); // src/config/inputs.ts async function getToolsInput(action, repositoryProperties) { @@ -193841,11 +193852,21 @@ async function getToolsInput(action, repositoryProperties) { // src/languages/swift.ts function checkSwiftCompatibility(action, config) { - if (config.languages.includes("swift" /* swift */) && action.platform !== "darwin") { + if (!config.languages.includes("swift" /* swift */)) { + return; + } + const version = macOSVersion(action); + if (version === void 0) { throw new ConfigurationError( `Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.` ); } + if (typeof version === "string") { + action.logger.warning( + `Unable to determine version of macOS, got: ${version}` + ); + return; + } } // src/status-report/tools-download.ts @@ -194322,7 +194343,7 @@ async function run3(actionState) { ) { const publicPreview = "2.22.1"; const actualVer = (await codeql.getVersion()).version; - if (semver10.lt(actualVer, publicPreview)) { + if (semver11.lt(actualVer, publicPreview)) { actionState.env.export("CODEQL_ENABLE_EXPERIMENTAL_FEATURES" /* EXPERIMENTAL_FEATURES */, "true"); logger2.info("Experimental Rust analysis enabled"); } diff --git a/src/languages/swift.test.ts b/src/languages/swift.test.ts index 2f3182fea2..344a1ead57 100644 --- a/src/languages/swift.test.ts +++ b/src/languages/swift.test.ts @@ -3,6 +3,7 @@ import sinon from "sinon"; import { ActionsEnvVars } from "../environment"; import { + checkExpectedLogMessages, createTestConfig, getCodeQLForTesting, getTestEnv, @@ -68,3 +69,14 @@ for (const nonDarwinPlatform of nonDarwinPlatforms) { ); }); } + +test("checkSwiftCompatibility warns if version string is not a semver", (t) => { + const logger = new RecordingLogger(); + checkSwiftCompatibility( + initAllState({ logger, platform: "darwin", osRelease: "unexpected" }), + createTestConfig({ languages: [BuiltInLanguage.swift] }), + ); + checkExpectedLogMessages(t, logger.messages, [ + "Unable to determine version of macOS, got: unexpected", + ]); +}); diff --git a/src/languages/swift.ts b/src/languages/swift.ts index 4faa3efe96..bb542b08bb 100644 --- a/src/languages/swift.ts +++ b/src/languages/swift.ts @@ -1,5 +1,6 @@ import { ActionState } from "../action-common"; import { Config } from "../config-utils"; +import { macOSVersion } from "../platform"; import { ConfigurationError } from "../util"; import { BuiltInLanguage } from "."; @@ -13,15 +14,28 @@ import { BuiltInLanguage } from "."; * @throws {ConfigurationError} If Swift analysis is not possible on the current runner. */ export function checkSwiftCompatibility( - action: ActionState<["Base"]>, + action: ActionState<["Base", "Logger"]>, config: Config, ) { - if ( - config.languages.includes(BuiltInLanguage.swift) && - action.platform !== "darwin" - ) { + // The checks are not relevant if we are not trying to analyse Swift. + if (!config.languages.includes(BuiltInLanguage.swift)) { + return; + } + + // Try to get the macOS version. + const version = macOSVersion(action); + + // If `version` is undefined, then we are not on macOS. + if (version === undefined) { throw new ConfigurationError( `Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.`, ); } + // If we got a string, we are on macOS but couldn't parse the version string. + if (typeof version === "string") { + action.logger.warning( + `Unable to determine version of macOS, got: ${version}`, + ); + return; + } } From 9271dd21d565303911c55434c82577d11c589154 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 14:41:26 +0100 Subject: [PATCH 114/174] Add `swiftSupportsAllPlatforms` to `ToolsFeature` --- src/tools-features.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools-features.ts b/src/tools-features.ts index 35e626c887..84dc1d0f44 100644 --- a/src/tools-features.ts +++ b/src/tools-features.ts @@ -6,6 +6,7 @@ export enum ToolsFeature { BundleSupportsOverlay = "bundleSupportsOverlay", IndirectTracingSupportsStaticBinaries = "indirectTracingSupportsStaticBinaries", SuppressesMissingFileBaselineWarning = "suppressesMissingFileBaselineWarning", + SwiftSupportsAllPlatforms = "swiftSupportsAllPlatforms", } /** From a9623043dcb0be718bbea42be6d1a5745449afb3 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 15:25:46 +0100 Subject: [PATCH 115/174] Skip Swift checks if tools feature is enabled --- lib/entry-points.js | 7 ++- src/init-action.ts | 2 +- src/languages/swift.test.ts | 105 +++++++++++++++++++++++++++--------- src/languages/swift.ts | 12 ++++- src/testing-utils.ts | 3 +- 5 files changed, 99 insertions(+), 30 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 3bd8098e43..290ba395ab 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -193851,10 +193851,13 @@ async function getToolsInput(action, repositoryProperties) { } // src/languages/swift.ts -function checkSwiftCompatibility(action, config) { +async function checkSwiftCompatibility(action, config, codeql) { if (!config.languages.includes("swift" /* swift */)) { return; } + if (await codeql.supportsFeature("swiftSupportsAllPlatforms" /* SwiftSupportsAllPlatforms */)) { + return; + } const version = macOSVersion(action); if (version === void 0) { throw new ConfigurationError( @@ -194388,7 +194391,7 @@ async function run3(actionState) { enableFileCoverageInformation: fileCoverageResult.enabled, logger: logger2 }); - checkSwiftCompatibility(actionState, config); + await checkSwiftCompatibility(actionState, config, codeql); if (repositoryPropertiesResult.isFailure()) { addNoLanguageDiagnostic( config, diff --git a/src/init-action.ts b/src/init-action.ts index 5146d7530c..d0d06faaa0 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -419,7 +419,7 @@ async function run( logger, }); - checkSwiftCompatibility(actionState, config); + await checkSwiftCompatibility(actionState, config, codeql); if (repositoryPropertiesResult.isFailure()) { addNoLanguageDiagnostic( diff --git a/src/languages/swift.test.ts b/src/languages/swift.test.ts index 344a1ead57..9f0561fad6 100644 --- a/src/languages/swift.test.ts +++ b/src/languages/swift.test.ts @@ -11,27 +11,56 @@ import { makeVersionInfo, RecordingLogger, } from "../testing-utils"; +import { ToolsFeature } from "../tools-features"; import { ConfigurationError, withTmpDir } from "../util"; import { checkSwiftCompatibility } from "./swift"; import { BuiltInLanguage } from "."; -test("checkSwiftCompatibility doesn't throw for non-Swift languages", (t) => { +test("checkSwiftCompatibility doesn't throw for non-Swift languages", async (t) => { for (const language of Object.values(BuiltInLanguage)) { if (language === BuiltInLanguage.swift) { continue; } - t.notThrows(() => + const codeql = await getCodeQLForTesting(); + await t.notThrowsAsync( checkSwiftCompatibility( initAllState(), createTestConfig({ languages: [language] }), + codeql, ), ); } }); +test("checkSwiftCompatibility doesn't throw for Swift if CLI supports swiftSupportsAllPlatforms", async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLForTesting("codeql-for-testing", logger, env); + const supportsFeature = sinon + .stub(codeql, "supportsFeature") + .withArgs(ToolsFeature.SwiftSupportsAllPlatforms) + .resolves(true); + + await t.notThrowsAsync( + checkSwiftCompatibility( + initAllState({ platform: "darwin", env, logger }), + createTestConfig({ languages: [BuiltInLanguage.swift] }), + codeql, + ), + ); + + t.is(supportsFeature.callCount, 1); + t.deepEqual(supportsFeature.args[0], [ + ToolsFeature.SwiftSupportsAllPlatforms, + ]); + })); + test("checkSwiftCompatibility doesn't throw for Swift on darwin", async (t) => withTmpDir(async (tmpDir) => { const logger = new RecordingLogger(); @@ -41,42 +70,68 @@ test("checkSwiftCompatibility doesn't throw for Swift on darwin", async (t) => const codeql = await getCodeQLForTesting("codeql-for-testing", logger, env); sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); - t.notThrows(() => + await t.notThrowsAsync( checkSwiftCompatibility( initAllState({ platform: "darwin", env, logger }), createTestConfig({ tempDir: tmpDir, languages: [BuiltInLanguage.swift], }), + codeql, ), ); })); const nonDarwinPlatforms: NodeJS.Platform[] = ["linux", "win32"]; for (const nonDarwinPlatform of nonDarwinPlatforms) { - test(`checkSwiftCompatibility throws for Swift on ${nonDarwinPlatform}`, (t) => { - t.throws( - () => { + test(`checkSwiftCompatibility throws for Swift on ${nonDarwinPlatform}`, async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLForTesting( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + await t.throwsAsync( checkSwiftCompatibility( - initAllState({ platform: nonDarwinPlatform }), + initAllState({ platform: nonDarwinPlatform, env, logger }), createTestConfig({ languages: [BuiltInLanguage.swift] }), - ); - }, - { - instanceOf: ConfigurationError, - message: /^Swift analysis is only supported on macOS runner images/, - }, - ); - }); + codeql, + ), + { + instanceOf: ConfigurationError, + message: /^Swift analysis is only supported on macOS runner images/, + }, + ); + })); } -test("checkSwiftCompatibility warns if version string is not a semver", (t) => { - const logger = new RecordingLogger(); - checkSwiftCompatibility( - initAllState({ logger, platform: "darwin", osRelease: "unexpected" }), - createTestConfig({ languages: [BuiltInLanguage.swift] }), - ); - checkExpectedLogMessages(t, logger.messages, [ - "Unable to determine version of macOS, got: unexpected", - ]); -}); +test("checkSwiftCompatibility warns if version string is not a semver", async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLForTesting("codeql-for-testing", logger, env); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + await checkSwiftCompatibility( + initAllState({ + logger, + platform: "darwin", + osRelease: "unexpected", + env, + }), + createTestConfig({ languages: [BuiltInLanguage.swift] }), + codeql, + ); + + checkExpectedLogMessages(t, logger.messages, [ + "Unable to determine version of macOS, got: unexpected", + ]); + })); diff --git a/src/languages/swift.ts b/src/languages/swift.ts index bb542b08bb..c9be490a64 100644 --- a/src/languages/swift.ts +++ b/src/languages/swift.ts @@ -1,6 +1,8 @@ import { ActionState } from "../action-common"; +import { CodeQL } from "../codeql"; import { Config } from "../config-utils"; import { macOSVersion } from "../platform"; +import { ToolsFeature } from "../tools-features"; import { ConfigurationError } from "../util"; import { BuiltInLanguage } from "."; @@ -13,15 +15,23 @@ import { BuiltInLanguage } from "."; * * @throws {ConfigurationError} If Swift analysis is not possible on the current runner. */ -export function checkSwiftCompatibility( +export async function checkSwiftCompatibility( action: ActionState<["Base", "Logger"]>, config: Config, + codeql: CodeQL, ) { // The checks are not relevant if we are not trying to analyse Swift. if (!config.languages.includes(BuiltInLanguage.swift)) { return; } + // Skip the checks if the `swiftSupportsAllPlatforms` feature is supported by the CLI. + // This is a forward-looking measure that allows a future CLI update to disable these + // platform checks in the Action when they shouldn't be enforced anymore. + if (await codeql.supportsFeature(ToolsFeature.SwiftSupportsAllPlatforms)) { + return; + } + // Try to get the macOS version. const version = macOSVersion(action); diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 2dc68e2568..2b8e634e9d 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -35,6 +35,7 @@ import { joinMessageStrings, Loggable, LoggableError, Logger } from "./logging"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import { getBundlePlatform } from "./platform"; import { ActionName } from "./status-report"; +import { ToolsFeature } from "./tools-features"; import { DEFAULT_DEBUG_ARTIFACT_NAME, DEFAULT_DEBUG_DATABASE_NAME, @@ -913,7 +914,7 @@ export function mockLanguagesInRepo(languages: string[]) { */ export const makeVersionInfo = ( version: string, - features?: { [name: string]: boolean }, + features?: { [key in ToolsFeature]?: boolean }, overlayVersion?: number, ): VersionInfo => ({ version, From 45b8586e1babe2e8e2daf172b99a98a649d436c5 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 15:51:31 +0100 Subject: [PATCH 116/174] Check if macOS version is unsupported --- lib/entry-points.js | 31 +++++++++++++++++++ src/languages/swift.test.ts | 61 +++++++++++++++++++++++++++++++++++++ src/languages/swift.ts | 41 +++++++++++++++++++++++++ 3 files changed, 133 insertions(+) diff --git a/lib/entry-points.js b/lib/entry-points.js index 290ba395ab..9b527484d8 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -193851,6 +193851,8 @@ async function getToolsInput(action, repositoryProperties) { } // src/languages/swift.ts +var SWIFT_TRACED_UNSUPPORTED_MACOS = 27; +var SWIFT_TRACED_UNSUPPORTED_XCODE = 27; async function checkSwiftCompatibility(action, config, codeql) { if (!config.languages.includes("swift" /* swift */)) { return; @@ -193870,6 +193872,35 @@ async function checkSwiftCompatibility(action, config, codeql) { ); return; } + if (version.major >= SWIFT_TRACED_UNSUPPORTED_MACOS) { + const baseMessage = [ + `Traced Swift analysis is not supported on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS} or above.`, + `Configure your analysis to run on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS - 1} or below`, + `and XCode ${SWIFT_TRACED_UNSUPPORTED_XCODE - 1} or below.` + ].join(" "); + action.logger.warning(baseMessage); + addDiagnostic( + config, + "swift" /* swift */, + makeDiagnostic( + "codeql-action/unsupported-traced-swift-analysis-macos", + "Traced Swift analysis is not supported on this version of macOS", + { + attributes: { + languages: config.languages, + macOSVersion: version.toString() + }, + markdownMessage: baseMessage, + severity: "warning", + visibility: { + cliSummaryTable: true, + statusPage: true, + telemetry: true + } + } + ) + ); + } } // src/status-report/tools-download.ts diff --git a/src/languages/swift.test.ts b/src/languages/swift.test.ts index 9f0561fad6..8cddd4d482 100644 --- a/src/languages/swift.test.ts +++ b/src/languages/swift.test.ts @@ -1,6 +1,7 @@ import test from "ava"; import sinon from "sinon"; +import * as diagnostics from "../diagnostics"; import { ActionsEnvVars } from "../environment"; import { checkExpectedLogMessages, @@ -10,6 +11,7 @@ import { initAllState, makeVersionInfo, RecordingLogger, + setupTests, } from "../testing-utils"; import { ToolsFeature } from "../tools-features"; import { ConfigurationError, withTmpDir } from "../util"; @@ -18,6 +20,8 @@ import { checkSwiftCompatibility } from "./swift"; import { BuiltInLanguage } from "."; +setupTests(test); + test("checkSwiftCompatibility doesn't throw for non-Swift languages", async (t) => { for (const language of Object.values(BuiltInLanguage)) { if (language === BuiltInLanguage.swift) { @@ -135,3 +139,60 @@ test("checkSwiftCompatibility warns if version string is not a semver", async (t "Unable to determine version of macOS, got: unexpected", ]); })); + +// `addDiagnostic` changes global state and we must stub it, so this test must be serial. +test.serial( + "checkSwiftCompatibility logs and adds diagnostic if macOS version is unsupported", + async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLForTesting( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); + + const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); + await checkSwiftCompatibility( + initAllState({ + logger, + platform: "darwin", + osRelease: "27.0.0", + env, + }), + config, + codeql, + ); + + checkExpectedLogMessages(t, logger.messages, [ + "Traced Swift analysis is not supported on macOS 27", + ]); + + t.is(addDiagnostic.callCount, 1); + t.like(addDiagnostic.args[0], [ + config, + BuiltInLanguage.swift, + { + attributes: { + languages: [BuiltInLanguage.swift], + macOSVersion: "27.0.0", + }, + source: { + id: "codeql-action/unsupported-traced-swift-analysis-macos", + name: "Traced Swift analysis is not supported on this version of macOS", + }, + visibility: { + cliSummaryTable: true, + statusPage: true, + telemetry: true, + }, + } satisfies Partial, + ]); + }), +); diff --git a/src/languages/swift.ts b/src/languages/swift.ts index c9be490a64..834fe9629e 100644 --- a/src/languages/swift.ts +++ b/src/languages/swift.ts @@ -1,12 +1,19 @@ import { ActionState } from "../action-common"; import { CodeQL } from "../codeql"; import { Config } from "../config-utils"; +import { addDiagnostic, makeDiagnostic } from "../diagnostics"; import { macOSVersion } from "../platform"; import { ToolsFeature } from "../tools-features"; import { ConfigurationError } from "../util"; import { BuiltInLanguage } from "."; +/** macOS 27 and above do not support traced extraction for Swift. */ +export const SWIFT_TRACED_UNSUPPORTED_MACOS = 27; + +/** Xcode 27 and above do not support traced extraction for Swift. */ +export const SWIFT_TRACED_UNSUPPORTED_XCODE = 27; + /** * Determines whether we can run a Swift analysis on the current runner. * @@ -48,4 +55,38 @@ export async function checkSwiftCompatibility( ); return; } + + if (version.major >= SWIFT_TRACED_UNSUPPORTED_MACOS) { + const baseMessage = [ + `Traced Swift analysis is not supported on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS} or above.`, + `Configure your analysis to run on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS - 1} or below`, + `and XCode ${SWIFT_TRACED_UNSUPPORTED_XCODE - 1} or below.`, + ].join(" "); + + // Log the message. This will also show up as a workflow annotation. + action.logger.warning(baseMessage); + + // Create a diagnostic that will show up on the TSP. + addDiagnostic( + config, + BuiltInLanguage.swift, + makeDiagnostic( + "codeql-action/unsupported-traced-swift-analysis-macos", + "Traced Swift analysis is not supported on this version of macOS", + { + attributes: { + languages: config.languages, + macOSVersion: version.toString(), + }, + markdownMessage: baseMessage, + severity: "warning", + visibility: { + cliSummaryTable: true, + statusPage: true, + telemetry: true, + }, + }, + ), + ); + } } From 5f65e35fec2efabaeacdef372ac5b877693d1be9 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 16:01:15 +0100 Subject: [PATCH 117/174] Add FF to fail if macOS version is unsupported --- lib/entry-points.js | 18 +++++++++-- src/feature-flags.ts | 7 +++++ src/init-action.ts | 2 +- src/languages/swift.test.ts | 62 +++++++++++++++++++++++++++++++++++++ src/languages/swift.ts | 21 ++++++++++--- 5 files changed, 101 insertions(+), 9 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 9b527484d8..8d51fab4c0 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -179942,6 +179942,11 @@ var featureConfig = { envVar: "CODEQL_ACTION_START_PROXY_USE_FEATURES_RELEASE", minimumVersion: void 0 }, + ["skip_unsupported_traced_analysis" /* SkipUnsupportedTracedAnalysis */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_SKIP_UNSUPPORTED_TRACED_ANALYSIS", + minimumVersion: void 0 + }, ["tools_repository_property" /* ToolsRepositoryProperty */]: { defaultValue: false, envVar: "CODEQL_ACTION_TOOLS_REPOSITORY_PROPERTY", @@ -193872,13 +193877,15 @@ async function checkSwiftCompatibility(action, config, codeql) { ); return; } + const skipUnsupportedTracedAnalysis = await action.features.getValue( + "skip_unsupported_traced_analysis" /* SkipUnsupportedTracedAnalysis */ + ); if (version.major >= SWIFT_TRACED_UNSUPPORTED_MACOS) { const baseMessage = [ `Traced Swift analysis is not supported on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS} or above.`, `Configure your analysis to run on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS - 1} or below`, `and XCode ${SWIFT_TRACED_UNSUPPORTED_XCODE - 1} or below.` ].join(" "); - action.logger.warning(baseMessage); addDiagnostic( config, "swift" /* swift */, @@ -193891,7 +193898,7 @@ async function checkSwiftCompatibility(action, config, codeql) { macOSVersion: version.toString() }, markdownMessage: baseMessage, - severity: "warning", + severity: skipUnsupportedTracedAnalysis ? "error" : "warning", visibility: { cliSummaryTable: true, statusPage: true, @@ -193900,6 +193907,11 @@ async function checkSwiftCompatibility(action, config, codeql) { } ) ); + if (skipUnsupportedTracedAnalysis) { + throw new ConfigurationError(baseMessage); + } else { + action.logger.warning(baseMessage); + } } } @@ -194422,7 +194434,7 @@ async function run3(actionState) { enableFileCoverageInformation: fileCoverageResult.enabled, logger: logger2 }); - await checkSwiftCompatibility(actionState, config, codeql); + await checkSwiftCompatibility(actionStateWithFeatures, config, codeql); if (repositoryPropertiesResult.isFailure()) { addNoLanguageDiagnostic( config, diff --git a/src/feature-flags.ts b/src/feature-flags.ts index f0fbcd3233..e326b08e6e 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -144,6 +144,8 @@ export enum Feature { /** Controls whether overlay build failures on the default branch are stored in the Actions cache. */ OverlayAnalysisStatusSave = "overlay_analysis_status_save", QaTelemetryEnabled = "qa_telemetry_enabled", + /** Whether we should fail early if we detect that traced analysis is unsupported. */ + SkipUnsupportedTracedAnalysis = "skip_unsupported_traced_analysis", /** Routes (some) API requests through the registry proxy. */ ProxyApiRequests = "proxy_api_requests", /** Note that this currently only disables baseline file coverage information. */ @@ -410,6 +412,11 @@ export const featureConfig = { envVar: "CODEQL_ACTION_START_PROXY_USE_FEATURES_RELEASE", minimumVersion: undefined, }, + [Feature.SkipUnsupportedTracedAnalysis]: { + defaultValue: false, + envVar: "CODEQL_ACTION_SKIP_UNSUPPORTED_TRACED_ANALYSIS", + minimumVersion: undefined, + }, [Feature.ToolsRepositoryProperty]: { defaultValue: false, envVar: "CODEQL_ACTION_TOOLS_REPOSITORY_PROPERTY", diff --git a/src/init-action.ts b/src/init-action.ts index d0d06faaa0..ae793e19ba 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -419,7 +419,7 @@ async function run( logger, }); - await checkSwiftCompatibility(actionState, config, codeql); + await checkSwiftCompatibility(actionStateWithFeatures, config, codeql); if (repositoryPropertiesResult.isFailure()) { addNoLanguageDiagnostic( diff --git a/src/languages/swift.test.ts b/src/languages/swift.test.ts index 8cddd4d482..dd3bca80c4 100644 --- a/src/languages/swift.test.ts +++ b/src/languages/swift.test.ts @@ -3,8 +3,10 @@ import sinon from "sinon"; import * as diagnostics from "../diagnostics"; import { ActionsEnvVars } from "../environment"; +import { Feature } from "../feature-flags"; import { checkExpectedLogMessages, + createFeatures, createTestConfig, getCodeQLForTesting, getTestEnv, @@ -183,6 +185,66 @@ test.serial( languages: [BuiltInLanguage.swift], macOSVersion: "27.0.0", }, + severity: "warning", + source: { + id: "codeql-action/unsupported-traced-swift-analysis-macos", + name: "Traced Swift analysis is not supported on this version of macOS", + }, + visibility: { + cliSummaryTable: true, + statusPage: true, + telemetry: true, + }, + } satisfies Partial, + ]); + }), +); + +// `addDiagnostic` changes global state and we must stub it, so this test must be serial. +test.serial( + "checkSwiftCompatibility throws if macOS version is unsupported and FF is enabled", + async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const features = createFeatures([Feature.SkipUnsupportedTracedAnalysis]); + + const codeql = await getCodeQLForTesting( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); + + const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); + await t.throwsAsync( + checkSwiftCompatibility( + initAllState({ + logger, + platform: "darwin", + osRelease: "27.0.0", + env, + features, + }), + config, + codeql, + ), + ); + + t.is(addDiagnostic.callCount, 1); + t.like(addDiagnostic.args[0], [ + config, + BuiltInLanguage.swift, + { + attributes: { + languages: [BuiltInLanguage.swift], + macOSVersion: "27.0.0", + }, + severity: "error", source: { id: "codeql-action/unsupported-traced-swift-analysis-macos", name: "Traced Swift analysis is not supported on this version of macOS", diff --git a/src/languages/swift.ts b/src/languages/swift.ts index 834fe9629e..30a77eb420 100644 --- a/src/languages/swift.ts +++ b/src/languages/swift.ts @@ -2,6 +2,7 @@ import { ActionState } from "../action-common"; import { CodeQL } from "../codeql"; import { Config } from "../config-utils"; import { addDiagnostic, makeDiagnostic } from "../diagnostics"; +import { Feature } from "../feature-flags"; import { macOSVersion } from "../platform"; import { ToolsFeature } from "../tools-features"; import { ConfigurationError } from "../util"; @@ -23,7 +24,7 @@ export const SWIFT_TRACED_UNSUPPORTED_XCODE = 27; * @throws {ConfigurationError} If Swift analysis is not possible on the current runner. */ export async function checkSwiftCompatibility( - action: ActionState<["Base", "Logger"]>, + action: ActionState<["Base", "Logger", "FeatureFlags"]>, config: Config, codeql: CodeQL, ) { @@ -56,6 +57,9 @@ export async function checkSwiftCompatibility( return; } + const skipUnsupportedTracedAnalysis = await action.features.getValue( + Feature.SkipUnsupportedTracedAnalysis, + ); if (version.major >= SWIFT_TRACED_UNSUPPORTED_MACOS) { const baseMessage = [ `Traced Swift analysis is not supported on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS} or above.`, @@ -63,9 +67,6 @@ export async function checkSwiftCompatibility( `and XCode ${SWIFT_TRACED_UNSUPPORTED_XCODE - 1} or below.`, ].join(" "); - // Log the message. This will also show up as a workflow annotation. - action.logger.warning(baseMessage); - // Create a diagnostic that will show up on the TSP. addDiagnostic( config, @@ -79,7 +80,7 @@ export async function checkSwiftCompatibility( macOSVersion: version.toString(), }, markdownMessage: baseMessage, - severity: "warning", + severity: skipUnsupportedTracedAnalysis ? "error" : "warning", visibility: { cliSummaryTable: true, statusPage: true, @@ -88,5 +89,15 @@ export async function checkSwiftCompatibility( }, ), ); + + // Throw an error to abort the analysis if the FF is enabled or log the message. + if (skipUnsupportedTracedAnalysis) { + // ConfigurationErrors are converted to the "aborted" status by the exception handler + // in `init-action.ts` that guards the call to `isSwiftCompatible`. + throw new ConfigurationError(baseMessage); + } else { + // This will also show up as a workflow annotation. + action.logger.warning(baseMessage); + } } } From 242ea52c053a1f486f451825bf91e7230fccd010 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 28 Oct 2026 12:57:13 +0000 Subject: [PATCH 118/174] Add function to determine Xcode version based on symlink --- src/action-common.ts | 2 + src/platform.test.ts | 140 ++++++++++++++++++++++++++++++++++++++++++- src/platform.ts | 69 ++++++++++++++++++++- 3 files changed, 208 insertions(+), 3 deletions(-) diff --git a/src/action-common.ts b/src/action-common.ts index b272869069..efb0bd97a0 100644 --- a/src/action-common.ts +++ b/src/action-common.ts @@ -15,6 +15,8 @@ import { } from "./status-report"; import { getEnv, getErrorMessage, wrapError } from "./util"; +export type { Logger } from "./logging"; + /** Base state that is available to an Action on startup. */ export interface BaseState { /** The name of the Action. */ diff --git a/src/platform.test.ts b/src/platform.test.ts index 803e28b903..5de468d823 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -1,7 +1,23 @@ +import fs from "fs"; + import test from "ava"; +import * as sinon from "sinon"; + +import { + BundlePlatform, + getBundlePlatform, + macOSVersion, + XCODE_SELECT_LINK_PATH, + xcodeVersion, +} from "./platform"; +import { + checkExpectedLogMessages, + initAllState, + RecordingLogger, + setupTests, +} from "./testing-utils"; -import { BundlePlatform, getBundlePlatform, macOSVersion } from "./platform"; -import { initAllState } from "./testing-utils"; +setupTests(test); for (const [platform, arch, expected] of [ ["linux", "x64", BundlePlatform.Linux64], @@ -54,3 +70,123 @@ test("macOSVersion returns semver if parsing succeeds", (t) => { t.is(version["patch"], 1); } }); + +test.serial("xcodeVersion returns undefined if symlink doesn't exist", (t) => { + const logger = new RecordingLogger(); + + const statSync = sinon.stub(fs, "statSync").throws(new Error("ENOENT")); + + t.is(xcodeVersion(logger), undefined); + t.is(statSync.callCount, 1); + t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + + checkExpectedLogMessages(t, logger.messages, [ + "Unable to determine Xcode version: ENOENT", + ]); +}); + +test.serial("xcodeVersion returns undefined if file is not a symlink", (t) => { + const logger = new RecordingLogger(); + + const statSync = sinon + .stub(fs, "statSync") + .returns({ isSymbolicLink: () => false } as fs.Stats); + + t.is(xcodeVersion(logger), undefined); + t.is(statSync.callCount, 1); + t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + + checkExpectedLogMessages(t, logger.messages, [ + "exists, but is not a symbolic link", + ]); +}); + +test.serial( + "xcodeVersion returns undefined if resolving the symlink returns nothing", + (t) => { + const logger = new RecordingLogger(); + + const statSync = sinon + .stub(fs, "statSync") + .returns({ isSymbolicLink: () => true } as fs.Stats); + const readlinkSync = sinon.stub(fs, "readlinkSync").returns(""); + + t.is(xcodeVersion(logger), undefined); + t.is(statSync.callCount, 1); + t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); + + checkExpectedLogMessages(t, logger.messages, [ + "unexpectedly returned nothing", + ]); + }, +); + +test.serial( + "xcodeVersion returns undefined if resolved path doesn't include pattern", + (t) => { + const logger = new RecordingLogger(); + + const statSync = sinon + .stub(fs, "statSync") + .returns({ isSymbolicLink: () => true } as fs.Stats); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .returns("/Applications/Xcode.app/Contents/Developer"); + + t.is(xcodeVersion(logger), undefined); + t.is(statSync.callCount, 1); + t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); + + checkExpectedLogMessages(t, logger.messages, [ + "does not contain expected pattern", + ]); + }, +); + +test.serial("xcodeVersion returns undefined if match can't be parsed", (t) => { + const logger = new RecordingLogger(); + + const statSync = sinon + .stub(fs, "statSync") + .returns({ isSymbolicLink: () => true } as fs.Stats); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .returns("/Applications/Xcode_00.0.app/Contents/Developer"); + + t.is(xcodeVersion(logger), undefined); + t.is(statSync.callCount, 1); + t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); + + checkExpectedLogMessages(t, logger.messages, [ + "Couldn't parse '00.0' as a semantic version.", + ]); +}); + +test.serial("xcodeVersion returns version from resolved path", (t) => { + const logger = new RecordingLogger(); + + const statSync = sinon + .stub(fs, "statSync") + .returns({ isSymbolicLink: () => true } as fs.Stats); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .returns("/Applications/Xcode_16.4.app/Contents/Developer"); + + const result = xcodeVersion(logger); + + if (t.truthy(result)) { + t.is(result.major, 16); + t.is(result.minor, 4); + } + + t.is(statSync.callCount, 1); + t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); +}); diff --git a/src/platform.ts b/src/platform.ts index 59785d3124..d5c77c9f73 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -1,6 +1,9 @@ +import fs from "fs"; + import * as semver from "semver"; -import type { ActionState } from "./action-common"; +import type { ActionState, Logger } from "./action-common"; +import { getErrorMessage } from "./util"; /** Platform identifiers used in CodeQL bundle asset names. */ export enum BundlePlatform { @@ -53,3 +56,67 @@ export function macOSVersion( return version; } + +/** The static path we check for a symbolic link to the (dynamic) Xcode location. */ +export const XCODE_SELECT_LINK_PATH = "/private/var/db/xcode_select_link"; + +/** The pattern we expect to find in the Xcode path. */ +export const XCODE_APP_FILENAME_PATTERN = new RegExp( + /(?Xcode_(?\d+.\d+).app)/, +); + +/** + * Tries to determine the version of Xcode that is installed. + * + * @param logger The logger to use. + * @returns The Xcode version or `undefined` if it couldn't be determined. + */ +export function xcodeVersion(logger: Logger): semver.SemVer | undefined { + try { + // Stat the expected symbolic link to check that it exists and is a symbolic link. + // The `readlinkSync` call below returns an empty string in either case and so + // this check allows us to distinguish between the two cases. + const stats = fs.statSync(XCODE_SELECT_LINK_PATH); + + if (!stats.isSymbolicLink()) { + logger.warning( + `${XCODE_SELECT_LINK_PATH} exists, but is not a symbolic link.`, + ); + return undefined; + } + + // Read what the symbolic link points to. + const xcodePath = fs.readlinkSync(XCODE_SELECT_LINK_PATH); + + if (xcodePath === "") { + logger.warning( + `Resolving ${XCODE_SELECT_LINK_PATH} unexpectedly returned nothing.`, + ); + return undefined; + } + + // Try to extract the version from the path. + const matchResult = xcodePath.match(XCODE_APP_FILENAME_PATTERN); + + if (matchResult?.groups === undefined) { + logger.warning( + `Xcode path '${xcodePath}' does not contain expected pattern.`, + ); + return undefined; + } + + const majorMinor = matchResult.groups["majorMinor"]; + const version = semver.coerce(majorMinor); + + if (version === null) { + logger.warning(`Couldn't parse '${majorMinor}' as a semantic version.`); + return undefined; + } + return version; + } catch (err) { + logger.warning( + `Unable to determine Xcode version: ${getErrorMessage(err)}`, + ); + return undefined; + } +} From 7121af21e18a5ea2cde8abb79370fdfed5834262 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 9 Oct 2026 18:11:41 +0100 Subject: [PATCH 119/174] Check if Xcode version is unsupported --- lib/entry-points.js | 883 +++++++++++++++++++---------------- src/init-action.ts | 8 +- src/languages/swift.test.ts | 189 +------- src/languages/swift.ts | 79 +--- src/languages/traced.test.ts | 390 ++++++++++++++++ src/languages/traced.ts | 134 ++++++ 6 files changed, 1025 insertions(+), 658 deletions(-) create mode 100644 src/languages/traced.test.ts create mode 100644 src/languages/traced.ts diff --git a/lib/entry-points.js b/lib/entry-points.js index 8d51fab4c0..8f9769bbac 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -213,7 +213,7 @@ var require_file_command = __commonJS({ exports2.issueFileCommand = issueFileCommand; exports2.prepareKeyValueMessage = prepareKeyValueMessage; var crypto3 = __importStar2(require("crypto")); - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var os8 = __importStar2(require("os")); var utils_1 = require_utils(); function issueFileCommand(command, message) { @@ -221,10 +221,10 @@ var require_file_command = __commonJS({ if (!filePath) { throw new Error(`Unable to find environment variable for file command ${command}`); } - if (!fs33.existsSync(filePath)) { + if (!fs34.existsSync(filePath)) { throw new Error(`Missing file at path: ${filePath}`); } - fs33.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os8.EOL}`, { + fs34.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os8.EOL}`, { encoding: "utf8" }); } @@ -28154,13 +28154,13 @@ var require_io_util = __commonJS({ exports2.isRooted = isRooted; exports2.tryGetExecutablePath = tryGetExecutablePath; exports2.getCmdPath = getCmdPath; - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var path30 = __importStar2(require("path")); - _a6 = fs33.promises, exports2.chmod = _a6.chmod, exports2.copyFile = _a6.copyFile, exports2.lstat = _a6.lstat, exports2.mkdir = _a6.mkdir, exports2.open = _a6.open, exports2.readdir = _a6.readdir, exports2.rename = _a6.rename, exports2.rm = _a6.rm, exports2.rmdir = _a6.rmdir, exports2.stat = _a6.stat, exports2.symlink = _a6.symlink, exports2.unlink = _a6.unlink; + _a6 = fs34.promises, exports2.chmod = _a6.chmod, exports2.copyFile = _a6.copyFile, exports2.lstat = _a6.lstat, exports2.mkdir = _a6.mkdir, exports2.open = _a6.open, exports2.readdir = _a6.readdir, exports2.rename = _a6.rename, exports2.rm = _a6.rm, exports2.rmdir = _a6.rmdir, exports2.stat = _a6.stat, exports2.symlink = _a6.symlink, exports2.unlink = _a6.unlink; exports2.IS_WINDOWS = process.platform === "win32"; function readlink(fsPath) { return __awaiter2(this, void 0, void 0, function* () { - const result = yield fs33.promises.readlink(fsPath); + const result = yield fs34.promises.readlink(fsPath); if (exports2.IS_WINDOWS && !result.endsWith("\\")) { return `${result}\\`; } @@ -28168,7 +28168,7 @@ var require_io_util = __commonJS({ }); } exports2.UV_FS_O_EXLOCK = 268435456; - exports2.READONLY = fs33.constants.O_RDONLY; + exports2.READONLY = fs34.constants.O_RDONLY; function exists(fsPath) { return __awaiter2(this, void 0, void 0, function* () { try { @@ -34999,7 +34999,7 @@ var require_coerce = __commonJS({ var SemVer = require_semver(); var parse4 = require_parse2(); var { safeRe: re, t } = require_re(); - var coerce3 = (version, options) => { + var coerce4 = (version, options) => { if (version instanceof SemVer) { return version; } @@ -35034,7 +35034,7 @@ var require_coerce = __commonJS({ const build2 = options.includePrerelease && match2[6] ? `+${match2[6]}` : ""; return parse4(`${major}.${minor}.${patch}${prerelease}${build2}`, options); }; - module2.exports = coerce3; + module2.exports = coerce4; } }); @@ -36120,7 +36120,7 @@ var require_semver2 = __commonJS({ var gte7 = require_gte(); var lte2 = require_lte(); var cmp = require_cmp(); - var coerce3 = require_coerce(); + var coerce4 = require_coerce(); var truncate = require_truncate(); var Comparator = require_comparator(); var Range2 = require_range(); @@ -36159,7 +36159,7 @@ var require_semver2 = __commonJS({ gte: gte7, lte: lte2, cmp, - coerce: coerce3, + coerce: coerce4, truncate, Comparator, Range: Range2, @@ -40776,7 +40776,7 @@ var require_internal_globber = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.DefaultGlobber = void 0; var core29 = __importStar2(require_core()); - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var globOptionsHelper = __importStar2(require_internal_glob_options_helper()); var path30 = __importStar2(require("path")); var patternHelper = __importStar2(require_internal_pattern_helper()); @@ -40830,7 +40830,7 @@ var require_internal_globber = __commonJS({ for (const searchPath of patternHelper.getSearchPaths(patterns)) { core29.debug(`Search path '${searchPath}'`); try { - yield __await2(fs33.promises.lstat(searchPath)); + yield __await2(fs34.promises.lstat(searchPath)); } catch (err) { if (err.code === "ENOENT") { continue; @@ -40864,7 +40864,7 @@ var require_internal_globber = __commonJS({ continue; } const childLevel = item.level + 1; - const childItems = (yield __await2(fs33.promises.readdir(item.path))).map((x) => new internal_search_state_1.SearchState(path30.join(item.path, x), childLevel)); + const childItems = (yield __await2(fs34.promises.readdir(item.path))).map((x) => new internal_search_state_1.SearchState(path30.join(item.path, x), childLevel)); stack.push(...childItems.reverse()); } else if (match2 & internal_match_kind_1.MatchKind.File) { yield yield __await2(item.path); @@ -40899,7 +40899,7 @@ var require_internal_globber = __commonJS({ let stats; if (options.followSymbolicLinks) { try { - stats = yield fs33.promises.stat(item.path); + stats = yield fs34.promises.stat(item.path); } catch (err) { if (err.code === "ENOENT") { if (options.omitBrokenSymbolicLinks) { @@ -40911,10 +40911,10 @@ var require_internal_globber = __commonJS({ throw err; } } else { - stats = yield fs33.promises.lstat(item.path); + stats = yield fs34.promises.lstat(item.path); } if (stats.isDirectory() && options.followSymbolicLinks) { - const realPath = yield fs33.promises.realpath(item.path); + const realPath = yield fs34.promises.realpath(item.path); while (traversalChain.length >= item.level) { traversalChain.pop(); } @@ -41023,7 +41023,7 @@ var require_internal_hash_files = __commonJS({ exports2.hashFiles = hashFiles2; var crypto3 = __importStar2(require("crypto")); var core29 = __importStar2(require_core()); - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var stream2 = __importStar2(require("stream")); var util4 = __importStar2(require("util")); var path30 = __importStar2(require("path")); @@ -41046,13 +41046,13 @@ var require_internal_hash_files = __commonJS({ writeDelegate(`Ignore '${file}' since it is not under GITHUB_WORKSPACE.`); continue; } - if (fs33.statSync(file).isDirectory()) { + if (fs34.statSync(file).isDirectory()) { writeDelegate(`Skip directory '${file}'.`); continue; } const hash2 = crypto3.createHash("sha256"); const pipeline2 = util4.promisify(stream2.pipeline); - yield pipeline2(fs33.createReadStream(file), hash2); + yield pipeline2(fs34.createReadStream(file), hash2); result.write(hash2.digest()); count++; if (!hasMatch) { @@ -42258,8 +42258,8 @@ var require_semver3 = __commonJS({ r2 = new Range2(r2, options); return r1.intersects(r2); } - exports2.coerce = coerce3; - function coerce3(version, options) { + exports2.coerce = coerce4; + function coerce4(version, options) { if (version instanceof SemVer) { return version; } @@ -42428,7 +42428,7 @@ var require_cacheUtils = __commonJS({ var glob2 = __importStar2(require_glob()); var io9 = __importStar2(require_io()); var crypto3 = __importStar2(require("crypto")); - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var path30 = __importStar2(require("path")); var semver12 = __importStar2(require_semver3()); var util4 = __importStar2(require("util")); @@ -42457,7 +42457,7 @@ var require_cacheUtils = __commonJS({ }); } function getArchiveFileSizeInBytes(filePath) { - return fs33.statSync(filePath).size; + return fs34.statSync(filePath).size; } function resolvePaths(patterns) { return __awaiter2(this, void 0, void 0, function* () { @@ -42495,7 +42495,7 @@ var require_cacheUtils = __commonJS({ } function unlinkFile(filePath) { return __awaiter2(this, void 0, void 0, function* () { - return util4.promisify(fs33.unlink)(filePath); + return util4.promisify(fs34.unlink)(filePath); }); } function getVersion(app_1) { @@ -42537,7 +42537,7 @@ var require_cacheUtils = __commonJS({ } function getGnuTarPathOnWindows() { return __awaiter2(this, void 0, void 0, function* () { - if (fs33.existsSync(constants_1.GnuTarPathOnWindows)) { + if (fs34.existsSync(constants_1.GnuTarPathOnWindows)) { return constants_1.GnuTarPathOnWindows; } const versionOutput = yield getVersion("tar"); @@ -45310,7 +45310,7 @@ var require_common = __commonJS({ function setup(env) { createDebug.debug = createDebug; createDebug.default = createDebug; - createDebug.coerce = coerce3; + createDebug.coerce = coerce4; createDebug.disable = disable; createDebug.enable = enable; createDebug.enabled = enabled; @@ -45465,7 +45465,7 @@ var require_common = __commonJS({ } return false; } - function coerce3(val) { + function coerce4(val) { if (val instanceof Error) { return val.stack || val.message; } @@ -50678,11 +50678,11 @@ var require_tracingPolicy = __commonJS({ var import_log = require_log3(); var import_core_util = require_commonjs4(); var import_restError = require_restError3(); - var import_util60 = require_internal3(); + var import_util62 = require_internal3(); var tracingPolicyName2 = "tracingPolicy"; function tracingPolicy2(options = {}) { const userAgentPromise = (0, import_userAgent.getUserAgentValue)(options.userAgentPrefix); - const sanitizer = new import_util60.Sanitizer({ + const sanitizer = new import_util62.Sanitizer({ additionalAllowedQueryParameters: options.additionalAllowedQueryParameters }); const tracingClient = tryCreateTracingClient(); @@ -54308,11 +54308,11 @@ var require_response2 = __commonJS({ }); module2.exports = __toCommonJS2(response_exports); var import_core_rest_pipeline = require_commonjs6(); - var import_util60 = require_util7(); + var import_util62 = require_util7(); var originalResponse = /* @__PURE__ */ Symbol("Original FullOperationResponse"); function toCompatResponse2(response, options) { - let request3 = (0, import_util60.toWebResourceLike)(response.request); - let headers = (0, import_util60.toHttpHeadersLike)(response.headers); + let request3 = (0, import_util62.toWebResourceLike)(response.request); + let headers = (0, import_util62.toHttpHeadersLike)(response.headers); if (options?.createProxy) { return new Proxy(response, { get(target, prop, receiver) { @@ -54353,7 +54353,7 @@ var require_response2 = __commonJS({ return { ...compatResponse, headers, - request: (0, import_util60.toPipelineRequest)(compatResponse.request) + request: (0, import_util62.toPipelineRequest)(compatResponse.request) }; } } @@ -54460,7 +54460,7 @@ var require_requestPolicyFactoryPolicy = __commonJS({ requestPolicyFactoryPolicyName: () => requestPolicyFactoryPolicyName2 }); module2.exports = __toCommonJS2(requestPolicyFactoryPolicy_exports); - var import_util60 = require_util7(); + var import_util62 = require_util7(); var import_response = require_response2(); var HttpPipelineLogLevel2 = /* @__PURE__ */ ((HttpPipelineLogLevel22) => { HttpPipelineLogLevel22[HttpPipelineLogLevel22["ERROR"] = 1] = "ERROR"; @@ -54484,14 +54484,14 @@ var require_requestPolicyFactoryPolicy = __commonJS({ async sendRequest(request3, next) { let httpPipeline = { async sendRequest(httpRequest) { - const response2 = await next((0, import_util60.toPipelineRequest)(httpRequest)); + const response2 = await next((0, import_util62.toPipelineRequest)(httpRequest)); return (0, import_response.toCompatResponse)(response2, { createProxy: true }); } }; for (const factory of orderedFactories) { httpPipeline = factory.create(httpPipeline, mockRequestPolicyOptions); } - const webResourceLike = (0, import_util60.toWebResourceLike)(request3, { createProxy: true }); + const webResourceLike = (0, import_util62.toWebResourceLike)(request3, { createProxy: true }); const response = await httpPipeline.sendRequest(webResourceLike); return (0, import_response.toPipelineResponse)(response); } @@ -54526,12 +54526,12 @@ var require_httpClientAdapter = __commonJS({ }); module2.exports = __toCommonJS2(httpClientAdapter_exports); var import_response = require_response2(); - var import_util60 = require_util7(); + var import_util62 = require_util7(); function convertHttpClient2(requestPolicyClient) { return { sendRequest: async (request3) => { const response = await requestPolicyClient.sendRequest( - (0, import_util60.toWebResourceLike)(request3, { createProxy: true }) + (0, import_util62.toWebResourceLike)(request3, { createProxy: true }) ); return (0, import_response.toPipelineResponse)(response); } @@ -54569,7 +54569,7 @@ var require_commonjs9 = __commonJS({ disableKeepAlivePolicyName: () => import_disableKeepAlivePolicy.disableKeepAlivePolicyName, requestPolicyFactoryPolicyName: () => import_requestPolicyFactoryPolicy.requestPolicyFactoryPolicyName, toCompatResponse: () => import_response.toCompatResponse, - toHttpHeadersLike: () => import_util60.toHttpHeadersLike + toHttpHeadersLike: () => import_util62.toHttpHeadersLike }); module2.exports = __toCommonJS2(src_exports); var import_extendedClient = require_extendedClient(); @@ -54577,7 +54577,7 @@ var require_commonjs9 = __commonJS({ var import_requestPolicyFactoryPolicy = require_requestPolicyFactoryPolicy(); var import_disableKeepAlivePolicy = require_disableKeepAlivePolicy(); var import_httpClientAdapter = require_httpClientAdapter(); - var import_util60 = require_util7(); + var import_util62 = require_util7(); } }); @@ -107261,7 +107261,7 @@ var require_downloadUtils = __commonJS({ var http_client_1 = require_lib(); var storage_blob_1 = require_commonjs15(); var buffer = __importStar2(require("buffer")); - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var stream2 = __importStar2(require("stream")); var util4 = __importStar2(require("util")); var utils = __importStar2(require_cacheUtils()); @@ -107372,7 +107372,7 @@ var require_downloadUtils = __commonJS({ exports2.DownloadProgress = DownloadProgress; function downloadCacheHttpClient(archiveLocation, archivePath) { return __awaiter2(this, void 0, void 0, function* () { - const writeStream = fs33.createWriteStream(archivePath); + const writeStream = fs34.createWriteStream(archivePath); const httpClient = new http_client_1.HttpClient("actions/cache"); const downloadResponse = yield (0, requestUtils_1.retryHttpClientResponse)("downloadCache", () => __awaiter2(this, void 0, void 0, function* () { return httpClient.get(archiveLocation); @@ -107397,7 +107397,7 @@ var require_downloadUtils = __commonJS({ function downloadCacheHttpClientConcurrent(archiveLocation, archivePath, options) { return __awaiter2(this, void 0, void 0, function* () { var _a6; - const archiveDescriptor = yield fs33.promises.open(archivePath, "w"); + const archiveDescriptor = yield fs34.promises.open(archivePath, "w"); const httpClient = new http_client_1.HttpClient("actions/cache", void 0, { socketTimeout: options.timeoutInMs, keepAlive: true @@ -107513,7 +107513,7 @@ var require_downloadUtils = __commonJS({ } else { const maxSegmentSize = Math.min(134217728, buffer.constants.MAX_LENGTH); const downloadProgress = new DownloadProgress(contentLength); - const fd = fs33.openSync(archivePath, "w"); + const fd = fs34.openSync(archivePath, "w"); try { downloadProgress.startDisplayTimer(); const controller = new abort_controller_1.AbortController(); @@ -107531,12 +107531,12 @@ var require_downloadUtils = __commonJS({ controller.abort(); throw new Error("Aborting cache download as the download time exceeded the timeout."); } else if (Buffer.isBuffer(result)) { - fs33.writeFileSync(fd, result); + fs34.writeFileSync(fd, result); } } } finally { downloadProgress.stopDisplayTimer(); - fs33.closeSync(fd); + fs34.closeSync(fd); } } }); @@ -107875,7 +107875,7 @@ var require_cacheHttpClient = __commonJS({ var core29 = __importStar2(require_core()); var http_client_1 = require_lib(); var auth_1 = require_auth(); - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var url_1 = require("url"); var utils = __importStar2(require_cacheUtils()); var uploadUtils_1 = require_uploadUtils(); @@ -108016,7 +108016,7 @@ Other caches with similar key:`); return __awaiter2(this, void 0, void 0, function* () { const fileSize = utils.getArchiveFileSizeInBytes(archivePath); const resourceUrl = getCacheApiUrl(`caches/${cacheId.toString()}`); - const fd = fs33.openSync(archivePath, "r"); + const fd = fs34.openSync(archivePath, "r"); const uploadOptions = (0, options_1.getUploadOptions)(options); const concurrency = utils.assertDefined("uploadConcurrency", uploadOptions.uploadConcurrency); const maxChunkSize = utils.assertDefined("uploadChunkSize", uploadOptions.uploadChunkSize); @@ -108030,7 +108030,7 @@ Other caches with similar key:`); const start = offset; const end = offset + chunkSize - 1; offset += maxChunkSize; - yield uploadChunk(httpClient, resourceUrl, () => fs33.createReadStream(archivePath, { + yield uploadChunk(httpClient, resourceUrl, () => fs34.createReadStream(archivePath, { fd, start, end, @@ -108041,7 +108041,7 @@ Other caches with similar key:`); } }))); } finally { - fs33.closeSync(fd); + fs34.closeSync(fd); } return; }); @@ -114076,7 +114076,7 @@ var require_manifest = __commonJS({ var core_1 = require_core(); var os8 = require("os"); var cp = require("child_process"); - var fs33 = require("fs"); + var fs34 = require("fs"); function _findMatch(versionSpec, stable, candidates, archFilter) { return __awaiter2(this, void 0, void 0, function* () { const platFilter = os8.platform(); @@ -114138,10 +114138,10 @@ var require_manifest = __commonJS({ const lsbReleaseFile = "/etc/lsb-release"; const osReleaseFile = "/etc/os-release"; let contents = ""; - if (fs33.existsSync(lsbReleaseFile)) { - contents = fs33.readFileSync(lsbReleaseFile).toString(); - } else if (fs33.existsSync(osReleaseFile)) { - contents = fs33.readFileSync(osReleaseFile).toString(); + if (fs34.existsSync(lsbReleaseFile)) { + contents = fs34.readFileSync(lsbReleaseFile).toString(); + } else if (fs34.existsSync(osReleaseFile)) { + contents = fs34.readFileSync(osReleaseFile).toString(); } return contents; } @@ -114350,7 +114350,7 @@ var require_tool_cache = __commonJS({ var core29 = __importStar2(require_core()); var io9 = __importStar2(require_io()); var crypto3 = __importStar2(require("crypto")); - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var mm = __importStar2(require_manifest()); var os8 = __importStar2(require("os")); var path30 = __importStar2(require("path")); @@ -114396,7 +114396,7 @@ var require_tool_cache = __commonJS({ } function downloadToolAttempt(url2, dest, auth2, headers) { return __awaiter2(this, void 0, void 0, function* () { - if (fs33.existsSync(dest)) { + if (fs34.existsSync(dest)) { throw new Error(`Destination file path ${dest} already exists`); } const http = new httpm.HttpClient(userAgent2, [], { @@ -114420,7 +114420,7 @@ var require_tool_cache = __commonJS({ const readStream = responseMessageFactory(); let succeeded = false; try { - yield pipeline2(readStream, fs33.createWriteStream(dest)); + yield pipeline2(readStream, fs34.createWriteStream(dest)); core29.debug("download complete"); succeeded = true; return dest; @@ -114632,11 +114632,11 @@ var require_tool_cache = __commonJS({ arch2 = arch2 || os8.arch(); core29.debug(`Caching tool ${tool} ${version} ${arch2}`); core29.debug(`source dir: ${sourceDir}`); - if (!fs33.statSync(sourceDir).isDirectory()) { + if (!fs34.statSync(sourceDir).isDirectory()) { throw new Error("sourceDir is not a directory"); } const destPath = yield _createToolPath(tool, version, arch2); - for (const itemName of fs33.readdirSync(sourceDir)) { + for (const itemName of fs34.readdirSync(sourceDir)) { const s = path30.join(sourceDir, itemName); yield io9.cp(s, destPath, { recursive: true }); } @@ -114650,7 +114650,7 @@ var require_tool_cache = __commonJS({ arch2 = arch2 || os8.arch(); core29.debug(`Caching tool ${tool} ${version} ${arch2}`); core29.debug(`source file: ${sourceFile}`); - if (!fs33.statSync(sourceFile).isFile()) { + if (!fs34.statSync(sourceFile).isFile()) { throw new Error("sourceFile is not a file"); } const destFolder = yield _createToolPath(tool, version, arch2); @@ -114679,7 +114679,7 @@ var require_tool_cache = __commonJS({ versionSpec = semver12.clean(versionSpec) || ""; const cachePath = path30.join(_getCacheDirectory(), toolName, versionSpec, arch2); core29.debug(`checking cache: ${cachePath}`); - if (fs33.existsSync(cachePath) && fs33.existsSync(`${cachePath}.complete`)) { + if (fs34.existsSync(cachePath) && fs34.existsSync(`${cachePath}.complete`)) { core29.debug(`Found tool in cache ${toolName} ${versionSpec} ${arch2}`); toolPath = cachePath; } else { @@ -114692,12 +114692,12 @@ var require_tool_cache = __commonJS({ const versions = []; arch2 = arch2 || os8.arch(); const toolPath = path30.join(_getCacheDirectory(), toolName); - if (fs33.existsSync(toolPath)) { - const children = fs33.readdirSync(toolPath); + if (fs34.existsSync(toolPath)) { + const children = fs34.readdirSync(toolPath); for (const child of children) { if (isExplicitVersion(child)) { const fullPath = path30.join(toolPath, child, arch2 || ""); - if (fs33.existsSync(fullPath) && fs33.existsSync(`${fullPath}.complete`)) { + if (fs34.existsSync(fullPath) && fs34.existsSync(`${fullPath}.complete`)) { versions.push(child); } } @@ -114768,7 +114768,7 @@ var require_tool_cache = __commonJS({ function _completeToolPath(tool, version, arch2) { const folderPath = path30.join(_getCacheDirectory(), tool, semver12.clean(version) || version, arch2 || ""); const markerPath = `${folderPath}.complete`; - fs33.writeFileSync(markerPath, ""); + fs34.writeFileSync(markerPath, ""); core29.debug("finished caching tool"); } function isExplicitVersion(versionSpec) { @@ -120981,15 +120981,15 @@ var require_upload_zip_specification = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.getUploadZipSpecification = exports2.validateRootDirectory = void 0; - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var core_1 = require_core(); var path_1 = require("path"); var path_and_artifact_name_validation_1 = require_path_and_artifact_name_validation(); function validateRootDirectory(rootDirectory) { - if (!fs33.existsSync(rootDirectory)) { + if (!fs34.existsSync(rootDirectory)) { throw new Error(`The provided rootDirectory ${rootDirectory} does not exist`); } - if (!fs33.statSync(rootDirectory).isDirectory()) { + if (!fs34.statSync(rootDirectory).isDirectory()) { throw new Error(`The provided rootDirectory ${rootDirectory} is not a valid directory`); } (0, core_1.info)(`Root directory input is valid!`); @@ -121000,7 +121000,7 @@ var require_upload_zip_specification = __commonJS({ rootDirectory = (0, path_1.normalize)(rootDirectory); rootDirectory = (0, path_1.resolve)(rootDirectory); for (let file of filesToZip) { - const stats = fs33.lstatSync(file, { throwIfNoEntry: false }); + const stats = fs34.lstatSync(file, { throwIfNoEntry: false }); if (!stats) { throw new Error(`File ${file} does not exist`); } @@ -122075,13 +122075,13 @@ var require_minimatch2 = __commonJS({ var require_readdir_glob = __commonJS({ "node_modules/@actions/artifact/node_modules/readdir-glob/index.js"(exports2, module2) { module2.exports = readdirGlob2; - var fs33 = require("fs"); + var fs34 = require("fs"); var { EventEmitter: EventEmitter2 } = require("events"); var { Minimatch: Minimatch2 } = require_minimatch2(); var { resolve: resolve15 } = require("path"); function readdir3(dir, strict) { return new Promise((resolve16, reject) => { - fs33.readdir(dir, { withFileTypes: true }, (err, files) => { + fs34.readdir(dir, { withFileTypes: true }, (err, files) => { if (err) { switch (err.code) { case "ENOTDIR": @@ -122114,7 +122114,7 @@ var require_readdir_glob = __commonJS({ } function stat2(file, followSymlinks) { return new Promise((resolve16, reject) => { - const statFunc = followSymlinks ? fs33.stat : fs33.lstat; + const statFunc = followSymlinks ? fs34.stat : fs34.lstat; statFunc(file, (err, stats) => { if (err) { switch (err.code) { @@ -124179,54 +124179,54 @@ var require_polyfills = __commonJS({ } var chdir; module2.exports = patch; - function patch(fs33) { + function patch(fs34) { if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { - patchLchmod(fs33); - } - if (!fs33.lutimes) { - patchLutimes(fs33); - } - fs33.chown = chownFix(fs33.chown); - fs33.fchown = chownFix(fs33.fchown); - fs33.lchown = chownFix(fs33.lchown); - fs33.chmod = chmodFix(fs33.chmod); - fs33.fchmod = chmodFix(fs33.fchmod); - fs33.lchmod = chmodFix(fs33.lchmod); - fs33.chownSync = chownFixSync(fs33.chownSync); - fs33.fchownSync = chownFixSync(fs33.fchownSync); - fs33.lchownSync = chownFixSync(fs33.lchownSync); - fs33.chmodSync = chmodFixSync(fs33.chmodSync); - fs33.fchmodSync = chmodFixSync(fs33.fchmodSync); - fs33.lchmodSync = chmodFixSync(fs33.lchmodSync); - fs33.stat = statFix(fs33.stat); - fs33.fstat = statFix(fs33.fstat); - fs33.lstat = statFix(fs33.lstat); - fs33.statSync = statFixSync(fs33.statSync); - fs33.fstatSync = statFixSync(fs33.fstatSync); - fs33.lstatSync = statFixSync(fs33.lstatSync); - if (fs33.chmod && !fs33.lchmod) { - fs33.lchmod = function(path30, mode, cb) { + patchLchmod(fs34); + } + if (!fs34.lutimes) { + patchLutimes(fs34); + } + fs34.chown = chownFix(fs34.chown); + fs34.fchown = chownFix(fs34.fchown); + fs34.lchown = chownFix(fs34.lchown); + fs34.chmod = chmodFix(fs34.chmod); + fs34.fchmod = chmodFix(fs34.fchmod); + fs34.lchmod = chmodFix(fs34.lchmod); + fs34.chownSync = chownFixSync(fs34.chownSync); + fs34.fchownSync = chownFixSync(fs34.fchownSync); + fs34.lchownSync = chownFixSync(fs34.lchownSync); + fs34.chmodSync = chmodFixSync(fs34.chmodSync); + fs34.fchmodSync = chmodFixSync(fs34.fchmodSync); + fs34.lchmodSync = chmodFixSync(fs34.lchmodSync); + fs34.stat = statFix(fs34.stat); + fs34.fstat = statFix(fs34.fstat); + fs34.lstat = statFix(fs34.lstat); + fs34.statSync = statFixSync(fs34.statSync); + fs34.fstatSync = statFixSync(fs34.fstatSync); + fs34.lstatSync = statFixSync(fs34.lstatSync); + if (fs34.chmod && !fs34.lchmod) { + fs34.lchmod = function(path30, mode, cb) { if (cb) process.nextTick(cb); }; - fs33.lchmodSync = function() { + fs34.lchmodSync = function() { }; } - if (fs33.chown && !fs33.lchown) { - fs33.lchown = function(path30, uid, gid, cb) { + if (fs34.chown && !fs34.lchown) { + fs34.lchown = function(path30, uid, gid, cb) { if (cb) process.nextTick(cb); }; - fs33.lchownSync = function() { + fs34.lchownSync = function() { }; } if (platform2 === "win32") { - fs33.rename = typeof fs33.rename !== "function" ? fs33.rename : (function(fs$rename) { + fs34.rename = typeof fs34.rename !== "function" ? fs34.rename : (function(fs$rename) { function rename(from, to, cb) { var start = Date.now(); var backoff = 0; fs$rename(from, to, function CB(er) { if (er && (er.code === "EACCES" || er.code === "EPERM") && Date.now() - start < 6e4) { setTimeout(function() { - fs33.stat(to, function(stater, st) { + fs34.stat(to, function(stater, st) { if (stater && stater.code === "ENOENT") fs$rename(from, to, CB); else @@ -124242,9 +124242,9 @@ var require_polyfills = __commonJS({ } if (Object.setPrototypeOf) Object.setPrototypeOf(rename, fs$rename); return rename; - })(fs33.rename); + })(fs34.rename); } - fs33.read = typeof fs33.read !== "function" ? fs33.read : (function(fs$read) { + fs34.read = typeof fs34.read !== "function" ? fs34.read : (function(fs$read) { function read(fd, buffer, offset, length, position, callback_) { var callback; if (callback_ && typeof callback_ === "function") { @@ -124252,22 +124252,22 @@ var require_polyfills = __commonJS({ callback = function(er, _2, __) { if (er && er.code === "EAGAIN" && eagCounter < 10) { eagCounter++; - return fs$read.call(fs33, fd, buffer, offset, length, position, callback); + return fs$read.call(fs34, fd, buffer, offset, length, position, callback); } callback_.apply(this, arguments); }; } - return fs$read.call(fs33, fd, buffer, offset, length, position, callback); + return fs$read.call(fs34, fd, buffer, offset, length, position, callback); } if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read); return read; - })(fs33.read); - fs33.readSync = typeof fs33.readSync !== "function" ? fs33.readSync : /* @__PURE__ */ (function(fs$readSync) { + })(fs34.read); + fs34.readSync = typeof fs34.readSync !== "function" ? fs34.readSync : /* @__PURE__ */ (function(fs$readSync) { return function(fd, buffer, offset, length, position) { var eagCounter = 0; while (true) { try { - return fs$readSync.call(fs33, fd, buffer, offset, length, position); + return fs$readSync.call(fs34, fd, buffer, offset, length, position); } catch (er) { if (er.code === "EAGAIN" && eagCounter < 10) { eagCounter++; @@ -124277,10 +124277,10 @@ var require_polyfills = __commonJS({ } } }; - })(fs33.readSync); - function patchLchmod(fs34) { - fs34.lchmod = function(path30, mode, callback) { - fs34.open( + })(fs34.readSync); + function patchLchmod(fs35) { + fs35.lchmod = function(path30, mode, callback) { + fs35.open( path30, constants.O_WRONLY | constants.O_SYMLINK, mode, @@ -124289,80 +124289,80 @@ var require_polyfills = __commonJS({ if (callback) callback(err); return; } - fs34.fchmod(fd, mode, function(err2) { - fs34.close(fd, function(err22) { + fs35.fchmod(fd, mode, function(err2) { + fs35.close(fd, function(err22) { if (callback) callback(err2 || err22); }); }); } ); }; - fs34.lchmodSync = function(path30, mode) { - var fd = fs34.openSync(path30, constants.O_WRONLY | constants.O_SYMLINK, mode); + fs35.lchmodSync = function(path30, mode) { + var fd = fs35.openSync(path30, constants.O_WRONLY | constants.O_SYMLINK, mode); var threw = true; var ret; try { - ret = fs34.fchmodSync(fd, mode); + ret = fs35.fchmodSync(fd, mode); threw = false; } finally { if (threw) { try { - fs34.closeSync(fd); + fs35.closeSync(fd); } catch (er) { } } else { - fs34.closeSync(fd); + fs35.closeSync(fd); } } return ret; }; } - function patchLutimes(fs34) { - if (constants.hasOwnProperty("O_SYMLINK") && fs34.futimes) { - fs34.lutimes = function(path30, at, mt, cb) { - fs34.open(path30, constants.O_SYMLINK, function(er, fd) { + function patchLutimes(fs35) { + if (constants.hasOwnProperty("O_SYMLINK") && fs35.futimes) { + fs35.lutimes = function(path30, at, mt, cb) { + fs35.open(path30, constants.O_SYMLINK, function(er, fd) { if (er) { if (cb) cb(er); return; } - fs34.futimes(fd, at, mt, function(er2) { - fs34.close(fd, function(er22) { + fs35.futimes(fd, at, mt, function(er2) { + fs35.close(fd, function(er22) { if (cb) cb(er2 || er22); }); }); }); }; - fs34.lutimesSync = function(path30, at, mt) { - var fd = fs34.openSync(path30, constants.O_SYMLINK); + fs35.lutimesSync = function(path30, at, mt) { + var fd = fs35.openSync(path30, constants.O_SYMLINK); var ret; var threw = true; try { - ret = fs34.futimesSync(fd, at, mt); + ret = fs35.futimesSync(fd, at, mt); threw = false; } finally { if (threw) { try { - fs34.closeSync(fd); + fs35.closeSync(fd); } catch (er) { } } else { - fs34.closeSync(fd); + fs35.closeSync(fd); } } return ret; }; - } else if (fs34.futimes) { - fs34.lutimes = function(_a6, _b2, _c2, cb) { + } else if (fs35.futimes) { + fs35.lutimes = function(_a6, _b2, _c2, cb) { if (cb) process.nextTick(cb); }; - fs34.lutimesSync = function() { + fs35.lutimesSync = function() { }; } } function chmodFix(orig) { if (!orig) return orig; return function(target, mode, cb) { - return orig.call(fs33, target, mode, function(er) { + return orig.call(fs34, target, mode, function(er) { if (chownErOk(er)) er = null; if (cb) cb.apply(this, arguments); }); @@ -124372,7 +124372,7 @@ var require_polyfills = __commonJS({ if (!orig) return orig; return function(target, mode) { try { - return orig.call(fs33, target, mode); + return orig.call(fs34, target, mode); } catch (er) { if (!chownErOk(er)) throw er; } @@ -124381,7 +124381,7 @@ var require_polyfills = __commonJS({ function chownFix(orig) { if (!orig) return orig; return function(target, uid, gid, cb) { - return orig.call(fs33, target, uid, gid, function(er) { + return orig.call(fs34, target, uid, gid, function(er) { if (chownErOk(er)) er = null; if (cb) cb.apply(this, arguments); }); @@ -124391,7 +124391,7 @@ var require_polyfills = __commonJS({ if (!orig) return orig; return function(target, uid, gid) { try { - return orig.call(fs33, target, uid, gid); + return orig.call(fs34, target, uid, gid); } catch (er) { if (!chownErOk(er)) throw er; } @@ -124411,13 +124411,13 @@ var require_polyfills = __commonJS({ } if (cb) cb.apply(this, arguments); } - return options ? orig.call(fs33, target, options, callback) : orig.call(fs33, target, callback); + return options ? orig.call(fs34, target, options, callback) : orig.call(fs34, target, callback); }; } function statFixSync(orig) { if (!orig) return orig; return function(target, options) { - var stats = options ? orig.call(fs33, target, options) : orig.call(fs33, target); + var stats = options ? orig.call(fs34, target, options) : orig.call(fs34, target); if (stats) { if (stats.uid < 0) stats.uid += 4294967296; if (stats.gid < 0) stats.gid += 4294967296; @@ -124446,7 +124446,7 @@ var require_legacy_streams = __commonJS({ "node_modules/graceful-fs/legacy-streams.js"(exports2, module2) { var Stream = require("stream").Stream; module2.exports = legacy; - function legacy(fs33) { + function legacy(fs34) { return { ReadStream, WriteStream @@ -124489,7 +124489,7 @@ var require_legacy_streams = __commonJS({ }); return; } - fs33.open(this.path, this.flags, this.mode, function(err, fd) { + fs34.open(this.path, this.flags, this.mode, function(err, fd) { if (err) { self2.emit("error", err); self2.readable = false; @@ -124528,7 +124528,7 @@ var require_legacy_streams = __commonJS({ this.busy = false; this._queue = []; if (this.fd === null) { - this._open = fs33.open; + this._open = fs34.open; this._queue.push([this._open, this.path, this.flags, this.mode, void 0]); this.flush(); } @@ -124563,7 +124563,7 @@ var require_clone = __commonJS({ // node_modules/graceful-fs/graceful-fs.js var require_graceful_fs = __commonJS({ "node_modules/graceful-fs/graceful-fs.js"(exports2, module2) { - var fs33 = require("fs"); + var fs34 = require("fs"); var polyfills = require_polyfills(); var legacy = require_legacy_streams(); var clone = require_clone(); @@ -124595,12 +124595,12 @@ var require_graceful_fs = __commonJS({ m = "GFS4: " + m.split(/\n/).join("\nGFS4: "); console.error(m); }; - if (!fs33[gracefulQueue]) { + if (!fs34[gracefulQueue]) { queue2 = global[gracefulQueue] || []; - publishQueue(fs33, queue2); - fs33.close = (function(fs$close) { + publishQueue(fs34, queue2); + fs34.close = (function(fs$close) { function close(fd, cb) { - return fs$close.call(fs33, fd, function(err) { + return fs$close.call(fs34, fd, function(err) { if (!err) { resetQueue(); } @@ -124612,40 +124612,40 @@ var require_graceful_fs = __commonJS({ value: fs$close }); return close; - })(fs33.close); - fs33.closeSync = (function(fs$closeSync) { + })(fs34.close); + fs34.closeSync = (function(fs$closeSync) { function closeSync(fd) { - fs$closeSync.apply(fs33, arguments); + fs$closeSync.apply(fs34, arguments); resetQueue(); } Object.defineProperty(closeSync, previousSymbol, { value: fs$closeSync }); return closeSync; - })(fs33.closeSync); + })(fs34.closeSync); if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) { process.on("exit", function() { - debug6(fs33[gracefulQueue]); - require("assert").equal(fs33[gracefulQueue].length, 0); + debug6(fs34[gracefulQueue]); + require("assert").equal(fs34[gracefulQueue].length, 0); }); } } var queue2; if (!global[gracefulQueue]) { - publishQueue(global, fs33[gracefulQueue]); - } - module2.exports = patch(clone(fs33)); - if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs33.__patched) { - module2.exports = patch(fs33); - fs33.__patched = true; - } - function patch(fs34) { - polyfills(fs34); - fs34.gracefulify = patch; - fs34.createReadStream = createReadStream4; - fs34.createWriteStream = createWriteStream3; - var fs$readFile = fs34.readFile; - fs34.readFile = readFile; + publishQueue(global, fs34[gracefulQueue]); + } + module2.exports = patch(clone(fs34)); + if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs34.__patched) { + module2.exports = patch(fs34); + fs34.__patched = true; + } + function patch(fs35) { + polyfills(fs35); + fs35.gracefulify = patch; + fs35.createReadStream = createReadStream4; + fs35.createWriteStream = createWriteStream3; + var fs$readFile = fs35.readFile; + fs35.readFile = readFile; function readFile(path30, options, cb) { if (typeof options === "function") cb = options, options = null; @@ -124661,8 +124661,8 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$writeFile = fs34.writeFile; - fs34.writeFile = writeFile; + var fs$writeFile = fs35.writeFile; + fs35.writeFile = writeFile; function writeFile(path30, data, options, cb) { if (typeof options === "function") cb = options, options = null; @@ -124678,9 +124678,9 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$appendFile = fs34.appendFile; + var fs$appendFile = fs35.appendFile; if (fs$appendFile) - fs34.appendFile = appendFile; + fs35.appendFile = appendFile; function appendFile(path30, data, options, cb) { if (typeof options === "function") cb = options, options = null; @@ -124696,9 +124696,9 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$copyFile = fs34.copyFile; + var fs$copyFile = fs35.copyFile; if (fs$copyFile) - fs34.copyFile = copyFile2; + fs35.copyFile = copyFile2; function copyFile2(src, dest, flags, cb) { if (typeof flags === "function") { cb = flags; @@ -124716,8 +124716,8 @@ var require_graceful_fs = __commonJS({ }); } } - var fs$readdir = fs34.readdir; - fs34.readdir = readdir3; + var fs$readdir = fs35.readdir; + fs35.readdir = readdir3; var noReaddirOptionVersions = /^v[0-5]\./; function readdir3(path30, options, cb) { if (typeof options === "function") @@ -124758,21 +124758,21 @@ var require_graceful_fs = __commonJS({ } } if (process.version.substr(0, 4) === "v0.8") { - var legStreams = legacy(fs34); + var legStreams = legacy(fs35); ReadStream = legStreams.ReadStream; WriteStream = legStreams.WriteStream; } - var fs$ReadStream = fs34.ReadStream; + var fs$ReadStream = fs35.ReadStream; if (fs$ReadStream) { ReadStream.prototype = Object.create(fs$ReadStream.prototype); ReadStream.prototype.open = ReadStream$open; } - var fs$WriteStream = fs34.WriteStream; + var fs$WriteStream = fs35.WriteStream; if (fs$WriteStream) { WriteStream.prototype = Object.create(fs$WriteStream.prototype); WriteStream.prototype.open = WriteStream$open; } - Object.defineProperty(fs34, "ReadStream", { + Object.defineProperty(fs35, "ReadStream", { get: function() { return ReadStream; }, @@ -124782,7 +124782,7 @@ var require_graceful_fs = __commonJS({ enumerable: true, configurable: true }); - Object.defineProperty(fs34, "WriteStream", { + Object.defineProperty(fs35, "WriteStream", { get: function() { return WriteStream; }, @@ -124793,7 +124793,7 @@ var require_graceful_fs = __commonJS({ configurable: true }); var FileReadStream = ReadStream; - Object.defineProperty(fs34, "FileReadStream", { + Object.defineProperty(fs35, "FileReadStream", { get: function() { return FileReadStream; }, @@ -124804,7 +124804,7 @@ var require_graceful_fs = __commonJS({ configurable: true }); var FileWriteStream = WriteStream; - Object.defineProperty(fs34, "FileWriteStream", { + Object.defineProperty(fs35, "FileWriteStream", { get: function() { return FileWriteStream; }, @@ -124853,13 +124853,13 @@ var require_graceful_fs = __commonJS({ }); } function createReadStream4(path30, options) { - return new fs34.ReadStream(path30, options); + return new fs35.ReadStream(path30, options); } function createWriteStream3(path30, options) { - return new fs34.WriteStream(path30, options); + return new fs35.WriteStream(path30, options); } - var fs$open = fs34.open; - fs34.open = open; + var fs$open = fs35.open; + fs35.open = open; function open(path30, flags, mode, cb) { if (typeof mode === "function") cb = mode, mode = null; @@ -124875,20 +124875,20 @@ var require_graceful_fs = __commonJS({ }); } } - return fs34; + return fs35; } function enqueue(elem) { debug6("ENQUEUE", elem[0].name, elem[1]); - fs33[gracefulQueue].push(elem); + fs34[gracefulQueue].push(elem); retry2(); } var retryTimer; function resetQueue() { var now = Date.now(); - for (var i = 0; i < fs33[gracefulQueue].length; ++i) { - if (fs33[gracefulQueue][i].length > 2) { - fs33[gracefulQueue][i][3] = now; - fs33[gracefulQueue][i][4] = now; + for (var i = 0; i < fs34[gracefulQueue].length; ++i) { + if (fs34[gracefulQueue][i].length > 2) { + fs34[gracefulQueue][i][3] = now; + fs34[gracefulQueue][i][4] = now; } } retry2(); @@ -124896,9 +124896,9 @@ var require_graceful_fs = __commonJS({ function retry2() { clearTimeout(retryTimer); retryTimer = void 0; - if (fs33[gracefulQueue].length === 0) + if (fs34[gracefulQueue].length === 0) return; - var elem = fs33[gracefulQueue].shift(); + var elem = fs34[gracefulQueue].shift(); var fn = elem[0]; var args = elem[1]; var err = elem[2]; @@ -124920,7 +124920,7 @@ var require_graceful_fs = __commonJS({ debug6("RETRY", fn.name, args); fn.apply(null, args.concat([startTime])); } else { - fs33[gracefulQueue].push(elem); + fs34[gracefulQueue].push(elem); } } if (retryTimer === void 0) { @@ -135743,7 +135743,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s)) retur g.minimatch.escape = vi.escape; g.minimatch.unescape = Ei.unescape; }); - var fs33 = R((Wt) => { + var fs34 = R((Wt) => { "use strict"; Object.defineProperty(Wt, "__esModule", { value: true }); Wt.LRUCache = void 0; @@ -136612,7 +136612,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s)) retur }; Object.defineProperty(_2, "__esModule", { value: true }); _2.PathScurry = _2.Path = _2.PathScurryDarwin = _2.PathScurryPosix = _2.PathScurryWin32 = _2.PathScurryBase = _2.PathPosix = _2.PathWin32 = _2.PathBase = _2.ChildrenCache = _2.ResolveCache = void 0; - var Qt = fs33(), Yt = require("node:path"), yr = require("node:url"), pt = require("fs"), Sr = br(require("node:fs")), vr = pt.realpathSync.native, Ht = require("node:fs/promises"), bs = Oe(), mt = { lstatSync: pt.lstatSync, readdir: pt.readdir, readdirSync: pt.readdirSync, readlinkSync: pt.readlinkSync, realpathSync: vr, promises: { lstat: Ht.lstat, readdir: Ht.readdir, readlink: Ht.readlink, realpath: Ht.realpath } }, _s2 = (n) => !n || n === mt || n === Sr ? mt : { ...mt, ...n, promises: { ...mt.promises, ...n.promises || {} } }, Os = /^\\\\\?\\([a-z]:)\\?$/i, Er = (n) => n.replace(/\//g, "\\").replace(Os, "$1\\"), _r2 = /[\\\/]/, N = 0, xs = 1, Ts = 2, G = 4, Cs = 6, Rs = 8, Q = 10, As = 12, j = 15, dt = ~j, xe = 16, ys = 32, gt = 64, W = 128, Vt = 256, Xt = 512, Ss = gt | W | Xt, Or = 1023, Te = (n) => n.isFile() ? Rs : n.isDirectory() ? G : n.isSymbolicLink() ? Q : n.isCharacterDevice() ? Ts : n.isBlockDevice() ? Cs : n.isSocket() ? As : n.isFIFO() ? xs : N, vs = new Qt.LRUCache({ max: 2 ** 12 }), wt = (n) => { + var Qt = fs34(), Yt = require("node:path"), yr = require("node:url"), pt = require("fs"), Sr = br(require("node:fs")), vr = pt.realpathSync.native, Ht = require("node:fs/promises"), bs = Oe(), mt = { lstatSync: pt.lstatSync, readdir: pt.readdir, readdirSync: pt.readdirSync, readlinkSync: pt.readlinkSync, realpathSync: vr, promises: { lstat: Ht.lstat, readdir: Ht.readdir, readlink: Ht.readlink, realpath: Ht.realpath } }, _s2 = (n) => !n || n === mt || n === Sr ? mt : { ...mt, ...n, promises: { ...mt.promises, ...n.promises || {} } }, Os = /^\\\\\?\\([a-z]:)\\?$/i, Er = (n) => n.replace(/\//g, "\\").replace(Os, "$1\\"), _r2 = /[\\\/]/, N = 0, xs = 1, Ts = 2, G = 4, Cs = 6, Rs = 8, Q = 10, As = 12, j = 15, dt = ~j, xe = 16, ys = 32, gt = 64, W = 128, Vt = 256, Xt = 512, Ss = gt | W | Xt, Or = 1023, Te = (n) => n.isFile() ? Rs : n.isDirectory() ? G : n.isSymbolicLink() ? Q : n.isCharacterDevice() ? Ts : n.isBlockDevice() ? Cs : n.isSocket() ? As : n.isFIFO() ? xs : N, vs = new Qt.LRUCache({ max: 2 ** 12 }), wt = (n) => { let t = vs.get(n); if (t) return t; let e = n.normalize("NFKD"); @@ -137990,7 +137990,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s)) retur // node_modules/archiver-utils/file.js var require_file2 = __commonJS({ "node_modules/archiver-utils/file.js"(exports2, module2) { - var fs33 = require_graceful_fs(); + var fs34 = require_graceful_fs(); var path30 = require("path"); var flatten = require_flatten(); var difference = require_difference(); @@ -138017,7 +138017,7 @@ var require_file2 = __commonJS({ }; file.exists = function() { var filepath = path30.join.apply(path30, arguments); - return fs33.existsSync(filepath); + return fs34.existsSync(filepath); }; file.expand = function(...args) { var options = isPlainObject4(args[0]) ? args.shift() : {}; @@ -138035,7 +138035,7 @@ var require_file2 = __commonJS({ if (typeof options.filter === "function") { return options.filter(filepath); } else { - return fs33.statSync(filepath)[options.filter](); + return fs34.statSync(filepath)[options.filter](); } } catch (e) { return false; @@ -138143,7 +138143,7 @@ var require_file2 = __commonJS({ // node_modules/archiver-utils/index.js var require_archiver_utils = __commonJS({ "node_modules/archiver-utils/index.js"(exports2, module2) { - var fs33 = require_graceful_fs(); + var fs34 = require_graceful_fs(); var path30 = require("path"); var isStream2 = require_is_stream(); var lazystream = require_lazystream(); @@ -138192,7 +138192,7 @@ var require_archiver_utils = __commonJS({ }; utils.lazyReadStream = function(filepath) { return new lazystream.Readable(function() { - return fs33.createReadStream(filepath); + return fs34.createReadStream(filepath); }); }; utils.normalizeInputSource = function(source) { @@ -138220,7 +138220,7 @@ var require_archiver_utils = __commonJS({ callback = base; base = dirpath; } - fs33.readdir(dirpath, function(err, list) { + fs34.readdir(dirpath, function(err, list) { var i = 0; var file; var filepath; @@ -138233,7 +138233,7 @@ var require_archiver_utils = __commonJS({ return callback(null, results); } filepath = path30.join(dirpath, file); - fs33.stat(filepath, function(err2, stats) { + fs34.stat(filepath, function(err2, stats) { results.push({ path: filepath, relative: path30.relative(base, filepath).replace(/\\/g, "/"), @@ -138295,7 +138295,7 @@ var require_error3 = __commonJS({ // node_modules/@actions/artifact/node_modules/archiver/lib/core.js var require_core2 = __commonJS({ "node_modules/@actions/artifact/node_modules/archiver/lib/core.js"(exports2, module2) { - var fs33 = require("fs"); + var fs34 = require("fs"); var glob2 = require_readdir_glob(); var async = require_async(); var path30 = require("path"); @@ -138359,7 +138359,7 @@ var require_core2 = __commonJS({ data.sourcePath = filepath; task.data = data; this._entriesCount++; - if (data.stats && data.stats instanceof fs33.Stats) { + if (data.stats && data.stats instanceof fs34.Stats) { task = this._updateQueueTaskWithStats(task, data.stats); if (task) { if (data.stats.size) { @@ -138530,7 +138530,7 @@ var require_core2 = __commonJS({ callback(); return; } - fs33.lstat(task.filepath, function(err, stats) { + fs34.lstat(task.filepath, function(err, stats) { if (this._state.aborted) { setImmediate(callback); return; @@ -138573,7 +138573,7 @@ var require_core2 = __commonJS({ task.data.sourceType = "buffer"; task.source = Buffer.concat([]); } else if (stats.isSymbolicLink() && this._moduleSupports("symlink")) { - var linkPath = fs33.readlinkSync(task.filepath); + var linkPath = fs34.readlinkSync(task.filepath); var dirName = path30.dirname(task.filepath); task.data.type = "symlink"; task.data.linkname = path30.relative(dirName, path30.resolve(dirName, linkPath)); @@ -149475,7 +149475,7 @@ var require_parser_stream = __commonJS({ var require_mkdirp = __commonJS({ "node_modules/mkdirp/index.js"(exports2, module2) { var path30 = require("path"); - var fs33 = require("fs"); + var fs34 = require("fs"); var _0777 = parseInt("0777", 8); module2.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; function mkdirP(p, opts, f, made) { @@ -149486,7 +149486,7 @@ var require_mkdirp = __commonJS({ opts = { mode: opts }; } var mode = opts.mode; - var xfs = opts.fs || fs33; + var xfs = opts.fs || fs34; if (mode === void 0) { mode = _0777; } @@ -149525,7 +149525,7 @@ var require_mkdirp = __commonJS({ opts = { mode: opts }; } var mode = opts.mode; - var xfs = opts.fs || fs33; + var xfs = opts.fs || fs34; if (mode === void 0) { mode = _0777; } @@ -149562,7 +149562,7 @@ var require_mkdirp = __commonJS({ // node_modules/unzip-stream/lib/extract.js var require_extract2 = __commonJS({ "node_modules/unzip-stream/lib/extract.js"(exports2, module2) { - var fs33 = require("fs"); + var fs34 = require("fs"); var path30 = require("path"); var util4 = require("util"); var mkdirp = require_mkdirp(); @@ -149609,7 +149609,7 @@ var require_extract2 = __commonJS({ var directory = entry.isDirectory ? destPath : path30.dirname(destPath); this.unfinishedEntries++; var writeFileFn = function() { - var pipedStream = fs33.createWriteStream(destPath); + var pipedStream = fs34.createWriteStream(destPath); pipedStream.on("close", function() { self2.unfinishedEntries--; self2._notifyAwaiter(); @@ -150807,7 +150807,7 @@ var require_file_command2 = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.prepareKeyValueMessage = exports2.issueFileCommand = void 0; var crypto3 = __importStar2(require("crypto")); - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var os8 = __importStar2(require("os")); var utils_1 = require_utils11(); function issueFileCommand(command, message) { @@ -150815,10 +150815,10 @@ var require_file_command2 = __commonJS({ if (!filePath) { throw new Error(`Unable to find environment variable for file command ${command}`); } - if (!fs33.existsSync(filePath)) { + if (!fs34.existsSync(filePath)) { throw new Error(`Missing file at path: ${filePath}`); } - fs33.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os8.EOL}`, { + fs34.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os8.EOL}`, { encoding: "utf8" }); } @@ -152141,12 +152141,12 @@ var require_io_util2 = __commonJS({ var _a6; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.getCmdPath = exports2.tryGetExecutablePath = exports2.isRooted = exports2.isDirectory = exports2.exists = exports2.READONLY = exports2.UV_FS_O_EXLOCK = exports2.IS_WINDOWS = exports2.unlink = exports2.symlink = exports2.stat = exports2.rmdir = exports2.rm = exports2.rename = exports2.readlink = exports2.readdir = exports2.open = exports2.mkdir = exports2.lstat = exports2.copyFile = exports2.chmod = void 0; - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var path30 = __importStar2(require("path")); - _a6 = fs33.promises, exports2.chmod = _a6.chmod, exports2.copyFile = _a6.copyFile, exports2.lstat = _a6.lstat, exports2.mkdir = _a6.mkdir, exports2.open = _a6.open, exports2.readdir = _a6.readdir, exports2.readlink = _a6.readlink, exports2.rename = _a6.rename, exports2.rm = _a6.rm, exports2.rmdir = _a6.rmdir, exports2.stat = _a6.stat, exports2.symlink = _a6.symlink, exports2.unlink = _a6.unlink; + _a6 = fs34.promises, exports2.chmod = _a6.chmod, exports2.copyFile = _a6.copyFile, exports2.lstat = _a6.lstat, exports2.mkdir = _a6.mkdir, exports2.open = _a6.open, exports2.readdir = _a6.readdir, exports2.readlink = _a6.readlink, exports2.rename = _a6.rename, exports2.rm = _a6.rm, exports2.rmdir = _a6.rmdir, exports2.stat = _a6.stat, exports2.symlink = _a6.symlink, exports2.unlink = _a6.unlink; exports2.IS_WINDOWS = process.platform === "win32"; exports2.UV_FS_O_EXLOCK = 268435456; - exports2.READONLY = fs33.constants.O_RDONLY; + exports2.READONLY = fs34.constants.O_RDONLY; function exists(fsPath) { return __awaiter2(this, void 0, void 0, function* () { try { @@ -153535,25 +153535,25 @@ var require_upload_specification = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.getUploadSpecification = void 0; - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var core_1 = require_core3(); var path_1 = require("path"); var path_and_artifact_name_validation_1 = require_path_and_artifact_name_validation2(); function getUploadSpecification(artifactName, rootDirectory, artifactFiles) { const specifications = []; - if (!fs33.existsSync(rootDirectory)) { + if (!fs34.existsSync(rootDirectory)) { throw new Error(`Provided rootDirectory ${rootDirectory} does not exist`); } - if (!fs33.statSync(rootDirectory).isDirectory()) { + if (!fs34.statSync(rootDirectory).isDirectory()) { throw new Error(`Provided rootDirectory ${rootDirectory} is not a valid directory`); } rootDirectory = (0, path_1.normalize)(rootDirectory); rootDirectory = (0, path_1.resolve)(rootDirectory); for (let file of artifactFiles) { - if (!fs33.existsSync(file)) { + if (!fs34.existsSync(file)) { throw new Error(`File ${file} does not exist`); } - if (!fs33.statSync(file).isDirectory()) { + if (!fs34.statSync(file).isDirectory()) { file = (0, path_1.normalize)(file); file = (0, path_1.resolve)(file); if (!file.startsWith(rootDirectory)) { @@ -153578,11 +153578,11 @@ var require_upload_specification = __commonJS({ // node_modules/tmp/lib/tmp.js var require_tmp = __commonJS({ "node_modules/tmp/lib/tmp.js"(exports2, module2) { - var fs33 = require("fs"); + var fs34 = require("fs"); var os8 = require("os"); var path30 = require("path"); var crypto3 = require("crypto"); - var _c2 = { fs: fs33.constants, os: os8.constants }; + var _c2 = { fs: fs34.constants, os: os8.constants }; var RANDOM_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; var TEMPLATE_PATTERN = /XXXXXX/; var DEFAULT_TRIES = 3; @@ -153594,13 +153594,13 @@ var require_tmp = __commonJS({ var FILE_MODE = 384; var EXIT = "exit"; var _removeObjects = []; - var FN_RMDIR_SYNC = fs33.rmdirSync.bind(fs33); + var FN_RMDIR_SYNC = fs34.rmdirSync.bind(fs34); var _gracefulCleanup = false; function rimraf(dirPath, callback) { - return fs33.rm(dirPath, { recursive: true }, callback); + return fs34.rm(dirPath, { recursive: true }, callback); } function FN_RIMRAF_SYNC(dirPath) { - return fs33.rmSync(dirPath, { recursive: true }); + return fs34.rmSync(dirPath, { recursive: true }); } function tmpName(options, callback) { const args = _parseArguments(options, callback), opts = args[0], cb = args[1]; @@ -153610,7 +153610,7 @@ var require_tmp = __commonJS({ (function _getUniqueName() { try { const name = _generateTmpName(sanitizedOptions); - fs33.stat(name, function(err2) { + fs34.stat(name, function(err2) { if (!err2) { if (tries-- > 0) return _getUniqueName(); return cb(new Error("Could not get a unique tmp filename, max tries reached " + name)); @@ -153630,7 +153630,7 @@ var require_tmp = __commonJS({ do { const name = _generateTmpName(sanitizedOptions); try { - fs33.statSync(name); + fs34.statSync(name); } catch (e) { return name; } @@ -153641,10 +153641,10 @@ var require_tmp = __commonJS({ const args = _parseArguments(options, callback), opts = args[0], cb = args[1]; tmpName(opts, function _tmpNameCreated(err, name) { if (err) return cb(err); - fs33.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) { + fs34.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) { if (err2) return cb(err2); if (opts.discardDescriptor) { - return fs33.close(fd, function _discardCallback(possibleErr) { + return fs34.close(fd, function _discardCallback(possibleErr) { return cb(possibleErr, name, void 0, _prepareTmpFileRemoveCallback(name, -1, opts, false)); }); } else { @@ -153658,9 +153658,9 @@ var require_tmp = __commonJS({ const args = _parseArguments(options), opts = args[0]; const discardOrDetachDescriptor = opts.discardDescriptor || opts.detachDescriptor; const name = tmpNameSync(opts); - let fd = fs33.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE); + let fd = fs34.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE); if (opts.discardDescriptor) { - fs33.closeSync(fd); + fs34.closeSync(fd); fd = void 0; } return { @@ -153673,7 +153673,7 @@ var require_tmp = __commonJS({ const args = _parseArguments(options, callback), opts = args[0], cb = args[1]; tmpName(opts, function _tmpNameCreated(err, name) { if (err) return cb(err); - fs33.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) { + fs34.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) { if (err2) return cb(err2); cb(null, name, _prepareTmpDirRemoveCallback(name, opts, false)); }); @@ -153682,7 +153682,7 @@ var require_tmp = __commonJS({ function dirSync(options) { const args = _parseArguments(options), opts = args[0]; const name = tmpNameSync(opts); - fs33.mkdirSync(name, opts.mode || DIR_MODE); + fs34.mkdirSync(name, opts.mode || DIR_MODE); return { name, removeCallback: _prepareTmpDirRemoveCallback(name, opts, true) @@ -153696,20 +153696,20 @@ var require_tmp = __commonJS({ next(); }; if (0 <= fdPath[0]) - fs33.close(fdPath[0], function() { - fs33.unlink(fdPath[1], _handler); + fs34.close(fdPath[0], function() { + fs34.unlink(fdPath[1], _handler); }); - else fs33.unlink(fdPath[1], _handler); + else fs34.unlink(fdPath[1], _handler); } function _removeFileSync(fdPath) { let rethrownException = null; try { - if (0 <= fdPath[0]) fs33.closeSync(fdPath[0]); + if (0 <= fdPath[0]) fs34.closeSync(fdPath[0]); } catch (e) { if (!_isEBADF(e) && !_isENOENT(e)) throw e; } finally { try { - fs33.unlinkSync(fdPath[1]); + fs34.unlinkSync(fdPath[1]); } catch (e) { if (!_isENOENT(e)) rethrownException = e; } @@ -153725,7 +153725,7 @@ var require_tmp = __commonJS({ return sync ? removeCallbackSync : removeCallback; } function _prepareTmpDirRemoveCallback(name, opts, sync) { - const removeFunction = opts.unsafeCleanup ? rimraf : fs33.rmdir.bind(fs33); + const removeFunction = opts.unsafeCleanup ? rimraf : fs34.rmdir.bind(fs34); const removeFunctionSync = opts.unsafeCleanup ? FN_RIMRAF_SYNC : FN_RMDIR_SYNC; const removeCallbackSync = _prepareRemoveCallback(removeFunctionSync, name, sync); const removeCallback = _prepareRemoveCallback(removeFunction, name, sync, removeCallbackSync); @@ -153788,24 +153788,24 @@ var require_tmp = __commonJS({ } function _resolvePath(name, tmpDir, cb) { const pathToResolve = path30.isAbsolute(name) ? name : path30.join(tmpDir, name); - fs33.stat(pathToResolve, function(err) { + fs34.stat(pathToResolve, function(err) { if (err) { - fs33.realpath(path30.dirname(pathToResolve), function(err2, parentDir) { + fs34.realpath(path30.dirname(pathToResolve), function(err2, parentDir) { if (err2) return cb(err2); cb(null, path30.join(parentDir, path30.basename(pathToResolve))); }); } else { - fs33.realpath(pathToResolve, cb); + fs34.realpath(pathToResolve, cb); } }); } function _resolvePathSync(name, tmpDir) { const pathToResolve = path30.isAbsolute(name) ? name : path30.join(tmpDir, name); try { - fs33.statSync(pathToResolve); - return fs33.realpathSync(pathToResolve); + fs34.statSync(pathToResolve); + return fs34.realpathSync(pathToResolve); } catch (_err) { - const parentDir = fs33.realpathSync(path30.dirname(pathToResolve)); + const parentDir = fs34.realpathSync(path30.dirname(pathToResolve)); return path30.join(parentDir, path30.basename(pathToResolve)); } } @@ -153926,10 +153926,10 @@ var require_tmp = __commonJS({ _gracefulCleanup = true; } function _getTmpDir(options, cb) { - return fs33.realpath(options && options.tmpdir || os8.tmpdir(), cb); + return fs34.realpath(options && options.tmpdir || os8.tmpdir(), cb); } function _getTmpDirSync(options) { - return fs33.realpathSync(options && options.tmpdir || os8.tmpdir()); + return fs34.realpathSync(options && options.tmpdir || os8.tmpdir()); } process.addListener(EXIT, _garbageCollector); Object.defineProperty(module2.exports, "tmpdir", { @@ -154783,10 +154783,10 @@ var require_upload_gzip = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.createGZipFileInBuffer = exports2.createGZipFileOnDisk = void 0; - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var zlib3 = __importStar2(require("zlib")); var util_1 = require("util"); - var stat2 = (0, util_1.promisify)(fs33.stat); + var stat2 = (0, util_1.promisify)(fs34.stat); var gzipExemptFileExtensions = [ ".gz", ".gzip", @@ -154819,9 +154819,9 @@ var require_upload_gzip = __commonJS({ } } return new Promise((resolve15, reject) => { - const inputStream = fs33.createReadStream(originalFilePath); + const inputStream = fs34.createReadStream(originalFilePath); const gzip = zlib3.createGzip(); - const outputStream = fs33.createWriteStream(tempFilePath); + const outputStream = fs34.createWriteStream(tempFilePath); inputStream.pipe(gzip).pipe(outputStream); outputStream.on("finish", () => __awaiter2(this, void 0, void 0, function* () { const size = (yield stat2(tempFilePath)).size; @@ -154839,7 +154839,7 @@ var require_upload_gzip = __commonJS({ return __awaiter2(this, void 0, void 0, function* () { return new Promise((resolve15) => __awaiter2(this, void 0, void 0, function* () { var _a6, e_1, _b2, _c2; - const inputStream = fs33.createReadStream(originalFilePath); + const inputStream = fs34.createReadStream(originalFilePath); const gzip = zlib3.createGzip(); inputStream.pipe(gzip); const chunks = []; @@ -155048,7 +155048,7 @@ var require_upload_http_client = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.UploadHttpClient = void 0; - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var core29 = __importStar2(require_core3()); var tmp2 = __importStar2(require_tmp_promise()); var stream2 = __importStar2(require("stream")); @@ -155062,7 +155062,7 @@ var require_upload_http_client = __commonJS({ var http_manager_1 = require_http_manager(); var upload_gzip_1 = require_upload_gzip(); var requestUtils_1 = require_requestUtils2(); - var stat2 = (0, util_1.promisify)(fs33.stat); + var stat2 = (0, util_1.promisify)(fs34.stat); var UploadHttpClient = class { constructor() { this.uploadHttpManager = new http_manager_1.HttpManager((0, config_variables_1.getUploadFileConcurrency)(), "@actions/artifact-upload"); @@ -155199,7 +155199,7 @@ var require_upload_http_client = __commonJS({ let openUploadStream; if (totalFileSize < buffer.byteLength) { core29.debug(`The gzip file created for ${parameters.file} did not help with reducing the size of the file. The original file will be uploaded as-is`); - openUploadStream = () => fs33.createReadStream(parameters.file); + openUploadStream = () => fs34.createReadStream(parameters.file); isGzip = false; uploadFileSize = totalFileSize; } else { @@ -155245,7 +155245,7 @@ var require_upload_http_client = __commonJS({ failedChunkSizes += chunkSize; continue; } - const result = yield this.uploadChunk(httpClientIndex, parameters.resourceUrl, () => fs33.createReadStream(uploadFilePath, { + const result = yield this.uploadChunk(httpClientIndex, parameters.resourceUrl, () => fs34.createReadStream(uploadFilePath, { start: startChunkIndex, end: endChunkIndex, autoClose: false @@ -155440,7 +155440,7 @@ var require_download_http_client = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.DownloadHttpClient = void 0; - var fs33 = __importStar2(require("fs")); + var fs34 = __importStar2(require("fs")); var core29 = __importStar2(require_core3()); var zlib3 = __importStar2(require("zlib")); var utils_1 = require_utils12(); @@ -155531,7 +155531,7 @@ var require_download_http_client = __commonJS({ return __awaiter2(this, void 0, void 0, function* () { let retryCount = 0; const retryLimit = (0, config_variables_1.getRetryLimit)(); - let destinationStream = fs33.createWriteStream(downloadPath); + let destinationStream = fs34.createWriteStream(downloadPath); const headers = (0, utils_1.getDownloadHeaders)("application/json", true, true); const makeDownloadRequest = () => __awaiter2(this, void 0, void 0, function* () { const client = this.downloadHttpManager.getClient(httpClientIndex); @@ -155573,7 +155573,7 @@ var require_download_http_client = __commonJS({ } }); yield (0, utils_1.rmFile)(fileDownloadPath); - destinationStream = fs33.createWriteStream(fileDownloadPath); + destinationStream = fs34.createWriteStream(fileDownloadPath); }); while (retryCount <= retryLimit) { let response; @@ -173779,7 +173779,7 @@ __export(entry_points_exports, { module.exports = __toCommonJS(entry_points_exports); // src/analyze-action.ts -var fs24 = __toESM(require("fs")); +var fs25 = __toESM(require("fs")); var import_path5 = __toESM(require("path")); var import_perf_hooks6 = require("perf_hooks"); var core14 = __toESM(require_core()); @@ -173942,21 +173942,21 @@ async function getFolderSize(itemPath, options) { getFolderSize.loose = async (itemPath, options) => await core2(itemPath, options); getFolderSize.strict = async (itemPath, options) => await core2(itemPath, options, { strict: true }); async function core2(rootItemPath, options = {}, returnType = {}) { - const fs33 = options.fs || await import("node:fs/promises"); + const fs34 = options.fs || await import("node:fs/promises"); let folderSize = 0n; const foundInos = /* @__PURE__ */ new Set(); const errors = []; await processItem(rootItemPath); async function processItem(itemPath) { if (options.ignore?.test(itemPath)) return; - const stats = returnType.strict ? await fs33.lstat(itemPath, { bigint: true }) : await fs33.lstat(itemPath, { bigint: true }).catch((error3) => errors.push(error3)); + const stats = returnType.strict ? await fs34.lstat(itemPath, { bigint: true }) : await fs34.lstat(itemPath, { bigint: true }).catch((error3) => errors.push(error3)); if (typeof stats !== "object") return; if (!foundInos.has(stats.ino)) { foundInos.add(stats.ino); folderSize += stats.size; } if (stats.isDirectory()) { - const directoryItems = returnType.strict ? await fs33.readdir(itemPath) : await fs33.readdir(itemPath).catch((error3) => errors.push(error3)); + const directoryItems = returnType.strict ? await fs34.readdir(itemPath) : await fs34.readdir(itemPath).catch((error3) => errors.push(error3)); if (typeof directoryItems !== "object") return; await Promise.all( directoryItems.map( @@ -180438,13 +180438,13 @@ var SarifScanOrder = [ ]; // src/analyze.ts -var fs18 = __toESM(require("fs")); +var fs19 = __toESM(require("fs")); var path16 = __toESM(require("path")); var import_perf_hooks5 = require("perf_hooks"); var io5 = __toESM(require_io()); // src/codeql.ts -var fs17 = __toESM(require("fs")); +var fs18 = __toESM(require("fs")); var path15 = __toESM(require("path")); var core12 = __toESM(require_core()); var toolrunner3 = __toESM(require_toolrunner()); @@ -183079,7 +183079,7 @@ async function logGeneratedFilesTelemetry(config, duration, generatedFilesCount) } // src/setup-codeql.ts -var fs15 = __toESM(require("fs")); +var fs16 = __toESM(require("fs")); var path13 = __toESM(require("path")); var import_perf_hooks4 = require("perf_hooks"); var toolcache3 = __toESM(require_tool_cache()); @@ -183415,6 +183415,7 @@ async function getCodeQlVersionsForOverlayBaseDatabases(rawLanguages, logger2) { var semver7 = __toESM(require_semver2()); // src/platform.ts +var import_fs = __toESM(require("fs")); var semver6 = __toESM(require_semver2()); function getBundlePlatform(platform2 = process.platform, arch2 = process.arch) { switch (platform2) { @@ -183438,6 +183439,47 @@ function macOSVersion(action) { } return version; } +var XCODE_SELECT_LINK_PATH = "/private/var/db/xcode_select_link"; +var XCODE_APP_FILENAME_PATTERN = new RegExp( + /(?Xcode_(?\d+.\d+).app)/ +); +function xcodeVersion(logger2) { + try { + const stats = import_fs.default.statSync(XCODE_SELECT_LINK_PATH); + if (!stats.isSymbolicLink()) { + logger2.warning( + `${XCODE_SELECT_LINK_PATH} exists, but is not a symbolic link.` + ); + return void 0; + } + const xcodePath = import_fs.default.readlinkSync(XCODE_SELECT_LINK_PATH); + if (xcodePath === "") { + logger2.warning( + `Resolving ${XCODE_SELECT_LINK_PATH} unexpectedly returned nothing.` + ); + return void 0; + } + const matchResult = xcodePath.match(XCODE_APP_FILENAME_PATTERN); + if (matchResult?.groups === void 0) { + logger2.warning( + `Xcode path '${xcodePath}' does not contain expected pattern.` + ); + return void 0; + } + const majorMinor = matchResult.groups["majorMinor"]; + const version = semver6.coerce(majorMinor); + if (version === null) { + logger2.warning(`Couldn't parse '${majorMinor}' as a semantic version.`); + return void 0; + } + return version; + } catch (err) { + logger2.warning( + `Unable to determine Xcode version: ${getErrorMessage(err)}` + ); + return void 0; + } +} // src/per-language-bundles.ts var MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION = "2.27.1"; @@ -183618,7 +183660,7 @@ async function getCodeQLAssetDownloadURL(action, apiDetails, tagName, assetName, // src/tar.ts var import_child_process = require("child_process"); -var fs13 = __toESM(require("fs")); +var fs14 = __toESM(require("fs")); var stream = __toESM(require("stream")); var import_toolrunner = __toESM(require_toolrunner()); var io4 = __toESM(require_io()); @@ -183691,7 +183733,7 @@ async function isZstdAvailable(logger2) { } } async function extract(tarPath, dest, compressionMethod, tarVersion, logger2) { - fs13.mkdirSync(dest, { recursive: true }); + fs14.mkdirSync(dest, { recursive: true }); switch (compressionMethod) { case "gzip": return await toolcache.extractTar(tarPath, dest); @@ -183777,7 +183819,7 @@ function inferCompressionMethod(tarPath) { } // src/tools-download.ts -var fs14 = __toESM(require("fs")); +var fs15 = __toESM(require("fs")); var os5 = __toESM(require("os")); var path12 = __toESM(require("path")); var import_perf_hooks3 = require("perf_hooks"); @@ -183863,7 +183905,7 @@ async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorizat }; } async function downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorization, headers, tarVersion, logger2) { - fs14.mkdirSync(dest, { recursive: true }); + fs15.mkdirSync(dest, { recursive: true }); const agent = new import_http_client.HttpClient().getAgent(codeqlURL); headers = Object.assign( { "User-Agent": "CodeQL Action" }, @@ -183922,7 +183964,7 @@ function getToolcacheDirectory(version) { } function isToolcacheOnWorkspaceFilesystem(logger2) { try { - return fs14.statSync(getRequiredEnvParam("RUNNER_TOOL_CACHE")).dev === fs14.statSync(getRequiredEnvParam("GITHUB_WORKSPACE")).dev; + return fs15.statSync(getRequiredEnvParam("RUNNER_TOOL_CACHE")).dev === fs15.statSync(getRequiredEnvParam("GITHUB_WORKSPACE")).dev; } catch (e) { logger2.debug( `Could not determine whether the toolcache is on the same filesystem as the workspace: ${getErrorMessage(e)}` @@ -183944,7 +183986,7 @@ async function deleteToolcacheBundles({ return { deletedVersions: [], failed: true }; } try { - if ((await fs14.promises.lstat(toolDirectory)).isSymbolicLink()) { + if ((await fs15.promises.lstat(toolDirectory)).isSymbolicLink()) { logger2.info( `Not deleting the CodeQL tools from the toolcache since '${toolDirectory}' is a symlink.` ); @@ -183963,7 +184005,7 @@ async function deleteToolcacheBundles({ return { deletedVersions: [], failed: true }; } try { - const entries = await fs14.promises.readdir(toolDirectory, { + const entries = await fs15.promises.readdir(toolDirectory, { withFileTypes: true }); const deletedVersions = []; @@ -183977,7 +184019,7 @@ async function deleteToolcacheBundles({ } const versionDirectory = path12.join(toolDirectory, entry.name); try { - await fs14.promises.rm(versionDirectory, { + await fs15.promises.rm(versionDirectory, { force: true, recursive: true }); @@ -184002,7 +184044,7 @@ async function deleteToolcacheBundles({ } function writeToolcacheMarkerFile(extractedPath, logger2) { const markerFilePath = `${extractedPath}.complete`; - fs14.writeFileSync(markerFilePath, ""); + fs15.writeFileSync(markerFilePath, ""); logger2.info(`Created toolcache marker file ${markerFilePath}`); } @@ -184054,7 +184096,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger2) { const candidates = toolcache3.findAllVersions("CodeQL").filter(isGoodVersion).map((version) => ({ folder: toolcache3.find("CodeQL", version), version - })).filter(({ folder }) => fs15.existsSync(path13.join(folder, "pinned-version"))); + })).filter(({ folder }) => fs16.existsSync(path13.join(folder, "pinned-version"))); if (candidates.length === 1) { const candidate = candidates[0]; logger2.debug( @@ -184676,7 +184718,7 @@ function isReservedToolsValue(tools) { } // src/tracer-config.ts -var fs16 = __toESM(require("fs")); +var fs17 = __toESM(require("fs")); var path14 = __toESM(require("path")); async function shouldEnableIndirectTracing(codeql, config) { if (config.buildMode === "none" /* None */) { @@ -184696,14 +184738,14 @@ async function endTracingForCluster(codeql, config, logger2) { config.dbLocation, "temp/tracingEnvironment/end-tracing.json" ); - if (!fs16.existsSync(envVariablesFile)) { + if (!fs17.existsSync(envVariablesFile)) { throw new Error( `Environment file for ending tracing not found: ${envVariablesFile}` ); } try { const endTracingEnvVariables = JSON.parse( - fs16.readFileSync(envVariablesFile, "utf8") + fs17.readFileSync(envVariablesFile, "utf8") ); for (const [key, value] of Object.entries(endTracingEnvVariables)) { if (value !== null) { @@ -184724,7 +184766,7 @@ async function getTracerConfigForCluster(logger2, config) { "temp/tracingEnvironment/start-tracing.json" ); try { - const tracingEnvVariables = JSON.parse(fs16.readFileSync(filePath, "utf8")); + const tracingEnvVariables = JSON.parse(fs17.readFileSync(filePath, "utf8")); return { env: tracingEnvVariables }; @@ -184847,7 +184889,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { "tools", "tracing-config.lua" ); - return fs17.existsSync(tracingConfigPath); + return fs18.existsSync(tracingConfigPath); }, async isScannedLanguage(language) { return !await this.isTracedLanguage(language); @@ -185143,7 +185185,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { }, async diagnosticsExport(sarifFile, automationDetailsId, config, diagnosticDir) { let configPath = getGeneratedCodeScanningConfigPath(config); - if (!fs17.existsSync(configPath)) { + if (!fs18.existsSync(configPath)) { if (config.successfullyInitialised) { logger2.warning( [ @@ -185331,7 +185373,7 @@ async function writeCodeScanningConfigFile(config, logger2) { logger2.startGroup("Augmented user configuration file contents"); logger2.info(dump(augmentedConfig)); logger2.endGroup(); - fs17.writeFileSync(codeScanningConfigFile, dump(augmentedConfig)); + fs18.writeFileSync(codeScanningConfigFile, dump(augmentedConfig)); return codeScanningConfigFile; } var TRAP_CACHE_SIZE_MB = 1024; @@ -185827,7 +185869,7 @@ function dbIsFinalized(config, language, logger2) { const dbPath = getCodeQLDatabasePath(config, language); try { const dbInfo = load( - fs18.readFileSync(path16.resolve(dbPath, "codeql-database.yml"), "utf8") + fs19.readFileSync(path16.resolve(dbPath, "codeql-database.yml"), "utf8") ); return !("inProgress" in dbInfo); } catch { @@ -185911,8 +185953,8 @@ function writeDiffRangeDataExtensionPack(logger2, ranges, checkoutPath) { ranges = [{ path: "", startLine: 0, endLine: 0 }]; } const diffRangeDir = path16.join(getTemporaryDirectory(), "pr-diff-range"); - fs18.mkdirSync(diffRangeDir, { recursive: true }); - fs18.writeFileSync( + fs19.mkdirSync(diffRangeDir, { recursive: true }); + fs19.writeFileSync( path16.join(diffRangeDir, "qlpack.yml"), ` name: codeql-action/pr-diff-range @@ -185929,7 +185971,7 @@ dataExtensions: checkoutPath ); const extensionFilePath = path16.join(diffRangeDir, "pr-diff-range.yml"); - fs18.writeFileSync(extensionFilePath, extensionContents); + fs19.writeFileSync(extensionFilePath, extensionContents); logger2.debug( `Wrote pr-diff-range extension pack to ${extensionFilePath}: ${extensionContents}` @@ -186074,7 +186116,7 @@ async function runQueries(sarifFolder, memoryFlag, threadsFlag, diffRangePackDir } function getPerQueryAlertCounts(sarifPath) { const sarifObject = JSON.parse( - fs18.readFileSync(sarifPath, "utf8") + fs19.readFileSync(sarifPath, "utf8") ); const perQueryAlertCounts = {}; for (const sarifRun of sarifObject.runs) { @@ -186092,13 +186134,13 @@ async function runQueries(sarifFolder, memoryFlag, threadsFlag, diffRangePackDir } async function runFinalize(features, outputDir, threadsFlag, memoryFlag, codeql, config, logger2) { try { - await fs18.promises.rm(outputDir, { force: true, recursive: true }); + await fs19.promises.rm(outputDir, { force: true, recursive: true }); } catch (error3) { if (error3?.code !== "ENOENT") { throw error3; } } - await fs18.promises.mkdir(outputDir, { recursive: true }); + await fs19.promises.mkdir(outputDir, { recursive: true }); const timings = await finalizeDatabaseCreation( codeql, features, @@ -186142,7 +186184,7 @@ async function warnIfGoInstalledAfterInit(config, logger2) { } // src/database-upload.ts -var fs19 = __toESM(require("fs")); +var fs20 = __toESM(require("fs")); async function cleanupAndUploadDatabases(action, repositoryNwo, codeql, config, apiDetails, checkoutPath) { const logger2 = action.logger; if (getRequiredInput("upload-database") !== "true") { @@ -186179,7 +186221,7 @@ async function cleanupAndUploadDatabases(action, repositoryNwo, codeql, config, const bundledDb = await bundleDb(config, language, codeql, language, { includeDiagnostics: false }); - bundledDbSize = fs19.statSync(bundledDb).size; + bundledDbSize = fs20.statSync(bundledDb).size; const commitOid = await getCommitOid(action.env, checkoutPath); const maxAttempts = 4; let uploadDurationMs; @@ -186257,7 +186299,7 @@ async function recordClearCleanupSizes(codeql, config, reports, logger2) { const bundledDb = await bundleDb(config, language, codeql, language, { includeDiagnostics: false }); - report.clear_cleanup_zipped_size_bytes = fs19.statSync(bundledDb).size; + report.clear_cleanup_zipped_size_bytes = fs20.statSync(bundledDb).size; logger2.debug( `Database for ${language} is ${report.clear_cleanup_zipped_size_bytes} bytes zipped at the '${"clear" /* Clear */}' cleanup level (vs. ${report.zipped_upload_size_bytes ?? "unknown"} bytes at the '${"overlay" /* Overlay */}' level).` ); @@ -186280,7 +186322,7 @@ async function uploadBundledDatabase(repositoryNwo, language, commitOid, bundled if (uploadsBaseUrl.endsWith("/")) { uploadsBaseUrl = uploadsBaseUrl.slice(0, -1); } - const bundledDbReadStream = fs19.createReadStream(bundledDb); + const bundledDbReadStream = fs20.createReadStream(bundledDb); try { const startTime = performance.now(); await client.request( @@ -186332,7 +186374,7 @@ __export(upload_lib_exports, { waitForProcessing: () => waitForProcessing, writePostProcessedFiles: () => writePostProcessedFiles }); -var fs23 = __toESM(require("fs")); +var fs24 = __toESM(require("fs")); var path19 = __toESM(require("path")); var url = __toESM(require("url")); var import_zlib = __toESM(require("zlib")); @@ -186340,7 +186382,7 @@ var core13 = __toESM(require_core()); var jsonschema2 = __toESM(require_lib2()); // src/fingerprints.ts -var fs20 = __toESM(require("fs")); +var fs21 = __toESM(require("fs")); var import_path4 = __toESM(require("path")); // node_modules/long/index.js @@ -187328,7 +187370,7 @@ async function hash(callback, filepath) { } updateHash(current); }; - const readStream = fs20.createReadStream(filepath, "utf8"); + const readStream = fs21.createReadStream(filepath, "utf8"); for await (const data of readStream) { for (let i = 0; i < data.length; ++i) { processCharacter(data.charCodeAt(i)); @@ -187403,11 +187445,11 @@ function resolveUriToFile(location, artifacts, sourceRoot, logger2) { if (!import_path4.default.isAbsolute(uri)) { uri = srcRootPrefix + uri; } - if (!fs20.existsSync(uri)) { + if (!fs21.existsSync(uri)) { logger2.debug(`Unable to compute fingerprint for non-existent file: ${uri}`); return void 0; } - if (fs20.statSync(uri).isDirectory()) { + if (fs21.statSync(uri).isDirectory()) { logger2.debug(`Unable to compute fingerprint for directory: ${uri}`); return void 0; } @@ -187462,7 +187504,7 @@ async function addFingerprints(sarifLog, sourceRoot, logger2) { } // src/init.ts -var fs21 = __toESM(require("fs")); +var fs22 = __toESM(require("fs")); var path18 = __toESM(require("path")); var toolrunner4 = __toESM(require_toolrunner()); var github3 = __toESM(require_github()); @@ -187497,7 +187539,7 @@ async function initConfig2(actionState, inputs) { }); } async function runDatabaseInitCluster(databaseInitEnvironment, codeql, config, sourceRoot, processName, qlconfigFile) { - fs21.mkdirSync(config.dbLocation, { recursive: true }); + fs22.mkdirSync(config.dbLocation, { recursive: true }); await wrapEnvironment( databaseInitEnvironment, async () => await codeql.databaseInitCluster( @@ -187532,24 +187574,24 @@ async function checkPacksForOverlayCompatibility(codeql, config, logger2) { function checkPackForOverlayCompatibility(packDir, codeQlOverlayVersion, logger2) { try { let qlpackPath = path18.join(packDir, "qlpack.yml"); - if (!fs21.existsSync(qlpackPath)) { + if (!fs22.existsSync(qlpackPath)) { qlpackPath = path18.join(packDir, "codeql-pack.yml"); } const qlpackContents = load( - fs21.readFileSync(qlpackPath, "utf8") + fs22.readFileSync(qlpackPath, "utf8") ); if (!qlpackContents.buildMetadata) { return true; } const packInfoPath = path18.join(packDir, ".packinfo"); - if (!fs21.existsSync(packInfoPath)) { + if (!fs22.existsSync(packInfoPath)) { logger2.warning( `The query pack at ${packDir} does not have a .packinfo file, so it cannot support overlay analysis. Recompiling the query pack with the latest CodeQL CLI should solve this problem.` ); return false; } const packInfoFileContents = JSON.parse( - fs21.readFileSync(packInfoPath, "utf8") + fs22.readFileSync(packInfoPath, "utf8") ); const packOverlayVersion = packInfoFileContents.overlayVersion; if (typeof packOverlayVersion !== "number") { @@ -187584,8 +187626,8 @@ async function checkInstallPython311(languages, codeql) { ]).exec(); } } -function cleanupDatabaseClusterDirectory(config, logger2, options = {}, rmSync5 = fs21.rmSync) { - if (fs21.existsSync(config.dbLocation) && (fs21.statSync(config.dbLocation).isFile() || fs21.readdirSync(config.dbLocation).length > 0)) { +function cleanupDatabaseClusterDirectory(config, logger2, options = {}, rmSync5 = fs22.rmSync) { + if (fs22.existsSync(config.dbLocation) && (fs22.statSync(config.dbLocation).isFile() || fs22.readdirSync(config.dbLocation).length > 0)) { if (!options.disableExistingDirectoryWarning) { logger2.warning( `The database cluster directory ${config.dbLocation} must be empty. Attempting to clean it up.` @@ -187690,7 +187732,7 @@ To opt out of this change, ${envVarOptOut}`; } // src/sarif/index.ts -var fs22 = __toESM(require("fs")); +var fs23 = __toESM(require("fs")); var InvalidSarifUploadError = class extends Error { }; function getToolNames(sarifFile) { @@ -187706,7 +187748,7 @@ function getToolNames(sarifFile) { } function readSarifFile(sarifFilePath) { try { - return JSON.parse(fs22.readFileSync(sarifFilePath, "utf8")); + return JSON.parse(fs23.readFileSync(sarifFilePath, "utf8")); } catch (err) { throw new Error( `Parsing SARIF file at '${sarifFilePath}' failed: ${getErrorMessage(err)}` @@ -187847,8 +187889,8 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo codeQL = initCodeQLResult.codeql; } const baseTempDir = path19.resolve(tempDir, "combined-sarif"); - fs23.mkdirSync(baseTempDir, { recursive: true }); - const outputDirectory = fs23.mkdtempSync(path19.resolve(baseTempDir, "output-")); + fs24.mkdirSync(baseTempDir, { recursive: true }); + const outputDirectory = fs24.mkdtempSync(path19.resolve(baseTempDir, "output-")); const outputFile = path19.resolve(outputDirectory, "combined-sarif.sarif"); await codeQL.mergeResults(sarifFiles, outputFile, { mergeRunsFromEqualCategory: true @@ -187893,7 +187935,7 @@ async function uploadPayload(payload, repositoryNwo, logger2, analysis) { `SARIF upload disabled by an environment variable. Saving to ${payloadSaveFile}` ); logger2.info(`Payload: ${JSON.stringify(payload, null, 2)}`); - fs23.writeFileSync(payloadSaveFile, JSON.stringify(payload, null, 2)); + fs24.writeFileSync(payloadSaveFile, JSON.stringify(payload, null, 2)); return "dummy-sarif-id"; } const client = getApiClient(); @@ -187927,7 +187969,7 @@ async function uploadPayload(payload, repositoryNwo, logger2, analysis) { function findSarifFilesInDir(sarifPath, isSarif) { const sarifFiles = []; const walkSarifFiles = (dir) => { - const entries = fs23.readdirSync(dir, { withFileTypes: true }); + const entries = fs24.readdirSync(dir, { withFileTypes: true }); for (const entry of entries) { if (entry.isFile() && isSarif(entry.name)) { sarifFiles.push(path19.resolve(dir, entry.name)); @@ -187940,11 +187982,11 @@ function findSarifFilesInDir(sarifPath, isSarif) { return sarifFiles; } function getSarifFilePaths(sarifPath, isSarif) { - if (!fs23.existsSync(sarifPath)) { + if (!fs24.existsSync(sarifPath)) { throw new ConfigurationError(`Path does not exist: ${sarifPath}`); } let sarifFiles; - if (fs23.lstatSync(sarifPath).isDirectory()) { + if (fs24.lstatSync(sarifPath).isDirectory()) { sarifFiles = findSarifFilesInDir(sarifPath, isSarif); if (sarifFiles.length === 0) { throw new ConfigurationError( @@ -187957,7 +187999,7 @@ function getSarifFilePaths(sarifPath, isSarif) { return sarifFiles; } async function getGroupedSarifFilePaths(logger2, sarifPath) { - const stats = fs23.statSync(sarifPath, { throwIfNoEntry: false }); + const stats = fs24.statSync(sarifPath, { throwIfNoEntry: false }); if (stats === void 0) { throw new ConfigurationError(`Path does not exist: ${sarifPath}`); } @@ -188092,7 +188134,7 @@ function buildPayload(commitOid, ref, analysisKey, analysisName, zippedSarif, wo payloadObj.base_sha = mergeBaseCommitOid; } else if (process.env.GITHUB_EVENT_PATH) { const githubEvent = JSON.parse( - fs23.readFileSync(process.env.GITHUB_EVENT_PATH, "utf8") + fs24.readFileSync(process.env.GITHUB_EVENT_PATH, "utf8") ); payloadObj.base_ref = `refs/heads/${githubEvent.pull_request.base.ref}`; payloadObj.base_sha = githubEvent.pull_request.base.sha; @@ -188230,9 +188272,9 @@ async function uploadPostProcessedFiles(logger2, checkoutPath, uploadTarget, pos }; } function dumpSarifFile(sarifPayload, outputDir, logger2, uploadTarget) { - if (!fs23.existsSync(outputDir)) { - fs23.mkdirSync(outputDir, { recursive: true }); - } else if (!fs23.lstatSync(outputDir).isDirectory()) { + if (!fs24.existsSync(outputDir)) { + fs24.mkdirSync(outputDir, { recursive: true }); + } else if (!fs24.lstatSync(outputDir).isDirectory()) { throw new ConfigurationError( `The path that processed SARIF files should be written to exists, but is not a directory: ${outputDir}` ); @@ -188242,7 +188284,7 @@ function dumpSarifFile(sarifPayload, outputDir, logger2, uploadTarget) { `upload${uploadTarget.sarifExtension}` ); logger2.info(`Writing processed SARIF file to ${outputFile}`); - fs23.writeFileSync(outputFile, sarifPayload); + fs24.writeFileSync(outputFile, sarifPayload); } var STATUS_CHECK_INITIAL_BACKOFF_MILLISECONDS = 5 * 1e3; var STATUS_CHECK_BACKOFF_MULTIPLIER = 2; @@ -188488,7 +188530,7 @@ function doesGoExtractionOutputExist(config) { "trap", "go" /* go */ ); - return fs24.existsSync(trapDirectory) && fs24.readdirSync(trapDirectory).some( + return fs25.existsSync(trapDirectory) && fs25.readdirSync(trapDirectory).some( (fileName) => [ ".trap", ".trap.gz", @@ -188784,18 +188826,18 @@ async function runWrapper() { } // src/analyze-action-post.ts -var fs28 = __toESM(require("fs")); +var fs29 = __toESM(require("fs")); var core16 = __toESM(require_core()); // src/debug-artifacts.ts -var fs27 = __toESM(require("fs")); +var fs28 = __toESM(require("fs")); var path23 = __toESM(require("path")); var artifact = __toESM(require_artifact2()); var artifactLegacy = __toESM(require_artifact_client2()); var core15 = __toESM(require_core()); // node_modules/archiver/lib/core.js -var import_fs = require("fs"); +var import_fs2 = require("fs"); // node_modules/is-stream/index.js function isStream(stream2, { checkOpen = true } = {}) { @@ -188803,7 +188845,7 @@ function isStream(stream2, { checkOpen = true } = {}) { } // node_modules/readdir-glob/dist/index.mjs -var fs25 = __toESM(require("fs"), 1); +var fs26 = __toESM(require("fs"), 1); var import_events = require("events"); // node_modules/readdir-glob/node_modules/balanced-match/dist/esm/index.js @@ -190680,7 +190722,7 @@ minimatch.unescape = unescape2; var import_path6 = require("path"); function readdir2(dir, strict) { return new Promise((resolve$1, reject) => { - fs25.readdir(dir, { withFileTypes: true }, (err, files) => { + fs26.readdir(dir, { withFileTypes: true }, (err, files) => { if (err) switch (err.code) { case "ENOTDIR": if (strict) reject(err); @@ -190703,7 +190745,7 @@ function readdir2(dir, strict) { } function getStat(file, followSymlinks) { return new Promise((resolve$1) => { - const statFunc = followSymlinks ? fs25.stat : fs25.lstat; + const statFunc = followSymlinks ? fs26.stat : fs26.lstat; statFunc(file, (err, stats) => { if (err) switch (err.code) { case "ENOENT": @@ -190873,7 +190915,7 @@ var import_async = __toESM(require_async(), 1); var import_path7 = require("path"); // node_modules/archiver/lib/error.js -var import_util37 = __toESM(require("util"), 1); +var import_util38 = __toESM(require("util"), 1); var ERROR_CODES = { ABORTED: "archive was aborted", DIRECTORYDIRPATHREQUIRED: "diretory dirpath argument must be a non-empty string value", @@ -190898,7 +190940,7 @@ function ArchiverError(code, data) { this.code = code; this.data = data; } -import_util37.default.inherits(ArchiverError, Error); +import_util38.default.inherits(ArchiverError, Error); // node_modules/archiver/lib/core.js var import_readable_stream2 = __toESM(require_ours(), 1); @@ -191011,7 +191053,7 @@ var Archiver = class extends import_readable_stream2.Transform { data.sourcePath = filepath; task.data = data; this._entriesCount++; - if (data.stats && data.stats instanceof import_fs.Stats) { + if (data.stats && data.stats instanceof import_fs2.Stats) { task = this._updateQueueTaskWithStats(task, data.stats); if (task) { if (data.stats.size) { @@ -191259,7 +191301,7 @@ var Archiver = class extends import_readable_stream2.Transform { callback(); return; } - (0, import_fs.lstat)( + (0, import_fs2.lstat)( task.filepath, function(err, stats) { if (this._state.aborted) { @@ -191321,7 +191363,7 @@ var Archiver = class extends import_readable_stream2.Transform { task.data.type = "file"; task.data.sourceType = "stream"; task.source = new import_lazystream.Readable(function() { - return (0, import_fs.createReadStream)(task.filepath); + return (0, import_fs2.createReadStream)(task.filepath); }); } else if (stats.isDirectory() && this._supportsDirectory) { task.data.name = trailingSlashIt(task.data.name); @@ -191330,7 +191372,7 @@ var Archiver = class extends import_readable_stream2.Transform { task.data.sourceType = "buffer"; task.source = Buffer.concat([]); } else if (stats.isSymbolicLink() && this._supportsSymlink) { - const linkPath = (0, import_fs.readlinkSync)(task.filepath); + const linkPath = (0, import_fs2.readlinkSync)(task.filepath); const dirName = (0, import_path7.dirname)(task.filepath); task.data.type = "symlink"; task.data.linkname = (0, import_path7.relative)( @@ -193173,7 +193215,7 @@ var ZipArchive = class extends Archiver { }; // src/artifact-scanner.ts -var fs26 = __toESM(require("fs")); +var fs27 = __toESM(require("fs")); var os7 = __toESM(require("os")); var path22 = __toESM(require("path")); var exec = __toESM(require_exec()); @@ -193220,7 +193262,7 @@ function isAuthToken(value, patterns = GITHUB_TOKEN_PATTERNS) { function scanFileForTokens(filePath, relativePath2, logger2) { const findings = []; try { - const content = fs26.readFileSync(filePath, "utf8"); + const content = fs27.readFileSync(filePath, "utf8"); for (const { type, pattern } of GITHUB_TOKEN_PATTERNS) { const matches = content.match(pattern); if (matches) { @@ -193253,7 +193295,7 @@ async function scanArchiveFile(archivePath, relativeArchivePath, extractDir, log findings: [] }; try { - const tempExtractDir = fs26.mkdtempSync( + const tempExtractDir = fs27.mkdtempSync( path22.join(extractDir, `extract-${depth}-`) ); const fileName = path22.basename(archivePath).toLowerCase(); @@ -193287,7 +193329,7 @@ async function scanArchiveFile(archivePath, relativeArchivePath, extractDir, log path22.basename(archivePath, ".gz") ); await exec.exec("gunzip", ["-c", archivePath], { - outStream: fs26.createWriteStream(outputFile), + outStream: fs27.createWriteStream(outputFile), silent: true }); } else if (fileName.endsWith(".zip")) { @@ -193308,7 +193350,7 @@ async function scanArchiveFile(archivePath, relativeArchivePath, extractDir, log ); result.scannedFiles += scanResult.scannedFiles; result.findings.push(...scanResult.findings); - fs26.rmSync(tempExtractDir, { recursive: true, force: true }); + fs27.rmSync(tempExtractDir, { recursive: true, force: true }); } catch (e) { logger2.debug( `Could not extract or scan archive file ${archivePath}: ${getErrorMessage(e)}` @@ -193343,7 +193385,7 @@ async function scanDirectory(dirPath, baseRelativePath, logger2, depth = 0) { scannedFiles: 0, findings: [] }; - const entries = fs26.readdirSync(dirPath, { withFileTypes: true }); + const entries = fs27.readdirSync(dirPath, { withFileTypes: true }); for (const entry of entries) { const fullPath = path22.join(dirPath, entry.name); const relativePath2 = path22.join(baseRelativePath, entry.name); @@ -193378,10 +193420,10 @@ async function scanArtifactsForTokens(filesToScan, logger2) { scannedFiles: 0, findings: [] }; - const tempScanDir = fs26.mkdtempSync(path22.join(os7.tmpdir(), "artifact-scan-")); + const tempScanDir = fs27.mkdtempSync(path22.join(os7.tmpdir(), "artifact-scan-")); try { for (const filePath of filesToScan) { - const stats = fs26.statSync(filePath); + const stats = fs27.statSync(filePath); const fileName = path22.basename(filePath); if (stats.isDirectory()) { const dirResult = await scanDirectory(filePath, fileName, logger2); @@ -193419,7 +193461,7 @@ async function scanArtifactsForTokens(filesToScan, logger2) { } } finally { try { - fs26.rmSync(tempScanDir, { recursive: true, force: true }); + fs27.rmSync(tempScanDir, { recursive: true, force: true }); } catch (e) { logger2.debug( `Could not clean up temporary scan directory: ${getErrorMessage(e)}` @@ -193441,10 +193483,10 @@ async function uploadCombinedSarifArtifacts(logger2, gitHubVariant) { ); const baseTempDir = path23.resolve(tempDir, "combined-sarif"); const toUpload = []; - if (fs27.existsSync(baseTempDir)) { - const outputDirs = fs27.readdirSync(baseTempDir); + if (fs28.existsSync(baseTempDir)) { + const outputDirs = fs28.readdirSync(baseTempDir); for (const outputDir of outputDirs) { - const sarifFiles = fs27.readdirSync(path23.resolve(baseTempDir, outputDir)).filter((f) => path23.extname(f) === ".sarif"); + const sarifFiles = fs28.readdirSync(path23.resolve(baseTempDir, outputDir)).filter((f) => path23.extname(f) === ".sarif"); for (const sarifFile of sarifFiles) { toUpload.push(path23.resolve(baseTempDir, outputDir, sarifFile)); } @@ -193471,17 +193513,17 @@ async function uploadCombinedSarifArtifacts(logger2, gitHubVariant) { function tryPrepareSarifDebugArtifact(config, language, logger2) { try { const analyzeActionOutputDir = process.env["CODEQL_ACTION_SARIF_RESULTS_OUTPUT_DIR" /* SARIF_RESULTS_OUTPUT_DIR */]; - if (analyzeActionOutputDir !== void 0 && fs27.existsSync(analyzeActionOutputDir) && fs27.lstatSync(analyzeActionOutputDir).isDirectory()) { + if (analyzeActionOutputDir !== void 0 && fs28.existsSync(analyzeActionOutputDir) && fs28.lstatSync(analyzeActionOutputDir).isDirectory()) { const sarifFile = path23.resolve( analyzeActionOutputDir, `${language}.sarif` ); - if (fs27.existsSync(sarifFile)) { + if (fs28.existsSync(sarifFile)) { const sarifInDbLocation = path23.resolve( config.dbLocation, `${language}.sarif` ); - fs27.copyFileSync(sarifFile, sarifInDbLocation); + fs28.copyFileSync(sarifFile, sarifInDbLocation); return sarifInDbLocation; } } @@ -193649,10 +193691,10 @@ async function createPartialDatabaseBundle(config, language) { core15.info( `${config.debugDatabaseName}-${language} is not finalized. Uploading partial database bundle at ${databaseBundlePath}...` ); - if (fs27.existsSync(databaseBundlePath)) { - await fs27.promises.rm(databaseBundlePath, { force: true }); + if (fs28.existsSync(databaseBundlePath)) { + await fs28.promises.rm(databaseBundlePath, { force: true }); } - const output = fs27.createWriteStream(databaseBundlePath); + const output = fs28.createWriteStream(databaseBundlePath); const zip = new ZipArchive(); zip.on("error", (err) => { throw err; @@ -193702,9 +193744,9 @@ async function runWrapper2() { getCsharpTempDependencyDir() ]; for (const tempDependencyDir of tempDependencyDirs) { - if (fs28.existsSync(tempDependencyDir)) { + if (fs29.existsSync(tempDependencyDir)) { try { - fs28.rmSync(tempDependencyDir, { recursive: true }); + fs29.rmSync(tempDependencyDir, { recursive: true }); } catch (error3) { logger2.info( `Failed to remove temporary dependencies directory: ${getErrorMessage(error3)}` @@ -193815,7 +193857,7 @@ async function runWrapper3() { } // src/init-action.ts -var fs30 = __toESM(require("fs")); +var fs31 = __toESM(require("fs")); var path25 = __toESM(require("path")); var core19 = __toESM(require_core()); var io7 = __toESM(require_io()); @@ -193856,46 +193898,41 @@ async function getToolsInput(action, repositoryProperties) { } // src/languages/swift.ts -var SWIFT_TRACED_UNSUPPORTED_MACOS = 27; -var SWIFT_TRACED_UNSUPPORTED_XCODE = 27; -async function checkSwiftCompatibility(action, config, codeql) { +async function checkSwiftCompatibility(config, codeql, macosVersion) { if (!config.languages.includes("swift" /* swift */)) { return; } if (await codeql.supportsFeature("swiftSupportsAllPlatforms" /* SwiftSupportsAllPlatforms */)) { return; } - const version = macOSVersion(action); - if (version === void 0) { + if (macosVersion === void 0) { throw new ConfigurationError( `Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.` ); } - if (typeof version === "string") { - action.logger.warning( - `Unable to determine version of macOS, got: ${version}` - ); - return; - } - const skipUnsupportedTracedAnalysis = await action.features.getValue( - "skip_unsupported_traced_analysis" /* SkipUnsupportedTracedAnalysis */ - ); - if (version.major >= SWIFT_TRACED_UNSUPPORTED_MACOS) { - const baseMessage = [ - `Traced Swift analysis is not supported on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS} or above.`, - `Configure your analysis to run on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS - 1} or below`, - `and XCode ${SWIFT_TRACED_UNSUPPORTED_XCODE - 1} or below.` - ].join(" "); +} + +// src/languages/traced.ts +var UNSUPPORTED_MACOS_FOR_TRACED = 27; +var UNSUPPORTED_XCODE_FOR_TRACED = 27; +function handleUnsupportedVersion(logger2, config, skipUnsupportedTracedAnalysis, product, version) { + const baseMessage = [ + `Traced analysis is not supported on ${product} ${UNSUPPORTED_MACOS_FOR_TRACED} or above.`, + `Configure your analysis to run on macOS ${UNSUPPORTED_MACOS_FOR_TRACED - 1} or below`, + `and XCode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.` + ].join(" "); + const attributeName = product === "macOS" ? "macOSVersion" : "xcodeVersion"; + for (const language of config.languages) { addDiagnostic( config, - "swift" /* swift */, + language, makeDiagnostic( - "codeql-action/unsupported-traced-swift-analysis-macos", - "Traced Swift analysis is not supported on this version of macOS", + `codeql-action/unsupported-traced-analysis-${product.toLowerCase()}`, + `Traced analysis is not supported on this version of ${product}`, { attributes: { languages: config.languages, - macOSVersion: version.toString() + [attributeName]: version.toString() }, markdownMessage: baseMessage, severity: skipUnsupportedTracedAnalysis ? "error" : "warning", @@ -193907,11 +193944,41 @@ async function checkSwiftCompatibility(action, config, codeql) { } ) ); - if (skipUnsupportedTracedAnalysis) { - throw new ConfigurationError(baseMessage); - } else { - action.logger.warning(baseMessage); - } + } + if (skipUnsupportedTracedAnalysis) { + throw new ConfigurationError(baseMessage); + } else { + logger2.warning(baseMessage); + } +} +async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { + const version = macOSVersion(action); + await checkSwiftCompatibility(config, codeql, version); + const skipUnsupportedTracedAnalysis = await action.features.getValue( + "skip_unsupported_traced_analysis" /* SkipUnsupportedTracedAnalysis */ + ); + if (typeof version === "string") { + action.logger.warning( + `Unable to determine version of macOS, got: ${version}` + ); + } else if (version !== void 0 && version.major >= UNSUPPORTED_MACOS_FOR_TRACED) { + handleUnsupportedVersion( + action.logger, + config, + skipUnsupportedTracedAnalysis, + "macOS", + version + ); + } + const xcodeVer = xcodeVersion(action.logger); + if (xcodeVer !== void 0 && xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED) { + handleUnsupportedVersion( + action.logger, + config, + skipUnsupportedTracedAnalysis, + "Xcode", + xcodeVer + ); } } @@ -193934,7 +194001,7 @@ function createInitToolsDownloadFields(report, toolsFeatureFlagsValid) { } // src/workflow.ts -var fs29 = __toESM(require("fs")); +var fs30 = __toESM(require("fs")); var path24 = __toESM(require("path")); var import_zlib3 = __toESM(require("zlib")); var core18 = __toESM(require_core()); @@ -194086,7 +194153,7 @@ async function getWorkflow(logger2) { ); } const workflowPath = await getWorkflowAbsolutePath(logger2); - return load(fs29.readFileSync(workflowPath, "utf-8")); + return load(fs30.readFileSync(workflowPath, "utf-8")); } async function getWorkflowAbsolutePath(logger2) { const relativePath2 = await getWorkflowRelativePath(); @@ -194094,7 +194161,7 @@ async function getWorkflowAbsolutePath(logger2) { getRequiredEnvParam("GITHUB_WORKSPACE"), relativePath2 ); - if (fs29.existsSync(absolutePath)) { + if (fs30.existsSync(absolutePath)) { logger2.debug( `Derived the following absolute path for the currently executing workflow: ${absolutePath}.` ); @@ -194434,7 +194501,11 @@ async function run3(actionState) { enableFileCoverageInformation: fileCoverageResult.enabled, logger: logger2 }); - await checkSwiftCompatibility(actionStateWithFeatures, config, codeql); + await checkRunnerSupportsTracedAnalysis( + actionStateWithFeatures, + config, + codeql + ); if (repositoryPropertiesResult.isFailure()) { addNoLanguageDiagnostic( config, @@ -194534,16 +194605,16 @@ async function run3(actionState) { "codeql-action-go-tracing", "bin" ); - fs30.mkdirSync(tempBinPath, { recursive: true }); + fs31.mkdirSync(tempBinPath, { recursive: true }); core19.addPath(tempBinPath); const goWrapperPath = path25.resolve(tempBinPath, "go"); - fs30.writeFileSync( + fs31.writeFileSync( goWrapperPath, `#!/bin/bash exec ${goBinaryPath} "$@"` ); - fs30.chmodSync(goWrapperPath, "755"); + fs31.chmodSync(goWrapperPath, "755"); actionState.env.export("CODEQL_ACTION_GO_BINARY" /* GO_BINARY_LOCATION */, goWrapperPath); } catch (e) { logger2.warning( @@ -194726,7 +194797,7 @@ async function runWrapper4() { var core20 = __toESM(require_core()); // src/init-action-post-helper.ts -var fs31 = __toESM(require("fs")); +var fs32 = __toESM(require("fs")); var import_path8 = __toESM(require("path")); var github4 = __toESM(require_github()); function createFailedUploadFailedSarifResult(error3) { @@ -194808,7 +194879,7 @@ async function generateFailedSarif(logger2, features, config, category, checkout let diagnosticDir = getTempDiagnosticsRoot( config.tempDir ); - if (!exportDiagnosticsEnabled || !fs31.existsSync(diagnosticDir)) { + if (!exportDiagnosticsEnabled || !fs32.existsSync(diagnosticDir)) { diagnosticDir = void 0; } await codeql.diagnosticsExport(sarifFile, category, config, diagnosticDir); @@ -194935,7 +195006,7 @@ async function uploadFailureInfo(uploadAllAvailableDebugArtifacts, printDebugLog } if (isSelfHostedRunner() && config.dbLocation) { try { - fs31.rmSync(config.dbLocation, { + fs32.rmSync(config.dbLocation, { recursive: true, force: true, maxRetries: 3 @@ -195875,7 +195946,7 @@ function generateCertificateAuthority() { } // src/start-proxy/environment.ts -var fs32 = __toESM(require("fs")); +var fs33 = __toESM(require("fs")); var path28 = __toESM(require("path")); var toolrunner5 = __toESM(require_toolrunner()); var io8 = __toESM(require_io()); @@ -195948,9 +196019,9 @@ function checkJdkSettings(logger2, jdkHome) { for (const fileToCheck of filesToCheck) { const file = path28.join(jdkHome, fileToCheck); try { - if (fs32.existsSync(file)) { + if (fs33.existsSync(file)) { logger2.debug(`Found '${file}'.`); - const lines = String(fs32.readFileSync(file)).split("\n"); + const lines = String(fs33.readFileSync(file)).split("\n"); for (const line of lines) { for (const property of javaProperties) { if (line.startsWith(`${property}=`)) { diff --git a/src/init-action.ts b/src/init-action.ts index ae793e19ba..af95e8ffab 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -62,7 +62,7 @@ import { runDatabaseInitCluster, } from "./init"; import { JavaEnvVars, BuiltInLanguage } from "./languages"; -import { checkSwiftCompatibility } from "./languages/swift"; +import { checkRunnerSupportsTracedAnalysis } from "./languages/traced"; import { Logger, withGroupAsync } from "./logging"; import { downloadOverlayBaseDatabaseFromCache, @@ -419,7 +419,11 @@ async function run( logger, }); - await checkSwiftCompatibility(actionStateWithFeatures, config, codeql); + await checkRunnerSupportsTracedAnalysis( + actionStateWithFeatures, + config, + codeql, + ); if (repositoryPropertiesResult.isFailure()) { addNoLanguageDiagnostic( diff --git a/src/languages/swift.test.ts b/src/languages/swift.test.ts index dd3bca80c4..465f782c16 100644 --- a/src/languages/swift.test.ts +++ b/src/languages/swift.test.ts @@ -1,22 +1,17 @@ import test from "ava"; import sinon from "sinon"; -import * as diagnostics from "../diagnostics"; import { ActionsEnvVars } from "../environment"; -import { Feature } from "../feature-flags"; import { - checkExpectedLogMessages, - createFeatures, createTestConfig, getCodeQLForTesting, getTestEnv, - initAllState, makeVersionInfo, RecordingLogger, setupTests, } from "../testing-utils"; import { ToolsFeature } from "../tools-features"; -import { ConfigurationError, withTmpDir } from "../util"; +import { withTmpDir } from "../util"; import { checkSwiftCompatibility } from "./swift"; @@ -33,9 +28,11 @@ test("checkSwiftCompatibility doesn't throw for non-Swift languages", async (t) const codeql = await getCodeQLForTesting(); await t.notThrowsAsync( checkSwiftCompatibility( - initAllState(), createTestConfig({ languages: [language] }), codeql, + // A value of `undefined` should make `isSwiftCompatible` throw for Swift by default + // since it means we are on a platform other than macOS + undefined, ), ); } @@ -55,9 +52,11 @@ test("checkSwiftCompatibility doesn't throw for Swift if CLI supports swiftSuppo await t.notThrowsAsync( checkSwiftCompatibility( - initAllState({ platform: "darwin", env, logger }), createTestConfig({ languages: [BuiltInLanguage.swift] }), codeql, + // A value of `undefined` should make `isSwiftCompatible` throw for Swift by default + // since it means we are on a platform other than macOS + undefined, ), ); @@ -78,183 +77,13 @@ test("checkSwiftCompatibility doesn't throw for Swift on darwin", async (t) => await t.notThrowsAsync( checkSwiftCompatibility( - initAllState({ platform: "darwin", env, logger }), createTestConfig({ tempDir: tmpDir, languages: [BuiltInLanguage.swift], }), codeql, + // A value other than `undefined` means we are on macOS. + "some-macos-version", ), ); })); - -const nonDarwinPlatforms: NodeJS.Platform[] = ["linux", "win32"]; -for (const nonDarwinPlatform of nonDarwinPlatforms) { - test(`checkSwiftCompatibility throws for Swift on ${nonDarwinPlatform}`, async (t) => - withTmpDir(async (tmpDir) => { - const logger = new RecordingLogger(); - const env = getTestEnv(); - env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - - const codeql = await getCodeQLForTesting( - "codeql-for-testing", - logger, - env, - ); - sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); - - await t.throwsAsync( - checkSwiftCompatibility( - initAllState({ platform: nonDarwinPlatform, env, logger }), - createTestConfig({ languages: [BuiltInLanguage.swift] }), - codeql, - ), - { - instanceOf: ConfigurationError, - message: /^Swift analysis is only supported on macOS runner images/, - }, - ); - })); -} - -test("checkSwiftCompatibility warns if version string is not a semver", async (t) => - withTmpDir(async (tmpDir) => { - const logger = new RecordingLogger(); - const env = getTestEnv(); - env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - - const codeql = await getCodeQLForTesting("codeql-for-testing", logger, env); - sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); - - await checkSwiftCompatibility( - initAllState({ - logger, - platform: "darwin", - osRelease: "unexpected", - env, - }), - createTestConfig({ languages: [BuiltInLanguage.swift] }), - codeql, - ); - - checkExpectedLogMessages(t, logger.messages, [ - "Unable to determine version of macOS, got: unexpected", - ]); - })); - -// `addDiagnostic` changes global state and we must stub it, so this test must be serial. -test.serial( - "checkSwiftCompatibility logs and adds diagnostic if macOS version is unsupported", - async (t) => - withTmpDir(async (tmpDir) => { - const logger = new RecordingLogger(); - const env = getTestEnv(); - env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - - const codeql = await getCodeQLForTesting( - "codeql-for-testing", - logger, - env, - ); - sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); - - const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); - - const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); - await checkSwiftCompatibility( - initAllState({ - logger, - platform: "darwin", - osRelease: "27.0.0", - env, - }), - config, - codeql, - ); - - checkExpectedLogMessages(t, logger.messages, [ - "Traced Swift analysis is not supported on macOS 27", - ]); - - t.is(addDiagnostic.callCount, 1); - t.like(addDiagnostic.args[0], [ - config, - BuiltInLanguage.swift, - { - attributes: { - languages: [BuiltInLanguage.swift], - macOSVersion: "27.0.0", - }, - severity: "warning", - source: { - id: "codeql-action/unsupported-traced-swift-analysis-macos", - name: "Traced Swift analysis is not supported on this version of macOS", - }, - visibility: { - cliSummaryTable: true, - statusPage: true, - telemetry: true, - }, - } satisfies Partial, - ]); - }), -); - -// `addDiagnostic` changes global state and we must stub it, so this test must be serial. -test.serial( - "checkSwiftCompatibility throws if macOS version is unsupported and FF is enabled", - async (t) => - withTmpDir(async (tmpDir) => { - const logger = new RecordingLogger(); - const env = getTestEnv(); - env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - - const features = createFeatures([Feature.SkipUnsupportedTracedAnalysis]); - - const codeql = await getCodeQLForTesting( - "codeql-for-testing", - logger, - env, - ); - sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); - - const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); - - const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); - await t.throwsAsync( - checkSwiftCompatibility( - initAllState({ - logger, - platform: "darwin", - osRelease: "27.0.0", - env, - features, - }), - config, - codeql, - ), - ); - - t.is(addDiagnostic.callCount, 1); - t.like(addDiagnostic.args[0], [ - config, - BuiltInLanguage.swift, - { - attributes: { - languages: [BuiltInLanguage.swift], - macOSVersion: "27.0.0", - }, - severity: "error", - source: { - id: "codeql-action/unsupported-traced-swift-analysis-macos", - name: "Traced Swift analysis is not supported on this version of macOS", - }, - visibility: { - cliSummaryTable: true, - statusPage: true, - telemetry: true, - }, - } satisfies Partial, - ]); - }), -); diff --git a/src/languages/swift.ts b/src/languages/swift.ts index 30a77eb420..45ca87416a 100644 --- a/src/languages/swift.ts +++ b/src/languages/swift.ts @@ -1,32 +1,25 @@ -import { ActionState } from "../action-common"; +import type { SemVer } from "semver"; + import { CodeQL } from "../codeql"; -import { Config } from "../config-utils"; -import { addDiagnostic, makeDiagnostic } from "../diagnostics"; -import { Feature } from "../feature-flags"; -import { macOSVersion } from "../platform"; +import type { ActionConfig } from "../config/action-config"; import { ToolsFeature } from "../tools-features"; import { ConfigurationError } from "../util"; import { BuiltInLanguage } from "."; -/** macOS 27 and above do not support traced extraction for Swift. */ -export const SWIFT_TRACED_UNSUPPORTED_MACOS = 27; - -/** Xcode 27 and above do not support traced extraction for Swift. */ -export const SWIFT_TRACED_UNSUPPORTED_XCODE = 27; - /** * Determines whether we can run a Swift analysis on the current runner. * - * @param action The Action state. * @param config The Action configuration. + * @param codeql The {@link CodeQL} CLI instance. + * @param macosVersion The version of macOS, if any. * * @throws {ConfigurationError} If Swift analysis is not possible on the current runner. */ export async function checkSwiftCompatibility( - action: ActionState<["Base", "Logger", "FeatureFlags"]>, - config: Config, + config: ActionConfig<"languages">, codeql: CodeQL, + macosVersion: SemVer | string | undefined, ) { // The checks are not relevant if we are not trying to analyse Swift. if (!config.languages.includes(BuiltInLanguage.swift)) { @@ -40,64 +33,10 @@ export async function checkSwiftCompatibility( return; } - // Try to get the macOS version. - const version = macOSVersion(action); - - // If `version` is undefined, then we are not on macOS. - if (version === undefined) { + // If `macosVersion` is undefined, then we are not on macOS and Swift analysis is unsupported. + if (macosVersion === undefined) { throw new ConfigurationError( `Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.`, ); } - // If we got a string, we are on macOS but couldn't parse the version string. - if (typeof version === "string") { - action.logger.warning( - `Unable to determine version of macOS, got: ${version}`, - ); - return; - } - - const skipUnsupportedTracedAnalysis = await action.features.getValue( - Feature.SkipUnsupportedTracedAnalysis, - ); - if (version.major >= SWIFT_TRACED_UNSUPPORTED_MACOS) { - const baseMessage = [ - `Traced Swift analysis is not supported on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS} or above.`, - `Configure your analysis to run on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS - 1} or below`, - `and XCode ${SWIFT_TRACED_UNSUPPORTED_XCODE - 1} or below.`, - ].join(" "); - - // Create a diagnostic that will show up on the TSP. - addDiagnostic( - config, - BuiltInLanguage.swift, - makeDiagnostic( - "codeql-action/unsupported-traced-swift-analysis-macos", - "Traced Swift analysis is not supported on this version of macOS", - { - attributes: { - languages: config.languages, - macOSVersion: version.toString(), - }, - markdownMessage: baseMessage, - severity: skipUnsupportedTracedAnalysis ? "error" : "warning", - visibility: { - cliSummaryTable: true, - statusPage: true, - telemetry: true, - }, - }, - ), - ); - - // Throw an error to abort the analysis if the FF is enabled or log the message. - if (skipUnsupportedTracedAnalysis) { - // ConfigurationErrors are converted to the "aborted" status by the exception handler - // in `init-action.ts` that guards the call to `isSwiftCompatible`. - throw new ConfigurationError(baseMessage); - } else { - // This will also show up as a workflow annotation. - action.logger.warning(baseMessage); - } - } } diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts new file mode 100644 index 0000000000..74afef5dd7 --- /dev/null +++ b/src/languages/traced.test.ts @@ -0,0 +1,390 @@ +import fs from "fs"; + +import test from "ava"; +import * as sinon from "sinon"; + +import * as diagnostics from "../diagnostics"; +import { ActionsEnvVars } from "../environment"; +import { Feature } from "../feature-flags"; +import { XCODE_SELECT_LINK_PATH } from "../platform"; +import { + checkExpectedLogMessages, + checkUnexpectedLogMessages, + createFeatures, + createTestConfig, + getCodeQLForTesting, + getTestEnv, + initAllState, + makeVersionInfo, + RecordingLogger, + setupTests, +} from "../testing-utils"; +import { ConfigurationError, withTmpDir } from "../util"; + +import { checkRunnerSupportsTracedAnalysis } from "./traced"; + +import { BuiltInLanguage } from "."; + +setupTests(test); + +const nonDarwinPlatforms: NodeJS.Platform[] = ["linux", "win32"]; +for (const nonDarwinPlatform of nonDarwinPlatforms) { + test(`checkRunnerSupportsTracedAnalysis throws for Swift on ${nonDarwinPlatform}`, async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLForTesting( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + await t.throwsAsync( + checkRunnerSupportsTracedAnalysis( + initAllState({ platform: nonDarwinPlatform, env, logger }), + createTestConfig({ languages: [BuiltInLanguage.swift] }), + codeql, + ), + { + instanceOf: ConfigurationError, + message: /^Swift analysis is only supported on macOS runner images/, + }, + ); + })); +} + +test("checkRunnerSupportsTracedAnalysis warns if version string is not a semver", async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLForTesting("codeql-for-testing", logger, env); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + await checkRunnerSupportsTracedAnalysis( + initAllState({ + logger, + platform: "darwin", + osRelease: "unexpected", + env, + }), + createTestConfig({ languages: [BuiltInLanguage.go] }), + codeql, + ); + + checkExpectedLogMessages(t, logger.messages, [ + "Unable to determine version of macOS, got: unexpected", + ]); + })); + +// `addDiagnostic` changes global state and we must stub it, so this test must be serial. +test.serial( + "checkRunnerSupportsTracedAnalysis logs and adds diagnostic if macOS version is unsupported", + async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLForTesting( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); + + const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); + await checkRunnerSupportsTracedAnalysis( + initAllState({ + logger, + platform: "darwin", + osRelease: "27.0.0", + env, + }), + config, + codeql, + ); + + checkExpectedLogMessages(t, logger.messages, [ + "Traced analysis is not supported on macOS 27", + ]); + + t.is(addDiagnostic.callCount, 1); + t.like(addDiagnostic.args[0], [ + config, + BuiltInLanguage.swift, + { + attributes: { + languages: [BuiltInLanguage.swift], + macOSVersion: "27.0.0", + }, + severity: "warning", + source: { + id: "codeql-action/unsupported-traced-analysis-macos", + name: "Traced analysis is not supported on this version of macOS", + }, + visibility: { + cliSummaryTable: true, + statusPage: true, + telemetry: true, + }, + } satisfies Partial, + ]); + }), +); + +// `addDiagnostic` changes global state and we must stub it, so this test must be serial. +test.serial( + "checkRunnerSupportsTracedAnalysis throws if macOS version is unsupported and FF is enabled", + async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const features = createFeatures([Feature.SkipUnsupportedTracedAnalysis]); + + const codeql = await getCodeQLForTesting( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); + + const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); + await t.throwsAsync( + checkRunnerSupportsTracedAnalysis( + initAllState({ + logger, + platform: "darwin", + osRelease: "27.0.0", + env, + features, + }), + config, + codeql, + ), + ); + + t.is(addDiagnostic.callCount, 1); + t.like(addDiagnostic.args[0], [ + config, + BuiltInLanguage.swift, + { + attributes: { + languages: [BuiltInLanguage.swift], + macOSVersion: "27.0.0", + }, + severity: "error", + source: { + id: "codeql-action/unsupported-traced-analysis-macos", + name: "Traced analysis is not supported on this version of macOS", + }, + visibility: { + cliSummaryTable: true, + statusPage: true, + telemetry: true, + }, + } satisfies Partial, + ]); + }), +); + +// `addDiagnostic` changes global state and we must stub it, so this test must be serial. +test.serial( + "checkRunnerSupportsTracedAnalysis doesn't add a diagnostic if Xcode version is supported", + async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const statSync = sinon + .stub(fs, "statSync") + .returns({ isSymbolicLink: () => true } as fs.Stats); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .returns("/Applications/Xcode_26.0.app/Contents/Developer"); + + const codeql = await getCodeQLForTesting( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); + + const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); + await checkRunnerSupportsTracedAnalysis( + initAllState({ + logger, + platform: "darwin", + osRelease: "26.0.0", + env, + }), + config, + codeql, + ); + + t.is(statSync.callCount, 1); + t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); + + checkUnexpectedLogMessages(t, logger.messages, [ + "Traced analysis is not supported on Xcode 27", + ]); + + t.is(addDiagnostic.callCount, 0); + }), +); + +// `addDiagnostic` changes global state and we must stub it, so this test must be serial. +test.serial( + "checkRunnerSupportsTracedAnalysis logs and adds diagnostic if Xcode version is unsupported", + async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const statSync = sinon + .stub(fs, "statSync") + .returns({ isSymbolicLink: () => true } as fs.Stats); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .returns("/Applications/Xcode_27.0.app/Contents/Developer"); + + const codeql = await getCodeQLForTesting( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); + + const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); + await checkRunnerSupportsTracedAnalysis( + initAllState({ + logger, + platform: "darwin", + osRelease: "26.0.0", + env, + }), + config, + codeql, + ); + + t.is(statSync.callCount, 1); + t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); + + checkExpectedLogMessages(t, logger.messages, [ + "Traced analysis is not supported on Xcode 27", + ]); + + t.is(addDiagnostic.callCount, 1); + t.like(addDiagnostic.args[0], [ + config, + BuiltInLanguage.swift, + { + attributes: { + languages: [BuiltInLanguage.swift], + xcodeVersion: "27.0.0", + }, + severity: "warning", + source: { + id: "codeql-action/unsupported-traced-analysis-xcode", + name: "Traced analysis is not supported on this version of Xcode", + }, + visibility: { + cliSummaryTable: true, + statusPage: true, + telemetry: true, + }, + } satisfies Partial, + ]); + }), +); + +// `addDiagnostic` changes global state and we must stub it, so this test must be serial. +test.serial( + "checkRunnerSupportsTracedAnalysis throws if Xcode version is unsupported and FF is enabled", + async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const statSync = sinon + .stub(fs, "statSync") + .returns({ isSymbolicLink: () => true } as fs.Stats); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .returns("/Applications/Xcode_27.0.app/Contents/Developer"); + + const features = createFeatures([Feature.SkipUnsupportedTracedAnalysis]); + + const codeql = await getCodeQLForTesting( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); + + const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); + await t.throwsAsync( + checkRunnerSupportsTracedAnalysis( + initAllState({ + logger, + platform: "darwin", + osRelease: "26.0.0", + env, + features, + }), + config, + codeql, + ), + ); + + t.is(statSync.callCount, 1); + t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); + + t.is(addDiagnostic.callCount, 1); + t.like(addDiagnostic.args[0], [ + config, + BuiltInLanguage.swift, + { + attributes: { + languages: [BuiltInLanguage.swift], + xcodeVersion: "27.0.0", + }, + severity: "error", + source: { + id: "codeql-action/unsupported-traced-analysis-xcode", + name: "Traced analysis is not supported on this version of Xcode", + }, + visibility: { + cliSummaryTable: true, + statusPage: true, + telemetry: true, + }, + } satisfies Partial, + ]); + }), +); diff --git a/src/languages/traced.ts b/src/languages/traced.ts new file mode 100644 index 0000000000..1d731187ba --- /dev/null +++ b/src/languages/traced.ts @@ -0,0 +1,134 @@ +import * as semver from "semver"; + +import type { ActionState, Logger } from "../action-common"; +import type { CodeQL } from "../codeql"; +import type { ActionConfig } from "../config/action-config"; +import { addDiagnostic, makeDiagnostic } from "../diagnostics"; +import { Feature } from "../feature-flags"; +import { macOSVersion, xcodeVersion } from "../platform"; +import { ConfigurationError } from "../util"; + +import { checkSwiftCompatibility } from "./swift"; + +/** macOS 27 and above do not support traced extraction. */ +export const UNSUPPORTED_MACOS_FOR_TRACED = 27; + +/** Xcode 27 and above do not support traced extraction. */ +export const UNSUPPORTED_XCODE_FOR_TRACED = 27; + +/** + * Creates a diagnostic indicating that `version` of `product` is unsupported for traced analysis. + * Depending on `skipUnsupportedTracedAnalysis`, this function then either throws a {@link ConfigurationError} + * or logs the problem as a warning. + * + * @param logger The logger to use. + * @param config The CodeQL Action configuration. + * @param skipUnsupportedTracedAnalysis Whether this is a fatal error. + * @param product The product that the version is unsupported of. + * @param version The unsupported version. + */ +function handleUnsupportedVersion( + logger: Logger, + config: ActionConfig<"languages" | "dbLocation" | "tempDir">, + skipUnsupportedTracedAnalysis: boolean, + product: "macOS" | "Xcode", + version: semver.SemVer, +) { + const baseMessage = [ + `Traced analysis is not supported on ${product} ${UNSUPPORTED_MACOS_FOR_TRACED} or above.`, + `Configure your analysis to run on macOS ${UNSUPPORTED_MACOS_FOR_TRACED - 1} or below`, + `and XCode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.`, + ].join(" "); + + const attributeName = product === "macOS" ? "macOSVersion" : "xcodeVersion"; + + // Create a diagnostic that will show up on the TSP. + for (const language of config.languages) { + addDiagnostic( + config, + language, + makeDiagnostic( + `codeql-action/unsupported-traced-analysis-${product.toLowerCase()}`, + `Traced analysis is not supported on this version of ${product}`, + { + attributes: { + languages: config.languages, + [attributeName]: version.toString(), + }, + markdownMessage: baseMessage, + severity: skipUnsupportedTracedAnalysis ? "error" : "warning", + visibility: { + cliSummaryTable: true, + statusPage: true, + telemetry: true, + }, + }, + ), + ); + } + + // Throw an error to abort the analysis if the FF is enabled or log the message. + if (skipUnsupportedTracedAnalysis) { + // ConfigurationErrors are converted to the "aborted" status by the exception handler + // in `init-action.ts` that guards the call to `checkRunnerSupportsTracedAnalysis`. + throw new ConfigurationError(baseMessage); + } else { + // This will also show up as a workflow annotation. + logger.warning(baseMessage); + } +} + +/** + * Determines whether we can run a traced analysis on the current runner. + * + * @throws {ConfigurationError} If traced analysis is not possible on the current runner. + */ +export async function checkRunnerSupportsTracedAnalysis( + action: ActionState<["Base", "Logger", "FeatureFlags"]>, + config: ActionConfig<"languages" | "dbLocation" | "tempDir">, + codeql: CodeQL, +) { + // Try to get the macOS version. + const version = macOSVersion(action); + + // Perform some initial, Swift-specific checks. + await checkSwiftCompatibility(config, codeql, version); + + const skipUnsupportedTracedAnalysis = await action.features.getValue( + Feature.SkipUnsupportedTracedAnalysis, + ); + if (typeof version === "string") { + // If we got a string, we are on macOS but couldn't parse the version string. + action.logger.warning( + `Unable to determine version of macOS, got: ${version}`, + ); + } else if ( + version !== undefined && + version.major >= UNSUPPORTED_MACOS_FOR_TRACED + ) { + handleUnsupportedVersion( + action.logger, + config, + skipUnsupportedTracedAnalysis, + "macOS", + version, + ); + } + + // Determining whether the Xcode version is supported only makes sense on macOS, so we only do it + // after determining that we are running on macOS. + const xcodeVer = xcodeVersion(action.logger); + + if ( + xcodeVer !== undefined && + xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED + ) { + handleUnsupportedVersion( + action.logger, + config, + skipUnsupportedTracedAnalysis, + "Xcode", + xcodeVer, + ); + } +} From 86bb85349e6a39e16be0f94b22cf56e1b7b10ac0 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 22:56:47 +0100 Subject: [PATCH 120/174] Don't perform check for non-traced analyses --- lib/entry-points.js | 14 +++++ src/languages/traced.test.ts | 105 ++++++++++++++++++++++++++++++++--- src/languages/traced.ts | 27 +++++++++ 3 files changed, 137 insertions(+), 9 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 8f9769bbac..656a119b24 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -193951,9 +193951,23 @@ function handleUnsupportedVersion(logger2, config, skipUnsupportedTracedAnalysis logger2.warning(baseMessage); } } +async function hasTracedLanguages(config, codeql) { + for (const language of config.languages) { + if (await codeql.isTracedLanguage(language)) { + return true; + } + } + return false; +} async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { const version = macOSVersion(action); await checkSwiftCompatibility(config, codeql, version); + if (config.buildMode !== void 0 && config.buildMode === "none") { + return; + } + if (!await hasTracedLanguages(config, codeql)) { + return; + } const skipUnsupportedTracedAnalysis = await action.features.getValue( "skip_unsupported_traced_analysis" /* SkipUnsupportedTracedAnalysis */ ); diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index 74afef5dd7..5a45788f5b 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -3,9 +3,11 @@ import fs from "fs"; import test from "ava"; import * as sinon from "sinon"; +import { type CodeQL } from "../codeql"; import * as diagnostics from "../diagnostics"; -import { ActionsEnvVars } from "../environment"; +import { ActionsEnvVars, type Env } from "../environment"; import { Feature } from "../feature-flags"; +import type { Logger } from "../logging"; import { XCODE_SELECT_LINK_PATH } from "../platform"; import { checkExpectedLogMessages, @@ -19,7 +21,7 @@ import { RecordingLogger, setupTests, } from "../testing-utils"; -import { ConfigurationError, withTmpDir } from "../util"; +import { BuildMode, ConfigurationError, withTmpDir } from "../util"; import { checkRunnerSupportsTracedAnalysis } from "./traced"; @@ -27,6 +29,26 @@ import { BuiltInLanguage } from "."; setupTests(test); +const TEST_DEFAULT_TRACED_LANGUAGES = { + [BuiltInLanguage.swift]: true, + [BuiltInLanguage.go]: true, +}; + +async function getCodeQLWithTracedStub( + cmd: string, + logger: Logger, + env: Env, + tracedLanguages: Partial< + Record + > = TEST_DEFAULT_TRACED_LANGUAGES, +): Promise { + const codeql = await getCodeQLForTesting(cmd, logger, env); + sinon.stub(codeql, "isTracedLanguage").callsFake(async (language) => { + return tracedLanguages[language] === true; + }); + return codeql; +} + const nonDarwinPlatforms: NodeJS.Platform[] = ["linux", "win32"]; for (const nonDarwinPlatform of nonDarwinPlatforms) { test(`checkRunnerSupportsTracedAnalysis throws for Swift on ${nonDarwinPlatform}`, async (t) => @@ -35,7 +57,7 @@ for (const nonDarwinPlatform of nonDarwinPlatforms) { const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - const codeql = await getCodeQLForTesting( + const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", logger, env, @@ -56,13 +78,78 @@ for (const nonDarwinPlatform of nonDarwinPlatforms) { })); } +test(`checkRunnerSupportsTracedAnalysis doesn't throw for BMN`, async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLWithTracedStub( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + await t.notThrowsAsync( + checkRunnerSupportsTracedAnalysis( + initAllState({ + platform: "darwin", + osRelease: "27.0.0", + env, + logger, + }), + createTestConfig({ buildMode: BuildMode.None }), + codeql, + ), + ); + })); + +// Some languages not in `TEST_DEFAULT_TRACED_LANGUAGES`. +const nonTracedLanguages: BuiltInLanguage[] = [ + BuiltInLanguage.javascript, + BuiltInLanguage.actions, +]; +for (const nonTracedLanguage of nonTracedLanguages) { + test(`checkRunnerSupportsTracedAnalysis doesn't throw for ${nonTracedLanguage} on unsupported macOS`, async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLWithTracedStub( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + await t.notThrowsAsync( + checkRunnerSupportsTracedAnalysis( + initAllState({ + platform: "darwin", + osRelease: "27.0.0", + env, + logger, + }), + createTestConfig({ languages: [nonTracedLanguage] }), + codeql, + ), + ); + })); +} + test("checkRunnerSupportsTracedAnalysis warns if version string is not a semver", async (t) => withTmpDir(async (tmpDir) => { const logger = new RecordingLogger(); const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - const codeql = await getCodeQLForTesting("codeql-for-testing", logger, env); + const codeql = await getCodeQLWithTracedStub( + "codeql-for-testing", + logger, + env, + ); sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); await checkRunnerSupportsTracedAnalysis( @@ -90,7 +177,7 @@ test.serial( const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - const codeql = await getCodeQLForTesting( + const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", logger, env, @@ -150,7 +237,7 @@ test.serial( const features = createFeatures([Feature.SkipUnsupportedTracedAnalysis]); - const codeql = await getCodeQLForTesting( + const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", logger, env, @@ -214,7 +301,7 @@ test.serial( .stub(fs, "readlinkSync") .returns("/Applications/Xcode_26.0.app/Contents/Developer"); - const codeql = await getCodeQLForTesting( + const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", logger, env, @@ -264,7 +351,7 @@ test.serial( .stub(fs, "readlinkSync") .returns("/Applications/Xcode_27.0.app/Contents/Developer"); - const codeql = await getCodeQLForTesting( + const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", logger, env, @@ -336,7 +423,7 @@ test.serial( const features = createFeatures([Feature.SkipUnsupportedTracedAnalysis]); - const codeql = await getCodeQLForTesting( + const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", logger, env, diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 1d731187ba..ea60a6789c 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -78,6 +78,23 @@ function handleUnsupportedVersion( } } +/** + * Decides whether {@link config} has any traced languages by looking for tracer + * configurations in the {@link codeql} CLI installation. + */ +export async function hasTracedLanguages( + config: ActionConfig<"languages">, + codeql: CodeQL, +): Promise { + for (const language of config.languages) { + if (await codeql.isTracedLanguage(language)) { + return true; + } + } + + return false; +} + /** * Determines whether we can run a traced analysis on the current runner. * @@ -94,6 +111,16 @@ export async function checkRunnerSupportsTracedAnalysis( // Perform some initial, Swift-specific checks. await checkSwiftCompatibility(config, codeql, version); + // `build-mode: none` doesn't use the tracer, so it is always supported. + if (config.buildMode !== undefined && config.buildMode === "none") { + return; + } + + // If none of the languages are traced, then we can skip the compatibility checks below as well. + if (!(await hasTracedLanguages(config, codeql))) { + return; + } + const skipUnsupportedTracedAnalysis = await action.features.getValue( Feature.SkipUnsupportedTracedAnalysis, ); From 156dc2ce18f2cccb7ba87342d743e3eb3a3dfc14 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 19 Oct 2026 11:51:33 +0100 Subject: [PATCH 121/174] Include URL to announcement in diagnostic and log messages --- lib/entry-points.js | 13 ++++++++++--- src/doc-url.ts | 2 ++ src/languages/traced.ts | 16 +++++++++++++--- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 656a119b24..bacb322a2a 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -193934,7 +193934,10 @@ function handleUnsupportedVersion(logger2, config, skipUnsupportedTracedAnalysis languages: config.languages, [attributeName]: version.toString() }, - markdownMessage: baseMessage, + markdownMessage: [ + baseMessage, + `For more information, see [this announcement](${"https://github.blog/changelog/2026-10-19-codeql-changes-for-macos-27-xcode-27-and-swift-6-4/" /* UNSUPPORTED_TRACED_ANALYSIS_MACOS27 */}).` + ].join(" "), severity: skipUnsupportedTracedAnalysis ? "error" : "warning", visibility: { cliSummaryTable: true, @@ -193945,10 +193948,14 @@ function handleUnsupportedVersion(logger2, config, skipUnsupportedTracedAnalysis ) ); } + const logMessage = [ + baseMessage, + `For more information, see ${"https://github.blog/changelog/2026-10-19-codeql-changes-for-macos-27-xcode-27-and-swift-6-4/" /* UNSUPPORTED_TRACED_ANALYSIS_MACOS27 */}` + ].join(" "); if (skipUnsupportedTracedAnalysis) { - throw new ConfigurationError(baseMessage); + throw new ConfigurationError(logMessage); } else { - logger2.warning(baseMessage); + logger2.warning(logMessage); } } async function hasTracedLanguages(config, codeql) { diff --git a/src/doc-url.ts b/src/doc-url.ts index 97f5451d85..c75d47a68d 100644 --- a/src/doc-url.ts +++ b/src/doc-url.ts @@ -12,4 +12,6 @@ export enum DocUrl { SPECIFY_BUILD_STEPS_MANUALLY = "https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#about-specifying-build-steps-manually", SYSTEM_REQUIREMENTS = "https://codeql.github.com/docs/codeql-overview/system-requirements/", TRACK_CODE_SCANNING_ALERTS_ACROSS_RUNS = "https://docs.github.com/en/code-security/reference/code-scanning/sarif-support-for-code-scanning#data-for-preventing-duplicated-alerts", + /** Blog post about traced analysis being unsupported on macOS 27 and with Xcode 27. */ + UNSUPPORTED_TRACED_ANALYSIS_MACOS27 = "https://github.blog/changelog/2026-10-19-codeql-changes-for-macos-27-xcode-27-and-swift-6-4/", } diff --git a/src/languages/traced.ts b/src/languages/traced.ts index ea60a6789c..0de35b589e 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -4,6 +4,7 @@ import type { ActionState, Logger } from "../action-common"; import type { CodeQL } from "../codeql"; import type { ActionConfig } from "../config/action-config"; import { addDiagnostic, makeDiagnostic } from "../diagnostics"; +import { DocUrl } from "../doc-url"; import { Feature } from "../feature-flags"; import { macOSVersion, xcodeVersion } from "../platform"; import { ConfigurationError } from "../util"; @@ -55,7 +56,10 @@ function handleUnsupportedVersion( languages: config.languages, [attributeName]: version.toString(), }, - markdownMessage: baseMessage, + markdownMessage: [ + baseMessage, + `For more information, see [this announcement](${DocUrl.UNSUPPORTED_TRACED_ANALYSIS_MACOS27}).`, + ].join(" "), severity: skipUnsupportedTracedAnalysis ? "error" : "warning", visibility: { cliSummaryTable: true, @@ -67,14 +71,20 @@ function handleUnsupportedVersion( ); } + // Log messages generally don't render as markdown, so we include the URL verbatim there. + const logMessage = [ + baseMessage, + `For more information, see ${DocUrl.UNSUPPORTED_TRACED_ANALYSIS_MACOS27}`, + ].join(" "); + // Throw an error to abort the analysis if the FF is enabled or log the message. if (skipUnsupportedTracedAnalysis) { // ConfigurationErrors are converted to the "aborted" status by the exception handler // in `init-action.ts` that guards the call to `checkRunnerSupportsTracedAnalysis`. - throw new ConfigurationError(baseMessage); + throw new ConfigurationError(logMessage); } else { // This will also show up as a workflow annotation. - logger.warning(baseMessage); + logger.warning(logMessage); } } From 7e5643a58ebc717911e86a7ae622acad6588f84a Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 19 Oct 2026 12:45:28 +0100 Subject: [PATCH 122/174] Accept paths containing only major version Also fix unescaped dot patterns in regex --- lib/entry-points.js | 2 +- src/platform.test.ts | 26 ++++++++++++++++++++++++++ src/platform.ts | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index bacb322a2a..8070d8e1a3 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -183441,7 +183441,7 @@ function macOSVersion(action) { } var XCODE_SELECT_LINK_PATH = "/private/var/db/xcode_select_link"; var XCODE_APP_FILENAME_PATTERN = new RegExp( - /(?Xcode_(?\d+.\d+).app)/ + /(?Xcode_(?\d+(\.\d+)?)\.app)/ ); function xcodeVersion(logger2) { try { diff --git a/src/platform.test.ts b/src/platform.test.ts index 5de468d823..3fdeec2752 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -190,3 +190,29 @@ test.serial("xcodeVersion returns version from resolved path", (t) => { t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); }); + +test.serial("xcodeVersion returns major version from resolved path", (t) => { + const logger = new RecordingLogger(); + + const lstatSync = sinon + .stub(fs, "lstatSync") + .returns({ isSymbolicLink: () => true } as fs.Stats); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .returns("/Applications/Xcode_16.app/Contents/Developer"); + + const result = xcodeVersion(logger); + + if (t.truthy(result)) { + t.is(result.major, 16); + t.is(result.minor, 0); + } + + t.is(lstatSync.callCount, 1); + t.deepEqual(lstatSync.args[0], [ + XCODE_SELECT_LINK_PATH, + { throwIfNoEntry: false }, + ]); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); +}); diff --git a/src/platform.ts b/src/platform.ts index d5c77c9f73..22c8f6a935 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -62,7 +62,7 @@ export const XCODE_SELECT_LINK_PATH = "/private/var/db/xcode_select_link"; /** The pattern we expect to find in the Xcode path. */ export const XCODE_APP_FILENAME_PATTERN = new RegExp( - /(?Xcode_(?\d+.\d+).app)/, + /(?Xcode_(?\d+(\.\d+)?)\.app)/, ); /** From fe45268b48e1b79045143cdfc794a9f5d1544751 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 19 Oct 2026 12:28:54 +0100 Subject: [PATCH 123/174] Use `lstat` instead of `stat` --- lib/entry-points.js | 10 ++++- src/languages/traced.test.ts | 33 +++++++++------ src/platform.test.ts | 81 ++++++++++++++++++++++++++---------- src/platform.ts | 10 ++++- 4 files changed, 97 insertions(+), 37 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 8070d8e1a3..20469ed709 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -183445,7 +183445,15 @@ var XCODE_APP_FILENAME_PATTERN = new RegExp( ); function xcodeVersion(logger2) { try { - const stats = import_fs.default.statSync(XCODE_SELECT_LINK_PATH); + const stats = import_fs.default.lstatSync(XCODE_SELECT_LINK_PATH, { + throwIfNoEntry: false + }); + if (stats === void 0) { + logger2.debug( + `'${XCODE_SELECT_LINK_PATH}' does not exist. Xcode is probably not installed.` + ); + return void 0; + } if (!stats.isSymbolicLink()) { logger2.warning( `${XCODE_SELECT_LINK_PATH} exists, but is not a symbolic link.` diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index 5a45788f5b..777fdccc35 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -294,8 +294,8 @@ test.serial( const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - const statSync = sinon - .stub(fs, "statSync") + const lstatSync = sinon + .stub(fs, "lstatSync") .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") @@ -322,8 +322,11 @@ test.serial( codeql, ); - t.is(statSync.callCount, 1); - t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(lstatSync.callCount, 1); + t.deepEqual(lstatSync.args[0], [ + XCODE_SELECT_LINK_PATH, + { throwIfNoEntry: false }, + ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); @@ -344,8 +347,8 @@ test.serial( const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - const statSync = sinon - .stub(fs, "statSync") + const lstatSync = sinon + .stub(fs, "lstatSync") .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") @@ -372,8 +375,11 @@ test.serial( codeql, ); - t.is(statSync.callCount, 1); - t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(lstatSync.callCount, 1); + t.deepEqual(lstatSync.args[0], [ + XCODE_SELECT_LINK_PATH, + { throwIfNoEntry: false }, + ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); @@ -414,8 +420,8 @@ test.serial( const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - const statSync = sinon - .stub(fs, "statSync") + const lstatSync = sinon + .stub(fs, "lstatSync") .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") @@ -447,8 +453,11 @@ test.serial( ), ); - t.is(statSync.callCount, 1); - t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(lstatSync.callCount, 1); + t.deepEqual(lstatSync.args[0], [ + XCODE_SELECT_LINK_PATH, + { throwIfNoEntry: false }, + ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); diff --git a/src/platform.test.ts b/src/platform.test.ts index 3fdeec2752..6688f66af8 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -74,11 +74,31 @@ test("macOSVersion returns semver if parsing succeeds", (t) => { test.serial("xcodeVersion returns undefined if symlink doesn't exist", (t) => { const logger = new RecordingLogger(); - const statSync = sinon.stub(fs, "statSync").throws(new Error("ENOENT")); + const lstatSync = sinon.stub(fs, "lstatSync").returns(undefined); t.is(xcodeVersion(logger), undefined); - t.is(statSync.callCount, 1); - t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(lstatSync.callCount, 1); + t.deepEqual(lstatSync.args[0], [ + XCODE_SELECT_LINK_PATH, + { throwIfNoEntry: false }, + ]); + + checkExpectedLogMessages(t, logger.messages, [ + "Xcode is probably not installed.", + ]); +}); + +test.serial("xcodeVersion returns undefined if lstatSync throws", (t) => { + const logger = new RecordingLogger(); + + const lstatSync = sinon.stub(fs, "lstatSync").throws(new Error("ENOENT")); + + t.is(xcodeVersion(logger), undefined); + t.is(lstatSync.callCount, 1); + t.deepEqual(lstatSync.args[0], [ + XCODE_SELECT_LINK_PATH, + { throwIfNoEntry: false }, + ]); checkExpectedLogMessages(t, logger.messages, [ "Unable to determine Xcode version: ENOENT", @@ -88,13 +108,16 @@ test.serial("xcodeVersion returns undefined if symlink doesn't exist", (t) => { test.serial("xcodeVersion returns undefined if file is not a symlink", (t) => { const logger = new RecordingLogger(); - const statSync = sinon - .stub(fs, "statSync") + const lstatSync = sinon + .stub(fs, "lstatSync") .returns({ isSymbolicLink: () => false } as fs.Stats); t.is(xcodeVersion(logger), undefined); - t.is(statSync.callCount, 1); - t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(lstatSync.callCount, 1); + t.deepEqual(lstatSync.args[0], [ + XCODE_SELECT_LINK_PATH, + { throwIfNoEntry: false }, + ]); checkExpectedLogMessages(t, logger.messages, [ "exists, but is not a symbolic link", @@ -106,14 +129,17 @@ test.serial( (t) => { const logger = new RecordingLogger(); - const statSync = sinon - .stub(fs, "statSync") + const lstatSync = sinon + .stub(fs, "lstatSync") .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon.stub(fs, "readlinkSync").returns(""); t.is(xcodeVersion(logger), undefined); - t.is(statSync.callCount, 1); - t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(lstatSync.callCount, 1); + t.deepEqual(lstatSync.args[0], [ + XCODE_SELECT_LINK_PATH, + { throwIfNoEntry: false }, + ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); @@ -128,16 +154,19 @@ test.serial( (t) => { const logger = new RecordingLogger(); - const statSync = sinon - .stub(fs, "statSync") + const lstatSync = sinon + .stub(fs, "lstatSync") .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") .returns("/Applications/Xcode.app/Contents/Developer"); t.is(xcodeVersion(logger), undefined); - t.is(statSync.callCount, 1); - t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(lstatSync.callCount, 1); + t.deepEqual(lstatSync.args[0], [ + XCODE_SELECT_LINK_PATH, + { throwIfNoEntry: false }, + ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); @@ -150,16 +179,19 @@ test.serial( test.serial("xcodeVersion returns undefined if match can't be parsed", (t) => { const logger = new RecordingLogger(); - const statSync = sinon - .stub(fs, "statSync") + const lstatSync = sinon + .stub(fs, "lstatSync") .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") .returns("/Applications/Xcode_00.0.app/Contents/Developer"); t.is(xcodeVersion(logger), undefined); - t.is(statSync.callCount, 1); - t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(lstatSync.callCount, 1); + t.deepEqual(lstatSync.args[0], [ + XCODE_SELECT_LINK_PATH, + { throwIfNoEntry: false }, + ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); @@ -171,8 +203,8 @@ test.serial("xcodeVersion returns undefined if match can't be parsed", (t) => { test.serial("xcodeVersion returns version from resolved path", (t) => { const logger = new RecordingLogger(); - const statSync = sinon - .stub(fs, "statSync") + const lstatSync = sinon + .stub(fs, "lstatSync") .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") @@ -185,8 +217,11 @@ test.serial("xcodeVersion returns version from resolved path", (t) => { t.is(result.minor, 4); } - t.is(statSync.callCount, 1); - t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(lstatSync.callCount, 1); + t.deepEqual(lstatSync.args[0], [ + XCODE_SELECT_LINK_PATH, + { throwIfNoEntry: false }, + ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); }); diff --git a/src/platform.ts b/src/platform.ts index 22c8f6a935..9492dff192 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -76,8 +76,16 @@ export function xcodeVersion(logger: Logger): semver.SemVer | undefined { // Stat the expected symbolic link to check that it exists and is a symbolic link. // The `readlinkSync` call below returns an empty string in either case and so // this check allows us to distinguish between the two cases. - const stats = fs.statSync(XCODE_SELECT_LINK_PATH); + const stats = fs.lstatSync(XCODE_SELECT_LINK_PATH, { + throwIfNoEntry: false, + }); + if (stats === undefined) { + logger.debug( + `'${XCODE_SELECT_LINK_PATH}' does not exist. Xcode is probably not installed.`, + ); + return undefined; + } if (!stats.isSymbolicLink()) { logger.warning( `${XCODE_SELECT_LINK_PATH} exists, but is not a symbolic link.`, From 97b90230e5548caa99fc7149ed756e3b4e71a1ca Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 28 Oct 2026 12:27:23 +0000 Subject: [PATCH 124/174] Clarify that we are looking at the Darwin version --- lib/entry-points.js | 18 +++++++++--------- src/languages/swift.ts | 8 ++++---- src/languages/traced.test.ts | 4 ++-- src/languages/traced.ts | 16 ++++++++-------- src/platform.test.ts | 14 +++++++------- src/platform.ts | 7 ++++--- 6 files changed, 34 insertions(+), 33 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 20469ed709..46736e51e8 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -183429,7 +183429,7 @@ function getBundlePlatform(platform2 = process.platform, arch2 = process.arch) { return void 0; } } -function macOSVersion(action) { +function darwinVersion(action) { if (action.platform !== "darwin") { return void 0; } @@ -193906,14 +193906,14 @@ async function getToolsInput(action, repositoryProperties) { } // src/languages/swift.ts -async function checkSwiftCompatibility(config, codeql, macosVersion) { +async function checkSwiftCompatibility(config, codeql, darwinVersion2) { if (!config.languages.includes("swift" /* swift */)) { return; } if (await codeql.supportsFeature("swiftSupportsAllPlatforms" /* SwiftSupportsAllPlatforms */)) { return; } - if (macosVersion === void 0) { + if (darwinVersion2 === void 0) { throw new ConfigurationError( `Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.` ); @@ -193921,15 +193921,15 @@ async function checkSwiftCompatibility(config, codeql, macosVersion) { } // src/languages/traced.ts -var UNSUPPORTED_MACOS_FOR_TRACED = 27; +var UNSUPPORTED_DARWIN_FOR_TRACED = 27; var UNSUPPORTED_XCODE_FOR_TRACED = 27; function handleUnsupportedVersion(logger2, config, skipUnsupportedTracedAnalysis, product, version) { const baseMessage = [ - `Traced analysis is not supported on ${product} ${UNSUPPORTED_MACOS_FOR_TRACED} or above.`, - `Configure your analysis to run on macOS ${UNSUPPORTED_MACOS_FOR_TRACED - 1} or below`, + `Traced analysis is not supported on ${product} ${UNSUPPORTED_DARWIN_FOR_TRACED} or above.`, + `Configure your analysis to run on macOS ${UNSUPPORTED_DARWIN_FOR_TRACED - 1} or below`, `and XCode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.` ].join(" "); - const attributeName = product === "macOS" ? "macOSVersion" : "xcodeVersion"; + const attributeName = product === "macOS" ? "darwinVersion" : "xcodeVersion"; for (const language of config.languages) { addDiagnostic( config, @@ -193975,7 +193975,7 @@ async function hasTracedLanguages(config, codeql) { return false; } async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { - const version = macOSVersion(action); + const version = darwinVersion(action); await checkSwiftCompatibility(config, codeql, version); if (config.buildMode !== void 0 && config.buildMode === "none") { return; @@ -193990,7 +193990,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { action.logger.warning( `Unable to determine version of macOS, got: ${version}` ); - } else if (version !== void 0 && version.major >= UNSUPPORTED_MACOS_FOR_TRACED) { + } else if (version !== void 0 && version.major >= UNSUPPORTED_DARWIN_FOR_TRACED) { handleUnsupportedVersion( action.logger, config, diff --git a/src/languages/swift.ts b/src/languages/swift.ts index 45ca87416a..e617684e05 100644 --- a/src/languages/swift.ts +++ b/src/languages/swift.ts @@ -12,14 +12,14 @@ import { BuiltInLanguage } from "."; * * @param config The Action configuration. * @param codeql The {@link CodeQL} CLI instance. - * @param macosVersion The version of macOS, if any. + * @param darwinVersion The version of the Darwin kernel on macOS, if any. * * @throws {ConfigurationError} If Swift analysis is not possible on the current runner. */ export async function checkSwiftCompatibility( config: ActionConfig<"languages">, codeql: CodeQL, - macosVersion: SemVer | string | undefined, + darwinVersion: SemVer | string | undefined, ) { // The checks are not relevant if we are not trying to analyse Swift. if (!config.languages.includes(BuiltInLanguage.swift)) { @@ -33,8 +33,8 @@ export async function checkSwiftCompatibility( return; } - // If `macosVersion` is undefined, then we are not on macOS and Swift analysis is unsupported. - if (macosVersion === undefined) { + // If `darwinVersion` is undefined, then we are not on macOS and Swift analysis is unsupported. + if (darwinVersion === undefined) { throw new ConfigurationError( `Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.`, ); diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index 777fdccc35..3b8a3b3315 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -209,7 +209,7 @@ test.serial( { attributes: { languages: [BuiltInLanguage.swift], - macOSVersion: "27.0.0", + darwinVersion: "27.0.0", }, severity: "warning", source: { @@ -268,7 +268,7 @@ test.serial( { attributes: { languages: [BuiltInLanguage.swift], - macOSVersion: "27.0.0", + darwinVersion: "27.0.0", }, severity: "error", source: { diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 0de35b589e..605c99f2ec 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -6,13 +6,13 @@ import type { ActionConfig } from "../config/action-config"; import { addDiagnostic, makeDiagnostic } from "../diagnostics"; import { DocUrl } from "../doc-url"; import { Feature } from "../feature-flags"; -import { macOSVersion, xcodeVersion } from "../platform"; +import { darwinVersion, xcodeVersion } from "../platform"; import { ConfigurationError } from "../util"; import { checkSwiftCompatibility } from "./swift"; /** macOS 27 and above do not support traced extraction. */ -export const UNSUPPORTED_MACOS_FOR_TRACED = 27; +export const UNSUPPORTED_DARWIN_FOR_TRACED = 27; /** Xcode 27 and above do not support traced extraction. */ export const UNSUPPORTED_XCODE_FOR_TRACED = 27; @@ -36,12 +36,12 @@ function handleUnsupportedVersion( version: semver.SemVer, ) { const baseMessage = [ - `Traced analysis is not supported on ${product} ${UNSUPPORTED_MACOS_FOR_TRACED} or above.`, - `Configure your analysis to run on macOS ${UNSUPPORTED_MACOS_FOR_TRACED - 1} or below`, + `Traced analysis is not supported on ${product} ${UNSUPPORTED_DARWIN_FOR_TRACED} or above.`, + `Configure your analysis to run on macOS ${UNSUPPORTED_DARWIN_FOR_TRACED - 1} or below`, `and XCode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.`, ].join(" "); - const attributeName = product === "macOS" ? "macOSVersion" : "xcodeVersion"; + const attributeName = product === "macOS" ? "darwinVersion" : "xcodeVersion"; // Create a diagnostic that will show up on the TSP. for (const language of config.languages) { @@ -115,8 +115,8 @@ export async function checkRunnerSupportsTracedAnalysis( config: ActionConfig<"languages" | "dbLocation" | "tempDir">, codeql: CodeQL, ) { - // Try to get the macOS version. - const version = macOSVersion(action); + // Try to get the Darwin version on macOS. + const version = darwinVersion(action); // Perform some initial, Swift-specific checks. await checkSwiftCompatibility(config, codeql, version); @@ -141,7 +141,7 @@ export async function checkRunnerSupportsTracedAnalysis( ); } else if ( version !== undefined && - version.major >= UNSUPPORTED_MACOS_FOR_TRACED + version.major >= UNSUPPORTED_DARWIN_FOR_TRACED ) { handleUnsupportedVersion( action.logger, diff --git a/src/platform.test.ts b/src/platform.test.ts index 6688f66af8..e3a3b77833 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -6,7 +6,7 @@ import * as sinon from "sinon"; import { BundlePlatform, getBundlePlatform, - macOSVersion, + darwinVersion, XCODE_SELECT_LINK_PATH, xcodeVersion, } from "./platform"; @@ -36,25 +36,25 @@ for (const [platform, arch, expected] of [ const platforms: NodeJS.Platform[] = ["linux", "win32", "freebsd"]; for (const platform of platforms) { - test(`macOSVersion returns undefined on ${platform}`, (t) => { - t.is(macOSVersion(initAllState({ platform })), undefined); + test(`darwinVersion returns undefined on ${platform}`, (t) => { + t.is(darwinVersion(initAllState({ platform })), undefined); }); } -test("macOSVersion returns raw string if semver parsing fails", (t) => { +test("darwinVersion returns raw string if semver parsing fails", (t) => { const invalidSemVer = "sealOS-2026"; t.is( - macOSVersion( + darwinVersion( initAllState({ platform: "darwin", osRelease: invalidSemVer }), ), invalidSemVer, ); }); -test("macOSVersion returns semver if parsing succeeds", (t) => { +test("darwinVersion returns semver if parsing succeeds", (t) => { const validSemVer = "27.0.1"; - const version = macOSVersion( + const version = darwinVersion( initAllState({ platform: "darwin", osRelease: validSemVer }), ); diff --git a/src/platform.ts b/src/platform.ts index 9492dff192..22df77c1ac 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -33,13 +33,14 @@ export function getBundlePlatform( } /** - * Tries to determine the version of macOS. + * Tries to determine the version of the kernel on macOS. We approximate this based on the + * Darwin kernel version so that we don't have to launch an external process. * * @returns * The version as either a semantic version object, the raw version string * if it is not a semantic version, or `undefined` if we are not on macOS. */ -export function macOSVersion( +export function darwinVersion( action: ActionState<["Base"]>, ): semver.SemVer | string | undefined { // Skip if we are not running on macOS. @@ -47,7 +48,7 @@ export function macOSVersion( return undefined; } - // Try to parse the OS version string. + // Try to parse the kernel version string. const version = semver.parse(action.osRelease); if (version === null) { From eff66e8fb1ca04760c1502ab0cc2b7b647122e7f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 28 Oct 2026 12:30:50 +0000 Subject: [PATCH 125/174] Make Xcode regex more flexible --- lib/entry-points.js | 2 +- src/platform.test.ts | 29 +++++++++++++++++++++++++++++ src/platform.ts | 2 +- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 46736e51e8..7f5c3b447f 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -183441,7 +183441,7 @@ function darwinVersion(action) { } var XCODE_SELECT_LINK_PATH = "/private/var/db/xcode_select_link"; var XCODE_APP_FILENAME_PATTERN = new RegExp( - /(?Xcode_(?\d+(\.\d+)?)\.app)/ + /(?Xcode_(?\d+(\.\d+)?).*\.app)/ ); function xcodeVersion(logger2) { try { diff --git a/src/platform.test.ts b/src/platform.test.ts index e3a3b77833..d6439226e8 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -251,3 +251,32 @@ test.serial("xcodeVersion returns major version from resolved path", (t) => { t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); }); + +test.serial( + "xcodeVersion allows more version components in resolved path", + (t) => { + const logger = new RecordingLogger(); + + const lstatSync = sinon + .stub(fs, "lstatSync") + .returns({ isSymbolicLink: () => true } as fs.Stats); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .returns("/Applications/Xcode_16.5.9.app/Contents/Developer"); + + const result = xcodeVersion(logger); + + if (t.truthy(result)) { + t.is(result.major, 16); + t.is(result.minor, 5); + } + + t.is(lstatSync.callCount, 1); + t.deepEqual(lstatSync.args[0], [ + XCODE_SELECT_LINK_PATH, + { throwIfNoEntry: false }, + ]); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); + }, +); diff --git a/src/platform.ts b/src/platform.ts index 22df77c1ac..4d17b33e93 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -63,7 +63,7 @@ export const XCODE_SELECT_LINK_PATH = "/private/var/db/xcode_select_link"; /** The pattern we expect to find in the Xcode path. */ export const XCODE_APP_FILENAME_PATTERN = new RegExp( - /(?Xcode_(?\d+(\.\d+)?)\.app)/, + /(?Xcode_(?\d+(\.\d+)?).*\.app)/, ); /** From 5547a3567fb87b011ac795c9af6ff35fc3f9ba76 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 28 Oct 2026 12:34:08 +0000 Subject: [PATCH 126/174] Only create diagnostics for traced languages --- lib/entry-points.js | 14 +++++++++----- src/languages/traced.ts | 21 ++++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 7f5c3b447f..e025efbdd3 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -193923,14 +193923,14 @@ async function checkSwiftCompatibility(config, codeql, darwinVersion2) { // src/languages/traced.ts var UNSUPPORTED_DARWIN_FOR_TRACED = 27; var UNSUPPORTED_XCODE_FOR_TRACED = 27; -function handleUnsupportedVersion(logger2, config, skipUnsupportedTracedAnalysis, product, version) { +function handleUnsupportedVersion(logger2, config, tracedLanguages, skipUnsupportedTracedAnalysis, product, version) { const baseMessage = [ `Traced analysis is not supported on ${product} ${UNSUPPORTED_DARWIN_FOR_TRACED} or above.`, `Configure your analysis to run on macOS ${UNSUPPORTED_DARWIN_FOR_TRACED - 1} or below`, `and XCode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.` ].join(" "); const attributeName = product === "macOS" ? "darwinVersion" : "xcodeVersion"; - for (const language of config.languages) { + for (const language of tracedLanguages) { addDiagnostic( config, language, @@ -193967,12 +193967,13 @@ function handleUnsupportedVersion(logger2, config, skipUnsupportedTracedAnalysis } } async function hasTracedLanguages(config, codeql) { + const tracedLanguages = []; for (const language of config.languages) { if (await codeql.isTracedLanguage(language)) { - return true; + tracedLanguages.push(language); } } - return false; + return tracedLanguages; } async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { const version = darwinVersion(action); @@ -193980,7 +193981,8 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { if (config.buildMode !== void 0 && config.buildMode === "none") { return; } - if (!await hasTracedLanguages(config, codeql)) { + const tracedLanguages = await hasTracedLanguages(config, codeql); + if (tracedLanguages.length === 0) { return; } const skipUnsupportedTracedAnalysis = await action.features.getValue( @@ -193994,6 +193996,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { handleUnsupportedVersion( action.logger, config, + tracedLanguages, skipUnsupportedTracedAnalysis, "macOS", version @@ -194004,6 +194007,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { handleUnsupportedVersion( action.logger, config, + tracedLanguages, skipUnsupportedTracedAnalysis, "Xcode", xcodeVer diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 605c99f2ec..85f9ddc1b7 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -24,13 +24,15 @@ export const UNSUPPORTED_XCODE_FOR_TRACED = 27; * * @param logger The logger to use. * @param config The CodeQL Action configuration. + * @param tracedLanguages Traced languages that are configured for analysis. * @param skipUnsupportedTracedAnalysis Whether this is a fatal error. * @param product The product that the version is unsupported of. * @param version The unsupported version. */ function handleUnsupportedVersion( logger: Logger, - config: ActionConfig<"languages" | "dbLocation" | "tempDir">, + config: ActionConfig<"dbLocation" | "tempDir">, + tracedLanguages: string[], skipUnsupportedTracedAnalysis: boolean, product: "macOS" | "Xcode", version: semver.SemVer, @@ -44,7 +46,7 @@ function handleUnsupportedVersion( const attributeName = product === "macOS" ? "darwinVersion" : "xcodeVersion"; // Create a diagnostic that will show up on the TSP. - for (const language of config.languages) { + for (const language of tracedLanguages) { addDiagnostic( config, language, @@ -89,20 +91,22 @@ function handleUnsupportedVersion( } /** - * Decides whether {@link config} has any traced languages by looking for tracer + * Returns traced languages from {@link config} by looking for tracer * configurations in the {@link codeql} CLI installation. */ export async function hasTracedLanguages( config: ActionConfig<"languages">, codeql: CodeQL, -): Promise { +): Promise { + const tracedLanguages: string[] = []; + for (const language of config.languages) { if (await codeql.isTracedLanguage(language)) { - return true; + tracedLanguages.push(language); } } - return false; + return tracedLanguages; } /** @@ -127,7 +131,8 @@ export async function checkRunnerSupportsTracedAnalysis( } // If none of the languages are traced, then we can skip the compatibility checks below as well. - if (!(await hasTracedLanguages(config, codeql))) { + const tracedLanguages = await hasTracedLanguages(config, codeql); + if (tracedLanguages.length === 0) { return; } @@ -146,6 +151,7 @@ export async function checkRunnerSupportsTracedAnalysis( handleUnsupportedVersion( action.logger, config, + tracedLanguages, skipUnsupportedTracedAnalysis, "macOS", version, @@ -163,6 +169,7 @@ export async function checkRunnerSupportsTracedAnalysis( handleUnsupportedVersion( action.logger, config, + tracedLanguages, skipUnsupportedTracedAnalysis, "Xcode", xcodeVer, From 84e80cea7e53b85af543663db34bc71d690c1af0 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 28 Oct 2026 12:35:56 +0000 Subject: [PATCH 127/174] Avoid producing the same-ish message twice --- lib/entry-points.js | 1 + src/languages/traced.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/lib/entry-points.js b/lib/entry-points.js index e025efbdd3..50b1cb5f91 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -194001,6 +194001,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { "macOS", version ); + return; } const xcodeVer = xcodeVersion(action.logger); if (xcodeVer !== void 0 && xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED) { diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 85f9ddc1b7..35347a0c52 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -156,6 +156,10 @@ export async function checkRunnerSupportsTracedAnalysis( "macOS", version, ); + + // Return early so that we don't end up producing more-or-less the same log message/diagnostic + // twice. The ones for macOS already comment on the Xcode requirement. + return; } // Determining whether the Xcode version is supported only makes sense on macOS, so we only do it From 87ef6f583408767b23acadf31ce1de192253039a Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 28 Oct 2026 12:37:40 +0000 Subject: [PATCH 128/174] Return early if we are not on macOS to avoid unnecessary work --- lib/entry-points.js | 5 ++++- src/languages/traced.ts | 10 ++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 50b1cb5f91..46bd1301f3 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -193981,6 +193981,9 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { if (config.buildMode !== void 0 && config.buildMode === "none") { return; } + if (version === void 0) { + return; + } const tracedLanguages = await hasTracedLanguages(config, codeql); if (tracedLanguages.length === 0) { return; @@ -193992,7 +193995,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { action.logger.warning( `Unable to determine version of macOS, got: ${version}` ); - } else if (version !== void 0 && version.major >= UNSUPPORTED_DARWIN_FOR_TRACED) { + } else if (version.major >= UNSUPPORTED_DARWIN_FOR_TRACED) { handleUnsupportedVersion( action.logger, config, diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 35347a0c52..f2b23170b9 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -130,6 +130,11 @@ export async function checkRunnerSupportsTracedAnalysis( return; } + // These checks don't apply if we are not on macOS. + if (version === undefined) { + return; + } + // If none of the languages are traced, then we can skip the compatibility checks below as well. const tracedLanguages = await hasTracedLanguages(config, codeql); if (tracedLanguages.length === 0) { @@ -144,10 +149,7 @@ export async function checkRunnerSupportsTracedAnalysis( action.logger.warning( `Unable to determine version of macOS, got: ${version}`, ); - } else if ( - version !== undefined && - version.major >= UNSUPPORTED_DARWIN_FOR_TRACED - ) { + } else if (version.major >= UNSUPPORTED_DARWIN_FOR_TRACED) { handleUnsupportedVersion( action.logger, config, From 17685f3ebaf046ff756eaca3182ef7fc6211be85 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 23:00:47 +0100 Subject: [PATCH 129/174] Add e2e test --- .github/workflows/__unsupported-macos.yml | 134 ++++++++++++++++++++++ pr-checks/checks/unsupported-macos.yml | 66 +++++++++++ pr-checks/sync.ts | 9 +- 3 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/__unsupported-macos.yml create mode 100644 pr-checks/checks/unsupported-macos.yml diff --git a/.github/workflows/__unsupported-macos.yml b/.github/workflows/__unsupported-macos.yml new file mode 100644 index 0000000000..e5a7842fe7 --- /dev/null +++ b/.github/workflows/__unsupported-macos.yml @@ -0,0 +1,134 @@ +# Warning: This file is generated automatically, and should not be modified. +# Instead, please modify the template in the pr-checks directory and run: +# pr-checks/sync.sh +# to regenerate this file. + +name: PR Check - Unsupported macOS +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GO111MODULE: auto +on: + push: + branches: + - main + - releases/v* + pull_request: {} + merge_group: + types: + - checks_requested + schedule: + - cron: '0 5 * * *' + workflow_dispatch: + inputs: {} + workflow_call: + inputs: {} +defaults: + run: + shell: bash +concurrency: + cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} + group: unsupported-macos-${{github.ref}} +jobs: + unsupported-macos: + strategy: + fail-fast: false + matrix: + include: + - os: xcode-27 + version: linked + - os: xcode-27 + version: nightly-latest + name: Unsupported macOS + if: github.triggering_actor != 'dependabot[bot]' + permissions: + contents: read + security-events: read + timeout-minutes: 45 + runs-on: ${{ matrix.os }} + steps: + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Install Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: 20.x + cache: npm + - name: Install newer npm + run: npm install -g npm@11.19.1 + - name: Install dependencies + run: npm ci + - name: Prepare test + id: prepare-test + uses: ./.github/actions/prepare-test + with: + version: ${{ matrix.version }} + use-all-platform-bundle: 'false' + setup-kotlin: 'true' + - name: Check xcode_select_link + run: | + readlink /private/var/db/xcode_select_link + file -h /private/var/db/xcode_select_link + + - uses: ./../action/init + id: init + continue-on-error: true + env: + CODEQL_ACTION_SKIP_UNSUPPORTED_TRACED_ANALYSIS: true + with: + languages: swift + tools: ${{ steps.prepare-test.outputs.tools-url }} + + - name: Analyze + # We could run `analyze` here from `./../analyze`, but `getAnalyzeActionName` in `workflow.ts` + # can't cope with that unless we introduce a different testing environment. Since this step + # would just fail on `xcode-27` anyway, we just skip it instead. + if: false + uses: ./analyze + with: + category: '/test-codeql-version:${{ matrix.version }}' + env: + CODEQL_ACTION_SKIP_GENERATE_FAILED_SARIF: false + CODEQL_ACTION_SKIP_SARIF_UPLOAD: true + CODEQL_ACTION_TESTING_ENVIRONMENT: codeql-action-pr-checks + CODEQL_ACTION_TEST_MODE: true + unsupported-macos-sarif-checks: + if: github.triggering_actor != 'dependabot[bot]' + needs: + - unsupported-macos + permissions: + contents: read + security-events: read + timeout-minutes: 5 + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Install Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: 20.x + cache: npm + - name: Install newer npm + run: npm install -g npm@11.19.1 + - name: Install dependencies + run: npm ci + - name: Download workflow artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: test-mode-sarif-* + path: sarif + + - name: List artifact contents + run: ls -laR ./sarif + + - name: Check diagnostics appear in SARIF + env: + SARIF_PATH: "./sarif/" + DIAGNOSTIC_ID: "codeql-action/unsupported-traced-analysis-macos" + DIAGNOSTIC_NAME: "Traced analysis is not supported on this version of macOS" + EXPECTED_LOCATIONS: "0" + EXPECTED_MESSAGE: | + Traced analysis is not supported on macOS 27 or above. + run: npx tsx ./pr-checks/check-diagnostics.ts + env: + CODEQL_ACTION_TEST_MODE: true diff --git a/pr-checks/checks/unsupported-macos.yml b/pr-checks/checks/unsupported-macos.yml new file mode 100644 index 0000000000..04392ae290 --- /dev/null +++ b/pr-checks/checks/unsupported-macos.yml @@ -0,0 +1,66 @@ +name: "Unsupported macOS" +description: "Tests that unsupported macOS versions are detected and result in appropriate diagnostics." +versions: + - linked + - nightly-latest +installNode: true + +operatingSystems: + - os: macos + runner-image: xcode-27 + +env: + # Allow the failed SARIF file to be generated. + CODEQL_ACTION_SKIP_GENERATE_FAILED_SARIF: false + # But don't actually upload it. + CODEQL_ACTION_SKIP_SARIF_UPLOAD: true + # Mark telemetry for this workflow so it can be treated separately. + CODEQL_ACTION_TESTING_ENVIRONMENT: codeql-action-pr-checks + +steps: + - name: Check xcode_select_link + run: | + readlink /private/var/db/xcode_select_link + file -h /private/var/db/xcode_select_link + + - uses: ./../action/init + id: init + continue-on-error: true + env: + CODEQL_ACTION_SKIP_UNSUPPORTED_TRACED_ANALYSIS: true + with: + languages: swift + tools: ${{ steps.prepare-test.outputs.tools-url }} + + - name: Analyze + # We could run `analyze` here from `./../analyze`, but `getAnalyzeActionName` in `workflow.ts` + # can't cope with that unless we introduce a different testing environment. Since this step + # would just fail on `xcode-27` anyway, we just skip it instead. + if: false + uses: ./analyze + with: + category: "/test-codeql-version:${{ matrix.version }}" + +validationJobs: + unsupported-macos-sarif-checks: + checkout: true + installNode: true + steps: + - name: Download workflow artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: test-mode-sarif-* + path: sarif + + - name: List artifact contents + run: ls -laR ./sarif + + - name: Check diagnostics appear in SARIF + env: + SARIF_PATH: "./sarif/" + DIAGNOSTIC_ID: "codeql-action/unsupported-traced-analysis-macos" + DIAGNOSTIC_NAME: "Traced analysis is not supported on this version of macOS" + EXPECTED_LOCATIONS: "0" + EXPECTED_MESSAGE: | + Traced analysis is not supported on macOS 27 or above. + run: npx tsx ./pr-checks/check-diagnostics.ts diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index c205e94a72..8874655e59 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -124,6 +124,8 @@ interface JobSpecification { type ValidationJobSpecification = JobSpecification & { checkout?: boolean; + /** Optional condition for the validation job. */ + if?: string; }; /** Describes language/framework-specific steps and inputs. */ @@ -666,9 +668,14 @@ function generateValidationJob( // Add the generated steps in front of the ones from the specification. specSteps.items.unshift(...checkoutStep, ...steps); + const baseCondition = "github.triggering_actor != 'dependabot[bot]'"; + const validationJob: Record = { name: jobSpecification.name, - if: "github.triggering_actor != 'dependabot[bot]'", + if: + jobSpecification.if !== undefined + ? `${baseCondition} && ${jobSpecification.if}` + : baseCondition, needs: [checkName], permissions: { contents: "read", From 202d9f1a6b796b5ff7e36bef959c35f56a832c0f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 28 Oct 2026 13:13:15 +0000 Subject: [PATCH 130/174] Add `CheckUnsupportedTracedAnalysis` FF --- lib/entry-points.js | 5 +++++ src/feature-flags.ts | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/entry-points.js b/lib/entry-points.js index 46bd1301f3..4deb1fb26b 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -179727,6 +179727,11 @@ var featureConfig = { envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS", minimumVersion: void 0 }, + ["check_unsupported_traced_analysis" /* CheckUnsupportedTracedAnalysis */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_CHECK_UNSUPPORTED_TRACED_ANALYSIS", + minimumVersion: void 0 + }, ["config_file_repository_property" /* ConfigFileRepositoryProperty */]: { defaultValue: false, envVar: "CODEQL_ACTION_CONFIG_FILE_REPOSITORY_PROPERTY", diff --git a/src/feature-flags.ts b/src/feature-flags.ts index e326b08e6e..36fccc6aab 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -74,6 +74,11 @@ export enum Feature { AllowMergeConfigFiles = "allow_merge_config_files", /** Controls whether we allow multiple values for the `analysis-kinds` input. */ AllowMultipleAnalysisKinds = "allow_multiple_analysis_kinds", + /** + * Whether to check for unsupported traced analysis. Primarily intended as an override to disable + * the check if it causes problems somehow. + */ + CheckUnsupportedTracedAnalysis = "check_unsupported_traced_analysis", /** Whether to allow the `config-file` input to be specified via a repository property. */ ConfigFileRepositoryProperty = "config_file_repository_property", CppDependencyInstallation = "cpp_dependency_installation_enabled", @@ -197,6 +202,11 @@ export const featureConfig = { envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS", minimumVersion: undefined, }, + [Feature.CheckUnsupportedTracedAnalysis]: { + defaultValue: false, + envVar: "CODEQL_ACTION_CHECK_UNSUPPORTED_TRACED_ANALYSIS", + minimumVersion: undefined, + }, [Feature.ConfigFileRepositoryProperty]: { defaultValue: false, envVar: "CODEQL_ACTION_CONFIG_FILE_REPOSITORY_PROPERTY", From 99971dd136aecba06b031d54b7695b66be2b5ce2 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 28 Oct 2026 13:19:40 +0000 Subject: [PATCH 131/174] Gate checks behind FF --- lib/entry-points.js | 3 +++ src/languages/traced.test.ts | 49 ++++++++++++++++++++++++++++++++++-- src/languages/traced.ts | 7 ++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 4deb1fb26b..d01987f6ff 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -193983,6 +193983,9 @@ async function hasTracedLanguages(config, codeql) { async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { const version = darwinVersion(action); await checkSwiftCompatibility(config, codeql, version); + if (!await action.features.getValue("check_unsupported_traced_analysis" /* CheckUnsupportedTracedAnalysis */)) { + return; + } if (config.buildMode !== void 0 && config.buildMode === "none") { return; } diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index 3b8a3b3315..2faf7f1ba6 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -139,11 +139,43 @@ for (const nonTracedLanguage of nonTracedLanguages) { })); } +test("checkRunnerSupportsTracedAnalysis doesn't perform checks if FF is not enabled", async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + const features = createFeatures([]); + + const codeql = await getCodeQLWithTracedStub( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + await checkRunnerSupportsTracedAnalysis( + initAllState({ + logger, + platform: "darwin", + osRelease: "unexpected", + env, + features, + }), + createTestConfig({ languages: [BuiltInLanguage.go] }), + codeql, + ); + + checkUnexpectedLogMessages(t, logger.messages, [ + "Unable to determine version of macOS, got: unexpected", + ]); + })); + test("checkRunnerSupportsTracedAnalysis warns if version string is not a semver", async (t) => withTmpDir(async (tmpDir) => { const logger = new RecordingLogger(); const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", @@ -158,6 +190,7 @@ test("checkRunnerSupportsTracedAnalysis warns if version string is not a semver" platform: "darwin", osRelease: "unexpected", env, + features, }), createTestConfig({ languages: [BuiltInLanguage.go] }), codeql, @@ -174,6 +207,7 @@ test.serial( async (t) => withTmpDir(async (tmpDir) => { const logger = new RecordingLogger(); + const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); @@ -193,6 +227,7 @@ test.serial( platform: "darwin", osRelease: "27.0.0", env, + features, }), config, codeql, @@ -235,7 +270,10 @@ test.serial( const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - const features = createFeatures([Feature.SkipUnsupportedTracedAnalysis]); + const features = createFeatures([ + Feature.CheckUnsupportedTracedAnalysis, + Feature.SkipUnsupportedTracedAnalysis, + ]); const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", @@ -293,6 +331,7 @@ test.serial( const logger = new RecordingLogger(); const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); const lstatSync = sinon .stub(fs, "lstatSync") @@ -317,6 +356,7 @@ test.serial( platform: "darwin", osRelease: "26.0.0", env, + features, }), config, codeql, @@ -346,6 +386,7 @@ test.serial( const logger = new RecordingLogger(); const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); const lstatSync = sinon .stub(fs, "lstatSync") @@ -370,6 +411,7 @@ test.serial( platform: "darwin", osRelease: "26.0.0", env, + features, }), config, codeql, @@ -427,7 +469,10 @@ test.serial( .stub(fs, "readlinkSync") .returns("/Applications/Xcode_27.0.app/Contents/Developer"); - const features = createFeatures([Feature.SkipUnsupportedTracedAnalysis]); + const features = createFeatures([ + Feature.CheckUnsupportedTracedAnalysis, + Feature.SkipUnsupportedTracedAnalysis, + ]); const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", diff --git a/src/languages/traced.ts b/src/languages/traced.ts index f2b23170b9..2d0c5f9347 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -125,6 +125,13 @@ export async function checkRunnerSupportsTracedAnalysis( // Perform some initial, Swift-specific checks. await checkSwiftCompatibility(config, codeql, version); + // Skip the checks for unsupported traced analysis if the FF is not enabled. + if ( + !(await action.features.getValue(Feature.CheckUnsupportedTracedAnalysis)) + ) { + return; + } + // `build-mode: none` doesn't use the tracer, so it is always supported. if (config.buildMode !== undefined && config.buildMode === "none") { return; From ad2b30ba0f9445c3e95f18c6909e39f6b4500540 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 28 Oct 2026 13:29:20 +0000 Subject: [PATCH 132/174] Use new FF in e2e test --- .github/workflows/__unsupported-macos.yml | 1 + pr-checks/checks/unsupported-macos.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/__unsupported-macos.yml b/.github/workflows/__unsupported-macos.yml index e5a7842fe7..8f4a473df5 100644 --- a/.github/workflows/__unsupported-macos.yml +++ b/.github/workflows/__unsupported-macos.yml @@ -73,6 +73,7 @@ jobs: id: init continue-on-error: true env: + CODEQL_ACTION_CHECK_UNSUPPORTED_TRACED_ANALYSIS: true CODEQL_ACTION_SKIP_UNSUPPORTED_TRACED_ANALYSIS: true with: languages: swift diff --git a/pr-checks/checks/unsupported-macos.yml b/pr-checks/checks/unsupported-macos.yml index 04392ae290..d417e6082d 100644 --- a/pr-checks/checks/unsupported-macos.yml +++ b/pr-checks/checks/unsupported-macos.yml @@ -27,6 +27,7 @@ steps: id: init continue-on-error: true env: + CODEQL_ACTION_CHECK_UNSUPPORTED_TRACED_ANALYSIS: true CODEQL_ACTION_SKIP_UNSUPPORTED_TRACED_ANALYSIS: true with: languages: swift From 2d85855366ad654e675845d39b1c2be6d1be0ccd Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 28 Oct 2026 15:59:59 +0000 Subject: [PATCH 133/174] Refactor `defaultRunnerImages` into `DEFAULT_RUNNER_IMAGES` map --- pr-checks/sync.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index c205e94a72..02125504af 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -43,6 +43,13 @@ type WorkflowInputs = Partial>; /** An operating system identifier. */ type OperatingSystemIdentifier = "ubuntu" | "macos" | "windows"; +/** Mapping from {@link OperatingSystemIdentifier} to default runner image labels. */ +const DEFAULT_RUNNER_IMAGES: Record = { + ubuntu: "ubuntu-latest", + macos: "macos-latest", + windows: "windows-latest", +}; + /** * Represents an operating system matrix entry for a generated PR check workflow. * @@ -414,12 +421,6 @@ function generateJobMatrix( ); } - const defaultRunnerImages = [ - "ubuntu-latest", - "macos-latest", - "windows-latest", - ]; - for (const operatingSystemConfig of operatingSystems) { const operatingSystem = typeof operatingSystemConfig === "string" @@ -449,7 +450,7 @@ function generateJobMatrix( const runnerImagesForOs = typeof operatingSystemConfig === "string" || operatingSystemConfig["runner-image"] === undefined - ? defaultRunnerImages.filter((image) => + ? Object.values(DEFAULT_RUNNER_IMAGES).filter((image) => image.startsWith(operatingSystem), ) : [operatingSystemConfig["runner-image"]]; From 4b0f575f5a3e9f27dfda63b4c90a52c412ab23c9 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 28 Oct 2026 16:00:58 +0000 Subject: [PATCH 134/174] Replace floating occurrences of `ubuntu-latest` --- pr-checks/sync.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index 02125504af..e84aaa0acc 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -463,7 +463,7 @@ function generateJobMatrix( // is removed from `defaultTestVersions`. const requiresOlderRunnerImage: DefaultTestVersion = "stable-v2.20.7"; if ( - runnerImage === "ubuntu-latest" && + runnerImage === DEFAULT_RUNNER_IMAGES["ubuntu"] && version === requiresOlderRunnerImage ) { matrix.push({ os: "ubuntu-24.04", version }); @@ -676,7 +676,7 @@ function generateValidationJob( "security-events": "read", }, "timeout-minutes": 5, - "runs-on": "ubuntu-latest", + "runs-on": DEFAULT_RUNNER_IMAGES["ubuntu"], steps: specSteps, }; From b8e636781a1e3c68def5687b19d0fea3100bc7ef Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 28 Oct 2026 16:02:23 +0000 Subject: [PATCH 135/174] Replace `-latest` with current, corresponding labels in `DEFAULT_RUNNER_IMAGES` --- .github/workflows/__all-platform-bundle.yml | 4 ++-- .github/workflows/__analysis-kinds.yml | 16 +++++++-------- .github/workflows/__analyze-ref-input.yml | 2 +- .github/workflows/__autobuild-action.yml | 6 +++--- ...obuild-direct-tracing-with-working-dir.yml | 8 ++++---- .github/workflows/__autobuild-working-dir.yml | 2 +- .github/workflows/__build-mode-autobuild.yml | 8 ++++---- .github/workflows/__build-mode-manual.yml | 2 +- .github/workflows/__build-mode-none.yml | 4 ++-- .github/workflows/__build-mode-rollback.yml | 2 +- .github/workflows/__bundle-from-nightly.yml | 2 +- .github/workflows/__bundle-from-toolcache.yml | 2 +- .github/workflows/__bundle-toolcache.yml | 6 +++--- .../workflows/__cleanup-db-cluster-dir.yml | 2 +- .github/workflows/__config-export.yml | 4 ++-- .github/workflows/__config-input.yml | 2 +- .github/workflows/__cpp-deptrace-disabled.yml | 6 +++--- .../__cpp-deptrace-enabled-on-macos.yml | 4 ++-- .github/workflows/__cpp-deptrace-enabled.yml | 6 +++--- .github/workflows/__diagnostics-export.yml | 4 ++-- .../workflows/__diagnostics-without-db.yml | 4 ++-- .../__export-file-baseline-information.yml | 6 +++--- .github/workflows/__extractor-ram-threads.yml | 2 +- .github/workflows/__global-proxy.yml | 4 ++-- .github/workflows/__go-custom-queries.yml | 4 ++-- ...indirect-tracing-workaround-diagnostic.yml | 2 +- ...ect-tracing-workaround-no-file-program.yml | 2 +- .../__go-indirect-tracing-workaround.yml | 2 +- .../workflows/__go-tracing-autobuilder.yml | 20 +++++++++---------- .../__go-tracing-custom-build-steps.yml | 20 +++++++++---------- .../__go-tracing-legacy-workflow.yml | 20 +++++++++---------- .github/workflows/__init-with-registries.yml | 6 +++--- .../workflows/__javascript-source-root.yml | 6 +++--- .github/workflows/__job-run-uuid-sarif.yml | 2 +- .github/workflows/__language-aliases.yml | 2 +- .github/workflows/__local-bundle.yml | 2 +- .../workflows/__multi-language-autodetect.yml | 16 +++++++-------- .github/workflows/__overlay-init-fallback.yml | 4 ++-- ...ackaging-codescanning-config-inputs-js.yml | 6 +++--- .../__packaging-config-inputs-js.yml | 6 +++--- .github/workflows/__packaging-config-js.yml | 6 +++--- .github/workflows/__packaging-inputs-js.yml | 6 +++--- .github/workflows/__remote-config.yml | 4 ++-- .../__resolve-environment-action.yml | 6 +++--- .github/workflows/__ruby.yml | 12 +++++------ .github/workflows/__rust.yml | 8 ++++---- .github/workflows/__split-workflow.yml | 12 +++++------ .github/workflows/__start-proxy.yml | 6 +++--- .github/workflows/__submit-sarif-failure.yml | 6 +++--- .github/workflows/__unset-environment.yml | 4 ++-- .github/workflows/__upload-ref-sha-input.yml | 2 +- .github/workflows/__upload-sarif.yml | 6 +++--- .github/workflows/__with-checkout-path.yml | 2 +- pr-checks/sync.ts | 6 +++--- 54 files changed, 157 insertions(+), 157 deletions(-) diff --git a/.github/workflows/__all-platform-bundle.yml b/.github/workflows/__all-platform-bundle.yml index 4846d13f1e..a0272b3e45 100644 --- a/.github/workflows/__all-platform-bundle.yml +++ b/.github/workflows/__all-platform-bundle.yml @@ -54,11 +54,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest - os: macos-latest-xlarge version: nightly-latest - - os: windows-latest + - os: windows-2025 version: nightly-latest name: All-platform bundle if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__analysis-kinds.yml b/.github/workflows/__analysis-kinds.yml index 5353c10956..a0a14c8c5e 100644 --- a/.github/workflows/__analysis-kinds.yml +++ b/.github/workflows/__analysis-kinds.yml @@ -34,28 +34,28 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked analysis-kinds: code-scanning - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked analysis-kinds: code-quality - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked analysis-kinds: code-scanning,code-quality - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked analysis-kinds: risk-assessment - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest analysis-kinds: code-scanning - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest analysis-kinds: code-quality - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest analysis-kinds: code-scanning,code-quality - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest analysis-kinds: risk-assessment name: Analysis kinds diff --git a/.github/workflows/__analyze-ref-input.yml b/.github/workflows/__analyze-ref-input.yml index 7341a41740..1e899b39a6 100644 --- a/.github/workflows/__analyze-ref-input.yml +++ b/.github/workflows/__analyze-ref-input.yml @@ -54,7 +54,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: default name: "Analyze: 'ref' and 'sha' from inputs" if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__autobuild-action.yml b/.github/workflows/__autobuild-action.yml index 730a387f90..fcf5094e11 100644 --- a/.github/workflows/__autobuild-action.yml +++ b/.github/workflows/__autobuild-action.yml @@ -44,11 +44,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: macos-latest + - os: macos-26 version: linked - - os: windows-latest + - os: windows-2025 version: linked name: autobuild-action if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml b/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml index bad4921eb8..d0830846a0 100644 --- a/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml +++ b/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml @@ -44,13 +44,13 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: windows-latest + - os: windows-2025 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest - - os: windows-latest + - os: windows-2025 version: nightly-latest name: Autobuild direct tracing (custom working directory) if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__autobuild-working-dir.yml b/.github/workflows/__autobuild-working-dir.yml index fac4ef9f54..489e4ed7d9 100644 --- a/.github/workflows/__autobuild-working-dir.yml +++ b/.github/workflows/__autobuild-working-dir.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked name: Autobuild working directory if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__build-mode-autobuild.yml b/.github/workflows/__build-mode-autobuild.yml index 76e3f348ad..2e89573366 100644 --- a/.github/workflows/__build-mode-autobuild.yml +++ b/.github/workflows/__build-mode-autobuild.yml @@ -44,13 +44,13 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: windows-latest + - os: windows-2025 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest - - os: windows-latest + - os: windows-2025 version: nightly-latest name: Build mode autobuild if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__build-mode-manual.yml b/.github/workflows/__build-mode-manual.yml index bfe92c55ea..14cdc5654e 100644 --- a/.github/workflows/__build-mode-manual.yml +++ b/.github/workflows/__build-mode-manual.yml @@ -54,7 +54,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Build mode manual if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__build-mode-none.yml b/.github/workflows/__build-mode-none.yml index da7aa76383..690e7fe38c 100644 --- a/.github/workflows/__build-mode-none.yml +++ b/.github/workflows/__build-mode-none.yml @@ -34,9 +34,9 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Build mode none if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__build-mode-rollback.yml b/.github/workflows/__build-mode-rollback.yml index fcc77ea36e..0e53ba1959 100644 --- a/.github/workflows/__build-mode-rollback.yml +++ b/.github/workflows/__build-mode-rollback.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Build mode rollback if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__bundle-from-nightly.yml b/.github/workflows/__bundle-from-nightly.yml index 6c414fb67e..08fb849598 100644 --- a/.github/workflows/__bundle-from-nightly.yml +++ b/.github/workflows/__bundle-from-nightly.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked name: 'Bundle: From nightly' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__bundle-from-toolcache.yml b/.github/workflows/__bundle-from-toolcache.yml index 1a307ba2ee..79245e6651 100644 --- a/.github/workflows/__bundle-from-toolcache.yml +++ b/.github/workflows/__bundle-from-toolcache.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: toolcache name: 'Bundle: From toolcache' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__bundle-toolcache.yml b/.github/workflows/__bundle-toolcache.yml index 96a901cf34..3f72648207 100644 --- a/.github/workflows/__bundle-toolcache.yml +++ b/.github/workflows/__bundle-toolcache.yml @@ -34,11 +34,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: macos-latest + - os: macos-26 version: linked - - os: windows-latest + - os: windows-2025 version: linked name: 'Bundle: Caching checks' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__cleanup-db-cluster-dir.yml b/.github/workflows/__cleanup-db-cluster-dir.yml index 3153041401..904932cedf 100644 --- a/.github/workflows/__cleanup-db-cluster-dir.yml +++ b/.github/workflows/__cleanup-db-cluster-dir.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked name: Clean up database cluster directory if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__config-export.yml b/.github/workflows/__config-export.yml index f8d0ecf0c6..82ff82728c 100644 --- a/.github/workflows/__config-export.yml +++ b/.github/workflows/__config-export.yml @@ -34,9 +34,9 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Config export if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__config-input.yml b/.github/workflows/__config-input.yml index c015526c68..8c4544a7a5 100644 --- a/.github/workflows/__config-input.yml +++ b/.github/workflows/__config-input.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked name: Config input if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__cpp-deptrace-disabled.yml b/.github/workflows/__cpp-deptrace-disabled.yml index e2434f4256..d84e322986 100644 --- a/.github/workflows/__cpp-deptrace-disabled.yml +++ b/.github/workflows/__cpp-deptrace-disabled.yml @@ -34,11 +34,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: 'C/C++: disabling autoinstalling dependencies (Linux)' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__cpp-deptrace-enabled-on-macos.yml b/.github/workflows/__cpp-deptrace-enabled-on-macos.yml index 344ed8d1ea..cca23b0895 100644 --- a/.github/workflows/__cpp-deptrace-enabled-on-macos.yml +++ b/.github/workflows/__cpp-deptrace-enabled-on-macos.yml @@ -34,9 +34,9 @@ jobs: fail-fast: false matrix: include: - - os: macos-latest + - os: macos-26 version: linked - - os: macos-latest + - os: macos-26 version: nightly-latest name: 'C/C++: autoinstalling dependencies is skipped (macOS)' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__cpp-deptrace-enabled.yml b/.github/workflows/__cpp-deptrace-enabled.yml index ab1a70584b..51ce4401cb 100644 --- a/.github/workflows/__cpp-deptrace-enabled.yml +++ b/.github/workflows/__cpp-deptrace-enabled.yml @@ -34,11 +34,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: 'C/C++: autoinstalling dependencies (Linux)' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__diagnostics-export.yml b/.github/workflows/__diagnostics-export.yml index 930ff0eb4c..d6494ac789 100644 --- a/.github/workflows/__diagnostics-export.yml +++ b/.github/workflows/__diagnostics-export.yml @@ -34,9 +34,9 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Diagnostic export if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__diagnostics-without-db.yml b/.github/workflows/__diagnostics-without-db.yml index 44c24fa683..9a1c3d6d9f 100644 --- a/.github/workflows/__diagnostics-without-db.yml +++ b/.github/workflows/__diagnostics-without-db.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked name: Diagnostic export without database if: github.triggering_actor != 'dependabot[bot]' @@ -108,7 +108,7 @@ jobs: contents: read security-events: read timeout-minutes: 5 - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 diff --git a/.github/workflows/__export-file-baseline-information.yml b/.github/workflows/__export-file-baseline-information.yml index a3b68dbb25..0500122576 100644 --- a/.github/workflows/__export-file-baseline-information.yml +++ b/.github/workflows/__export-file-baseline-information.yml @@ -54,11 +54,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest - - os: macos-latest + - os: macos-26 version: nightly-latest - - os: windows-latest + - os: windows-2025 version: nightly-latest name: Export file baseline information if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__extractor-ram-threads.yml b/.github/workflows/__extractor-ram-threads.yml index 5bd5c8b940..2275921b4f 100644 --- a/.github/workflows/__extractor-ram-threads.yml +++ b/.github/workflows/__extractor-ram-threads.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked name: Extractor ram and threads options test if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__global-proxy.yml b/.github/workflows/__global-proxy.yml index 9244d1fc8f..0c68f0dd4e 100644 --- a/.github/workflows/__global-proxy.yml +++ b/.github/workflows/__global-proxy.yml @@ -34,9 +34,9 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Proxy test if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__go-custom-queries.yml b/.github/workflows/__go-custom-queries.yml index 7b4cd1305b..db7acd1ac6 100644 --- a/.github/workflows/__go-custom-queries.yml +++ b/.github/workflows/__go-custom-queries.yml @@ -54,9 +54,9 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: 'Go: Custom queries' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__go-indirect-tracing-workaround-diagnostic.yml b/.github/workflows/__go-indirect-tracing-workaround-diagnostic.yml index 968caf1e69..b570ae4a64 100644 --- a/.github/workflows/__go-indirect-tracing-workaround-diagnostic.yml +++ b/.github/workflows/__go-indirect-tracing-workaround-diagnostic.yml @@ -44,7 +44,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: default name: 'Go: diagnostic when Go is changed after init step' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__go-indirect-tracing-workaround-no-file-program.yml b/.github/workflows/__go-indirect-tracing-workaround-no-file-program.yml index 0f13b1e663..137583625f 100644 --- a/.github/workflows/__go-indirect-tracing-workaround-no-file-program.yml +++ b/.github/workflows/__go-indirect-tracing-workaround-no-file-program.yml @@ -44,7 +44,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: default name: 'Go: diagnostic when `file` is not installed' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__go-indirect-tracing-workaround.yml b/.github/workflows/__go-indirect-tracing-workaround.yml index 915835c2ab..5296e5837f 100644 --- a/.github/workflows/__go-indirect-tracing-workaround.yml +++ b/.github/workflows/__go-indirect-tracing-workaround.yml @@ -44,7 +44,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: default name: 'Go: workaround for indirect tracing' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__go-tracing-autobuilder.yml b/.github/workflows/__go-tracing-autobuilder.yml index a36cc43a7b..2b7005698e 100644 --- a/.github/workflows/__go-tracing-autobuilder.yml +++ b/.github/workflows/__go-tracing-autobuilder.yml @@ -46,25 +46,25 @@ jobs: include: - os: ubuntu-24.04 version: stable-v2.20.7 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.21.4 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.22.4 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.23.9 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.24.3 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.25.6 - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: macos-latest + - os: macos-26 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest - - os: macos-latest + - os: macos-26 version: nightly-latest name: 'Go: tracing with autobuilder step' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__go-tracing-custom-build-steps.yml b/.github/workflows/__go-tracing-custom-build-steps.yml index 05fedfb035..cc14651de7 100644 --- a/.github/workflows/__go-tracing-custom-build-steps.yml +++ b/.github/workflows/__go-tracing-custom-build-steps.yml @@ -46,25 +46,25 @@ jobs: include: - os: ubuntu-24.04 version: stable-v2.20.7 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.21.4 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.22.4 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.23.9 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.24.3 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.25.6 - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: macos-latest + - os: macos-26 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest - - os: macos-latest + - os: macos-26 version: nightly-latest name: 'Go: tracing with custom build steps' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__go-tracing-legacy-workflow.yml b/.github/workflows/__go-tracing-legacy-workflow.yml index 276d4cfda5..df62bf53cc 100644 --- a/.github/workflows/__go-tracing-legacy-workflow.yml +++ b/.github/workflows/__go-tracing-legacy-workflow.yml @@ -46,25 +46,25 @@ jobs: include: - os: ubuntu-24.04 version: stable-v2.20.7 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.21.4 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.22.4 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.23.9 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.24.3 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.25.6 - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: macos-latest + - os: macos-26 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest - - os: macos-latest + - os: macos-26 version: nightly-latest name: 'Go: tracing with legacy workflow' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__init-with-registries.yml b/.github/workflows/__init-with-registries.yml index 9293dcc196..2e36baddc4 100644 --- a/.github/workflows/__init-with-registries.yml +++ b/.github/workflows/__init-with-registries.yml @@ -34,11 +34,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: 'Packaging: Download using registries' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__javascript-source-root.yml b/.github/workflows/__javascript-source-root.yml index 1dcbd38a85..08c68e6f94 100644 --- a/.github/workflows/__javascript-source-root.yml +++ b/.github/workflows/__javascript-source-root.yml @@ -34,11 +34,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Custom source root if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__job-run-uuid-sarif.yml b/.github/workflows/__job-run-uuid-sarif.yml index b24ab39005..5d49830cdd 100644 --- a/.github/workflows/__job-run-uuid-sarif.yml +++ b/.github/workflows/__job-run-uuid-sarif.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Job run UUID added to SARIF if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__language-aliases.yml b/.github/workflows/__language-aliases.yml index 731d975ce3..1e5c17395a 100644 --- a/.github/workflows/__language-aliases.yml +++ b/.github/workflows/__language-aliases.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked name: Language aliases if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__local-bundle.yml b/.github/workflows/__local-bundle.yml index 8e448080f3..bc384bdf11 100644 --- a/.github/workflows/__local-bundle.yml +++ b/.github/workflows/__local-bundle.yml @@ -54,7 +54,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked name: Local CodeQL bundle if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__multi-language-autodetect.yml b/.github/workflows/__multi-language-autodetect.yml index d54b24a1ef..fd252d6de7 100644 --- a/.github/workflows/__multi-language-autodetect.yml +++ b/.github/workflows/__multi-language-autodetect.yml @@ -58,35 +58,35 @@ jobs: version: stable-v2.20.7 - os: macos-15-xlarge version: stable-v2.20.7 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.21.4 - os: macos-15-xlarge version: stable-v2.21.4 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.22.4 - os: macos-15-xlarge version: stable-v2.22.4 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.23.9 - os: macos-latest-xlarge version: stable-v2.23.9 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.24.3 - os: macos-latest-xlarge version: stable-v2.24.3 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.25.6 - os: macos-latest-xlarge version: stable-v2.25.6 - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - os: macos-latest-xlarge version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - os: macos-latest-xlarge version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest - os: macos-latest-xlarge version: nightly-latest diff --git a/.github/workflows/__overlay-init-fallback.yml b/.github/workflows/__overlay-init-fallback.yml index b6c99efcef..a2c320fb53 100644 --- a/.github/workflows/__overlay-init-fallback.yml +++ b/.github/workflows/__overlay-init-fallback.yml @@ -34,9 +34,9 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Overlay database init fallback if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__packaging-codescanning-config-inputs-js.yml b/.github/workflows/__packaging-codescanning-config-inputs-js.yml index 27139c8314..070d7e3910 100644 --- a/.github/workflows/__packaging-codescanning-config-inputs-js.yml +++ b/.github/workflows/__packaging-codescanning-config-inputs-js.yml @@ -54,11 +54,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: 'Packaging: Config and input passed to the CLI' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__packaging-config-inputs-js.yml b/.github/workflows/__packaging-config-inputs-js.yml index 9844c43488..3465616dbf 100644 --- a/.github/workflows/__packaging-config-inputs-js.yml +++ b/.github/workflows/__packaging-config-inputs-js.yml @@ -54,11 +54,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: 'Packaging: Config and input' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__packaging-config-js.yml b/.github/workflows/__packaging-config-js.yml index 916e892765..0e7b828c0a 100644 --- a/.github/workflows/__packaging-config-js.yml +++ b/.github/workflows/__packaging-config-js.yml @@ -54,11 +54,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: 'Packaging: Config file' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__packaging-inputs-js.yml b/.github/workflows/__packaging-inputs-js.yml index 01ddb5dc31..80c792069d 100644 --- a/.github/workflows/__packaging-inputs-js.yml +++ b/.github/workflows/__packaging-inputs-js.yml @@ -54,11 +54,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: 'Packaging: Action input' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__remote-config.yml b/.github/workflows/__remote-config.yml index e1c3785f6a..485a4904c8 100644 --- a/.github/workflows/__remote-config.yml +++ b/.github/workflows/__remote-config.yml @@ -54,9 +54,9 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Remote config file if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__resolve-environment-action.yml b/.github/workflows/__resolve-environment-action.yml index 11a31fdabc..7a4e284d72 100644 --- a/.github/workflows/__resolve-environment-action.yml +++ b/.github/workflows/__resolve-environment-action.yml @@ -34,11 +34,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Resolve environment if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__ruby.yml b/.github/workflows/__ruby.yml index 98f8ec6a2a..833e49789e 100644 --- a/.github/workflows/__ruby.yml +++ b/.github/workflows/__ruby.yml @@ -34,17 +34,17 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: macos-latest + - os: macos-26 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: macos-latest + - os: macos-26 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest - - os: macos-latest + - os: macos-26 version: nightly-latest name: Ruby analysis if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__rust.yml b/.github/workflows/__rust.yml index d3b5a8a5b8..83cdbf6771 100644 --- a/.github/workflows/__rust.yml +++ b/.github/workflows/__rust.yml @@ -36,13 +36,13 @@ jobs: include: - os: ubuntu-24.04 version: stable-v2.20.7 - - os: ubuntu-latest + - os: ubuntu-26.04 version: stable-v2.22.1 - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Rust analysis if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__split-workflow.yml b/.github/workflows/__split-workflow.yml index 512058a598..0cb63b85cc 100644 --- a/.github/workflows/__split-workflow.yml +++ b/.github/workflows/__split-workflow.yml @@ -54,17 +54,17 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: macos-latest + - os: macos-26 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: macos-latest + - os: macos-26 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest - - os: macos-latest + - os: macos-26 version: nightly-latest name: Split workflow if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__start-proxy.yml b/.github/workflows/__start-proxy.yml index edc6aa1cc5..e6906cbc3c 100644 --- a/.github/workflows/__start-proxy.yml +++ b/.github/workflows/__start-proxy.yml @@ -34,11 +34,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: macos-latest + - os: macos-26 version: linked - - os: windows-latest + - os: windows-2025 version: linked name: Start proxy if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__submit-sarif-failure.yml b/.github/workflows/__submit-sarif-failure.yml index 36f7be4eb6..b7edd62fc0 100644 --- a/.github/workflows/__submit-sarif-failure.yml +++ b/.github/workflows/__submit-sarif-failure.yml @@ -34,11 +34,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Submit SARIF after failure if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__unset-environment.yml b/.github/workflows/__unset-environment.yml index 8a8796d9a7..6ef214e709 100644 --- a/.github/workflows/__unset-environment.yml +++ b/.github/workflows/__unset-environment.yml @@ -54,9 +54,9 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: Test unsetting environment variables if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__upload-ref-sha-input.yml b/.github/workflows/__upload-ref-sha-input.yml index 76e8f4e3c0..079bc65971 100644 --- a/.github/workflows/__upload-ref-sha-input.yml +++ b/.github/workflows/__upload-ref-sha-input.yml @@ -54,7 +54,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: default name: "Upload-sarif: 'ref' and 'sha' from inputs" if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__upload-sarif.yml b/.github/workflows/__upload-sarif.yml index 77fa0264e5..c35fb3f597 100644 --- a/.github/workflows/__upload-sarif.yml +++ b/.github/workflows/__upload-sarif.yml @@ -54,13 +54,13 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: default analysis-kinds: code-scanning - - os: ubuntu-latest + - os: ubuntu-26.04 version: default analysis-kinds: code-quality - - os: ubuntu-latest + - os: ubuntu-26.04 version: default analysis-kinds: code-scanning,code-quality name: Test different uses of `upload-sarif` diff --git a/.github/workflows/__with-checkout-path.yml b/.github/workflows/__with-checkout-path.yml index 59a8edc9d1..d3c849c739 100644 --- a/.github/workflows/__with-checkout-path.yml +++ b/.github/workflows/__with-checkout-path.yml @@ -54,7 +54,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked name: Use a custom `checkout_path` if: github.triggering_actor != 'dependabot[bot]' diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index e84aaa0acc..2a42eef294 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -45,9 +45,9 @@ type OperatingSystemIdentifier = "ubuntu" | "macos" | "windows"; /** Mapping from {@link OperatingSystemIdentifier} to default runner image labels. */ const DEFAULT_RUNNER_IMAGES: Record = { - ubuntu: "ubuntu-latest", - macos: "macos-latest", - windows: "windows-latest", + ubuntu: "ubuntu-26.04", + macos: "macos-26", + windows: "windows-2025", }; /** From 1965df5d2e9d0b97868061130a01aebfaeceeb0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Oct 2026 17:54:58 +0000 Subject: [PATCH 136/174] Bump the npm-minor group across 1 directory with 2 updates Bumps the npm-minor group with 2 updates in the / directory: [@types/sinon](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/sinon) and [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc). Updates `@types/sinon` from 22.0.0 to 22.0.1 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/sinon) Updates `eslint-plugin-jsdoc` from 65.3.15 to 65.4.0 - [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases) - [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v65.3.15...v65.4.0) --- updated-dependencies: - dependency-name: "@types/sinon" dependency-version: 22.0.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-minor - dependency-name: eslint-plugin-jsdoc dependency-version: 65.4.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 172 +++++++++++++++++++++++++++++++--------------- package.json | 4 +- 2 files changed, 120 insertions(+), 56 deletions(-) diff --git a/package-lock.json b/package-lock.json index 935bceb5d3..c1a68345a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,14 +50,14 @@ "@types/node-forge": "^1.3.14", "@types/sarif": "^2.1.7", "@types/semver": "^7.8.0", - "@types/sinon": "^22.0.0", + "@types/sinon": "^22.0.1", "ava": "^6.4.1", "esbuild": "^0.28.2", "eslint": "^9.39.5", "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-github": "^6.1.2", "eslint-plugin-import-x": "^4.17.1", - "eslint-plugin-jsdoc": "^65.3.15", + "eslint-plugin-jsdoc": "^65.4.0", "eslint-plugin-no-async-foreach": "^0.1.1", "glob": "^13.0.6", "globals": "^17.13.0", @@ -67,14 +67,6 @@ "typescript-eslint": "^8.72.0" } }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@actions/artifact": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-5.0.3.tgz", @@ -958,18 +950,89 @@ "tslib": "^2.4.0" } }, + "node_modules/@es-joy/escodegen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@es-joy/escodegen/-/escodegen-4.2.0.tgz", + "integrity": "sha512-jWqqS3StW6vGwJeT8yu6alS4nipOBi3kD/pR63+9hG2NfGafCJ4viDME15mVf+fyupyptcUJDXfv63gFF5Gzfg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@es-joy/estraverse": "^7.1.1", + "@es-joy/jsdoccomment": "^0.62.0", + "esprima": "^4.0.1", + "esutils": "^2.0.3", + "optionator": "^0.9.4" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.7.6" + } + }, + "node_modules/@es-joy/escodegen/node_modules/@es-joy/jsdoccomment": { + "version": "0.62.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.62.0.tgz", + "integrity": "sha512-yWi6sm7INEwnfS7IJvE0dU+RTrwzLPFcY7e7eGpu/l5Q9lWfQ2ROwZ0qVnc242jw2TUPsfHX3XMIISkGBv57RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.8", + "@typescript-eslint/types": "^8.44.1", + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~5.9.0" + }, + "engines": { + "node": ">=20.11.0" + } + }, + "node_modules/@es-joy/escodegen/node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/@es-joy/escodegen/node_modules/jsdoc-type-pratt-parser": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-5.9.2.tgz", + "integrity": "sha512-TYzkACp/wPvDJLRY7qpHXtrhgwoAaojIOnLaaVNi+AbPU2u1kkjfKd9hXXTq0qSAGsyYXvwUXt99h9I5iCmjjw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@es-joy/estraverse": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@es-joy/estraverse/-/estraverse-7.1.1.tgz", + "integrity": "sha512-h2d737iS0LFAqypZOmXizu54qAbHofI/RpD30Zom03O6BCXKHuFevWKPcGarZbGq82h7qSBb5G6kLdhTMO+caw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.98.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.98.0.tgz", - "integrity": "sha512-QS+b7I2aaSM+gZfDz1b9E4B367JJ2qTjFXRKF289iKkh9sYdZ21Q5MiF/Duzouy3J0C4VhM3I/8f2F4+zT8gYQ==", + "version": "0.100.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.100.0.tgz", + "integrity": "sha512-QuIT5kMg3XWN22Wa1rcXmR/GkfSg6Ygs/ikMiHihdSpu+o3O59LygkFV9srKa5xHplBFwNd5ZCo3bywL4k7qMQ==", "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.9", - "@typescript-eslint/types": "^8.70.0", + "@typescript-eslint/types": "^8.72.0", "comment-parser": "1.4.9", "esquery": "^1.7.0", - "jsdoc-type-pratt-parser": "~9.2.2" + "jsdoc-type-pratt-parser": "~9.3.0" }, "engines": { "node": "^22.22.2 || >=24.15.0" @@ -2681,20 +2744,15 @@ "license": "MIT" }, "node_modules/@types/sinon": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-22.0.0.tgz", - "integrity": "sha512-TDbVpbccc2HfiqHR09Argj3mHV1KMW7sCCKj52fsl8lbRLkEn7fB1966EWhOKWUBcqfBueZuPoA7/OK1CKiy3g==", + "version": "22.0.1", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-22.0.1.tgz", + "integrity": "sha512-MThluJXPmpBY+Z5S3565F2z+hjkCXnBrr36j2mitVQ7JUtxA+A+YQhs+0Q6J8jxb0SVJvydO+6NWfj9EBzpiBQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/sinonjs__fake-timers": "*" + "@sinonjs/fake-timers": "^15.4.0" } }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.2", - "dev": true, - "license": "MIT" - }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -5366,15 +5424,16 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "65.3.15", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-65.3.15.tgz", - "integrity": "sha512-cpU66X+daaX2X6cndE0grdLAIlodysI3KuUEdrJd6FvQHuuYOOvMRAdy8ToYjyJrsoUv0fXkMclA5RM5kaipMw==", + "version": "65.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-65.4.0.tgz", + "integrity": "sha512-bRiU6LfCFmLL7GuePKvA6ZIcXLonhZGCg2TgQLmkcExeVdAirQp2Hsf3xeSUTmlKwAAsREVEOLbZYD8F7oA69g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.98.0", + "@es-joy/escodegen": "^4.2.0", + "@es-joy/jsdoccomment": "~0.100.0", "@es-joy/resolve.exports": "1.2.0", - "@typescript-eslint/utils": "^8.70.1", + "@typescript-eslint/utils": "^8.72.0", "are-docs-informative": "^0.1.1", "comment-parser": "1.4.9", "debug": "^4.4.3", @@ -7170,36 +7229,18 @@ } }, "node_modules/jsdoc-type-pratt-parser": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-9.2.2.tgz", - "integrity": "sha512-eFY7Rlscvv/BpY6UsVsjKwMhu1tJO/F4U/vC9g3yeRy/JqszuO1UP6Vdq+85G+3FP6fEw/sWR8a5ftPFY86csw==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-9.3.0.tgz", + "integrity": "sha512-JZ8lKMCZXDlM1jAjAK5tTmtFJtgv6iFQQfjE3Fza6jBRACUueaEXLY17n1u05JO1lcPkNxgP+ddEDtiPsk5ktg==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "^1.0.9", - "@types/node": "^26.4.0" + "@types/estree": "^1.0.9" }, "engines": { "node": "^22.22.2 || >=24.15.0" } }, - "node_modules/jsdoc-type-pratt-parser/node_modules/@types/node": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.2.tgz", - "integrity": "sha512-X1P21scMv4zGKLYqjdGjaKa7COa0RKVYYZZN/NfvLQ1JegxFhdhpZG/Lyn8AXx6CDUavKAd11v6BvfpkDByK8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~8.9.0" - } - }, - "node_modules/jsdoc-type-pratt-parser/node_modules/undici-types": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz", - "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==", - "dev": true, - "license": "MIT" - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -8360,16 +8401,18 @@ } }, "node_modules/optionator": { - "version": "0.9.3", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -9293,6 +9336,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/spdx-exceptions": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", @@ -10326,6 +10380,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index 46b00e9474..cfd11dd5ff 100644 --- a/package.json +++ b/package.json @@ -58,14 +58,14 @@ "@types/node-forge": "^1.3.14", "@types/sarif": "^2.1.7", "@types/semver": "^7.8.0", - "@types/sinon": "^22.0.0", + "@types/sinon": "^22.0.1", "ava": "^6.4.1", "esbuild": "^0.28.2", "eslint": "^9.39.5", "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-github": "^6.1.2", "eslint-plugin-import-x": "^4.17.1", - "eslint-plugin-jsdoc": "^65.3.15", + "eslint-plugin-jsdoc": "^65.4.0", "eslint-plugin-no-async-foreach": "^0.1.1", "glob": "^13.0.6", "globals": "^17.13.0", From 1b863a0649bc929f1ab7bd5535ab820ef770dbbe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Oct 2026 17:57:49 +0000 Subject: [PATCH 137/174] Bump actions/setup-python Bumps the actions-minor group with 1 update in the /.github/workflows directory: [actions/setup-python](https://github.com/actions/setup-python). Updates `actions/setup-python` from 7.0.0 to 7.1.0 - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/5fda3b95a4ea91299a34e894583c3862153e4b97...6d4fd22b20465ccc0f7354476588e8df7c9ca0e0) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: 7.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/__multi-language-autodetect.yml | 2 +- .github/workflows/python312-windows.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/__multi-language-autodetect.yml b/.github/workflows/__multi-language-autodetect.yml index d54b24a1ef..5c376f3d4f 100644 --- a/.github/workflows/__multi-language-autodetect.yml +++ b/.github/workflows/__multi-language-autodetect.yml @@ -121,7 +121,7 @@ jobs: # imports `importlib._bootstrap._ERR_MSG`, which those Python versions no longer define. # See https://github.com/github/codeql-action/pull/3212 if: matrix.version != 'nightly-latest' && matrix.version != 'linked' - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0 with: python-version: '3.13.15' diff --git a/.github/workflows/python312-windows.yml b/.github/workflows/python312-windows.yml index ab169499e2..1d9107e30f 100644 --- a/.github/workflows/python312-windows.yml +++ b/.github/workflows/python312-windows.yml @@ -32,7 +32,7 @@ jobs: runs-on: windows-latest steps: - - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0 with: python-version: 3.12 From 931fefa4bce096a5d58773d83cf7773e46281d9e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Oct 2026 18:00:29 +0000 Subject: [PATCH 138/174] Rebuild --- pr-checks/checks/multi-language-autodetect.yml | 2 +- pr-checks/sync.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pr-checks/checks/multi-language-autodetect.yml b/pr-checks/checks/multi-language-autodetect.yml index c826ac7ea6..6b422531f9 100644 --- a/pr-checks/checks/multi-language-autodetect.yml +++ b/pr-checks/checks/multi-language-autodetect.yml @@ -23,7 +23,7 @@ steps: # imports `importlib._bootstrap._ERR_MSG`, which those Python versions no longer define. # See https://github.com/github/codeql-action/pull/3212 if: matrix.version != 'nightly-latest' && matrix.version != 'linked' - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0 with: python-version: "3.13.15" diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index c205e94a72..81fbc8e29e 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -296,8 +296,8 @@ const languageSetups: LanguageSetups = { name: "Install Python", uses: pinnedUses( "actions/setup-python", - "5fda3b95a4ea91299a34e894583c3862153e4b97", - "v7.0.0", + "6d4fd22b20465ccc0f7354476588e8df7c9ca0e0", + "v7.1.0", ), with: { "python-version": `\${{ inputs.python-version || '${defaultLanguageVersions.python}' }}`, From c8bf9adf8afb442a0b9ed0b8a1ffca33b1e87be2 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 29 Oct 2026 16:25:19 +0000 Subject: [PATCH 139/174] Update hard-coded `latest` runner labels --- .../__per-language-bundle-validation.yml | 18 +++++++++--------- .github/workflows/codeql.yml | 4 ++-- .github/workflows/codescanning-config-cli.yml | 6 +++--- .../workflows/debug-artifacts-failure-safe.yml | 4 ++-- .github/workflows/debug-artifacts-safe.yml | 4 ++-- .github/workflows/post-release-mergeback.yml | 10 +++++----- .github/workflows/pr-checks.yml | 8 ++++---- .github/workflows/prepare-release.yml | 2 +- .github/workflows/python312-windows.yml | 2 +- .github/workflows/query-filters.yml | 2 +- .github/workflows/rebuild.yml | 4 ++-- .github/workflows/rollback-release.yml | 2 +- .github/workflows/test-codeql-bundle-all.yml | 2 +- .github/workflows/update-bundle.yml | 2 +- .github/workflows/update-release-branch.yml | 4 ++-- .../checks/per-language-bundle-validation.yml | 18 +++++++++--------- 16 files changed, 46 insertions(+), 46 deletions(-) diff --git a/.github/workflows/__per-language-bundle-validation.yml b/.github/workflows/__per-language-bundle-validation.yml index ee779ab40b..177f4a0d8f 100644 --- a/.github/workflows/__per-language-bundle-validation.yml +++ b/.github/workflows/__per-language-bundle-validation.yml @@ -35,37 +35,37 @@ jobs: matrix: include: - language: actions - os: ubuntu-latest + os: ubuntu-26.04 version: linked expected-extractors: actions javascript - language: cpp - os: ubuntu-latest + os: ubuntu-26.04 version: linked build-mode: manual build-command: gcc -o main main.c - language: csharp - os: ubuntu-latest + os: ubuntu-26.04 version: linked build-mode: none - language: go - os: ubuntu-latest + os: ubuntu-26.04 version: linked build-mode: autobuild - language: java - os: ubuntu-latest + os: ubuntu-26.04 version: linked build-mode: none - language: javascript - os: ubuntu-latest + os: ubuntu-26.04 version: linked - language: python - os: ubuntu-latest + os: ubuntu-26.04 version: linked - language: ruby - os: ubuntu-latest + os: ubuntu-26.04 version: linked - language: rust - os: ubuntu-latest + os: ubuntu-26.04 version: linked - language: swift os: macos-latest-xlarge diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f27de17fd8..451238b668 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -22,7 +22,7 @@ jobs: # Identify the CodeQL tool versions to use in the analysis job. check-codeql-versions: if: github.triggering_actor != 'dependabot[bot]' - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 outputs: versions: ${{ steps.compare.outputs.versions }} @@ -106,7 +106,7 @@ jobs: analyze-other: if: github.triggering_actor != 'dependabot[bot]' - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 strategy: fail-fast: false diff --git a/.github/workflows/codescanning-config-cli.yml b/.github/workflows/codescanning-config-cli.yml index 7820319486..b1194460d3 100644 --- a/.github/workflows/codescanning-config-cli.yml +++ b/.github/workflows/codescanning-config-cli.yml @@ -41,11 +41,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: linked - - os: ubuntu-latest + - os: ubuntu-26.04 version: default - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest # Code-Scanning config not created because environment variable is not set diff --git a/.github/workflows/debug-artifacts-failure-safe.yml b/.github/workflows/debug-artifacts-failure-safe.yml index 38c4045d33..c9599e446c 100644 --- a/.github/workflows/debug-artifacts-failure-safe.yml +++ b/.github/workflows/debug-artifacts-failure-safe.yml @@ -47,7 +47,7 @@ jobs: # stable-v2.20.7 requires an older version of Java than the default on `ubuntu-latest` (`ubuntu-26.04`). # We could install that older version on the newer runners, or use the older runner. # We do the latter here. This can be removed once we stop supporting `v2.20.7`. - runs-on: ${{ case(matrix.version == 'stable-v2.20.7', 'ubuntu-24.04', 'ubuntu-latest') }} + runs-on: ${{ case(matrix.version == 'stable-v2.20.7', 'ubuntu-24.04', 'ubuntu-26.04') }} steps: - name: Dump GitHub event @@ -91,7 +91,7 @@ jobs: timeout-minutes: 45 permissions: contents: read - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: Download all artifacts uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 diff --git a/.github/workflows/debug-artifacts-safe.yml b/.github/workflows/debug-artifacts-safe.yml index 610e1aab8a..4e2035b9ee 100644 --- a/.github/workflows/debug-artifacts-safe.yml +++ b/.github/workflows/debug-artifacts-safe.yml @@ -45,7 +45,7 @@ jobs: # stable-v2.20.7 requires an older version of Java than the default on `ubuntu-latest` (`ubuntu-26.04`). # We could install that older version on the newer runners, or use the older runner. # We do the latter here. This can be removed once we stop supporting `v2.20.7`. - runs-on: ${{ case(matrix.version == 'stable-v2.20.7', 'ubuntu-24.04', 'ubuntu-latest') }} + runs-on: ${{ case(matrix.version == 'stable-v2.20.7', 'ubuntu-24.04', 'ubuntu-26.04') }} steps: - name: Check out repository @@ -84,7 +84,7 @@ jobs: timeout-minutes: 45 permissions: contents: read - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: Download all artifacts uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 diff --git a/.github/workflows/post-release-mergeback.yml b/.github/workflows/post-release-mergeback.yml index 76ef6e555f..4e9a0c7a77 100644 --- a/.github/workflows/post-release-mergeback.yml +++ b/.github/workflows/post-release-mergeback.yml @@ -10,7 +10,7 @@ on: workflow_dispatch: inputs: baseBranch: - description: 'The base branch to merge into' + description: "The base branch to merge into" default: main required: false @@ -24,7 +24,7 @@ defaults: jobs: merge-back: - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 environment: Automation if: github.repository == 'github/codeql-action' env: @@ -41,16 +41,16 @@ jobs: - name: Dump GitHub context env: - GITHUB_CONTEXT: '${{ toJson(github) }}' + GITHUB_CONTEXT: "${{ toJson(github) }}" run: echo "${GITHUB_CONTEXT}" - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - fetch-depth: 0 # ensure we have all tags and can push commits + fetch-depth: 0 # ensure we have all tags and can push commits - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 24 - cache: 'npm' + cache: "npm" - name: Install JavaScript dependencies run: npm ci diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 5d2b1576f7..cb6bf9e07a 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -25,7 +25,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [ubuntu-26.04, macos-26, windows-2025] node-version: [20, 24] permissions: contents: read @@ -71,7 +71,7 @@ jobs: run: npm test - name: Lint - if: always() && matrix.os != 'windows-latest' + if: always() && matrix.os != 'windows-2025' run: npm run lint-ci - name: Upload sarif @@ -81,7 +81,7 @@ jobs: # paired `push` run that the queue branch creates use that ref, so gate on the ref itself # rather than the event. The same results are uploaded by the `pull_request` run and again # by the `push` run on `main`. - if: matrix.os == 'ubuntu-latest' && matrix.node-version == 24 && !startsWith(github.ref, 'refs/heads/gh-readonly-queue/') + if: matrix.os == 'ubuntu-26.04' && matrix.node-version == 24 && !startsWith(github.ref, 'refs/heads/gh-readonly-queue/') with: sarif_file: eslint.sarif category: eslint @@ -93,7 +93,7 @@ jobs: if: github.triggering_actor != 'dependabot[bot]' permissions: contents: read - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 timeout-minutes: 10 concurrency: diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 8ece992d48..8073c44c32 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -29,7 +29,7 @@ defaults: jobs: prepare: name: "Release info" - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 if: github.repository == 'github/codeql-action' permissions: diff --git a/.github/workflows/python312-windows.yml b/.github/workflows/python312-windows.yml index ab169499e2..b56b1c827d 100644 --- a/.github/workflows/python312-windows.yml +++ b/.github/workflows/python312-windows.yml @@ -29,7 +29,7 @@ jobs: contents: read # We currently need `security-events: read` to access feature flags. security-events: read - runs-on: windows-latest + runs-on: windows-2025 steps: - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 diff --git a/.github/workflows/query-filters.yml b/.github/workflows/query-filters.yml index 1891f4195b..745e84b2e8 100644 --- a/.github/workflows/query-filters.yml +++ b/.github/workflows/query-filters.yml @@ -25,7 +25,7 @@ jobs: name: Query Filters Tests if: github.triggering_actor != 'dependabot[bot]' timeout-minutes: 45 - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 permissions: contents: read # This permission is needed to allow the GitHub Actions workflow to read the contents of the repository. steps: diff --git a/.github/workflows/rebuild.yml b/.github/workflows/rebuild.yml index 1c174ac7a3..c37910a779 100644 --- a/.github/workflows/rebuild.yml +++ b/.github/workflows/rebuild.yml @@ -12,7 +12,7 @@ defaults: jobs: rebuild: name: Rebuild Action - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 if: github.event.label.name == 'Rebuild' || github.event_name == 'workflow_dispatch' env: @@ -33,7 +33,7 @@ jobs: uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 24 - cache: 'npm' + cache: "npm" - name: Remove label if: github.event_name == 'pull_request' diff --git a/.github/workflows/rollback-release.yml b/.github/workflows/rollback-release.yml index 14a8490b8c..81353bfb4f 100644 --- a/.github/workflows/rollback-release.yml +++ b/.github/workflows/rollback-release.yml @@ -34,7 +34,7 @@ jobs: rollback: name: "Create rollback release" if: github.repository == 'github/codeql-action' - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 timeout-minutes: 45 # Don't set the deployment environment for test runs diff --git a/.github/workflows/test-codeql-bundle-all.yml b/.github/workflows/test-codeql-bundle-all.yml index 477fdf0524..cf63b1caa5 100644 --- a/.github/workflows/test-codeql-bundle-all.yml +++ b/.github/workflows/test-codeql-bundle-all.yml @@ -27,7 +27,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-26.04 version: nightly-latest name: 'CodeQL Bundle All' if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/update-bundle.yml b/.github/workflows/update-bundle.yml index 43708f573c..d7d90b749a 100644 --- a/.github/workflows/update-bundle.yml +++ b/.github/workflows/update-bundle.yml @@ -20,7 +20,7 @@ defaults: jobs: update-bundle: if: github.event.release.prerelease && startsWith(github.event.release.tag_name, 'codeql-bundle-') - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 permissions: contents: write # needed to push commits pull-requests: write # needed to create pull requests diff --git a/.github/workflows/update-release-branch.yml b/.github/workflows/update-release-branch.yml index 981a38eaca..6ceb30c42b 100644 --- a/.github/workflows/update-release-branch.yml +++ b/.github/workflows/update-release-branch.yml @@ -26,7 +26,7 @@ jobs: update: name: "Update release branch" timeout-minutes: 45 - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 if: github.event_name == 'workflow_dispatch' needs: [prepare] env: @@ -79,7 +79,7 @@ jobs: backport: name: "Create backport" timeout-minutes: 45 - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 environment: Automation needs: [prepare] if: ${{ (github.event_name == 'push') && needs.prepare.outputs.backport_target_branches != '[]' }} diff --git a/pr-checks/checks/per-language-bundle-validation.yml b/pr-checks/checks/per-language-bundle-validation.yml index ad18736739..942611d628 100644 --- a/pr-checks/checks/per-language-bundle-validation.yml +++ b/pr-checks/checks/per-language-bundle-validation.yml @@ -3,38 +3,38 @@ description: Validates extraction and analysis using each per-language CodeQL bu matrix: include: - language: actions - os: ubuntu-latest + os: ubuntu-26.04 version: linked # Actions also needs the JavaScript extractor. expected-extractors: actions javascript - language: cpp - os: ubuntu-latest + os: ubuntu-26.04 version: linked build-mode: manual build-command: gcc -o main main.c - language: csharp - os: ubuntu-latest + os: ubuntu-26.04 version: linked build-mode: none - language: go - os: ubuntu-latest + os: ubuntu-26.04 version: linked build-mode: autobuild - language: java - os: ubuntu-latest + os: ubuntu-26.04 version: linked build-mode: none - language: javascript - os: ubuntu-latest + os: ubuntu-26.04 version: linked - language: python - os: ubuntu-latest + os: ubuntu-26.04 version: linked - language: ruby - os: ubuntu-latest + os: ubuntu-26.04 version: linked - language: rust - os: ubuntu-latest + os: ubuntu-26.04 version: linked - language: swift os: macos-latest-xlarge From 8cafec0756c1db64e5213379ee031ac3525725b2 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 29 Oct 2026 16:28:51 +0000 Subject: [PATCH 140/174] Skip checks on self-hosted runners --- lib/entry-points.js | 3 +++ src/languages/traced.test.ts | 32 ++++++++++++++++++++++++++++++++ src/languages/traced.ts | 8 +++++++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index d01987f6ff..7a3db767fc 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -193986,6 +193986,9 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { if (!await action.features.getValue("check_unsupported_traced_analysis" /* CheckUnsupportedTracedAnalysis */)) { return; } + if (isSelfHostedRunner(action.env)) { + return; + } if (config.buildMode !== void 0 && config.buildMode === "none") { return; } diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index 2faf7f1ba6..1e78127e97 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -170,6 +170,38 @@ test("checkRunnerSupportsTracedAnalysis doesn't perform checks if FF is not enab ]); })); +test("checkRunnerSupportsTracedAnalysis doesn't perform checks on self-hosted runners", async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + env.set(ActionsEnvVars.RUNNER_ENVIRONMENT, "self-hosted"); + const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); + + const codeql = await getCodeQLWithTracedStub( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + await checkRunnerSupportsTracedAnalysis( + initAllState({ + logger, + platform: "darwin", + osRelease: "unexpected", + env, + features, + }), + createTestConfig({ languages: [BuiltInLanguage.go] }), + codeql, + ); + + checkUnexpectedLogMessages(t, logger.messages, [ + "Unable to determine version of macOS, got: unexpected", + ]); + })); + test("checkRunnerSupportsTracedAnalysis warns if version string is not a semver", async (t) => withTmpDir(async (tmpDir) => { const logger = new RecordingLogger(); diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 2d0c5f9347..da8085f704 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -1,6 +1,7 @@ import * as semver from "semver"; import type { ActionState, Logger } from "../action-common"; +import { isSelfHostedRunner } from "../actions-util"; import type { CodeQL } from "../codeql"; import type { ActionConfig } from "../config/action-config"; import { addDiagnostic, makeDiagnostic } from "../diagnostics"; @@ -115,7 +116,7 @@ export async function hasTracedLanguages( * @throws {ConfigurationError} If traced analysis is not possible on the current runner. */ export async function checkRunnerSupportsTracedAnalysis( - action: ActionState<["Base", "Logger", "FeatureFlags"]>, + action: ActionState<["Base", "Env", "Logger", "FeatureFlags"]>, config: ActionConfig<"languages" | "dbLocation" | "tempDir">, codeql: CodeQL, ) { @@ -132,6 +133,11 @@ export async function checkRunnerSupportsTracedAnalysis( return; } + // Skip if we are on a self-hosted runner. + if (isSelfHostedRunner(action.env)) { + return; + } + // `build-mode: none` doesn't use the tracer, so it is always supported. if (config.buildMode !== undefined && config.buildMode === "none") { return; From 019a5caccdd41ccc55e6910c85f3797c5e98dcdd Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 29 Oct 2026 16:33:54 +0000 Subject: [PATCH 141/174] Change log level of messages in `xcodeVersion` --- lib/entry-points.js | 20 ++++++++++---------- src/languages/traced.ts | 4 ++++ src/platform.test.ts | 2 +- src/platform.ts | 16 ++++++---------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 7a3db767fc..7b3d3d0648 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -183454,27 +183454,25 @@ function xcodeVersion(logger2) { throwIfNoEntry: false }); if (stats === void 0) { - logger2.debug( - `'${XCODE_SELECT_LINK_PATH}' does not exist. Xcode is probably not installed.` - ); + logger2.debug(`'${XCODE_SELECT_LINK_PATH}' does not exist.`); return void 0; } if (!stats.isSymbolicLink()) { - logger2.warning( + logger2.debug( `${XCODE_SELECT_LINK_PATH} exists, but is not a symbolic link.` ); return void 0; } const xcodePath = import_fs.default.readlinkSync(XCODE_SELECT_LINK_PATH); if (xcodePath === "") { - logger2.warning( + logger2.debug( `Resolving ${XCODE_SELECT_LINK_PATH} unexpectedly returned nothing.` ); return void 0; } const matchResult = xcodePath.match(XCODE_APP_FILENAME_PATTERN); if (matchResult?.groups === void 0) { - logger2.warning( + logger2.debug( `Xcode path '${xcodePath}' does not contain expected pattern.` ); return void 0; @@ -183482,14 +183480,12 @@ function xcodeVersion(logger2) { const majorMinor = matchResult.groups["majorMinor"]; const version = semver6.coerce(majorMinor); if (version === null) { - logger2.warning(`Couldn't parse '${majorMinor}' as a semantic version.`); + logger2.debug(`Couldn't parse '${majorMinor}' as a semantic version.`); return void 0; } return version; } catch (err) { - logger2.warning( - `Unable to determine Xcode version: ${getErrorMessage(err)}` - ); + logger2.debug(`Unable to determine Xcode version: ${getErrorMessage(err)}`); return void 0; } } @@ -194027,6 +194023,10 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { "Xcode", xcodeVer ); + } else if (xcodeVer === void 0) { + action.logger.info( + "Unable to determine Xcode version. Assuming it is not installed." + ); } } diff --git a/src/languages/traced.ts b/src/languages/traced.ts index da8085f704..a1c69a56be 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -193,5 +193,9 @@ export async function checkRunnerSupportsTracedAnalysis( "Xcode", xcodeVer, ); + } else if (xcodeVer === undefined) { + action.logger.info( + "Unable to determine Xcode version. Assuming it is not installed.", + ); } } diff --git a/src/platform.test.ts b/src/platform.test.ts index d6439226e8..43108c4225 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -84,7 +84,7 @@ test.serial("xcodeVersion returns undefined if symlink doesn't exist", (t) => { ]); checkExpectedLogMessages(t, logger.messages, [ - "Xcode is probably not installed.", + "'/private/var/db/xcode_select_link' does not exist", ]); }); diff --git a/src/platform.ts b/src/platform.ts index 4d17b33e93..cb7df698a8 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -82,13 +82,11 @@ export function xcodeVersion(logger: Logger): semver.SemVer | undefined { }); if (stats === undefined) { - logger.debug( - `'${XCODE_SELECT_LINK_PATH}' does not exist. Xcode is probably not installed.`, - ); + logger.debug(`'${XCODE_SELECT_LINK_PATH}' does not exist.`); return undefined; } if (!stats.isSymbolicLink()) { - logger.warning( + logger.debug( `${XCODE_SELECT_LINK_PATH} exists, but is not a symbolic link.`, ); return undefined; @@ -98,7 +96,7 @@ export function xcodeVersion(logger: Logger): semver.SemVer | undefined { const xcodePath = fs.readlinkSync(XCODE_SELECT_LINK_PATH); if (xcodePath === "") { - logger.warning( + logger.debug( `Resolving ${XCODE_SELECT_LINK_PATH} unexpectedly returned nothing.`, ); return undefined; @@ -108,7 +106,7 @@ export function xcodeVersion(logger: Logger): semver.SemVer | undefined { const matchResult = xcodePath.match(XCODE_APP_FILENAME_PATTERN); if (matchResult?.groups === undefined) { - logger.warning( + logger.debug( `Xcode path '${xcodePath}' does not contain expected pattern.`, ); return undefined; @@ -118,14 +116,12 @@ export function xcodeVersion(logger: Logger): semver.SemVer | undefined { const version = semver.coerce(majorMinor); if (version === null) { - logger.warning(`Couldn't parse '${majorMinor}' as a semantic version.`); + logger.debug(`Couldn't parse '${majorMinor}' as a semantic version.`); return undefined; } return version; } catch (err) { - logger.warning( - `Unable to determine Xcode version: ${getErrorMessage(err)}`, - ); + logger.debug(`Unable to determine Xcode version: ${getErrorMessage(err)}`); return undefined; } } From 3da973862d42c4bb73cb9e05594860439be4a462 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 29 Oct 2026 16:35:49 +0000 Subject: [PATCH 142/174] Add debug-level log messages when checks are skipped --- lib/entry-points.js | 15 +++++++++++++++ src/languages/traced.ts | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/lib/entry-points.js b/lib/entry-points.js index 7b3d3d0648..f90431684d 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -193980,19 +193980,34 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { const version = darwinVersion(action); await checkSwiftCompatibility(config, codeql, version); if (!await action.features.getValue("check_unsupported_traced_analysis" /* CheckUnsupportedTracedAnalysis */)) { + action.logger.debug( + "Skipping traced analysis compatibility checks because the feature is not enabled." + ); return; } if (isSelfHostedRunner(action.env)) { + action.logger.debug( + "Skipping traced analysis compatibility checks because we are on a self-hosted runner." + ); return; } if (config.buildMode !== void 0 && config.buildMode === "none") { + action.logger.debug( + "Skipping traced analysis compatibility checks because the build mode is 'none'." + ); return; } if (version === void 0) { + action.logger.debug( + "Skipping traced analysis compatibility checks because we are not on macOS." + ); return; } const tracedLanguages = await hasTracedLanguages(config, codeql); if (tracedLanguages.length === 0) { + action.logger.debug( + "Skipping traced analysis compatibility checks because no traced languages are being analyzed." + ); return; } const skipUnsupportedTracedAnalysis = await action.features.getValue( diff --git a/src/languages/traced.ts b/src/languages/traced.ts index a1c69a56be..202252fb13 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -130,27 +130,42 @@ export async function checkRunnerSupportsTracedAnalysis( if ( !(await action.features.getValue(Feature.CheckUnsupportedTracedAnalysis)) ) { + action.logger.debug( + "Skipping traced analysis compatibility checks because the feature is not enabled.", + ); return; } // Skip if we are on a self-hosted runner. if (isSelfHostedRunner(action.env)) { + action.logger.debug( + "Skipping traced analysis compatibility checks because we are on a self-hosted runner.", + ); return; } // `build-mode: none` doesn't use the tracer, so it is always supported. if (config.buildMode !== undefined && config.buildMode === "none") { + action.logger.debug( + "Skipping traced analysis compatibility checks because the build mode is 'none'.", + ); return; } // These checks don't apply if we are not on macOS. if (version === undefined) { + action.logger.debug( + "Skipping traced analysis compatibility checks because we are not on macOS.", + ); return; } // If none of the languages are traced, then we can skip the compatibility checks below as well. const tracedLanguages = await hasTracedLanguages(config, codeql); if (tracedLanguages.length === 0) { + action.logger.debug( + "Skipping traced analysis compatibility checks because no traced languages are being analyzed.", + ); return; } From d37c3131f400dc8edece7a0370ab26ddbee3f937 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 10:52:53 +0000 Subject: [PATCH 143/174] Improve comment/log message wording --- lib/entry-points.js | 6 +++--- src/languages/swift.test.ts | 4 ++-- src/languages/traced.test.ts | 6 +++--- src/languages/traced.ts | 13 ++++++------- src/platform.ts | 5 +++-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index f90431684d..d7de1c8331 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -193928,7 +193928,7 @@ function handleUnsupportedVersion(logger2, config, tracedLanguages, skipUnsuppor const baseMessage = [ `Traced analysis is not supported on ${product} ${UNSUPPORTED_DARWIN_FOR_TRACED} or above.`, `Configure your analysis to run on macOS ${UNSUPPORTED_DARWIN_FOR_TRACED - 1} or below`, - `and XCode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.` + `and Xcode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.` ].join(" "); const attributeName = product === "macOS" ? "darwinVersion" : "xcodeVersion"; for (const language of tracedLanguages) { @@ -194015,7 +194015,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { ); if (typeof version === "string") { action.logger.warning( - `Unable to determine version of macOS, got: ${version}` + `Unable to parse Darwin kernel version, got: ${version}. Skipping macOS compatibility check.` ); } else if (version.major >= UNSUPPORTED_DARWIN_FOR_TRACED) { handleUnsupportedVersion( @@ -194040,7 +194040,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { ); } else if (xcodeVer === void 0) { action.logger.info( - "Unable to determine Xcode version. Assuming it is not installed." + "Unable to determine Xcode version. Skipping Xcode compatibility check." ); } } diff --git a/src/languages/swift.test.ts b/src/languages/swift.test.ts index 465f782c16..c3d18c476f 100644 --- a/src/languages/swift.test.ts +++ b/src/languages/swift.test.ts @@ -30,7 +30,7 @@ test("checkSwiftCompatibility doesn't throw for non-Swift languages", async (t) checkSwiftCompatibility( createTestConfig({ languages: [language] }), codeql, - // A value of `undefined` should make `isSwiftCompatible` throw for Swift by default + // A value of `undefined` should make `checkSwiftCompatibility` throw for Swift by default // since it means we are on a platform other than macOS undefined, ), @@ -54,7 +54,7 @@ test("checkSwiftCompatibility doesn't throw for Swift if CLI supports swiftSuppo checkSwiftCompatibility( createTestConfig({ languages: [BuiltInLanguage.swift] }), codeql, - // A value of `undefined` should make `isSwiftCompatible` throw for Swift by default + // A value of `undefined` should make `checkSwiftCompatibility` throw for Swift by default // since it means we are on a platform other than macOS undefined, ), diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index 1e78127e97..d37a742f62 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -166,7 +166,7 @@ test("checkRunnerSupportsTracedAnalysis doesn't perform checks if FF is not enab ); checkUnexpectedLogMessages(t, logger.messages, [ - "Unable to determine version of macOS, got: unexpected", + "Unable to parse Darwin kernel version, got: unexpected", ]); })); @@ -198,7 +198,7 @@ test("checkRunnerSupportsTracedAnalysis doesn't perform checks on self-hosted ru ); checkUnexpectedLogMessages(t, logger.messages, [ - "Unable to determine version of macOS, got: unexpected", + "Unable to parse Darwin kernel version, got: unexpected", ]); })); @@ -229,7 +229,7 @@ test("checkRunnerSupportsTracedAnalysis warns if version string is not a semver" ); checkExpectedLogMessages(t, logger.messages, [ - "Unable to determine version of macOS, got: unexpected", + "Unable to parse Darwin kernel version, got: unexpected", ]); })); diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 202252fb13..816ff2f807 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -19,7 +19,7 @@ export const UNSUPPORTED_DARWIN_FOR_TRACED = 27; export const UNSUPPORTED_XCODE_FOR_TRACED = 27; /** - * Creates a diagnostic indicating that `version` of `product` is unsupported for traced analysis. + * Creates a diagnostic indicating that `version` of `product` is unsupported for traced analysis. * Depending on `skipUnsupportedTracedAnalysis`, this function then either throws a {@link ConfigurationError} * or logs the problem as a warning. * @@ -41,7 +41,7 @@ function handleUnsupportedVersion( const baseMessage = [ `Traced analysis is not supported on ${product} ${UNSUPPORTED_DARWIN_FOR_TRACED} or above.`, `Configure your analysis to run on macOS ${UNSUPPORTED_DARWIN_FOR_TRACED - 1} or below`, - `and XCode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.`, + `and Xcode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.`, ].join(" "); const attributeName = product === "macOS" ? "darwinVersion" : "xcodeVersion"; @@ -82,8 +82,6 @@ function handleUnsupportedVersion( // Throw an error to abort the analysis if the FF is enabled or log the message. if (skipUnsupportedTracedAnalysis) { - // ConfigurationErrors are converted to the "aborted" status by the exception handler - // in `init-action.ts` that guards the call to `checkRunnerSupportsTracedAnalysis`. throw new ConfigurationError(logMessage); } else { // This will also show up as a workflow annotation. @@ -136,7 +134,8 @@ export async function checkRunnerSupportsTracedAnalysis( return; } - // Skip if we are on a self-hosted runner. + // Skip if we are on a self-hosted runner since the current Xcode version detection + // is only validated on hosted runners. if (isSelfHostedRunner(action.env)) { action.logger.debug( "Skipping traced analysis compatibility checks because we are on a self-hosted runner.", @@ -175,7 +174,7 @@ export async function checkRunnerSupportsTracedAnalysis( if (typeof version === "string") { // If we got a string, we are on macOS but couldn't parse the version string. action.logger.warning( - `Unable to determine version of macOS, got: ${version}`, + `Unable to parse Darwin kernel version, got: ${version}. Skipping macOS compatibility check.`, ); } else if (version.major >= UNSUPPORTED_DARWIN_FOR_TRACED) { handleUnsupportedVersion( @@ -210,7 +209,7 @@ export async function checkRunnerSupportsTracedAnalysis( ); } else if (xcodeVer === undefined) { action.logger.info( - "Unable to determine Xcode version. Assuming it is not installed.", + "Unable to determine Xcode version. Skipping Xcode compatibility check.", ); } } diff --git a/src/platform.ts b/src/platform.ts index cb7df698a8..070f30a8f7 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -33,8 +33,9 @@ export function getBundlePlatform( } /** - * Tries to determine the version of the kernel on macOS. We approximate this based on the - * Darwin kernel version so that we don't have to launch an external process. + * Tries to determine the version of the Darwin kernel. We use this to approximate the macOS version based + * on the Darwin kernel version so that we don't have to launch an external process. Note that the Darwin + * kernel major version does not correspond perfectly to the macOS major version. * * @returns * The version as either a semantic version object, the raw version string From 239b07849dc23a339968dcbe4732e60cf55e2fbd Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 10:56:23 +0000 Subject: [PATCH 144/174] Only skip Xcode check on self-hosted runners --- lib/entry-points.js | 12 +++---- src/languages/traced.test.ts | 64 ++++++++++++++++++------------------ src/languages/traced.ts | 18 +++++----- 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index d7de1c8331..afb99c091c 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -193985,12 +193985,6 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { ); return; } - if (isSelfHostedRunner(action.env)) { - action.logger.debug( - "Skipping traced analysis compatibility checks because we are on a self-hosted runner." - ); - return; - } if (config.buildMode !== void 0 && config.buildMode === "none") { action.logger.debug( "Skipping traced analysis compatibility checks because the build mode is 'none'." @@ -194028,6 +194022,12 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { ); return; } + if (isSelfHostedRunner(action.env)) { + action.logger.debug( + "Skipping traced analysis compatibility check for Xcode because we are on a self-hosted runner." + ); + return; + } const xcodeVer = xcodeVersion(action.logger); if (xcodeVer !== void 0 && xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED) { handleUnsupportedVersion( diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index d37a742f62..d5b377b9cc 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -170,38 +170,6 @@ test("checkRunnerSupportsTracedAnalysis doesn't perform checks if FF is not enab ]); })); -test("checkRunnerSupportsTracedAnalysis doesn't perform checks on self-hosted runners", async (t) => - withTmpDir(async (tmpDir) => { - const logger = new RecordingLogger(); - const env = getTestEnv(); - env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - env.set(ActionsEnvVars.RUNNER_ENVIRONMENT, "self-hosted"); - const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); - - const codeql = await getCodeQLWithTracedStub( - "codeql-for-testing", - logger, - env, - ); - sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); - - await checkRunnerSupportsTracedAnalysis( - initAllState({ - logger, - platform: "darwin", - osRelease: "unexpected", - env, - features, - }), - createTestConfig({ languages: [BuiltInLanguage.go] }), - codeql, - ); - - checkUnexpectedLogMessages(t, logger.messages, [ - "Unable to parse Darwin kernel version, got: unexpected", - ]); - })); - test("checkRunnerSupportsTracedAnalysis warns if version string is not a semver", async (t) => withTmpDir(async (tmpDir) => { const logger = new RecordingLogger(); @@ -355,6 +323,38 @@ test.serial( }), ); +test("checkRunnerSupportsTracedAnalysis doesn't perform Xcode check on self-hosted runners", async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + env.set(ActionsEnvVars.RUNNER_ENVIRONMENT, "self-hosted"); + const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); + + const codeql = await getCodeQLWithTracedStub( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + await checkRunnerSupportsTracedAnalysis( + initAllState({ + logger, + platform: "darwin", + osRelease: "27.0.0", + env, + features, + }), + createTestConfig({ languages: [BuiltInLanguage.go] }), + codeql, + ); + + checkUnexpectedLogMessages(t, logger.messages, [ + "Skipping traced analysis compatibility check for Xcode because we are on a self-hosted runner.", + ]); + })); + // `addDiagnostic` changes global state and we must stub it, so this test must be serial. test.serial( "checkRunnerSupportsTracedAnalysis doesn't add a diagnostic if Xcode version is supported", diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 816ff2f807..7d73595cfb 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -134,15 +134,6 @@ export async function checkRunnerSupportsTracedAnalysis( return; } - // Skip if we are on a self-hosted runner since the current Xcode version detection - // is only validated on hosted runners. - if (isSelfHostedRunner(action.env)) { - action.logger.debug( - "Skipping traced analysis compatibility checks because we are on a self-hosted runner.", - ); - return; - } - // `build-mode: none` doesn't use the tracer, so it is always supported. if (config.buildMode !== undefined && config.buildMode === "none") { action.logger.debug( @@ -191,6 +182,15 @@ export async function checkRunnerSupportsTracedAnalysis( return; } + // Skip if we are on a self-hosted runner since the current Xcode version detection + // is only validated on hosted runners. + if (isSelfHostedRunner(action.env)) { + action.logger.debug( + "Skipping traced analysis compatibility check for Xcode because we are on a self-hosted runner.", + ); + return; + } + // Determining whether the Xcode version is supported only makes sense on macOS, so we only do it // after determining that we are running on macOS. const xcodeVer = xcodeVersion(action.logger); From b2bb71bc61adc1ab23b8624aa6fb56b53ac0cc45 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 10:58:21 +0000 Subject: [PATCH 145/174] Set `tempDir` in all `createTestConfig` calls in `traced.test.ts` To avoid stray diagnostic files ending up in the working directory --- src/languages/traced.test.ts | 40 ++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index d5b377b9cc..d14af8b47d 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -67,7 +67,10 @@ for (const nonDarwinPlatform of nonDarwinPlatforms) { await t.throwsAsync( checkRunnerSupportsTracedAnalysis( initAllState({ platform: nonDarwinPlatform, env, logger }), - createTestConfig({ languages: [BuiltInLanguage.swift] }), + createTestConfig({ + tempDir: tmpDir, + languages: [BuiltInLanguage.swift], + }), codeql, ), { @@ -99,7 +102,7 @@ test(`checkRunnerSupportsTracedAnalysis doesn't throw for BMN`, async (t) => env, logger, }), - createTestConfig({ buildMode: BuildMode.None }), + createTestConfig({ tempDir: tmpDir, buildMode: BuildMode.None }), codeql, ), ); @@ -132,7 +135,7 @@ for (const nonTracedLanguage of nonTracedLanguages) { env, logger, }), - createTestConfig({ languages: [nonTracedLanguage] }), + createTestConfig({ tempDir: tmpDir, languages: [nonTracedLanguage] }), codeql, ), ); @@ -161,7 +164,7 @@ test("checkRunnerSupportsTracedAnalysis doesn't perform checks if FF is not enab env, features, }), - createTestConfig({ languages: [BuiltInLanguage.go] }), + createTestConfig({ tempDir: tmpDir, languages: [BuiltInLanguage.go] }), codeql, ); @@ -192,7 +195,7 @@ test("checkRunnerSupportsTracedAnalysis warns if version string is not a semver" env, features, }), - createTestConfig({ languages: [BuiltInLanguage.go] }), + createTestConfig({ tempDir: tmpDir, languages: [BuiltInLanguage.go] }), codeql, ); @@ -220,7 +223,10 @@ test.serial( const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); - const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); + const config = createTestConfig({ + tempDir: tmpDir, + languages: [BuiltInLanguage.swift], + }); await checkRunnerSupportsTracedAnalysis( initAllState({ logger, @@ -284,7 +290,10 @@ test.serial( const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); - const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); + const config = createTestConfig({ + tempDir: tmpDir, + languages: [BuiltInLanguage.swift], + }); await t.throwsAsync( checkRunnerSupportsTracedAnalysis( initAllState({ @@ -346,7 +355,7 @@ test("checkRunnerSupportsTracedAnalysis doesn't perform Xcode check on self-host env, features, }), - createTestConfig({ languages: [BuiltInLanguage.go] }), + createTestConfig({ tempDir: tmpDir, languages: [BuiltInLanguage.go] }), codeql, ); @@ -381,7 +390,10 @@ test.serial( const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); - const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); + const config = createTestConfig({ + tempDir: tmpDir, + languages: [BuiltInLanguage.swift], + }); await checkRunnerSupportsTracedAnalysis( initAllState({ logger, @@ -436,7 +448,10 @@ test.serial( const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); - const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); + const config = createTestConfig({ + tempDir: tmpDir, + languages: [BuiltInLanguage.swift], + }); await checkRunnerSupportsTracedAnalysis( initAllState({ logger, @@ -515,7 +530,10 @@ test.serial( const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); - const config = createTestConfig({ languages: [BuiltInLanguage.swift] }); + const config = createTestConfig({ + tempDir: tmpDir, + languages: [BuiltInLanguage.swift], + }); await t.throwsAsync( checkRunnerSupportsTracedAnalysis( initAllState({ From 5bdb913da11ac3b7db87fced3be7d5b04d836809 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 11:00:42 +0000 Subject: [PATCH 146/174] Rename FF to include "Abort" instead of "Skip" --- .github/workflows/__unsupported-macos.yml | 2 +- lib/entry-points.js | 18 +++++++++--------- pr-checks/checks/unsupported-macos.yml | 2 +- src/feature-flags.ts | 6 +++--- src/languages/traced.test.ts | 4 ++-- src/languages/traced.ts | 16 ++++++++-------- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/__unsupported-macos.yml b/.github/workflows/__unsupported-macos.yml index 8f4a473df5..a888ce757c 100644 --- a/.github/workflows/__unsupported-macos.yml +++ b/.github/workflows/__unsupported-macos.yml @@ -74,7 +74,7 @@ jobs: continue-on-error: true env: CODEQL_ACTION_CHECK_UNSUPPORTED_TRACED_ANALYSIS: true - CODEQL_ACTION_SKIP_UNSUPPORTED_TRACED_ANALYSIS: true + CODEQL_ACTION_ABORT_UNSUPPORTED_TRACED_ANALYSIS: true with: languages: swift tools: ${{ steps.prepare-test.outputs.tools-url }} diff --git a/lib/entry-points.js b/lib/entry-points.js index afb99c091c..26dc274b75 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -179947,9 +179947,9 @@ var featureConfig = { envVar: "CODEQL_ACTION_START_PROXY_USE_FEATURES_RELEASE", minimumVersion: void 0 }, - ["skip_unsupported_traced_analysis" /* SkipUnsupportedTracedAnalysis */]: { + ["abort_unsupported_traced_analysis" /* AbortUnsupportedTracedAnalysis */]: { defaultValue: false, - envVar: "CODEQL_ACTION_SKIP_UNSUPPORTED_TRACED_ANALYSIS", + envVar: "CODEQL_ACTION_ABORT_UNSUPPORTED_TRACED_ANALYSIS", minimumVersion: void 0 }, ["tools_repository_property" /* ToolsRepositoryProperty */]: { @@ -193924,7 +193924,7 @@ async function checkSwiftCompatibility(config, codeql, darwinVersion2) { // src/languages/traced.ts var UNSUPPORTED_DARWIN_FOR_TRACED = 27; var UNSUPPORTED_XCODE_FOR_TRACED = 27; -function handleUnsupportedVersion(logger2, config, tracedLanguages, skipUnsupportedTracedAnalysis, product, version) { +function handleUnsupportedVersion(logger2, config, tracedLanguages, abortUnsupportedTracedAnalysis, product, version) { const baseMessage = [ `Traced analysis is not supported on ${product} ${UNSUPPORTED_DARWIN_FOR_TRACED} or above.`, `Configure your analysis to run on macOS ${UNSUPPORTED_DARWIN_FOR_TRACED - 1} or below`, @@ -193947,7 +193947,7 @@ function handleUnsupportedVersion(logger2, config, tracedLanguages, skipUnsuppor baseMessage, `For more information, see [this announcement](${"https://github.blog/changelog/2026-10-19-codeql-changes-for-macos-27-xcode-27-and-swift-6-4/" /* UNSUPPORTED_TRACED_ANALYSIS_MACOS27 */}).` ].join(" "), - severity: skipUnsupportedTracedAnalysis ? "error" : "warning", + severity: abortUnsupportedTracedAnalysis ? "error" : "warning", visibility: { cliSummaryTable: true, statusPage: true, @@ -193961,7 +193961,7 @@ function handleUnsupportedVersion(logger2, config, tracedLanguages, skipUnsuppor baseMessage, `For more information, see ${"https://github.blog/changelog/2026-10-19-codeql-changes-for-macos-27-xcode-27-and-swift-6-4/" /* UNSUPPORTED_TRACED_ANALYSIS_MACOS27 */}` ].join(" "); - if (skipUnsupportedTracedAnalysis) { + if (abortUnsupportedTracedAnalysis) { throw new ConfigurationError(logMessage); } else { logger2.warning(logMessage); @@ -194004,8 +194004,8 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { ); return; } - const skipUnsupportedTracedAnalysis = await action.features.getValue( - "skip_unsupported_traced_analysis" /* SkipUnsupportedTracedAnalysis */ + const abortUnsupportedTracedAnalysis = await action.features.getValue( + "abort_unsupported_traced_analysis" /* AbortUnsupportedTracedAnalysis */ ); if (typeof version === "string") { action.logger.warning( @@ -194016,7 +194016,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { action.logger, config, tracedLanguages, - skipUnsupportedTracedAnalysis, + abortUnsupportedTracedAnalysis, "macOS", version ); @@ -194034,7 +194034,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { action.logger, config, tracedLanguages, - skipUnsupportedTracedAnalysis, + abortUnsupportedTracedAnalysis, "Xcode", xcodeVer ); diff --git a/pr-checks/checks/unsupported-macos.yml b/pr-checks/checks/unsupported-macos.yml index d417e6082d..5881b174a8 100644 --- a/pr-checks/checks/unsupported-macos.yml +++ b/pr-checks/checks/unsupported-macos.yml @@ -28,7 +28,7 @@ steps: continue-on-error: true env: CODEQL_ACTION_CHECK_UNSUPPORTED_TRACED_ANALYSIS: true - CODEQL_ACTION_SKIP_UNSUPPORTED_TRACED_ANALYSIS: true + CODEQL_ACTION_ABORT_UNSUPPORTED_TRACED_ANALYSIS: true with: languages: swift tools: ${{ steps.prepare-test.outputs.tools-url }} diff --git a/src/feature-flags.ts b/src/feature-flags.ts index 36fccc6aab..a321b941f0 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -150,7 +150,7 @@ export enum Feature { OverlayAnalysisStatusSave = "overlay_analysis_status_save", QaTelemetryEnabled = "qa_telemetry_enabled", /** Whether we should fail early if we detect that traced analysis is unsupported. */ - SkipUnsupportedTracedAnalysis = "skip_unsupported_traced_analysis", + AbortUnsupportedTracedAnalysis = "abort_unsupported_traced_analysis", /** Routes (some) API requests through the registry proxy. */ ProxyApiRequests = "proxy_api_requests", /** Note that this currently only disables baseline file coverage information. */ @@ -422,9 +422,9 @@ export const featureConfig = { envVar: "CODEQL_ACTION_START_PROXY_USE_FEATURES_RELEASE", minimumVersion: undefined, }, - [Feature.SkipUnsupportedTracedAnalysis]: { + [Feature.AbortUnsupportedTracedAnalysis]: { defaultValue: false, - envVar: "CODEQL_ACTION_SKIP_UNSUPPORTED_TRACED_ANALYSIS", + envVar: "CODEQL_ACTION_ABORT_UNSUPPORTED_TRACED_ANALYSIS", minimumVersion: undefined, }, [Feature.ToolsRepositoryProperty]: { diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index d14af8b47d..71c3c57571 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -278,7 +278,7 @@ test.serial( const features = createFeatures([ Feature.CheckUnsupportedTracedAnalysis, - Feature.SkipUnsupportedTracedAnalysis, + Feature.AbortUnsupportedTracedAnalysis, ]); const codeql = await getCodeQLWithTracedStub( @@ -518,7 +518,7 @@ test.serial( const features = createFeatures([ Feature.CheckUnsupportedTracedAnalysis, - Feature.SkipUnsupportedTracedAnalysis, + Feature.AbortUnsupportedTracedAnalysis, ]); const codeql = await getCodeQLWithTracedStub( diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 7d73595cfb..bf9f3b781a 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -26,7 +26,7 @@ export const UNSUPPORTED_XCODE_FOR_TRACED = 27; * @param logger The logger to use. * @param config The CodeQL Action configuration. * @param tracedLanguages Traced languages that are configured for analysis. - * @param skipUnsupportedTracedAnalysis Whether this is a fatal error. + * @param abortUnsupportedTracedAnalysis Whether this is a fatal error. * @param product The product that the version is unsupported of. * @param version The unsupported version. */ @@ -34,7 +34,7 @@ function handleUnsupportedVersion( logger: Logger, config: ActionConfig<"dbLocation" | "tempDir">, tracedLanguages: string[], - skipUnsupportedTracedAnalysis: boolean, + abortUnsupportedTracedAnalysis: boolean, product: "macOS" | "Xcode", version: semver.SemVer, ) { @@ -63,7 +63,7 @@ function handleUnsupportedVersion( baseMessage, `For more information, see [this announcement](${DocUrl.UNSUPPORTED_TRACED_ANALYSIS_MACOS27}).`, ].join(" "), - severity: skipUnsupportedTracedAnalysis ? "error" : "warning", + severity: abortUnsupportedTracedAnalysis ? "error" : "warning", visibility: { cliSummaryTable: true, statusPage: true, @@ -81,7 +81,7 @@ function handleUnsupportedVersion( ].join(" "); // Throw an error to abort the analysis if the FF is enabled or log the message. - if (skipUnsupportedTracedAnalysis) { + if (abortUnsupportedTracedAnalysis) { throw new ConfigurationError(logMessage); } else { // This will also show up as a workflow annotation. @@ -159,8 +159,8 @@ export async function checkRunnerSupportsTracedAnalysis( return; } - const skipUnsupportedTracedAnalysis = await action.features.getValue( - Feature.SkipUnsupportedTracedAnalysis, + const abortUnsupportedTracedAnalysis = await action.features.getValue( + Feature.AbortUnsupportedTracedAnalysis, ); if (typeof version === "string") { // If we got a string, we are on macOS but couldn't parse the version string. @@ -172,7 +172,7 @@ export async function checkRunnerSupportsTracedAnalysis( action.logger, config, tracedLanguages, - skipUnsupportedTracedAnalysis, + abortUnsupportedTracedAnalysis, "macOS", version, ); @@ -203,7 +203,7 @@ export async function checkRunnerSupportsTracedAnalysis( action.logger, config, tracedLanguages, - skipUnsupportedTracedAnalysis, + abortUnsupportedTracedAnalysis, "Xcode", xcodeVer, ); From 688c04ad4c79bd731d276fbc1c9b957771ad5aac Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 11:01:35 +0000 Subject: [PATCH 147/174] Remove `if` option for validation jobs --- pr-checks/sync.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index 8874655e59..8b40e72528 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -124,8 +124,6 @@ interface JobSpecification { type ValidationJobSpecification = JobSpecification & { checkout?: boolean; - /** Optional condition for the validation job. */ - if?: string; }; /** Describes language/framework-specific steps and inputs. */ @@ -672,10 +670,7 @@ function generateValidationJob( const validationJob: Record = { name: jobSpecification.name, - if: - jobSpecification.if !== undefined - ? `${baseCondition} && ${jobSpecification.if}` - : baseCondition, + if: baseCondition, needs: [checkName], permissions: { contents: "read", From 251f480fa345928ca302ff6228cd62dbf84bf319 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 11:02:47 +0000 Subject: [PATCH 148/174] Use correct version constant in `handleUnsupportedVersion` `baseMessage` --- lib/entry-points.js | 3 ++- src/languages/traced.ts | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 26dc274b75..2cb33152f1 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -193925,8 +193925,9 @@ async function checkSwiftCompatibility(config, codeql, darwinVersion2) { var UNSUPPORTED_DARWIN_FOR_TRACED = 27; var UNSUPPORTED_XCODE_FOR_TRACED = 27; function handleUnsupportedVersion(logger2, config, tracedLanguages, abortUnsupportedTracedAnalysis, product, version) { + const unsupportedVersion = product === "macOS" ? UNSUPPORTED_DARWIN_FOR_TRACED : UNSUPPORTED_XCODE_FOR_TRACED; const baseMessage = [ - `Traced analysis is not supported on ${product} ${UNSUPPORTED_DARWIN_FOR_TRACED} or above.`, + `Traced analysis is not supported on ${product} ${unsupportedVersion} or above.`, `Configure your analysis to run on macOS ${UNSUPPORTED_DARWIN_FOR_TRACED - 1} or below`, `and Xcode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.` ].join(" "); diff --git a/src/languages/traced.ts b/src/languages/traced.ts index bf9f3b781a..1e6442dd60 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -38,8 +38,12 @@ function handleUnsupportedVersion( product: "macOS" | "Xcode", version: semver.SemVer, ) { + const unsupportedVersion = + product === "macOS" + ? UNSUPPORTED_DARWIN_FOR_TRACED + : UNSUPPORTED_XCODE_FOR_TRACED; const baseMessage = [ - `Traced analysis is not supported on ${product} ${UNSUPPORTED_DARWIN_FOR_TRACED} or above.`, + `Traced analysis is not supported on ${product} ${unsupportedVersion} or above.`, `Configure your analysis to run on macOS ${UNSUPPORTED_DARWIN_FOR_TRACED - 1} or below`, `and Xcode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.`, ].join(" "); From c6cc137b274d5fb60acc8e25119b2cc5d57ac65e Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 11:10:38 +0000 Subject: [PATCH 149/174] Fix assertions and features for tests --- src/languages/traced.test.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index 71c3c57571..b8fa7b9372 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -86,6 +86,7 @@ test(`checkRunnerSupportsTracedAnalysis doesn't throw for BMN`, async (t) => const logger = new RecordingLogger(); const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", @@ -101,11 +102,16 @@ test(`checkRunnerSupportsTracedAnalysis doesn't throw for BMN`, async (t) => osRelease: "27.0.0", env, logger, + features, }), createTestConfig({ tempDir: tmpDir, buildMode: BuildMode.None }), codeql, ), ); + + checkExpectedLogMessages(t, logger.messages, [ + "Skipping traced analysis compatibility checks because the build mode is 'none'.", + ]); })); // Some languages not in `TEST_DEFAULT_TRACED_LANGUAGES`. @@ -119,6 +125,7 @@ for (const nonTracedLanguage of nonTracedLanguages) { const logger = new RecordingLogger(); const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", @@ -134,11 +141,16 @@ for (const nonTracedLanguage of nonTracedLanguages) { osRelease: "27.0.0", env, logger, + features, }), createTestConfig({ tempDir: tmpDir, languages: [nonTracedLanguage] }), codeql, ), ); + + checkExpectedLogMessages(t, logger.messages, [ + "Skipping traced analysis compatibility checks because no traced languages are being analyzed.", + ]); })); } @@ -147,7 +159,7 @@ test("checkRunnerSupportsTracedAnalysis doesn't perform checks if FF is not enab const logger = new RecordingLogger(); const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - const features = createFeatures([]); + const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", @@ -169,7 +181,7 @@ test("checkRunnerSupportsTracedAnalysis doesn't perform checks if FF is not enab ); checkUnexpectedLogMessages(t, logger.messages, [ - "Unable to parse Darwin kernel version, got: unexpected", + "Skipping traced analysis compatibility checks because the feature is not enabled.", ]); })); From f583e03df677f0c871214f2a65023d68eba889fb Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 11:24:30 +0000 Subject: [PATCH 150/174] Remove unnecessary `lstatSync` call --- lib/entry-points.js | 15 +----- src/languages/traced.test.ts | 24 ---------- src/platform.test.ts | 93 +++++------------------------------- src/platform.ts | 23 ++------- 4 files changed, 16 insertions(+), 139 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 2cb33152f1..b2bb9c1835 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -183450,21 +183450,8 @@ var XCODE_APP_FILENAME_PATTERN = new RegExp( ); function xcodeVersion(logger2) { try { - const stats = import_fs.default.lstatSync(XCODE_SELECT_LINK_PATH, { - throwIfNoEntry: false - }); - if (stats === void 0) { - logger2.debug(`'${XCODE_SELECT_LINK_PATH}' does not exist.`); - return void 0; - } - if (!stats.isSymbolicLink()) { - logger2.debug( - `${XCODE_SELECT_LINK_PATH} exists, but is not a symbolic link.` - ); - return void 0; - } const xcodePath = import_fs.default.readlinkSync(XCODE_SELECT_LINK_PATH); - if (xcodePath === "") { + if (xcodePath.trim() === "") { logger2.debug( `Resolving ${XCODE_SELECT_LINK_PATH} unexpectedly returned nothing.` ); diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index b8fa7b9372..2aa9318437 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -386,9 +386,6 @@ test.serial( env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); - const lstatSync = sinon - .stub(fs, "lstatSync") - .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") .returns("/Applications/Xcode_26.0.app/Contents/Developer"); @@ -418,11 +415,6 @@ test.serial( codeql, ); - t.is(lstatSync.callCount, 1); - t.deepEqual(lstatSync.args[0], [ - XCODE_SELECT_LINK_PATH, - { throwIfNoEntry: false }, - ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); @@ -444,9 +436,6 @@ test.serial( env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); - const lstatSync = sinon - .stub(fs, "lstatSync") - .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") .returns("/Applications/Xcode_27.0.app/Contents/Developer"); @@ -476,11 +465,6 @@ test.serial( codeql, ); - t.is(lstatSync.callCount, 1); - t.deepEqual(lstatSync.args[0], [ - XCODE_SELECT_LINK_PATH, - { throwIfNoEntry: false }, - ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); @@ -521,9 +505,6 @@ test.serial( const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - const lstatSync = sinon - .stub(fs, "lstatSync") - .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") .returns("/Applications/Xcode_27.0.app/Contents/Developer"); @@ -560,11 +541,6 @@ test.serial( ), ); - t.is(lstatSync.callCount, 1); - t.deepEqual(lstatSync.args[0], [ - XCODE_SELECT_LINK_PATH, - { throwIfNoEntry: false }, - ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); diff --git a/src/platform.test.ts b/src/platform.test.ts index 43108c4225..58c41408e5 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -74,53 +74,32 @@ test("darwinVersion returns semver if parsing succeeds", (t) => { test.serial("xcodeVersion returns undefined if symlink doesn't exist", (t) => { const logger = new RecordingLogger(); - const lstatSync = sinon.stub(fs, "lstatSync").returns(undefined); - - t.is(xcodeVersion(logger), undefined); - t.is(lstatSync.callCount, 1); - t.deepEqual(lstatSync.args[0], [ - XCODE_SELECT_LINK_PATH, - { throwIfNoEntry: false }, - ]); - - checkExpectedLogMessages(t, logger.messages, [ - "'/private/var/db/xcode_select_link' does not exist", - ]); -}); - -test.serial("xcodeVersion returns undefined if lstatSync throws", (t) => { - const logger = new RecordingLogger(); - - const lstatSync = sinon.stub(fs, "lstatSync").throws(new Error("ENOENT")); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .throws(new Error("ENOENT: no such file or directory")); t.is(xcodeVersion(logger), undefined); - t.is(lstatSync.callCount, 1); - t.deepEqual(lstatSync.args[0], [ - XCODE_SELECT_LINK_PATH, - { throwIfNoEntry: false }, - ]); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); checkExpectedLogMessages(t, logger.messages, [ - "Unable to determine Xcode version: ENOENT", + "Unable to determine Xcode version: ENOENT: no such file or directory", ]); }); test.serial("xcodeVersion returns undefined if file is not a symlink", (t) => { const logger = new RecordingLogger(); - const lstatSync = sinon - .stub(fs, "lstatSync") - .returns({ isSymbolicLink: () => false } as fs.Stats); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .throws(new Error("EINVAL: invalid argument")); t.is(xcodeVersion(logger), undefined); - t.is(lstatSync.callCount, 1); - t.deepEqual(lstatSync.args[0], [ - XCODE_SELECT_LINK_PATH, - { throwIfNoEntry: false }, - ]); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); checkExpectedLogMessages(t, logger.messages, [ - "exists, but is not a symbolic link", + "Unable to determine Xcode version: EINVAL: invalid argument", ]); }); @@ -129,17 +108,9 @@ test.serial( (t) => { const logger = new RecordingLogger(); - const lstatSync = sinon - .stub(fs, "lstatSync") - .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon.stub(fs, "readlinkSync").returns(""); t.is(xcodeVersion(logger), undefined); - t.is(lstatSync.callCount, 1); - t.deepEqual(lstatSync.args[0], [ - XCODE_SELECT_LINK_PATH, - { throwIfNoEntry: false }, - ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); @@ -154,19 +125,11 @@ test.serial( (t) => { const logger = new RecordingLogger(); - const lstatSync = sinon - .stub(fs, "lstatSync") - .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") .returns("/Applications/Xcode.app/Contents/Developer"); t.is(xcodeVersion(logger), undefined); - t.is(lstatSync.callCount, 1); - t.deepEqual(lstatSync.args[0], [ - XCODE_SELECT_LINK_PATH, - { throwIfNoEntry: false }, - ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); @@ -179,19 +142,11 @@ test.serial( test.serial("xcodeVersion returns undefined if match can't be parsed", (t) => { const logger = new RecordingLogger(); - const lstatSync = sinon - .stub(fs, "lstatSync") - .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") .returns("/Applications/Xcode_00.0.app/Contents/Developer"); t.is(xcodeVersion(logger), undefined); - t.is(lstatSync.callCount, 1); - t.deepEqual(lstatSync.args[0], [ - XCODE_SELECT_LINK_PATH, - { throwIfNoEntry: false }, - ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); @@ -203,9 +158,6 @@ test.serial("xcodeVersion returns undefined if match can't be parsed", (t) => { test.serial("xcodeVersion returns version from resolved path", (t) => { const logger = new RecordingLogger(); - const lstatSync = sinon - .stub(fs, "lstatSync") - .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") .returns("/Applications/Xcode_16.4.app/Contents/Developer"); @@ -217,11 +169,6 @@ test.serial("xcodeVersion returns version from resolved path", (t) => { t.is(result.minor, 4); } - t.is(lstatSync.callCount, 1); - t.deepEqual(lstatSync.args[0], [ - XCODE_SELECT_LINK_PATH, - { throwIfNoEntry: false }, - ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); }); @@ -229,9 +176,6 @@ test.serial("xcodeVersion returns version from resolved path", (t) => { test.serial("xcodeVersion returns major version from resolved path", (t) => { const logger = new RecordingLogger(); - const lstatSync = sinon - .stub(fs, "lstatSync") - .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") .returns("/Applications/Xcode_16.app/Contents/Developer"); @@ -243,11 +187,6 @@ test.serial("xcodeVersion returns major version from resolved path", (t) => { t.is(result.minor, 0); } - t.is(lstatSync.callCount, 1); - t.deepEqual(lstatSync.args[0], [ - XCODE_SELECT_LINK_PATH, - { throwIfNoEntry: false }, - ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); }); @@ -257,9 +196,6 @@ test.serial( (t) => { const logger = new RecordingLogger(); - const lstatSync = sinon - .stub(fs, "lstatSync") - .returns({ isSymbolicLink: () => true } as fs.Stats); const readlinkSync = sinon .stub(fs, "readlinkSync") .returns("/Applications/Xcode_16.5.9.app/Contents/Developer"); @@ -271,11 +207,6 @@ test.serial( t.is(result.minor, 5); } - t.is(lstatSync.callCount, 1); - t.deepEqual(lstatSync.args[0], [ - XCODE_SELECT_LINK_PATH, - { throwIfNoEntry: false }, - ]); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); }, diff --git a/src/platform.ts b/src/platform.ts index 070f30a8f7..e5c0e6ac63 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -75,28 +75,11 @@ export const XCODE_APP_FILENAME_PATTERN = new RegExp( */ export function xcodeVersion(logger: Logger): semver.SemVer | undefined { try { - // Stat the expected symbolic link to check that it exists and is a symbolic link. - // The `readlinkSync` call below returns an empty string in either case and so - // this check allows us to distinguish between the two cases. - const stats = fs.lstatSync(XCODE_SELECT_LINK_PATH, { - throwIfNoEntry: false, - }); - - if (stats === undefined) { - logger.debug(`'${XCODE_SELECT_LINK_PATH}' does not exist.`); - return undefined; - } - if (!stats.isSymbolicLink()) { - logger.debug( - `${XCODE_SELECT_LINK_PATH} exists, but is not a symbolic link.`, - ); - return undefined; - } - - // Read what the symbolic link points to. + // Read what the symbolic link points to. This will throw if `XCODE_SELECT_LINK_PATH` does not + // exist (`ENOENT`) or is not a symbolic link (`EINVAL`). const xcodePath = fs.readlinkSync(XCODE_SELECT_LINK_PATH); - if (xcodePath === "") { + if (xcodePath.trim() === "") { logger.debug( `Resolving ${XCODE_SELECT_LINK_PATH} unexpectedly returned nothing.`, ); From 690197ddd4a2da38a0c7cc2b7640fce563db2d39 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 11:39:57 +0000 Subject: [PATCH 151/174] Replace `macos-latest-xlarge` with `macos-26-xlarge` --- .github/workflows/__all-platform-bundle.yml | 2 +- .github/workflows/__multi-language-autodetect.yml | 12 ++++++------ .../workflows/__per-language-bundle-validation.yml | 2 +- .github/workflows/__swift-autobuild.yml | 2 +- .github/workflows/__swift-custom-build.yml | 6 +++--- pr-checks/checks/all-platform-bundle.yml | 2 +- pr-checks/checks/multi-language-autodetect.yml | 2 +- pr-checks/checks/per-language-bundle-validation.yml | 2 +- pr-checks/checks/swift-autobuild.yml | 2 +- pr-checks/checks/swift-custom-build.yml | 2 +- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/__all-platform-bundle.yml b/.github/workflows/__all-platform-bundle.yml index a0272b3e45..5f2a6fa861 100644 --- a/.github/workflows/__all-platform-bundle.yml +++ b/.github/workflows/__all-platform-bundle.yml @@ -56,7 +56,7 @@ jobs: include: - os: ubuntu-26.04 version: nightly-latest - - os: macos-latest-xlarge + - os: macos-26-xlarge version: nightly-latest - os: windows-2025 version: nightly-latest diff --git a/.github/workflows/__multi-language-autodetect.yml b/.github/workflows/__multi-language-autodetect.yml index fd252d6de7..b8a6728581 100644 --- a/.github/workflows/__multi-language-autodetect.yml +++ b/.github/workflows/__multi-language-autodetect.yml @@ -68,27 +68,27 @@ jobs: version: stable-v2.22.4 - os: ubuntu-26.04 version: stable-v2.23.9 - - os: macos-latest-xlarge + - os: macos-26-xlarge version: stable-v2.23.9 - os: ubuntu-26.04 version: stable-v2.24.3 - - os: macos-latest-xlarge + - os: macos-26-xlarge version: stable-v2.24.3 - os: ubuntu-26.04 version: stable-v2.25.6 - - os: macos-latest-xlarge + - os: macos-26-xlarge version: stable-v2.25.6 - os: ubuntu-26.04 version: default - - os: macos-latest-xlarge + - os: macos-26-xlarge version: default - os: ubuntu-26.04 version: linked - - os: macos-latest-xlarge + - os: macos-26-xlarge version: linked - os: ubuntu-26.04 version: nightly-latest - - os: macos-latest-xlarge + - os: macos-26-xlarge version: nightly-latest name: Multi-language repository if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__per-language-bundle-validation.yml b/.github/workflows/__per-language-bundle-validation.yml index 177f4a0d8f..cb6b1a773d 100644 --- a/.github/workflows/__per-language-bundle-validation.yml +++ b/.github/workflows/__per-language-bundle-validation.yml @@ -68,7 +68,7 @@ jobs: os: ubuntu-26.04 version: linked - language: swift - os: macos-latest-xlarge + os: macos-26-xlarge version: linked build-mode: autobuild name: Per-language bundles diff --git a/.github/workflows/__swift-autobuild.yml b/.github/workflows/__swift-autobuild.yml index 52c189f3a8..4ba28f3489 100644 --- a/.github/workflows/__swift-autobuild.yml +++ b/.github/workflows/__swift-autobuild.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: include: - - os: macos-latest-xlarge + - os: macos-26-xlarge version: nightly-latest name: Swift analysis using autobuild if: github.triggering_actor != 'dependabot[bot]' diff --git a/.github/workflows/__swift-custom-build.yml b/.github/workflows/__swift-custom-build.yml index 000b681eb4..c38f0daa12 100644 --- a/.github/workflows/__swift-custom-build.yml +++ b/.github/workflows/__swift-custom-build.yml @@ -54,11 +54,11 @@ jobs: fail-fast: false matrix: include: - - os: macos-latest-xlarge + - os: macos-26-xlarge version: linked - - os: macos-latest-xlarge + - os: macos-26-xlarge version: default - - os: macos-latest-xlarge + - os: macos-26-xlarge version: nightly-latest name: Swift analysis using a custom build command if: github.triggering_actor != 'dependabot[bot]' diff --git a/pr-checks/checks/all-platform-bundle.yml b/pr-checks/checks/all-platform-bundle.yml index a13ba7cdee..24bd290159 100644 --- a/pr-checks/checks/all-platform-bundle.yml +++ b/pr-checks/checks/all-platform-bundle.yml @@ -3,7 +3,7 @@ description: "Tests using an all-platform CodeQL Bundle" operatingSystems: - ubuntu - os: macos - runner-image: macos-latest-xlarge + runner-image: macos-26-xlarge - windows versions: - nightly-latest diff --git a/pr-checks/checks/multi-language-autodetect.yml b/pr-checks/checks/multi-language-autodetect.yml index c826ac7ea6..108dcd8080 100644 --- a/pr-checks/checks/multi-language-autodetect.yml +++ b/pr-checks/checks/multi-language-autodetect.yml @@ -3,7 +3,7 @@ description: "An end-to-end integration test of a multi-language repository usin operatingSystems: - ubuntu - os: macos - runner-image: macos-latest-xlarge + runner-image: macos-26-xlarge # Older CodeQL CLI versions only support Swift up to 6.1, which requires Xcode 16. That is # not available on macOS 26, so run these versions on macOS 15 where we select Xcode 16 # below. See https://github.com/actions/runner-images/issues/14167. diff --git a/pr-checks/checks/per-language-bundle-validation.yml b/pr-checks/checks/per-language-bundle-validation.yml index 942611d628..b84c15494d 100644 --- a/pr-checks/checks/per-language-bundle-validation.yml +++ b/pr-checks/checks/per-language-bundle-validation.yml @@ -37,7 +37,7 @@ matrix: os: ubuntu-26.04 version: linked - language: swift - os: macos-latest-xlarge + os: macos-26-xlarge version: linked build-mode: autobuild installNode: true diff --git a/pr-checks/checks/swift-autobuild.yml b/pr-checks/checks/swift-autobuild.yml index 393857cd2c..8087e1aeef 100644 --- a/pr-checks/checks/swift-autobuild.yml +++ b/pr-checks/checks/swift-autobuild.yml @@ -4,7 +4,7 @@ versions: - nightly-latest operatingSystems: - os: macos - runner-image: macos-latest-xlarge + runner-image: macos-26-xlarge steps: - uses: ./../action/init id: init diff --git a/pr-checks/checks/swift-custom-build.yml b/pr-checks/checks/swift-custom-build.yml index 53131b1aef..a10c0a6ed7 100644 --- a/pr-checks/checks/swift-custom-build.yml +++ b/pr-checks/checks/swift-custom-build.yml @@ -6,7 +6,7 @@ versions: - nightly-latest operatingSystems: - os: macos - runner-image: macos-latest-xlarge + runner-image: macos-26-xlarge installGo: true installDotNet: true env: From 0aaf198c565dd3ffc69eff50b101ec42da89dc2a Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 11:43:19 +0000 Subject: [PATCH 152/174] Seperate checks in `pr-checks.yml` --- .github/workflows/pr-checks.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index ba6dfbcdb8..4736cef4ab 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -126,10 +126,15 @@ jobs: if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }} run: .github/workflows/script/verify-pr-checks.sh - - name: Run pr-checks checks + - name: Typecheck pr-checks scripts if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }} working-directory: pr-checks - run: npm run checks + run: npm run typecheck + + - name: Run pr-checks tests + if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }} + working-directory: pr-checks + run: npm run test - name: Run `pr-checks/changenotes.ts` to ensure that all unreleased change notes are valid if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }} From 3ecc7a9b7d5ff6d668a383a9c0963b03c7804b0c Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 12:56:44 +0000 Subject: [PATCH 153/174] Add change note --- unreleased-change-notes/macos-xcode-deprecation.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 unreleased-change-notes/macos-xcode-deprecation.md diff --git a/unreleased-change-notes/macos-xcode-deprecation.md b/unreleased-change-notes/macos-xcode-deprecation.md new file mode 100644 index 0000000000..ea7586d08f --- /dev/null +++ b/unreleased-change-notes/macos-xcode-deprecation.md @@ -0,0 +1 @@ +- Starting with macOS 27 and Xcode 27, traced analyses are unsupported. See [this blog post for more information](https://github.blog/changelog/2026-10-19-codeql-changes-for-macos-27-xcode-27-and-swift-6-4/). The CodeQL Action will now try to identify if a workflow is about to perform a traced analysis on version 27 or above of macOS or Xcode. If so, the CodeQL Action will emit a corresponding warning that will also be visible on the [Tool Status Page](https://docs.github.com/en/code-security/how-tos/find-and-fix-code-vulnerabilities/manage-your-configuration/use-the-tools-status-page-for-code-scanning). This check will be rolled out following this release of the CodeQL Action. [#4221](https://github.com/github/codeql-action/pull/4221) From b5b3ef7c6a1cb79be3bf0bfc836979d384501698 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 12:59:24 +0000 Subject: [PATCH 154/174] Fix Xcode skip on `self-hosted` runner test --- src/languages/traced.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index 2aa9318437..60a98e6bfd 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -363,7 +363,7 @@ test("checkRunnerSupportsTracedAnalysis doesn't perform Xcode check on self-host initAllState({ logger, platform: "darwin", - osRelease: "27.0.0", + osRelease: "26.0.0", env, features, }), @@ -371,7 +371,7 @@ test("checkRunnerSupportsTracedAnalysis doesn't perform Xcode check on self-host codeql, ); - checkUnexpectedLogMessages(t, logger.messages, [ + checkExpectedLogMessages(t, logger.messages, [ "Skipping traced analysis compatibility check for Xcode because we are on a self-hosted runner.", ]); })); From c56bb9b85b02e18f4fe3941da23a6b0fa6ff9162 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 13:00:33 +0000 Subject: [PATCH 155/174] Fix checks if FF is disabled test using the wrong predicate --- src/languages/traced.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index 60a98e6bfd..8de9512a5d 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -159,7 +159,7 @@ test("checkRunnerSupportsTracedAnalysis doesn't perform checks if FF is not enab const logger = new RecordingLogger(); const env = getTestEnv(); env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); + const features = createFeatures([]); const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", @@ -180,7 +180,7 @@ test("checkRunnerSupportsTracedAnalysis doesn't perform checks if FF is not enab codeql, ); - checkUnexpectedLogMessages(t, logger.messages, [ + checkExpectedLogMessages(t, logger.messages, [ "Skipping traced analysis compatibility checks because the feature is not enabled.", ]); })); From 104d2381d1d0e845848711ea035771db97f630b5 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 14:23:48 +0000 Subject: [PATCH 156/174] Update workflows --- .github/workflows/__unsupported-macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/__unsupported-macos.yml b/.github/workflows/__unsupported-macos.yml index a888ce757c..5e388d1ec0 100644 --- a/.github/workflows/__unsupported-macos.yml +++ b/.github/workflows/__unsupported-macos.yml @@ -100,7 +100,7 @@ jobs: contents: read security-events: read timeout-minutes: 5 - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 From 4a6767cdd0faaaa28ded2b054493fec5bafdb1a9 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 29 Oct 2026 16:41:01 +0000 Subject: [PATCH 157/174] Rename `xcodeVersion` to `xcodeVersionFromLink` --- lib/entry-points.js | 5 ++- src/platform.test.ts | 103 +++++++++++++++++++++++-------------------- src/platform.ts | 17 ++++++- 3 files changed, 75 insertions(+), 50 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index b2bb9c1835..8f903af15b 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -183448,7 +183448,7 @@ var XCODE_SELECT_LINK_PATH = "/private/var/db/xcode_select_link"; var XCODE_APP_FILENAME_PATTERN = new RegExp( /(?Xcode_(?\d+(\.\d+)?).*\.app)/ ); -function xcodeVersion(logger2) { +function xcodeVersionFromLink(logger2) { try { const xcodePath = import_fs.default.readlinkSync(XCODE_SELECT_LINK_PATH); if (xcodePath.trim() === "") { @@ -183476,6 +183476,9 @@ function xcodeVersion(logger2) { return void 0; } } +function xcodeVersion(logger2) { + return xcodeVersionFromLink(logger2); +} // src/per-language-bundles.ts var MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION = "2.27.1"; diff --git a/src/platform.test.ts b/src/platform.test.ts index 58c41408e5..d84ccb43d7 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -8,7 +8,7 @@ import { getBundlePlatform, darwinVersion, XCODE_SELECT_LINK_PATH, - xcodeVersion, + xcodeVersionFromLink, } from "./platform"; import { checkExpectedLogMessages, @@ -71,21 +71,24 @@ test("darwinVersion returns semver if parsing succeeds", (t) => { } }); -test.serial("xcodeVersion returns undefined if symlink doesn't exist", (t) => { - const logger = new RecordingLogger(); +test.serial( + "xcodeVersionFromLink returns undefined if symlink doesn't exist", + (t) => { + const logger = new RecordingLogger(); - const readlinkSync = sinon - .stub(fs, "readlinkSync") - .throws(new Error("ENOENT: no such file or directory")); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .throws(new Error("ENOENT: no such file or directory")); - t.is(xcodeVersion(logger), undefined); - t.is(readlinkSync.callCount, 1); - t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(xcodeVersionFromLink(logger), undefined); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); - checkExpectedLogMessages(t, logger.messages, [ - "Unable to determine Xcode version: ENOENT: no such file or directory", - ]); -}); + checkExpectedLogMessages(t, logger.messages, [ + "Unable to determine Xcode version: ENOENT: no such file or directory", + ]); + }, +); test.serial("xcodeVersion returns undefined if file is not a symlink", (t) => { const logger = new RecordingLogger(); @@ -94,7 +97,7 @@ test.serial("xcodeVersion returns undefined if file is not a symlink", (t) => { .stub(fs, "readlinkSync") .throws(new Error("EINVAL: invalid argument")); - t.is(xcodeVersion(logger), undefined); + t.is(xcodeVersionFromLink(logger), undefined); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); @@ -104,13 +107,13 @@ test.serial("xcodeVersion returns undefined if file is not a symlink", (t) => { }); test.serial( - "xcodeVersion returns undefined if resolving the symlink returns nothing", + "xcodeVersionFromLink returns undefined if resolving the symlink returns nothing", (t) => { const logger = new RecordingLogger(); const readlinkSync = sinon.stub(fs, "readlinkSync").returns(""); - t.is(xcodeVersion(logger), undefined); + t.is(xcodeVersionFromLink(logger), undefined); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); @@ -121,7 +124,7 @@ test.serial( ); test.serial( - "xcodeVersion returns undefined if resolved path doesn't include pattern", + "xcodeVersionFromLink returns undefined if resolved path doesn't include pattern", (t) => { const logger = new RecordingLogger(); @@ -129,7 +132,7 @@ test.serial( .stub(fs, "readlinkSync") .returns("/Applications/Xcode.app/Contents/Developer"); - t.is(xcodeVersion(logger), undefined); + t.is(xcodeVersionFromLink(logger), undefined); t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); @@ -139,30 +142,33 @@ test.serial( }, ); -test.serial("xcodeVersion returns undefined if match can't be parsed", (t) => { - const logger = new RecordingLogger(); +test.serial( + "xcodeVersionFromLink returns undefined if match can't be parsed", + (t) => { + const logger = new RecordingLogger(); - const readlinkSync = sinon - .stub(fs, "readlinkSync") - .returns("/Applications/Xcode_00.0.app/Contents/Developer"); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .returns("/Applications/Xcode_00.0.app/Contents/Developer"); - t.is(xcodeVersion(logger), undefined); - t.is(readlinkSync.callCount, 1); - t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(xcodeVersionFromLink(logger), undefined); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); - checkExpectedLogMessages(t, logger.messages, [ - "Couldn't parse '00.0' as a semantic version.", - ]); -}); + checkExpectedLogMessages(t, logger.messages, [ + "Couldn't parse '00.0' as a semantic version.", + ]); + }, +); -test.serial("xcodeVersion returns version from resolved path", (t) => { +test.serial("xcodeVersionFromLink returns version from resolved path", (t) => { const logger = new RecordingLogger(); const readlinkSync = sinon .stub(fs, "readlinkSync") .returns("/Applications/Xcode_16.4.app/Contents/Developer"); - const result = xcodeVersion(logger); + const result = xcodeVersionFromLink(logger); if (t.truthy(result)) { t.is(result.major, 16); @@ -173,26 +179,29 @@ test.serial("xcodeVersion returns version from resolved path", (t) => { t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); }); -test.serial("xcodeVersion returns major version from resolved path", (t) => { - const logger = new RecordingLogger(); +test.serial( + "xcodeVersionFromLink returns major version from resolved path", + (t) => { + const logger = new RecordingLogger(); - const readlinkSync = sinon - .stub(fs, "readlinkSync") - .returns("/Applications/Xcode_16.app/Contents/Developer"); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .returns("/Applications/Xcode_16.app/Contents/Developer"); - const result = xcodeVersion(logger); + const result = xcodeVersionFromLink(logger); - if (t.truthy(result)) { - t.is(result.major, 16); - t.is(result.minor, 0); - } + if (t.truthy(result)) { + t.is(result.major, 16); + t.is(result.minor, 0); + } - t.is(readlinkSync.callCount, 1); - t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); -}); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); + }, +); test.serial( - "xcodeVersion allows more version components in resolved path", + "xcodeVersionFromLink allows more version components in resolved path", (t) => { const logger = new RecordingLogger(); @@ -200,7 +209,7 @@ test.serial( .stub(fs, "readlinkSync") .returns("/Applications/Xcode_16.5.9.app/Contents/Developer"); - const result = xcodeVersion(logger); + const result = xcodeVersionFromLink(logger); if (t.truthy(result)) { t.is(result.major, 16); diff --git a/src/platform.ts b/src/platform.ts index e5c0e6ac63..37cd7fa11b 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -68,12 +68,15 @@ export const XCODE_APP_FILENAME_PATTERN = new RegExp( ); /** - * Tries to determine the version of Xcode that is installed. + * Tries to determine the version of Xcode that is installed from the resolved symbolic link + * at {@link XCODE_SELECT_LINK_PATH}. * * @param logger The logger to use. * @returns The Xcode version or `undefined` if it couldn't be determined. */ -export function xcodeVersion(logger: Logger): semver.SemVer | undefined { +export function xcodeVersionFromLink( + logger: Logger, +): semver.SemVer | undefined { try { // Read what the symbolic link points to. This will throw if `XCODE_SELECT_LINK_PATH` does not // exist (`ENOENT`) or is not a symbolic link (`EINVAL`). @@ -109,3 +112,13 @@ export function xcodeVersion(logger: Logger): semver.SemVer | undefined { return undefined; } } + +/** + * Tries to determine the version of Xcode that is installed. + * + * @param logger The logger to use. + * @returns The Xcode version or `undefined` if it couldn't be determined. + */ +export function xcodeVersion(logger: Logger): semver.SemVer | undefined { + return xcodeVersionFromLink(logger); +} From be54d791a11fa6fd2800a0353310bd0cebe58c38 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 29 Oct 2026 17:19:57 +0000 Subject: [PATCH 158/174] Add `xcrun`-based fallback for Xcode version detection --- lib/entry-points.js | 175 +++++++++++++++++++++++++--------------- src/languages/traced.ts | 2 +- src/platform.test.ts | 96 ++++++++++++++++++++++ src/platform.ts | 64 ++++++++++++++- 4 files changed, 270 insertions(+), 67 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 8f903af15b..81833ec2de 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -28347,7 +28347,7 @@ var require_io = __commonJS({ exports2.mv = mv; exports2.rmRF = rmRF; exports2.mkdirP = mkdirP; - exports2.which = which9; + exports2.which = which10; exports2.findInPath = findInPath; var assert_1 = require("assert"); var path30 = __importStar2(require("path")); @@ -28423,13 +28423,13 @@ var require_io = __commonJS({ yield ioUtil.mkdir(fsPath, { recursive: true }); }); } - function which9(tool, check) { + function which10(tool, check) { return __awaiter2(this, void 0, void 0, function* () { if (!tool) { throw new Error("parameter 'tool' is required"); } if (check) { - const result = yield which9(tool, false); + const result = yield which10(tool, false); if (!result) { if (ioUtil.IS_WINDOWS) { throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); @@ -28610,11 +28610,11 @@ var require_toolrunner = __commonJS({ var events = __importStar2(require("events")); var child = __importStar2(require("child_process")); var path30 = __importStar2(require("path")); - var io9 = __importStar2(require_io()); + var io10 = __importStar2(require_io()); var ioUtil = __importStar2(require_io_util()); var timers_1 = require("timers"); var IS_WINDOWS = process.platform === "win32"; - var ToolRunner7 = class extends events.EventEmitter { + var ToolRunner8 = class extends events.EventEmitter { constructor(toolPath, args, options) { super(); if (!toolPath) { @@ -28826,7 +28826,7 @@ var require_toolrunner = __commonJS({ if (!ioUtil.isRooted(this.toolPath) && (this.toolPath.includes("/") || IS_WINDOWS && this.toolPath.includes("\\"))) { this.toolPath = path30.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); } - this.toolPath = yield io9.which(this.toolPath, true); + this.toolPath = yield io10.which(this.toolPath, true); return new Promise((resolve15, reject) => __awaiter2(this, void 0, void 0, function* () { this._debug(`exec tool: ${this.toolPath}`); this._debug("arguments:"); @@ -28923,7 +28923,7 @@ var require_toolrunner = __commonJS({ }); } }; - exports2.ToolRunner = ToolRunner7; + exports2.ToolRunner = ToolRunner8; function argStringToArray(argString) { const args = []; let inQuotes = false; @@ -42426,7 +42426,7 @@ var require_cacheUtils = __commonJS({ var core29 = __importStar2(require_core()); var exec3 = __importStar2(require_exec()); var glob2 = __importStar2(require_glob()); - var io9 = __importStar2(require_io()); + var io10 = __importStar2(require_io()); var crypto3 = __importStar2(require("crypto")); var fs34 = __importStar2(require("fs")); var path30 = __importStar2(require("path")); @@ -42452,7 +42452,7 @@ var require_cacheUtils = __commonJS({ tempDirectory = path30.join(baseLocation, "actions", "temp"); } const dest = path30.join(tempDirectory, crypto3.randomUUID()); - yield io9.mkdirP(dest); + yield io10.mkdirP(dest); return dest; }); } @@ -42541,7 +42541,7 @@ var require_cacheUtils = __commonJS({ return constants_1.GnuTarPathOnWindows; } const versionOutput = yield getVersion("tar"); - return versionOutput.toLowerCase().includes("gnu tar") ? io9.which("tar") : ""; + return versionOutput.toLowerCase().includes("gnu tar") ? io10.which("tar") : ""; }); } function assertDefined(name, value) { @@ -113305,7 +113305,7 @@ var require_tar = __commonJS({ exports2.createTar = createTar; var core29 = __importStar2(require_core()); var exec_1 = require_exec(); - var io9 = __importStar2(require_io()); + var io10 = __importStar2(require_io()); var fs_1 = require("fs"); var path30 = __importStar2(require("path")); var utils = __importStar2(require_cacheUtils()); @@ -113325,12 +113325,12 @@ var require_tar = __commonJS({ break; } case "darwin": { - const gnuTar = yield io9.which("gtar", false); + const gnuTar = yield io10.which("gtar", false); if (gnuTar) { return { path: gnuTar, type: constants_1.ArchiveToolType.GNU }; } else { return { - path: yield io9.which("tar", true), + path: yield io10.which("tar", true), type: constants_1.ArchiveToolType.BSD }; } @@ -113339,7 +113339,7 @@ var require_tar = __commonJS({ break; } return { - path: yield io9.which("tar", true), + path: yield io10.which("tar", true), type: constants_1.ArchiveToolType.GNU }; }); @@ -113468,7 +113468,7 @@ var require_tar = __commonJS({ } finally { if (tempDirectory) { try { - yield io9.rmRF(tempDirectory); + yield io10.rmRF(tempDirectory); } catch (error3) { core29.debug(`Failed to delete temporary tar directory: ${error3}`); } @@ -113484,7 +113484,7 @@ var require_tar = __commonJS({ function extractTar3(archivePath, compressionMethod) { return __awaiter2(this, void 0, void 0, function* () { const workingDirectory = getWorkingDirectory(); - yield io9.mkdirP(workingDirectory); + yield io10.mkdirP(workingDirectory); yield execReadCommands(archivePath, compressionMethod, "extract"); }); } @@ -114348,7 +114348,7 @@ var require_tool_cache = __commonJS({ exports2.isExplicitVersion = isExplicitVersion; exports2.evaluateVersions = evaluateVersions; var core29 = __importStar2(require_core()); - var io9 = __importStar2(require_io()); + var io10 = __importStar2(require_io()); var crypto3 = __importStar2(require("crypto")); var fs34 = __importStar2(require("fs")); var mm = __importStar2(require_manifest()); @@ -114375,7 +114375,7 @@ var require_tool_cache = __commonJS({ function downloadTool3(url2, dest, auth2, headers) { return __awaiter2(this, void 0, void 0, function* () { dest = dest || path30.join(_getTempDirectory(), crypto3.randomUUID()); - yield io9.mkdirP(path30.dirname(dest)); + yield io10.mkdirP(path30.dirname(dest)); core29.debug(`Downloading ${url2}`); core29.debug(`Destination ${dest}`); const maxAttempts = 3; @@ -114428,7 +114428,7 @@ var require_tool_cache = __commonJS({ if (!succeeded) { core29.debug("download failed"); try { - yield io9.rmRF(dest); + yield io10.rmRF(dest); } catch (err) { core29.debug(`Failed to delete '${dest}'. ${err.message}`); } @@ -114483,7 +114483,7 @@ var require_tool_cache = __commonJS({ silent: true }; try { - const powershellPath = yield io9.which("powershell", true); + const powershellPath = yield io10.which("powershell", true); yield (0, exec_1.exec)(`"${powershellPath}"`, args, options); } finally { process.chdir(originalCwd); @@ -114550,7 +114550,7 @@ var require_tool_cache = __commonJS({ if (core29.isDebug()) { args.push("-v"); } - const xarPath = yield io9.which("xar", true); + const xarPath = yield io10.which("xar", true); yield (0, exec_1.exec)(`"${xarPath}"`, _unique(args)); return dest; }); @@ -114573,7 +114573,7 @@ var require_tool_cache = __commonJS({ return __awaiter2(this, void 0, void 0, function* () { const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, ""); const escapedDest = dest.replace(/'/g, "''").replace(/"|\n|\r/g, ""); - const pwshPath = yield io9.which("pwsh", false); + const pwshPath = yield io10.which("pwsh", false); if (pwshPath) { const pwshCommand = [ `$ErrorActionPreference = 'Stop' ;`, @@ -114609,7 +114609,7 @@ var require_tool_cache = __commonJS({ "-Command", powershellCommand ]; - const powershellPath = yield io9.which("powershell", true); + const powershellPath = yield io10.which("powershell", true); core29.debug(`Using powershell at path: ${powershellPath}`); yield (0, exec_1.exec)(`"${powershellPath}"`, args); } @@ -114617,7 +114617,7 @@ var require_tool_cache = __commonJS({ } function extractZipNix(file, dest) { return __awaiter2(this, void 0, void 0, function* () { - const unzipPath = yield io9.which("unzip", true); + const unzipPath = yield io10.which("unzip", true); const args = [file]; if (!core29.isDebug()) { args.unshift("-q"); @@ -114638,7 +114638,7 @@ var require_tool_cache = __commonJS({ const destPath = yield _createToolPath(tool, version, arch2); for (const itemName of fs34.readdirSync(sourceDir)) { const s = path30.join(sourceDir, itemName); - yield io9.cp(s, destPath, { recursive: true }); + yield io10.cp(s, destPath, { recursive: true }); } _completeToolPath(tool, version, arch2); return destPath; @@ -114656,7 +114656,7 @@ var require_tool_cache = __commonJS({ const destFolder = yield _createToolPath(tool, version, arch2); const destPath = path30.join(destFolder, targetFile); core29.debug(`destination file ${destPath}`); - yield io9.cp(sourceFile, destPath); + yield io10.cp(sourceFile, destPath); _completeToolPath(tool, version, arch2); return destFolder; }); @@ -114750,7 +114750,7 @@ var require_tool_cache = __commonJS({ if (!dest) { dest = path30.join(_getTempDirectory(), crypto3.randomUUID()); } - yield io9.mkdirP(dest); + yield io10.mkdirP(dest); return dest; }); } @@ -114759,9 +114759,9 @@ var require_tool_cache = __commonJS({ const folderPath = path30.join(_getCacheDirectory(), tool, semver12.clean(version) || version, arch2 || ""); core29.debug(`destination ${folderPath}`); const markerPath = `${folderPath}.complete`; - yield io9.rmRF(folderPath); - yield io9.rmRF(markerPath); - yield io9.mkdirP(folderPath); + yield io10.rmRF(folderPath); + yield io10.rmRF(markerPath); + yield io10.mkdirP(folderPath); return folderPath; }); } @@ -152391,13 +152391,13 @@ var require_io2 = __commonJS({ }); } exports2.mkdirP = mkdirP; - function which9(tool, check) { + function which10(tool, check) { return __awaiter2(this, void 0, void 0, function* () { if (!tool) { throw new Error("parameter 'tool' is required"); } if (check) { - const result = yield which9(tool, false); + const result = yield which10(tool, false); if (!result) { if (ioUtil.IS_WINDOWS) { throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); @@ -152414,7 +152414,7 @@ var require_io2 = __commonJS({ return ""; }); } - exports2.which = which9; + exports2.which = which10; function findInPath(tool) { return __awaiter2(this, void 0, void 0, function* () { if (!tool) { @@ -152565,11 +152565,11 @@ var require_toolrunner2 = __commonJS({ var events = __importStar2(require("events")); var child = __importStar2(require("child_process")); var path30 = __importStar2(require("path")); - var io9 = __importStar2(require_io2()); + var io10 = __importStar2(require_io2()); var ioUtil = __importStar2(require_io_util2()); var timers_1 = require("timers"); var IS_WINDOWS = process.platform === "win32"; - var ToolRunner7 = class extends events.EventEmitter { + var ToolRunner8 = class extends events.EventEmitter { constructor(toolPath, args, options) { super(); if (!toolPath) { @@ -152781,7 +152781,7 @@ var require_toolrunner2 = __commonJS({ if (!ioUtil.isRooted(this.toolPath) && (this.toolPath.includes("/") || IS_WINDOWS && this.toolPath.includes("\\"))) { this.toolPath = path30.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); } - this.toolPath = yield io9.which(this.toolPath, true); + this.toolPath = yield io10.which(this.toolPath, true); return new Promise((resolve15, reject) => __awaiter2(this, void 0, void 0, function* () { this._debug(`exec tool: ${this.toolPath}`); this._debug("arguments:"); @@ -152878,7 +152878,7 @@ var require_toolrunner2 = __commonJS({ }); } }; - exports2.ToolRunner = ToolRunner7; + exports2.ToolRunner = ToolRunner8; function argStringToArray(argString) { const args = []; let inQuotes = false; @@ -180446,13 +180446,13 @@ var SarifScanOrder = [ var fs19 = __toESM(require("fs")); var path16 = __toESM(require("path")); var import_perf_hooks5 = require("perf_hooks"); -var io5 = __toESM(require_io()); +var io6 = __toESM(require_io()); // src/codeql.ts var fs18 = __toESM(require("fs")); var path15 = __toESM(require("path")); var core12 = __toESM(require_core()); -var toolrunner3 = __toESM(require_toolrunner()); +var toolrunner4 = __toESM(require_toolrunner()); // src/cli-errors.ts var SUPPORTED_PLATFORMS = [ @@ -183421,6 +183421,8 @@ var semver7 = __toESM(require_semver2()); // src/platform.ts var import_fs = __toESM(require("fs")); +var toolrunner3 = __toESM(require_toolrunner()); +var io4 = __toESM(require_io()); var semver6 = __toESM(require_semver2()); function getBundlePlatform(platform2 = process.platform, arch2 = process.arch) { switch (platform2) { @@ -183476,8 +183478,53 @@ function xcodeVersionFromLink(logger2) { return void 0; } } -function xcodeVersion(logger2) { - return xcodeVersionFromLink(logger2); +async function xcodeVersionFromSdk(logger2) { + try { + const xcrun = await io4.which("xcrun", true); + let stdout = ""; + let stderr = ""; + const exitCode = await new toolrunner3.ToolRunner( + xcrun, + ["--sdk", "macosx", "--show-sdk-version"], + { + silent: true, + ignoreReturnCode: true, + listeners: { + stdout: (data) => { + stdout += data.toString("utf-8"); + }, + stderr: (data) => { + stderr += data.toString("utf-8"); + } + } + } + ).exec(); + if (exitCode !== 0) { + logger2.debug(`xcrun returned exit code ${exitCode}`); + logger2.debug(`stdout: +${stdout}`); + logger2.debug(`stderr: +${stderr}`); + return void 0; + } + const version = semver6.coerce(stdout.trim()); + if (version === null) { + logger2.debug( + `xcrun's output couldn't be parsed as a version: +${stdout}` + ); + logger2.debug(`stderr: +${stderr}`); + return void 0; + } + return version; + } catch (err) { + logger2.debug(`Unable to determine Xcode version: ${getErrorMessage(err)}`); + return void 0; + } +} +async function xcodeVersion(logger2) { + return xcodeVersionFromLink(logger2) ?? await xcodeVersionFromSdk(logger2); } // src/per-language-bundles.ts @@ -183662,13 +183709,13 @@ var import_child_process = require("child_process"); var fs14 = __toESM(require("fs")); var stream = __toESM(require("stream")); var import_toolrunner = __toESM(require_toolrunner()); -var io4 = __toESM(require_io()); +var io5 = __toESM(require_io()); var toolcache = __toESM(require_tool_cache()); var semver8 = __toESM(require_semver2()); var MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3"; var MIN_REQUIRED_GNU_TAR_VERSION = "1.31"; async function getTarVersion() { - const tar = await io4.which("tar", true); + const tar = await io5.which("tar", true); let stdout = ""; const exitCode = await new import_toolrunner.ToolRunner(tar, ["--version"], { listeners: { @@ -185157,7 +185204,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { ]) ); } - await new toolrunner3.ToolRunner(cmd, args, { + await new toolrunner4.ToolRunner(cmd, args, { env: env.getDefined() }).exec(); }, @@ -185178,7 +185225,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { if (automationDetailsId !== void 0) { args.push("--sarif-category", automationDetailsId); } - await new toolrunner3.ToolRunner(cmd, args, { + await new toolrunner4.ToolRunner(cmd, args, { env: env.getDefined() }).exec(); }, @@ -185207,13 +185254,13 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) { if (automationDetailsId !== void 0) { args.push("--sarif-category", automationDetailsId); } - await new toolrunner3.ToolRunner(cmd, args, { + await new toolrunner4.ToolRunner(cmd, args, { env: env.getDefined() }).exec(); }, async resolveExtractor(language) { let extractorPath = ""; - await new toolrunner3.ToolRunner( + await new toolrunner4.ToolRunner( cmd, [ "resolve", @@ -186156,7 +186203,7 @@ async function runFinalize(features, outputDir, threadsFlag, memoryFlag, codeql, async function warnIfGoInstalledAfterInit(config, logger2) { const goInitPath = process.env["CODEQL_ACTION_GO_BINARY" /* GO_BINARY_LOCATION */]; if (process.env["CODEQL_ACTION_DID_AUTOBUILD_GOLANG" /* DID_AUTOBUILD_GOLANG */] !== "true" && goInitPath !== void 0) { - const goBinaryPath = await io5.which("go", true); + const goBinaryPath = await io6.which("go", true); if (goInitPath !== goBinaryPath) { logger2.warning( `Expected \`which go\` to return ${goInitPath}, but got ${goBinaryPath}: please ensure that the correct version of Go is installed before the \`codeql-action/init\` Action is used.` @@ -187505,9 +187552,9 @@ async function addFingerprints(sarifLog, sourceRoot, logger2) { // src/init.ts var fs22 = __toESM(require("fs")); var path18 = __toESM(require("path")); -var toolrunner4 = __toESM(require_toolrunner()); +var toolrunner5 = __toESM(require_toolrunner()); var github3 = __toESM(require_github()); -var io6 = __toESM(require_io()); +var io7 = __toESM(require_io()); async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, rawLanguages, otherLanguagePacksReason, useOverlayAwareDefaultCliVersion, features, logger2) { logger2.startGroup("Setup CodeQL tools"); const { codeql, toolsDownloadStatusReport, toolsSource, toolsVersion } = await setupCodeQL( @@ -187620,7 +187667,7 @@ async function checkInstallPython311(languages, codeql) { "../python-setup", "check_python12.ps1" ); - await new toolrunner4.ToolRunner(await io6.which("powershell", true), [ + await new toolrunner5.ToolRunner(await io7.which("powershell", true), [ script ]).exec(); } @@ -190348,10 +190395,10 @@ var Minimatch = class { let ai = 0; let bi = 0; let result = []; - let which9 = ""; + let which10 = ""; while (ai < a.length && bi < b.length) { if (a[ai] === b[bi]) { - result.push(which9 === "b" ? b[bi] : a[ai]); + result.push(which10 === "b" ? b[bi] : a[ai]); ai++; bi++; } else if (emptyGSMatch && a[ai] === "**" && b[bi] === a[ai + 1]) { @@ -190361,16 +190408,16 @@ var Minimatch = class { result.push(b[bi]); bi++; } else if (a[ai] === "*" && b[bi] && (this.options.dot || !b[bi].startsWith(".")) && b[bi] !== "**") { - if (which9 === "b") + if (which10 === "b") return false; - which9 = "a"; + which10 = "a"; result.push(a[ai]); ai++; bi++; } else if (b[bi] === "*" && a[ai] && (this.options.dot || !a[ai].startsWith(".")) && a[ai] !== "**") { - if (which9 === "a") + if (which10 === "a") return false; - which9 = "b"; + which10 = "b"; result.push(b[bi]); ai++; bi++; @@ -193859,7 +193906,7 @@ async function runWrapper3() { var fs31 = __toESM(require("fs")); var path25 = __toESM(require("path")); var core19 = __toESM(require_core()); -var io7 = __toESM(require_io()); +var io8 = __toESM(require_io()); var semver11 = __toESM(require_semver2()); // src/config/inputs.ts @@ -194019,7 +194066,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { ); return; } - const xcodeVer = xcodeVersion(action.logger); + const xcodeVer = await xcodeVersion(action.logger); if (xcodeVer !== void 0 && xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED) { handleUnsupportedVersion( action.logger, @@ -194647,7 +194694,7 @@ async function run3(actionState) { } if (config.languages.includes("go" /* go */) && process.platform === "linux") { try { - const goBinaryPath = await io7.which("go", true); + const goBinaryPath = await io8.which("go", true); const fileOutput = await getFileType(goBinaryPath); if (fileOutput.includes("statically linked") && !await codeql.supportsFeature( "indirectTracingSupportsStaticBinaries" /* IndirectTracingSupportsStaticBinaries */ @@ -196002,8 +196049,8 @@ function generateCertificateAuthority() { // src/start-proxy/environment.ts var fs33 = __toESM(require("fs")); var path28 = __toESM(require("path")); -var toolrunner5 = __toESM(require_toolrunner()); -var io8 = __toESM(require_io()); +var toolrunner6 = __toESM(require_toolrunner()); +var io9 = __toESM(require_io()); function checkEnvVar(logger2, name) { const value = process.env[name]; if (isDefined2(value)) { @@ -196093,9 +196140,9 @@ function checkJdkSettings(logger2, jdkHome) { } async function showJavaSettings(logger2) { try { - const java = await io8.which("java", true); + const java = await io9.which("java", true); let output = ""; - await new toolrunner5.ToolRunner( + await new toolrunner6.ToolRunner( java, ["-XshowSettings:all", "-XshowSettings:security:all", "-version"], { diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 1e6442dd60..a84c3aa745 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -197,7 +197,7 @@ export async function checkRunnerSupportsTracedAnalysis( // Determining whether the Xcode version is supported only makes sense on macOS, so we only do it // after determining that we are running on macOS. - const xcodeVer = xcodeVersion(action.logger); + const xcodeVer = await xcodeVersion(action.logger); if ( xcodeVer !== undefined && diff --git a/src/platform.test.ts b/src/platform.test.ts index d84ccb43d7..22aca6b217 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -1,5 +1,8 @@ import fs from "fs"; +import type { ExecOptions } from "@actions/exec/lib/interfaces"; +import * as toolrunner from "@actions/exec/lib/toolrunner"; +import * as io from "@actions/io"; import test from "ava"; import * as sinon from "sinon"; @@ -9,6 +12,8 @@ import { darwinVersion, XCODE_SELECT_LINK_PATH, xcodeVersionFromLink, + xcodeVersion, + xcodeVersionFromSdk, } from "./platform"; import { checkExpectedLogMessages, @@ -220,3 +225,94 @@ test.serial( t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); }, ); + +test.serial( + "xcodeVersionFromSdk returns undefined for non-zero exit code", + async (t) => { + const logger = new RecordingLogger(); + + const which = sinon.stub(io, "which").resolves("/path/to/xcrun"); + const exec = sinon.stub<[], Promise>().resolves(1); + const runner = sinon.createStubInstance(toolrunner.ToolRunner, { exec }); + const toolrunnerStub = sinon.stub(toolrunner, "ToolRunner").returns(runner); + + await t.notThrowsAsync(async () => { + const result = await xcodeVersionFromSdk(logger); + + t.is(result, undefined); + + t.is(which.callCount, 1); + t.deepEqual(which.args[0], ["xcrun", true]); + + t.is(toolrunnerStub.callCount, 1); + t.is(exec.callCount, 1); + + checkExpectedLogMessages(t, logger.messages, [ + "xcrun returned exit code 1", + ]); + }); + }, +); + +test.serial( + "xcodeVersionFromSdk extracts version from xcrun stdout", + async (t) => { + const logger = new RecordingLogger(); + + const which = sinon.stub(io, "which").resolves("/path/to/xcrun"); + + let stdoutListener: ((data: Buffer) => void) | undefined = undefined; + const exec = sinon.stub<[], Promise>().callsFake(async () => { + if (stdoutListener !== undefined) { + stdoutListener(Buffer.from("26.5")); + } + return 0; + }); + const runner = sinon.createStubInstance(toolrunner.ToolRunner, { exec }); + + const toolrunnerStub = sinon + .stub(toolrunner, "ToolRunner") + .callsFake((_cmd, _args, opts: ExecOptions) => { + stdoutListener = opts.listeners?.stdout; + return runner; + }); + + await t.notThrowsAsync(async () => { + const result = await xcodeVersionFromSdk(logger); + + t.not(result, undefined); + t.is(result?.major, 26); + t.is(result?.minor, 5); + + t.is(which.callCount, 1); + t.deepEqual(which.args[0], ["xcrun", true]); + + t.is(toolrunnerStub.callCount, 1); + t.is(exec.callCount, 1); + }); + }, +); + +test.serial("xcodeVersion falls back to xcodeVersionFromSdk", async (t) => { + const logger = new RecordingLogger(); + + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .throws(new Error("ENOENT: no such file or directory")); + const which = sinon.stub(io, "which").throws(new Error("No such tool")); + + await t.notThrowsAsync(async () => { + const result = await xcodeVersion(logger); + + t.is(result, undefined); + + t.is(readlinkSync.callCount, 1); + t.is(which.callCount, 1); + t.deepEqual(which.args[0], ["xcrun", true]); + + checkExpectedLogMessages(t, logger.messages, [ + "Unable to determine Xcode version: ENOENT: no such file or directory", + "Unable to determine Xcode version: No such tool", + ]); + }); +}); diff --git a/src/platform.ts b/src/platform.ts index 37cd7fa11b..fd1487b503 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -1,5 +1,7 @@ import fs from "fs"; +import * as toolrunner from "@actions/exec/lib/toolrunner"; +import * as io from "@actions/io"; import * as semver from "semver"; import type { ActionState, Logger } from "./action-common"; @@ -113,12 +115,70 @@ export function xcodeVersionFromLink( } } +/** + * Tries to determine the version of Xcode that is installed by running `xcrun --sdk macosx --show-sdk-version`. + * + * @param logger The logger to use. + * @returns The Xcode version or `undefined` if it couldn't be determined. + */ +export async function xcodeVersionFromSdk( + logger: Logger, +): Promise { + try { + const xcrun = await io.which("xcrun", true); + let stdout = ""; + let stderr = ""; + + const exitCode = await new toolrunner.ToolRunner( + xcrun, + ["--sdk", "macosx", "--show-sdk-version"], + { + silent: true, + ignoreReturnCode: true, + listeners: { + stdout: (data: Buffer) => { + stdout += data.toString("utf-8"); + }, + stderr: (data: Buffer) => { + stderr += data.toString("utf-8"); + }, + }, + }, + ).exec(); + + if (exitCode !== 0) { + logger.debug(`xcrun returned exit code ${exitCode}`); + logger.debug(`stdout:\n${stdout}`); + logger.debug(`stderr:\n${stderr}`); + return undefined; + } + + // We expect the output to only be a version string. Try to parse it into a semver. + const version = semver.coerce(stdout.trim()); + + if (version === null) { + logger.debug( + `xcrun's output couldn't be parsed as a version:\n${stdout}`, + ); + logger.debug(`stderr:\n${stderr}`); + return undefined; + } + + return version; + } catch (err) { + logger.debug(`Unable to determine Xcode version: ${getErrorMessage(err)}`); + return undefined; + } +} + /** * Tries to determine the version of Xcode that is installed. * * @param logger The logger to use. * @returns The Xcode version or `undefined` if it couldn't be determined. */ -export function xcodeVersion(logger: Logger): semver.SemVer | undefined { - return xcodeVersionFromLink(logger); +export async function xcodeVersion( + logger: Logger, +): Promise { + return xcodeVersionFromLink(logger) ?? (await xcodeVersionFromSdk(logger)); } From 1fb93080c2afde80071fd6e6be7c331db1e37c1c Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 15:38:28 +0000 Subject: [PATCH 159/174] Fix test name --- src/platform.test.ts | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/platform.test.ts b/src/platform.test.ts index 22aca6b217..45e4ccf202 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -95,21 +95,24 @@ test.serial( }, ); -test.serial("xcodeVersion returns undefined if file is not a symlink", (t) => { - const logger = new RecordingLogger(); +test.serial( + "xcodeVersionFromLink returns undefined if file is not a symlink", + (t) => { + const logger = new RecordingLogger(); - const readlinkSync = sinon - .stub(fs, "readlinkSync") - .throws(new Error("EINVAL: invalid argument")); + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .throws(new Error("EINVAL: invalid argument")); - t.is(xcodeVersionFromLink(logger), undefined); - t.is(readlinkSync.callCount, 1); - t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(xcodeVersionFromLink(logger), undefined); + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); - checkExpectedLogMessages(t, logger.messages, [ - "Unable to determine Xcode version: EINVAL: invalid argument", - ]); -}); + checkExpectedLogMessages(t, logger.messages, [ + "Unable to determine Xcode version: EINVAL: invalid argument", + ]); + }, +); test.serial( "xcodeVersionFromLink returns undefined if resolving the symlink returns nothing", From 8f2596eca17ac9d6840a75002189167225dd6f64 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 15:51:13 +0000 Subject: [PATCH 160/174] Remove `xcodeVersion` and inline fallback logic in `checkRunnerSupportsTracedAnalysis` --- lib/entry-points.js | 5 +--- src/languages/traced.test.ts | 56 ++++++++++++++++++++++++++++++++++++ src/languages/traced.ts | 14 +++++++-- src/platform.test.ts | 25 ---------------- src/platform.ts | 12 -------- 5 files changed, 68 insertions(+), 44 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 81833ec2de..0d44bf8816 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -183523,9 +183523,6 @@ ${stderr}`); return void 0; } } -async function xcodeVersion(logger2) { - return xcodeVersionFromLink(logger2) ?? await xcodeVersionFromSdk(logger2); -} // src/per-language-bundles.ts var MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION = "2.27.1"; @@ -194066,7 +194063,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { ); return; } - const xcodeVer = await xcodeVersion(action.logger); + const xcodeVer = xcodeVersionFromLink(action.logger) ?? await xcodeVersionFromSdk(action.logger); if (xcodeVer !== void 0 && xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED) { handleUnsupportedVersion( action.logger, diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index 8de9512a5d..f317306efa 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -1,5 +1,6 @@ import fs from "fs"; +import * as io from "@actions/io"; import test from "ava"; import * as sinon from "sinon"; @@ -426,6 +427,61 @@ test.serial( }), ); +test.serial( + "checkRunnerSupportsTracedAnalysis uses Xcode SDK version as fallback", + async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); + + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .throws(new Error("Not found")); + const which = sinon.stub(io, "which").throws(new Error("Tool not found")); + + const codeql = await getCodeQLWithTracedStub( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); + + const config = createTestConfig({ + tempDir: tmpDir, + languages: [BuiltInLanguage.swift], + }); + await checkRunnerSupportsTracedAnalysis( + initAllState({ + logger, + platform: "darwin", + osRelease: "26.0.0", + env, + features, + }), + config, + codeql, + ); + + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); + t.is(which.callCount, 1); + t.deepEqual(which.args[0], ["xcrun", true]); + + checkExpectedLogMessages(t, logger.messages, [ + "Unable to determine Xcode version: Tool not found", + ]); + checkUnexpectedLogMessages(t, logger.messages, [ + "Traced analysis is not supported on Xcode 27", + ]); + + t.is(addDiagnostic.callCount, 0); + }), +); + // `addDiagnostic` changes global state and we must stub it, so this test must be serial. test.serial( "checkRunnerSupportsTracedAnalysis logs and adds diagnostic if Xcode version is unsupported", diff --git a/src/languages/traced.ts b/src/languages/traced.ts index a84c3aa745..9290190227 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -7,7 +7,11 @@ import type { ActionConfig } from "../config/action-config"; import { addDiagnostic, makeDiagnostic } from "../diagnostics"; import { DocUrl } from "../doc-url"; import { Feature } from "../feature-flags"; -import { darwinVersion, xcodeVersion } from "../platform"; +import { + darwinVersion, + xcodeVersionFromLink, + xcodeVersionFromSdk, +} from "../platform"; import { ConfigurationError } from "../util"; import { checkSwiftCompatibility } from "./swift"; @@ -196,8 +200,12 @@ export async function checkRunnerSupportsTracedAnalysis( } // Determining whether the Xcode version is supported only makes sense on macOS, so we only do it - // after determining that we are running on macOS. - const xcodeVer = await xcodeVersion(action.logger); + // after determining that we are running on macOS. We first try to obtain the version of Xcode itself + // starting with the cheapest approach. If that doesn't work, we obtain the version from the SDK instead. + // Since either Xcode or the SDK at version 27 or above is incompatible, the major version of either is fine. + const xcodeVer = + xcodeVersionFromLink(action.logger) ?? + (await xcodeVersionFromSdk(action.logger)); if ( xcodeVer !== undefined && diff --git a/src/platform.test.ts b/src/platform.test.ts index 45e4ccf202..152d5a8105 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -12,7 +12,6 @@ import { darwinVersion, XCODE_SELECT_LINK_PATH, xcodeVersionFromLink, - xcodeVersion, xcodeVersionFromSdk, } from "./platform"; import { @@ -295,27 +294,3 @@ test.serial( }); }, ); - -test.serial("xcodeVersion falls back to xcodeVersionFromSdk", async (t) => { - const logger = new RecordingLogger(); - - const readlinkSync = sinon - .stub(fs, "readlinkSync") - .throws(new Error("ENOENT: no such file or directory")); - const which = sinon.stub(io, "which").throws(new Error("No such tool")); - - await t.notThrowsAsync(async () => { - const result = await xcodeVersion(logger); - - t.is(result, undefined); - - t.is(readlinkSync.callCount, 1); - t.is(which.callCount, 1); - t.deepEqual(which.args[0], ["xcrun", true]); - - checkExpectedLogMessages(t, logger.messages, [ - "Unable to determine Xcode version: ENOENT: no such file or directory", - "Unable to determine Xcode version: No such tool", - ]); - }); -}); diff --git a/src/platform.ts b/src/platform.ts index fd1487b503..26c81b7aa1 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -170,15 +170,3 @@ export async function xcodeVersionFromSdk( return undefined; } } - -/** - * Tries to determine the version of Xcode that is installed. - * - * @param logger The logger to use. - * @returns The Xcode version or `undefined` if it couldn't be determined. - */ -export async function xcodeVersion( - logger: Logger, -): Promise { - return xcodeVersionFromLink(logger) ?? (await xcodeVersionFromSdk(logger)); -} From efea0445d3ca3302d5a335cadbdbf995b685c34e Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 16:14:50 +0000 Subject: [PATCH 161/174] Add `xcodeVersionFromXcodeBuild` --- lib/entry-points.js | 60 ++++++++++++++++++++++++++++++- src/languages/traced.test.ts | 34 +++++++++++++++--- src/languages/traced.ts | 7 ++-- src/platform.test.ts | 69 +++++++++++++++++++++++++++++++++++ src/platform.ts | 70 ++++++++++++++++++++++++++++++++++++ 5 files changed, 233 insertions(+), 7 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 0d44bf8816..2f9741b59f 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -183478,6 +183478,64 @@ function xcodeVersionFromLink(logger2) { return void 0; } } +async function xcodeVersionFromXcodeBuild(logger2) { + try { + const xcrun = await io4.which("xcrun", true); + let stdout = ""; + let stderr = ""; + const exitCode = await new toolrunner3.ToolRunner( + xcrun, + ["xcodebuild", "-version"], + { + silent: true, + ignoreReturnCode: true, + listeners: { + stdout: (data) => { + stdout += data.toString("utf-8"); + }, + stderr: (data) => { + stderr += data.toString("utf-8"); + } + } + } + ).exec(); + if (exitCode !== 0) { + logger2.debug(`xcodebuild returned exit code ${exitCode}`); + logger2.debug(`stdout: +${stdout}`); + logger2.debug(`stderr: +${stderr}`); + return void 0; + } + const match2 = stdout.match(/^Xcode (\d+(\.\d+)?)/); + if (match2 === null) { + logger2.debug( + `Output doesn't appear to contain the Xcode product version.` + ); + logger2.debug(`stdout: +${stdout}`); + logger2.debug(`stderr: +${stderr}`); + return void 0; + } + const version = semver6.coerce(match2[1].trim()); + if (version === null) { + logger2.debug( + `xcodebuild's output couldn't be parsed as a version: +${stdout}` + ); + logger2.debug(`stderr: +${stderr}`); + return void 0; + } + return version; + } catch (err) { + logger2.debug( + `Unable to determine Xcode version from xcodebuild: ${getErrorMessage(err)}` + ); + return void 0; + } +} async function xcodeVersionFromSdk(logger2) { try { const xcrun = await io4.which("xcrun", true); @@ -194063,7 +194121,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { ); return; } - const xcodeVer = xcodeVersionFromLink(action.logger) ?? await xcodeVersionFromSdk(action.logger); + const xcodeVer = xcodeVersionFromLink(action.logger) ?? await xcodeVersionFromXcodeBuild(action.logger) ?? await xcodeVersionFromSdk(action.logger); if (xcodeVer !== void 0 && xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED) { handleUnsupportedVersion( action.logger, diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index f317306efa..250295ebf3 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -1,5 +1,6 @@ import fs from "fs"; +import * as toolrunner from "@actions/exec/lib/toolrunner"; import * as io from "@actions/io"; import test from "ava"; import * as sinon from "sinon"; @@ -428,7 +429,7 @@ test.serial( ); test.serial( - "checkRunnerSupportsTracedAnalysis uses Xcode SDK version as fallback", + "checkRunnerSupportsTracedAnalysis attempts fallbacks if needed", async (t) => withTmpDir(async (tmpDir) => { const logger = new RecordingLogger(); @@ -439,7 +440,16 @@ test.serial( const readlinkSync = sinon .stub(fs, "readlinkSync") .throws(new Error("Not found")); - const which = sinon.stub(io, "which").throws(new Error("Tool not found")); + const which = sinon.stub(io, "which").resolves("/path/to/xcrun"); + const exec = sinon.stub<[], Promise>().callsFake(async () => { + throw new Error("Error to force next fallback"); + }); + const runner = sinon.createStubInstance(toolrunner.ToolRunner, { exec }); + const toolrunnerStub = sinon + .stub(toolrunner, "ToolRunner") + .callsFake(() => { + return runner; + }); const codeql = await getCodeQLWithTracedStub( "codeql-for-testing", @@ -468,11 +478,27 @@ test.serial( t.is(readlinkSync.callCount, 1); t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); - t.is(which.callCount, 1); + t.is(which.callCount, 2); t.deepEqual(which.args[0], ["xcrun", true]); + t.deepEqual(which.args[1], ["xcrun", true]); + + t.is(toolrunnerStub.callCount, 2); + t.is(exec.callCount, 2); + + t.is(toolrunnerStub.args[0][0], "/path/to/xcrun"); + t.deepEqual(toolrunnerStub.args[0][1], ["xcodebuild", "-version"]); + + t.is(toolrunnerStub.args[1][0], "/path/to/xcrun"); + t.deepEqual(toolrunnerStub.args[1][1], [ + "--sdk", + "macosx", + "--show-sdk-version", + ]); checkExpectedLogMessages(t, logger.messages, [ - "Unable to determine Xcode version: Tool not found", + "Unable to determine Xcode version: Not found", + "Unable to determine Xcode version from xcodebuild: Error to force next fallback", + "Unable to determine Xcode version: Error to force next fallback", ]); checkUnexpectedLogMessages(t, logger.messages, [ "Traced analysis is not supported on Xcode 27", diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 9290190227..090068e498 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -11,6 +11,7 @@ import { darwinVersion, xcodeVersionFromLink, xcodeVersionFromSdk, + xcodeVersionFromXcodeBuild, } from "../platform"; import { ConfigurationError } from "../util"; @@ -201,10 +202,12 @@ export async function checkRunnerSupportsTracedAnalysis( // Determining whether the Xcode version is supported only makes sense on macOS, so we only do it // after determining that we are running on macOS. We first try to obtain the version of Xcode itself - // starting with the cheapest approach. If that doesn't work, we obtain the version from the SDK instead. - // Since either Xcode or the SDK at version 27 or above is incompatible, the major version of either is fine. + // starting with the cheapest approach and then call out to an external program. If neither works, we try + // to obtain the version from the SDK instead. Since either Xcode or the SDK at version 27 or above is + // incompatible, either is fine as we only check the major version below. const xcodeVer = xcodeVersionFromLink(action.logger) ?? + (await xcodeVersionFromXcodeBuild(action.logger)) ?? (await xcodeVersionFromSdk(action.logger)); if ( diff --git a/src/platform.test.ts b/src/platform.test.ts index 152d5a8105..a0d2d34bf2 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -13,6 +13,7 @@ import { XCODE_SELECT_LINK_PATH, xcodeVersionFromLink, xcodeVersionFromSdk, + xcodeVersionFromXcodeBuild, } from "./platform"; import { checkExpectedLogMessages, @@ -228,6 +229,74 @@ test.serial( }, ); +test.serial( + "xcodeVersionFromXcodeBuild returns undefined for non-zero exit code", + async (t) => { + const logger = new RecordingLogger(); + + const which = sinon.stub(io, "which").resolves("/path/to/xcrun"); + const exec = sinon.stub<[], Promise>().resolves(1); + const runner = sinon.createStubInstance(toolrunner.ToolRunner, { exec }); + const toolrunnerStub = sinon.stub(toolrunner, "ToolRunner").returns(runner); + + await t.notThrowsAsync(async () => { + const result = await xcodeVersionFromXcodeBuild(logger); + + t.is(result, undefined); + + t.is(which.callCount, 1); + t.deepEqual(which.args[0], ["xcrun", true]); + + t.is(toolrunnerStub.callCount, 1); + t.is(exec.callCount, 1); + + checkExpectedLogMessages(t, logger.messages, [ + "xcodebuild returned exit code 1", + ]); + }); + }, +); + +test.serial( + "xcodeVersionFromXcodeBuild extracts version from xcrun stdout", + async (t) => { + const logger = new RecordingLogger(); + + const which = sinon.stub(io, "which").resolves("/path/to/xcrun"); + + let stdoutListener: ((data: Buffer) => void) | undefined = undefined; + const exec = sinon.stub<[], Promise>().callsFake(async () => { + if (stdoutListener !== undefined) { + stdoutListener(Buffer.from("Xcode 26.5")); + stdoutListener(Buffer.from("Build version 26F9")); + } + return 0; + }); + const runner = sinon.createStubInstance(toolrunner.ToolRunner, { exec }); + + const toolrunnerStub = sinon + .stub(toolrunner, "ToolRunner") + .callsFake((_cmd, _args, opts: ExecOptions) => { + stdoutListener = opts.listeners?.stdout; + return runner; + }); + + await t.notThrowsAsync(async () => { + const result = await xcodeVersionFromXcodeBuild(logger); + + t.not(result, undefined); + t.is(result?.major, 26); + t.is(result?.minor, 5); + + t.is(which.callCount, 1); + t.deepEqual(which.args[0], ["xcrun", true]); + + t.is(toolrunnerStub.callCount, 1); + t.is(exec.callCount, 1); + }); + }, +); + test.serial( "xcodeVersionFromSdk returns undefined for non-zero exit code", async (t) => { diff --git a/src/platform.ts b/src/platform.ts index 26c81b7aa1..ef66de3003 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -115,6 +115,76 @@ export function xcodeVersionFromLink( } } +/** + * Tries to determine the version of Xcode that is installed by running `xcrun xcodebuild -version`. + * + * @param logger The logger to use. + * @returns The Xcode version or `undefined` if it couldn't be determined. + */ +export async function xcodeVersionFromXcodeBuild( + logger: Logger, +): Promise { + try { + const xcrun = await io.which("xcrun", true); + let stdout = ""; + let stderr = ""; + + const exitCode = await new toolrunner.ToolRunner( + xcrun, + ["xcodebuild", "-version"], + { + silent: true, + ignoreReturnCode: true, + listeners: { + stdout: (data: Buffer) => { + stdout += data.toString("utf-8"); + }, + stderr: (data: Buffer) => { + stderr += data.toString("utf-8"); + }, + }, + }, + ).exec(); + + if (exitCode !== 0) { + logger.debug(`xcodebuild returned exit code ${exitCode}`); + logger.debug(`stdout:\n${stdout}`); + logger.debug(`stderr:\n${stderr}`); + return undefined; + } + + // The output contains a couple of lines, but we only care about the product version. + const match = stdout.match(/^Xcode (\d+(\.\d+)?)/); + + if (match === null) { + logger.debug( + `Output doesn't appear to contain the Xcode product version.`, + ); + logger.debug(`stdout:\n${stdout}`); + logger.debug(`stderr:\n${stderr}`); + return undefined; + } + + // We expect the output to only be a version string. Try to parse it into a semver. + const version = semver.coerce(match[1].trim()); + + if (version === null) { + logger.debug( + `xcodebuild's output couldn't be parsed as a version:\n${stdout}`, + ); + logger.debug(`stderr:\n${stderr}`); + return undefined; + } + + return version; + } catch (err) { + logger.debug( + `Unable to determine Xcode version from xcodebuild: ${getErrorMessage(err)}`, + ); + return undefined; + } +} + /** * Tries to determine the version of Xcode that is installed by running `xcrun --sdk macosx --show-sdk-version`. * From 80d7b74bf4895008a44edfb29e403630ff5ecd53 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 16:18:06 +0000 Subject: [PATCH 162/174] Rename `xcodeVersionFromSdk` and improve comments/log messages --- lib/entry-points.js | 8 +++-- src/languages/traced.test.ts | 2 +- src/languages/traced.ts | 4 +-- src/platform.test.ts | 65 +++++++++++++++++------------------- src/platform.ts | 11 +++--- 5 files changed, 46 insertions(+), 44 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 2f9741b59f..2a2537cf52 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -183536,7 +183536,7 @@ ${stderr}`); return void 0; } } -async function xcodeVersionFromSdk(logger2) { +async function xcodeSdkVersion(logger2) { try { const xcrun = await io4.which("xcrun", true); let stdout = ""; @@ -183577,7 +183577,9 @@ ${stderr}`); } return version; } catch (err) { - logger2.debug(`Unable to determine Xcode version: ${getErrorMessage(err)}`); + logger2.debug( + `Unable to determine Xcode SDK version: ${getErrorMessage(err)}` + ); return void 0; } } @@ -194121,7 +194123,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { ); return; } - const xcodeVer = xcodeVersionFromLink(action.logger) ?? await xcodeVersionFromXcodeBuild(action.logger) ?? await xcodeVersionFromSdk(action.logger); + const xcodeVer = xcodeVersionFromLink(action.logger) ?? await xcodeVersionFromXcodeBuild(action.logger) ?? await xcodeSdkVersion(action.logger); if (xcodeVer !== void 0 && xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED) { handleUnsupportedVersion( action.logger, diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index 250295ebf3..08d5291084 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -498,7 +498,7 @@ test.serial( checkExpectedLogMessages(t, logger.messages, [ "Unable to determine Xcode version: Not found", "Unable to determine Xcode version from xcodebuild: Error to force next fallback", - "Unable to determine Xcode version: Error to force next fallback", + "Unable to determine Xcode SDK version: Error to force next fallback", ]); checkUnexpectedLogMessages(t, logger.messages, [ "Traced analysis is not supported on Xcode 27", diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 090068e498..08b886376e 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -10,7 +10,7 @@ import { Feature } from "../feature-flags"; import { darwinVersion, xcodeVersionFromLink, - xcodeVersionFromSdk, + xcodeSdkVersion, xcodeVersionFromXcodeBuild, } from "../platform"; import { ConfigurationError } from "../util"; @@ -208,7 +208,7 @@ export async function checkRunnerSupportsTracedAnalysis( const xcodeVer = xcodeVersionFromLink(action.logger) ?? (await xcodeVersionFromXcodeBuild(action.logger)) ?? - (await xcodeVersionFromSdk(action.logger)); + (await xcodeSdkVersion(action.logger)); if ( xcodeVer !== undefined && diff --git a/src/platform.test.ts b/src/platform.test.ts index a0d2d34bf2..e696142027 100644 --- a/src/platform.test.ts +++ b/src/platform.test.ts @@ -12,7 +12,7 @@ import { darwinVersion, XCODE_SELECT_LINK_PATH, xcodeVersionFromLink, - xcodeVersionFromSdk, + xcodeSdkVersion, xcodeVersionFromXcodeBuild, } from "./platform"; import { @@ -298,7 +298,7 @@ test.serial( ); test.serial( - "xcodeVersionFromSdk returns undefined for non-zero exit code", + "xcodeSdkVersion returns undefined for non-zero exit code", async (t) => { const logger = new RecordingLogger(); @@ -308,7 +308,7 @@ test.serial( const toolrunnerStub = sinon.stub(toolrunner, "ToolRunner").returns(runner); await t.notThrowsAsync(async () => { - const result = await xcodeVersionFromSdk(logger); + const result = await xcodeSdkVersion(logger); t.is(result, undefined); @@ -325,41 +325,38 @@ test.serial( }, ); -test.serial( - "xcodeVersionFromSdk extracts version from xcrun stdout", - async (t) => { - const logger = new RecordingLogger(); +test.serial("xcodeSdkVersion extracts version from xcrun stdout", async (t) => { + const logger = new RecordingLogger(); - const which = sinon.stub(io, "which").resolves("/path/to/xcrun"); + const which = sinon.stub(io, "which").resolves("/path/to/xcrun"); - let stdoutListener: ((data: Buffer) => void) | undefined = undefined; - const exec = sinon.stub<[], Promise>().callsFake(async () => { - if (stdoutListener !== undefined) { - stdoutListener(Buffer.from("26.5")); - } - return 0; - }); - const runner = sinon.createStubInstance(toolrunner.ToolRunner, { exec }); + let stdoutListener: ((data: Buffer) => void) | undefined = undefined; + const exec = sinon.stub<[], Promise>().callsFake(async () => { + if (stdoutListener !== undefined) { + stdoutListener(Buffer.from("26.5")); + } + return 0; + }); + const runner = sinon.createStubInstance(toolrunner.ToolRunner, { exec }); - const toolrunnerStub = sinon - .stub(toolrunner, "ToolRunner") - .callsFake((_cmd, _args, opts: ExecOptions) => { - stdoutListener = opts.listeners?.stdout; - return runner; - }); + const toolrunnerStub = sinon + .stub(toolrunner, "ToolRunner") + .callsFake((_cmd, _args, opts: ExecOptions) => { + stdoutListener = opts.listeners?.stdout; + return runner; + }); - await t.notThrowsAsync(async () => { - const result = await xcodeVersionFromSdk(logger); + await t.notThrowsAsync(async () => { + const result = await xcodeSdkVersion(logger); - t.not(result, undefined); - t.is(result?.major, 26); - t.is(result?.minor, 5); + t.not(result, undefined); + t.is(result?.major, 26); + t.is(result?.minor, 5); - t.is(which.callCount, 1); - t.deepEqual(which.args[0], ["xcrun", true]); + t.is(which.callCount, 1); + t.deepEqual(which.args[0], ["xcrun", true]); - t.is(toolrunnerStub.callCount, 1); - t.is(exec.callCount, 1); - }); - }, -); + t.is(toolrunnerStub.callCount, 1); + t.is(exec.callCount, 1); + }); +}); diff --git a/src/platform.ts b/src/platform.ts index ef66de3003..283a789c0b 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -186,12 +186,13 @@ export async function xcodeVersionFromXcodeBuild( } /** - * Tries to determine the version of Xcode that is installed by running `xcrun --sdk macosx --show-sdk-version`. + * Tries to determine the version of the Xcode SDK that is installed by running + * `xcrun --sdk macosx --show-sdk-version`. * * @param logger The logger to use. - * @returns The Xcode version or `undefined` if it couldn't be determined. + * @returns The Xcode SDK version or `undefined` if it couldn't be determined. */ -export async function xcodeVersionFromSdk( +export async function xcodeSdkVersion( logger: Logger, ): Promise { try { @@ -236,7 +237,9 @@ export async function xcodeVersionFromSdk( return version; } catch (err) { - logger.debug(`Unable to determine Xcode version: ${getErrorMessage(err)}`); + logger.debug( + `Unable to determine Xcode SDK version: ${getErrorMessage(err)}`, + ); return undefined; } } From a189728bdd709a4bf697869ed02bf3d538b77c51 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 16:37:57 +0000 Subject: [PATCH 163/174] Exclude more unused files in `tsconfig.json` --- pr-checks/tsconfig.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pr-checks/tsconfig.json b/pr-checks/tsconfig.json index 367148ab9a..f75a95289b 100644 --- a/pr-checks/tsconfig.json +++ b/pr-checks/tsconfig.json @@ -9,5 +9,12 @@ "noEmit": true }, "include": ["./**/*.ts", "../src/**/*.ts"], - "exclude": ["node_modules", "../src/**/*.test.ts"] + "exclude": [ + "node_modules", + "../src/testdata/**", + "../src/**/*.test.ts", + "../src/testing-utils.ts", + "../src/json/testing-util.ts", + "../src/feature-flags/testing-util.ts" + ] } From ce1de8daeaac5948e003d5719dc21e192722c4d7 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 16:44:04 +0000 Subject: [PATCH 164/174] Run Xcode check on self-hosted runners --- lib/entry-points.js | 6 ------ src/languages/traced.test.ts | 32 -------------------------------- src/languages/traced.ts | 10 ---------- 3 files changed, 48 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 2a2537cf52..1445e238ec 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -194117,12 +194117,6 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { ); return; } - if (isSelfHostedRunner(action.env)) { - action.logger.debug( - "Skipping traced analysis compatibility check for Xcode because we are on a self-hosted runner." - ); - return; - } const xcodeVer = xcodeVersionFromLink(action.logger) ?? await xcodeVersionFromXcodeBuild(action.logger) ?? await xcodeSdkVersion(action.logger); if (xcodeVer !== void 0 && xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED) { handleUnsupportedVersion( diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index 08d5291084..2b9d50dfab 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -346,38 +346,6 @@ test.serial( }), ); -test("checkRunnerSupportsTracedAnalysis doesn't perform Xcode check on self-hosted runners", async (t) => - withTmpDir(async (tmpDir) => { - const logger = new RecordingLogger(); - const env = getTestEnv(); - env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); - env.set(ActionsEnvVars.RUNNER_ENVIRONMENT, "self-hosted"); - const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); - - const codeql = await getCodeQLWithTracedStub( - "codeql-for-testing", - logger, - env, - ); - sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); - - await checkRunnerSupportsTracedAnalysis( - initAllState({ - logger, - platform: "darwin", - osRelease: "26.0.0", - env, - features, - }), - createTestConfig({ tempDir: tmpDir, languages: [BuiltInLanguage.go] }), - codeql, - ); - - checkExpectedLogMessages(t, logger.messages, [ - "Skipping traced analysis compatibility check for Xcode because we are on a self-hosted runner.", - ]); - })); - // `addDiagnostic` changes global state and we must stub it, so this test must be serial. test.serial( "checkRunnerSupportsTracedAnalysis doesn't add a diagnostic if Xcode version is supported", diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 08b886376e..92eca5efe3 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -1,7 +1,6 @@ import * as semver from "semver"; import type { ActionState, Logger } from "../action-common"; -import { isSelfHostedRunner } from "../actions-util"; import type { CodeQL } from "../codeql"; import type { ActionConfig } from "../config/action-config"; import { addDiagnostic, makeDiagnostic } from "../diagnostics"; @@ -191,15 +190,6 @@ export async function checkRunnerSupportsTracedAnalysis( return; } - // Skip if we are on a self-hosted runner since the current Xcode version detection - // is only validated on hosted runners. - if (isSelfHostedRunner(action.env)) { - action.logger.debug( - "Skipping traced analysis compatibility check for Xcode because we are on a self-hosted runner.", - ); - return; - } - // Determining whether the Xcode version is supported only makes sense on macOS, so we only do it // after determining that we are running on macOS. We first try to obtain the version of Xcode itself // starting with the cheapest approach and then call out to an external program. If neither works, we try From 410d706e43e6dae32abb6a4e9eef48290317f54e Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 16:57:53 +0000 Subject: [PATCH 165/174] Combine product name and version into `ProductVersion` type --- lib/entry-points.js | 9 ++++----- src/languages/traced.ts | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 1445e238ec..ddd43b41da 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -194018,7 +194018,8 @@ async function checkSwiftCompatibility(config, codeql, darwinVersion2) { // src/languages/traced.ts var UNSUPPORTED_DARWIN_FOR_TRACED = 27; var UNSUPPORTED_XCODE_FOR_TRACED = 27; -function handleUnsupportedVersion(logger2, config, tracedLanguages, abortUnsupportedTracedAnalysis, product, version) { +function handleUnsupportedVersion(logger2, config, tracedLanguages, abortUnsupportedTracedAnalysis, productVersion) { + const { product, version } = productVersion; const unsupportedVersion = product === "macOS" ? UNSUPPORTED_DARWIN_FOR_TRACED : UNSUPPORTED_XCODE_FOR_TRACED; const baseMessage = [ `Traced analysis is not supported on ${product} ${unsupportedVersion} or above.`, @@ -194112,8 +194113,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { config, tracedLanguages, abortUnsupportedTracedAnalysis, - "macOS", - version + { product: "macOS", version } ); return; } @@ -194124,8 +194124,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { config, tracedLanguages, abortUnsupportedTracedAnalysis, - "Xcode", - xcodeVer + { product: "Xcode", version: xcodeVer } ); } else if (xcodeVer === void 0) { action.logger.info( diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 92eca5efe3..a6fedd67e1 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -22,6 +22,12 @@ export const UNSUPPORTED_DARWIN_FOR_TRACED = 27; /** Xcode 27 and above do not support traced extraction. */ export const UNSUPPORTED_XCODE_FOR_TRACED = 27; +/** A version along with the product it relates to. */ +type ProductVersion = { + product: "macOS" | "Xcode"; + version: semver.SemVer; +}; + /** * Creates a diagnostic indicating that `version` of `product` is unsupported for traced analysis. * Depending on `skipUnsupportedTracedAnalysis`, this function then either throws a {@link ConfigurationError} @@ -31,17 +37,16 @@ export const UNSUPPORTED_XCODE_FOR_TRACED = 27; * @param config The CodeQL Action configuration. * @param tracedLanguages Traced languages that are configured for analysis. * @param abortUnsupportedTracedAnalysis Whether this is a fatal error. - * @param product The product that the version is unsupported of. - * @param version The unsupported version. + * @param productVersion A description of the product and its version that is unsupported. */ function handleUnsupportedVersion( logger: Logger, config: ActionConfig<"dbLocation" | "tempDir">, tracedLanguages: string[], abortUnsupportedTracedAnalysis: boolean, - product: "macOS" | "Xcode", - version: semver.SemVer, + productVersion: ProductVersion, ) { + const { product, version } = productVersion; const unsupportedVersion = product === "macOS" ? UNSUPPORTED_DARWIN_FOR_TRACED @@ -181,8 +186,7 @@ export async function checkRunnerSupportsTracedAnalysis( config, tracedLanguages, abortUnsupportedTracedAnalysis, - "macOS", - version, + { product: "macOS", version }, ); // Return early so that we don't end up producing more-or-less the same log message/diagnostic @@ -209,8 +213,7 @@ export async function checkRunnerSupportsTracedAnalysis( config, tracedLanguages, abortUnsupportedTracedAnalysis, - "Xcode", - xcodeVer, + { product: "Xcode", version: xcodeVer }, ); } else if (xcodeVer === undefined) { action.logger.info( From 8d18caadc81554aba4706c3c8772e4991fd14382 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 17:09:47 +0000 Subject: [PATCH 166/174] Distinguish between Xcode and SDK version in messages --- lib/entry-points.js | 31 +++++++++++++++++++++++----- src/languages/traced.ts | 45 +++++++++++++++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index ddd43b41da..093dcf159a 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -194018,15 +194018,29 @@ async function checkSwiftCompatibility(config, codeql, darwinVersion2) { // src/languages/traced.ts var UNSUPPORTED_DARWIN_FOR_TRACED = 27; var UNSUPPORTED_XCODE_FOR_TRACED = 27; +function diagnosticAttributeName(product) { + switch (product) { + case "macOS": + return "darwinVersion"; + case "Xcode": + return "xcodeVersion"; + case "Xcode SDK": + return "xcodeSdkVersion"; + } +} function handleUnsupportedVersion(logger2, config, tracedLanguages, abortUnsupportedTracedAnalysis, productVersion) { const { product, version } = productVersion; - const unsupportedVersion = product === "macOS" ? UNSUPPORTED_DARWIN_FOR_TRACED : UNSUPPORTED_XCODE_FOR_TRACED; + const unsupportedVersion = product === "macOS" ? UNSUPPORTED_DARWIN_FOR_TRACED : ( + // We use the same constant for both Xcode and the Xcode SDK since we treat them + // as equivalent indicators for whether traced analysis is unsupported. + UNSUPPORTED_XCODE_FOR_TRACED + ); const baseMessage = [ `Traced analysis is not supported on ${product} ${unsupportedVersion} or above.`, `Configure your analysis to run on macOS ${UNSUPPORTED_DARWIN_FOR_TRACED - 1} or below`, `and Xcode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.` ].join(" "); - const attributeName = product === "macOS" ? "darwinVersion" : "xcodeVersion"; + const attributeName = diagnosticAttributeName(product); for (const language of tracedLanguages) { addDiagnostic( config, @@ -194117,14 +194131,21 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { ); return; } - const xcodeVer = xcodeVersionFromLink(action.logger) ?? await xcodeVersionFromXcodeBuild(action.logger) ?? await xcodeSdkVersion(action.logger); - if (xcodeVer !== void 0 && xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED) { + const xcodeVer = xcodeVersionFromLink(action.logger) ?? await xcodeVersionFromXcodeBuild(action.logger); + let xcodeProduct = void 0; + if (xcodeVer !== void 0) { + xcodeProduct = { product: "Xcode", version: xcodeVer }; + } else { + const xcodeSdkVer = await xcodeSdkVersion(action.logger); + xcodeProduct = xcodeSdkVer !== void 0 ? { product: "Xcode SDK", version: xcodeSdkVer } : void 0; + } + if (xcodeProduct !== void 0 && xcodeProduct.version.major >= UNSUPPORTED_XCODE_FOR_TRACED) { handleUnsupportedVersion( action.logger, config, tracedLanguages, abortUnsupportedTracedAnalysis, - { product: "Xcode", version: xcodeVer } + xcodeProduct ); } else if (xcodeVer === void 0) { action.logger.info( diff --git a/src/languages/traced.ts b/src/languages/traced.ts index a6fedd67e1..12ecd03a3c 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -22,12 +22,27 @@ export const UNSUPPORTED_DARWIN_FOR_TRACED = 27; /** Xcode 27 and above do not support traced extraction. */ export const UNSUPPORTED_XCODE_FOR_TRACED = 27; +/** Names of products that we check the versions of here. */ +type ProductName = "macOS" | "Xcode" | "Xcode SDK"; + /** A version along with the product it relates to. */ type ProductVersion = { - product: "macOS" | "Xcode"; + product: ProductName; version: semver.SemVer; }; +/** Gets the appropriate attribute name for the diagnostic based on {@link product}. */ +function diagnosticAttributeName(product: ProductName): string { + switch (product) { + case "macOS": + return "darwinVersion"; + case "Xcode": + return "xcodeVersion"; + case "Xcode SDK": + return "xcodeSdkVersion"; + } +} + /** * Creates a diagnostic indicating that `version` of `product` is unsupported for traced analysis. * Depending on `skipUnsupportedTracedAnalysis`, this function then either throws a {@link ConfigurationError} @@ -50,14 +65,17 @@ function handleUnsupportedVersion( const unsupportedVersion = product === "macOS" ? UNSUPPORTED_DARWIN_FOR_TRACED - : UNSUPPORTED_XCODE_FOR_TRACED; + : // We use the same constant for both Xcode and the Xcode SDK since we treat them + // as equivalent indicators for whether traced analysis is unsupported. + UNSUPPORTED_XCODE_FOR_TRACED; + const baseMessage = [ `Traced analysis is not supported on ${product} ${unsupportedVersion} or above.`, `Configure your analysis to run on macOS ${UNSUPPORTED_DARWIN_FOR_TRACED - 1} or below`, `and Xcode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.`, ].join(" "); - const attributeName = product === "macOS" ? "darwinVersion" : "xcodeVersion"; + const attributeName = diagnosticAttributeName(product); // Create a diagnostic that will show up on the TSP. for (const language of tracedLanguages) { @@ -201,19 +219,30 @@ export async function checkRunnerSupportsTracedAnalysis( // incompatible, either is fine as we only check the major version below. const xcodeVer = xcodeVersionFromLink(action.logger) ?? - (await xcodeVersionFromXcodeBuild(action.logger)) ?? - (await xcodeSdkVersion(action.logger)); + (await xcodeVersionFromXcodeBuild(action.logger)); + let xcodeProduct: ProductVersion | undefined = undefined; + + if (xcodeVer !== undefined) { + xcodeProduct = { product: "Xcode", version: xcodeVer }; + } else { + // Fallback to checking the SDK version, which may be available even if a full Xcode installation is not. + const xcodeSdkVer = await xcodeSdkVersion(action.logger); + xcodeProduct = + xcodeSdkVer !== undefined + ? { product: "Xcode SDK", version: xcodeSdkVer } + : undefined; + } if ( - xcodeVer !== undefined && - xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED + xcodeProduct !== undefined && + xcodeProduct.version.major >= UNSUPPORTED_XCODE_FOR_TRACED ) { handleUnsupportedVersion( action.logger, config, tracedLanguages, abortUnsupportedTracedAnalysis, - { product: "Xcode", version: xcodeVer }, + xcodeProduct, ); } else if (xcodeVer === undefined) { action.logger.info( From 0b97d537111f2ceccc660cfbdad7ce5be1b37f3a Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Fri, 30 Oct 2026 16:14:46 +0000 Subject: [PATCH 167/174] Extract zstd bundles using the tar path found by getTarVersion Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 10 +++++----- src/tar.test.ts | 2 +- src/tar.ts | 12 +++++++----- src/tools-download.test.ts | 10 +++++----- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index b2bb9c1835..4e142c5172 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -183682,13 +183682,13 @@ async function getTarVersion() { if (!match2?.[1]) { throw new Error("Failed to parse output of tar --version."); } - return { type: "gnu", version: match2[1] }; + return { type: "gnu", version: match2[1], path: tar }; } else if (stdout.includes("bsdtar")) { const match2 = stdout.match(/bsdtar ([0-9.]+)/); if (!match2?.[1]) { throw new Error("Failed to parse output of tar --version."); } - return { type: "bsd", version: match2[1] }; + return { type: "bsd", version: match2[1], path: tar }; } else { throw new Error("Unknown tar version"); } @@ -183755,10 +183755,10 @@ async function extractTarZst(tar, dest, tarVersion, logger2) { args.push("--overwrite"); } args.push("-f", tar instanceof stream.Readable ? "-" : tar, "-C", dest); - process.stdout.write(`[command]tar ${args.join(" ")} + process.stdout.write(`[command]${tarVersion.path} ${args.join(" ")} `); await new Promise((resolve15, reject) => { - const tarProcess = (0, import_child_process.spawn)("tar", args, { stdio: "pipe" }); + const tarProcess = (0, import_child_process.spawn)(tarVersion.path, args, { stdio: "pipe" }); let stdout = ""; tarProcess.stdout?.on("data", (data) => { stdout += data.toString(); @@ -183785,7 +183785,7 @@ async function extractTarZst(tar, dest, tarVersion, logger2) { if (code !== 0) { reject( new CommandInvocationError( - "tar", + tarVersion.path, args, code ?? void 0, stdout, diff --git a/src/tar.test.ts b/src/tar.test.ts index 99d68b5317..e193b2df44 100644 --- a/src/tar.test.ts +++ b/src/tar.test.ts @@ -15,7 +15,7 @@ test("extractTarZst rejects if the input stream errors", async (t) => { const promise = extractTarZst( archive, path.join(tmpDir, "dest"), - { type: "gnu", version: "1.34" }, + { type: "gnu", version: "1.34", path: "tar" }, new RecordingLogger(), ); diff --git a/src/tar.ts b/src/tar.ts index 3a0d79cc64..4dd1c48be4 100644 --- a/src/tar.ts +++ b/src/tar.ts @@ -17,6 +17,8 @@ const MIN_REQUIRED_GNU_TAR_VERSION = "1.31"; export type TarVersion = { type: "gnu" | "bsd"; version: string; + /** Path to the `tar` executable that reported this version. */ + path: string; }; async function getTarVersion(): Promise { @@ -39,14 +41,14 @@ async function getTarVersion(): Promise { throw new Error("Failed to parse output of tar --version."); } - return { type: "gnu", version: match[1] }; + return { type: "gnu", version: match[1], path: tar }; } else if (stdout.includes("bsdtar")) { const match = stdout.match(/bsdtar ([0-9.]+)/); if (!match?.[1]) { throw new Error("Failed to parse output of tar --version."); } - return { type: "bsd", version: match[1] }; + return { type: "bsd", version: match[1], path: tar }; } else { throw new Error("Unknown tar version"); } @@ -171,10 +173,10 @@ export async function extractTarZst( args.push("-f", tar instanceof stream.Readable ? "-" : tar, "-C", dest); - process.stdout.write(`[command]tar ${args.join(" ")}\n`); + process.stdout.write(`[command]${tarVersion.path} ${args.join(" ")}\n`); await new Promise((resolve, reject) => { - const tarProcess = spawn("tar", args, { stdio: "pipe" }); + const tarProcess = spawn(tarVersion.path, args, { stdio: "pipe" }); let stdout = ""; tarProcess.stdout?.on("data", (data: Buffer) => { @@ -210,7 +212,7 @@ export async function extractTarZst( if (code !== 0) { reject( new CommandInvocationError( - "tar", + tarVersion.path, args, code ?? undefined, stdout, diff --git a/src/tools-download.test.ts b/src/tools-download.test.ts index 1ba980bbe3..928255d3c2 100644 --- a/src/tools-download.test.ts +++ b/src/tools-download.test.ts @@ -70,7 +70,7 @@ test.serial( destination, undefined, {}, - { type: "gnu", version: "1.34" }, + { type: "gnu", version: "1.34", path: "tar" }, new RecordingLogger(), ); @@ -103,7 +103,7 @@ test.serial( destination, undefined, {}, - { type: "gnu", version: "1.34" }, + { type: "gnu", version: "1.34", path: "tar" }, new RecordingLogger(), ), { @@ -147,7 +147,7 @@ test.serial( destination, undefined, {}, - { type: "gnu", version: "1.34" }, + { type: "gnu", version: "1.34", path: "tar" }, new RecordingLogger(), ); @@ -187,7 +187,7 @@ test.serial( destination, undefined, {}, - { type: "gnu", version: "1.34" }, + { type: "gnu", version: "1.34", path: "tar" }, new RecordingLogger(), ); @@ -235,7 +235,7 @@ test.serial( path.join(tmpDir, "codeql"), undefined, {}, - { type: "gnu", version: "1.34" }, + { type: "gnu", version: "1.34", path: "tar" }, new RecordingLogger(), ); From 8512f45c1a3244f7f1f2c0f416734b06513a22ba Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Fri, 30 Oct 2026 17:10:42 +0000 Subject: [PATCH 168/174] Fix stdout and stderr being swapped in tar extraction errors Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 4 ++-- src/tar.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 4e142c5172..d9d14db90c 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -183788,8 +183788,8 @@ async function extractTarZst(tar, dest, tarVersion, logger2) { tarVersion.path, args, code ?? void 0, - stdout, - stderr + stderr, + stdout ) ); } diff --git a/src/tar.ts b/src/tar.ts index 4dd1c48be4..3497da5e5e 100644 --- a/src/tar.ts +++ b/src/tar.ts @@ -215,8 +215,8 @@ export async function extractTarZst( tarVersion.path, args, code ?? undefined, - stdout, stderr, + stdout, ), ); } From f1396bd6e235e057dede6642e3943800c54b0b5c Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 17:47:22 +0000 Subject: [PATCH 169/174] Fix incorrect `xcodeVer` check --- lib/entry-points.js | 2 +- src/languages/traced.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 093dcf159a..3a43d4cd5d 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -194147,7 +194147,7 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) { abortUnsupportedTracedAnalysis, xcodeProduct ); - } else if (xcodeVer === void 0) { + } else if (xcodeProduct === void 0) { action.logger.info( "Unable to determine Xcode version. Skipping Xcode compatibility check." ); diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 12ecd03a3c..96eb5da45b 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -244,7 +244,7 @@ export async function checkRunnerSupportsTracedAnalysis( abortUnsupportedTracedAnalysis, xcodeProduct, ); - } else if (xcodeVer === undefined) { + } else if (xcodeProduct === undefined) { action.logger.info( "Unable to determine Xcode version. Skipping Xcode compatibility check.", ); From 120993f7238c7cf9a7c3af84bbfb7a3084742083 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 30 Oct 2026 18:06:04 +0000 Subject: [PATCH 170/174] Convert diagnostic ID to kebab case --- lib/entry-points.js | 2 +- src/languages/traced.test.ts | 99 ++++++++++++++++++++++++++++++++++++ src/languages/traced.ts | 2 +- 3 files changed, 101 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 3a43d4cd5d..7740535e88 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -194046,7 +194046,7 @@ function handleUnsupportedVersion(logger2, config, tracedLanguages, abortUnsuppo config, language, makeDiagnostic( - `codeql-action/unsupported-traced-analysis-${product.toLowerCase()}`, + `codeql-action/unsupported-traced-analysis-${product.toLowerCase().replaceAll(" ", "-")}`, `Traced analysis is not supported on this version of ${product}`, { attributes: { diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index 2b9d50dfab..e4b38761c6 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -1,5 +1,6 @@ import fs from "fs"; +import type { ExecOptions } from "@actions/exec"; import * as toolrunner from "@actions/exec/lib/toolrunner"; import * as io from "@actions/io"; import test from "ava"; @@ -546,6 +547,104 @@ test.serial( }), ); +// `addDiagnostic` changes global state and we must stub it, so this test must be serial. +test.serial( + "checkRunnerSupportsTracedAnalysis logs and adds diagnostic if Xcode SDK version is unsupported", + async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]); + + const readlinkSync = sinon + .stub(fs, "readlinkSync") + .throws(new Error("Not found")); + const which = sinon.stub(io, "which").resolves("/path/to/xcrun"); + + let stdoutListener: ((data: Buffer) => void) | undefined = undefined; + const exec = sinon.stub<[], Promise>().callsFake(async () => { + if (stdoutListener !== undefined) { + stdoutListener(Buffer.from("Xcode 27.5")); + stdoutListener(Buffer.from("Build version 27F9")); + return 0; + } else { + throw new Error("Error to force next fallback"); + } + }); + const runner = sinon.createStubInstance(toolrunner.ToolRunner, { + exec, + }); + const toolrunnerStub = sinon + .stub(toolrunner, "ToolRunner") + .callsFake((_cmd, args: string[], opts: ExecOptions) => { + if (args[0] !== "xcodebuild") { + stdoutListener = opts.listeners?.stdout; + } + return runner; + }); + + const codeql = await getCodeQLWithTracedStub( + "codeql-for-testing", + logger, + env, + ); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic"); + + const config = createTestConfig({ + tempDir: tmpDir, + languages: [BuiltInLanguage.swift], + }); + await checkRunnerSupportsTracedAnalysis( + initAllState({ + logger, + platform: "darwin", + osRelease: "26.0.0", + env, + features, + }), + config, + codeql, + ); + + t.is(readlinkSync.callCount, 1); + t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]); + + t.is(which.callCount, 2); + t.is(toolrunnerStub.callCount, 2); + t.is(exec.callCount, 2); + + checkExpectedLogMessages(t, logger.messages, [ + "Unable to determine Xcode version from xcodebuild", + "Traced analysis is not supported on Xcode SDK 27", + ]); + + t.is(addDiagnostic.callCount, 1); + t.like(addDiagnostic.args[0], [ + config, + BuiltInLanguage.swift, + { + attributes: { + languages: [BuiltInLanguage.swift], + xcodeSdkVersion: "27.5.0", + }, + severity: "warning", + source: { + id: "codeql-action/unsupported-traced-analysis-xcode-sdk", + name: "Traced analysis is not supported on this version of Xcode SDK", + }, + visibility: { + cliSummaryTable: true, + statusPage: true, + telemetry: true, + }, + } satisfies Partial, + ]); + }), +); + // `addDiagnostic` changes global state and we must stub it, so this test must be serial. test.serial( "checkRunnerSupportsTracedAnalysis throws if Xcode version is unsupported and FF is enabled", diff --git a/src/languages/traced.ts b/src/languages/traced.ts index 96eb5da45b..406afc9b35 100644 --- a/src/languages/traced.ts +++ b/src/languages/traced.ts @@ -83,7 +83,7 @@ function handleUnsupportedVersion( config, language, makeDiagnostic( - `codeql-action/unsupported-traced-analysis-${product.toLowerCase()}`, + `codeql-action/unsupported-traced-analysis-${product.toLowerCase().replaceAll(" ", "-")}`, `Traced analysis is not supported on this version of ${product}`, { attributes: { From 95dd6bfbc42487e3e3695e9c9cb52f3a4b3fcd4f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 2 Nov 2026 12:24:01 +0000 Subject: [PATCH 171/174] Fix new test not providing typical input --- src/languages/traced.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/languages/traced.test.ts b/src/languages/traced.test.ts index e4b38761c6..631a647ae3 100644 --- a/src/languages/traced.test.ts +++ b/src/languages/traced.test.ts @@ -565,8 +565,7 @@ test.serial( let stdoutListener: ((data: Buffer) => void) | undefined = undefined; const exec = sinon.stub<[], Promise>().callsFake(async () => { if (stdoutListener !== undefined) { - stdoutListener(Buffer.from("Xcode 27.5")); - stdoutListener(Buffer.from("Build version 27F9")); + stdoutListener(Buffer.from("27.5")); return 0; } else { throw new Error("Error to force next fallback"); From 2ef3b622017573270975effb6820567f855245aa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 2 Nov 2026 16:15:52 +0000 Subject: [PATCH 172/174] Update default bundle to codeql-bundle-v2.27.4 --- lib/defaults.json | 8 ++++---- lib/entry-points.js | 4 ++-- src/defaults.json | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/defaults.json b/lib/defaults.json index cde5136e28..cfa3f6c1c7 100644 --- a/lib/defaults.json +++ b/lib/defaults.json @@ -1,6 +1,6 @@ { - "bundleVersion": "codeql-bundle-v2.27.3", - "cliVersion": "2.27.3", - "priorBundleVersion": "codeql-bundle-v2.27.2", - "priorCliVersion": "2.27.2" + "bundleVersion": "codeql-bundle-v2.27.4", + "cliVersion": "2.27.4", + "priorBundleVersion": "codeql-bundle-v2.27.3", + "priorCliVersion": "2.27.3" } diff --git a/lib/entry-points.js b/lib/entry-points.js index 9f802ddfac..cbd2993c71 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -179587,8 +179587,8 @@ var path6 = __toESM(require("path")); var semver3 = __toESM(require_semver2()); // src/defaults.json -var bundleVersion = "codeql-bundle-v2.27.3"; -var cliVersion = "2.27.3"; +var bundleVersion = "codeql-bundle-v2.27.4"; +var cliVersion = "2.27.4"; // src/overlay/index.ts var fs5 = __toESM(require("fs")); diff --git a/src/defaults.json b/src/defaults.json index cde5136e28..cfa3f6c1c7 100644 --- a/src/defaults.json +++ b/src/defaults.json @@ -1,6 +1,6 @@ { - "bundleVersion": "codeql-bundle-v2.27.3", - "cliVersion": "2.27.3", - "priorBundleVersion": "codeql-bundle-v2.27.2", - "priorCliVersion": "2.27.2" + "bundleVersion": "codeql-bundle-v2.27.4", + "cliVersion": "2.27.4", + "priorBundleVersion": "codeql-bundle-v2.27.3", + "priorCliVersion": "2.27.3" } From adfcd5ffb8f15a420edbc24cce8056e2626d76bd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 2 Nov 2026 16:15:59 +0000 Subject: [PATCH 173/174] Add changelog note --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a96e0a9c4..950e8ffbe2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th ## [UNRELEASED] -No user facing changes. +- Update default CodeQL bundle version to [2.27.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.4). [#4284](https://github.com/github/codeql-action/pull/4284) ## 4.39.1 - 21 Oct 2026 From d9984814e484244a9abd81ad96a4646ca1c4122a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Nov 2026 10:25:27 +0000 Subject: [PATCH 174/174] Update changelog for v4.39.2 --- CHANGELOG.md | 5 ++++- unreleased-change-notes/ghes-3-18-deprecation.md | 1 - unreleased-change-notes/macos-xcode-deprecation.md | 1 - unreleased-change-notes/remove-trap-cache-cleanup.md | 1 - 4 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 unreleased-change-notes/ghes-3-18-deprecation.md delete mode 100644 unreleased-change-notes/macos-xcode-deprecation.md delete mode 100644 unreleased-change-notes/remove-trap-cache-cleanup.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 950e8ffbe2..9336064497 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,12 @@ See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. -## [UNRELEASED] +## 4.39.2 - 03 Nov 2026 - Update default CodeQL bundle version to [2.27.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.4). [#4284](https://github.com/github/codeql-action/pull/4284) +- _Upcoming breaking change_: CodeQL version 2.22.3 and earlier were discontinued on 16 October 2026 alongside GitHub Enterprise Server 3.18, and will be unsupported by the next minor release of the CodeQL Action. Added a deprecation warning for customers using these versions of CodeQL. [#4266](https://github.com/github/codeql-action/pull/4266) +- Starting with macOS 27 and Xcode 27, traced analyses are unsupported. See [this blog post for more information](https://github.blog/changelog/2026-10-19-codeql-changes-for-macos-27-xcode-27-and-swift-6-4/). The CodeQL Action will now try to identify if a workflow is about to perform a traced analysis on version 27 or above of macOS or Xcode. If so, the CodeQL Action will emit a corresponding warning that will also be visible on the [Tool Status Page](https://docs.github.com/en/code-security/how-tos/find-and-fix-code-vulnerabilities/manage-your-configuration/use-the-tools-status-page-for-code-scanning). This check will be rolled out following this release of the CodeQL Action. [#4221](https://github.com/github/codeql-action/pull/4221) +- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable has been removed, as announced in the release notes for CodeQL Action 4.35.2. The `analyze` Action now warns if this environment variable is set. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#4243](https://github.com/github/codeql-action/pull/4243) ## 4.39.1 - 21 Oct 2026 diff --git a/unreleased-change-notes/ghes-3-18-deprecation.md b/unreleased-change-notes/ghes-3-18-deprecation.md deleted file mode 100644 index 0e33d39327..0000000000 --- a/unreleased-change-notes/ghes-3-18-deprecation.md +++ /dev/null @@ -1 +0,0 @@ -- _Upcoming breaking change_: CodeQL version 2.22.3 and earlier were discontinued on 16 October 2026 alongside GitHub Enterprise Server 3.18, and will be unsupported by the next minor release of the CodeQL Action. Added a deprecation warning for customers using these versions of CodeQL. [#4266](https://github.com/github/codeql-action/pull/4266) diff --git a/unreleased-change-notes/macos-xcode-deprecation.md b/unreleased-change-notes/macos-xcode-deprecation.md deleted file mode 100644 index ea7586d08f..0000000000 --- a/unreleased-change-notes/macos-xcode-deprecation.md +++ /dev/null @@ -1 +0,0 @@ -- Starting with macOS 27 and Xcode 27, traced analyses are unsupported. See [this blog post for more information](https://github.blog/changelog/2026-10-19-codeql-changes-for-macos-27-xcode-27-and-swift-6-4/). The CodeQL Action will now try to identify if a workflow is about to perform a traced analysis on version 27 or above of macOS or Xcode. If so, the CodeQL Action will emit a corresponding warning that will also be visible on the [Tool Status Page](https://docs.github.com/en/code-security/how-tos/find-and-fix-code-vulnerabilities/manage-your-configuration/use-the-tools-status-page-for-code-scanning). This check will be rolled out following this release of the CodeQL Action. [#4221](https://github.com/github/codeql-action/pull/4221) diff --git a/unreleased-change-notes/remove-trap-cache-cleanup.md b/unreleased-change-notes/remove-trap-cache-cleanup.md deleted file mode 100644 index b3cb822b86..0000000000 --- a/unreleased-change-notes/remove-trap-cache-cleanup.md +++ /dev/null @@ -1 +0,0 @@ -- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable has been removed, as announced in the release notes for CodeQL Action 4.35.2. The `analyze` Action now warns if this environment variable is set. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#4243](https://github.com/github/codeql-action/pull/4243)