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.
		
		
		
		
		
			
		
			
				
					119 lines
				
				4.5 KiB
			
		
		
			
		
	
	
					119 lines
				
				4.5 KiB
			| 
											3 years ago
										 | 'use strict'; | ||
|  | 
 | ||
|  | var anObject = require('./_an-object'); | ||
|  | var toObject = require('./_to-object'); | ||
|  | var toLength = require('./_to-length'); | ||
|  | var toInteger = require('./_to-integer'); | ||
|  | var advanceStringIndex = require('./_advance-string-index'); | ||
|  | var regExpExec = require('./_regexp-exec-abstract'); | ||
|  | var max = Math.max; | ||
|  | var min = Math.min; | ||
|  | var floor = Math.floor; | ||
|  | var SUBSTITUTION_SYMBOLS = /\$([$&`']|\d\d?|<[^>]*>)/g; | ||
|  | var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&`']|\d\d?)/g; | ||
|  | 
 | ||
|  | var maybeToString = function (it) { | ||
|  |   return it === undefined ? it : String(it); | ||
|  | }; | ||
|  | 
 | ||
|  | // @@replace logic
 | ||
|  | require('./_fix-re-wks')('replace', 2, function (defined, REPLACE, $replace, maybeCallNative) { | ||
|  |   return [ | ||
|  |     // `String.prototype.replace` method
 | ||
|  |     // https://tc39.github.io/ecma262/#sec-string.prototype.replace
 | ||
|  |     function replace(searchValue, replaceValue) { | ||
|  |       var O = defined(this); | ||
|  |       var fn = searchValue == undefined ? undefined : searchValue[REPLACE]; | ||
|  |       return fn !== undefined | ||
|  |         ? fn.call(searchValue, O, replaceValue) | ||
|  |         : $replace.call(String(O), searchValue, replaceValue); | ||
|  |     }, | ||
|  |     // `RegExp.prototype[@@replace]` method
 | ||
|  |     // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@replace
 | ||
|  |     function (regexp, replaceValue) { | ||
|  |       var res = maybeCallNative($replace, regexp, this, replaceValue); | ||
|  |       if (res.done) return res.value; | ||
|  | 
 | ||
|  |       var rx = anObject(regexp); | ||
|  |       var S = String(this); | ||
|  |       var functionalReplace = typeof replaceValue === 'function'; | ||
|  |       if (!functionalReplace) replaceValue = String(replaceValue); | ||
|  |       var global = rx.global; | ||
|  |       if (global) { | ||
|  |         var fullUnicode = rx.unicode; | ||
|  |         rx.lastIndex = 0; | ||
|  |       } | ||
|  |       var results = []; | ||
|  |       while (true) { | ||
|  |         var result = regExpExec(rx, S); | ||
|  |         if (result === null) break; | ||
|  |         results.push(result); | ||
|  |         if (!global) break; | ||
|  |         var matchStr = String(result[0]); | ||
|  |         if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode); | ||
|  |       } | ||
|  |       var accumulatedResult = ''; | ||
|  |       var nextSourcePosition = 0; | ||
|  |       for (var i = 0; i < results.length; i++) { | ||
|  |         result = results[i]; | ||
|  |         var matched = String(result[0]); | ||
|  |         var position = max(min(toInteger(result.index), S.length), 0); | ||
|  |         var captures = []; | ||
|  |         // NOTE: This is equivalent to
 | ||
|  |         //   captures = result.slice(1).map(maybeToString)
 | ||
|  |         // but for some reason `nativeSlice.call(result, 1, result.length)` (called in
 | ||
|  |         // the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and
 | ||
|  |         // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it.
 | ||
|  |         for (var j = 1; j < result.length; j++) captures.push(maybeToString(result[j])); | ||
|  |         var namedCaptures = result.groups; | ||
|  |         if (functionalReplace) { | ||
|  |           var replacerArgs = [matched].concat(captures, position, S); | ||
|  |           if (namedCaptures !== undefined) replacerArgs.push(namedCaptures); | ||
|  |           var replacement = String(replaceValue.apply(undefined, replacerArgs)); | ||
|  |         } else { | ||
|  |           replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue); | ||
|  |         } | ||
|  |         if (position >= nextSourcePosition) { | ||
|  |           accumulatedResult += S.slice(nextSourcePosition, position) + replacement; | ||
|  |           nextSourcePosition = position + matched.length; | ||
|  |         } | ||
|  |       } | ||
|  |       return accumulatedResult + S.slice(nextSourcePosition); | ||
|  |     } | ||
|  |   ]; | ||
|  | 
 | ||
|  |     // https://tc39.github.io/ecma262/#sec-getsubstitution
 | ||
|  |   function getSubstitution(matched, str, position, captures, namedCaptures, replacement) { | ||
|  |     var tailPos = position + matched.length; | ||
|  |     var m = captures.length; | ||
|  |     var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED; | ||
|  |     if (namedCaptures !== undefined) { | ||
|  |       namedCaptures = toObject(namedCaptures); | ||
|  |       symbols = SUBSTITUTION_SYMBOLS; | ||
|  |     } | ||
|  |     return $replace.call(replacement, symbols, function (match, ch) { | ||
|  |       var capture; | ||
|  |       switch (ch.charAt(0)) { | ||
|  |         case '$': return '$'; | ||
|  |         case '&': return matched; | ||
|  |         case '`': return str.slice(0, position); | ||
|  |         case "'": return str.slice(tailPos); | ||
|  |         case '<': | ||
|  |           capture = namedCaptures[ch.slice(1, -1)]; | ||
|  |           break; | ||
|  |         default: // \d\d?
 | ||
|  |           var n = +ch; | ||
|  |           if (n === 0) return match; | ||
|  |           if (n > m) { | ||
|  |             var f = floor(n / 10); | ||
|  |             if (f === 0) return match; | ||
|  |             if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1); | ||
|  |             return match; | ||
|  |           } | ||
|  |           capture = captures[n - 1]; | ||
|  |       } | ||
|  |       return capture === undefined ? '' : capture; | ||
|  |     }); | ||
|  |   } | ||
|  | }); |