Files
orca/config/scripts/ci/unit-selection/dependency-graph/ci-unit-indirect-inputs.mjs
Neil 9bd6272fdf refactor(tooling): organize build, CI, and test owners (#38130)
* refactor(tooling): organize test runtime and maintenance owners

* test(tooling): preserve relocated runtime fixture dependency edges

* refactor(tooling): preserve xterm routing owner checks

* ci(tooling): include routing owner in sparse checkout

* test(tooling): preserve copied workflow dependency closures

* fix(tooling): normalize hashed JSON assets in release parity

* fix(tooling): distinguish asset aliases from literal references

* fix(tooling): frame normalized asset reference payloads

* fix(tooling): normalize decoded JSON asset references

* refactor(tooling): organize build, CI and release owners

* fix(tooling): align moved generator and workflow path contracts

* fix(tooling): update generated plugin bundle owner banners

* test(tooling): create relocated mobile verifier fixture directories

* test(tooling): copy headless detector dependency closure

* test(tooling): align native batch policy fixtures with owner path

* fix(tooling): link moved reliability command to historical evidence

* fix(tooling): preserve nested sandbox owners and canonical guide source

* fix(tooling): target release version owners in checkout fixture
2026-11-04 21:08:19 -08:00

89 lines
2.7 KiB
JavaScript

import ts from 'typescript-api'
import {
literalString,
propertyName,
unwrap
} from '../../../static-analysis/module-requests/static-module-specifiers.mjs'
const INDIRECT_NAME =
/^(?:readFile\w*|readdir\w*|glob(?:Sync|Stream|Iterate|SyncIterate|StreamSync)?|spawn(?:Sync)?|execFile(?:Sync)?|execSync|runProcess\w*|fork|Worker|createRequire|getBuiltinModule|create(?:Incremental|Watch|EmitAndSemanticDiagnosticsBuilder|SemanticDiagnosticsBuilder)?Program|createSolutionBuilder(?:WithWatch)?|createLanguageService|getParsedCommandLineOfConfigFile|parseJson(?:SourceFile)?ConfigFileContent|readConfigFile|resolveModuleName|resolveTypeReferenceDirective|readDirectory|eval|Function)$/
const INDIRECT_CANDIDATE = new RegExp(
`\\b${INDIRECT_NAME.source.slice(1, -1)}\\b|\\b(?:import|require)\\s*\\(|\\bURL\\b`
)
const INDIRECT_MODULES = new Set([
'fs',
'node:fs',
'fs/promises',
'node:fs/promises',
'module',
'node:module',
'child_process',
'node:child_process',
'worker_threads',
'node:worker_threads',
'vm',
'node:vm',
'glob',
'fast-glob',
'globby',
'tinyglobby'
])
export function hasIndirectUnitInputs(file, contents, imports) {
if (file.endsWith('.json')) {
return false
}
if (imports.some(({ fileName }) => INDIRECT_MODULES.has(fileName))) {
return true
}
if (!INDIRECT_CANDIDATE.test(contents)) {
return false
}
const source = ts.createSourceFile(file, contents, ts.ScriptTarget.Latest, false)
if (source.parseDiagnostics.length > 0) {
return true
}
function visit(node) {
if (
ts.isTypeNode(node) ||
ts.isInterfaceDeclaration(node) ||
ts.isTypeAliasDeclaration(node) ||
((ts.isImportClause(node) ||
ts.isImportSpecifier(node) ||
ts.isExportDeclaration(node) ||
ts.isExportSpecifier(node)) &&
node.isTypeOnly)
) {
return false
}
if (ts.isIdentifier(node) && INDIRECT_NAME.test(node.text)) {
return true
}
if (ts.isElementAccessExpression(node) && INDIRECT_NAME.test(propertyName(node) ?? '')) {
return true
}
if (ts.isCallExpression(node)) {
const callee = unwrap(node.expression)
if (
(callee.kind === ts.SyntaxKind.ImportKeyword ||
(ts.isIdentifier(callee) && callee.text === 'require')) &&
literalString(node.arguments[0]) === null
) {
return true
}
}
if (
ts.isNewExpression(node) &&
ts.isIdentifier(node.expression) &&
node.expression.text === 'URL'
) {
const url = literalString(node.arguments?.[0])
if (url === null || !/^(?:https?|wss?):/.test(url)) {
return true
}
}
return ts.forEachChild(node, visit) ?? false
}
return visit(source)
}