UNPKG

3.79 kBJavaScriptView Raw
1'use strict';
2var createNonEnumerableProperty = require('../internals/create-non-enumerable-property');
3var redefine = require('../internals/redefine');
4var fails = require('../internals/fails');
5var wellKnownSymbol = require('../internals/well-known-symbol');
6var regexpExec = require('../internals/regexp-exec');
7
8var SPECIES = wellKnownSymbol('species');
9
10var REPLACE_SUPPORTS_NAMED_GROUPS = !fails(function () {
11 // #replace needs built-in support for named groups.
12 // #match works fine because it just return the exec results, even if it has
13 // a "grops" property.
14 var re = /./;
15 re.exec = function () {
16 var result = [];
17 result.groups = { a: '7' };
18 return result;
19 };
20 return ''.replace(re, '$<a>') !== '7';
21});
22
23// Chrome 51 has a buggy "split" implementation when RegExp#exec !== nativeExec
24// Weex JS has frozen built-in prototypes, so use try / catch wrapper
25var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = !fails(function () {
26 var re = /(?:)/;
27 var originalExec = re.exec;
28 re.exec = function () { return originalExec.apply(this, arguments); };
29 var result = 'ab'.split(re);
30 return result.length !== 2 || result[0] !== 'a' || result[1] !== 'b';
31});
32
33module.exports = function (KEY, length, exec, sham) {
34 var SYMBOL = wellKnownSymbol(KEY);
35
36 var DELEGATES_TO_SYMBOL = !fails(function () {
37 // String methods call symbol-named RegEp methods
38 var O = {};
39 O[SYMBOL] = function () { return 7; };
40 return ''[KEY](O) != 7;
41 });
42
43 var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails(function () {
44 // Symbol-named RegExp methods call .exec
45 var execCalled = false;
46 var re = /a/;
47
48 if (KEY === 'split') {
49 // We can't use real regex here since it causes deoptimization
50 // and serious performance degradation in V8
51 // https://github.com/zloirock/core-js/issues/306
52 re = {};
53 // RegExp[@@split] doesn't call the regex's exec method, but first creates
54 // a new one. We need to return the patched regex when creating the new one.
55 re.constructor = {};
56 re.constructor[SPECIES] = function () { return re; };
57 re.flags = '';
58 re[SYMBOL] = /./[SYMBOL];
59 }
60
61 re.exec = function () { execCalled = true; return null; };
62
63 re[SYMBOL]('');
64 return !execCalled;
65 });
66
67 if (
68 !DELEGATES_TO_SYMBOL ||
69 !DELEGATES_TO_EXEC ||
70 (KEY === 'replace' && !REPLACE_SUPPORTS_NAMED_GROUPS) ||
71 (KEY === 'split' && !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC)
72 ) {
73 var nativeRegExpMethod = /./[SYMBOL];
74 var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) {
75 if (regexp.exec === regexpExec) {
76 if (DELEGATES_TO_SYMBOL && !forceStringMethod) {
77 // The native String method already delegates to @@method (this
78 // polyfilled function), leasing to infinite recursion.
79 // We avoid it by directly calling the native @@method method.
80 return { done: true, value: nativeRegExpMethod.call(regexp, str, arg2) };
81 }
82 return { done: true, value: nativeMethod.call(str, regexp, arg2) };
83 }
84 return { done: false };
85 });
86 var stringMethod = methods[0];
87 var regexMethod = methods[1];
88
89 redefine(String.prototype, KEY, stringMethod);
90 redefine(RegExp.prototype, SYMBOL, length == 2
91 // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)
92 // 21.2.5.11 RegExp.prototype[@@split](string, limit)
93 ? function (string, arg) { return regexMethod.call(string, this, arg); }
94 // 21.2.5.6 RegExp.prototype[@@match](string)
95 // 21.2.5.9 RegExp.prototype[@@search](string)
96 : function (string) { return regexMethod.call(string, this); }
97 );
98 if (sham) createNonEnumerableProperty(RegExp.prototype[SYMBOL], 'sham', true);
99 }
100};