Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5419,6 +5419,7 @@ fn externalCoreFixtureModule(
stage_run.addFileInput(b.path("packages/core/src/widget_metrics.ts"));
stage_run.addFileInput(b.path("packages/core/src/intrinsic_measure.ts"));
stage_run.addFileInput(b.path("packages/core/src/measurement_coordination.ts"));
stage_run.addFileInput(b.path("packages/core/src/flow_measurement.ts"));
stage_run.addFileInput(b.path("packages/core/src/stream_policy.ts"));
stage_run.addArg("--src");
stage_run.addDirectoryArg(spec.src_dir);
Expand Down
1 change: 1 addition & 0 deletions build/app.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1260,6 +1260,7 @@ fn tsCoreStage(
stage_run.addFileInput(dep.path("packages/core/src/widget_metrics.ts"));
stage_run.addFileInput(dep.path("packages/core/src/intrinsic_measure.ts"));
stage_run.addFileInput(dep.path("packages/core/src/measurement_coordination.ts"));
stage_run.addFileInput(dep.path("packages/core/src/flow_measurement.ts"));
stage_run.addFileInput(dep.path("packages/core/src/stream_policy.ts"));
if (typescript_view) {
stage_run.addArg("--view-markup");
Expand Down
121 changes: 121 additions & 0 deletions packages/core/src/flow_measurement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/** Portable grid admission and first-row measurement. Native retains copied
* requests, executes measurements, and traverses the resulting frames. */
function nscvGridMeasure(request: Uint8Array): Uint8Array {
if (request.length < 128 || request[0] !== 38 || request[1] !== 1 || request[2]! > 15 || request[3]! > 1)
throw new Error("invalid grid measurement header");
const w = new DataView(request.buffer, request.byteOffset, request.byteLength), count = w.getUint32(4, true);
if (request.length !== 128 + count * 64 || w.getUint32(8, true) !== 0 || w.getUint32(12, true) !== 0)
throw new Error("invalid grid measurement shape");
for (let i = 92; i < 128; i++) if (request[i] !== 0) throw new Error("invalid grid measurement reserved bytes");
const packet = request.slice(16, 92), p = new DataView(packet.buffer), virtual = request[3] === 1;
if (packet[0] !== 4 || packet[1] !== 0 || ((packet[2]! & 1) !== 0) !== virtual || p.getUint32(52, true) !== 0)
throw new Error("invalid grid measurement allocation");
let flows = 0;
for (let i = 0; i < count; i++) {
const at = 128 + i * 64, flags = w.getUint32(at, true), ready = w.getUint32(at + 4, true);
if (flags > 3 || ready > 1 || (flags & 1) === 0 && ready !== 0)
throw new Error("invalid grid measurement child");
for (let j = 44; j < 64; j++) if (request[at + j] !== 0) throw new Error("invalid grid measurement child reserved bytes");
if ((flags & 1) !== 0) flows++;
}
if (p.getUint32(4, true) !== flows || p.getUint32(8, true) !== 0) throw new Error("invalid grid measurement flow count");
let grid = nscvGridLayout(packet), g = new DataView(grid.buffer);
const result = new Uint8Array(32 + count * 32), out = new DataView(result.buffer); out.setUint32(0, 1, true);
if (flows === 0) return result;
const max = (a: number, b: number): number => nscvRenderExtreme(a, b, request[2]!, true);
const min = (a: number, b: number): number => nscvRenderExtreme(a, b, request[2]!, false);
if (virtual && !(p.getFloat32(48, true) > 0)) {
const columns = g.getUint32(0, true) + g.getUint32(4, true) * 4294967296;
let flow = 0, height = 0;
for (let i = 0; i < count && flow < columns; i++) {
const at = 128 + i * 64;
if ((w.getUint32(at, true) & 1) === 0) continue;
const authored = w.getFloat32(at + 20, true);
if (!(authored > 0) && w.getUint32(at + 4, true) === 0) {
out.setUint32(4, 1, true); out.setUint32(8, i, true); return result.slice(0, 32);
}
const value = authored > 0 ? authored : w.getFloat32(at + 40, true), ceiling = w.getFloat32(at + 36, true);
height = max(height, max(max(0, w.getFloat32(at + 28, true)), ceiling > 0 ? min(value, ceiling) : value));
flow++;
}
p.setFloat32(52, height, true); grid = nscvGridLayout(packet); g = new DataView(grid.buffer);
}
out.setUint32(12, nscvFlowSemantic(nscvFlowInteger(g, 8)), true);
result.set(grid.subarray(48, 52), 16); out.setUint32(24, 1, true);
const columns = g.getUint32(0, true) + g.getUint32(4, true) * 4294967296;
const start = g.getUint32(16, true) + g.getUint32(20, true) * 4294967296;
const end = g.getUint32(24, true) + g.getUint32(28, true) * 4294967296;
let flow = 0;
for (let i = 0; i < count; i++) {
const at = 128 + i * 64, flags = w.getUint32(at, true);
if ((flags & 1) === 0) continue;
const index = flow++; if (virtual && (Math.floor(index / columns) < start || Math.floor(index / columns) >= end)) continue;
const cell = new Uint8Array(76), c = new DataView(cell.buffer);
cell[0] = 4; cell[1] = 1; cell[2] = (virtual ? 1 : 0) | ((flags & 2) !== 0 ? 2 : 0);
c.setUint32(4, index, true); cell.set(grid.subarray(0, 8), 12);
cell.set(packet.subarray(28, 36), 20); cell.set(grid.subarray(32, 48), 28);
cell.set(request.subarray(at + 8, at + 24), 44);
cell.set(request.subarray(at + 24, at + 32), 60); cell.set(request.subarray(at + 32, at + 40), 68);
const frame = nscvGridLayout(cell), dest = 32 + i * 32;
out.setUint32(dest, 1, true); out.setUint32(dest + 4, index, true); out.setUint32(dest + 8, flows, true);
result.set(frame.subarray(1, 17), dest + 16);
}
return result;
}

/** Measurement scheduling for uniform/variable virtual rows and scroll
* shelves. Existing allocation operations retain their exact wire formats. */
function nscvFlowMeasure(request: Uint8Array): Uint8Array {
if (request.length < 144 || request[0] !== 39 || request[1] !== 1 || (request[2] !== 0 && request[2] !== 2) || request[3]! > 15)
throw new Error("invalid flow measurement header");
const w = new DataView(request.buffer, request.byteOffset, request.byteLength), count = w.getUint32(4, true), ready = w.getUint32(8, true);
if (request.length !== 144 + count * 72 || ready > 1 || w.getUint32(12, true) !== 0)
throw new Error("invalid flow measurement shape");
const packet = request.slice(16, 144 + count * 64), p = new DataView(packet.buffer), op = request[2]!;
if (packet[0] !== 8 || packet[1] !== op || p.getUint32(4, true) !== count) throw new Error("invalid flow measurement allocation");
const state = (i: number): number => 144 + count * 64 + i * 8;
let flows = 0;
for (let i = 0; i < count; i++) {
const lane = p.getUint32(128 + i * 64, true), at = state(i);
if (w.getUint32(at, true) > 1 || w.getUint32(at + 4, true) > 1 || lane === 0 && w.getUint32(at, true) !== 0)
throw new Error("invalid flow measurement child state");
if (lane === 1) flows++;
}
const initial = nscvVirtualFlow(packet), initialWire = new DataView(initial.buffer), mode = initialWire.getUint32(4, true);
const result = new Uint8Array(32), out = new DataView(result.buffer); out.setUint32(0, 1, true);
const command = (action: number, index: number, width: number = 0): Uint8Array => {
out.setUint32(4, action, true); out.setUint32(8, index, true); out.setFloat32(16, width, true); return result;
};
const max = (a: number, b: number): number => nscvRenderExtreme(a, b, request[3]!, true);
const min = (a: number, b: number): number => nscvRenderExtreme(a, b, request[3]!, false);
if (op === 0 && flows > 0) {
for (let i = 0; i < count; i++) {
const at = 128 + i * 64;
if (p.getUint32(at, true) === 0) continue;
const authored = p.getFloat32(at + 12, true);
if (mode === 1) {
if (!(authored > 0) && w.getUint32(state(i), true) === 0) return command(2, i, p.getFloat32(84, true));
} else if (!(p.getFloat32(96, true) > 0)) {
if (!(authored > 0) && ready === 0) return command(1, i);
const value = authored > 0 ? authored : p.getFloat32(100, true), ceiling = p.getFloat32(at + 28, true);
p.setFloat32(100, max(max(0, p.getFloat32(at + 24, true)), ceiling > 0 ? min(value, ceiling) : value), true);
break;
}
}
}
if (op === 2) {
for (let i = 0; i < count; i++) {
const at = 128 + i * 64;
if (p.getUint32(at, true) === 0) continue;
const stack = new Uint8Array(84), s = new DataView(stack.buffer); stack[0] = 5; stack[1] = 3; s.setUint32(8, 1, true);
stack.set(initial.subarray(24, 40), 12);
s.setUint32(36, 1 | (w.getUint32(state(i) + 4, true) !== 0 ? 2 : 0), true);
stack.set(packet.subarray(at + 8, at + 16), 44); stack.set(packet.subarray(at + 32, at + 40), 52);
for (const [from, to] of [[16,60],[20,64],[24,68],[28,72]]) stack.set(packet.subarray(at + from!, at + from! + 4), to!);
const frame = nscvContainerLayout(stack); packet.set(frame.subarray(12, 28), at + 48);
if ((initialWire.getUint32(48 + i * 32, true) & 2) !== 0 && w.getUint32(state(i), true) === 0) return command(3, i);
}
}
const final = nscvVirtualFlow(packet), complete = new Uint8Array(32 + final.length);
out.setUint32(24, flows > 0 ? 1 : 0, true); complete.set(result); complete.set(final, 32); return complete;
}
2 changes: 2 additions & 0 deletions packages/core/src/runtime_policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ export function native_window_policy(request: Uint8Array): Uint8Array {
if (request[0] === 35) return nscvAxisChildMeasure(request);
if (request[0] === 36) return nscvSpanSubtree(request);
if (request[0] === 37) return nscvAxisMeasure(request);
if (request[0] === 38) return nscvGridMeasure(request);
if (request[0] === 39) return nscvFlowMeasure(request);
const data = new DataView(request.buffer, request.byteOffset, request.byteLength);
let at = 0;
const byte = (): number => {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/view_frontend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -928,4 +928,5 @@ const viewPrelude = "\n// Portable Native components compiled beside the committ
readFileSync(new URL("./widget_metrics.ts", import.meta.url), "utf8") +
readFileSync(new URL("./intrinsic_measure.ts", import.meta.url), "utf8") +
readFileSync(new URL("./measurement_coordination.ts", import.meta.url), "utf8") +
readFileSync(new URL("./flow_measurement.ts", import.meta.url), "utf8") +
readFileSync(new URL("./stream_policy.ts", import.meta.url), "utf8");
81 changes: 81 additions & 0 deletions packages/core/test/flow_measurement.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import assert from "node:assert/strict";
import test from "node:test";
import { readFileSync } from "node:fs";
import { stripTypeScriptTypes } from "node:module";
const source = ["runtime_policy.ts", "flow_measurement.ts"].map(n => readFileSync(new URL(`../src/${n}`, import.meta.url), "utf8")).join("\n");
const { nscvGridMeasure: grid, nscvFlowMeasure: flow } = await import(`data:text/javascript;base64,${Buffer.from(stripTypeScriptTypes(source) + "\nexport {nscvGridMeasure,nscvFlowMeasure};").toString("base64")}`);
const wire = (b: Uint8Array) => new DataView(b.buffer, b.byteOffset, b.byteLength);
const word = (b: Uint8Array, at: number) => wire(b).getUint32(at, true);
const value = (b: Uint8Array, at: number) => wire(b).getFloat32(at, true);
function gridPacket(virtual = true): Uint8Array {
const b = new Uint8Array(384), w = wire(b); b.set([38, 1, 0, virtual ? 1 : 0]); w.setUint32(4, 4, true);
b.set([4, 0, virtual ? 1 : 0], 16); w.setBigUint64(20, 3n, true); w.setBigUint64(28, 2n, true);
for (const [at, v] of [[44,3.25],[48,5.125],[52,160],[56,100],[60,2],[76,3],[80,2],[84,2],[88,1]]) w.setFloat32(at!, v!, true);
for (const i of [0,2,3]) w.setUint32(128 + i * 64, 1, true);
w.setFloat32(148, 20, true); w.setFloat32(284, 10, true); w.setFloat32(292, 25, true);
return b;
}
function flowPacket(op = 0, count = 3): Uint8Array {
const b = new Uint8Array(144 + count * 72), w = wire(b); b.set([39,1,op,0]); w.setUint32(4, count, true);
b.set([8,op,0,3], 16); w.setUint32(20, count, true);
for (const [at,v] of [[72,count],[76,count],[92,3.25],[96,5.125],[100,160],[104,100],[108,2]]) w.setFloat32(at!, v!, true);
for (let i = 0; i < count; i++) { w.setUint32(144 + i * 64, 1, true); w.setFloat32(148 + i * 64, i, true); }
return b;
}
function reply(b: Uint8Array, index: number, at: number, result: number): void {
wire(b).setUint32(144 + word(b, 4) * 64 + index * 8, 1, true);
wire(b).setFloat32(144 + index * 64 + at, result, true);
}
test("virtual grid measures only missing heights in the first flow row and preserves complete child records", () => {
const b = gridPacket(), w = wire(b);
let r = grid(b); assert.equal(word(r,4),1); assert.equal(word(r,8),2);
w.setUint32(260,1,true); w.setFloat32(296,50,true); r = grid(b);
assert.equal(word(r,4),0); assert.equal(word(r,12),2); assert.equal(value(r,16),25);
assert.equal(word(r,64),0); assert.equal(word(r,96),1); assert.equal(word(r,100),1); assert.equal(word(r,104),3);
assert.equal(value(r,112),84.25); assert.equal(value(r,124),25); assert.equal(word(r,128),1); assert.equal(value(r,148),32.125);
});
test("authored grid extents suppress measurements; nonvirtual cells preserve authored semantic ownership", () => {
const b = gridPacket(); wire(b).setFloat32(64,40,true); assert.equal(word(grid(b),4),0); assert.equal(value(grid(b),16),40);
const plain = gridPacket(false); const r = grid(plain); assert.equal(word(r,4),0); assert.equal(value(r,16),0); assert.equal(value(r,124),25); assert.equal(value(r,156),49);
});
test("grid preserves wide column words and copied results without modifying the borrowed request", () => {
const b = gridPacket(false), w = wire(b); w.setBigUint64(28,0xffffffffffffffffn,true); w.setFloat32(80,Math.fround(2 ** 64),true); w.setFloat32(88,Math.fround(2 ** 64),true);
const before = b.slice(), r = grid(b), saved = r.slice(); assert.equal(word(r,12),1); assert.deepEqual(b,before); b.fill(255); assert.deepEqual(r,saved);
});
test("uniform rows measure only the first flow child and clamp its reply before allocation", () => {
const b = flowPacket(), w = wire(b); w.setUint32(144,0,true); w.setFloat32(212,0,true); w.setFloat32(276,1,true); w.setFloat32(232,12,true); w.setFloat32(236,30,true);
let r = flow(b); assert.equal(word(r,4),1); assert.equal(word(r,8),1);
w.setUint32(8,1,true); w.setFloat32(116,50,true); r = flow(b);
assert.equal(word(r,4),0); assert.equal(word(r,40),2); assert.equal(value(r,44),30); assert.equal(word(r,80),0);
assert.equal(value(r,124),5.125); assert.equal(value(r,156),37.125);
});
test("variable rows query every missing window height in order and retain the anchor layout", () => {
const b = flowPacket(), w = wire(b); w.setBigUint64(32,100n,true); w.setBigUint64(40,1n,true); w.setFloat32(132,1000,true); w.setFloat32(128,80,true); w.setFloat32(220,40,true);
let r = flow(b); assert.equal(word(r,4),2); assert.equal(word(r,8),0); assert.equal(value(r,16),160);
reply(b,0,40,20); r = flow(b); assert.equal(word(r,4),2); assert.equal(word(r,8),2);
reply(b,2,40,60); r = flow(b); assert.equal(word(r,4),0); assert.equal(word(r,36),1);
assert.equal(value(r,92),63.125); assert.equal(value(r,124),85.125); assert.equal(value(r,156),127.125);
});
test("scroll shelves measure only horizontal missing widths and preserve stack frames and stale-axis filtering", () => {
const b = flowPacket(2), w = wire(b); w.setUint32(208,0,true); w.setFloat32(280,200,true); w.setFloat32(120,7,true); w.setFloat32(124,9,true);
let r = flow(b); assert.equal(word(r,4),3); assert.equal(word(r,8),0);
reply(b,0,44,300); r = flow(b); assert.equal(word(r,4),0); assert.equal(word(r,36),4);
assert.equal(value(r,88),-3.75); assert.equal(value(r,92),-3.875); assert.equal(value(r,96),300); assert.equal(value(r,160),200);
b[19] = 2; const vertical = flow(b); assert.equal(value(vertical,88),3.25); assert.equal(value(vertical,96),160);
});
test("empty flow parents retain inactive admission instead of replacing declared metadata", () => {
const b = gridPacket(); const w = wire(b); w.setBigUint64(20,0n,true);
for (let i=0;i<4;i++) w.setUint32(128+i*64,0,true);
assert.equal(word(grid(b),24),0);
const f = flowPacket(0,0); assert.equal(word(flow(f),24),0); assert.equal(word(flow(f),4),0);
});
test("complete packets reject malformed states, lengths and reserved data before issuing a query", () => {
for (const at of [0,1,2,3,4,8,12,16,17,18,19,20,92,127,128,132,172,191]) {
const b=gridPacket(); b[at]=255; assert.throws(()=>grid(b),/invalid/);
}
for (const at of [0,1,2,3,4,8,12,16,17,18,19,20,136,140,144,336,340]) {
const b=flowPacket(); b[at]=255; assert.throws(()=>flow(b),/invalid/);
}
for (const derive of [grid,flow]) assert.throws(()=>derive(new Uint8Array(143)),/invalid/);
const b=flowPacket(), before=b.slice(), r=flow(b), saved=r.slice(); assert.deepEqual(b,before); b.fill(255); assert.deepEqual(r,saved);
});
2 changes: 1 addition & 1 deletion packages/core/test/view_frontend.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ test("the view frontend and compiled portable component bundle typecheck", () =>
};
// Production joins these policies in one module before compiling the view.
const bundlePath = new URL("../src/view_components_typecheck.ts", import.meta.url).pathname;
const bundle = ["view_components.ts", "runtime_policy.ts", "control_appearance.ts", "component_construction.ts", "widget_motion.ts", "component_composition.ts", "code_content.ts", "chart_content.ts", "markdown_content.ts", "widget_audits.ts", "widget_routing.ts", "widget_changes.ts", "widget_paint.ts", "widget_presentation.ts", "widget_paint_walk.ts", "control_geometry.ts", "control_content.ts", "surface_recipes.ts", "widget_metrics.ts", "intrinsic_measure.ts", "measurement_coordination.ts", "stream_policy.ts"]
const bundle = ["view_components.ts", "runtime_policy.ts", "control_appearance.ts", "component_construction.ts", "widget_motion.ts", "component_composition.ts", "code_content.ts", "chart_content.ts", "markdown_content.ts", "widget_audits.ts", "widget_routing.ts", "widget_changes.ts", "widget_paint.ts", "widget_presentation.ts", "widget_paint_walk.ts", "control_geometry.ts", "control_content.ts", "surface_recipes.ts", "widget_metrics.ts", "intrinsic_measure.ts", "measurement_coordination.ts", "flow_measurement.ts", "stream_policy.ts"]
.map(name => readFileSync(new URL(`../src/${name}`, import.meta.url), "utf8")).join("\n");
const host = ts.createCompilerHost(options);
const readSource = host.getSourceFile.bind(host);
Expand Down
Loading
Loading