From ddbafbcd43ba3d09d61ba18e0b90d79c3415ff89 Mon Sep 17 00:00:00 2001 From: Furqan-14 Date: Wed, 17 Jun 2026 19:24:45 +0530 Subject: [PATCH] fix(build): build_wasm.ps1 builds the real wasm-pdfium engine + deploys pdfium-engine.{mjs,wasm} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit build_wasm.ps1 built the `wasm` STUB preset (PDFENGINE_WITH_PDFIUM=OFF, reflow #ifdef'd out) and deployed it to the UNUSED pdfengine.{mjs,wasm}. The frontend actually loads pdfium-engine.{mjs,wasm} (the `wasm-pdfium` preset). So "rebuild the WASM" silently shipped a reflow-less stub to the wrong file — engine changes never reached the browser. - Build the `wasm-pdfium` preset (PDFium ON) into pdfeng-build/wasm-pdfium (outside OneDrive). - Deploy bin/pdfengine.{mjs,wasm} -> public/pdfium-engine.{mjs,wasm} (the rename the frontend expects). - Set EMSDK_QUIET before sourcing emsdk_env.ps1 (its stderr tripped $ErrorActionPreference='Stop'). - Run a new pdfium-engine.smoke.mjs (buildInfo + live-preview exports) instead of pdfengine.test.mjs, which targets the stub facade (mock render / engineHasSkia / getDocumentFonts) and can't pass here. - Relax EAP around the smoke node call so a real failure reports cleanly, not as NativeCommandError. - pdfengine.test.mjs: de-brittle the buildInfo assertion (was pinned to a stale exact phrase). Verified: scripts/build_wasm.ps1 runs green end-to-end and deploys pdfium-engine.wasm (md5 53d1ec9f). Co-Authored-By: Claude Opus 4.8 (1M context) --- scripts/build_wasm.ps1 | 50 +++++++++++++++++++++++++----------- wasm/pdfengine.test.mjs | 4 ++- wasm/pdfium-engine.smoke.mjs | 37 ++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 wasm/pdfium-engine.smoke.mjs diff --git a/scripts/build_wasm.ps1 b/scripts/build_wasm.ps1 index 5f59083..dd76c86 100644 --- a/scripts/build_wasm.ps1 +++ b/scripts/build_wasm.ps1 @@ -38,12 +38,21 @@ if (-not (Test-Path $envScript)) { } Write-Host "Loading Emscripten environment variables..." -ForegroundColor Cyan +# emsdk_env.ps1 prints an informational line to stderr; with $ErrorActionPreference='Stop' PowerShell +# treats that as a terminating NativeCommandError and aborts the script. EMSDK_QUIET silences it. +$env:EMSDK_QUIET = "1" . $envScript -# Resolve build directory -$BuildDir = Join-Path $ProjectRoot "out\build\wasm" +# Resolve build directory. +# IMPORTANT: build the `wasm-pdfium` preset (PDFENGINE_WITH_PDFIUM=ON) — this is the LIVE-PREVIEW +# engine the frontend actually loads (deployed as pdfium-engine.{mjs,wasm}). The `wasm` preset is a +# PDFium-OFF stub: the reflow code lives inside #ifdef PDFENGINE_WITH_PDFIUM, so the stub contains NO +# reflow at all. Building the stub here silently ships a reflow-less engine (and to the wrong file), +# which makes engine changes appear to "not take" in the browser. +$BuildDir = Join-Path $ProjectRoot "out\build\wasm-pdfium" if ($IsWindows -or $env:OS -eq "Windows_NT") { - $BuildDir = "C:\Users\$env:USERNAME\pdfeng-build\wasm" + # Keep the build dir OUTSIDE OneDrive / paths with spaces (Emscripten/Ninja break otherwise). + $BuildDir = "C:\Users\$env:USERNAME\pdfeng-build\wasm-pdfium" if (-not (Test-Path $BuildDir)) { New-Item -ItemType Directory -Path $BuildDir -Force | Out-Null } @@ -51,8 +60,8 @@ if ($IsWindows -or $env:OS -eq "Windows_NT") { $WasmBinDir = Join-Path $BuildDir "bin" # Configure WASM preset -Write-Host "Configuring CMake WASM preset in $BuildDir..." -ForegroundColor Cyan -cmake --preset wasm -B $BuildDir +Write-Host "Configuring CMake wasm-pdfium preset in $BuildDir..." -ForegroundColor Cyan +cmake --preset wasm-pdfium -B $BuildDir if ($LASTEXITCODE -ne 0) { Write-Error "CMake configuration failed." exit $LASTEXITCODE @@ -66,13 +75,21 @@ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } -# Run WASM smoke tests +# Run WASM smoke tests. Node prints its diagnostics to stderr; under $ErrorActionPreference='Stop' +# PowerShell would turn that into a terminating NativeCommandError (a cryptic abort) even though we +# want to inspect the real exit code. Relax EAP just around the call and branch on $LASTEXITCODE. Write-Host "Running WASM smoke tests..." -ForegroundColor Cyan $env:PDFENGINE_MJS = Join-Path $WasmBinDir "pdfengine.mjs" -node wasm/pdfengine.test.mjs -if ($LASTEXITCODE -ne 0) { - Write-Error "WASM smoke tests failed." - exit $LASTEXITCODE +$prevEAP = $ErrorActionPreference +$ErrorActionPreference = 'Continue' +# Validate the REAL pdfium engine (buildInfo + live-preview exports). pdfengine.test.mjs targets the +# PDFium-OFF stub facade (mock render, engineHasSkia, getDocumentFonts) and does NOT apply here. +node wasm/pdfium-engine.smoke.mjs +$smokeExit = $LASTEXITCODE +$ErrorActionPreference = $prevEAP +if ($smokeExit -ne 0) { + Write-Error "WASM smoke tests failed (exit $smokeExit)." + exit $smokeExit } # Copy built targets to frontend public folder @@ -81,10 +98,13 @@ $FrontendPublic = Join-Path $ProjectRoot "frontend\public" if (-not (Test-Path $FrontendPublic)) { Write-Warning "Frontend public folder not found at $FrontendPublic. Skipping copy." } else { - Write-Host "Copying WASM build artifacts to frontend public folder..." -ForegroundColor Cyan - Copy-Item -Path (Join-Path $WasmBinDir "pdfengine.mjs") -Destination (Join-Path $FrontendPublic "pdfengine.mjs") -Force - Copy-Item -Path (Join-Path $WasmBinDir "pdfengine.wasm") -Destination (Join-Path $FrontendPublic "pdfengine.wasm") -Force - Write-Host "Successfully copied WASM files to $FrontendPublic" -ForegroundColor Green + # The cmake target's OUTPUT_NAME is "pdfengine"; the frontend loads it as "pdfium-engine". + # Deploy with that rename so the live preview picks up this build. + Write-Host "Deploying WASM engine -> pdfium-engine.{mjs,wasm} in frontend public..." -ForegroundColor Cyan + Copy-Item -Path (Join-Path $WasmBinDir "pdfengine.mjs") -Destination (Join-Path $FrontendPublic "pdfium-engine.mjs") -Force + Copy-Item -Path (Join-Path $WasmBinDir "pdfengine.wasm") -Destination (Join-Path $FrontendPublic "pdfium-engine.wasm") -Force + Write-Host "Successfully deployed pdfium-engine.{mjs,wasm} to $FrontendPublic" -ForegroundColor Green + Write-Host "NOTE: bump the cache-buster V in frontend/src/lib/pdfiumEngine.ts so browsers refetch." -ForegroundColor Yellow } -Write-Host "Success! WASM built and deployed." -ForegroundColor Green \ No newline at end of file +Write-Host "Success! WASM (wasm-pdfium) built and deployed as pdfium-engine.{mjs,wasm}." -ForegroundColor Green \ No newline at end of file diff --git a/wasm/pdfengine.test.mjs b/wasm/pdfengine.test.mjs index 2b5e58e..cd4a0b1 100644 --- a/wasm/pdfengine.test.mjs +++ b/wasm/pdfengine.test.mjs @@ -23,7 +23,9 @@ const Module = await createModule(); // 1. Test build info const buildInfo = Module.ccall("engineBuildInfo", "string", [], []); console.log(`[pdfengine-smoke] buildInfo: "${buildInfo}"`); -assert.equal(buildInfo, "PdfEngine WASM Facade (Phase 1/2 Enabled)"); +// Non-brittle: the build-info string evolves (e.g. "pdfengine-wasm+pdfium"); just assert the engine +// reports a non-empty identifier rather than pinning an exact (quickly-stale) phrase. +assert.ok(buildInfo && buildInfo.toLowerCase().includes("pdfengine"), `unexpected buildInfo: ${buildInfo}`); // 2. Test hasSkia const hasSkia = Module.ccall("engineHasSkia", "number", [], []); diff --git a/wasm/pdfium-engine.smoke.mjs b/wasm/pdfium-engine.smoke.mjs new file mode 100644 index 0000000..460271d --- /dev/null +++ b/wasm/pdfium-engine.smoke.mjs @@ -0,0 +1,37 @@ +// Smoke test for the LIVE-PREVIEW engine (wasm-pdfium preset, deployed as pdfium-engine.{mjs,wasm}). +// Unlike pdfengine.test.mjs (which targets the PDFium-OFF stub facade), this validates the real +// engine the frontend loads: it instantiates, reports a pdfium build, and exports the functions the +// live preview calls. Pass PDFENGINE_MJS=. +import { existsSync } from "node:fs"; +import { pathToFileURL } from "node:url"; + +const enginePath = process.env.PDFENGINE_MJS; +if (!enginePath || !existsSync(enginePath)) { + console.error(`[pdfium-smoke] engine .mjs not found at: ${enginePath}`); + process.exit(1); +} + +const { default: createModule } = await import(pathToFileURL(enginePath).href); +const Module = await createModule(); + +// 1. Build info — must report a real pdfium engine (not the stub facade). +const buildInfo = Module.ccall("engineBuildInfo", "string", [], []); +console.log(`[pdfium-smoke] buildInfo: "${buildInfo}"`); +if (!buildInfo || !buildInfo.toLowerCase().includes("pdfium")) { + console.error(`[pdfium-smoke] FAIL: buildInfo does not look like the pdfium engine: "${buildInfo}"`); + process.exit(1); +} + +// 2. The exports the live preview depends on must be present (catches a stub/mis-built artifact). +const required = [ + "_loadDocument", "_previewRender", "_previewRenderRegion", + "_lastRenderPtr", "_lastRenderW", "_lastRenderH", "_lastLayoutJson", + "_freeDocument", "_malloc", "_free", +]; +const missing = required.filter((f) => typeof Module[f] !== "function"); +if (missing.length) { + console.error(`[pdfium-smoke] FAIL: missing exports: ${missing.join(", ")}`); + process.exit(1); +} + +console.log("[pdfium-smoke] OK — pdfium engine instantiated with all live-preview exports.");