11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  ArrayPrototypeForEach,
51cb0ef41Sopenharmony_ci  ArrayPrototypeIncludes,
61cb0ef41Sopenharmony_ci  ArrayPrototypeMap,
71cb0ef41Sopenharmony_ci  ArrayPrototypePush,
81cb0ef41Sopenharmony_ci  ArrayPrototypePushApply,
91cb0ef41Sopenharmony_ci  ArrayPrototypeShift,
101cb0ef41Sopenharmony_ci  ArrayPrototypeSlice,
111cb0ef41Sopenharmony_ci  ArrayPrototypeUnshiftApply,
121cb0ef41Sopenharmony_ci  ObjectEntries,
131cb0ef41Sopenharmony_ci  ObjectPrototypeHasOwnProperty: ObjectHasOwn,
141cb0ef41Sopenharmony_ci  StringPrototypeCharAt,
151cb0ef41Sopenharmony_ci  StringPrototypeIndexOf,
161cb0ef41Sopenharmony_ci  StringPrototypeSlice,
171cb0ef41Sopenharmony_ci  StringPrototypeStartsWith,
181cb0ef41Sopenharmony_ci} = require('./internal/primordials');
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciconst {
211cb0ef41Sopenharmony_ci  validateArray,
221cb0ef41Sopenharmony_ci  validateBoolean,
231cb0ef41Sopenharmony_ci  validateBooleanArray,
241cb0ef41Sopenharmony_ci  validateObject,
251cb0ef41Sopenharmony_ci  validateString,
261cb0ef41Sopenharmony_ci  validateStringArray,
271cb0ef41Sopenharmony_ci  validateUnion,
281cb0ef41Sopenharmony_ci} = require('./internal/validators');
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ciconst {
311cb0ef41Sopenharmony_ci  kEmptyObject,
321cb0ef41Sopenharmony_ci} = require('./internal/util');
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ciconst {
351cb0ef41Sopenharmony_ci  findLongOptionForShort,
361cb0ef41Sopenharmony_ci  isLoneLongOption,
371cb0ef41Sopenharmony_ci  isLoneShortOption,
381cb0ef41Sopenharmony_ci  isLongOptionAndValue,
391cb0ef41Sopenharmony_ci  isOptionValue,
401cb0ef41Sopenharmony_ci  isOptionLikeValue,
411cb0ef41Sopenharmony_ci  isShortOptionAndValue,
421cb0ef41Sopenharmony_ci  isShortOptionGroup,
431cb0ef41Sopenharmony_ci  useDefaultValueOption,
441cb0ef41Sopenharmony_ci  objectGetOwn,
451cb0ef41Sopenharmony_ci  optionsGetOwn,
461cb0ef41Sopenharmony_ci} = require('./utils');
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ciconst {
491cb0ef41Sopenharmony_ci  codes: {
501cb0ef41Sopenharmony_ci    ERR_INVALID_ARG_VALUE,
511cb0ef41Sopenharmony_ci    ERR_PARSE_ARGS_INVALID_OPTION_VALUE,
521cb0ef41Sopenharmony_ci    ERR_PARSE_ARGS_UNKNOWN_OPTION,
531cb0ef41Sopenharmony_ci    ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL,
541cb0ef41Sopenharmony_ci  },
551cb0ef41Sopenharmony_ci} = require('./internal/errors');
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_cifunction getMainArgs() {
581cb0ef41Sopenharmony_ci  // Work out where to slice process.argv for user supplied arguments.
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  // Check node options for scenarios where user CLI args follow executable.
611cb0ef41Sopenharmony_ci  const execArgv = process.execArgv;
621cb0ef41Sopenharmony_ci  if (ArrayPrototypeIncludes(execArgv, '-e') ||
631cb0ef41Sopenharmony_ci      ArrayPrototypeIncludes(execArgv, '--eval') ||
641cb0ef41Sopenharmony_ci      ArrayPrototypeIncludes(execArgv, '-p') ||
651cb0ef41Sopenharmony_ci      ArrayPrototypeIncludes(execArgv, '--print')) {
661cb0ef41Sopenharmony_ci    return ArrayPrototypeSlice(process.argv, 1);
671cb0ef41Sopenharmony_ci  }
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci  // Normally first two arguments are executable and script, then CLI arguments
701cb0ef41Sopenharmony_ci  return ArrayPrototypeSlice(process.argv, 2);
711cb0ef41Sopenharmony_ci}
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci/**
741cb0ef41Sopenharmony_ci * In strict mode, throw for possible usage errors like --foo --bar
751cb0ef41Sopenharmony_ci *
761cb0ef41Sopenharmony_ci * @param {object} token - from tokens as available from parseArgs
771cb0ef41Sopenharmony_ci */
781cb0ef41Sopenharmony_cifunction checkOptionLikeValue(token) {
791cb0ef41Sopenharmony_ci  if (!token.inlineValue && isOptionLikeValue(token.value)) {
801cb0ef41Sopenharmony_ci    // Only show short example if user used short option.
811cb0ef41Sopenharmony_ci    const example = StringPrototypeStartsWith(token.rawName, '--') ?
821cb0ef41Sopenharmony_ci      `'${token.rawName}=-XYZ'` :
831cb0ef41Sopenharmony_ci      `'--${token.name}=-XYZ' or '${token.rawName}-XYZ'`;
841cb0ef41Sopenharmony_ci    const errorMessage = `Option '${token.rawName}' argument is ambiguous.
851cb0ef41Sopenharmony_ciDid you forget to specify the option argument for '${token.rawName}'?
861cb0ef41Sopenharmony_ciTo specify an option argument starting with a dash use ${example}.`;
871cb0ef41Sopenharmony_ci    throw new ERR_PARSE_ARGS_INVALID_OPTION_VALUE(errorMessage);
881cb0ef41Sopenharmony_ci  }
891cb0ef41Sopenharmony_ci}
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci/**
921cb0ef41Sopenharmony_ci * In strict mode, throw for usage errors.
931cb0ef41Sopenharmony_ci *
941cb0ef41Sopenharmony_ci * @param {object} config - from config passed to parseArgs
951cb0ef41Sopenharmony_ci * @param {object} token - from tokens as available from parseArgs
961cb0ef41Sopenharmony_ci */
971cb0ef41Sopenharmony_cifunction checkOptionUsage(config, token) {
981cb0ef41Sopenharmony_ci  if (!ObjectHasOwn(config.options, token.name)) {
991cb0ef41Sopenharmony_ci    throw new ERR_PARSE_ARGS_UNKNOWN_OPTION(
1001cb0ef41Sopenharmony_ci      token.rawName, config.allowPositionals);
1011cb0ef41Sopenharmony_ci  }
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  const short = optionsGetOwn(config.options, token.name, 'short');
1041cb0ef41Sopenharmony_ci  const shortAndLong = `${short ? `-${short}, ` : ''}--${token.name}`;
1051cb0ef41Sopenharmony_ci  const type = optionsGetOwn(config.options, token.name, 'type');
1061cb0ef41Sopenharmony_ci  if (type === 'string' && typeof token.value !== 'string') {
1071cb0ef41Sopenharmony_ci    throw new ERR_PARSE_ARGS_INVALID_OPTION_VALUE(`Option '${shortAndLong} <value>' argument missing`);
1081cb0ef41Sopenharmony_ci  }
1091cb0ef41Sopenharmony_ci  // (Idiomatic test for undefined||null, expecting undefined.)
1101cb0ef41Sopenharmony_ci  if (type === 'boolean' && token.value != null) {
1111cb0ef41Sopenharmony_ci    throw new ERR_PARSE_ARGS_INVALID_OPTION_VALUE(`Option '${shortAndLong}' does not take an argument`);
1121cb0ef41Sopenharmony_ci  }
1131cb0ef41Sopenharmony_ci}
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci/**
1171cb0ef41Sopenharmony_ci * Store the option value in `values`.
1181cb0ef41Sopenharmony_ci *
1191cb0ef41Sopenharmony_ci * @param {string} longOption - long option name e.g. 'foo'
1201cb0ef41Sopenharmony_ci * @param {string|undefined} optionValue - value from user args
1211cb0ef41Sopenharmony_ci * @param {object} options - option configs, from parseArgs({ options })
1221cb0ef41Sopenharmony_ci * @param {object} values - option values returned in `values` by parseArgs
1231cb0ef41Sopenharmony_ci */
1241cb0ef41Sopenharmony_cifunction storeOption(longOption, optionValue, options, values) {
1251cb0ef41Sopenharmony_ci  if (longOption === '__proto__') {
1261cb0ef41Sopenharmony_ci    return; // No. Just no.
1271cb0ef41Sopenharmony_ci  }
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci  // We store based on the option value rather than option type,
1301cb0ef41Sopenharmony_ci  // preserving the users intent for author to deal with.
1311cb0ef41Sopenharmony_ci  const newValue = optionValue ?? true;
1321cb0ef41Sopenharmony_ci  if (optionsGetOwn(options, longOption, 'multiple')) {
1331cb0ef41Sopenharmony_ci    // Always store value in array, including for boolean.
1341cb0ef41Sopenharmony_ci    // values[longOption] starts out not present,
1351cb0ef41Sopenharmony_ci    // first value is added as new array [newValue],
1361cb0ef41Sopenharmony_ci    // subsequent values are pushed to existing array.
1371cb0ef41Sopenharmony_ci    // (note: values has null prototype, so simpler usage)
1381cb0ef41Sopenharmony_ci    if (values[longOption]) {
1391cb0ef41Sopenharmony_ci      ArrayPrototypePush(values[longOption], newValue);
1401cb0ef41Sopenharmony_ci    } else {
1411cb0ef41Sopenharmony_ci      values[longOption] = [newValue];
1421cb0ef41Sopenharmony_ci    }
1431cb0ef41Sopenharmony_ci  } else {
1441cb0ef41Sopenharmony_ci    values[longOption] = newValue;
1451cb0ef41Sopenharmony_ci  }
1461cb0ef41Sopenharmony_ci}
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci/**
1491cb0ef41Sopenharmony_ci * Store the default option value in `values`.
1501cb0ef41Sopenharmony_ci *
1511cb0ef41Sopenharmony_ci * @param {string} longOption - long option name e.g. 'foo'
1521cb0ef41Sopenharmony_ci * @param {string
1531cb0ef41Sopenharmony_ci *         | boolean
1541cb0ef41Sopenharmony_ci *         | string[]
1551cb0ef41Sopenharmony_ci *         | boolean[]} optionValue - default value from option config
1561cb0ef41Sopenharmony_ci * @param {object} values - option values returned in `values` by parseArgs
1571cb0ef41Sopenharmony_ci */
1581cb0ef41Sopenharmony_cifunction storeDefaultOption(longOption, optionValue, values) {
1591cb0ef41Sopenharmony_ci  if (longOption === '__proto__') {
1601cb0ef41Sopenharmony_ci    return; // No. Just no.
1611cb0ef41Sopenharmony_ci  }
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci  values[longOption] = optionValue;
1641cb0ef41Sopenharmony_ci}
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci/**
1671cb0ef41Sopenharmony_ci * Process args and turn into identified tokens:
1681cb0ef41Sopenharmony_ci * - option (along with value, if any)
1691cb0ef41Sopenharmony_ci * - positional
1701cb0ef41Sopenharmony_ci * - option-terminator
1711cb0ef41Sopenharmony_ci *
1721cb0ef41Sopenharmony_ci * @param {string[]} args - from parseArgs({ args }) or mainArgs
1731cb0ef41Sopenharmony_ci * @param {object} options - option configs, from parseArgs({ options })
1741cb0ef41Sopenharmony_ci */
1751cb0ef41Sopenharmony_cifunction argsToTokens(args, options) {
1761cb0ef41Sopenharmony_ci  const tokens = [];
1771cb0ef41Sopenharmony_ci  let index = -1;
1781cb0ef41Sopenharmony_ci  let groupCount = 0;
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  const remainingArgs = ArrayPrototypeSlice(args);
1811cb0ef41Sopenharmony_ci  while (remainingArgs.length > 0) {
1821cb0ef41Sopenharmony_ci    const arg = ArrayPrototypeShift(remainingArgs);
1831cb0ef41Sopenharmony_ci    const nextArg = remainingArgs[0];
1841cb0ef41Sopenharmony_ci    if (groupCount > 0)
1851cb0ef41Sopenharmony_ci      groupCount--;
1861cb0ef41Sopenharmony_ci    else
1871cb0ef41Sopenharmony_ci      index++;
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci    // Check if `arg` is an options terminator.
1901cb0ef41Sopenharmony_ci    // Guideline 10 in https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html
1911cb0ef41Sopenharmony_ci    if (arg === '--') {
1921cb0ef41Sopenharmony_ci      // Everything after a bare '--' is considered a positional argument.
1931cb0ef41Sopenharmony_ci      ArrayPrototypePush(tokens, { kind: 'option-terminator', index });
1941cb0ef41Sopenharmony_ci      ArrayPrototypePushApply(
1951cb0ef41Sopenharmony_ci        tokens, ArrayPrototypeMap(remainingArgs, (arg) => {
1961cb0ef41Sopenharmony_ci          return { kind: 'positional', index: ++index, value: arg };
1971cb0ef41Sopenharmony_ci        })
1981cb0ef41Sopenharmony_ci      );
1991cb0ef41Sopenharmony_ci      break; // Finished processing args, leave while loop.
2001cb0ef41Sopenharmony_ci    }
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci    if (isLoneShortOption(arg)) {
2031cb0ef41Sopenharmony_ci      // e.g. '-f'
2041cb0ef41Sopenharmony_ci      const shortOption = StringPrototypeCharAt(arg, 1);
2051cb0ef41Sopenharmony_ci      const longOption = findLongOptionForShort(shortOption, options);
2061cb0ef41Sopenharmony_ci      let value;
2071cb0ef41Sopenharmony_ci      let inlineValue;
2081cb0ef41Sopenharmony_ci      if (optionsGetOwn(options, longOption, 'type') === 'string' &&
2091cb0ef41Sopenharmony_ci          isOptionValue(nextArg)) {
2101cb0ef41Sopenharmony_ci        // e.g. '-f', 'bar'
2111cb0ef41Sopenharmony_ci        value = ArrayPrototypeShift(remainingArgs);
2121cb0ef41Sopenharmony_ci        inlineValue = false;
2131cb0ef41Sopenharmony_ci      }
2141cb0ef41Sopenharmony_ci      ArrayPrototypePush(
2151cb0ef41Sopenharmony_ci        tokens,
2161cb0ef41Sopenharmony_ci        { kind: 'option', name: longOption, rawName: arg,
2171cb0ef41Sopenharmony_ci          index, value, inlineValue });
2181cb0ef41Sopenharmony_ci      if (value != null) ++index;
2191cb0ef41Sopenharmony_ci      continue;
2201cb0ef41Sopenharmony_ci    }
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci    if (isShortOptionGroup(arg, options)) {
2231cb0ef41Sopenharmony_ci      // Expand -fXzy to -f -X -z -y
2241cb0ef41Sopenharmony_ci      const expanded = [];
2251cb0ef41Sopenharmony_ci      for (let index = 1; index < arg.length; index++) {
2261cb0ef41Sopenharmony_ci        const shortOption = StringPrototypeCharAt(arg, index);
2271cb0ef41Sopenharmony_ci        const longOption = findLongOptionForShort(shortOption, options);
2281cb0ef41Sopenharmony_ci        if (optionsGetOwn(options, longOption, 'type') !== 'string' ||
2291cb0ef41Sopenharmony_ci          index === arg.length - 1) {
2301cb0ef41Sopenharmony_ci          // Boolean option, or last short in group. Well formed.
2311cb0ef41Sopenharmony_ci          ArrayPrototypePush(expanded, `-${shortOption}`);
2321cb0ef41Sopenharmony_ci        } else {
2331cb0ef41Sopenharmony_ci          // String option in middle. Yuck.
2341cb0ef41Sopenharmony_ci          // Expand -abfFILE to -a -b -fFILE
2351cb0ef41Sopenharmony_ci          ArrayPrototypePush(expanded, `-${StringPrototypeSlice(arg, index)}`);
2361cb0ef41Sopenharmony_ci          break; // finished short group
2371cb0ef41Sopenharmony_ci        }
2381cb0ef41Sopenharmony_ci      }
2391cb0ef41Sopenharmony_ci      ArrayPrototypeUnshiftApply(remainingArgs, expanded);
2401cb0ef41Sopenharmony_ci      groupCount = expanded.length;
2411cb0ef41Sopenharmony_ci      continue;
2421cb0ef41Sopenharmony_ci    }
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci    if (isShortOptionAndValue(arg, options)) {
2451cb0ef41Sopenharmony_ci      // e.g. -fFILE
2461cb0ef41Sopenharmony_ci      const shortOption = StringPrototypeCharAt(arg, 1);
2471cb0ef41Sopenharmony_ci      const longOption = findLongOptionForShort(shortOption, options);
2481cb0ef41Sopenharmony_ci      const value = StringPrototypeSlice(arg, 2);
2491cb0ef41Sopenharmony_ci      ArrayPrototypePush(
2501cb0ef41Sopenharmony_ci        tokens,
2511cb0ef41Sopenharmony_ci        { kind: 'option', name: longOption, rawName: `-${shortOption}`,
2521cb0ef41Sopenharmony_ci          index, value, inlineValue: true });
2531cb0ef41Sopenharmony_ci      continue;
2541cb0ef41Sopenharmony_ci    }
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci    if (isLoneLongOption(arg)) {
2571cb0ef41Sopenharmony_ci      // e.g. '--foo'
2581cb0ef41Sopenharmony_ci      const longOption = StringPrototypeSlice(arg, 2);
2591cb0ef41Sopenharmony_ci      let value;
2601cb0ef41Sopenharmony_ci      let inlineValue;
2611cb0ef41Sopenharmony_ci      if (optionsGetOwn(options, longOption, 'type') === 'string' &&
2621cb0ef41Sopenharmony_ci          isOptionValue(nextArg)) {
2631cb0ef41Sopenharmony_ci        // e.g. '--foo', 'bar'
2641cb0ef41Sopenharmony_ci        value = ArrayPrototypeShift(remainingArgs);
2651cb0ef41Sopenharmony_ci        inlineValue = false;
2661cb0ef41Sopenharmony_ci      }
2671cb0ef41Sopenharmony_ci      ArrayPrototypePush(
2681cb0ef41Sopenharmony_ci        tokens,
2691cb0ef41Sopenharmony_ci        { kind: 'option', name: longOption, rawName: arg,
2701cb0ef41Sopenharmony_ci          index, value, inlineValue });
2711cb0ef41Sopenharmony_ci      if (value != null) ++index;
2721cb0ef41Sopenharmony_ci      continue;
2731cb0ef41Sopenharmony_ci    }
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ci    if (isLongOptionAndValue(arg)) {
2761cb0ef41Sopenharmony_ci      // e.g. --foo=bar
2771cb0ef41Sopenharmony_ci      const equalIndex = StringPrototypeIndexOf(arg, '=');
2781cb0ef41Sopenharmony_ci      const longOption = StringPrototypeSlice(arg, 2, equalIndex);
2791cb0ef41Sopenharmony_ci      const value = StringPrototypeSlice(arg, equalIndex + 1);
2801cb0ef41Sopenharmony_ci      ArrayPrototypePush(
2811cb0ef41Sopenharmony_ci        tokens,
2821cb0ef41Sopenharmony_ci        { kind: 'option', name: longOption, rawName: `--${longOption}`,
2831cb0ef41Sopenharmony_ci          index, value, inlineValue: true });
2841cb0ef41Sopenharmony_ci      continue;
2851cb0ef41Sopenharmony_ci    }
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci    ArrayPrototypePush(tokens, { kind: 'positional', index, value: arg });
2881cb0ef41Sopenharmony_ci  }
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci  return tokens;
2911cb0ef41Sopenharmony_ci}
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ciconst parseArgs = (config = kEmptyObject) => {
2941cb0ef41Sopenharmony_ci  const args = objectGetOwn(config, 'args') ?? getMainArgs();
2951cb0ef41Sopenharmony_ci  const strict = objectGetOwn(config, 'strict') ?? true;
2961cb0ef41Sopenharmony_ci  const allowPositionals = objectGetOwn(config, 'allowPositionals') ?? !strict;
2971cb0ef41Sopenharmony_ci  const returnTokens = objectGetOwn(config, 'tokens') ?? false;
2981cb0ef41Sopenharmony_ci  const options = objectGetOwn(config, 'options') ?? { __proto__: null };
2991cb0ef41Sopenharmony_ci  // Bundle these up for passing to strict-mode checks.
3001cb0ef41Sopenharmony_ci  const parseConfig = { args, strict, options, allowPositionals };
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci  // Validate input configuration.
3031cb0ef41Sopenharmony_ci  validateArray(args, 'args');
3041cb0ef41Sopenharmony_ci  validateBoolean(strict, 'strict');
3051cb0ef41Sopenharmony_ci  validateBoolean(allowPositionals, 'allowPositionals');
3061cb0ef41Sopenharmony_ci  validateBoolean(returnTokens, 'tokens');
3071cb0ef41Sopenharmony_ci  validateObject(options, 'options');
3081cb0ef41Sopenharmony_ci  ArrayPrototypeForEach(
3091cb0ef41Sopenharmony_ci    ObjectEntries(options),
3101cb0ef41Sopenharmony_ci    ({ 0: longOption, 1: optionConfig }) => {
3111cb0ef41Sopenharmony_ci      validateObject(optionConfig, `options.${longOption}`);
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ci      // type is required
3141cb0ef41Sopenharmony_ci      const optionType = objectGetOwn(optionConfig, 'type');
3151cb0ef41Sopenharmony_ci      validateUnion(optionType, `options.${longOption}.type`, ['string', 'boolean']);
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci      if (ObjectHasOwn(optionConfig, 'short')) {
3181cb0ef41Sopenharmony_ci        const shortOption = optionConfig.short;
3191cb0ef41Sopenharmony_ci        validateString(shortOption, `options.${longOption}.short`);
3201cb0ef41Sopenharmony_ci        if (shortOption.length !== 1) {
3211cb0ef41Sopenharmony_ci          throw new ERR_INVALID_ARG_VALUE(
3221cb0ef41Sopenharmony_ci            `options.${longOption}.short`,
3231cb0ef41Sopenharmony_ci            shortOption,
3241cb0ef41Sopenharmony_ci            'must be a single character'
3251cb0ef41Sopenharmony_ci          );
3261cb0ef41Sopenharmony_ci        }
3271cb0ef41Sopenharmony_ci      }
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ci      const multipleOption = objectGetOwn(optionConfig, 'multiple');
3301cb0ef41Sopenharmony_ci      if (ObjectHasOwn(optionConfig, 'multiple')) {
3311cb0ef41Sopenharmony_ci        validateBoolean(multipleOption, `options.${longOption}.multiple`);
3321cb0ef41Sopenharmony_ci      }
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci      const defaultValue = objectGetOwn(optionConfig, 'default');
3351cb0ef41Sopenharmony_ci      if (defaultValue !== undefined) {
3361cb0ef41Sopenharmony_ci        let validator;
3371cb0ef41Sopenharmony_ci        switch (optionType) {
3381cb0ef41Sopenharmony_ci          case 'string':
3391cb0ef41Sopenharmony_ci            validator = multipleOption ? validateStringArray : validateString;
3401cb0ef41Sopenharmony_ci            break;
3411cb0ef41Sopenharmony_ci
3421cb0ef41Sopenharmony_ci          case 'boolean':
3431cb0ef41Sopenharmony_ci            validator = multipleOption ? validateBooleanArray : validateBoolean;
3441cb0ef41Sopenharmony_ci            break;
3451cb0ef41Sopenharmony_ci        }
3461cb0ef41Sopenharmony_ci        validator(defaultValue, `options.${longOption}.default`);
3471cb0ef41Sopenharmony_ci      }
3481cb0ef41Sopenharmony_ci    }
3491cb0ef41Sopenharmony_ci  );
3501cb0ef41Sopenharmony_ci
3511cb0ef41Sopenharmony_ci  // Phase 1: identify tokens
3521cb0ef41Sopenharmony_ci  const tokens = argsToTokens(args, options);
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci  // Phase 2: process tokens into parsed option values and positionals
3551cb0ef41Sopenharmony_ci  const result = {
3561cb0ef41Sopenharmony_ci    values: { __proto__: null },
3571cb0ef41Sopenharmony_ci    positionals: [],
3581cb0ef41Sopenharmony_ci  };
3591cb0ef41Sopenharmony_ci  if (returnTokens) {
3601cb0ef41Sopenharmony_ci    result.tokens = tokens;
3611cb0ef41Sopenharmony_ci  }
3621cb0ef41Sopenharmony_ci  ArrayPrototypeForEach(tokens, (token) => {
3631cb0ef41Sopenharmony_ci    if (token.kind === 'option') {
3641cb0ef41Sopenharmony_ci      if (strict) {
3651cb0ef41Sopenharmony_ci        checkOptionUsage(parseConfig, token);
3661cb0ef41Sopenharmony_ci        checkOptionLikeValue(token);
3671cb0ef41Sopenharmony_ci      }
3681cb0ef41Sopenharmony_ci      storeOption(token.name, token.value, options, result.values);
3691cb0ef41Sopenharmony_ci    } else if (token.kind === 'positional') {
3701cb0ef41Sopenharmony_ci      if (!allowPositionals) {
3711cb0ef41Sopenharmony_ci        throw new ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL(token.value);
3721cb0ef41Sopenharmony_ci      }
3731cb0ef41Sopenharmony_ci      ArrayPrototypePush(result.positionals, token.value);
3741cb0ef41Sopenharmony_ci    }
3751cb0ef41Sopenharmony_ci  });
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ci  // Phase 3: fill in default values for missing args
3781cb0ef41Sopenharmony_ci  ArrayPrototypeForEach(ObjectEntries(options), ({ 0: longOption,
3791cb0ef41Sopenharmony_ci                                                   1: optionConfig }) => {
3801cb0ef41Sopenharmony_ci    const mustSetDefault = useDefaultValueOption(longOption,
3811cb0ef41Sopenharmony_ci                                                 optionConfig,
3821cb0ef41Sopenharmony_ci                                                 result.values);
3831cb0ef41Sopenharmony_ci    if (mustSetDefault) {
3841cb0ef41Sopenharmony_ci      storeDefaultOption(longOption,
3851cb0ef41Sopenharmony_ci                         objectGetOwn(optionConfig, 'default'),
3861cb0ef41Sopenharmony_ci                         result.values);
3871cb0ef41Sopenharmony_ci    }
3881cb0ef41Sopenharmony_ci  });
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ci  return result;
3921cb0ef41Sopenharmony_ci};
3931cb0ef41Sopenharmony_ci
3941cb0ef41Sopenharmony_cimodule.exports = {
3951cb0ef41Sopenharmony_ci  parseArgs,
3961cb0ef41Sopenharmony_ci};
397