fix(pack): lazy-load sharp and verify unpacked natives
Avoid crashing Electron at startup when sharp is corrupt, and fail pack if asarUnpack natives look truncated. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import test from 'node:test';
|
||||
|
||||
import { verifyUnpackedSharp } from './verify-packaged-sharp.mjs';
|
||||
|
||||
void test('verifyUnpackedSharp: accepts intact layout', () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'dnd-sharp-verify-'));
|
||||
try {
|
||||
const nm = path.join(root, 'resources', 'app.asar.unpacked', 'node_modules');
|
||||
const sharpLib = path.join(nm, 'sharp', 'lib');
|
||||
fs.mkdirSync(sharpLib, { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(sharpLib, 'index.js'),
|
||||
"'use strict';\nmodule.exports = require('./constructor');\n",
|
||||
'utf8',
|
||||
);
|
||||
const imgDir = path.join(nm, '@img', 'sharp-win32-x64');
|
||||
fs.mkdirSync(imgDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(imgDir, 'sharp.node'), Buffer.alloc(60_000, 1));
|
||||
|
||||
verifyUnpackedSharp({
|
||||
label: 'fixture',
|
||||
unpackedRoot: root,
|
||||
imgDirs: ['sharp-win32-x64'],
|
||||
});
|
||||
} finally {
|
||||
fs.rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
void test('verifyUnpackedSharp: rejects truncated sharp index', () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'dnd-sharp-verify-'));
|
||||
try {
|
||||
const nm = path.join(root, 'resources', 'app.asar.unpacked', 'node_modules');
|
||||
const sharpLib = path.join(nm, 'sharp', 'lib');
|
||||
fs.mkdirSync(sharpLib, { recursive: true });
|
||||
fs.writeFileSync(path.join(sharpLib, 'index.js'), 'x', 'utf8');
|
||||
const imgDir = path.join(nm, '@img', 'sharp-win32-x64');
|
||||
fs.mkdirSync(imgDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(imgDir, 'sharp.node'), Buffer.alloc(60_000, 1));
|
||||
|
||||
assert.throws(
|
||||
() =>
|
||||
verifyUnpackedSharp({
|
||||
label: 'fixture',
|
||||
unpackedRoot: root,
|
||||
imgDirs: ['sharp-win32-x64'],
|
||||
}),
|
||||
/truncated|corrupt/i,
|
||||
);
|
||||
} finally {
|
||||
fs.rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
void test('verifyUnpackedSharp: accepts mac .app layout', () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'dnd-sharp-verify-mac-'));
|
||||
try {
|
||||
const nm = path.join(
|
||||
root,
|
||||
'TTRPGPlayer.app',
|
||||
'Contents',
|
||||
'Resources',
|
||||
'app.asar.unpacked',
|
||||
'node_modules',
|
||||
);
|
||||
const sharpLib = path.join(nm, 'sharp', 'lib');
|
||||
fs.mkdirSync(sharpLib, { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(sharpLib, 'index.js'),
|
||||
"'use strict';\nmodule.exports = {};\n",
|
||||
'utf8',
|
||||
);
|
||||
const imgDir = path.join(nm, '@img', 'sharp-darwin-arm64');
|
||||
fs.mkdirSync(imgDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(imgDir, 'sharp.node'), Buffer.alloc(60_000, 1));
|
||||
|
||||
verifyUnpackedSharp({
|
||||
label: 'mac-fixture',
|
||||
unpackedRoot: root,
|
||||
imgDirs: ['sharp-darwin-arm64'],
|
||||
});
|
||||
} finally {
|
||||
fs.rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user