Files
WRNexusJS/packages/react/src/error-boundary.tsx
T
ClintchizandClaude Opus 5 17aa3b98eb feat(islands): wire islands end to end
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>
2026-08-18 16:16:03 +05:30

45 lines
1.3 KiB
TypeScript

/** @jsxImportSource react */
import { Component, type ErrorInfo, type ReactNode } from "react";
export interface IslandErrorBoundaryProps {
name: string;
development: boolean;
/** Optional so createElement(Boundary, props, child) typechecks. */
children?: ReactNode;
}
interface IslandErrorBoundaryState {
error: Error | null;
}
/**
* Contains island failures locally: a crashed island must never blank the
* surrounding server-rendered page.
*/
export class IslandErrorBoundary extends Component<
IslandErrorBoundaryProps,
IslandErrorBoundaryState
> {
override state: IslandErrorBoundaryState = { error: null };
static getDerivedStateFromError(error: Error): IslandErrorBoundaryState {
return { error };
}
override componentDidCatch(error: Error, info: ErrorInfo): void {
console.error(`[wrnexus] island '${this.props.name}' failed to render`, error, info);
}
override render(): ReactNode {
const { error } = this.state;
if (!error) return this.props.children;
if (!this.props.development) return null;
return (
<div data-wrn-island-error={this.props.name} style={{ padding: "0.75rem" }}>
<strong>{`Island '${this.props.name}' failed`}</strong>
<pre>{error.stack ?? error.message}</pre>
</div>
);
}
}