Compare commits

..
Author SHA1 Message Date
Bruno BorgesandCopilot App 8cd57eb681 Update Undici to 6.29.1 (#1308)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-30 12:52:17 -04:00
Bruno BorgesandCopilot App 816722acf8 Fix Liberica SDKMAN patch release resolution (#1291)
* Fix Liberica SDKMAN patch release resolution

Preserve BellSoft's fourth version component as SDKMAN patch metadata and cover real API version formats for Java 17 and 25.

Fixes #1290

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d5b53868-538f-4c5f-b2aa-c66dc4ad06e2

* Fix Liberica patch ordering and build-less requests

Share overridable matching and ordering with toolcache selection. Keep patch-only requests distinct from exact SDKMAN build requests and cover the reported API pair across remote and cached resolution.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d5b53868-538f-4c5f-b2aa-c66dc4ad06e2

---------

Copilot-Session: d5b53868-538f-4c5f-b2aa-c66dc4ad06e2
2026-10-19 10:48:21 -04:00
Bruno BorgesandCopilot App b843ebf9b9 Support Maven plugin repositories in generated settings.xml (#1286)
* Add Maven plugin repository support

Generate plugin repositories alongside dependency repositories and share Central inclusion and ordering controls. Cover repository parsing, credentials, explicit Central overrides, plugin ordering, and effective Maven models; document the compatibility change and rebuild runtime bundles.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52a8a8e2-7965-42d3-88d9-d66f64d0d60d

* Fix CI audit by updating Handlebars to 4.7.10

Update the transitive test dependency to the patched release without changing runtime dependencies or suppressing audit checks.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 282b173f-7b1d-4fcd-bca4-9c8e2fa72a37

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52a8a8e2-7965-42d3-88d9-d66f64d0d60d
Copilot-Session: 282b173f-7b1d-4fcd-bca4-9c8e2fa72a37
2026-10-14 16:11:40 -04:00
10 changed files with 615 additions and 91 deletions

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
--- ---
name: undici name: undici
version: 6.29.0 version: 6.29.1
type: npm type: npm
summary: An HTTP/1.1 client, written from scratch for Node.js summary: An HTTP/1.1 client, written from scratch for Node.js
homepage: https://undici.nodejs.org homepage: https://undici.nodejs.org
+232 -14
View File
@@ -15,6 +15,7 @@ import type {
} from '../../src/distributions/liberica/models.js'; } from '../../src/distributions/liberica/models.js';
import {HttpClient} from '@actions/http-client'; import {HttpClient} from '@actions/http-client';
import os from 'os'; import os from 'os';
import path from 'path';
import manifestData from '../data/liberica.json' with {type: 'json'}; import manifestData from '../data/liberica.json' with {type: 'json'};
@@ -253,35 +254,68 @@ describe('findPackageForDownload', () => {
expect(result.version).toBe(expected); expect(result.version).toBe(expected);
}); });
describe('compound build versions', () => { describe.each([
[17, 20],
[25, 4]
])('patch releases for Java %s.0.%s', (featureVersion, updateVersion) => {
const mainVersion = `${featureVersion}.0.${updateVersion}`;
beforeEach(() => { beforeEach(() => {
distribution['getAvailableVersions'] = async () => distribution['getAvailableVersions'] = async () =>
['1', '1.1', '1.2', '1.10'].map(build => ({ ['+1', '+10', '.1+1', '.1+2', '.1+10', '.2+1', '.10+1'].map(suffix => ({
featureVersion: 25, featureVersion,
interimVersion: 0, interimVersion: 0,
updateVersion: 4, updateVersion,
buildVersion: 1, buildVersion: Number(suffix.split('+')[1]),
version: `25.0.4+${build}`, version: `${mainVersion}${suffix}`,
downloadUrl: `https://download.bell-sw.com/java/25.0.4+${build}/bellsoft-jdk25.0.4+${build}-macos-aarch64.tar.gz` downloadUrl: `https://download.bell-sw.com/java/${mainVersion}${suffix}/bellsoft-jdk${mainVersion}${suffix}-macos-aarch64.tar.gz`
})); }));
}); });
it.each([ it.each([
['25.0.4+1.1', '25.0.4+1.1'], [`${mainVersion}+1.1`, `${mainVersion}+1.1`, '.1+1'],
['25.0.4+1', '25.0.4+1'], [`${mainVersion}+1.2`, `${mainVersion}+1.2`, '.1+2'],
['25.0.4', '25.0.4+1.10'], [`${mainVersion}+1.10`, `${mainVersion}+1.10`, '.1+10'],
['25', '25.0.4+1.10'] [`${mainVersion}+1`, `${mainVersion}+1`, '+1'],
])('version is %s -> %s', async (input, expected) => { [mainVersion, `${mainVersion}+10.1`, '.10+1'],
[`${featureVersion}`, `${mainVersion}+10.1`, '.10+1']
])('version is %s -> %s', async (input, expected, suffix) => {
const result = await distribution['findPackageForDownload'](input); const result = await distribution['findPackageForDownload'](input);
expect(result).toEqual({ expect(result).toEqual({
version: expected, version: expected,
url: `https://download.bell-sw.com/java/${expected}/bellsoft-jdk${expected}-macos-aarch64.tar.gz` url: `https://download.bell-sw.com/java/${mainVersion}${suffix}/bellsoft-jdk${mainVersion}${suffix}-macos-aarch64.tar.gz`
}); });
}); });
it('sorts builds within the same patch numerically', async () => {
const versions = await distribution['getAvailableVersions']();
distribution['getAvailableVersions'] = async () =>
versions.filter(item => item.version.startsWith(`${mainVersion}.1+`));
const result = await distribution['findPackageForDownload'](mainVersion);
expect(result.version).toBe(`${mainVersion}+1.10`);
});
it('selects the newest build for a four-component patch-only request', async () => {
const patchDistribution = new LibericaDistributions({
version: `${mainVersion}.1`,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
patchDistribution['getAvailableVersions'] =
distribution['getAvailableVersions'];
await expect(
patchDistribution['findPackageForDownload'](
patchDistribution['version']
)
).resolves.toMatchObject({version: `${mainVersion}+1.10`});
});
it('does not substitute a different compound build', async () => { it('does not substitute a different compound build', async () => {
await expect( await expect(
distribution['findPackageForDownload']('25.0.4+1.3') distribution['findPackageForDownload'](`${mainVersion}+1.3`)
).rejects.toThrow(/No matching version found for SemVer/); ).rejects.toThrow(/No matching version found for SemVer/);
}); });
}); });
@@ -293,6 +327,160 @@ describe('findPackageForDownload', () => {
}); });
}); });
describe('patch request resolution from the constructor', () => {
const releases: LibericaVersion[] = ['17.0.20+10', '17.0.20.1+1'].map(
version => ({
featureVersion: 17,
interimVersion: 0,
updateVersion: 20,
buildVersion: Number(version.split('+')[1]),
version,
downloadUrl: `https://download.bell-sw.com/java/${version}/jdk.tar.gz`
})
);
let cacheRoot: string;
let previousToolcache: string | undefined;
beforeEach(async () => {
previousToolcache = process.env['RUNNER_TOOL_CACHE'];
cacheRoot = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'liberica-'));
process.env['RUNNER_TOOL_CACHE'] = cacheRoot;
for (const version of ['17.0.20-10', '17.0.20-1.1']) {
const javaPath = path.join(
cacheRoot,
'Java_Liberica_jdk',
version,
'x64'
);
await fs.promises.mkdir(javaPath, {recursive: true});
await fs.promises.writeFile(`${javaPath}.complete`, '');
}
});
afterEach(async () => {
if (previousToolcache === undefined) {
delete process.env['RUNNER_TOOL_CACHE'];
} else {
process.env['RUNNER_TOOL_CACHE'] = previousToolcache;
}
await fs.promises.rm(cacheRoot, {recursive: true, force: true});
});
it.each([
['17', '17.0.20+1.1', '17.0.20.1+1'],
['17.0.20', '17.0.20+1.1', '17.0.20.1+1'],
['17.0.20+10', '17.0.20+10', '17.0.20+10'],
['17.0.20+1.1', '17.0.20+1.1', '17.0.20.1+1'],
['17.0.20.1', '17.0.20+1.1', '17.0.20.1+1'],
['17.0.20.1+1', '17.0.20+1.1', '17.0.20.1+1'],
['17.0.20.0', '17.0.20+10', '17.0.20+10']
])(
'resolves %s consistently remotely and in cache',
async (input, expected, apiVersion) => {
const distribution = new LibericaDistributions({
version: input,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
distribution['getAvailableVersions'] = async () => releases;
await expect(
distribution['findPackageForDownload'](distribution['version'])
).resolves.toEqual({
version: expected,
url: `https://download.bell-sw.com/java/${apiVersion}/jdk.tar.gz`
});
expect(distribution['findInToolcache']()).toEqual({
version: expected,
path: path.join(
cacheRoot,
'Java_Liberica_jdk',
expected.replace('+', '-'),
'x64'
)
});
}
);
it.each(['17.0.20.2', '17.0.20+1.2'])(
'does not substitute a different patch or exact build for %s',
async version => {
const distribution = new LibericaDistributions({
version,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
distribution['getAvailableVersions'] = async () => releases;
await expect(
distribution['findPackageForDownload'](distribution['version'])
).rejects.toThrow(/No matching version found/);
expect(distribution['findInToolcache']()).toBeNull();
}
);
it('keeps patch-only and exact-build resolution cache identities distinct', () => {
const distribution = new LibericaDistributions({
version: '17.0.20.1',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
expect(distribution['version']).toBe('17.0.20.1');
});
it('orders main versions, patches, and builds consistently in cache', async () => {
for (const version of ['17.0.20-1.2', '17.0.20-1.10', '17.0.21-1']) {
const javaPath = path.join(
cacheRoot,
'Java_Liberica_jdk',
version,
'x64'
);
await fs.promises.mkdir(javaPath, {recursive: true});
await fs.promises.writeFile(`${javaPath}.complete`, '');
}
for (const [version, expected] of [
['17', '17.0.21+1'],
['17.0.20', '17.0.20+1.10'],
['17.0.20.1', '17.0.20+1.10']
]) {
const distribution = new LibericaDistributions({
version,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
expect(distribution['findInToolcache']()?.version).toBe(expected);
}
});
it('preserves early-access handling for patch-only requests', async () => {
const javaPath = path.join(
cacheRoot,
'Java_Liberica_jdk',
'17.0.20-ea.1.2',
'x64'
);
await fs.promises.mkdir(javaPath, {recursive: true});
await fs.promises.writeFile(`${javaPath}.complete`, '');
const distribution = new LibericaDistributions({
version: '17.0.20.1-ea',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
expect(distribution['stable']).toBe(false);
expect(distribution['findInToolcache']()).toEqual({
version: '17.0.20+1.2',
path: javaPath
});
});
});
describe('getPlatformOption', () => { describe('getPlatformOption', () => {
beforeEach(() => { beforeEach(() => {
// The linux row below is glibc, so pin the Alpine probe rather than // The linux row below is glibc, so pin the Alpine probe rather than
@@ -369,6 +557,36 @@ describe('convertVersionToSemver', () => {
}, },
'11.0.0+13' '11.0.0+13'
], ],
[
{
version: '17.0.20.1+1',
featureVersion: 17,
interimVersion: 0,
updateVersion: 20,
buildVersion: 1
},
'17.0.20+1.1'
],
[
{
version: '25.0.4.1+1',
featureVersion: 25,
interimVersion: 0,
updateVersion: 4,
buildVersion: 1
},
'25.0.4+1.1'
],
[
{
version: '17.0.20.1+2',
featureVersion: 17,
interimVersion: 0,
updateVersion: 20,
buildVersion: 2
},
'17.0.20+1.2'
],
[ [
{ {
version: '25.0.4+1.1', version: '25.0.4+1.1',
+132 -28
View File
@@ -7217,7 +7217,7 @@ function defaultFactory (origin, opts) {
} }
class Agent extends DispatcherBase { class Agent extends DispatcherBase {
constructor ({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { constructor ({ factory = defaultFactory, maxRedirections = 0, connect, tls, ...options } = {}) {
if (typeof factory !== 'function') { if (typeof factory !== 'function') {
throw new InvalidArgumentError('factory must be a function.') throw new InvalidArgumentError('factory must be a function.')
} }
@@ -7236,11 +7236,15 @@ class Agent extends DispatcherBase {
connect = { ...connect } connect = { ...connect }
} }
if (tls && typeof tls !== 'function') {
tls = { ...tls }
}
this[kInterceptors] = options.interceptors?.Agent && Array.isArray(options.interceptors.Agent) this[kInterceptors] = options.interceptors?.Agent && Array.isArray(options.interceptors.Agent)
? options.interceptors.Agent ? options.interceptors.Agent
: [createRedirectInterceptor({ maxRedirections })] : [createRedirectInterceptor({ maxRedirections })]
this[kOptions] = { ...util.deepClone(options), connect } this[kOptions] = { ...util.deepClone(options), connect, tls }
this[kOptions].interceptors = options.interceptors this[kOptions].interceptors = options.interceptors
? { ...options.interceptors } ? { ...options.interceptors }
: undefined : undefined
@@ -8273,8 +8277,6 @@ async function connectH1 (client, socket) {
socket[kParser] = new Parser(client, socket, llhttpInstance) socket[kParser] = new Parser(client, socket, llhttpInstance)
addListener(socket, 'error', function (err) { addListener(socket, 'error', function (err) {
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
const parser = this[kParser] const parser = this[kParser]
// On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded // On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded
@@ -9204,8 +9206,6 @@ async function connectH2 (client, socket) {
socket[kHTTP2Session] = session socket[kHTTP2Session] = session
util.addListener(socket, 'error', function (err) { util.addListener(socket, 'error', function (err) {
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
this[kError] = err this[kError] = err
this[kClient][kOnError](err) this[kClient][kOnError](err)
@@ -9279,8 +9279,6 @@ function resumeH2 (client) {
} }
function onHttp2SessionError (err) { function onHttp2SessionError (err) {
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
this[kSocket][kError] = err this[kSocket][kError] = err
this[kClient][kOnError](err) this[kClient][kOnError](err)
} }
@@ -9978,9 +9976,10 @@ class Client extends DispatcherBase {
// h2 // h2
maxConcurrentStreams, maxConcurrentStreams,
allowH2, allowH2,
webSocket webSocket,
eventSource
} = {}) { } = {}) {
super({ webSocket }) super({ webSocket, eventSource })
if (keepAlive !== undefined) { if (keepAlive !== undefined) {
throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead') throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead')
@@ -10501,6 +10500,7 @@ module.exports = Client
const buffer = __nccwpck_require__(4573)
const Dispatcher = __nccwpck_require__(883) const Dispatcher = __nccwpck_require__(883)
const { const {
ClientDestroyedError, ClientDestroyedError,
@@ -10513,6 +10513,7 @@ const kOnDestroyed = Symbol('onDestroyed')
const kOnClosed = Symbol('onClosed') const kOnClosed = Symbol('onClosed')
const kInterceptedDispatch = Symbol('Intercepted Dispatch') const kInterceptedDispatch = Symbol('Intercepted Dispatch')
const kWebSocketOptions = Symbol('webSocketOptions') const kWebSocketOptions = Symbol('webSocketOptions')
const kEventSourceOptions = Symbol('eventSourceOptions')
class DispatcherBase extends Dispatcher { class DispatcherBase extends Dispatcher {
constructor (opts) { constructor (opts) {
@@ -10523,6 +10524,7 @@ class DispatcherBase extends Dispatcher {
this[kClosed] = false this[kClosed] = false
this[kOnClosed] = [] this[kOnClosed] = []
this[kWebSocketOptions] = opts?.webSocket ?? {} this[kWebSocketOptions] = opts?.webSocket ?? {}
this[kEventSourceOptions] = opts?.eventSource ?? {}
} }
get webSocketOptions () { get webSocketOptions () {
@@ -10532,6 +10534,12 @@ class DispatcherBase extends Dispatcher {
} }
} }
get eventSourceOptions () {
return {
maxEventSize: this[kEventSourceOptions].maxEventSize ?? buffer.kStringMaxLength
}
}
get destroyed () { get destroyed () {
return this[kDestroyed] return this[kDestroyed]
} }
@@ -16890,6 +16898,7 @@ module.exports = {
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
const buffer = __nccwpck_require__(4573)
const { Transform } = __nccwpck_require__(7075) const { Transform } = __nccwpck_require__(7075)
const { isASCIINumber, isValidLastEventId } = __nccwpck_require__(4811) const { isASCIINumber, isValidLastEventId } = __nccwpck_require__(4811)
@@ -16914,11 +16923,19 @@ const COLON = 0x3A
*/ */
const SPACE = 0x20 const SPACE = 0x20
const defaultMaxEventSize = buffer.kStringMaxLength
const DATA = Buffer.from('data') const DATA = Buffer.from('data')
const EVENT = Buffer.from('event') const EVENT = Buffer.from('event')
const ID = Buffer.from('id') const ID = Buffer.from('id')
const RETRY = Buffer.from('retry') const RETRY = Buffer.from('retry')
// Each data field creates a string node, and each unconsumed input chunk keeps
// a Buffer wrapper. The absolute ceiling protects the large default byte limit.
const minParserItems = 1024
const maxParserItems = 131072
const bytesPerParserItem = 128
function isASCIINumberBytes (buffer, start) { function isASCIINumberBytes (buffer, start) {
if (start >= buffer.length) { if (start >= buffer.length) {
return false return false
@@ -16957,6 +16974,12 @@ function isFieldName (line, length, field) {
return true return true
} }
function createMaxEventSizeExceededError () {
const error = new Error('EventSource message size exceeded')
error.aborted = false
return error
}
/** /**
* @typedef {object} EventSourceStreamEvent * @typedef {object} EventSourceStreamEvent
* @type {object} * @type {object}
@@ -17005,6 +17028,13 @@ class EventSourceStream extends Transform {
pos = 0 pos = 0
lineChunkIndex = 0 lineChunkIndex = 0
linePos = 0 linePos = 0
lineLength = 0
eventSize = 0
eventFieldSizes = { data: 0, event: 0, id: 0, retry: 0 }
dataLineCount = 0
maxEventSize
maxDataLines
maxBufferedChunks
event = { event = {
data: undefined, data: undefined,
@@ -17015,6 +17045,7 @@ class EventSourceStream extends Transform {
/** /**
* @param {object} options * @param {object} options
* @param {number} [options.maxEventSize]
* @param {eventSourceSettings} options.eventSourceSettings * @param {eventSourceSettings} options.eventSourceSettings
* @param {Function} [options.push] * @param {Function} [options.push]
*/ */
@@ -17026,6 +17057,12 @@ class EventSourceStream extends Transform {
super(options) super(options)
this.state = options.eventSourceSettings || {} 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) { if (options.push) {
this.push = options.push this.push = options.push
} }
@@ -17043,6 +17080,14 @@ class EventSourceStream extends Transform {
return return
} }
// A leading line ending can immediately release the currently buffered
// line, even when it uses the final allowed chunk slot.
if (this.maxEventSize > 0 &&
this.chunks.length >= this.maxBufferedChunks &&
chunk[0] !== LF && chunk[0] !== CR) {
callback(createMaxEventSizeExceededError())
return
}
this.chunks.push(chunk) this.chunks.push(chunk)
// Strip leading byte-order-mark if we opened the stream and started // Strip leading byte-order-mark if we opened the stream and started
@@ -17121,7 +17166,12 @@ class EventSourceStream extends Transform {
// In any case, we can process the line as we reached an // In any case, we can process the line as we reached an
// end-of-line character // end-of-line character
try {
this.parseLine(this.readLine(), this.event) this.parseLine(this.readLine(), this.event)
} catch (error) {
callback(error)
return
}
this.consumeCurrentByte() this.consumeCurrentByte()
// A line was processed and this could be the end of the event. We need // A line was processed and this could be the end of the event. We need
// to check if the next line is empty to determine if the event is // to check if the next line is empty to determine if the event is
@@ -17130,15 +17180,28 @@ class EventSourceStream extends Transform {
continue continue
} }
// readLine() is only called after CR or LF. Reject an unfinished line
// before it can retain an unbounded number of decoded chunks. The seven
// extra bytes allow the longest field prefix ("event: " or "retry: ").
if (this.maxEventSize > 0 && ++this.lineLength > this.maxEventSize + 7) {
callback(createMaxEventSizeExceededError())
return
}
this.advanceCursor() this.advanceCursor()
} }
callback() callback()
} }
_destroy (error, callback) {
this.chunks.length = 0
this.clearEvent()
super._destroy(error, callback)
}
/** /**
* @param {Buffer} line * @param {Buffer} line
* @param {EventStreamEvent} event * @param {EventSourceStreamEvent} event
*/ */
parseLine (line, event) { parseLine (line, event) {
// If the line is empty (a blank line) // If the line is empty (a blank line)
@@ -17172,6 +17235,13 @@ class EventSourceStream extends Transform {
} }
if (isFieldName(line, fieldLength, DATA)) { 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 === undefined ? 0 : 1) + valueBytes
this.setEventFieldSize('data', dataSize)
const value = line.toString('utf8', valueStart) const value = line.toString('utf8', valueStart)
if (event.data === undefined) { if (event.data === undefined) {
@@ -17179,11 +17249,13 @@ class EventSourceStream extends Transform {
} else { } else {
event.data += `\n${value}` event.data += `\n${value}`
} }
this.dataLineCount++
return return
} }
if (isFieldName(line, fieldLength, RETRY)) { if (isFieldName(line, fieldLength, RETRY)) {
if (isASCIINumberBytes(line, valueStart)) { if (isASCIINumberBytes(line, valueStart)) {
this.setEventFieldSize('retry', line.length - valueStart)
event.retry = line.toString('utf8', valueStart) event.retry = line.toString('utf8', valueStart)
} }
return return
@@ -17191,18 +17263,27 @@ class EventSourceStream extends Transform {
if (isFieldName(line, fieldLength, ID)) { if (isFieldName(line, fieldLength, ID)) {
if (isValidLastEventIdBytes(line, valueStart)) { if (isValidLastEventIdBytes(line, valueStart)) {
this.setEventFieldSize('id', line.length - valueStart)
event.id = line.toString('utf8', valueStart) event.id = line.toString('utf8', valueStart)
} }
return return
} }
if (isFieldName(line, fieldLength, EVENT)) { if (isFieldName(line, fieldLength, EVENT)) {
const value = line.toString('utf8', valueStart) if (valueStart < line.length) {
this.setEventFieldSize('event', line.length - valueStart)
event.event = line.toString('utf8', valueStart)
}
}
}
if (value.length > 0) { setEventFieldSize (field, size) {
event.event = value const eventSize = this.eventSize - this.eventFieldSizes[field] + size
} if (this.maxEventSize > 0 && eventSize > this.maxEventSize) {
throw createMaxEventSizeExceededError()
} }
this.eventSize = eventSize
this.eventFieldSizes[field] = size
} }
/** /**
@@ -17235,6 +17316,12 @@ class EventSourceStream extends Transform {
this.event.event = undefined this.event.event = undefined
this.event.id = undefined this.event.id = undefined
this.event.retry = undefined this.event.retry = undefined
this.eventSize = 0
this.dataLineCount = 0
this.eventFieldSizes.data = 0
this.eventFieldSizes.event = 0
this.eventFieldSizes.id = 0
this.eventFieldSizes.retry = 0
} }
hasPendingEvent () { hasPendingEvent () {
@@ -17270,14 +17357,16 @@ class EventSourceStream extends Transform {
syncLineStartToCursor () { syncLineStartToCursor () {
this.lineChunkIndex = this.chunkIndex this.lineChunkIndex = this.chunkIndex
this.linePos = this.pos this.linePos = this.pos
this.lineLength = 0
this.dropConsumedChunks() this.dropConsumedChunks()
} }
dropConsumedChunks () { dropConsumedChunks () {
while (this.lineChunkIndex > 0) { if (this.lineChunkIndex > 0) {
this.chunks.shift() const consumed = this.lineChunkIndex
this.lineChunkIndex-- this.chunks.splice(0, consumed)
this.chunkIndex-- this.lineChunkIndex = 0
this.chunkIndex -= consumed
} }
if (this.chunkIndex === this.chunks.length) { if (this.chunkIndex === this.chunks.length) {
@@ -17402,6 +17491,7 @@ const { isNetworkError } = __nccwpck_require__(9051)
const { delay } = __nccwpck_require__(4811) const { delay } = __nccwpck_require__(4811)
const { kEnumerableProperty } = __nccwpck_require__(3440) const { kEnumerableProperty } = __nccwpck_require__(3440)
const { environmentSettingsObject } = __nccwpck_require__(3168) const { environmentSettingsObject } = __nccwpck_require__(3168)
const { getGlobalDispatcher } = __nccwpck_require__(2581)
let experimentalWarned = false let experimentalWarned = false
@@ -17683,6 +17773,7 @@ class EventSource extends EventTarget {
const eventSourceStream = new EventSourceStream({ const eventSourceStream = new EventSourceStream({
eventSourceSettings: this.#state, eventSourceSettings: this.#state,
maxEventSize: this.#dispatcher.eventSourceOptions?.maxEventSize,
push: (event) => { push: (event) => {
this.dispatchEvent(createFastMessageEvent( this.dispatchEvent(createFastMessageEvent(
event.type, event.type,
@@ -17861,7 +17952,8 @@ webidl.converters.EventSourceInitDict = webidl.dictionaryConverter([
}, },
{ {
key: 'dispatcher', // undici only key: 'dispatcher', // undici only
converter: webidl.converters.any converter: webidl.converters.any,
defaultValue: () => getGlobalDispatcher()
} }
]) ])
@@ -22957,8 +23049,10 @@ async function httpNetworkFetch (
// 19. Run these steps in parallel: // 19. Run these steps in parallel:
// 1. Run these steps, but abort when fetchParams is canceled: // 1. Run these steps, but abort when fetchParams is canceled:
fetchParams.controller.onAborted = onAborted if (!fetchParams.controller.resume) {
fetchParams.controller.on('terminated', onAborted) fetchParams.controller.on('terminated', onAborted)
}
fetchParams.controller.resume = async () => { fetchParams.controller.resume = async () => {
// 1. While true // 1. While true
while (true) { while (true) {
@@ -23127,8 +23221,6 @@ async function httpNetworkFetch (
} }
location = headersList.get('location', true) location = headersList.get('location', true)
this.body = new Readable({ read: resume })
const decoders = [] const decoders = []
const willFollow = location && request.redirect === 'follow' && const willFollow = location && request.redirect === 'follow' &&
@@ -23146,7 +23238,7 @@ async function httpNetworkFetch (
// CVE fix similar to urllib3 (GHSA-gm62-xv2j-4w53) and curl (CVE-2022-32206). // CVE fix similar to urllib3 (GHSA-gm62-xv2j-4w53) and curl (CVE-2022-32206).
const maxContentEncodings = 5 const maxContentEncodings = 5
if (codings.length > maxContentEncodings) { 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 return true
} }
@@ -23179,6 +23271,8 @@ async function httpNetworkFetch (
} }
} }
this.body = new Readable({ read: resume })
const onError = this.onError.bind(this) const onError = this.onError.bind(this)
resolve({ resolve({
@@ -23225,10 +23319,6 @@ async function httpNetworkFetch (
fetchParams.controller.off('terminated', this.abort) fetchParams.controller.off('terminated', this.abort)
} }
if (fetchParams.controller.onAborted) {
fetchParams.controller.off('terminated', fetchParams.controller.onAborted)
}
fetchParams.controller.ended = true fetchParams.controller.ended = true
this.body.push(null) this.body.push(null)
@@ -29703,6 +29793,20 @@ class ByteParser extends Writable {
if (isControlFrame(this.#info.opcode)) { if (isControlFrame(this.#info.opcode)) {
this.#loop = this.parseControlFrame(body) this.#loop = this.parseControlFrame(body)
this.#state = parserStates.INFO this.#state = parserStates.INFO
// If the automatic PONG/CLOSE reply filled the socket's write buffer,
// stop parsing and resume on drain so a PING flood cannot grow the
// outbound queue without bound.
const socket = this.ws[kResponse].socket
if (this.#loop && socket.writableNeedDrain) {
this.#loop = false
socket.once('drain', () => {
if (this.destroyed) return
this.#loop = true
this.run(callback)
})
return
}
} else { } else {
if (!this.#info.compressed) { if (!this.#info.compressed) {
if (!this.writeFragments(body)) { if (!this.writeFragments(body)) {
+10 -4
View File
@@ -378,7 +378,7 @@ class JavaBase {
core/* info */.pq(`Java ${foundJava.version} was downloaded`); core/* info */.pq(`Java ${foundJava.version} was downloaded`);
if (javaRelease.floating) { if (javaRelease.floating) {
if (!semver_default().valid(foundJava.version) || if (!semver_default().valid(foundJava.version) ||
!(0,util/* isVersionSatisfies */.y)(this.version, foundJava.version)) { !this.isVersionSatisfied(this.version, foundJava.version)) {
throw new Error(`The downloaded ${this.distribution} artifact reported Java ${foundJava.version}, which does not satisfy '${this.version}'.`); throw new Error(`The downloaded ${this.distribution} artifact reported Java ${foundJava.version}, which does not satisfy '${this.version}'.`);
} }
javaRelease = { ...javaRelease, version: foundJava.version }; javaRelease = { ...javaRelease, version: foundJava.version };
@@ -501,7 +501,7 @@ class JavaBase {
return javaRelease; return javaRelease;
} }
if (!semver_default().valid(restored.release.version) || if (!semver_default().valid(restored.release.version) ||
!(0,util/* isVersionSatisfies */.y)(this.version, restored.release.version)) { !this.isVersionSatisfied(this.version, restored.release.version)) {
core/* debug */.Yz(`Ignoring the cached concrete version '${restored.release.version}' for ${this.distribution} ${this.version}.`); core/* debug */.Yz(`Ignoring the cached concrete version '${restored.release.version}' for ${this.distribution} ${this.version}.`);
return javaRelease; return javaRelease;
} }
@@ -684,10 +684,10 @@ class JavaBase {
}) })
.filter(item => item.stable === this.stable); .filter(item => item.stable === this.stable);
const satisfiedVersions = availableVersions const satisfiedVersions = availableVersions
.filter(item => (0,util/* isVersionSatisfies */.y)(this.version, item.version)) .filter(item => this.isVersionSatisfied(this.version, item.version))
.filter(item => item.path) .filter(item => item.path)
.sort((a, b) => { .sort((a, b) => {
return -semver_default().compareBuild(a.version, b.version); return -this.compareVersions(a.version, b.version);
}); });
if (!satisfiedVersions || satisfiedVersions.length === 0) { if (!satisfiedVersions || satisfiedVersions.length === 0) {
return null; return null;
@@ -697,6 +697,12 @@ class JavaBase {
path: satisfiedVersions[0].path path: satisfiedVersions[0].path
}; };
} }
isVersionSatisfied(range, version) {
return (0,util/* isVersionSatisfies */.y)(range, version);
}
compareVersions(a, b) {
return semver_default().compareBuild(a, b);
}
normalizeVersion(version) { normalizeVersion(version) {
let stable = true; let stable = true;
const latest = false; const latest = false;
+38 -2
View File
@@ -52,14 +52,46 @@ class LibericaDistributions extends _base_installer_js__WEBPACK_IMPORTED_MODULE_
version: this.convertVersionToSemver(item) version: this.convertVersionToSemver(item)
})); }));
const satisfiedVersion = availableVersions const satisfiedVersion = availableVersions
.filter(item => (0,_util_js__WEBPACK_IMPORTED_MODULE_2__/* .isVersionSatisfies */ .y)(range, item.version)) .filter(item => this.isVersionSatisfied(range, item.version))
.sort((a, b) => -semver__WEBPACK_IMPORTED_MODULE_1___default().compareBuild(a.version, b.version))[0]; .sort((a, b) => -this.compareVersions(a.version, b.version))[0];
if (!satisfiedVersion) { if (!satisfiedVersion) {
const availableVersionStrings = availableVersions.map(item => item.version); const availableVersionStrings = availableVersions.map(item => item.version);
throw this.createVersionNotFoundError(range, availableVersionStrings); throw this.createVersionNotFoundError(range, availableVersionStrings);
} }
return satisfiedVersion; return satisfiedVersion;
} }
normalizeVersion(version) {
const normalized = super.normalizeVersion(version);
if (/^\d+\.\d+\.\d+\.\d+(?:-ea)?$/.test(version)) {
// Keep patch-only requests distinct from exact SDKMAN build requests.
normalized.version = version.replace(/-ea$/, '');
}
return normalized;
}
isVersionSatisfied(range, version) {
const patchRequest = range.match(/^(\d+\.\d+\.\d+)\.(\d+)$/);
if (patchRequest) {
const candidate = semver__WEBPACK_IMPORTED_MODULE_1___default().parse(version);
if (!candidate || !semver__WEBPACK_IMPORTED_MODULE_1___default().eq(patchRequest[1], candidate)) {
return false;
}
const patch = candidate.build.length > 1 ? candidate.build[0] : '0';
return patch === patchRequest[2];
}
return super.isVersionSatisfied(range, version);
}
compareVersions(a, b) {
const mainComparison = semver__WEBPACK_IMPORTED_MODULE_1___default().compare(a, b);
if (mainComparison !== 0) {
return mainComparison;
}
// SDKMAN encodes patch.build, but unpatched releases contain only build.
const patchAndBuild = (version) => {
const build = new (semver__WEBPACK_IMPORTED_MODULE_1___default().SemVer)(version).build;
return (build.length > 1 ? build : ['0', ...build]).join('.');
};
return semver__WEBPACK_IMPORTED_MODULE_1___default().compareBuild(`0.0.0+${patchAndBuild(a)}`, `0.0.0+${patchAndBuild(b)}`);
}
async getAvailableVersions() { async getAvailableVersions() {
if (_actions_core__WEBPACK_IMPORTED_MODULE_3__/* .isDebug */ ._o()) { if (_actions_core__WEBPACK_IMPORTED_MODULE_3__/* .isDebug */ ._o()) {
console.time('Retrieving available versions for Liberica took'); // eslint-disable-line no-console console.time('Retrieving available versions for Liberica took'); // eslint-disable-line no-console
@@ -131,6 +163,10 @@ class LibericaDistributions extends _base_installer_js__WEBPACK_IMPORTED_MODULE_
const { featureVersion, interimVersion, updateVersion } = version; const { featureVersion, interimVersion, updateVersion } = version;
const buildVersion = version.version.split('+')[1] || version.buildVersion; const buildVersion = version.version.split('+')[1] || version.buildVersion;
const mainVersion = [featureVersion, interimVersion, updateVersion].join('.'); const mainVersion = [featureVersion, interimVersion, updateVersion].join('.');
const patchVersion = version.version.split('+')[0].split('.')[3];
if (patchVersion) {
return `${mainVersion}+${patchVersion}.${buildVersion}`;
}
if (buildVersion != 0) { if (buildVersion != 0) {
return `${mainVersion}+${buildVersion}`; return `${mainVersion}+${buildVersion}`;
} }
+132 -28
View File
@@ -7217,7 +7217,7 @@ function defaultFactory (origin, opts) {
} }
class Agent extends DispatcherBase { class Agent extends DispatcherBase {
constructor ({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { constructor ({ factory = defaultFactory, maxRedirections = 0, connect, tls, ...options } = {}) {
if (typeof factory !== 'function') { if (typeof factory !== 'function') {
throw new InvalidArgumentError('factory must be a function.') throw new InvalidArgumentError('factory must be a function.')
} }
@@ -7236,11 +7236,15 @@ class Agent extends DispatcherBase {
connect = { ...connect } connect = { ...connect }
} }
if (tls && typeof tls !== 'function') {
tls = { ...tls }
}
this[kInterceptors] = options.interceptors?.Agent && Array.isArray(options.interceptors.Agent) this[kInterceptors] = options.interceptors?.Agent && Array.isArray(options.interceptors.Agent)
? options.interceptors.Agent ? options.interceptors.Agent
: [createRedirectInterceptor({ maxRedirections })] : [createRedirectInterceptor({ maxRedirections })]
this[kOptions] = { ...util.deepClone(options), connect } this[kOptions] = { ...util.deepClone(options), connect, tls }
this[kOptions].interceptors = options.interceptors this[kOptions].interceptors = options.interceptors
? { ...options.interceptors } ? { ...options.interceptors }
: undefined : undefined
@@ -8273,8 +8277,6 @@ async function connectH1 (client, socket) {
socket[kParser] = new Parser(client, socket, llhttpInstance) socket[kParser] = new Parser(client, socket, llhttpInstance)
addListener(socket, 'error', function (err) { addListener(socket, 'error', function (err) {
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
const parser = this[kParser] const parser = this[kParser]
// On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded // On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded
@@ -9204,8 +9206,6 @@ async function connectH2 (client, socket) {
socket[kHTTP2Session] = session socket[kHTTP2Session] = session
util.addListener(socket, 'error', function (err) { util.addListener(socket, 'error', function (err) {
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
this[kError] = err this[kError] = err
this[kClient][kOnError](err) this[kClient][kOnError](err)
@@ -9279,8 +9279,6 @@ function resumeH2 (client) {
} }
function onHttp2SessionError (err) { function onHttp2SessionError (err) {
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
this[kSocket][kError] = err this[kSocket][kError] = err
this[kClient][kOnError](err) this[kClient][kOnError](err)
} }
@@ -9978,9 +9976,10 @@ class Client extends DispatcherBase {
// h2 // h2
maxConcurrentStreams, maxConcurrentStreams,
allowH2, allowH2,
webSocket webSocket,
eventSource
} = {}) { } = {}) {
super({ webSocket }) super({ webSocket, eventSource })
if (keepAlive !== undefined) { if (keepAlive !== undefined) {
throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead') throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead')
@@ -10501,6 +10500,7 @@ module.exports = Client
const buffer = __nccwpck_require__(4573)
const Dispatcher = __nccwpck_require__(883) const Dispatcher = __nccwpck_require__(883)
const { const {
ClientDestroyedError, ClientDestroyedError,
@@ -10513,6 +10513,7 @@ const kOnDestroyed = Symbol('onDestroyed')
const kOnClosed = Symbol('onClosed') const kOnClosed = Symbol('onClosed')
const kInterceptedDispatch = Symbol('Intercepted Dispatch') const kInterceptedDispatch = Symbol('Intercepted Dispatch')
const kWebSocketOptions = Symbol('webSocketOptions') const kWebSocketOptions = Symbol('webSocketOptions')
const kEventSourceOptions = Symbol('eventSourceOptions')
class DispatcherBase extends Dispatcher { class DispatcherBase extends Dispatcher {
constructor (opts) { constructor (opts) {
@@ -10523,6 +10524,7 @@ class DispatcherBase extends Dispatcher {
this[kClosed] = false this[kClosed] = false
this[kOnClosed] = [] this[kOnClosed] = []
this[kWebSocketOptions] = opts?.webSocket ?? {} this[kWebSocketOptions] = opts?.webSocket ?? {}
this[kEventSourceOptions] = opts?.eventSource ?? {}
} }
get webSocketOptions () { get webSocketOptions () {
@@ -10532,6 +10534,12 @@ class DispatcherBase extends Dispatcher {
} }
} }
get eventSourceOptions () {
return {
maxEventSize: this[kEventSourceOptions].maxEventSize ?? buffer.kStringMaxLength
}
}
get destroyed () { get destroyed () {
return this[kDestroyed] return this[kDestroyed]
} }
@@ -16890,6 +16898,7 @@ module.exports = {
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
const buffer = __nccwpck_require__(4573)
const { Transform } = __nccwpck_require__(7075) const { Transform } = __nccwpck_require__(7075)
const { isASCIINumber, isValidLastEventId } = __nccwpck_require__(4811) const { isASCIINumber, isValidLastEventId } = __nccwpck_require__(4811)
@@ -16914,11 +16923,19 @@ const COLON = 0x3A
*/ */
const SPACE = 0x20 const SPACE = 0x20
const defaultMaxEventSize = buffer.kStringMaxLength
const DATA = Buffer.from('data') const DATA = Buffer.from('data')
const EVENT = Buffer.from('event') const EVENT = Buffer.from('event')
const ID = Buffer.from('id') const ID = Buffer.from('id')
const RETRY = Buffer.from('retry') const RETRY = Buffer.from('retry')
// Each data field creates a string node, and each unconsumed input chunk keeps
// a Buffer wrapper. The absolute ceiling protects the large default byte limit.
const minParserItems = 1024
const maxParserItems = 131072
const bytesPerParserItem = 128
function isASCIINumberBytes (buffer, start) { function isASCIINumberBytes (buffer, start) {
if (start >= buffer.length) { if (start >= buffer.length) {
return false return false
@@ -16957,6 +16974,12 @@ function isFieldName (line, length, field) {
return true return true
} }
function createMaxEventSizeExceededError () {
const error = new Error('EventSource message size exceeded')
error.aborted = false
return error
}
/** /**
* @typedef {object} EventSourceStreamEvent * @typedef {object} EventSourceStreamEvent
* @type {object} * @type {object}
@@ -17005,6 +17028,13 @@ class EventSourceStream extends Transform {
pos = 0 pos = 0
lineChunkIndex = 0 lineChunkIndex = 0
linePos = 0 linePos = 0
lineLength = 0
eventSize = 0
eventFieldSizes = { data: 0, event: 0, id: 0, retry: 0 }
dataLineCount = 0
maxEventSize
maxDataLines
maxBufferedChunks
event = { event = {
data: undefined, data: undefined,
@@ -17015,6 +17045,7 @@ class EventSourceStream extends Transform {
/** /**
* @param {object} options * @param {object} options
* @param {number} [options.maxEventSize]
* @param {eventSourceSettings} options.eventSourceSettings * @param {eventSourceSettings} options.eventSourceSettings
* @param {Function} [options.push] * @param {Function} [options.push]
*/ */
@@ -17026,6 +17057,12 @@ class EventSourceStream extends Transform {
super(options) super(options)
this.state = options.eventSourceSettings || {} 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) { if (options.push) {
this.push = options.push this.push = options.push
} }
@@ -17043,6 +17080,14 @@ class EventSourceStream extends Transform {
return return
} }
// A leading line ending can immediately release the currently buffered
// line, even when it uses the final allowed chunk slot.
if (this.maxEventSize > 0 &&
this.chunks.length >= this.maxBufferedChunks &&
chunk[0] !== LF && chunk[0] !== CR) {
callback(createMaxEventSizeExceededError())
return
}
this.chunks.push(chunk) this.chunks.push(chunk)
// Strip leading byte-order-mark if we opened the stream and started // Strip leading byte-order-mark if we opened the stream and started
@@ -17121,7 +17166,12 @@ class EventSourceStream extends Transform {
// In any case, we can process the line as we reached an // In any case, we can process the line as we reached an
// end-of-line character // end-of-line character
try {
this.parseLine(this.readLine(), this.event) this.parseLine(this.readLine(), this.event)
} catch (error) {
callback(error)
return
}
this.consumeCurrentByte() this.consumeCurrentByte()
// A line was processed and this could be the end of the event. We need // A line was processed and this could be the end of the event. We need
// to check if the next line is empty to determine if the event is // to check if the next line is empty to determine if the event is
@@ -17130,15 +17180,28 @@ class EventSourceStream extends Transform {
continue continue
} }
// readLine() is only called after CR or LF. Reject an unfinished line
// before it can retain an unbounded number of decoded chunks. The seven
// extra bytes allow the longest field prefix ("event: " or "retry: ").
if (this.maxEventSize > 0 && ++this.lineLength > this.maxEventSize + 7) {
callback(createMaxEventSizeExceededError())
return
}
this.advanceCursor() this.advanceCursor()
} }
callback() callback()
} }
_destroy (error, callback) {
this.chunks.length = 0
this.clearEvent()
super._destroy(error, callback)
}
/** /**
* @param {Buffer} line * @param {Buffer} line
* @param {EventStreamEvent} event * @param {EventSourceStreamEvent} event
*/ */
parseLine (line, event) { parseLine (line, event) {
// If the line is empty (a blank line) // If the line is empty (a blank line)
@@ -17172,6 +17235,13 @@ class EventSourceStream extends Transform {
} }
if (isFieldName(line, fieldLength, DATA)) { 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 === undefined ? 0 : 1) + valueBytes
this.setEventFieldSize('data', dataSize)
const value = line.toString('utf8', valueStart) const value = line.toString('utf8', valueStart)
if (event.data === undefined) { if (event.data === undefined) {
@@ -17179,11 +17249,13 @@ class EventSourceStream extends Transform {
} else { } else {
event.data += `\n${value}` event.data += `\n${value}`
} }
this.dataLineCount++
return return
} }
if (isFieldName(line, fieldLength, RETRY)) { if (isFieldName(line, fieldLength, RETRY)) {
if (isASCIINumberBytes(line, valueStart)) { if (isASCIINumberBytes(line, valueStart)) {
this.setEventFieldSize('retry', line.length - valueStart)
event.retry = line.toString('utf8', valueStart) event.retry = line.toString('utf8', valueStart)
} }
return return
@@ -17191,18 +17263,27 @@ class EventSourceStream extends Transform {
if (isFieldName(line, fieldLength, ID)) { if (isFieldName(line, fieldLength, ID)) {
if (isValidLastEventIdBytes(line, valueStart)) { if (isValidLastEventIdBytes(line, valueStart)) {
this.setEventFieldSize('id', line.length - valueStart)
event.id = line.toString('utf8', valueStart) event.id = line.toString('utf8', valueStart)
} }
return return
} }
if (isFieldName(line, fieldLength, EVENT)) { if (isFieldName(line, fieldLength, EVENT)) {
const value = line.toString('utf8', valueStart) if (valueStart < line.length) {
this.setEventFieldSize('event', line.length - valueStart)
event.event = line.toString('utf8', valueStart)
}
}
}
if (value.length > 0) { setEventFieldSize (field, size) {
event.event = value const eventSize = this.eventSize - this.eventFieldSizes[field] + size
} if (this.maxEventSize > 0 && eventSize > this.maxEventSize) {
throw createMaxEventSizeExceededError()
} }
this.eventSize = eventSize
this.eventFieldSizes[field] = size
} }
/** /**
@@ -17235,6 +17316,12 @@ class EventSourceStream extends Transform {
this.event.event = undefined this.event.event = undefined
this.event.id = undefined this.event.id = undefined
this.event.retry = undefined this.event.retry = undefined
this.eventSize = 0
this.dataLineCount = 0
this.eventFieldSizes.data = 0
this.eventFieldSizes.event = 0
this.eventFieldSizes.id = 0
this.eventFieldSizes.retry = 0
} }
hasPendingEvent () { hasPendingEvent () {
@@ -17270,14 +17357,16 @@ class EventSourceStream extends Transform {
syncLineStartToCursor () { syncLineStartToCursor () {
this.lineChunkIndex = this.chunkIndex this.lineChunkIndex = this.chunkIndex
this.linePos = this.pos this.linePos = this.pos
this.lineLength = 0
this.dropConsumedChunks() this.dropConsumedChunks()
} }
dropConsumedChunks () { dropConsumedChunks () {
while (this.lineChunkIndex > 0) { if (this.lineChunkIndex > 0) {
this.chunks.shift() const consumed = this.lineChunkIndex
this.lineChunkIndex-- this.chunks.splice(0, consumed)
this.chunkIndex-- this.lineChunkIndex = 0
this.chunkIndex -= consumed
} }
if (this.chunkIndex === this.chunks.length) { if (this.chunkIndex === this.chunks.length) {
@@ -17402,6 +17491,7 @@ const { isNetworkError } = __nccwpck_require__(9051)
const { delay } = __nccwpck_require__(4811) const { delay } = __nccwpck_require__(4811)
const { kEnumerableProperty } = __nccwpck_require__(3440) const { kEnumerableProperty } = __nccwpck_require__(3440)
const { environmentSettingsObject } = __nccwpck_require__(3168) const { environmentSettingsObject } = __nccwpck_require__(3168)
const { getGlobalDispatcher } = __nccwpck_require__(2581)
let experimentalWarned = false let experimentalWarned = false
@@ -17683,6 +17773,7 @@ class EventSource extends EventTarget {
const eventSourceStream = new EventSourceStream({ const eventSourceStream = new EventSourceStream({
eventSourceSettings: this.#state, eventSourceSettings: this.#state,
maxEventSize: this.#dispatcher.eventSourceOptions?.maxEventSize,
push: (event) => { push: (event) => {
this.dispatchEvent(createFastMessageEvent( this.dispatchEvent(createFastMessageEvent(
event.type, event.type,
@@ -17861,7 +17952,8 @@ webidl.converters.EventSourceInitDict = webidl.dictionaryConverter([
}, },
{ {
key: 'dispatcher', // undici only key: 'dispatcher', // undici only
converter: webidl.converters.any converter: webidl.converters.any,
defaultValue: () => getGlobalDispatcher()
} }
]) ])
@@ -22957,8 +23049,10 @@ async function httpNetworkFetch (
// 19. Run these steps in parallel: // 19. Run these steps in parallel:
// 1. Run these steps, but abort when fetchParams is canceled: // 1. Run these steps, but abort when fetchParams is canceled:
fetchParams.controller.onAborted = onAborted if (!fetchParams.controller.resume) {
fetchParams.controller.on('terminated', onAborted) fetchParams.controller.on('terminated', onAborted)
}
fetchParams.controller.resume = async () => { fetchParams.controller.resume = async () => {
// 1. While true // 1. While true
while (true) { while (true) {
@@ -23127,8 +23221,6 @@ async function httpNetworkFetch (
} }
location = headersList.get('location', true) location = headersList.get('location', true)
this.body = new Readable({ read: resume })
const decoders = [] const decoders = []
const willFollow = location && request.redirect === 'follow' && const willFollow = location && request.redirect === 'follow' &&
@@ -23146,7 +23238,7 @@ async function httpNetworkFetch (
// CVE fix similar to urllib3 (GHSA-gm62-xv2j-4w53) and curl (CVE-2022-32206). // CVE fix similar to urllib3 (GHSA-gm62-xv2j-4w53) and curl (CVE-2022-32206).
const maxContentEncodings = 5 const maxContentEncodings = 5
if (codings.length > maxContentEncodings) { 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 return true
} }
@@ -23179,6 +23271,8 @@ async function httpNetworkFetch (
} }
} }
this.body = new Readable({ read: resume })
const onError = this.onError.bind(this) const onError = this.onError.bind(this)
resolve({ resolve({
@@ -23225,10 +23319,6 @@ async function httpNetworkFetch (
fetchParams.controller.off('terminated', this.abort) fetchParams.controller.off('terminated', this.abort)
} }
if (fetchParams.controller.onAborted) {
fetchParams.controller.off('terminated', fetchParams.controller.onAborted)
}
fetchParams.controller.ended = true fetchParams.controller.ended = true
this.body.push(null) this.body.push(null)
@@ -29703,6 +29793,20 @@ class ByteParser extends Writable {
if (isControlFrame(this.#info.opcode)) { if (isControlFrame(this.#info.opcode)) {
this.#loop = this.parseControlFrame(body) this.#loop = this.parseControlFrame(body)
this.#state = parserStates.INFO this.#state = parserStates.INFO
// If the automatic PONG/CLOSE reply filled the socket's write buffer,
// stop parsing and resume on drain so a PING flood cannot grow the
// outbound queue without bound.
const socket = this.ws[kResponse].socket
if (this.#loop && socket.writableNeedDrain) {
this.#loop = false
socket.once('drain', () => {
if (this.destroyed) return
this.#loop = true
this.run(callback)
})
return
}
} else { } else {
if (!this.#info.compressed) { if (!this.#info.compressed) {
if (!this.writeFragments(body)) { if (!this.writeFragments(body)) {
+6
View File
@@ -83,6 +83,12 @@ steps:
### Liberica ### Liberica
Exact patch releases use SDKMAN's `X.Y.Z+P.B` notation, including in `.sdkmanrc`.
For example, `java=17.0.20+1.1-librca` selects BellSoft's `17.0.20.1+1` release.
Alternatively, `java-version: '17.0.20.1'` selects the newest build of patch 1,
whereas `java-version: '17.0.20+1'` selects the exact unpatched build 1.
Floating versions such as `17` prefer newer patches before comparing build numbers.
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v7
+7 -7
View File
@@ -4320,13 +4320,13 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/handlebars": { "node_modules/handlebars": {
"version": "4.7.9", "version": "4.7.10",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.10.tgz",
"integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", "integrity": "sha512-P5VJMVM7qgBn6vjXMw8WG9uVI+ncf2pi72j4de4yz5ZULLj2RGqLYaKOYGsgyrViQ0tePOVlN1tDCCXXtFqXKg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"minimist": "^1.2.5", "minimist": "^1.2.8",
"neo-async": "^2.6.2", "neo-async": "^2.6.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
"wordwrap": "^1.0.0" "wordwrap": "^1.0.0"
@@ -6375,9 +6375,9 @@
} }
}, },
"node_modules/undici": { "node_modules/undici": {
"version": "6.29.0", "version": "6.29.1",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.29.0.tgz", "resolved": "https://registry.npmjs.org/undici/-/undici-6.29.1.tgz",
"integrity": "sha512-R+RODBqp6i2pPflGdq+xIOUkl+RNfGgHwoinecKu/JCuf2uO06cOKoDbI2P7Dn6KcswdKwrczbU6IYJ6K8X+wg==", "integrity": "sha512-EvRlUt/QqAEvXdQeRMYUfwOQsfzpDztykrG2owGEE/rBOBoYv9uF39ZzsNDh4lTFHhTr2XOZjKkYgueD12ZmGA==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18.17" "node": ">=18.17"
+12 -4
View File
@@ -241,7 +241,7 @@ export abstract class JavaBase {
if (javaRelease.floating) { if (javaRelease.floating) {
if ( if (
!semver.valid(foundJava.version) || !semver.valid(foundJava.version) ||
!isVersionSatisfies(this.version, foundJava.version) !this.isVersionSatisfied(this.version, foundJava.version)
) { ) {
throw new Error( throw new Error(
`The downloaded ${this.distribution} artifact reported Java ${foundJava.version}, which does not satisfy '${this.version}'.` `The downloaded ${this.distribution} artifact reported Java ${foundJava.version}, which does not satisfy '${this.version}'.`
@@ -401,7 +401,7 @@ export abstract class JavaBase {
} }
if ( if (
!semver.valid(restored.release.version) || !semver.valid(restored.release.version) ||
!isVersionSatisfies(this.version, restored.release.version) !this.isVersionSatisfied(this.version, restored.release.version)
) { ) {
core.debug( core.debug(
`Ignoring the cached concrete version '${restored.release.version}' for ${this.distribution} ${this.version}.` `Ignoring the cached concrete version '${restored.release.version}' for ${this.distribution} ${this.version}.`
@@ -622,10 +622,10 @@ export abstract class JavaBase {
.filter(item => item.stable === this.stable); .filter(item => item.stable === this.stable);
const satisfiedVersions = availableVersions const satisfiedVersions = availableVersions
.filter(item => isVersionSatisfies(this.version, item.version)) .filter(item => this.isVersionSatisfied(this.version, item.version))
.filter(item => item.path) .filter(item => item.path)
.sort((a, b) => { .sort((a, b) => {
return -semver.compareBuild(a.version, b.version); return -this.compareVersions(a.version, b.version);
}); });
if (!satisfiedVersions || satisfiedVersions.length === 0) { if (!satisfiedVersions || satisfiedVersions.length === 0) {
return null; return null;
@@ -637,6 +637,14 @@ export abstract class JavaBase {
}; };
} }
protected isVersionSatisfied(range: string, version: string): boolean {
return isVersionSatisfies(range, version);
}
protected compareVersions(a: string, b: string): number {
return semver.compareBuild(a, b);
}
protected normalizeVersion(version: string) { protected normalizeVersion(version: string) {
let stable = true; let stable = true;
const latest = false; const latest = false;
+45 -3
View File
@@ -9,7 +9,6 @@ import {
cacheJdkDir, cacheJdkDir,
extractJdkFile, extractJdkFile,
getDownloadArchiveExtension, getDownloadArchiveExtension,
isVersionSatisfies,
renameWinArchive renameWinArchive
} from '../../util.js'; } from '../../util.js';
import * as core from '@actions/core'; import * as core from '@actions/core';
@@ -66,8 +65,8 @@ export class LibericaDistributions extends JavaBase {
})); }));
const satisfiedVersion = availableVersions const satisfiedVersion = availableVersions
.filter(item => isVersionSatisfies(range, item.version)) .filter(item => this.isVersionSatisfied(range, item.version))
.sort((a, b) => -semver.compareBuild(a.version, b.version))[0]; .sort((a, b) => -this.compareVersions(a.version, b.version))[0];
if (!satisfiedVersion) { if (!satisfiedVersion) {
const availableVersionStrings = availableVersions.map( const availableVersionStrings = availableVersions.map(
@@ -79,6 +78,45 @@ export class LibericaDistributions extends JavaBase {
return satisfiedVersion; return satisfiedVersion;
} }
protected normalizeVersion(version: string) {
const normalized = super.normalizeVersion(version);
if (/^\d+\.\d+\.\d+\.\d+(?:-ea)?$/.test(version)) {
// Keep patch-only requests distinct from exact SDKMAN build requests.
normalized.version = version.replace(/-ea$/, '');
}
return normalized;
}
protected isVersionSatisfied(range: string, version: string): boolean {
const patchRequest = range.match(/^(\d+\.\d+\.\d+)\.(\d+)$/);
if (patchRequest) {
const candidate = semver.parse(version);
if (!candidate || !semver.eq(patchRequest[1], candidate)) {
return false;
}
const patch = candidate.build.length > 1 ? candidate.build[0] : '0';
return patch === patchRequest[2];
}
return super.isVersionSatisfied(range, version);
}
protected compareVersions(a: string, b: string): number {
const mainComparison = semver.compare(a, b);
if (mainComparison !== 0) {
return mainComparison;
}
// SDKMAN encodes patch.build, but unpatched releases contain only build.
const patchAndBuild = (version: string): string => {
const build = new semver.SemVer(version).build;
return (build.length > 1 ? build : ['0', ...build]).join('.');
};
return semver.compareBuild(
`0.0.0+${patchAndBuild(a)}`,
`0.0.0+${patchAndBuild(b)}`
);
}
private async getAvailableVersions(): Promise<LibericaVersion[]> { private async getAvailableVersions(): Promise<LibericaVersion[]> {
if (core.isDebug()) { if (core.isDebug()) {
console.time('Retrieving available versions for Liberica took'); // eslint-disable-line no-console console.time('Retrieving available versions for Liberica took'); // eslint-disable-line no-console
@@ -171,6 +209,10 @@ export class LibericaDistributions extends JavaBase {
const mainVersion = [featureVersion, interimVersion, updateVersion].join( const mainVersion = [featureVersion, interimVersion, updateVersion].join(
'.' '.'
); );
const patchVersion = version.version.split('+')[0].split('.')[3];
if (patchVersion) {
return `${mainVersion}+${patchVersion}.${buildVersion}`;
}
if (buildVersion != 0) { if (buildVersion != 0) {
return `${mainVersion}+${buildVersion}`; return `${mainVersion}+${buildVersion}`;
} }