get-substitution.js 1.6 KB

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