You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					129 lines
				
				4.3 KiB
			
		
		
			
		
	
	
					129 lines
				
				4.3 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var GetIntrinsic = require('get-intrinsic');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var $TypeError = GetIntrinsic('%TypeError%');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var callBound = require('call-bind/callBound');
							 | 
						||
| 
								 | 
							
								var regexTester = require('../helpers/regexTester');
							 | 
						||
| 
								 | 
							
								var every = require('../helpers/every');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var $charAt = callBound('String.prototype.charAt');
							 | 
						||
| 
								 | 
							
								var $strSlice = callBound('String.prototype.slice');
							 | 
						||
| 
								 | 
							
								var $indexOf = callBound('String.prototype.indexOf');
							 | 
						||
| 
								 | 
							
								var $parseInt = parseInt;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var isDigit = regexTester(/^[0-9]$/);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var inspect = require('object-inspect');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var Get = require('./Get');
							 | 
						||
| 
								 | 
							
								var IsArray = require('./IsArray');
							 | 
						||
| 
								 | 
							
								var IsInteger = require('./IsInteger');
							 | 
						||
| 
								 | 
							
								var ToObject = require('./ToObject');
							 | 
						||
| 
								 | 
							
								var ToString = require('./ToString');
							 | 
						||
| 
								 | 
							
								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');
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// http://262.ecma-international.org/9.0/#sec-getsubstitution
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// eslint-disable-next-line max-statements, max-params, max-lines-per-function
							 | 
						||
| 
								 | 
							
								module.exports = function GetSubstitution(matched, str, position, captures, namedCaptures, 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;
							 | 
						||
| 
								 | 
							
									if (Type(namedCaptures) !== 'Undefined') {
							 | 
						||
| 
								 | 
							
										namedCaptures = ToObject(namedCaptures); // eslint-disable-line no-param-reassign
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									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 if (next === '<') {
							 | 
						||
| 
								 | 
							
													// eslint-disable-next-line max-depth
							 | 
						||
| 
								 | 
							
													if (Type(namedCaptures) === 'Undefined') {
							 | 
						||
| 
								 | 
							
														result += '$<';
							 | 
						||
| 
								 | 
							
														i += 2;
							 | 
						||
| 
								 | 
							
													} else {
							 | 
						||
| 
								 | 
							
														var endIndex = $indexOf(replacement, '>', i);
							 | 
						||
| 
								 | 
							
														// eslint-disable-next-line max-depth
							 | 
						||
| 
								 | 
							
														if (endIndex > -1) {
							 | 
						||
| 
								 | 
							
															var groupName = $strSlice(replacement, i + '$<'.length, endIndex);
							 | 
						||
| 
								 | 
							
															var capture = Get(namedCaptures, groupName);
							 | 
						||
| 
								 | 
							
															// eslint-disable-next-line max-depth
							 | 
						||
| 
								 | 
							
															if (Type(capture) !== 'Undefined') {
							 | 
						||
| 
								 | 
							
																result += ToString(capture);
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															i += ('<' + groupName + '>').length;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
													result += '$';
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											// the final $, or else not a $
							 | 
						||
| 
								 | 
							
											result += $charAt(replacement, i);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return result;
							 | 
						||
| 
								 | 
							
								};
							 |