rsnext/bench/nested-deps/fuzzponent.js
hiro a00268e70f
Fix typos (#35683)
* fix(typo): wolrd -> world

* fix(typo): _lineNumer -> _lineNumber

* fix(typo): Dyanmic -> Dynamic

* fix(typo): mutliple -> multiple

* fix(typo): dyanmic -> dynamic

* fix(typo): speical -> special

* fix(typo): acceptible -> acceptable

* fix(typo): dyanmic -> dynamic

* fix(typo): nonexistant -> nonexistent

* fix(typo): nonexistant -> nonexistent

* fix(typo): nonexistant -> nonexistent

* fix(typo): nonexistant -> nonexistent

* fix(typo): nonexistant -> nonexistent

* fix(typo): nonexistant -> nonexistent

* fix(typo): accesible -> accessible

* fix(typo): explicitely -> explicitly
2022-03-28 22:53:51 -05:00

182 lines
5.1 KiB
JavaScript
Executable file

#!/usr/bin/env node
const path = require('path')
const fs = require('fs')
const getSequenceGenerator = require('random-seed')
const generate = require('@babel/generator').default
const t = require('@babel/types')
const MIN_COMPONENT_NAME_LEN = 18
const MAX_COMPONENT_NAME_LEN = 24
const MIN_CHILDREN = 4
const MAX_CHILDREN = 80
const arrayUntil = (len) => [...Array(len)].map((_, i) => i)
const generateFunctionalComponentModule = (componentName, children = []) => {
const body = [
generateImport('React', 'react'),
...children.map((childName) => generateImport(childName, `./${childName}`)),
t.variableDeclaration('const', [
t.variableDeclarator(
t.identifier(componentName),
t.arrowFunctionExpression(
[],
t.parenthesizedExpression(
generateJSXElement(
'div',
children.map((childName) => generateJSXElement(childName))
)
)
)
),
]),
t.exportDefaultDeclaration(t.identifier(componentName)),
]
return t.program(body, [], 'module')
}
const generateJSXElement = (componentName, children = null) =>
t.JSXElement(
t.JSXOpeningElement(t.JSXIdentifier(componentName), [], !children),
children ? t.JSXClosingElement(t.JSXIdentifier(componentName)) : null,
children || [],
!children
)
const generateImport = (componentName, requireString) =>
t.importDeclaration(
[t.importDefaultSpecifier(t.identifier(componentName))],
t.stringLiteral(requireString)
)
const validFirstChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
const validOtherChars = validFirstChars.toLowerCase()
function generateComponentName(seqGenerator, opts) {
const numOtherChars = seqGenerator.intBetween(opts.minLen, opts.maxLen)
const firstChar = validFirstChars[seqGenerator.range(validFirstChars.length)]
const otherChars = arrayUntil(numOtherChars).map(
() => validOtherChars[seqGenerator.range(validOtherChars.length)]
)
return `${firstChar}${otherChars.join('')}`
}
function* generateModules(name, remainingDepth, seqGenerator, opts) {
const filename = `${name}.${opts.extension}`
let ast
if (name === 'index') {
name = 'RootComponent'
}
if (remainingDepth === 0) {
ast = generateFunctionalComponentModule(name)
} else {
const numChildren = seqGenerator.intBetween(opts.minChild, opts.maxChild)
const children = arrayUntil(numChildren).map(() =>
generateComponentName(seqGenerator, opts)
)
ast = generateFunctionalComponentModule(name, children)
for (const child of children) {
yield* generateModules(child, remainingDepth - 1, seqGenerator, opts)
}
}
yield {
filename,
content: generate(ast).code,
}
}
function generateFuzzponents(outdir, seed, depth, opts) {
const seqGenerator = getSequenceGenerator(seed)
const filenames = new Set()
for (const { filename, content } of generateModules(
'index',
depth,
seqGenerator,
opts
)) {
if (filenames.has(filename)) {
throw new Error(
`Seed "${seed}" generates output with filename collisions.`
)
} else {
filenames.add(filename)
}
const fpath = path.join(outdir, filename)
fs.writeFileSync(fpath, `// ${filename}\n\n${content}`)
}
}
if (require.main === module) {
const { outdir, seed, depth, ...opts } = require('yargs')
.option('depth', {
alias: 'd',
demandOption: true,
describe: 'component hierarchy depth',
type: 'number',
})
.option('seed', {
alias: 's',
demandOption: true,
describe: 'prng seed',
type: 'number',
})
.option('outdir', {
alias: 'o',
demandOption: false,
default: process.cwd(),
describe: 'the directory where components should be written',
type: 'string',
normalize: true,
})
.option('minLen', {
demandOption: false,
default: MIN_COMPONENT_NAME_LEN,
describe: 'the smallest acceptable component name length',
type: 'number',
})
.option('maxLen', {
demandOption: false,
default: MAX_COMPONENT_NAME_LEN,
describe: 'the largest acceptable component name length',
type: 'number',
})
.option('minLen', {
demandOption: false,
default: MIN_COMPONENT_NAME_LEN,
describe: 'the smallest acceptable component name length',
type: 'number',
})
.option('maxLen', {
demandOption: false,
default: MAX_COMPONENT_NAME_LEN,
describe: 'the largest acceptable component name length',
type: 'number',
})
.option('minChild', {
demandOption: false,
default: MIN_CHILDREN,
describe: 'the smallest number of acceptable component children',
type: 'number',
})
.option('maxChild', {
demandOption: false,
default: MAX_CHILDREN,
describe: 'the largest number of acceptable component children',
type: 'number',
})
.option('extension', {
default: 'jsx',
describe: 'extension to use for generated components',
type: 'string',
}).argv
generateFuzzponents(outdir, seed, depth, opts)
}
module.exports = generateFuzzponents