get-substitution.js 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. var uncurryThis = require('../internals/function-uncurry-this');
  2. var toObject = require('../internals/to-object');
  3. var floor = Math.floor;
  4. var charAt = uncurryThis(''.charAt);
  5. var replace = uncurryThis(''.replace);
  6. var stringSlice = uncurryThis(''.slice);
  7. // eslint-disable-next-line redos/no-vulnerable -- safe
  8. var SUBSTITUTION_SYMBOLS = /\$([$&'`]|\d{1,2}|<[^>]*>)/g;
  9. var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&'`]|\d{1,2})/g;
  10. // `GetSubstitution` abstract operation
  11. // https://tc39.es/ecma262/#sec-getsubstitution
  12. module.exports = function (matched, str, position, captures, namedCaptures, replacement) {
  13. var tailPos = position + matched.length;
  14. var m = captures.length;
  15. var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;
  16. if (namedCaptures !== undefined) {
  17. namedCaptures = toObject(namedCaptures);
  18. symbols = SUBSTITUTION_SYMBOLS;
  19. }
  20. return replace(replacement, symbols, function (match, ch) {
  21. var capture;
  22. switch (charAt(ch, 0)) {
  23. case '$': return '$';
  24. case '&': return matched;
  25. case '`': return stringSlice(str, 0, position);
  26. case "'": return stringSlice(str, tailPos);
  27. case '<':
  28. capture = namedCaptures[stringSlice(ch, 1, -1)];
  29. break;
  30. default: // \d\d?
  31. var n = +ch;
  32. if (n === 0) return match;
  33. if (n > m) {
  34. var f = floor(n / 10);
  35. if (f === 0) return match;
  36. if (f <= m) return captures[f - 1] === undefined ? charAt(ch, 1) : captures[f - 1] + charAt(ch, 1);
  37. return match;
  38. }
  39. capture = captures[n - 1];
  40. }
  41. return capture === undefined ? '' : capture;
  42. });
  43. };