diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 00688273de8..c1c8e60f35b 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -324,6 +324,7 @@ HRESULT regexp_match_next(script_ctx_t*,DispatchEx*,DWORD,const WCHAR*,DWORD,con DWORD*,DWORD*,match_result_t*); HRESULT regexp_match(script_ctx_t*,DispatchEx*,const WCHAR*,DWORD,BOOL,match_result_t**,DWORD*); HRESULT parse_regexp_flags(const WCHAR*,DWORD,DWORD*); +HRESULT regexp_string_match(script_ctx_t*,DispatchEx*,BSTR,VARIANT*,jsexcept_t*); static inline VARIANT *get_arg(DISPPARAMS *dp, DWORD i) { diff --git a/dlls/jscript/regexp.c b/dlls/jscript/regexp.c index a5d607e7f87..7861d229826 100644 --- a/dlls/jscript/regexp.c +++ b/dlls/jscript/regexp.c @@ -3878,6 +3878,87 @@ HRESULT create_regexp_var(script_ctx_t *ctx, VARIANT *src_arg, VARIANT *flags_ar return create_regexp(ctx, src, -1, flags, ret); } +HRESULT regexp_string_match(script_ctx_t *ctx, DispatchEx *re, BSTR str, + VARIANT *retv, jsexcept_t *ei) +{ + RegExpInstance *regexp = (RegExpInstance*)re; + match_result_t *match_result; + DWORD match_cnt, i, length; + DispatchEx *array; + VARIANT var; + HRESULT hres; + + length = SysStringLen(str); + + if(!(regexp->jsregexp->flags & JSREG_GLOB)) { + match_result_t match, *parens = NULL; + DWORD parens_cnt, parens_size = 0; + const WCHAR *cp = str; + + hres = regexp_match_next(ctx, ®exp->dispex, 0, str, length, &cp, &parens, &parens_size, &parens_cnt, &match); + if(FAILED(hres)) + return hres; + + if(retv) { + if(hres == S_OK) { + IDispatch *ret; + + hres = create_match_array(ctx, str, &match, parens, parens_cnt, ei, &ret); + if(SUCCEEDED(hres)) { + V_VT(retv) = VT_DISPATCH; + V_DISPATCH(retv) = ret; + } + }else { + V_VT(retv) = VT_NULL; + } + } + + heap_free(parens); + return S_OK; + } + + hres = regexp_match(ctx, ®exp->dispex, str, length, FALSE, &match_result, &match_cnt); + if(FAILED(hres)) + return hres; + + if(!match_cnt) { + TRACE("no match\n"); + + if(retv) + V_VT(retv) = VT_NULL; + return S_OK; + } + + hres = create_array(ctx, match_cnt, &array); + if(FAILED(hres)) + return hres; + + V_VT(&var) = VT_BSTR; + + for(i=0; i < match_cnt; i++) { + V_BSTR(&var) = SysAllocStringLen(match_result[i].str, match_result[i].len); + if(!V_BSTR(&var)) { + hres = E_OUTOFMEMORY; + break; + } + + hres = jsdisp_propput_idx(array, i, &var, ei, NULL/*FIXME*/); + SysFreeString(V_BSTR(&var)); + if(FAILED(hres)) + break; + } + + heap_free(match_result); + + if(SUCCEEDED(hres) && retv) { + V_VT(retv) = VT_DISPATCH; + V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(array); + }else { + jsdisp_release(array); + } + return hres; +} + static HRESULT RegExpConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) { diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index df43fee27ed..510dcc272c6 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -622,11 +622,9 @@ static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) { const WCHAR *str; - match_result_t *match_result; DispatchEx *regexp; - DispatchEx *array; - VARIANT var, *arg_var; - DWORD length, match_cnt, i; + VARIANT *arg_var; + DWORD length; BSTR val_str = NULL; HRESULT hres = S_OK; @@ -645,7 +643,7 @@ static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP case VT_DISPATCH: regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var)); if(regexp) { - if(regexp->builtin_info->class == JSCLASS_REGEXP) + if(is_class(regexp, JSCLASS_REGEXP)) break; jsdisp_release(regexp); } @@ -664,54 +662,17 @@ static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP } hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str); - if(SUCCEEDED(hres)) - hres = regexp_match(ctx, regexp, str, length, FALSE, &match_result, &match_cnt); - jsdisp_release(regexp); - if(FAILED(hres)) { - SysFreeString(val_str); - return hres; - } - - if(!match_cnt) { - TRACE("no match\n"); - - if(retv) - V_VT(retv) = VT_NULL; - - SysFreeString(val_str); - return S_OK; - } - - hres = create_array(ctx, match_cnt, &array); - if(FAILED(hres)) { - SysFreeString(val_str); - return hres; - } - - V_VT(&var) = VT_BSTR; - - for(i=0; i < match_cnt; i++) { - V_BSTR(&var) = SysAllocStringLen(match_result[i].str, match_result[i].len); - if(!V_BSTR(&var)) { + if(SUCCEEDED(hres)) { + if(!val_str) + val_str = SysAllocStringLen(str, length); + if(val_str) + hres = regexp_string_match(ctx, regexp, val_str, retv, ei); + else hres = E_OUTOFMEMORY; - break; - } - - hres = jsdisp_propput_idx(array, i, &var, ei, NULL/*FIXME*/); - SysFreeString(V_BSTR(&var)); - if(FAILED(hres)) - break; } - heap_free(match_result); + jsdisp_release(regexp); SysFreeString(val_str); - - if(SUCCEEDED(hres) && retv) { - V_VT(retv) = VT_DISPATCH; - V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(array); - }else { - jsdisp_release(array); - } return hres; } diff --git a/dlls/jscript/tests/regexp.js b/dlls/jscript/tests/regexp.js index 513e56ed407..7b74cb11421 100644 --- a/dlls/jscript/tests/regexp.js +++ b/dlls/jscript/tests/regexp.js @@ -113,6 +113,7 @@ ok(typeof(m) === "object", "typeof m is not object"); ok(m.length === 2, "m.length is not 2"); ok(m["0"] === "ab", "m[0] is not \"ab\""); ok(m["1"] === "ab", "m[1] is not \"ab\""); +/* ok(m.input === "abcabc", "m.input = " + m.input); */ m = "abcabc".match(/Ab/g); ok(typeof(m) === "object", "typeof m is not object"); @@ -167,6 +168,32 @@ ok(m["0"] === "ab", "m[0] is not \"ab\""); m = "abcabc".match(); ok(m === null, "m is not null"); +m = "abcabc".match(/(a)(b)cabc/); +ok(typeof(m) === "object", "typeof m is not object"); +ok(m.length === 3, "m.length is not 3"); +ok(m[0] === "abcabc", "m[0] is not \"abc\""); +ok(m[1] === "a", "m[1] is not \"a\""); +ok(m[2] === "b", "m[2] is not \"b\""); + +re = /(a)bcabc/; +re.lastIndex = -3; +m = "abcabc".match(re); +ok(typeof(m) === "object", "typeof m is not object"); +ok(m.length === 2, "m.length = " + m.length + "expected 3"); +ok(m[0] === "abcabc", "m[0] is not \"abc\""); +ok(m[1] === "a", "m[1] is not \"a\""); +ok(re.lastIndex === 6, "re.lastIndex = " + re.lastIndex); + +re = /(a)bcabc/; +re.lastIndex = 2; +m = "abcabcxxx".match(re); +ok(typeof(m) === "object", "typeof m is not object"); +ok(m.length === 2, "m.length = " + m.length + "expected 3"); +ok(m[0] === "abcabc", "m[0] is not \"abc\""); +ok(m[1] === "a", "m[1] is not \"a\""); +ok(m.input === "abcabcxxx", "m.input = " + m.input); +ok(re.lastIndex === 6, "re.lastIndex = " + re.lastIndex); + r = "- [test] -".replace(re = /\[([^\[]+)\]/g, "success"); ok(r === "- success -", "r = " + r + " expected '- success -'"); ok(re.lastIndex === 8, "re.lastIndex = " + re.lastIndex);