diff options
Diffstat (limited to 'src/node_modules/es-abstract/2017/GetSubstitution.js')
-rw-r--r-- | src/node_modules/es-abstract/2017/GetSubstitution.js | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/node_modules/es-abstract/2017/GetSubstitution.js b/src/node_modules/es-abstract/2017/GetSubstitution.js new file mode 100644 index 0000000..6497aae --- /dev/null +++ b/src/node_modules/es-abstract/2017/GetSubstitution.js @@ -0,0 +1,104 @@ + +'use strict'; + +var GetIntrinsic = require('../GetIntrinsic'); + +var $TypeError = GetIntrinsic('%TypeError%'); +var $parseInt = GetIntrinsic('%parseInt%'); + +var inspect = require('object-inspect'); + +var regexTester = require('../helpers/regexTester'); +var callBound = require('../helpers/callBound'); +var every = require('../helpers/every'); + +var isDigit = regexTester(/^[0-9]$/); + +var $charAt = callBound('String.prototype.charAt'); +var $strSlice = callBound('String.prototype.slice'); + +var IsArray = require('./IsArray'); +var IsInteger = require('./IsInteger'); +var Type = require('./Type'); + +var canDistinguishSparseFromUndefined = 0 in [undefined]; // IE 6 - 8 have a bug where this returns false + +var isStringOrHole = function (capture, index, arr) { + return Type(capture) === 'String' || (canDistinguishSparseFromUndefined ? !(index in arr) : Type(capture) === 'Undefined'); +}; + +// https://www.ecma-international.org/ecma-262/6.0/#sec-getsubstitution + +// eslint-disable-next-line max-statements, max-params, max-lines-per-function +module.exports = function GetSubstitution(matched, str, position, captures, replacement) { + if (Type(matched) !== 'String') { + throw new $TypeError('Assertion failed: `matched` must be a String'); + } + var matchLength = matched.length; + + if (Type(str) !== 'String') { + throw new $TypeError('Assertion failed: `str` must be a String'); + } + var stringLength = str.length; + + if (!IsInteger(position) || position < 0 || position > stringLength) { + throw new $TypeError('Assertion failed: `position` must be a nonnegative integer, and less than or equal to the length of `string`, got ' + inspect(position)); + } + + if (!IsArray(captures) || !every(captures, isStringOrHole)) { + throw new $TypeError('Assertion failed: `captures` must be a List of Strings, got ' + inspect(captures)); + } + + if (Type(replacement) !== 'String') { + throw new $TypeError('Assertion failed: `replacement` must be a String'); + } + + var tailPos = position + matchLength; + var m = captures.length; + + var result = ''; + for (var i = 0; i < replacement.length; i += 1) { + // if this is a $, and it's not the end of the replacement + var current = $charAt(replacement, i); + var isLast = (i + 1) >= replacement.length; + var nextIsLast = (i + 2) >= replacement.length; + if (current === '$' && !isLast) { + var next = $charAt(replacement, i + 1); + if (next === '$') { + result += '$'; + i += 1; + } else if (next === '&') { + result += matched; + i += 1; + } else if (next === '`') { + result += position === 0 ? '' : $strSlice(str, 0, position - 1); + i += 1; + } else if (next === "'") { + result += tailPos >= stringLength ? '' : $strSlice(str, tailPos); + i += 1; + } else { + var nextNext = nextIsLast ? null : $charAt(replacement, i + 2); + if (isDigit(next) && next !== '0' && (nextIsLast || !isDigit(nextNext))) { + // $1 through $9, and not followed by a digit + var n = $parseInt(next, 10); + // if (n > m, impl-defined) + result += n <= m && Type(captures[n - 1]) === 'Undefined' ? '' : captures[n - 1]; + i += 1; + } else if (isDigit(next) && (nextIsLast || isDigit(nextNext))) { + // $00 through $99 + var nn = next + nextNext; + var nnI = $parseInt(nn, 10) - 1; + // if nn === '00' or nn > m, impl-defined + result += nn <= m && Type(captures[nnI]) === 'Undefined' ? '' : captures[nnI]; + i += 2; + } else { + result += '$'; + } + } + } else { + // the final $, or else not a $ + result += $charAt(replacement, i); + } + } + return result; +}; |