async function inlineFs(code, filepath) {
  // Approach:
  // - scan `code` for fs methods
  // - parse only the expression at each found index
  // - statically evaluate arguments to fs method, collapsing to single string
  // - execute fs method with computed argument
  // - replace original expression with result of fs call
  // - if an expression cannot be parsed or statically evaluated, warn and skip
  // - if no expressions found or all are skipped, return null

  const fsSearch = /fs\.(?:readFileSync|readdirSync)\(/g;
  const foundIndices = [...code.matchAll(fsSearch)].map(e => e.index);

  // Return null for not-applicable files with as little work as possible.
  if (foundIndices.length === 0) return {code: null, warnings: []};

  const output = new MagicString(code);
  let madeChange = false;
  /** @type {Array<Warning>} */
  const warnings = [];

  // Can iterate forwards in string because MagicString always uses original indices.
  for (const foundIndex of foundIndices) {
    if (foundIndex === undefined) continue; // https://github.com/microsoft/TypeScript/issues/36788

    let parsed;
    try {
      parsed = parseExpressionAt(code, foundIndex, {ecmaVersion: 'latest'});
    } catch (err) {
      // `err.loc` added by acorn.
      warnings.push(createWarning(err, filepath, err.loc));
      continue;
    }

    // If root of expression isn't the fs call, descend down chained methods on
    // the result (e.g. `fs.readdirSync().map(...)`) until reaching the fs call.
    for (;;) {
      assertEqualString(parsed.type, 'CallExpression');
      assertEqualString(parsed.callee.type, 'MemberExpression');
      if (parsed.callee.object.type === 'Identifier' && parsed.callee.object.name === 'fs') {
        break;
      }
      parsed = parsed.callee.object;
    }

    // We've regexed for an fs method, so the property better be an identifier.
    assertEqualString(parsed.callee.property.type, 'Identifier');

    let content;
    try {
      if (parsed.callee.property.name === 'readFileSync') {
        content = await getReadFileReplacement(parsed, filepath);
      } else if (parsed.callee.property.name === 'readdirSync') {
        content = await getReaddirReplacement(parsed, filepath);
      } else {
        throw new AstError(`unexpected fs call 'fs.${parsed.callee.property.name}'`,
            parsed.callee.property);
      }
    } catch (err) {
      // Consider missing files to be a fatal error.
      if (err.code === 'ENOENT') {
        throw err;
      }

      // Use the specific node with the error if available; fallback to fs.method location.
      const offsets = getNodeOffsets(err.node || parsed);
      const location = acorn.getLineInfo(code, offsets.start);

      warnings.push(createWarning(err, filepath, location));
      continue;
    }

    const offsets = getNodeOffsets(parsed);
    // TODO(bckenny): use options to customize `storeName` for source maps.
    output.overwrite(offsets.start, offsets.end, content);
    madeChange = true;
  }

  // Be explicit if no change has been made.
  const outputCode = madeChange ? output.toString() : null;

  return {
    code: outputCode,
    warnings,
  };
}
Inlines the values of selected `fs` methods if their targets can be
statically determined. Currently `readFileSync` and `readdirSync` are
supported.
Returns `null` as code if no changes were made.
@param {string} code
@param {string} filepath
@return {Promise<{code: string|null, warnings: Array<Warning>}>}