Files
Web_FreeCAD_Bitbybit/public/chrome-topology-harness.html

60 lines
3.2 KiB
HTML

<!doctype html>
<meta charset="utf-8">
<title>Chrome Topology Harness</title>
<pre id="result">running</pre>
<script type="module">
import { BitbybitGeometryRuntime } from '/src/facade/geometryRuntime.ts'
const output = document.querySelector('#result')
const report = { schemaVersion: 1, browserId: 'chrome', crossOriginIsolated: globalThis.crossOriginIsolated === true, status: 'running' }
const persistTopologyInOpfs = async (topology) => {
if (!navigator.storage?.getDirectory) return false
const root = await navigator.storage.getDirectory()
const directory = await root.getDirectoryHandle('bitbybit-topology-harness', { create: true })
const name = `topology-${crypto.randomUUID()}.json`
const payload = JSON.stringify({ adjacency: topology.adjacency, ids: topology.entries.map((entry) => entry.ref.persistentId) })
try {
const handle = await directory.getFileHandle(name, { create: true })
const writable = await handle.createWritable()
await writable.write(payload)
await writable.close()
const restored = JSON.parse(await (await handle.getFile()).text())
return JSON.stringify(restored) === JSON.stringify(JSON.parse(payload))
} finally {
await directory.removeEntry(name).catch(() => {})
}
}
try {
const runtime = new BitbybitGeometryRuntime()
report.capabilities = await runtime.initialize()
const shape = await runtime.createBox({ documentId: 'chrome-topology', documentVersion: 1, width: 10, length: 20, height: 30, originOnCenter: false })
try {
const topology = await runtime.topology(shape, 0.05)
const analyticFaces = topology.entries.filter((entry) => entry.ref.kind === 'face' && entry.signature.analytic?.type === 'Plane').length
const analyticEdges = topology.entries.filter((entry) => entry.ref.kind === 'edge' && entry.signature.analytic?.type === 'Line').length
const adjacency = topology.adjacency
const opfsTopologyRoundTrip = await persistTopologyInOpfs(topology)
report.topology = {
faces: topology.faces.length,
edges: topology.edges.length,
vertices: topology.vertices.length,
analyticFaces,
analyticEdges,
adjacencyKeys: adjacency ? Object.values(adjacency).map((map) => Object.keys(map).length) : [],
transientIndexFree: topology.entries.every((entry) => !/index|faceIndex|edgeIndex|vertexIndex/i.test(entry.ref.persistentId)),
opfsTopologyRoundTrip,
}
report.status = report.crossOriginIsolated && report.capabilities.status === 'ready' && topology.faces.length === 6 && topology.edges.length === 12 && topology.vertices.length === 8 && analyticFaces === 6 && analyticEdges === 12 && adjacency && Object.values(adjacency).every((map) => Object.keys(map).length > 0) && report.topology.transientIndexFree && opfsTopologyRoundTrip ? 'pass' : 'failed'
} finally {
await runtime.release(shape)
runtime.dispose()
}
} catch (error) {
report.status = 'failed'
report.error = error instanceof Error ? error.message : String(error)
}
output.textContent = JSON.stringify(report)
await fetch('/__topology-report', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(report) })
if (report.status !== 'pass') throw new Error(report.error || 'Chrome topology harness failed.')
</script>