-
Notifications
You must be signed in to change notification settings - Fork 147
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: update sharp special case for pnpm (#387)
This ensures we trace child optional dependencies as well so that the symlink hierarchy is maintained for pnpm. x-ref: vercel/next.js#59346 x-ref: lovell/sharp#3967 --------- Co-authored-by: Steven <[email protected]>
- Loading branch information
Showing
4 changed files
with
105 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,68 +3,106 @@ const path = require('path'); | |
const { nodeFileTrace } = require('../out/node-file-trace'); | ||
const os = require('os'); | ||
const rimraf = require('rimraf'); | ||
const { readFile, writeFile, readlink, symlink } = promises; | ||
const { fork } = require('child_process'); | ||
const { readFile, writeFile, readlink, symlink, copyFile } = promises; | ||
const { fork, exec: execOrig } = require('child_process'); | ||
|
||
const exec = require('util').promisify(execOrig); | ||
|
||
jest.setTimeout(200_000); | ||
|
||
const integrationDir = `${__dirname}${path.sep}integration`; | ||
|
||
for (const integrationTest of readdirSync(integrationDir)) { | ||
let currentIntegrationDir = integrationDir; | ||
|
||
it(`should correctly trace and correctly execute ${integrationTest}`, async () => { | ||
console.log('Tracing and executing ' + integrationTest); | ||
const nftCache = {} | ||
const nftCache = {}; | ||
const rand = Math.random().toString().slice(2); | ||
const fails = integrationTest.endsWith('failure.js'); | ||
const { fileList, reasons, warnings } = await nodeFileTrace([`${integrationDir}/${integrationTest}`], { | ||
log: true, | ||
cache: nftCache, | ||
base: path.resolve(__dirname, '..'), | ||
processCwd: integrationDir, | ||
// ignore other integration tests | ||
ignore: ['test/integration/**'] | ||
}); | ||
let traceBase = path.resolve(__dirname, '..'); | ||
|
||
if (integrationTest === 'sharp-pnpm.js') { | ||
if (process.version.startsWith('v18.') && process.platform === 'win32') { | ||
console.log( | ||
'Skipping sharp-pnpm.js on Node 18 and Windows because of a bug: ' + | ||
'https://github.com/nodejs/node/issues/18518' | ||
); | ||
return; | ||
} | ||
const tmpdir = path.resolve(os.tmpdir(), `node-file-trace-${integrationTest}-${rand}`); | ||
rimraf.sync(tmpdir); | ||
mkdirSync(tmpdir); | ||
await copyFile( | ||
path.join(integrationDir, integrationTest), | ||
path.join(tmpdir, integrationTest) | ||
); | ||
await writeFile( | ||
path.join(tmpdir, 'package.json'), | ||
JSON.stringify({ packageManager: '[email protected]', dependencies: { sharp: '0.33.2' } }) | ||
); | ||
await exec(`corepack enable && pnpm i`, { cwd: tmpdir, stdio: 'inherit' }); | ||
currentIntegrationDir = tmpdir; | ||
traceBase = tmpdir; | ||
} | ||
|
||
const { fileList, reasons, warnings } = await nodeFileTrace( | ||
[`${currentIntegrationDir}/${integrationTest}`], | ||
{ | ||
log: true, | ||
cache: nftCache, | ||
base: traceBase, | ||
processCwd: currentIntegrationDir, | ||
// ignore other integration tests | ||
ignore: ['test/integration/**'], | ||
} | ||
); | ||
// warnings.forEach(warning => console.warn(warning)); | ||
const randomTmpId = Math.random().toString().slice(2) | ||
const tmpdir = path.resolve(os.tmpdir(), `node-file-trace-${randomTmpId}`); | ||
const tmpdir = path.resolve(os.tmpdir(), `node-file-trace-${rand}`); | ||
rimraf.sync(tmpdir); | ||
mkdirSync(tmpdir); | ||
await Promise.all([...fileList].map(async file => { | ||
const inPath = path.resolve(__dirname, '..', file); | ||
const outPath = path.resolve(tmpdir, file); | ||
try { | ||
var symlinkPath = await readlink(inPath); | ||
} | ||
catch (e) { | ||
if (e.code !== 'EINVAL' && e.code !== 'UNKNOWN') throw e; | ||
} | ||
mkdirSync(path.dirname(outPath), { recursive: true }); | ||
if (symlinkPath) { | ||
await symlink(symlinkPath, outPath); | ||
} | ||
else { | ||
await writeFile(outPath, await readFile(inPath), { mode: 0o777 }); | ||
} | ||
})); | ||
const testFile = path.join(tmpdir, 'test', 'integration', integrationTest); | ||
|
||
await Promise.all( | ||
[...fileList].map(async (file) => { | ||
const inPath = path.resolve(traceBase, file); | ||
const outPath = path.resolve(tmpdir, file); | ||
try { | ||
var symlinkPath = await readlink(inPath); | ||
} catch (e) { | ||
if (e.code !== 'EINVAL' && e.code !== 'UNKNOWN') throw e; | ||
} | ||
mkdirSync(path.dirname(outPath), { recursive: true }); | ||
if (symlinkPath) { | ||
await symlink(symlinkPath, outPath); | ||
} else { | ||
await writeFile(outPath, await readFile(inPath), { mode: 0o777 }); | ||
} | ||
}) | ||
); | ||
const testFile = path.join(tmpdir, path.relative(traceBase, currentIntegrationDir), integrationTest); | ||
|
||
const ps = fork(testFile, { | ||
stdio: fails ? 'pipe' : 'inherit' | ||
stdio: fails ? 'pipe' : 'inherit', | ||
}); | ||
const code = await new Promise(resolve => ps.on('close', resolve)); | ||
const code = await new Promise((resolve) => ps.on('close', resolve)); | ||
expect(code).toBe(fails ? 1 : 0); | ||
rimraf.sync(tmpdir); | ||
|
||
// TODO: ensure analysis cache is safe for below case | ||
// seems this fails with cache since < 0.14.0 | ||
if (integrationTest !== 'browserify-middleware.js') { | ||
const cachedResult = await nodeFileTrace([`${integrationDir}/${integrationTest}`], { | ||
log: true, | ||
cache: nftCache, | ||
base: path.resolve(__dirname, '..'), | ||
processCwd: integrationDir, | ||
// ignore other integration tests | ||
ignore: ['test/integration/**'] | ||
}); | ||
expect([...cachedResult.fileList].sort()).toEqual([...fileList].sort()) | ||
const cachedResult = await nodeFileTrace( | ||
[`${currentIntegrationDir}/${integrationTest}`], | ||
{ | ||
log: true, | ||
cache: nftCache, | ||
base: traceBase, | ||
processCwd: currentIntegrationDir, | ||
// ignore other integration tests | ||
ignore: ['test/integration/**'], | ||
} | ||
); | ||
expect([...cachedResult.fileList].sort()).toEqual([...fileList].sort()); | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const sharp = require('sharp'); | ||
|
||
const roundedCorners = Buffer.from( | ||
'<svg><rect x="0" y="0" width="200" height="200" rx="50" ry="50"/></svg>' | ||
); | ||
|
||
sharp(roundedCorners) | ||
.resize(200, 200) | ||
.png().toBuffer(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters