Files
ycode/scripts/rea/recover-tool-virtualizer.mjs
T

529 lines
23 KiB
JavaScript

import { createHash } from 'node:crypto'
import fs from 'node:fs/promises'
import path from 'node:path'
import { parse } from '@babel/parser'
import traverseModule from '@babel/traverse'
import generatorModule from '@babel/generator'
const EVIDENCE_PATH = '.tmp/rea-runtime-scripts.json'
const OUTPUT_DIRECTORY = path.resolve('src/renderer/src/workbuddy/conversation/recovered-virtualizer')
const EXPECTED_EVIDENCE_ID = 'ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb'
const EXPECTED_EXPORT_SHA256 = '747e41d215375e1214c366213aea7e077d85421923029c61cbb6e9562be58de0'
const EXPECTED_MAIN_SHA256 = '6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4'
const EXPECTED_EXPORT_PATH = './src-DPDj7_qD.js'
const EXPECTED_ROOT_SHA256 = '035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918'
const IMPORT_ADAPTERS = new Map([
['./rolldown-runtime-BJCASTsb.js', new Map([
['n', '__esmMin'],
['o', '__toESM'],
])],
['./react-z__Ncn__.js', new Map([['t', 'React namespace']])],
['./react-dom-mnR6psRT.js', new Map([['t', 'ReactDOM namespace']])],
])
const traverse = traverseModule.default
const generate = generatorModule.default ?? generatorModule
const sha256 = value => createHash('sha256').update(value).digest('hex')
const fail = message => { throw new Error(message) }
function collectPatternNames(node, names = []) {
if (!node) return names
if (node.type === 'Identifier') names.push(node.name)
else if (node.type === 'RestElement') collectPatternNames(node.argument, names)
else if (node.type === 'AssignmentPattern') collectPatternNames(node.left, names)
else if (node.type === 'ArrayPattern') node.elements.forEach(entry => collectPatternNames(entry, names))
else if (node.type === 'ObjectPattern') {
for (const property of node.properties) {
if (property.type === 'RestElement') collectPatternNames(property.argument, names)
else collectPatternNames(property.value, names)
}
}
return names
}
function closeBindings(source, rootNames, { includeImports = false } = {}) {
const ast = parse(source, { sourceType: 'module' })
let programPath
traverse(ast, {
Program(pathRef) {
programPath = pathRef
pathRef.scope.crawl()
pathRef.stop()
},
})
const included = new Map()
const queue = []
const imported = new Map()
const enqueue = binding => {
if (!binding || binding.scope !== programPath.scope || included.has(binding.identifier.name)) return
included.set(binding.identifier.name, binding)
queue.push(binding)
}
const visitReferences = pathRef => pathRef.traverse({
Identifier(reference) {
if (!reference.isReferencedIdentifier() && !reference.isBindingIdentifier()) return
enqueue(reference.scope.getBinding(reference.node.name))
},
})
for (const rootName of rootNames) {
const root = programPath.scope.getBinding(rootName)
if (!root || root.kind === 'module') fail(`Missing program binding: ${rootName}`)
enqueue(root)
}
while (queue.length > 0) {
const binding = queue.shift()
if (binding.kind === 'module') {
const declaration = binding.path.findParent(candidate => candidate.isImportDeclaration())
if (!declaration) fail(`Cannot locate import for ${binding.identifier.name}`)
const names = imported.get(declaration.node.source.value) ?? new Set()
names.add(binding.identifier.name)
imported.set(declaration.node.source.value, names)
continue
}
if (binding.path.isFunctionDeclaration() || binding.path.isClassDeclaration()) {
visitReferences(binding.path)
continue
}
if (!binding.path.isVariableDeclarator()) continue
if (binding.path.node.init) visitReferences(binding.path.get('init'))
else {
for (const violation of binding.constantViolations) {
visitReferences(violation)
const owner = violation.findParent(candidate => candidate.isVariableDeclarator())
if (owner && owner !== binding.path && owner.node.id.type === 'Identifier') {
enqueue(programPath.scope.getBinding(owner.node.id.name))
}
}
}
}
const importRecords = []
const declarationChunks = []
const isRolldownModuleInitializer = binding => {
if (!binding || !binding.path.isVariableDeclarator()) return false
const initializer = binding.path.node.init
if (initializer?.type !== 'CallExpression' || initializer.callee.type !== 'Identifier') return false
const helperBinding = programPath.scope.getBinding(initializer.callee.name)
if (helperBinding?.kind !== 'module') return false
const helperDeclaration = helperBinding.path.findParent(candidate => candidate.isImportDeclaration())
if (!helperDeclaration || helperDeclaration.node.source.value !== './rolldown-runtime-BJCASTsb.js') return false
return helperBinding.path.node.imported?.name === 'n'
}
const initializerBindings = [...included.entries()]
.filter(([, binding]) => isRolldownModuleInitializer(binding))
const nestedInitializers = new Set()
for (const [, binding] of initializerBindings) {
const initializer = binding.path.get('init').get('arguments.0')
if (!initializer?.node || (!initializer.isArrowFunctionExpression() && !initializer.isFunctionExpression())) continue
initializer.traverse({
Function(pathRef) { pathRef.skip() },
CallExpression(pathRef) {
const callee = pathRef.node.callee
if (callee.type === 'Identifier' && initializerBindings.some(([name]) => name === callee.name)) {
nestedInitializers.add(callee.name)
}
},
})
}
const initializationCalls = initializerBindings
.map(([name]) => name)
.filter(name => !nestedInitializers.has(name))
.sort()
for (const statement of ast.program.body) {
if (statement.type === 'ImportDeclaration') {
const names = imported.get(statement.source.value)
if (!names || names.size === 0) continue
const specifiers = statement.specifiers.filter(specifier => names.has(specifier.local.name))
for (const specifier of specifiers) {
importRecords.push({
source: statement.source.value,
local: specifier.local.name,
imported: specifier.type === 'ImportSpecifier'
? specifier.imported.name ?? specifier.imported.value
: 'default',
})
}
if (!includeImports) continue
const parts = []
const defaultImport = specifiers.find(specifier => specifier.type === 'ImportDefaultSpecifier')
const namespaceImport = specifiers.find(specifier => specifier.type === 'ImportNamespaceSpecifier')
const namedImports = specifiers.filter(specifier => specifier.type === 'ImportSpecifier')
if (defaultImport) parts.push(defaultImport.local.name)
if (namespaceImport) parts.push(`* as ${namespaceImport.local.name}`)
if (namedImports.length > 0) {
parts.push(`{ ${namedImports.map(specifier => {
const importedName = specifier.imported.name ?? specifier.imported.value
return importedName === specifier.local.name ? importedName : `${importedName} as ${specifier.local.name}`
}).join(', ')} }`)
}
declarationChunks.push(`import ${parts.join(', ')} from ${JSON.stringify(statement.source.value)};`)
continue
}
if (statement.type === 'VariableDeclaration') {
for (const declaration of statement.declarations) {
const names = collectPatternNames(declaration.id)
if (names.some(name => included.has(name))) {
declarationChunks.push(`${statement.kind} ${source.slice(declaration.start, declaration.end)};`)
}
}
continue
}
if ((statement.type === 'FunctionDeclaration' || statement.type === 'ClassDeclaration') &&
included.has(statement.id?.name)) {
declarationChunks.push(source.slice(statement.start, statement.end))
continue
}
}
declarationChunks.push(...initializationCalls.map(name => `${name}();`))
return {
code: declarationChunks.join('\n'),
bindingNames: [...included.keys()].sort(),
imports: importRecords.sort((left, right) => left.source.localeCompare(right.source) || left.local.localeCompare(right.local)),
initializationCalls,
}
}
function renameProgramBindings(source, prefix) {
const ast = parse(source, { sourceType: 'module' })
let programPath
traverse(ast, {
Program(pathRef) {
programPath = pathRef
pathRef.scope.crawl()
pathRef.stop()
},
})
const renamed = new Map()
let index = 0
for (const name of Object.keys(programPath.scope.bindings)) {
const binding = programPath.scope.getBinding(name)
if (!binding || binding.kind === 'module') continue
const newName = `${prefix}${name.replace(/[^A-Za-z0-9_$]/gu, '_')}_${index++}`
programPath.scope.rename(name, newName)
renamed.set(name, newName)
}
return { source: generate(ast, { comments: false, compact: true }).code, renamed }
}
function getProperty(objectNode, key) {
return objectNode?.type === 'ObjectExpression'
? objectNode.properties.find(property => property.type === 'ObjectProperty' &&
(property.key.name ?? property.key.value) === key)?.value
: undefined
}
function readNumber(node, programScope) {
if (node?.type === 'NumericLiteral') return node.value
if (node?.type === 'Identifier') {
const binding = programScope.getBinding(node.name)
const init = binding?.path.isVariableDeclarator() ? binding.path.node.init : undefined
if (init?.type === 'NumericLiteral') return init.value
const assignment = binding?.constantViolations.find(violation =>
violation.isAssignmentExpression() && violation.node.left.type === 'Identifier' &&
violation.node.left.name === node.name)
if (assignment?.node.right.type === 'NumericLiteral') return assignment.node.right.value
}
return undefined
}
function verifySourceAnchor(mainSource) {
const ast = parse(mainSource, { sourceType: 'module' })
let programPath
traverse(ast, {
Program(pathRef) {
programPath = pathRef
pathRef.scope.crawl()
pathRef.stop()
},
})
const alias = programPath.scope.getBinding('Ae')
const importDeclaration = alias?.path.findParent(candidate => candidate.isImportDeclaration())
if (!importDeclaration || importDeclaration.node.source.value !== EXPECTED_EXPORT_PATH ||
alias.path.node.imported?.name !== 'tt') {
fail('Main REA source no longer maps Ae to the selected useVirtualizer export')
}
const component = programPath.scope.getBinding('aE')
if (!component) fail('Could not find the original aE SourceToolDiff component binding')
const componentAssignments = component.constantViolations.filter(violation =>
violation.isAssignmentExpression() && violation.node.left.type === 'Identifier' && violation.node.left.name === 'aE')
if (componentAssignments.length !== 1) fail(`Expected one aE component assignment, found ${componentAssignments.length}`)
const calls = alias.referencePaths.filter(reference => {
const call = reference.parentPath
return call.isCallExpression() && call.node.callee === reference.node &&
call.node.start >= componentAssignments[0].node.start && call.node.end <= componentAssignments[0].node.end
})
if (calls.length !== 1) fail(`Expected one aE useVirtualizer call, found ${calls.length}`)
const options = calls[0].parentPath.node.arguments[0]
const initialRect = getProperty(options, 'initialRect')
const width = readNumber(getProperty(initialRect, 'width'), programPath.scope)
const height = readNumber(getProperty(initialRect, 'height'), programPath.scope)
const estimateSize = getProperty(options, 'estimateSize')
const estimate = estimateSize?.type === 'ArrowFunctionExpression'
? readNumber(estimateSize.body, programPath.scope)
: undefined
const overscan = readNumber(getProperty(options, 'overscan'), programPath.scope)
if (width !== 0 || height !== 260 || estimate !== 20 || overscan !== 12) {
fail(`Original virtualizer options differ from the requested contract: ${JSON.stringify({ width, height, estimate, overscan })}`)
}
return {
component: 'aE',
importedLocal: 'Ae',
exportedName: 'tt',
exportChunk: EXPECTED_EXPORT_PATH,
componentAssignmentOffsetUtf16: componentAssignments[0].node.start,
callOffsetUtf16: calls[0].node.start,
options: { initialRect: { width, height }, estimateSize: estimate, overscan },
}
}
function selectEvidenceArtifact(data, expected) {
const matches = data.items.filter(item => item.source?.artifact?.sha256 === expected.sha256)
if (matches.length !== 1) fail(`Expected one REA export for ${expected.fileName}, found ${matches.length}`)
const item = matches[0]
const text = item.source.artifact.text
const actualSha256 = sha256(text)
const bytes = Buffer.byteLength(text, 'utf8')
if (actualSha256 !== expected.sha256 || bytes !== expected.bytes || item.length !== expected.bytes) {
fail(`REA artifact identity mismatch for ${expected.fileName}`)
}
if (path.posix.basename(item.file_path.replace(/\\/gu, '/')) !== expected.fileName) {
fail(`REA Evidence path does not match expected ${expected.fileName}: ${item.file_path}`)
}
return {
text,
record: { path: item.file_path, fileName: expected.fileName, bytes, sha256: actualSha256 },
}
}
function resolveImportedAdapters(imports) {
const result = []
const seenSources = new Set()
for (const entry of imports) {
const adapters = IMPORT_ADAPTERS.get(entry.source)
if (!adapters) fail(`Recovered closure has an unapproved import: ${entry.source}`)
const adapter = adapters.get(entry.imported)
if (!adapter) fail(`No adapter for ${entry.source} export ${entry.imported}`)
if (entry.source.startsWith('./rolldown-runtime-')) {
result.push({ ...entry, adapter })
} else if (entry.source === './react-z__Ncn__.js' && entry.local === 'u' && entry.imported === 't') {
result.push({ ...entry, adapter: 'React namespace factory' })
} else if (entry.source === './react-dom-mnR6psRT.js' && entry.local === 'p' && entry.imported === 't') {
result.push({ ...entry, adapter: 'ReactDOM namespace factory' })
} else {
fail(`Unexpected adapter binding for ${entry.source}: ${entry.local} as ${entry.imported}`)
}
seenSources.add(entry.source)
}
for (const source of IMPORT_ADAPTERS.keys()) {
if (!seenSources.has(source)) fail(`Expected closure dependency was not found: ${source}`)
}
return result
}
async function writeGenerated(filePath, content, expectedKind) {
try {
const current = await fs.readFile(filePath, 'utf8')
if (current === content) return
const isGenerated = expectedKind === 'manifest'
? JSON.parse(current).kind === 'rea-recovered-tool-virtualizer'
: current.startsWith('// Generated by scripts/rea/recover-tool-virtualizer.mjs')
if (!isGenerated) fail(`Refusing to overwrite a non-generated artifact: ${filePath}`)
} catch (error) {
if (error.code !== 'ENOENT' && !(error instanceof SyntaxError)) throw error
if (error instanceof SyntaxError) fail(`Refusing to overwrite an invalid generated manifest: ${filePath}`)
}
await fs.writeFile(filePath, content, 'utf8')
}
const evidenceBytes = await fs.readFile(EVIDENCE_PATH)
const evidence = JSON.parse(evidenceBytes.toString('utf8'))
if (evidence.evidence_id !== EXPECTED_EVIDENCE_ID) fail(`Unexpected REA Evidence ID: ${evidence.evidence_id}`)
const [mainArtifact, virtualizerArtifact, runtimeArtifact, reactArtifact, reactDomArtifact] = [
selectEvidenceArtifact(evidence, {
fileName: 'src-DbE1_mgM.js',
sha256: EXPECTED_MAIN_SHA256,
bytes: 1968427,
}),
selectEvidenceArtifact(evidence, {
fileName: 'src-DPDj7_qD.js',
sha256: EXPECTED_EXPORT_SHA256,
bytes: 1062959,
}),
selectEvidenceArtifact(evidence, {
fileName: 'rolldown-runtime-BJCASTsb.js',
sha256: '318f798e3ab3fd684d64dce773065dd76581974fcf633e5d4a3f1d31cf9a7ef7',
bytes: 1413,
}),
selectEvidenceArtifact(evidence, {
fileName: 'react-z__Ncn__.js',
sha256: '43f15c3eca4613e6a3ff249303f3807e326f02d3f0f3cec5e1ce77caa4c21509',
bytes: 6517,
}),
selectEvidenceArtifact(evidence, {
fileName: 'react-dom-mnR6psRT.js',
sha256: '68481241365522811081eecba169d0000151c884621657df3a6080a5213f17ce',
bytes: 133010,
}),
]
const exportAst = parse(virtualizerArtifact.text, { sourceType: 'module' })
let exportedUseVirtualizer = false
traverse(exportAst, {
Program(pathRef) {
for (const statement of pathRef.node.body) {
if (statement.type !== 'ExportNamedDeclaration') continue
for (const specifier of statement.specifiers) {
if (specifier.local.name === 'useVirtualizer' && specifier.exported.name === 'tt') {
exportedUseVirtualizer = true
}
}
}
pathRef.stop()
},
})
if (!exportedUseVirtualizer) fail('The selected REA module does not export useVirtualizer as tt')
const anchor = verifySourceAnchor(mainArtifact.text)
const closure = closeBindings(virtualizerArtifact.text, ['useVirtualizer'])
if (closure.bindingNames.length !== 35 || !closure.bindingNames.includes('Virtualizer') ||
!closure.bindingNames.includes('calculateRangeImpl')) {
fail(`Unexpected virtualizer closure: ${closure.bindingNames.length} bindings`)
}
if (closure.initializationCalls.length === 0) fail('Virtualizer closure is missing its Rolldown module initialization call')
const importedAdapters = resolveImportedAdapters(closure.imports)
const rolldownClosure = closeBindings(runtimeArtifact.text, ['__esmMin', '__toESM'])
if (rolldownClosure.imports.length !== 0) fail('Rolldown helper closure unexpectedly imports another module')
const renamedRuntime = renameProgramBindings(rolldownClosure.code, '__ycodeRecoveredRolldown_')
const esmHelper = renamedRuntime.renamed.get('__esmMin')
const toEsmHelper = renamedRuntime.renamed.get('__toESM')
if (!esmHelper || !toEsmHelper) fail('Could not bind required Rolldown helpers')
const header = [
`// Generated by scripts/rea/recover-tool-virtualizer.mjs from REA Evidence ${EXPECTED_EVIDENCE_ID}.`,
`// Source: renderer/assets/src-DPDj7_qD.js; sha256: ${EXPECTED_EXPORT_SHA256}.`,
`import * as __ycodeReact from 'react';`,
`import * as __ycodeReactDOM from 'react-dom';`,
]
const adapters = [
`const r = ${esmHelper};`,
`const s = ${toEsmHelper};`,
`const u = () => __ycodeReact;`,
`const p = () => __ycodeReactDOM;`,
]
const exports = `export { useVirtualizer as useRecoveredToolVirtualizer, Virtualizer as RecoveredVirtualizer };`
const engine = `${header.join('\n')}\n${renamedRuntime.source}\n${adapters.join('\n')}\n${closure.code}\n${exports}\n`
const engineAst = parse(engine, { sourceType: 'module' })
const outputImports = engineAst.program.body
.filter(statement => statement.type === 'ImportDeclaration')
.map(statement => statement.source.value)
.sort()
if (JSON.stringify(outputImports) !== JSON.stringify(['react', 'react-dom'])) {
fail(`Recovered engine has unexpected imports: ${JSON.stringify(outputImports)}`)
}
const declarations = `// Generated by scripts/rea/recover-tool-virtualizer.mjs; source is locked to REA Evidence ${EXPECTED_EVIDENCE_ID}.\n` +
`import type { RefCallback } from 'react'\n` +
`export interface RecoveredVirtualItem { index: number; key: string | number; start: number; size: number; end: number; lane: number }\n` +
`export interface RecoveredVirtualizerOptions { count: number; getScrollElement: () => Element | Window | null; estimateSize: (index: number) => number; overscan?: number; initialRect?: { width: number; height: number }; initialOffset?: number; [key: string]: unknown }\n` +
`export interface RecoveredVirtualizerInstance { getVirtualItems(): RecoveredVirtualItem[]; getTotalSize(): number; measureElement: RefCallback<HTMLDivElement> }\n` +
`export declare function useRecoveredToolVirtualizer(options: RecoveredVirtualizerOptions): RecoveredVirtualizerInstance\n` +
`export declare class RecoveredVirtualizer { constructor(options: RecoveredVirtualizerOptions); scrollOffset: number | null; getVirtualItems(): RecoveredVirtualItem[]; getTotalSize(): number; setOptions(options: RecoveredVirtualizerOptions): void }\n`
await fs.mkdir(OUTPUT_DIRECTORY, { recursive: true })
const outputPaths = {
engine: path.join(OUTPUT_DIRECTORY, 'index.mjs'),
declarations: path.join(OUTPUT_DIRECTORY, 'index.d.mts'),
manifest: path.join(OUTPUT_DIRECTORY, 'manifest.json'),
}
await writeGenerated(outputPaths.engine, engine, 'source')
await writeGenerated(outputPaths.declarations, declarations, 'source')
const outputArtifacts = []
for (const [kind, filePath] of Object.entries(outputPaths).filter(([kind]) => kind !== 'manifest')) {
const bytes = await fs.readFile(filePath)
outputArtifacts.push({ path: path.basename(filePath), kind, bytes: bytes.length, sha256: sha256(bytes) })
}
const manifest = {
kind: 'rea-recovered-tool-virtualizer',
target: {
name: 'WorkBuddy',
version: '5.8.2',
asar_sha256: EXPECTED_ROOT_SHA256,
},
evidence: {
evidence_id: evidence.evidence_id,
export_path: EVIDENCE_PATH,
export_bytes: evidenceBytes.length,
export_sha256: sha256(evidenceBytes),
selected_artifacts: [
mainArtifact.record,
virtualizerArtifact.record,
runtimeArtifact.record,
reactArtifact.record,
reactDomArtifact.record,
],
},
source_anchor: anchor,
recovered_export: {
local_binding: 'useVirtualizer',
exported_name: 'tt',
closure_binding_count: closure.bindingNames.length,
closure_bindings: closure.bindingNames,
rolldown_initialization_calls: closure.initializationCalls,
},
rolldown_runtime_closure: {
source_file: runtimeArtifact.record.fileName,
source_sha256: runtimeArtifact.record.sha256,
source_bindings: rolldownClosure.bindingNames,
renamed_bindings: Object.fromEntries(renamedRuntime.renamed),
restored_helpers: [
{ local: 'r', export: '__esmMin', binding: esmHelper },
{ local: 's', export: '__toESM', binding: toEsmHelper },
],
external_imports: [],
},
imports: {
original: importedAdapters,
output: outputImports,
unresolved: [],
},
transformations: [
'Babel Program scope closure started at the source binding useVirtualizer.',
'Included only declarations reachable from useVirtualizer and required Rolldown lazy-module initialization calls.',
'Recovered Rolldown __esmMin and __toESM helper closures and renamed their Program bindings to avoid collisions.',
'Rebound WorkBuddy React and ReactDOM module factories to the YCode react and react-dom package namespaces.',
'Excluded the WorkBuddy application entrypoint, UI components, and unrelated module initializers.',
'Exported the recovered useVirtualizer hook and its Virtualizer core class for the YCode view and focused regression.',
],
outputs: outputArtifacts,
limitations: [
'The source is locked to the selected WorkBuddy 5.8.2 runtime bundle; the original TanStack package version is not inferred or installed.',
'React and ReactDOM resolve to YCode package versions; exact React package version parity with WorkBuddy was not established by this hook recovery.',
'The focused regression verifies SSR initial ranges and core scroll ranges; full application interaction and pixel parity remain separate acceptance work.',
],
}
await writeGenerated(outputPaths.manifest, `${JSON.stringify(manifest, null, 2)}\n`, 'manifest')
console.log(JSON.stringify({
outputDirectory: OUTPUT_DIRECTORY,
evidenceId: evidence.evidence_id,
closureBindings: closure.bindingNames.length,
importedAdapters,
initializationCalls: closure.initializationCalls,
outputImports,
outputs: outputArtifacts,
manifest: outputPaths.manifest,
}, null, 2))