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