diff --git a/package-lock.json b/package-lock.json index 5c6f869..9b9783a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3289,9 +3289,9 @@ } }, "node_modules/@react-native/codegen/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -4338,9 +4338,9 @@ } }, "node_modules/brace-expansion": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", - "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -6404,9 +6404,9 @@ } }, "node_modules/expo/node_modules/brace-expansion": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", - "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -10557,9 +10557,9 @@ } }, "node_modules/react-native/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -10977,9 +10977,9 @@ } }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -11703,9 +11703,9 @@ } }, "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -11931,9 +11931,9 @@ } }, "node_modules/undici": { - "version": "6.28.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", - "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==", + "version": "6.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.29.0.tgz", + "integrity": "sha512-R+RODBqp6i2pPflGdq+xIOUkl+RNfGgHwoinecKu/JCuf2uO06cOKoDbI2P7Dn6KcswdKwrczbU6IYJ6K8X+wg==", "license": "MIT", "engines": { "node": ">=18.17" diff --git a/package.json b/package.json index 0248fe1..bece00d 100644 --- a/package.json +++ b/package.json @@ -73,14 +73,14 @@ "postcss": "^8.5.18", "js-yaml@^3.0.0": "^3.15.2", "js-yaml@^4.0.0": "^4.3.2", - "brace-expansion@^1.0.0": "^1.1.18", - "brace-expansion@^2.0.0": "^2.1.4", - "brace-expansion@^5.0.0": "^5.0.9", + "brace-expansion@^1.0.0": "^1.1.21", + "brace-expansion@^2.0.0": "^2.1.7", + "brace-expansion@^5.0.0": "^5.0.12", "@babel/core": "^7.29.6", "browserslist": "^4.28.7", "@expo/cli": { "ws": "^8.20.1", - "undici": "^6.28.0", + "undici": "^6.28.1", "tar": "^7.5.21" }, "react-devtools-core": { diff --git a/tests/smoke.test.cjs b/tests/smoke.test.cjs index 483e328..602ac52 100644 --- a/tests/smoke.test.cjs +++ b/tests/smoke.test.cjs @@ -264,6 +264,65 @@ check('@react-navigation/core deep link round trip keeps query params', () => { assert.equal(getPathFromState(state, config), '/task/abc?x=1&y=a%20b'); }); +// --- Override floors for build-tool transitive deps (#124, #125) --- +// brace-expansion is overridden per major (version-scoped): a blanket override +// forces one major onto every minimatch and breaks minimatch@3 (#103). The +// floors below are the patched head of each major; any other major is either +// vulnerable (4.x) or unexpected, and must fail loudly. + +function versionAtLeast(version, floor) { + const a = version.split('.').map(Number); + const b = floor.split('.').map(Number); + for (let i = 0; i < 3; i++) { + if (a[i] !== b[i]) return a[i] > b[i]; + } + return true; +} + +const BRACE_EXPANSION_FLOORS = { 1: '1.1.21', 2: '2.1.7', 5: '5.0.12' }; + +check('every installed brace-expansion copy is at or above its major floor', () => { + const copies = installedCopies('brace-expansion'); + assert.ok(copies.length > 0, 'brace-expansion is not installed'); + const strays = copies.filter((c) => { + const floor = BRACE_EXPANSION_FLOORS[majorOf(c.version)]; + return !floor || !versionAtLeast(c.version, floor); + }); + assert.deepEqual( + strays.map((c) => `${c.version} at ${path.relative(ROOT, c.dir)}`), + [], + `expected floors ${JSON.stringify(BRACE_EXPANSION_FLOORS)}` + ); +}); + +check('every installed undici copy is >= 6.28.1', () => { + const copies = installedCopies('undici'); + assert.ok(copies.length > 0, 'undici is not installed'); + const strays = copies.filter((c) => !versionAtLeast(c.version, '6.28.1')); + assert.deepEqual( + strays.map((c) => `${c.version} at ${path.relative(ROOT, c.dir)}`), + [], + 'undici must be >= 6.28.1' + ); +}); + +// The call that broke under the blanket override: each minimatch copy must +// still expand braces through its own brace-expansion major. +check('every installed minimatch copy still matches globs and braces', () => { + const copies = installedCopies('minimatch'); + const majors = [...new Set(copies.map((c) => majorOf(c.version)))].sort(); + assert.deepEqual(majors, ['10', '3', '9'], 'expected minimatch majors 3, 9 and 10'); + for (const c of copies) { + const mod = require(c.dir); + const minimatch = mod.minimatch || mod; // v3 exports the function itself + const where = `minimatch ${c.version} at ${path.relative(ROOT, c.dir)}`; + assert.equal(minimatch('foo/bar.js', '**/*.js'), true, `${where}: globstar`); + assert.equal(minimatch('a/b.js', 'a/{b,c}.js'), true, `${where}: brace match`); + assert.equal(minimatch('a/d.js', 'a/{b,c}.js'), false, `${where}: brace miss`); + assert.equal(minimatch('f3.js', 'f{1..3}.js'), true, `${where}: numeric range`); + } +}); + if (failed === 0) { console.log('\nsmoke OK'); process.exit(0);