Files
DndGamePlayer/scripts/verify-packaged-sharp.test.mjs
Ivan Fontosh 8d5a68c71e 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>
2026-08-07 07:47:36 +08:00

90 lines
2.8 KiB
JavaScript

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 });
}
});