Last active
October 30, 2024 17:39
-
-
Save jthemphill/5365b67cad46f837578e4d10c1a9528e to your computer and use it in GitHub Desktop.
Figure out which files are causing `babel-plugin-react-compiler` to output bad code and crash Vite's Rollup build
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio | |
import sys | |
import typing | |
""" | |
vite.config.ts has these lines: | |
function djb2Hash(str: string): number { | |
let hash = 5381 | |
for (let i = 0; i < str.length; i++) { | |
hash = (hash * 33) ^ str.charCodeAt(i) | |
} | |
return hash >>> 0 // Ensure positive integer | |
} | |
const NUMERATOR = 41 | |
const DENOMINATOR = 256 | |
""" | |
def write_constants(numerator: int, denominator: int) -> None: | |
with open("vite_config/vite.config.ts") as f: | |
lines = f.readlines() | |
for i, line in enumerate(lines): | |
if "const NUMERATOR" in line: | |
lines[i] = f"const NUMERATOR = {numerator}\n" | |
elif "const DENOMINATOR" in line: | |
lines[i] = f"const DENOMINATOR = {denominator}\n" | |
with open("vite_config/vite.config.ts", "w") as f: | |
f.writelines(lines) | |
SUCCESS_MESSAGE = 'Export "ConfigConsumer" of module' | |
FAILURE_MESSAGE = "ENOENT" | |
async def forward_stream( | |
input_stream: asyncio.StreamReader, | |
output_stream: typing.IO[str], | |
) -> None: | |
"""Forward a subprocess stream to one of our output streams.""" | |
while not input_stream.at_eof(): | |
line_bytes = await input_stream.readline() | |
line = line_bytes.decode() | |
output_stream.write(line) | |
output_stream.flush() | |
async def forward_and_parse_stream( | |
input_stream: asyncio.StreamReader, | |
output_stream: typing.IO[str], | |
) -> bool: | |
"""Process stderr and look for signs of success or failure. | |
Return True if we see a line indicating successful startup. | |
Return False if we see an error message. | |
""" | |
success: typing.Optional[bool] = None | |
while True: | |
line_bytes = await input_stream.readline() | |
line = line_bytes.decode() | |
# Forward each line of the process's stdout to our stdout | |
output_stream.write(line) | |
output_stream.flush() | |
# Look for messages which indicate success or failure | |
if success is None: | |
if SUCCESS_MESSAGE in line: | |
success = True | |
elif FAILURE_MESSAGE in line: | |
success = False | |
if success is not None: | |
return success | |
async def run_build( | |
stdout: typing.IO[str], | |
stderr: typing.IO[str], | |
) -> bool: | |
process = await asyncio.create_subprocess_exec( | |
"/opt/homebrew/bin/pnpm", | |
"vite:build", | |
stdout=asyncio.subprocess.PIPE, | |
stderr=asyncio.subprocess.PIPE, | |
) | |
assert process.stdout is not None | |
assert process.stderr is not None | |
stdout_forward = asyncio.create_task(forward_stream(process.stdout, stdout)) | |
success = await forward_and_parse_stream(process.stderr, stderr) | |
process.terminate() | |
await process.wait() | |
await stdout_forward | |
return success | |
async def bisect(): | |
nmodules = 27218 | |
numerator = 41 | |
denominator = 128 | |
# numerator = 297 | |
# denominator = 512 | |
with open("stdout.txt", "w") as stdout: | |
with open("stderr.txt", "w") as stderr: | |
while denominator < nmodules * 2: | |
write_constants(numerator, denominator) | |
print(f"jeff running: {numerator}/{denominator}...") | |
success = await run_build(stdout, stderr) | |
status_emoji = "✅" if success else "❌" | |
print(f"jeff result: {numerator}/{denominator}: {status_emoji}") | |
if success: | |
numerator += denominator // 2 | |
numerator = numerator % denominator | |
else: | |
denominator *= 2 | |
if __name__ == "__main__": | |
asyncio.run(bisect()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment