test(islands): guard zero-JS routes and single-React bundling
Two guards protect the core promise: a route with no islands emits no assets at all, and a page with several islands keeps React in one shared chunk. buildIslands now writes a generated entry per island instead of passing component sources directly. Two islands sharing a source deduped to a single entrypoint, and output order is not guaranteed to match input order, so island names could bind to the wrong bundle. Island modules are excluded from the editor compiler bundle: it globs packages/compiler/src, and island-bundle.ts calls Bun.build while island-codegen.ts imports @wrnexus/core — neither belongs in a Node-only VS Code artifact. Integration assertions share one build. bun test interferes with Bun.build's module reads after several build calls in one process, while the same calls succeed repeatedly outside the runner; production is unaffected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
"use strict";
|
||||
// Generated by scripts/build-editor-compiler.mjs. Do not edit directly.
|
||||
// WRN editor compiler source hash: c0e3e8c72c68cb3c182e2de84c13ef0b8921579d9b081550002b8cdbe4af3397
|
||||
// WRN editor compiler generator hash: c71e7fe4258c97b73b384ff14b321f0cf0b30cc2ed0322f5f84b04e757159b18
|
||||
// Generated with TypeScript: 5.9.3
|
||||
// WRN editor compiler source hash: 182fd799ca860d927879d4259c182ea61cbd89d913758cc9f690e1ae4a35d90f
|
||||
// WRN editor compiler generator hash: 2690208ba65bb00d9fea3e08cb3ab324cfda77792021cd46785814fadf41c1bc
|
||||
// Generated with TypeScript: 6.0.3
|
||||
const __nodeRequire = require;
|
||||
const __path = __nodeRequire("node:path");
|
||||
const __modules = {
|
||||
@@ -11,6 +11,7 @@ const __modules = {
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.optimizeAst = optimizeAst;
|
||||
exports.analyzeOptimizations = analyzeOptimizations;
|
||||
exports.routeNeedsIslands = routeNeedsIslands;
|
||||
exports.analyzeRuntimeRequirements = analyzeRuntimeRequirements;
|
||||
function identifiers(value) {
|
||||
return new Set(value.match(/[A-Za-z_$][\w$]*/g) ?? []);
|
||||
@@ -191,8 +192,18 @@ function hasEvent(nodes) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function analyzeRuntimeRequirements(ast) {
|
||||
/**
|
||||
* A route containing a React island ships JavaScript and can no longer be
|
||||
* classified as zero-JS static, so island presence must reach the classifier.
|
||||
*/
|
||||
function routeNeedsIslands(imports) {
|
||||
return imports.some((entry) => entry.kind === "island");
|
||||
}
|
||||
function analyzeRuntimeRequirements(ast, options = {}) {
|
||||
const hasIslands = options.hasIslands ?? false;
|
||||
const reasons = [];
|
||||
if (hasIslands)
|
||||
reasons.push("react island");
|
||||
const clientFunctions = ast.runtimeFunctions.some((fn) => fn.runtime !== "server");
|
||||
const clientState = ast.states.some((state) => state.runtime !== "server");
|
||||
const interactive = clientFunctions ||
|
||||
@@ -246,11 +257,16 @@ function analyzeRuntimeRequirements(ast) {
|
||||
kind = "streaming-ssr";
|
||||
reasons.push("partial-static shell with streamed dynamic regions");
|
||||
}
|
||||
// An island ships JavaScript, so a would-be zero-JS static route must be
|
||||
// reported as static-interactive. Explicit render modes still win above.
|
||||
if (hasIslands && kind === "static")
|
||||
kind = "static-interactive";
|
||||
const clientDisabled = ast.renderMode === "static" || ast.renderMode === "server";
|
||||
const serverDisabled = ast.renderMode === "client";
|
||||
return {
|
||||
kind,
|
||||
canPrerender: kind === "static" || kind === "static-interactive",
|
||||
needsIslandRuntime: hasIslands,
|
||||
needsClientRuntime: !clientDisabled &&
|
||||
(interactive || ast.renderMode === "client") &&
|
||||
ast.hydrate !== "none" &&
|
||||
@@ -3107,9 +3123,11 @@ function candidates(path) {
|
||||
path,
|
||||
`${path}.wrn`,
|
||||
`${path}.ts`,
|
||||
`${path}.tsx`,
|
||||
`${path}.d.ts`,
|
||||
(0, node_path_1.join)(path, "index.wrn"),
|
||||
(0, node_path_1.join)(path, "index.ts"),
|
||||
(0, node_path_1.join)(path, "index.tsx"),
|
||||
];
|
||||
}
|
||||
function resolveWrnImport(declaration, importer, options) {
|
||||
@@ -3136,8 +3154,12 @@ function resolveWrnImport(declaration, importer, options) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (found)
|
||||
return { declaration, resolved: (0, node_fs_1.realpathSync)(found) };
|
||||
if (found) {
|
||||
const resolved = (0, node_fs_1.realpathSync)(found);
|
||||
return resolved.endsWith(".tsx")
|
||||
? { declaration, resolved, kind: "island" }
|
||||
: { declaration, resolved };
|
||||
}
|
||||
const severity = (options.mode ?? "compatible") === "explicit" ? "error" : "warning";
|
||||
return {
|
||||
declaration,
|
||||
|
||||
Reference in New Issue
Block a user