fix: update bundleHash to full SHA-256 for integrity verification and migrate legacy hashes
This commit is contained in:
+36
-29
@@ -77,6 +77,32 @@ function resolveBundlePath(pluginDir: string, entrypoint: string): ResolvedBundl
|
||||
return null;
|
||||
}
|
||||
|
||||
async function bundleEntrypoint(bundlePath: string): Promise<string> {
|
||||
const esbuild = await import('esbuild');
|
||||
const result = await esbuild.build({
|
||||
entryPoints: [bundlePath],
|
||||
bundle: true,
|
||||
// CJS format matches the sandbox runtime's evaluator
|
||||
// (`new Function('module', 'exports', 'require', 'React', ...)`).
|
||||
format: 'cjs',
|
||||
platform: 'neutral',
|
||||
write: false,
|
||||
logLevel: 'silent',
|
||||
sourcemap: 'inline',
|
||||
target: ['es2020'],
|
||||
// The runtime's `require` shim resolves these at evaluation time:
|
||||
// react / react-dom / react-dom/client / react/jsx-runtime → host copies
|
||||
// @plugin-host → the per-plugin `api` object
|
||||
external: [
|
||||
'react', 'react-dom', 'react-dom/client', 'react/jsx-runtime',
|
||||
'@plugin-host',
|
||||
],
|
||||
});
|
||||
const out = result.outputFiles?.[0]?.text;
|
||||
if (!out) throw new Error('esbuild produced no output');
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and bundle a dev plugin's code. For `src/` sources this runs esbuild
|
||||
* on every call so saves are reflected immediately. Errors are surfaced as
|
||||
@@ -88,29 +114,7 @@ export async function readDevBundle(entry: DevPluginEntry): Promise<string> {
|
||||
return readFile(entry.bundlePath, 'utf-8');
|
||||
}
|
||||
try {
|
||||
const esbuild = await import('esbuild');
|
||||
const result = await esbuild.build({
|
||||
entryPoints: [entry.bundlePath],
|
||||
bundle: true,
|
||||
// CJS format matches the sandbox runtime's evaluator
|
||||
// (`new Function('module', 'exports', 'require', 'React', ...)`).
|
||||
format: 'cjs',
|
||||
platform: 'neutral',
|
||||
write: false,
|
||||
logLevel: 'silent',
|
||||
sourcemap: 'inline',
|
||||
target: ['es2020'],
|
||||
// The runtime's `require` shim resolves these at evaluation time:
|
||||
// react / react-dom / react-dom/client / react/jsx-runtime → host copies
|
||||
// @plugin-host → the per-plugin `api` object
|
||||
external: [
|
||||
'react', 'react-dom', 'react-dom/client', 'react/jsx-runtime',
|
||||
'@plugin-host',
|
||||
],
|
||||
});
|
||||
const out = result.outputFiles?.[0]?.text;
|
||||
if (!out) throw new Error('esbuild produced no output');
|
||||
return out;
|
||||
return await bundleEntrypoint(entry.bundlePath);
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
logger.warn(`[plugin-dev] esbuild failed for ${entry.plugin.id}`, { error: message });
|
||||
@@ -149,15 +153,18 @@ async function loadDevPlugin(pluginDir: string): Promise<DevPluginEntry | null>
|
||||
return null;
|
||||
}
|
||||
|
||||
// Hash from the on-disk source so any edit propagates. For src/ sources
|
||||
// we hash the source - close enough for dev-time change detection (we
|
||||
// don't need to re-hash transitive imports).
|
||||
// Hash from the exact bytes the bundle endpoint will serve so the client's
|
||||
// verifyBundle check passes. For src/ sources that means running esbuild
|
||||
// here too — slightly more work per manifest list, but unavoidable since
|
||||
// the source hash wouldn't match the served bundle.
|
||||
let bundleHash: string;
|
||||
try {
|
||||
const code = await readFile(resolved.bundlePath);
|
||||
bundleHash = createHash('sha256').update(code).digest('hex').slice(0, 16);
|
||||
const bytes = resolved.needsBundle
|
||||
? await bundleEntrypoint(resolved.bundlePath)
|
||||
: await readFile(resolved.bundlePath);
|
||||
bundleHash = createHash('sha256').update(bytes).digest('hex');
|
||||
} catch (err) {
|
||||
logger.warn(`[plugin-dev] failed to read ${resolved.bundlePath} for ${id}`, {
|
||||
logger.warn(`[plugin-dev] failed to hash bundle at ${resolved.bundlePath} for ${id}`, {
|
||||
error: err instanceof Error ? err.message : String(err),
|
||||
});
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user