Jacek Caban : jscript: Fixed String. match implementation for non-global regexps.

Alexandre Julliard julliard at winehq.org
Thu Apr 15 11:37:36 CDT 2010


Module: wine
Branch: master
Commit: 6f17fa5298449114a8532778b8a6c0f8a5c505de
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6f17fa5298449114a8532778b8a6c0f8a5c505de

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Apr 15 12:38:38 2010 +0200

jscript: Fixed String.match implementation for non-global regexps.

---

 dlls/jscript/jscript.h       |    1 +
 dlls/jscript/regexp.c        |   81 ++++++++++++++++++++++++++++++++++++++++++
 dlls/jscript/string.c        |   59 +++++-------------------------
 dlls/jscript/tests/regexp.js |   27 ++++++++++++++
 4 files changed, 119 insertions(+), 49 deletions(-)

diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h
index 0068827..c1c8e60 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 a5d607e..7861d22 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, &regexp->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, &regexp->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 df43fee..510dcc2 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 513e56e..7b74cb1 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);




More information about the wine-cvs mailing list