Files
Web_FreeCAD_Bitbybit/public/chrome-native-hole-history-harness.html

29 lines
5.2 KiB
HTML

<!doctype html>
<meta charset="utf-8">
<title>Chrome native Hole history harness</title>
<pre id="result">running</pre>
<script type="module">
import { BitbybitGeometryRuntime } from '/src/facade/geometryRuntime.ts'
import { NativeOcctHistoryWorkerProvider } from '/src/facade/nativeHistoryWorkerClient.ts'
const output = document.querySelector('#result')
const report = { schemaVersion: 1, browserId: 'chrome', executionContext: 'geometry-and-history-workers', crossOriginIsolated: globalThis.crossOriginIsolated === true, status: 'running' }
let runtime, provider, base, tool, result
try {
runtime = new BitbybitGeometryRuntime(); const capabilities = await runtime.initialize()
provider = new NativeOcctHistoryWorkerProvider({ moduleUrl: '/native/occt-history/bitbybit-occt-history.js' }); const nativeCapabilities = await provider.initialize(); runtime.configureNativeHistory(provider)
const context = { documentId: 'chrome-native-hole', documentVersion: 1 }
base = await runtime.createBox({ ...context, width: 10, length: 10, height: 10, center: [0, 0, 0], originOnCenter: true })
tool = await runtime.createCylinder({ ...context, radius: 1, height: 10, center: [0, 0, -5], direction: [0, 0, 1] })
result = await runtime.cut({ ...context, base, tools: [tool] })
const [quality, mass] = await Promise.all([runtime.qualityReport(result), runtime.massProperties(result)])
const markerDirectory = await navigator.storage.getDirectory(); const markerName = 'native-hole-history-chrome-marker.json'; const marker = await markerDirectory.getFileHandle(markerName, { create: true }); const writable = await marker.createWritable(); await writable.write(JSON.stringify({ operation: 'hole', provider: nativeCapabilities.providerId })); await writable.close(); const markerText = await (await marker.getFile()).text()
const records = await runtime.topologyHistory({ ...context, operationId: 'chrome-native-hole-history', operation: 'hole', radius: 1, depth: 10, position: [0, 0, -5], direction: [0, 0, 1], inputs: [{ objectId: 'Base', shape: base }], result })
const stageCaptures = records.stageCaptures || []
const relations = { modified: records.filter((record) => record.relation === 'modified').length, generated: records.filter((record) => record.relation === 'generated').length, deleted: records.filter((record) => record.relation === 'deleted').length }
report.capabilities = capabilities; report.nativeCapabilities = nativeCapabilities; report.history = { recordCount: records.length, relations, sourceObjects: [...new Set(records.map((record) => record.sourceObjectId))], stages: stageCaptures.map((stage) => ({ stageId: stage.stageId, operation: stage.operation, inputObjectIds: stage.inputObjectIds, resultObjectId: stage.resultObjectId, ordinal: stage.ordinal, topologyEntries: stage.topology.entries.length, recordCount: stage.records.length })), sourceStageIds: [...new Set(records.map((record) => record.sourceStageId).filter(Boolean))], resultStageIds: [...new Set(records.map((record) => record.resultStageId).filter(Boolean))] }; report.result = { structuralValid: quality.structuralValid, solids: quality.solids, volume: mass.volume }; report.opfs = { markerCreated: true, markerSuite: JSON.parse(markerText).operation, markerRemoved: false }; await markerDirectory.removeEntry(markerName); report.opfs.markerRemoved = true
await runtime.release(result); result = undefined; await runtime.release(tool); tool = undefined; await runtime.release(base); base = undefined; report.afterRelease = { shapeCount: runtime.capabilities().shapeCount, kernelReferenceCount: runtime.capabilities().kernelReferenceCount }
report.status = report.crossOriginIsolated && capabilities.status === 'ready' && nativeCapabilities.availability === 'available' && nativeCapabilities.operations.includes('hole') && records.length > 0 && relations.modified > 0 && relations.deleted > 0 && stageCaptures.length === 2 && stageCaptures[0].operation === 'hole' && stageCaptures[0].inputObjectIds.length === 0 && stageCaptures[0].topology.entries.length > 0 && stageCaptures[1].operation === 'cut' && stageCaptures[1].inputObjectIds.join(',') === `Base,${stageCaptures[0].resultObjectId}` && stageCaptures[1].topology.entries.length > 0 && records.every((record) => record.resultStageId === stageCaptures[1].stageId) && quality.structuralValid && quality.solids === 1 && mass.volume > 0 && mass.volume < 1000 && report.opfs.markerSuite === 'hole' && report.opfs.markerRemoved && report.afterRelease.shapeCount === 0 && report.afterRelease.kernelReferenceCount === 0 ? 'pass' : 'failed'
} catch (error) { report.status = 'failed'; report.error = error instanceof Error ? `${error.name}: ${error.message}` : String(error) } finally { if (result) await runtime?.release(result).catch(() => {}); if (tool) await runtime?.release(tool).catch(() => {}); if (base) await runtime?.release(base).catch(() => {}); provider?.dispose(); runtime?.dispose() }
output.textContent = JSON.stringify(report, null, 2); await fetch('/__native-hole-history-report', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(report) }); if (report.status !== 'pass') throw new Error(report.error || 'Chrome native Hole history harness failed.')
</script>