Skip to content

Commit

Permalink
add fixes for String#split / RegExp#@@split, #156
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed Jan 26, 2016
1 parent c19264e commit 7a90ad4
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 22 deletions.
10 changes: 6 additions & 4 deletions library/modules/_fix-re-wks.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,22 @@ var hide = require('./_hide')

module.exports = function(KEY, length, exec){
var SYMBOL = wks(KEY)
, original = ''[KEY];
, fns = exec(defined, SYMBOL, ''[KEY])
, strfn = fns[0]
, rxfn = fns[1];
if(fails(function(){
var O = {};
O[SYMBOL] = function(){ return 7; };
return ''[KEY](O) != 7;
})){
redefine(String.prototype, KEY, exec(defined, SYMBOL, original));
redefine(String.prototype, KEY, strfn);
hide(RegExp.prototype, SYMBOL, length == 2
// 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)
// 21.2.5.11 RegExp.prototype[@@split](string, limit)
? function(string, arg){ return original.call(string, this, arg); }
? function(string, arg){ return rxfn.call(string, this, arg); }
// 21.2.5.6 RegExp.prototype[@@match](string)
// 21.2.5.9 RegExp.prototype[@@search](string)
: function(string){ return original.call(string, this); }
: function(string){ return rxfn.call(string, this); }
);
}
};
10 changes: 6 additions & 4 deletions modules/_fix-re-wks.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,22 @@ var hide = require('./_hide')

module.exports = function(KEY, length, exec){
var SYMBOL = wks(KEY)
, original = ''[KEY];
, fns = exec(defined, SYMBOL, ''[KEY])
, strfn = fns[0]
, rxfn = fns[1];
if(fails(function(){
var O = {};
O[SYMBOL] = function(){ return 7; };
return ''[KEY](O) != 7;
})){
redefine(String.prototype, KEY, exec(defined, SYMBOL, original));
redefine(String.prototype, KEY, strfn);
hide(RegExp.prototype, SYMBOL, length == 2
// 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)
// 21.2.5.11 RegExp.prototype[@@split](string, limit)
? function(string, arg){ return original.call(string, this, arg); }
? function(string, arg){ return rxfn.call(string, this, arg); }
// 21.2.5.6 RegExp.prototype[@@match](string)
// 21.2.5.9 RegExp.prototype[@@search](string)
: function(string){ return original.call(string, this); }
: function(string){ return rxfn.call(string, this); }
);
}
};
6 changes: 3 additions & 3 deletions modules/es6.regexp.match.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// @@match logic
require('./_fix-re-wks')('match', 1, function(defined, MATCH){
require('./_fix-re-wks')('match', 1, function(defined, MATCH, $match){
// 21.1.3.11 String.prototype.match(regexp)
return function match(regexp){
return [function match(regexp){
'use strict';
var O = defined(this)
, fn = regexp == undefined ? undefined : regexp[MATCH];
return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[MATCH](String(O));
};
}, $match];
});
4 changes: 2 additions & 2 deletions modules/es6.regexp.replace.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// @@replace logic
require('./_fix-re-wks')('replace', 2, function(defined, REPLACE, $replace){
// 21.1.3.14 String.prototype.replace(searchValue, replaceValue)
return function replace(searchValue, replaceValue){
return [function replace(searchValue, replaceValue){
'use strict';
var O = defined(this)
, fn = searchValue == undefined ? undefined : searchValue[REPLACE];
return fn !== undefined
? fn.call(searchValue, O, replaceValue)
: $replace.call(String(O), searchValue, replaceValue);
};
}, $replace];
});
6 changes: 3 additions & 3 deletions modules/es6.regexp.search.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// @@search logic
require('./_fix-re-wks')('search', 1, function(defined, SEARCH){
require('./_fix-re-wks')('search', 1, function(defined, SEARCH, $search){
// 21.1.3.15 String.prototype.search(regexp)
return function search(regexp){
return [function search(regexp){
'use strict';
var O = defined(this)
, fn = regexp == undefined ? undefined : regexp[SEARCH];
return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O));
};
}, $search];
});
70 changes: 64 additions & 6 deletions modules/es6.regexp.split.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,70 @@
// @@split logic
require('./_fix-re-wks')('split', 2, function(defined, SPLIT, $split){
'use strict';
var isRegExp = require('./_is-regexp')
, _split = $split
, $push = [].push
, $SPLIT = 'split'
, LENGTH = 'length'
, LAST_INDEX = 'lastIndex';
if(
'abbc'[$SPLIT](/(b)*/)[1] == 'c' ||
'test'[$SPLIT](/(?:)/, -1)[LENGTH] != 4 ||
'ab'[$SPLIT](/(?:ab)*/)[LENGTH] != 2 ||
'.'[$SPLIT](/(.?)(.?)/)[LENGTH] != 4 ||
'.'[$SPLIT](/()()/)[LENGTH] > 1 ||
''[$SPLIT](/.?/)[LENGTH]
){
var NPCG = /()??/.exec('')[1] === undefined; // nonparticipating capturing group
// based on es5-shim implementation, need to rework it
$split = function(separator, limit){
var string = String(this);
if(separator === undefined && limit === 0)return [];
// If `separator` is not a regex, use native split
if(!isRegExp(separator))return _split.call(string, separator, limit);
var output = [];
var flags = (separator.ignoreCase ? 'i' : '') +
(separator.multiline ? 'm' : '') +
(separator.unicode ? 'u' : '') +
(separator.sticky ? 'y' : '');
var lastLastIndex = 0;
var splitLimit = limit === undefined ? 4294967295 : limit >>> 0;
// Make `global` and avoid `lastIndex` issues by working with a copy
var separatorCopy = new RegExp(separator.source, flags + 'g');
var separator2, match, lastIndex, lastLength, i;
// Doesn't need flags gy, but they don't hurt
if(!NPCG)separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags);
while(match = separatorCopy.exec(string)){
// `separatorCopy.lastIndex` is not reliable cross-browser
lastIndex = match.index + match[0][LENGTH];
if(lastIndex > lastLastIndex){
output.push(string.slice(lastLastIndex, match.index));
// Fix browsers whose `exec` methods don't consistently return `undefined` for NPCG
if(!NPCG && match[LENGTH] > 1)match[0].replace(separator2, function(){
for(i = 1; i < arguments[LENGTH] - 2; i++)if(arguments[i] === undefined)match[i] = undefined;
});
if(match[LENGTH] > 1 && match.index < string[LENGTH])$push.apply(output, match.slice(1));
lastLength = match[0][LENGTH];
lastLastIndex = lastIndex;
if(output[LENGTH] >= splitLimit)break;
}
if(separatorCopy[LAST_INDEX] === match.index)separatorCopy[LAST_INDEX]++; // Avoid an infinite loop
}
if(lastLastIndex === string[LENGTH]){
if(lastLength || !separatorCopy.test(''))output.push('');
} else output.push(string.slice(lastLastIndex));
return output[LENGTH] > splitLimit ? output.slice(0, splitLimit) : output;
};
// Chakra, V8
} else if('0'[$SPLIT](undefined, 0)[LENGTH]){
$split = function(separator, limit){
return separator === undefined && limit === 0 ? [] : _split.call(this, separator, limit);
};
}
// 21.1.3.17 String.prototype.split(separator, limit)
return function split(separator, limit){
'use strict';
return [function split(separator, limit){
var O = defined(this)
, fn = separator == undefined ? undefined : separator[SPLIT];
return fn !== undefined
? fn.call(separator, O, limit)
: $split.call(String(O), separator, limit);
};
return fn !== undefined ? fn.call(separator, O, limit) : $split.call(String(O), separator, limit);
}, $split];
});
62 changes: 62 additions & 0 deletions tests/es.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 7a90ad4

Please sign in to comment.