prepare-compiler.mjs (3227B)
1 // Trusted benchmark transport only. Authenticate and validate the site's bundle 2 // before converting to a compact DAG; this is not a public bundle loader. 3 import {readFile, writeFile, mkdir} from 'node:fs/promises'; 4 import {createHash} from 'node:crypto'; 5 import assert from 'node:assert/strict'; 6 import {pathToFileURL} from 'node:url'; 7 import path from 'node:path'; 8 const [site, output] = process.argv.slice(2); 9 const {decodeBundle, COMPILER_BUNDLE_LIMIT} = await import(pathToFileURL(path.resolve(site,'dist/bundle.js'))); 10 const {CONTRACT_BINDINGS} = await import(pathToFileURL(path.resolve(site,'dist/contracts.js'))); 11 const descriptor = JSON.parse(await readFile(path.join(site,'compiler.json'))); 12 const vectors = JSON.parse(await readFile(path.join(site,'test/compiler-conformance.json'))); 13 const bytes = await readFile(path.join(site,'bundles',descriptor.hash+'.arboricx')); 14 assert.equal(createHash('sha256').update(bytes).digest('hex'), descriptor.hash); 15 assert.equal(descriptor.hash,vectors.compilerBundleSha256); 16 assert.equal(descriptor.export,vectors.export); 17 const bundle = decodeBundle(bytes,COMPILER_BUNDLE_LIMIT); 18 const exports = new Map(bundle.exports.map(e=>[e.name,e.root])); 19 const root = exports.get(descriptor.export); assert.notEqual(root,undefined); 20 for (const name of ['sourceModuleHeaderStage','sourceModuleUseShape','sourceModuleExportShape','sourceModuleQualified']) { 21 assert.ok(exports.has('source_module.'+name), 'Missing native module compiler helper: '+name); 22 } 23 await mkdir(output,{recursive:true}); 24 const dag = Buffer.alloc(8+bundle.nodes.length*9); 25 dag.writeUInt32LE(bundle.nodes.length,0); dag.writeUInt32LE(root,4); 26 for (const [i,n] of bundle.nodes.entries()) { 27 const at=8+i*9; 28 dag[at]=n.kind==='leaf'?0:n.kind==='stem'?1:2; 29 dag.writeUInt32LE(n.kind==='stem'?n.child:n.kind==='fork'?n.left:0,at+1); 30 dag.writeUInt32LE(n.kind==='fork'?n.right:0,at+5); 31 } 32 await writeFile(path.join(output,'compiler.dag'),dag); 33 await writeFile(path.join(output,'compiler-exports.tsv'), [...exports].map(([name,root])=>`${name}\t${root}`).join('\n')+'\n'); 34 await writeFile(path.join(output,'environment.tsv'),Object.entries(CONTRACT_BINDINGS).map(([name,exported])=>{ 35 assert.ok(exports.has(exported)); return name+'\t'+exports.get(exported); 36 }).join('\n')+'\n'); 37 const cases=[]; 38 for (const [id,c] of vectors.cases.entries()) { 39 if(c.mode==='io')continue; // IO is a separate host-driver experiment. 40 const dir=path.join(output,String(id)); await mkdir(dir); 41 await writeFile(path.join(dir,'source'),c.source); 42 await writeFile(path.join(dir,'expected'),c.diagnostic ? 'error\n'+c.diagnostic+'\n' : 43 'ok\n'+Object.entries(c.definitions).map(([name,tree])=>name+'\t'+tree).join('\n')+'\n'); 44 await writeFile(path.join(dir,'run'),c.diagnostic?'': [c.export,c.result,...c.arguments].join('\n')+'\n'); 45 cases.push({id,source:c.source,diagnostic:c.diagnostic??null,extended:c.extended??false}); 46 } 47 await writeFile(path.join(output,'manifest.json'),JSON.stringify({compilerSha256:descriptor.hash, 48 goldenSha256:createHash('sha256').update(await readFile(path.join(site,'test/compiler-conformance.json'))).digest('hex'), 49 dagSha256:createHash('sha256').update(dag).digest('hex'),cases},null,2)+'\n');