jscript: Fixed String.match implementation for non-global regexps.
This commit is contained in:
parent
e3ae02433a
commit
6f17fa5298
|
@ -324,6 +324,7 @@ HRESULT regexp_match_next(script_ctx_t*,DispatchEx*,DWORD,const WCHAR*,DWORD,con
|
||||||
DWORD*,DWORD*,match_result_t*);
|
DWORD*,DWORD*,match_result_t*);
|
||||||
HRESULT regexp_match(script_ctx_t*,DispatchEx*,const WCHAR*,DWORD,BOOL,match_result_t**,DWORD*);
|
HRESULT regexp_match(script_ctx_t*,DispatchEx*,const WCHAR*,DWORD,BOOL,match_result_t**,DWORD*);
|
||||||
HRESULT parse_regexp_flags(const WCHAR*,DWORD,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)
|
static inline VARIANT *get_arg(DISPPARAMS *dp, DWORD i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
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,
|
static HRESULT RegExpConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
|
||||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||||
{
|
{
|
||||||
const WCHAR *str;
|
const WCHAR *str;
|
||||||
match_result_t *match_result;
|
|
||||||
DispatchEx *regexp;
|
DispatchEx *regexp;
|
||||||
DispatchEx *array;
|
VARIANT *arg_var;
|
||||||
VARIANT var, *arg_var;
|
DWORD length;
|
||||||
DWORD length, match_cnt, i;
|
|
||||||
BSTR val_str = NULL;
|
BSTR val_str = NULL;
|
||||||
HRESULT hres = S_OK;
|
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:
|
case VT_DISPATCH:
|
||||||
regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var));
|
regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var));
|
||||||
if(regexp) {
|
if(regexp) {
|
||||||
if(regexp->builtin_info->class == JSCLASS_REGEXP)
|
if(is_class(regexp, JSCLASS_REGEXP))
|
||||||
break;
|
break;
|
||||||
jsdisp_release(regexp);
|
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);
|
hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
|
||||||
if(SUCCEEDED(hres))
|
if(SUCCEEDED(hres)) {
|
||||||
hres = regexp_match(ctx, regexp, str, length, FALSE, &match_result, &match_cnt);
|
if(!val_str)
|
||||||
jsdisp_release(regexp);
|
val_str = SysAllocStringLen(str, length);
|
||||||
if(FAILED(hres)) {
|
if(val_str)
|
||||||
SysFreeString(val_str);
|
hres = regexp_string_match(ctx, regexp, val_str, retv, ei);
|
||||||
return hres;
|
else
|
||||||
}
|
|
||||||
|
|
||||||
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)) {
|
|
||||||
hres = E_OUTOFMEMORY;
|
hres = E_OUTOFMEMORY;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = jsdisp_propput_idx(array, i, &var, ei, NULL/*FIXME*/);
|
jsdisp_release(regexp);
|
||||||
SysFreeString(V_BSTR(&var));
|
|
||||||
if(FAILED(hres))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
heap_free(match_result);
|
|
||||||
SysFreeString(val_str);
|
SysFreeString(val_str);
|
||||||
|
|
||||||
if(SUCCEEDED(hres) && retv) {
|
|
||||||
V_VT(retv) = VT_DISPATCH;
|
|
||||||
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(array);
|
|
||||||
}else {
|
|
||||||
jsdisp_release(array);
|
|
||||||
}
|
|
||||||
return hres;
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,7 @@ ok(typeof(m) === "object", "typeof m is not object");
|
||||||
ok(m.length === 2, "m.length is not 2");
|
ok(m.length === 2, "m.length is not 2");
|
||||||
ok(m["0"] === "ab", "m[0] is not \"ab\"");
|
ok(m["0"] === "ab", "m[0] is not \"ab\"");
|
||||||
ok(m["1"] === "ab", "m[1] 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);
|
m = "abcabc".match(/Ab/g);
|
||||||
ok(typeof(m) === "object", "typeof m is not object");
|
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();
|
m = "abcabc".match();
|
||||||
ok(m === null, "m is not null");
|
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");
|
r = "- [test] -".replace(re = /\[([^\[]+)\]/g, "success");
|
||||||
ok(r === "- success -", "r = " + r + " expected '- success -'");
|
ok(r === "- success -", "r = " + r + " expected '- success -'");
|
||||||
ok(re.lastIndex === 8, "re.lastIndex = " + re.lastIndex);
|
ok(re.lastIndex === 8, "re.lastIndex = " + re.lastIndex);
|
||||||
|
|
Loading…
Reference in New Issue