The island pieces existed but nothing connected .wrn compilation to island
emission. Now:
- codegen emits a data-wrn-island placeholder for component tags bound to
.tsx imports, keeping .wrn components on the normal mount path
- the dev pipeline and static build resolve island imports, thread the
names into codegen, and build the bundles
- collectScripts adds /__wrnexus/islands.js only when island markup is
present, so island-free pages still ship nothing
- island routes classify as static-interactive via hasIslands
Three bugs found by driving a real page in the browser:
1. The mount runtime was never built anywhere, so the bootstrap 404'd and
no island mounted.
2. Building the runtime separately from the islands gave each its own copy
of React: "Cannot read properties of null (reading 'useState')". The
runtime is now an entrypoint of the same build so React stays in one
shared chunk. The existing single-React test only compared bundles
within one build and could not see across build boundaries.
3. Island props arrived as attribute strings, so start={3} was "3" and
incrementing produced "31" then "311". Props now follow JSX semantics:
{…} parses as JSON, quoted values stay strings, and a runtime
expression is a WRN-ISLAND-PROPS build error rather than a silent
wrong value.
island-codegen.ts no longer imports @wrnexus/core. Compiler modules are
bundled into the Node-only VS Code extension, which contains no other
packages, so a runtime import of core broke the editor compiler; the two
helpers are implemented locally and the core dependency is dropped again.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
141 lines
4.6 KiB
TypeScript
141 lines
4.6 KiB
TypeScript
/**
|
|
* @wrnexus/compiler — the `.wrn` language compiler.
|
|
*
|
|
* Parsing and language diagnostics are provided by the canonical
|
|
* `@wrnexus/syntax` package. This package owns platform-specific codegen.
|
|
*/
|
|
|
|
import {
|
|
assertValidAst,
|
|
diagnose,
|
|
diagnosticFromError,
|
|
formatDiagnostic,
|
|
parse,
|
|
ParseError,
|
|
type PageAst,
|
|
type WrnDiagnostic,
|
|
} from "@wrnexus/syntax";
|
|
export { formatWrn } from "@wrnexus/syntax";
|
|
export type { FormatWrnOptions } from "@wrnexus/syntax";
|
|
import { generate } from "./codegen.ts";
|
|
import { generateNative } from "./native-codegen.ts";
|
|
|
|
export {
|
|
assertValidAst,
|
|
diagnose,
|
|
diagnosticFromError,
|
|
formatDiagnostic,
|
|
parse,
|
|
ParseError,
|
|
} from "@wrnexus/syntax";
|
|
export { generate } from "./codegen.ts";
|
|
export { generateTargets } from "./targets.ts";
|
|
export { generateBrowserModule } from "./client-codegen.ts";
|
|
export { generateServerFunctionsModule, rpcManifest } from "./server-codegen.ts";
|
|
export { generateDeclarations } from "./type-codegen.ts";
|
|
export { generateStoreBrowserModule, generateStoreModule } from "./store-codegen.ts";
|
|
export { createComponentContract } from "./component-contract.ts";
|
|
export { resolveWrnImport, resolveWrnImports } from "./import-resolver.ts";
|
|
export { createWrnSourceMap } from "./source-map.ts";
|
|
export { analyzeOptimizations, analyzeRuntimeRequirements, optimizeAst } from "./analysis.ts";
|
|
export type { OptimizationReport, RouteExecutionKind, RuntimeRequirements } from "./analysis.ts";
|
|
export { analyzeRuntimeImports, runtimeCapabilities } from "./runtime-capabilities.ts";
|
|
export type {
|
|
DeploymentRuntime,
|
|
RuntimeCapability,
|
|
RuntimeCapabilityDiagnostic,
|
|
} from "./runtime-capabilities.ts";
|
|
export { generateNative, NativeCompileError } from "./native-codegen.ts";
|
|
export { Lexer, LexError } from "@wrnexus/syntax";
|
|
export { eraseFunctionTypes, inferredRuntimeType, runtimeTypeOf } from "@wrnexus/syntax";
|
|
export type {
|
|
ActionBlock,
|
|
ApiBlock,
|
|
Attr,
|
|
ComputedDecl,
|
|
DataApiBlock,
|
|
DataMode,
|
|
EffectBlock,
|
|
EventDecl,
|
|
OutputDecl,
|
|
RuntimeFunctionDecl,
|
|
StateRuntime,
|
|
StoreKind,
|
|
StructuredImportDecl,
|
|
LoadBlock,
|
|
ModeFunctionsBlock,
|
|
PageAst,
|
|
PropDecl,
|
|
RealtimeBlock,
|
|
SeoBlock,
|
|
StateDecl,
|
|
ViewNode,
|
|
WrnDiagnostic,
|
|
} from "@wrnexus/syntax";
|
|
|
|
export interface CompileResult {
|
|
code: string;
|
|
ast: PageAst;
|
|
/** Backward-compatible plain diagnostic messages. */
|
|
diagnostics: string[];
|
|
/** Structured diagnostics for editors, CI, and the DevToolbar. */
|
|
richDiagnostics: WrnDiagnostic[];
|
|
}
|
|
|
|
/** Compile `.wrn` source into an Expo Router React Native screen. */
|
|
export function compileNativeWrnFile(source: string): string {
|
|
const ast = parse(source);
|
|
assertValidAst(ast);
|
|
return generateNative(ast);
|
|
}
|
|
|
|
/**
|
|
* Compile `.wrn` source into TypeScript source. Errors include a stable code,
|
|
* source location, code frame, and actionable hint whenever available.
|
|
*/
|
|
export function compileWrnFile(source: string, filePath = "<inline .wrn>"): string {
|
|
try {
|
|
const ast = parse(source);
|
|
assertValidAst(ast, { file: filePath, accessibility: true });
|
|
return `// compiled from .wrn\n${generate(ast)}`;
|
|
} catch (error) {
|
|
const diagnostic = diagnosticFromError(source, error, { file: filePath });
|
|
throw new Error(`Failed to parse ${filePath}:\n\n${formatDiagnostic(source, diagnostic)}`, {
|
|
cause: error,
|
|
});
|
|
}
|
|
}
|
|
|
|
/** Richer entry point returning the AST and structured diagnostics. */
|
|
export function compile(source: string, filePath = "<inline .wrn>"): CompileResult {
|
|
const richDiagnostics = diagnose(source, { file: filePath, accessibility: true });
|
|
const errors = richDiagnostics.filter((diagnostic) => diagnostic.severity === "error");
|
|
if (errors.length > 0) {
|
|
throw new ParseError(
|
|
errors.map((diagnostic) => diagnostic.message).join("\n"),
|
|
errors[0]!.code,
|
|
);
|
|
}
|
|
const ast = parse(source);
|
|
return {
|
|
code: `// compiled from .wrn\n${generate(ast)}`,
|
|
ast,
|
|
diagnostics: richDiagnostics.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`),
|
|
richDiagnostics,
|
|
};
|
|
}
|
|
export { compilationKey, createCompilationCache, DependencyGraph } from "./cache.ts";
|
|
export type { CompilationCache, CompilationCacheEntry, CompilationCacheOptions } from "./cache.ts";
|
|
|
|
export {
|
|
islandNamesFrom,
|
|
islandPropValue,
|
|
parseIslandStrategy,
|
|
renderIslandMarker,
|
|
serializeIslandProps,
|
|
} from "./island-codegen.ts";
|
|
export type { IslandDiagnostic, IslandStrategy } from "./island-codegen.ts";
|
|
export { assertReactAvailable, buildIslands, generateIslandEntry } from "./island-bundle.ts";
|
|
export type { IslandBuildResult, IslandInput } from "./island-bundle.ts";
|
|
export { routeNeedsIslands } from "./analysis.ts";
|