jscript: Added support for RegExp.$* properties.

This commit is contained in:
Jacek Caban 2012-09-20 15:02:55 +02:00 committed by Alexandre Julliard
parent 1e5328c77c
commit 87d6e2385a
3 changed files with 151 additions and 5 deletions

View file

@ -299,6 +299,11 @@ typedef struct {
jsval_t val;
} jsexcept_t;
typedef struct {
const WCHAR *str;
DWORD len;
} match_result_t;
struct _script_ctx_t {
LONG ref;
@ -321,6 +326,7 @@ struct _script_ctx_t {
IDispatch *host_global;
BSTR last_match;
match_result_t match_parens[9];
DWORD last_match_index;
DWORD last_match_length;
@ -371,11 +377,6 @@ HRESULT create_vbarray_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDE
IUnknown *create_ax_site(script_ctx_t*) DECLSPEC_HIDDEN;
HRESULT create_jscaller(script_ctx_t*) DECLSPEC_HIDDEN;
typedef struct {
const WCHAR *str;
DWORD len;
} match_result_t;
#define REM_CHECK_GLOBAL 0x0001
#define REM_RESET_INDEX 0x0002
#define REM_NO_CTX_UPDATE 0x0004

View file

@ -101,6 +101,16 @@ static const WCHAR leftContextW[] =
static const WCHAR rightContextW[] =
{'r','i','g','h','t','C','o','n','t','e','x','t',0};
static const WCHAR idx1W[] = {'$','1',0};
static const WCHAR idx2W[] = {'$','2',0};
static const WCHAR idx3W[] = {'$','3',0};
static const WCHAR idx4W[] = {'$','4',0};
static const WCHAR idx5W[] = {'$','5',0};
static const WCHAR idx6W[] = {'$','6',0};
static const WCHAR idx7W[] = {'$','7',0};
static const WCHAR idx8W[] = {'$','8',0};
static const WCHAR idx9W[] = {'$','9',0};
static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
static const WCHAR emptyW[] = {0};
@ -3388,6 +3398,23 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, D
}
}
if(!(rem_flags & REM_NO_CTX_UPDATE)) {
DWORD i, n = min(sizeof(ctx->match_parens)/sizeof(ctx->match_parens[0]), regexp->jsregexp->parenCount);
for(i=0; i < n; i++) {
if(result->parens[i].index == -1) {
ctx->match_parens[i].str = NULL;
ctx->match_parens[i].len = 0;
}else {
ctx->match_parens[i].str = ctx->last_match + result->parens[i].index;
ctx->match_parens[i].len = result->parens[i].length;
}
}
if(n < sizeof(ctx->match_parens)/sizeof(ctx->match_parens[0]))
memset(ctx->match_parens+n, 0, sizeof(ctx->match_parens) - n*sizeof(ctx->match_parens[0]));
}
matchlen = (result->cp-*cp) - gData.skipped;
*cp = result->cp;
ret->str = result->cp-matchlen;
@ -4000,6 +4027,92 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, BSTR str, jsval_t *
return hres;
}
static HRESULT global_idx(script_ctx_t *ctx, DWORD flags, DWORD idx, jsval_t *r)
{
switch(flags) {
case DISPATCH_PROPERTYGET: {
BSTR ret = NULL;
ret = SysAllocStringLen(ctx->match_parens[idx].str, ctx->match_parens[idx].len);
if(!ret)
return E_OUTOFMEMORY;
*r = jsval_string(ret);
break;
}
case DISPATCH_PROPERTYPUT:
break;
default:
FIXME("unsupported flags\n");
return E_NOTIMPL;
}
return S_OK;
}
static HRESULT RegExpConstr_idx1(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
return global_idx(ctx, flags, 0, r);
}
static HRESULT RegExpConstr_idx2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
return global_idx(ctx, flags, 1, r);
}
static HRESULT RegExpConstr_idx3(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
return global_idx(ctx, flags, 2, r);
}
static HRESULT RegExpConstr_idx4(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
return global_idx(ctx, flags, 3, r);
}
static HRESULT RegExpConstr_idx5(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
return global_idx(ctx, flags, 4, r);
}
static HRESULT RegExpConstr_idx6(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
return global_idx(ctx, flags, 5, r);
}
static HRESULT RegExpConstr_idx7(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
return global_idx(ctx, flags, 6, r);
}
static HRESULT RegExpConstr_idx8(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
return global_idx(ctx, flags, 7, r);
}
static HRESULT RegExpConstr_idx9(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
return global_idx(ctx, flags, 8, r);
}
static HRESULT RegExpConstr_leftContext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
unsigned argc, jsval_t *argv, jsval_t *r)
{
@ -4108,6 +4221,15 @@ static HRESULT RegExpConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
}
static const builtin_prop_t RegExpConstr_props[] = {
{idx1W, RegExpConstr_idx1, 0},
{idx2W, RegExpConstr_idx2, 0},
{idx3W, RegExpConstr_idx3, 0},
{idx4W, RegExpConstr_idx4, 0},
{idx5W, RegExpConstr_idx5, 0},
{idx6W, RegExpConstr_idx6, 0},
{idx7W, RegExpConstr_idx7, 0},
{idx8W, RegExpConstr_idx8, 0},
{idx9W, RegExpConstr_idx9, 0},
{leftContextW, RegExpConstr_leftContext, 0},
{rightContextW, RegExpConstr_rightContext, 0}
};

View file

@ -598,4 +598,27 @@ ok(tmp === "x*y", '"x/y".replace(/[/]/, "*") = ' + tmp);
tmp = "x/y".replace(/[xy/]/g, "*");
ok(tmp === "***", '"x/y".replace(/[xy/]/, "*") = ' + tmp);
/(b)/.exec("abc");
ok(RegExp.$1 === "b", "RegExp.$1 = " + RegExp.$1);
ok("$2" in RegExp, "RegExp.$2 doesn't exist");
ok(RegExp.$2 === "", "RegExp.$2 = " + RegExp.$2);
ok(RegExp.$9 === "", "RegExp.$9 = " + RegExp.$9);
ok(!("$10" in RegExp), "RegExp.$10 exists");
/(b)(b)(b)(b)(b)(b)(b)(b)(b)(b)(b)/.exec("abbbbbbbbbbbc");
ok(RegExp.$1 === "b", "RegExp.$1 = " + RegExp.$1);
ok(RegExp.$2 === "b", "[2] RegExp.$2 = " + RegExp.$2);
ok(RegExp.$9 === "b", "RegExp.$9 = " + RegExp.$9);
ok(!("$10" in RegExp), "RegExp.$10 exists");
/(b)/.exec("abc");
ok(RegExp.$1 === "b", "RegExp.$1 = " + RegExp.$1);
ok("$2" in RegExp, "RegExp.$2 doesn't exist");
ok(RegExp.$2 === "", "RegExp.$2 = " + RegExp.$2);
ok(RegExp.$9 === "", "RegExp.$9 = " + RegExp.$9);
ok(!("$10" in RegExp), "RegExp.$10 exists");
RegExp.$1 = "a";
ok(RegExp.$1 === "b", "RegExp.$1 = " + RegExp.$1);
reportSuccess();