From 6dfd3c5062622427e70abcaadb1125f6d08314a7 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Sat, 4 Jul 2026 09:56:13 +0200 Subject: [PATCH] rebuild dist --- dist/{cache-Cb-Up9r2.js => cache-983zFS-E.js} | 72 ++- dist/{cache-1jS6aShy.js => cache-WmUk0Jib.js} | 2 +- ...leanup-ChNUL7jL.js => cleanup-Dr5MZ8bz.js} | 571 +++++++++--------- dist/restore.js | 2 +- dist/save.js | 2 +- 5 files changed, 367 insertions(+), 282 deletions(-) rename dist/{cache-Cb-Up9r2.js => cache-983zFS-E.js} (99%) rename dist/{cache-1jS6aShy.js => cache-WmUk0Jib.js} (99%) rename dist/{cleanup-ChNUL7jL.js => cleanup-Dr5MZ8bz.js} (99%) diff --git a/dist/cache-Cb-Up9r2.js b/dist/cache-983zFS-E.js similarity index 99% rename from dist/cache-Cb-Up9r2.js rename to dist/cache-983zFS-E.js index e38c644..679a9b1 100644 --- a/dist/cache-Cb-Up9r2.js +++ b/dist/cache-983zFS-E.js @@ -1,4 +1,4 @@ -import { f as debug, m as getDefaultExportFromCjs, n as mkdirP, l as exec, w as which, o as warning, i as info, H as HttpCodes, p as HttpClientError, q as HttpClient, t as isDebug, u as setSecret, B as BearerCredentialHandler, e as error } from './cleanup-ChNUL7jL.js'; +import { f as debug, m as getDefaultExportFromCjs, n as mkdirP, l as exec, w as which, o as warning, i as info, H as HttpCodes, p as HttpClientError, q as HttpClient, t as isDebug, u as setSecret, B as BearerCredentialHandler, e as error } from './cleanup-Dr5MZ8bz.js'; import * as path from 'path'; import * as fs from 'fs'; import { writeFileSync, existsSync } from 'fs'; @@ -44263,7 +44263,7 @@ function getCacheServiceURL() { } } -var version = "6.0.1"; +var version = "6.1.0"; var require$$0 = { version: version}; @@ -48513,6 +48513,35 @@ class ReserveCacheError extends Error { Object.setPrototypeOf(this, ReserveCacheError.prototype); } } +/** + * Stable prefix the receiver writes into the cache reservation response when + * the issuer downgraded the cache token to read-only (for example, because + * the run was triggered by an untrusted event). saveCacheV1 / saveCacheV2 + * dispatch on this prefix to re-classify the failure as a + * CacheWriteDeniedError so consumers (and the outer catch arm) can + * distinguish a policy denial from other reservation failures. + */ +const CACHE_WRITE_DENIED_PREFIX = 'cache write denied:'; +/** + * Raised when the cache backend refuses to reserve a writable cache entry + * because the JWT issued for this run was scoped read-only (for example, the + * run was triggered by an event the repository administrator classified as + * untrusted). The receiver-supplied detail message always begins with + * `cache write denied:` (the full error message includes additional context + * like the cache key). + * + * Extends ReserveCacheError for source-compatibility: existing + * `instanceof ReserveCacheError` checks and `typedError.name === + * ReserveCacheError.name` paths keep working, while consumers that want to + * distinguish the policy case can match on this subclass. + */ +class CacheWriteDeniedError extends ReserveCacheError { + constructor(message) { + super(message); + this.name = 'CacheWriteDeniedError'; + Object.setPrototypeOf(this, CacheWriteDeniedError.prototype); + } +} class FinalizeCacheError extends Error { constructor(message) { super(message); @@ -48785,7 +48814,7 @@ function saveCache(paths_1, key_1, options_1) { */ function saveCacheV1(paths_1, key_1, options_1) { return __awaiter(this, arguments, void 0, function* (paths, key, options, enableCrossOsArchive = false) { - var _a, _b, _c, _d, _e; + var _a, _b, _c, _d, _e, _f; const compressionMethod = yield getCompressionMethod(); let cacheId = -1; const cachePaths = yield resolvePaths(paths); @@ -48822,7 +48851,17 @@ function saveCacheV1(paths_1, key_1, options_1) { throw new Error((_d = (_c = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.error) === null || _c === void 0 ? void 0 : _c.message) !== null && _d !== void 0 ? _d : `Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the data cap limit, not saving cache.`); } else { - throw new ReserveCacheError(`Unable to reserve cache with key ${key}, another job may be creating this cache. More details: ${(_e = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.error) === null || _e === void 0 ? void 0 : _e.message}`); + // Inspect the receiver's error message before deciding which error to + // throw. A message starting with the stable `cache write denied:` + // prefix indicates the issuer downgraded the token to read-only + // (policy denial), not a contention case, so we surface it as a + // CacheWriteDeniedError which the outer catch arm logs at warning + // level. + const detailMessage = (_e = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.error) === null || _e === void 0 ? void 0 : _e.message; + if (detailMessage === null || detailMessage === void 0 ? void 0 : detailMessage.startsWith(CACHE_WRITE_DENIED_PREFIX)) { + throw new CacheWriteDeniedError(`Unable to reserve cache with key ${key}. More details: ${detailMessage}`); + } + throw new ReserveCacheError(`Unable to reserve cache with key ${key}, another job may be creating this cache. More details: ${(_f = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.error) === null || _f === void 0 ? void 0 : _f.message}`); } debug(`Saving Cache (ID: ${cacheId})`); yield saveCache$1(cacheId, archivePath, '', options); @@ -48832,6 +48871,12 @@ function saveCacheV1(paths_1, key_1, options_1) { if (typedError.name === ValidationError.name) { throw error$1; } + else if (typedError.name === CacheWriteDeniedError.name) { + // Cache write was denied by policy (read-only token). Surface to the + // customer at warning level so it is visible in the workflow log + // without failing the run. + warning(`Failed to save: ${typedError.message}`); + } else if (typedError.name === ReserveCacheError.name) { info(`Failed to save: ${typedError.message}`); } @@ -48870,6 +48915,7 @@ function saveCacheV1(paths_1, key_1, options_1) { */ function saveCacheV2(paths_1, key_1, options_1) { return __awaiter(this, arguments, void 0, function* (paths, key, options, enableCrossOsArchive = false) { + var _a; // Override UploadOptions to force the use of Azure // ...options goes first because we want to override the default values // set in UploadOptions with these specific figures @@ -48905,7 +48951,11 @@ function saveCacheV2(paths_1, key_1, options_1) { try { const response = yield twirpClient.CreateCacheEntry(request); if (!response.ok) { - if (response.message) { + // Skip the redundant inner warning when the receiver signalled a + // policy denial: the outer catch arm below will log a single + // customer-facing warning. + if (response.message && + !response.message.startsWith(CACHE_WRITE_DENIED_PREFIX)) { warning(`Cache reservation failed: ${response.message}`); } throw new Error(response.message || 'Response was not ok'); @@ -48914,6 +48964,10 @@ function saveCacheV2(paths_1, key_1, options_1) { } catch (error) { debug(`Failed to reserve cache: ${error}`); + const errorMessage = (_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : ''; + if (errorMessage.startsWith(CACHE_WRITE_DENIED_PREFIX)) { + throw new CacheWriteDeniedError(`Unable to reserve cache with key ${key}. More details: ${errorMessage}`); + } throw new ReserveCacheError(`Unable to reserve cache with key ${key}, another job may be creating this cache.`); } debug(`Attempting to upload cache located at: ${archivePath}`); @@ -48938,6 +48992,12 @@ function saveCacheV2(paths_1, key_1, options_1) { if (typedError.name === ValidationError.name) { throw error$1; } + else if (typedError.name === CacheWriteDeniedError.name) { + // Cache write was denied by policy (read-only token). Surface to the + // customer at warning level so it is visible in the workflow log + // without failing the run. + warning(`Failed to save: ${typedError.message}`); + } else if (typedError.name === ReserveCacheError.name) { info(`Failed to save: ${typedError.message}`); } @@ -48969,4 +49029,4 @@ function saveCacheV2(paths_1, key_1, options_1) { }); } -export { FinalizeCacheError, ReserveCacheError, ValidationError, isFeatureAvailable, restoreCache, saveCache }; +export { CACHE_WRITE_DENIED_PREFIX, CacheWriteDeniedError, FinalizeCacheError, ReserveCacheError, ValidationError, isFeatureAvailable, restoreCache, saveCache }; diff --git a/dist/cache-1jS6aShy.js b/dist/cache-WmUk0Jib.js similarity index 99% rename from dist/cache-1jS6aShy.js rename to dist/cache-WmUk0Jib.js index d25548f..a680327 100644 --- a/dist/cache-1jS6aShy.js +++ b/dist/cache-WmUk0Jib.js @@ -1,4 +1,4 @@ -import { v as commonjsGlobal, x as requireTunnel, m as getDefaultExportFromCjs, y as getAugmentedNamespace } from './cleanup-ChNUL7jL.js'; +import { v as commonjsGlobal, x as requireTunnel, m as getDefaultExportFromCjs, y as getAugmentedNamespace } from './cleanup-Dr5MZ8bz.js'; import os__default from 'os'; import crypto__default from 'crypto'; import fs__default from 'fs'; diff --git a/dist/cleanup-ChNUL7jL.js b/dist/cleanup-Dr5MZ8bz.js similarity index 99% rename from dist/cleanup-ChNUL7jL.js rename to dist/cleanup-Dr5MZ8bz.js index d3a2bfb..725fb76 100644 --- a/dist/cleanup-ChNUL7jL.js +++ b/dist/cleanup-Dr5MZ8bz.js @@ -33175,181 +33175,6 @@ function create(patterns, options) { }); } -/*! - * Copyright (c) Squirrel Chat et al., All rights reserved. - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -function getLineColFromPtr(string, ptr) { - let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g); - return [lines.length, lines.pop().length + 1]; -} -function makeCodeBlock(string, line, column) { - let lines = string.split(/\r\n|\n|\r/g); - let codeblock = ''; - let numberLen = (Math.log10(line + 1) | 0) + 1; - for (let i = line - 1; i <= line + 1; i++) { - let l = lines[i - 1]; - if (!l) - continue; - codeblock += i.toString().padEnd(numberLen, ' '); - codeblock += ': '; - codeblock += l; - codeblock += '\n'; - if (i === line) { - codeblock += ' '.repeat(numberLen + column + 2); - codeblock += '^\n'; - } - } - return codeblock; -} -class TomlError extends Error { - line; - column; - codeblock; - constructor(message, options) { - const [line, column] = getLineColFromPtr(options.toml, options.ptr); - const codeblock = makeCodeBlock(options.toml, line, column); - super(`Invalid TOML document: ${message}\n\n${codeblock}`, options); - this.line = line; - this.column = column; - this.codeblock = codeblock; - } -} - -/*! - * Copyright (c) Squirrel Chat et al., All rights reserved. - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -function isEscaped(str, ptr) { - let i = 0; - while (str[ptr - ++i] === '\\') - ; - return --i && (i % 2); -} -function indexOfNewline(str, start = 0, end = str.length) { - let idx = str.indexOf('\n', start); - if (str[idx - 1] === '\r') - idx--; - return idx <= end ? idx : -1; -} -function skipComment(str, ptr) { - for (let i = ptr; i < str.length; i++) { - let c = str[i]; - if (c === '\n') - return i; - if (c === '\r' && str[i + 1] === '\n') - return i + 1; - if ((c < '\x20' && c !== '\t') || c === '\x7f') { - throw new TomlError('control characters are not allowed in comments', { - toml: str, - ptr: ptr, - }); - } - } - return str.length; -} -function skipVoid(str, ptr, banNewLines, banComments) { - let c; - while (1) { - while ((c = str[ptr]) === ' ' || c === '\t' || (!banNewLines && (c === '\n' || c === '\r' && str[ptr + 1] === '\n'))) - ptr++; - // Tucking the return statement here would save 5 characters >:) - // But TypeScript fails to detect there is no way to exit the loop so it complains about the lack of final return - if (banComments || c !== '#') - break; - ptr = skipComment(str, ptr); - } - return ptr; -} -function skipUntil(str, ptr, sep, end, banNewLines = false) { - if (!end) { - ptr = indexOfNewline(str, ptr); - return ptr < 0 ? str.length : ptr; - } - for (let i = ptr; i < str.length; i++) { - let c = str[i]; - if (c === '#') { - i = indexOfNewline(str, i); - } - else if (c === sep) { - return i + 1; - } - else if (c === end || (banNewLines && (c === '\n' || (c === '\r' && str[i + 1] === '\n')))) { - return i; - } - } - throw new TomlError('cannot find end of structure', { - toml: str, - ptr: ptr - }); -} -function getStringEnd(str, seek) { - let first = str[seek]; - let target = first === str[seek + 1] && str[seek + 1] === str[seek + 2] - ? str.slice(seek, seek + 3) - : first; - seek += target.length - 1; - do - seek = str.indexOf(target, ++seek); - while (seek > -1 && first !== "'" && isEscaped(str, seek)); - if (seek > -1) { - seek += target.length; - if (target.length > 1) { - if (str[seek] === first) - seek++; - if (str[seek] === first) - seek++; - } - } - return seek; -} - /*! * Copyright (c) Squirrel Chat et al., All rights reserved. * SPDX-License-Identifier: BSD-3-Clause @@ -33505,101 +33330,223 @@ class TomlDate extends Date { * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +function getLineColFromPtr(string, ptr) { + let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g); + return [lines.length, lines.pop().length + 1]; +} +function makeCodeBlock(string, line, column) { + let lines = string.split(/\r\n|\n|\r/g); + let codeblock = ''; + let numberLen = (Math.log10(line + 1) | 0) + 1; + for (let i = line - 1; i <= line + 1; i++) { + let l = lines[i - 1]; + if (!l) + continue; + codeblock += i.toString().padEnd(numberLen, ' '); + codeblock += ': '; + codeblock += l; + codeblock += '\n'; + if (i === line) { + codeblock += ' '.repeat(numberLen + column + 2); + codeblock += '^\n'; + } + } + return codeblock; +} +class TomlError extends Error { + line; + column; + codeblock; + constructor(message, options) { + const [line, column] = getLineColFromPtr(options.toml, options.ptr); + const codeblock = makeCodeBlock(options.toml, line, column); + super(`Invalid TOML document: ${message}\n\n${codeblock}`, options); + this.line = line; + this.column = column; + this.codeblock = codeblock; + } +} + +/*! + * Copyright (c) Squirrel Chat et al., All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +// let CTRL_REGEX = /[\x00-\x08\x0f-\x1f\x7f]/ let INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/; let FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/; let LEADING_ZERO = /^[+-]?0[0-9_]/; -let ESCAPE_REGEX = /^[0-9a-f]{2,8}$/i; -let ESC_MAP = { - b: '\b', - t: '\t', - n: '\n', - f: '\f', - r: '\r', - e: '\x1b', - '"': '"', - '\\': '\\', -}; -function parseString(str, ptr = 0, endPtr = str.length) { - let isLiteral = str[ptr] === '\''; - let isMultiline = str[ptr++] === str[ptr] && str[ptr] === str[ptr + 1]; +function parseString(str, ptr) { + let c = str[ptr++]; + let first = c; + let isLiteral = c === "'"; + let isMultiline = c === str[ptr] && c === str[ptr + 1]; if (isMultiline) { - endPtr -= 2; - if (str[ptr += 2] === '\r') - ptr++; - if (str[ptr] === '\n') + // Trim initial newline + if (str[ptr += 2] === '\n') ptr++; + else if (str[ptr] === '\r' && str[ptr + 1] === '\n') + ptr += 2; } - let tmp = 0; - let isEscape; + /* + The fast path does not seem to bring significant performance gains, so it's commented out. + Kept for reference and/or future fafoing. + + Without: spec 5.08 µs/iter 3.88 ipc (99.44% cache) 23.90 branch misses 28.61k cycles 111.01k instructions + 5MB 115.73 ms/iter 2.51 ipc (98.36% cache) 3.12M branch misses 619.30M cycles 1.56G instructions + + With: spec 5.09 µs/iter 3.90 ipc (99.46% cache) 24.42 branch misses 28.57k cycles 111.49k instructions + 5MB 113.89 ms/iter 2.47 ipc (98.38% cache) 3.12M branch misses 611.94M cycles 1.51G instructions + + if (c === "'") { + // Literal strings fast path - no transform needs to occur; just grab the str and that's it + let endPtr = str.indexOf(isMultiline ? "'''" : "'", ptr) + if (endPtr < 0) { + throw new TomlError("unfinished string literal", { toml: str, ptr }) + } + + if (isMultiline) { + // If the string ends with 4-5 quotes, then the first 1-2 are part of the string + if (str[endPtr + 3] === "'") endPtr++ + if (str[endPtr + 3] === "'") endPtr++ + } + + let string = str.slice(ptr, endPtr) + if (CTRL_REGEX.test(string)) { + let match = string.match(CTRL_REGEX)! + throw new TomlError('control characters are not allowed in strings', { toml: str, ptr: ptr + (match.index ?? 0) }) + } + return [string, endPtr + (isMultiline ? 3 : 1)] + } + */ let parsed = ''; let sliceStart = ptr; - while (ptr < endPtr - 1) { - let c = str[ptr++]; - if (c === '\n' || (c === '\r' && str[ptr] === '\n')) { - if (!isMultiline) { - throw new TomlError('newlines are not allowed in strings', { - toml: str, - ptr: ptr - 1, - }); - } + // states: + // 0 - decoding + // 1 - decoding escape + // 2 - whitespace escape (no newline encountered yet, must fail on non-whitespace) + // 3 - whitespace escape (newline encountered, allowed to transition back to normal decode) + let state = 0; + for (let i = ptr; i < str.length; i++) { + c = str[i]; + // Deal with newlines first, since that simplifies control character checking and handling across all states + if (isMultiline && (c === '\n' || (c === '\r' && str[i + 1] === '\n'))) { + state = state && 3; } + // Control characters are banned in TOML, so we throw an error if we encounter them else if ((c < '\x20' && c !== '\t') || c === '\x7f') { throw new TomlError('control characters are not allowed in strings', { toml: str, - ptr: ptr - 1, + ptr: i, }); } - if (isEscape) { - isEscape = false; - if (c === 'x' || c === 'u' || c === 'U') { - // Unicode escape - let code = str.slice(ptr, (ptr += (c === 'x' ? 2 : c === 'u' ? 4 : 8))); - if (!ESCAPE_REGEX.test(code)) { - throw new TomlError('invalid unicode escape', { - toml: str, - ptr: tmp, - }); - } - try { - parsed += String.fromCodePoint(parseInt(code, 16)); - } - catch { - throw new TomlError('invalid unicode escape', { - toml: str, - ptr: tmp, - }); - } + // The string might terminate while we're parsing through a newline escape. + // It must have encountered a newline; otherwise, it'll simply fail in another branch. + else if ((!state || state === 3) && c === first && (!isMultiline || (str[i + 1] === first && str[i + 2] === first))) { + if (isMultiline) { + // If the string ends with 4-5 quotes, then the first 1-2 are part of the string + if (str[i + 3] === first) + i++; + if (str[i + 3] === first) + i++; } - else if (isMultiline && (c === '\n' || c === ' ' || c === '\t' || c === '\r')) { - // Multiline escape - ptr = skipVoid(str, ptr - 1, true); - if (str[ptr] !== '\n' && str[ptr] !== '\r') { - throw new TomlError('invalid escape: only line-ending whitespace may be escaped', { - toml: str, - ptr: tmp, - }); - } - ptr = skipVoid(str, ptr); + return [ + // If we're in a newline escape still, then there's nothing to add. + // Also try to avoid concat if there's nothing to add to parsed, or nothing has been added to parsed. + state ? parsed : parsed + str.slice(sliceStart, i), + i + (isMultiline ? 3 : 1), + ]; + } + else if (!state) { + if (!isLiteral && c === '\\') { + parsed += str.slice(sliceStart, (sliceStart = i)); + state = 1; } - else if (c in ESC_MAP) { - // Classic escape - parsed += ESC_MAP[c]; + } + else if (state === 1) { + if (c === 'x' || c === 'u' || c === 'U') { // Unicode escape + let value = 0; + let len = c === 'x' ? 2 : c === 'u' ? 4 : 8; + for (let j = 0; j < len; j++, i++) { + let hex = str.charCodeAt(i + 1); + let digit = + /* 0-9 */ hex >= 0x30 && hex <= 0x39 ? hex - 0x30 : + /* A-F */ hex >= 0x41 && hex <= 0x46 ? hex - 0x41 + 10 : + /* a-f */ hex >= 0x61 && hex <= 0x66 ? hex - 0x61 + 10 : -1; + if (digit < 0) + throw new TomlError('invalid non-hex character in unicode escape', { toml: str, ptr: i + 1 }); + value = (value << 4) | digit; + } + // Because JS does bitwise on signed 32bit integers, all 0xfzzzzzzz values are actually seen as negative + if (value < 0 || value > 0x10ffff || (value >= 0xd800 && value <= 0xdfff)) { + throw new TomlError('invalid unicode escape', { toml: str, ptr: i }); + } + parsed += String.fromCodePoint(value); + sliceStart = i + 1; + state = 0; + } + else if (c === ' ' || c === '\t') { // If it was a newline, it'd have been handled earlier + state = 2; } else { - throw new TomlError('unrecognized escape sequence', { + if (c === 'b') + parsed += '\b'; + else if (c === 't') + parsed += '\t'; + else if (c === 'n') + parsed += '\n'; + else if (c === 'f') + parsed += '\f'; + else if (c === 'r') + parsed += '\r'; + else if (c === 'e') + parsed += '\x1b'; + else if (c === '"') + parsed += '"'; + else if (c === '\\') + parsed += '\\'; + else + throw new TomlError('unrecognized escape sequence', { toml: str, ptr: i }); + sliceStart = i + 1; + state = 0; + } + } + else if (c !== ' ' && c !== '\t') { + if (state === 2) { + throw new TomlError('invalid escape: only line-ending whitespace may be escaped', { toml: str, - ptr: tmp, + ptr: sliceStart, }); } - sliceStart = ptr; - } - else if (!isLiteral && c === '\\') { - tmp = ptr - 1; - isEscape = true; - parsed += str.slice(sliceStart, tmp); + // State cannot be zero, or we'd have branched earlier already. + // If it's a backslash, immediately transition to the escape state so it can be processed. + state = !isLiteral && c === '\\' ? 1 : 0; + sliceStart = i; } } - return parsed + str.slice(sliceStart, endPtr - 1); + throw new TomlError('unfinished string', { toml: str, ptr }); } function parseValue(value, toml, ptr, integersAsBigInt) { // Constant values @@ -33655,6 +33602,91 @@ function parseValue(value, toml, ptr, integersAsBigInt) { return date; } +/*! + * Copyright (c) Squirrel Chat et al., All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +function indexOfNewline(str, start = 0, end = str.length) { + let idx = str.indexOf('\n', start); + if (str[idx - 1] === '\r') + idx--; + return idx <= end ? idx : -1; +} +function skipComment(str, ptr) { + for (let i = ptr; i < str.length; i++) { + let c = str[i]; + if (c === '\n') + return i; + if (c === '\r' && str[i + 1] === '\n') + return i + 1; + if ((c < '\x20' && c !== '\t') || c === '\x7f') { + throw new TomlError('control characters are not allowed in comments', { + toml: str, + ptr: ptr, + }); + } + } + return str.length; +} +function skipVoid(str, ptr, banNewLines, banComments) { + let c; + while (1) { + while ((c = str[ptr]) === ' ' || c === '\t' || (!banNewLines && (c === '\n' || (c === '\r' && str[ptr + 1] === '\n')))) + ptr++; + // Tucking the return statement here would save 5 characters >:) + // But TypeScript fails to detect there is no way to exit the loop so it complains about the lack of final return + if (banComments || c !== '#') + break; + ptr = skipComment(str, ptr); + } + return ptr; +} +function skipUntil(str, ptr, sep, end, banNewLines = false) { + if (!end) { + ptr = indexOfNewline(str, ptr); + return ptr < 0 ? str.length : ptr; + } + for (let i = ptr; i < str.length; i++) { + let c = str[i]; + if (c === '#') { + i = indexOfNewline(str, i); + } + else if (c === sep) { + return i + 1; + } + else if (c === end || (banNewLines && (c === '\n' || (c === '\r' && str[i + 1] === '\n')))) { + return i; + } + } + throw new TomlError('cannot find end of structure', { + toml: str, + ptr: ptr, + }); +} + /*! * Copyright (c) Squirrel Chat et al., All rights reserved. * SPDX-License-Identifier: BSD-3-Clause @@ -33697,7 +33729,7 @@ function extractValue(str, ptr, end, depth, integersAsBigInt) { if (depth === 0) { throw new TomlError('document contains excessively nested structures. aborting.', { toml: str, - ptr: ptr + ptr: ptr, }); } let c = str[ptr]; @@ -33718,10 +33750,8 @@ function extractValue(str, ptr, end, depth, integersAsBigInt) { } return [value, endPtr]; } - let endPtr; if (c === '"' || c === "'") { - endPtr = getStringEnd(str, ptr); - let parsed = parseString(str, ptr, endPtr); + let [parsed, endPtr] = parseString(str, ptr); if (end) { endPtr = skipVoid(str, endPtr); if (str[endPtr] && str[endPtr] !== ',' && str[endPtr] !== end && str[endPtr] !== '\n' && str[endPtr] !== '\r') { @@ -33730,21 +33760,23 @@ function extractValue(str, ptr, end, depth, integersAsBigInt) { ptr: endPtr, }); } - endPtr += (+(str[endPtr] === ',')); + if (str[endPtr] === ',') + endPtr++; } return [parsed, endPtr]; } - endPtr = skipUntil(str, ptr, ',', end); - let slice = sliceAndTrimEndOf(str, ptr, endPtr - (+(str[endPtr - 1] === ','))); + let endPtr = skipUntil(str, ptr, ',', end); + let slice = sliceAndTrimEndOf(str, ptr, endPtr - (str[endPtr - 1] === ',' ? 1 : 0)); if (!slice[0]) { throw new TomlError('incomplete key-value declaration: no value specified', { toml: str, - ptr: ptr + ptr: ptr, }); } if (end && slice[1] > -1) { endPtr = skipVoid(str, ptr + slice[1]); - endPtr += +(str[endPtr] === ','); + if (str[endPtr] === ',') + endPtr++; } return [ parseValue(slice[0], str, ptr, integersAsBigInt), @@ -33791,24 +33823,18 @@ function parseKey(str, ptr, end = '=') { }); } do { - let c = str[ptr = ++dot]; + let c = str[(ptr = ++dot)]; // If it's whitespace, ignore if (c !== ' ' && c !== '\t') { // If it's a string - if (c === '"' || c === '\'') { + if (c === '"' || c === "'") { if (c === str[ptr + 1] && c === str[ptr + 2]) { throw new TomlError('multiline strings are not allowed in keys', { toml: str, ptr: ptr, }); } - let eos = getStringEnd(str, ptr); - if (eos < 0) { - throw new TomlError('unfinished string encountered', { - toml: str, - ptr: ptr, - }); - } + let [part, eos] = parseString(str, ptr); dot = str.indexOf('.', eos); let strEnd = str.slice(eos, dot < 0 || dot > endPtr ? endPtr : dot); let newLine = indexOfNewline(strEnd); @@ -33833,7 +33859,7 @@ function parseKey(str, ptr, end = '=') { }); } } - parsed.push(parseString(str, ptr, eos)); + parsed.push(part); } else { // Normal raw key part consumption and validation @@ -33990,8 +34016,7 @@ function peekTable(key, table, meta, type) { } m[k] = { t: i < key.length - 1 && type === 2 /* Type.ARRAY */ - ? 3 /* Type.ARRAY_DOTTED */ - : type, + ? 3 /* Type.ARRAY_DOTTED */ : type, d: false, i: 0, c: {}, @@ -34032,7 +34057,7 @@ function parse(toml, { maxDepth = 1000, integersAsBigInt } = {}) { for (let ptr = skipVoid(toml, 0); ptr < toml.length;) { if (toml[ptr] === '[') { let isTableArray = toml[++ptr] === '['; - let k = parseKey(toml, ptr += +isTableArray, ']'); + let k = parseKey(toml, (ptr += +isTableArray), ']'); if (isTableArray) { if (toml[k[1] - 1] !== ']') { throw new TomlError('expected end of table declaration', { @@ -34070,7 +34095,7 @@ function parse(toml, { maxDepth = 1000, integersAsBigInt } = {}) { if (toml[ptr] && toml[ptr] !== '\n' && toml[ptr] !== '\r') { throw new TomlError('each key-value declaration must be followed by an end-of-line', { toml: toml, - ptr: ptr + ptr: ptr, }); } ptr = skipVoid(toml, ptr); @@ -34120,10 +34145,10 @@ async function getCacheProvider() { let cache; switch (cacheProvider) { case "github": - cache = await import('./cache-Cb-Up9r2.js'); + cache = await import('./cache-983zFS-E.js'); break; case "warpbuild": - cache = await import('./cache-1jS6aShy.js').then(function (n) { return n.c; }); + cache = await import('./cache-WmUk0Jib.js').then(function (n) { return n.c; }); break; default: throw new Error(`The \`cache-provider\` \`${cacheProvider}\` is not valid.`); @@ -34642,7 +34667,7 @@ async function cleanBin(oldBins) { async function cleanRegistry(packages, crates = true) { // remove `.cargo/credentials.toml` try { - const credentials = path__default.join(CARGO_HOME, ".cargo", "credentials.toml"); + const credentials = path__default.join(CARGO_HOME, "credentials.toml"); debug(`deleting "${credentials}"`); await fs__default.promises.unlink(credentials); } diff --git a/dist/restore.js b/dist/restore.js index 9410f7b..53e86f7 100644 --- a/dist/restore.js +++ b/dist/restore.js @@ -1,4 +1,4 @@ -import { e as error, g as getCacheProvider, a as getInput, b as exportVariable, C as CacheConfig, i as info, c as cleanTargetDir, r as reportError, s as setOutput } from './cleanup-ChNUL7jL.js'; +import { e as error, g as getCacheProvider, a as getInput, b as exportVariable, C as CacheConfig, i as info, c as cleanTargetDir, r as reportError, s as setOutput } from './cleanup-Dr5MZ8bz.js'; import 'os'; import 'crypto'; import 'fs'; diff --git a/dist/save.js b/dist/save.js index 0fc97a1..aa36330 100644 --- a/dist/save.js +++ b/dist/save.js @@ -1,4 +1,4 @@ -import { e as error, g as getCacheProvider, a as getInput, d as isCacheUpToDate, i as info, C as CacheConfig, c as cleanTargetDir, f as debug, h as cleanRegistry, j as cleanBin, k as cleanGit, r as reportError, l as exec } from './cleanup-ChNUL7jL.js'; +import { e as error, g as getCacheProvider, a as getInput, d as isCacheUpToDate, i as info, C as CacheConfig, c as cleanTargetDir, f as debug, h as cleanRegistry, j as cleanBin, k as cleanGit, r as reportError, l as exec } from './cleanup-Dr5MZ8bz.js'; import 'os'; import 'crypto'; import 'fs';