fix(compiler): strip TypeScript from client function bodies
Quality / quality (ubuntu-latest) (push) Failing after 9m53s
Quality / quality (windows-latest) (push) Canceled after 0s

`wrnexus build` failed on any client function whose body used TypeScript:

    const requestBody: Record<string, unknown> = {}
    error: Expected ";" but found ":"

Codegen copies a client function's body into the browser module verbatim.
It removes the types from the function's *signature*, which is what made
this easy to miss -- the emitted module looked transpiled, and only bodies
carried types through. The artifact is written as .mjs and read back as
plain JavaScript, so the failure surfaced as a syntax error in generated
code rather than at the .wrn line responsible.

Browser modules are now transpiled before they are written, at all three
sites that emit one (the production build and both dev-server paths).

Reproduced end to end: a page with an annotated body failed the build with
the reported errors, and after the fix builds, ships valid minified JS, and
runs -- the handler sets its state correctly in a browser.

Note: the same body is also embedded as a string for the CSP-safe fallback
interpreter, which still receives it untranspiled. The compiled module
shadows the fallback, so this is only reachable in the window before that
module loads. Left alone here because stripping it lives in codegen, which
also runs under Node in the editor bundle where the Bun transpiler is
unavailable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-19 14:03:14 +05:30
co-authored by Claude Opus 5
parent 8c609edd32
commit 55fed2177a
9 changed files with 170 additions and 7 deletions
+32 -2
View File
@@ -1,6 +1,6 @@
"use strict";
// Generated by scripts/build-editor-compiler.mjs. Do not edit directly.
// WRN editor compiler source hash: 27f13fbc79aedf4736913f268ab4af1f03a236ea44960cffb7caff225d157faf
// WRN editor compiler source hash: f474a2710a8861a4e863af13954e202e41a94b160c43c20297a7dfdd94b9ea8b
// WRN editor compiler generator hash: a54ca847c758bc98d8e353ad6d70088df31de1820f6cf9d1c3462505f563e6b8
// Generated with TypeScript: 6.0.3
const __nodeRequire = require;
@@ -285,6 +285,34 @@ function analyzeRuntimeRequirements(ast, options = {}) {
};
}
},
"packages/compiler/src/browser-transpile.ts": function (module, exports, require, __filename, __dirname) {
"use strict";
/**
* Strip TypeScript from a generated browser module.
*
* A client function's body is emitted verbatim, so anything TypeScript-only
* inside one -- an annotated local, an `as` cast, a local interface -- reaches
* the browser module as TypeScript source. Codegen removes the types from the
* function's *signature*, which is what made this easy to miss: the emitted
* module looked transpiled, and only bodies carried types through.
*
* The artifact is written as `.mjs` and read back as plain JavaScript, so the
* failure surfaced as a syntax error pointing at generated code rather than at
* the `.wrn` line responsible.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.stripBrowserTypes = stripBrowserTypes;
let transpiler = null;
function stripBrowserTypes(code) {
const bun = globalThis.Bun;
if (!bun?.Transpiler) {
throw new Error("WRN-CLIENT-TS: emitting a browser module needs the Bun transpiler to remove TypeScript from client function bodies.");
}
transpiler ??= new bun.Transpiler({ loader: "ts", target: "browser" });
return transpiler.transformSync(code);
}
},
"packages/compiler/src/cache.ts": function (module, exports, require, __filename, __dirname) {
"use strict";
@@ -3339,7 +3367,7 @@ function resolveWrnImports(declarations, importer, options) {
* `@wrnexus/syntax` package. This package owns platform-specific codegen.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.routeNeedsIslands = exports.generateIslandEntry = exports.buildIslands = exports.assertReactAvailable = exports.serializeIslandProps = exports.renderIslandMarker = exports.parseIslandStrategy = exports.islandPropValue = exports.islandNamesFrom = exports.DependencyGraph = exports.createCompilationCache = exports.compilationKey = exports.runtimeTypeOf = exports.inferredRuntimeType = exports.eraseFunctionTypes = exports.LexError = exports.Lexer = exports.NativeCompileError = exports.generateNative = exports.runtimeCapabilities = exports.analyzeRuntimeImports = exports.optimizeAst = exports.analyzeRuntimeRequirements = exports.analyzeOptimizations = exports.createWrnSourceMap = exports.resolveWrnImports = exports.resolveWrnImport = exports.createComponentContract = exports.generateStoreModule = exports.generateStoreBrowserModule = exports.generateDeclarations = exports.rpcManifest = exports.generateServerFunctionsModule = exports.generateBrowserModule = exports.generateTargets = exports.generate = exports.ParseError = exports.parse = exports.formatDiagnostic = exports.diagnosticFromError = exports.diagnose = exports.assertValidAst = exports.formatWrn = void 0;
exports.routeNeedsIslands = exports.generateIslandEntry = exports.buildIslands = exports.assertReactAvailable = exports.serializeIslandProps = exports.renderIslandMarker = exports.parseIslandStrategy = exports.islandPropValue = exports.islandNamesFrom = exports.DependencyGraph = exports.createCompilationCache = exports.compilationKey = exports.runtimeTypeOf = exports.inferredRuntimeType = exports.eraseFunctionTypes = exports.LexError = exports.Lexer = exports.NativeCompileError = exports.generateNative = exports.runtimeCapabilities = exports.analyzeRuntimeImports = exports.optimizeAst = exports.analyzeRuntimeRequirements = exports.analyzeOptimizations = exports.createWrnSourceMap = exports.resolveWrnImports = exports.resolveWrnImport = exports.createComponentContract = exports.generateStoreModule = exports.generateStoreBrowserModule = exports.generateDeclarations = exports.rpcManifest = exports.generateServerFunctionsModule = exports.stripBrowserTypes = exports.generateBrowserModule = exports.generateTargets = exports.generate = exports.ParseError = exports.parse = exports.formatDiagnostic = exports.diagnosticFromError = exports.diagnose = exports.assertValidAst = exports.formatWrn = void 0;
exports.compileNativeWrnFile = compileNativeWrnFile;
exports.compileWrnFile = compileWrnFile;
exports.compile = compile;
@@ -3361,6 +3389,8 @@ var targets_ts_1 = require("./targets.js");
Object.defineProperty(exports, "generateTargets", { enumerable: true, get: function () { return targets_ts_1.generateTargets; } });
var client_codegen_ts_1 = require("./client-codegen.js");
Object.defineProperty(exports, "generateBrowserModule", { enumerable: true, get: function () { return client_codegen_ts_1.generateBrowserModule; } });
var browser_transpile_ts_1 = require("./browser-transpile.js");
Object.defineProperty(exports, "stripBrowserTypes", { enumerable: true, get: function () { return browser_transpile_ts_1.stripBrowserTypes; } });
var server_codegen_ts_1 = require("./server-codegen.js");
Object.defineProperty(exports, "generateServerFunctionsModule", { enumerable: true, get: function () { return server_codegen_ts_1.generateServerFunctionsModule; } });
Object.defineProperty(exports, "rpcManifest", { enumerable: true, get: function () { return server_codegen_ts_1.rpcManifest; } });
+1 -1
View File
@@ -1,4 +1,4 @@
// WRN editor extension source hash: 63bce75e2686c7586a3a08b8811ebc681d2265fdfe54e984630614e3dcef21f5
// WRN editor extension source hash: 0a678785f34a594b64f06ca6e39cf7bea49127ddf344d585e52cc1b3eda9a82a
// WRN editor extension generator hash: 456d1d614e44e5fb1f19b784176c09cf2ade9b64ef73a17934c2698150b62728
"use strict";
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env node
// WRN editor language server source hash: 8555261bb7933ee73d08cee279600fa64d2f35b35c5144ceba516e6929593d37
// WRN editor language server source hash: afce4195f664e656dc8f38283bda8118637d977cd2eee8ba08c80906681510cd
// WRN editor language server generator hash: f593a44aaf05495b789ce7a3086bee1eebb951b884d41c0e017bbcfe5f547e72
// @bun @bun-cjs
(function(exports, require, module, __filename, __dirname) {var __create = Object.create;