Repository navigation
TS SDK - Fall back to closures when Function is forbidden - #6368
Open
JulienLavocat wants to merge 1 commit into
Open
JulienLavocat wants to merge 1 commit into
JulienLavocat wants to merge 1 commit into
Conversation
The TypeScript SDK builds its serializers and deserializers with
`Function`, which a Content-Security-Policy without 'unsafe-eval' and
Cloudflare Workers forbid, so the first row decode threw an EvalError.
- Probe once whether `Function` is allowed. If not, build the
serializers and deserializers from closures that write the same bytes.
- Load `undici` with a variable dynamic import instead of
`new Function('m', 'return import(m)')`.
Fixes #4966.
This branch has not been deployed
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.
Description of Changes
Fixes #4966 (and #4669, which was closed without a fix).
The TypeScript SDK builds its serializers and deserializers at runtime with
Function(...), in six places inalgebraic_type.ts. A Content-Security-Policy without'unsafe-eval'forbids that, and so do Cloudflare Workers, so the first row decode threwEvalErrorand the SDK could not be used there.src/lib/runtime_codegen.tsprobes once whetherFunctionis allowed and caches the answer, so a page under a CSP sees at most one violation report. It is internal and not re-exported.Functionis allowed, nothing changes: servers and normal browsers keep the generated fast path.ProductTypeandSumTypebuild their serializers and deserializers from closures that write the same bytes and return the same values. Like the fast path, each one is cached before its fields or variants are built, so recursive types terminate. An unknown sum tag on decode still yieldsundefined, as the generatedswitchdoes.ws.tsloadsundiciwithimport(undici)and thewebpackIgnore/@vite-ignorecomments instead ofnew Function('m', 'return import(m)').This doesn't generate serializers when the bindings are generated, as the issue suggests (and as #5003 tried). Types built at runtime, such as reducer arguments, would need this fallback anyway, and generating them in the bindings could follow as a performance change.
API and ABI breaking changes
None. The wire format is unchanged and no public API is added.
Rollback safety impact
n/a
Expected complexity level and risk
Functionis forbidden, which fails today. The risk is a mismatch between the two paths, which the new test checks byte for byte.Terser folds the
undicispecifier back into a literalimport("undici")indist/min/*. Those files are not in the packageexportsand are only used for the size limits; the bundles consumers import keep the variable and the ignore comments.Testing
tests/serde_without_function.test.tsforbidsFunctionthe way a CSP does and checks that both paths write identical bytes and round-trip a fixed-size product, a nested product with strings, arrays and an option, a sum, and recursive products and sums. Removing one fallback branch makes it fail.pnpm vitest run: everything passes exceptserver_test_utils_wasm,server_test_utils_wasm_adapterandconsumer_types, which fail the same way on master (missing WASM test artifacts and an unrelated case-conversion client).tsc -p tsconfig.build.json, eslint and prettier are clean, andtsupbuilds.dist/index.mjs,dist/index.browser.mjsanddist/min/index.browser.mjsundernode --disallow-code-generation-from-stringsand round-tripped a product, a sum and a fixed-size product. A master build throwsEvalError: Code generation from strings disallowed for this context.--disallow-code-generation-from-stringsitself (its worker pool usesnew Function), so the unit test uses the internal switch. Check you're happy with that.🤖 Generated with Claude Code