Build with -sDYNAMIC_EXECUTION=0 so the solver initialises under a strict CSP - #12
Open
MakerViking wants to merge 1 commit into
Open
Build with -sDYNAMIC_EXECUTION=0 so the solver initialises under a strict CSP#12MakerViking wants to merge 1 commit into
MakerViking wants to merge 1 commit into
Conversation
…ct CSP embind builds each invoker by passing a source string to the Function constructor (craftInvokerFunction, reached through new_), and that requires 'unsafe-eval'. Granting 'wasm-unsafe-eval' is not enough, because the failure is not WebAssembly compilation: the wasm compiles fine and initialisation then dies constructing the bindings. -s DYNAMIC_EXECUTION=0 makes emscripten stop emitting eval() and new Function(). embind falls back to a non-codegen path, which emscripten documents and gates in src/lib/libembind.js. The wasm is byte-identical with and without the flag, so this changes the JS glue only and carries no solver risk. All 59 tests pass on both builds.
cyberman
pushed a commit
to Be-Quiet-Home/SindriCAD
that referenced
this pull request
Aug 13, 2026
planegcs is an emscripten/embind module, and embind builds each invoker by handing a source string to the Function constructor. script-src carried 'wasm-unsafe-eval', which permits WebAssembly compilation but not the Function constructor, so the wasm compiled fine and initialisation then died constructing the bindings. Every packaged build since the solver shipped has had no working constraints, dimensions or sketch point dragging. It never reproduced locally because tauri dev serves from vite, which sends no CSP. Reported four times, eec3752a (0.1.73), ffff5144 (0.1.109), 9042ea56 (0.1.117) and cdf4c0f7 (0.1.123), plus once on Linux. The message sent all of them to update a webview runtime that was never the problem and one reinstalled WebView2 for nothing, so it now blames the build instead. 'unsafe-eval' is a real loosening. The only eval sink in the app is this vendored glue: src/params/parse.ts and eval.ts are a hand-written parser and must stay that way while the token is in the policy. Upstream fix proposed as Salusoft89/planegcs#12, which removes the need for it.
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
planegcs cannot initialise in any page whose Content Security Policy does not grant
'unsafe-eval'.'wasm-unsafe-eval'is not sufficient, because the failure is not WebAssembly compilation.The glue contains embind's
new_helper, closure-compiled so its constructor is the globalFunction:a.apply(c, b)wherea === Functionis a Function-constructor call, reached fromcraftInvokerFunction, which assembles each invoker from a source string.'wasm-unsafe-eval'permits wasm compilation only; the Function constructor needs'unsafe-eval'.Serving a page that imports the module under
script-src 'self' 'wasm-unsafe-eval'gives:The wasm itself compiles fine. This is not engine specific: I reproduced it on Chromium 151 and had a field report of the same failure on WebKitGTK.
Affects 1.1.7 and 1.2.0, whose
planegcs.jsare byte-identical.The change
One flag, added to
LINK_FLAGSinplanegcs/CMakeLists.txt:Emscripten stops emitting
eval()andnew Function(), and embind falls back to a non-codegen path. That fallback is a supported, gated path rather than an accident:src/lib/libembind.jscarries all three branches (DYNAMIC_EXECUTION && !EMBIND_AOT,EMBIND_AOT, andDYNAMIC_EXECUTION == 0 && !EMBIND_AOT).Verification
Built both ways in the repo's own Docker image (
emscripten/emsdk:3.1.45), afternpm run build:bindings.planegcs.js(28493 bytes), so the only variable is the flag.planegcs.wasmis byte-identical between the two builds (508141 bytes). This is a JS glue change only and carries no solver risk.npm testpasses identically on both: 8 files, 59 tests.script-src 'self' 'wasm-unsafe-eval': baseline throwsEvalError, the patched build initialises.Cost
The fallback is documented as slower, so I measured it rather than guessing. Same wasm on both sides, so this is purely invoker overhead. Node 22, best of 5 runs of 200 solves, a chain of horizontally-constrained lines:
DYNAMIC_EXECUTION=0An isolated microbenchmark of the boundary alone (200k
push_p_param+get_p_paramcalls) is 6.7 ms vs 41.5 ms, so the invoker layer really is about 6x. Real solves are dominated by solver math inside the wasm, which dilutes it to a steady ~1.5x. In absolute terms a 100-line solve goes from 0.11 ms to 0.17 ms, about 1% of a 60fps frame.If that cost is unwelcome,
-s EMBIND_AOT=1generates the invokers at compile time and removes it.EMBIND_AOTdoes not exist in emscripten 3.1.45, which the Dockerfile pins. I checkedsrc/settings.jsacross tags and it first appears in 3.1.51, so pairing the two depends on #8.DYNAMIC_EXECUTION=0alone works on the current pin, which is why this PR is just the one flag.Why it matters
I ship planegcs in a desktop CAD app. This silently disabled all sketch constraints, dimensions and point dragging for every user on every platform, and it was hard to find because a CSP only applies to packaged builds, never to a dev server. Users were told to update their browser runtime, which was never the problem.
Happy to add the
EMBIND_AOTflag to this PR instead if you would rather bump emscripten first.