release: WRNexusJS 0.5.10

This commit is contained in:
2026-07-30 13:36:29 +05:30
parent 8fc6f15402
commit d1b0c55b53
159 changed files with 7509 additions and 604 deletions
+251 -23
View File
@@ -3,6 +3,142 @@
const __nodeRequire = require;
const __path = __nodeRequire("node:path");
const __modules = {
"packages/compiler/src/cache.ts": function (module, exports, require, __filename, __dirname) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DependencyGraph = void 0;
exports.compilationKey = compilationKey;
exports.createCompilationCache = createCompilationCache;
const node_crypto_1 = require("node:crypto");
const syntax_1 = require("@wrnexus/syntax");
const codegen_ts_1 = require("./codegen.js");
function compileSource(source, filePath) {
const richDiagnostics = (0, syntax_1.diagnose)(source, { file: filePath, accessibility: true });
const errors = richDiagnostics.filter((diagnostic) => diagnostic.severity === "error");
if (errors.length > 0) {
throw new syntax_1.ParseError(errors.map((diagnostic) => diagnostic.message).join("\n"), errors[0].code);
}
const ast = (0, syntax_1.parse)(source);
return {
code: `// compiled from .wrn\n${(0, codegen_ts_1.generate)(ast)}`,
ast,
diagnostics: richDiagnostics.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`),
richDiagnostics,
};
}
function compilationKey(source, file = "<inline .wrn>", salt = "") {
return (0, node_crypto_1.createHash)("sha256")
.update(file)
.update("\0")
.update(salt)
.update("\0")
.update(source)
.digest("hex");
}
function createCompilationCache(options = {}) {
const maxEntries = options.maxEntries ?? 500;
if (!Number.isInteger(maxEntries) || maxEntries < 1)
throw new RangeError("maxEntries must be positive");
const now = options.now ?? Date.now;
const entries = new Map();
let hits = 0;
let misses = 0;
function touch(key, value) {
entries.delete(key);
entries.set(key, value);
while (entries.size > maxEntries)
entries.delete(entries.keys().next().value);
}
return {
compile(source, file = "<inline .wrn>", salt = "") {
const key = compilationKey(source, file, salt);
const existing = entries.get(key);
if (existing) {
hits++;
touch(key, existing);
return existing;
}
misses++;
const result = compileSource(source, file);
const entry = {
...result,
key,
file,
sourceHash: (0, node_crypto_1.createHash)("sha256").update(source).digest("hex"),
createdAt: now(),
};
touch(key, entry);
return entry;
},
get(key) {
const entry = entries.get(key);
if (entry)
touch(key, entry);
return entry;
},
invalidate(file) {
let removed = 0;
for (const [key, entry] of entries) {
if (!file || entry.file === file) {
entries.delete(key);
removed++;
}
}
return removed;
},
clear() {
entries.clear();
},
size: () => entries.size,
stats: () => ({ hits, misses, entries: entries.size }),
};
}
class DependencyGraph {
#dependencies = new Map();
#dependents = new Map();
set(file, dependencies) {
this.remove(file);
const values = new Set(dependencies);
this.#dependencies.set(file, values);
for (const dependency of values) {
const set = this.#dependents.get(dependency) ?? new Set();
set.add(file);
this.#dependents.set(dependency, set);
}
}
remove(file) {
for (const dependency of this.#dependencies.get(file) ?? []) {
const set = this.#dependents.get(dependency);
set?.delete(file);
if (set?.size === 0)
this.#dependents.delete(dependency);
}
this.#dependencies.delete(file);
}
dependencies(file) {
return [...(this.#dependencies.get(file) ?? [])].sort();
}
dependents(file) {
return [...(this.#dependents.get(file) ?? [])].sort();
}
affected(file) {
const found = new Set();
const queue = [file];
while (queue.length) {
const current = queue.shift();
for (const dependent of this.#dependents.get(current) ?? []) {
if (found.has(dependent))
continue;
found.add(dependent);
queue.push(dependent);
}
}
return [...found].sort();
}
}
exports.DependencyGraph = DependencyGraph;
},
"packages/compiler/src/codegen.ts": function (module, exports, require, __filename, __dirname) {
"use strict";
/**
@@ -937,6 +1073,9 @@ function exprRefsState(expr, stateNames) {
}
return false;
}
function exprRefsComponentReactiveValue(expr, ctx) {
return exprRefsState(expr, ctx.stateNames) || exprRefsState(expr, ctx.functionNames);
}
function viewHasEvents(nodes) {
return nodes.some((node) => {
if (node.type === "text")
@@ -999,7 +1138,7 @@ function compileText(raw, ctx) {
// list renderer fills it per item; it has no server-side value.
out += escLit(`{${expr}}`);
}
else if (exprRefsState(expr, ctx.stateNames)) {
else if (exprRefsComponentReactiveValue(expr, ctx)) {
// State interpolation: bake the initial value AND keep it reactive via a
// data-text span, so no-JS clients see the real value and hydration
// updates it in place. `count` → `<span data-text="count">0</span>`.
@@ -1156,6 +1295,7 @@ function renderComponentNode(node, ctx) {
});
}
}
const isExplicitComponentMount = node.attrs.some((attribute) => attribute.name === "data-component");
const attrs = node.attrs
.filter((a) => a.name !== "class" && !a.name.startsWith("class:"))
.map((a) => {
@@ -1172,7 +1312,7 @@ function renderComponentNode(node, ctx) {
if (isHtmlBooleanAttribute(a.name)) {
const expression = wholeAttributeExpression(a.value);
if (expression) {
const referencesState = exprRefsState(a.value, ctx.stateNames);
const referencesState = exprRefsComponentReactiveValue(a.value, ctx);
const referencesLoopVariable = elementContext.loopVars
? exprRefsState(a.value, elementContext.loopVars)
: false;
@@ -1189,8 +1329,12 @@ function renderComponentNode(node, ctx) {
if (a.value === "true" || a.value === "")
return ` ${a.name}`;
}
const rendered = ` ${a.name}="${compileAttrValue(a.value, elementContext)}"`;
const referencesState = exprRefsState(a.value, ctx.stateNames);
const wholeExpression = wholeAttributeExpression(a.value);
const compiledValue = isExplicitComponentMount && wholeExpression
? `\${__wireProp(${elementContext.resolveExpr(wholeExpression)})}`
: compileAttrValue(a.value, elementContext);
const rendered = ` ${a.name}="${compiledValue}"`;
const referencesState = exprRefsComponentReactiveValue(a.value, ctx);
const referencesLoopVariable = elementContext.loopVars
? exprRefsState(a.value, elementContext.loopVars)
: false;
@@ -1219,7 +1363,7 @@ function renderComponentNode(node, ctx) {
})
.join("");
const staticClassValue = staticClasses.join(" ");
const classReferencesState = exprRefsState(staticClassValue, ctx.stateNames);
const classReferencesState = exprRefsComponentReactiveValue(staticClassValue, ctx);
const classReferencesLoopVariable = elementContext.loopVars
? exprRefsState(staticClassValue, elementContext.loopVars)
: false;
@@ -1243,9 +1387,7 @@ function renderComponentNode(node, ctx) {
const loopLocalsAttribute = serverLoopLocalsAttribute(ctx);
const allAttrs = `${loopLocalsAttribute}` +
`${ctx.forwardRestAttrs ? "${__wireSpreadAttrs(__attrs)}" : ""}` +
`${ctx.forwardRestAttrs && ctx.eventNames?.length
? ` data-wrn-events="${attrEscape(ctx.eventNames.join(","))}"`
: ""}` +
`${ctx.eventNames?.length ? ` data-wrn-events="${attrEscape(ctx.eventNames.join(","))}"` : ""}` +
`${classAttribute}` +
`${classReactiveBinding}` +
`${classBindings}` +
@@ -1261,9 +1403,6 @@ function generateComponent(ast) {
if (ast.imports.length > 0)
out.push(ast.imports.join("\n"));
const hasServerEach = viewHasServerEach(ast.view);
if (hasServerEach) {
out.push(`import { Buffer } from "node:buffer";`);
}
const effectiveProps = ast.kind === "layout" && !ast.props.some((prop) => prop.name === "content")
? [
{
@@ -1300,6 +1439,9 @@ function generateComponent(ast) {
};
const ctx = {
stateNames,
functionNames: new Set(ast.functions.flatMap((body) => {
return Array.from(body.matchAll(/(?:async\s+)?function\s+([A-Za-z_$][\w$]*)\s*\(/g), (match) => match[1]);
})),
resolveExpr,
eventNames: ast.events.map((event) => event.name),
};
@@ -1330,6 +1472,9 @@ function generateComponent(ast) {
ast.computed.length > 0 ||
viewHasEvents(ast.view) ||
behavior !== null);
if (hasServerEach || needsScope) {
out.push(`import { Buffer as __WrnexusBuffer } from "node:buffer";`);
}
const scopeKeys = [
...effectiveProps.map((prop) => prop.name),
...ast.states.map((state) => state.name),
@@ -1354,16 +1499,16 @@ function generateComponent(ast) {
const returnExpr = needsScope
? "`" +
styleTag +
`<div data-scope="\${__scope}"${behaviorAttr}${hydrationAttribute(ast)}>` +
`<div data-scope="\${__scope}" data-wrn-scope="\${__scopePayload}"${behaviorAttr}${hydrationAttribute(ast)}>` +
viewCode +
"</div>`"
: "`" + styleTag + viewCode + "`";
const scopeLine = needsScope && scopeKeys.length > 0
? ` const __scope = __wrnexusScopeDecl({ ${scopeKeys
? ` const __scopeState = { ${scopeKeys
.map((key) => `${JSON.stringify(key)}: ${nameRefs.get(key)}`)
.join(", ")} });\n`
.join(", ")} };\n const __scope = __wrnexusScopeDecl(__scopeState);\n const __scopePayload = __WrnexusBuffer.from(JSON.stringify(__scopeState), "utf8").toString("base64");\n`
: needsScope
? ` const __scope = "";\n`
? ` const __scopeState = {};\n const __scope = "";\n const __scopePayload = __WrnexusBuffer.from("{}", "utf8").toString("base64");\n`
: "";
if (ast.kind === "layout") {
out.push(`export const __wrnexusLayout = ${JSON.stringify(ast.name)};`);
@@ -1553,7 +1698,7 @@ function __wireRaw(v: any): string {
}`);
if (hasServerEach) {
out.push(`function __wrnexusEncodeLoopLocals(value: Record<string, any>): string {
return Buffer.from(JSON.stringify(value), "utf8").toString("base64");
return __WrnexusBuffer.from(JSON.stringify(value), "utf8").toString("base64");
}`);
}
if (needsScope) {
@@ -1661,7 +1806,7 @@ function renderPageComponentAttr(attr, dynamicExpressions) {
* `@wrnexus/syntax` package. This package owns platform-specific codegen.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.runtimeTypeOf = exports.inferredRuntimeType = exports.eraseFunctionTypes = exports.LexError = exports.Lexer = exports.NativeCompileError = exports.generateNative = exports.generate = exports.ParseError = exports.parse = exports.formatDiagnostic = exports.diagnosticFromError = exports.diagnose = exports.assertValidAst = void 0;
exports.DependencyGraph = exports.createCompilationCache = exports.compilationKey = exports.runtimeTypeOf = exports.inferredRuntimeType = exports.eraseFunctionTypes = exports.LexError = exports.Lexer = exports.NativeCompileError = exports.generateNative = exports.generate = exports.ParseError = exports.parse = exports.formatDiagnostic = exports.diagnosticFromError = exports.diagnose = exports.assertValidAst = void 0;
exports.compileNativeWireFile = compileNativeWireFile;
exports.compileWireFile = compileWireFile;
exports.compile = compile;
@@ -1725,6 +1870,10 @@ function compile(source, filePath = "<inline .wrn>") {
richDiagnostics,
};
}
var cache_ts_1 = require("./cache.js");
Object.defineProperty(exports, "compilationKey", { enumerable: true, get: function () { return cache_ts_1.compilationKey; } });
Object.defineProperty(exports, "createCompilationCache", { enumerable: true, get: function () { return cache_ts_1.createCompilationCache; } });
Object.defineProperty(exports, "DependencyGraph", { enumerable: true, get: function () { return cache_ts_1.DependencyGraph; } });
},
"packages/compiler/src/native-codegen.ts": function (module, exports, require, __filename, __dirname) {
@@ -2211,7 +2360,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.positionAt = exports.isRuntimeTarget = exports.isHydrationStrategy = exports.formatDiagnostic = exports.diagnosticFromError = exports.diagnose = exports.classifyParseError = exports.assertValidAst = exports.validateTypedInitializer = exports.runtimeTypeOf = exports.inferredRuntimeType = exports.eraseFunctionTypes = exports.VOID_ELEMENTS = exports.ParseError = exports.parseHtmlView = exports.parse = exports.LexError = exports.Lexer = void 0;
exports.supportsSyntaxFeature = exports.diagnosticSummary = exports.sliceSource = exports.createSourceRange = exports.WRN_SYNTAX_FEATURES = exports.WRN_SYNTAX_VERSION = exports.positionAt = exports.isRuntimeTarget = exports.isHydrationStrategy = exports.formatDiagnostic = exports.diagnosticFromError = exports.diagnose = exports.classifyParseError = exports.assertValidAst = exports.validateTypedInitializer = exports.runtimeTypeOf = exports.inferredRuntimeType = exports.eraseFunctionTypes = exports.VOID_ELEMENTS = exports.ParseError = exports.parseHtmlView = exports.parse = exports.LexError = exports.Lexer = void 0;
var tokenizer_ts_1 = require("./tokenizer.js");
Object.defineProperty(exports, "Lexer", { enumerable: true, get: function () { return tokenizer_ts_1.Lexer; } });
Object.defineProperty(exports, "LexError", { enumerable: true, get: function () { return tokenizer_ts_1.LexError; } });
@@ -2235,6 +2384,13 @@ Object.defineProperty(exports, "isHydrationStrategy", { enumerable: true, get: f
Object.defineProperty(exports, "isRuntimeTarget", { enumerable: true, get: function () { return diagnostics_ts_1.isRuntimeTarget; } });
Object.defineProperty(exports, "positionAt", { enumerable: true, get: function () { return diagnostics_ts_1.positionAt; } });
__exportStar(require("./spec.js"), exports);
var versioning_ts_1 = require("./versioning.js");
Object.defineProperty(exports, "WRN_SYNTAX_VERSION", { enumerable: true, get: function () { return versioning_ts_1.WRN_SYNTAX_VERSION; } });
Object.defineProperty(exports, "WRN_SYNTAX_FEATURES", { enumerable: true, get: function () { return versioning_ts_1.WRN_SYNTAX_FEATURES; } });
Object.defineProperty(exports, "createSourceRange", { enumerable: true, get: function () { return versioning_ts_1.createSourceRange; } });
Object.defineProperty(exports, "sliceSource", { enumerable: true, get: function () { return versioning_ts_1.sliceSource; } });
Object.defineProperty(exports, "diagnosticSummary", { enumerable: true, get: function () { return versioning_ts_1.diagnosticSummary; } });
Object.defineProperty(exports, "supportsSyntaxFeature", { enumerable: true, get: function () { return versioning_ts_1.supportsSyntaxFeature; } });
},
"packages/syntax/src/parser.ts": function (module, exports, require, __filename, __dirname) {
@@ -2475,7 +2631,11 @@ function parse(source) {
else {
expect("eq");
}
states.push({ name: sName, valueType, expr: lx.readToLineEnd() });
// State values may be multiline structured expressions. Use the same
// balanced initializer reader as props so formatted arrays/objects
// remain one declaration instead of exposing their inner braces as
// component members on the next line.
states.push({ name: sName, valueType, expr: lx.readPropInitializer() });
break;
}
case "computed": {
@@ -2755,14 +2915,29 @@ function parseHtmlView(src, pos) {
while (i < src.length && isWs(src[i]))
i++;
};
/** Read a `{...}` interpolation (brace-balanced), braces included. */
/** Read a `{...}` interpolation (brace-balanced and quote-aware), braces included. */
const readInterpolation = () => {
const start = i;
let depth = 0;
let quote = null;
for (; i < src.length; i++) {
if (src[i] === "{")
const char = src[i];
if (quote) {
if (char === "\\" && i + 1 < src.length) {
i++;
continue;
}
if (char === quote)
quote = null;
continue;
}
if (char === '"' || char === "'" || char === "`") {
quote = char;
continue;
}
if (char === "{")
depth++;
else if (src[i] === "}" && --depth === 0) {
else if (char === "}" && --depth === 0) {
i++;
return src.slice(start, i);
}
@@ -2852,7 +3027,12 @@ function parseHtmlView(src, pos) {
if (src[i] === "=") {
i++;
skipWs();
attrs.push({ name, value: readQuoted(), event: false });
const value = src[i] === '"' || src[i] === "'"
? readQuoted()
: src[i] === "{"
? readInterpolation()
: fail(`Expected a quoted value or {...} expression after '${name}='`);
attrs.push({ name, value, event: false });
}
else {
attrs.push({ name, value: "", event: false, boolean: true });
@@ -3447,6 +3627,54 @@ function eraseFunctionTypes(source) {
});
}
},
"packages/syntax/src/versioning.ts": function (module, exports, require, __filename, __dirname) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WRN_SYNTAX_FEATURES = exports.WRN_SYNTAX_VERSION = void 0;
exports.createSourceRange = createSourceRange;
exports.sliceSource = sliceSource;
exports.diagnosticSummary = diagnosticSummary;
exports.supportsSyntaxFeature = supportsSyntaxFeature;
/** Current stable syntax contract. Bump only when parsers/codegen need migration. */
exports.WRN_SYNTAX_VERSION = "0.4";
exports.WRN_SYNTAX_FEATURES = Object.freeze({
"typed-declarations": true,
layouts: true,
"server-client-blocks": true,
effects: true,
watch: true,
lifecycle: true,
"embedded-api": true,
realtime: true,
"runtime-markers": true,
});
function createSourceRange(start, end) {
if (!Number.isInteger(start) || !Number.isInteger(end) || start < 0 || end < start) {
throw new RangeError(`Invalid source range ${start}..${end}`);
}
return { start, end };
}
function sliceSource(source, range) {
return source.slice(range.start, range.end);
}
function diagnosticSummary(diagnostics) {
const summary = { errors: 0, warnings: 0, info: 0, codes: {} };
for (const diagnostic of diagnostics) {
if (diagnostic.severity === "error")
summary.errors++;
else if (diagnostic.severity === "warning")
summary.warnings++;
else
summary.info++;
summary.codes[diagnostic.code] = (summary.codes[diagnostic.code] ?? 0) + 1;
}
return summary;
}
function supportsSyntaxFeature(feature) {
return Object.prototype.hasOwnProperty.call(exports.WRN_SYNTAX_FEATURES, feature);
}
}
};
const __aliases = {