jscript: Fix handling empty string regexp matches in String.prototype.split implementation.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
0189cf21ce
commit
b48cc9614e
|
@ -1131,21 +1131,20 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
|
||||||
jsval_t *r)
|
jsval_t *r)
|
||||||
{
|
{
|
||||||
match_state_t match_result, *match_ptr = &match_result;
|
match_state_t match_result, *match_ptr = &match_result;
|
||||||
DWORD length, i, match_len = 0;
|
size_t length, i = 0, match_len = 0;
|
||||||
const WCHAR *ptr, *ptr2, *str, *match_str = NULL;
|
const WCHAR *ptr, *ptr2, *str, *match_str = NULL;
|
||||||
unsigned limit = ~0u;
|
unsigned limit = ~0u;
|
||||||
jsdisp_t *array, *regexp = NULL;
|
jsdisp_t *array, *regexp = NULL;
|
||||||
jsstr_t *jsstr, *match_jsstr, *tmp_str;
|
jsstr_t *jsstr, *match_jsstr, *tmp_str;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
TRACE("\n");
|
|
||||||
|
|
||||||
hres = get_string_flat_val(ctx, jsthis, &jsstr, &str);
|
hres = get_string_flat_val(ctx, jsthis, &jsstr, &str);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
return hres;
|
return hres;
|
||||||
|
|
||||||
length = jsstr_length(jsstr);
|
length = jsstr_length(jsstr);
|
||||||
|
|
||||||
|
TRACE("%s\n", debugstr_wn(str, length));
|
||||||
|
|
||||||
if(!argc || (is_undefined(argv[0]) && ctx->version >= SCRIPTLANGUAGEVERSION_ES5)) {
|
if(!argc || (is_undefined(argv[0]) && ctx->version >= SCRIPTLANGUAGEVERSION_ES5)) {
|
||||||
if(!r)
|
if(!r)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -1203,11 +1202,29 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
|
||||||
if(SUCCEEDED(hres)) {
|
if(SUCCEEDED(hres)) {
|
||||||
ptr = str;
|
ptr = str;
|
||||||
match_result.cp = str;
|
match_result.cp = str;
|
||||||
for(i=0; i<limit; i++) {
|
while(i < limit) {
|
||||||
if(regexp) {
|
if(regexp) {
|
||||||
hres = regexp_match_next(ctx, regexp, REM_NO_PARENS, jsstr, &match_ptr);
|
hres = regexp_match_next(ctx, regexp, REM_NO_PARENS, jsstr, &match_ptr);
|
||||||
if(hres != S_OK)
|
if(hres != S_OK)
|
||||||
break;
|
break;
|
||||||
|
TRACE("got match %d %d\n", (int)(match_result.cp - match_result.match_len - str), match_result.match_len);
|
||||||
|
if(!match_result.match_len) {
|
||||||
|
/* If an empty string is matched, prevent including any match in the result */
|
||||||
|
if(!length) {
|
||||||
|
limit = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(match_result.cp == ptr) {
|
||||||
|
match_result.cp++;
|
||||||
|
hres = regexp_match_next(ctx, regexp, REM_NO_PARENS, jsstr, &match_ptr);
|
||||||
|
if(hres != S_OK)
|
||||||
|
break;
|
||||||
|
TRACE("retried, got match %d %d\n", (int)(match_result.cp - match_result.match_len - str),
|
||||||
|
match_result.match_len);
|
||||||
|
}
|
||||||
|
if(!match_result.match_len && match_result.cp == str + length)
|
||||||
|
break;
|
||||||
|
}
|
||||||
ptr2 = match_result.cp - match_result.match_len;
|
ptr2 = match_result.cp - match_result.match_len;
|
||||||
}else if(match_str) {
|
}else if(match_str) {
|
||||||
ptr2 = strstrW(ptr, match_str);
|
ptr2 = strstrW(ptr, match_str);
|
||||||
|
@ -1219,16 +1236,18 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
|
||||||
ptr2 = ptr+1;
|
ptr2 = ptr+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp_str = jsstr_alloc_len(ptr, ptr2-ptr);
|
if(!regexp || ptr2 > ptr) {
|
||||||
if(!tmp_str) {
|
tmp_str = jsstr_alloc_len(ptr, ptr2-ptr);
|
||||||
hres = E_OUTOFMEMORY;
|
if(!tmp_str) {
|
||||||
break;
|
hres = E_OUTOFMEMORY;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
hres = jsdisp_propput_idx(array, i, jsval_string(tmp_str));
|
hres = jsdisp_propput_idx(array, i++, jsval_string(tmp_str));
|
||||||
jsstr_release(tmp_str);
|
jsstr_release(tmp_str);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(regexp)
|
if(regexp)
|
||||||
ptr = match_result.cp;
|
ptr = match_result.cp;
|
||||||
|
@ -1242,7 +1261,7 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
|
||||||
if(SUCCEEDED(hres) && (match_str || regexp) && i<limit) {
|
if(SUCCEEDED(hres) && (match_str || regexp) && i<limit) {
|
||||||
DWORD len = (str+length) - ptr;
|
DWORD len = (str+length) - ptr;
|
||||||
|
|
||||||
if(len || match_str) {
|
if(len || match_str || !length) {
|
||||||
tmp_str = jsstr_alloc_len(ptr, len);
|
tmp_str = jsstr_alloc_len(ptr, len);
|
||||||
|
|
||||||
if(tmp_str) {
|
if(tmp_str) {
|
||||||
|
|
|
@ -644,6 +644,43 @@ ok(typeof(r) === "object", "typeof(r) = " + typeof(r));
|
||||||
ok(r.length === 1, "r.length = " + r.length);
|
ok(r.length === 1, "r.length = " + r.length);
|
||||||
ok(r[0] === "", "r[0] = " + r[0]);
|
ok(r[0] === "", "r[0] = " + r[0]);
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
function test(string, separator, result) {
|
||||||
|
var r = string.split(separator);
|
||||||
|
ok(r == result, "\"" + string + "\".split(" + separator + ") returned " + r + " expected " + result);
|
||||||
|
}
|
||||||
|
|
||||||
|
test("test", /^|\s+/, "test");
|
||||||
|
test("test", /$|\s+/, "test");
|
||||||
|
test("test", /^|./, "t");
|
||||||
|
test("test", /.*/, "");
|
||||||
|
test("test", /x*/, "t,e,s,t");
|
||||||
|
test("test", /$|x*/, "t,e,s,t");
|
||||||
|
test("test", /^|x*/, "t,e,s,t");
|
||||||
|
test("test", /t*/, "e,s");
|
||||||
|
test("xaabaax", /a*|b*/, "x,b,x");
|
||||||
|
test("xaabaax", /a+|b+/, "x,x");
|
||||||
|
test("xaabaax", /a+|b*/, "x,x");
|
||||||
|
test("xaaxbaax", /b+|a+/, "x,x,x");
|
||||||
|
test("test", /^|t/, "tes");
|
||||||
|
test("test", /^|t/, "tes");
|
||||||
|
test("a,,b", /,/, "a,b");
|
||||||
|
test("ab", /a*/, "b");
|
||||||
|
test("aab", "a", ",,b");
|
||||||
|
test("a", "a", ",");
|
||||||
|
|
||||||
|
function test_length(string, separator, len) {
|
||||||
|
var r = string.split(separator);
|
||||||
|
ok(r.length === len, "\"" + string + "\".split(" + separator + ").length = "
|
||||||
|
+ r.length + " expected " + len);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_length("", /a*/, 0);
|
||||||
|
test_length("", /a+/, 1);
|
||||||
|
test_length("", "", 0);
|
||||||
|
test_length("", "x", 1);
|
||||||
|
})();
|
||||||
|
|
||||||
tmp = "abcd".indexOf("bc",0);
|
tmp = "abcd".indexOf("bc",0);
|
||||||
ok(tmp === 1, "indexOf = " + tmp);
|
ok(tmp === 1, "indexOf = " + tmp);
|
||||||
tmp = "abcd".indexOf("bc",1);
|
tmp = "abcd".indexOf("bc",1);
|
||||||
|
|
Loading…
Reference in New Issue