2 * Copyright 2008 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(jscript
);
34 jsval_t last_index_val
;
37 static const WCHAR sourceW
[] = {'s','o','u','r','c','e',0};
38 static const WCHAR globalW
[] = {'g','l','o','b','a','l',0};
39 static const WCHAR ignoreCaseW
[] = {'i','g','n','o','r','e','C','a','s','e',0};
40 static const WCHAR multilineW
[] = {'m','u','l','t','i','l','i','n','e',0};
41 static const WCHAR lastIndexW
[] = {'l','a','s','t','I','n','d','e','x',0};
42 static const WCHAR toStringW
[] = {'t','o','S','t','r','i','n','g',0};
43 static const WCHAR execW
[] = {'e','x','e','c',0};
44 static const WCHAR testW
[] = {'t','e','s','t',0};
46 static const WCHAR leftContextW
[] =
47 {'l','e','f','t','C','o','n','t','e','x','t',0};
48 static const WCHAR rightContextW
[] =
49 {'r','i','g','h','t','C','o','n','t','e','x','t',0};
51 static const WCHAR idx1W
[] = {'$','1',0};
52 static const WCHAR idx2W
[] = {'$','2',0};
53 static const WCHAR idx3W
[] = {'$','3',0};
54 static const WCHAR idx4W
[] = {'$','4',0};
55 static const WCHAR idx5W
[] = {'$','5',0};
56 static const WCHAR idx6W
[] = {'$','6',0};
57 static const WCHAR idx7W
[] = {'$','7',0};
58 static const WCHAR idx8W
[] = {'$','8',0};
59 static const WCHAR idx9W
[] = {'$','9',0};
61 static const WCHAR undefinedW
[] = {'u','n','d','e','f','i','n','e','d',0};
62 static const WCHAR emptyW
[] = {0};
64 static inline RegExpInstance
*regexp_from_vdisp(vdisp_t
*vdisp
)
66 return (RegExpInstance
*)vdisp
->u
.jsdisp
;
69 static void set_last_index(RegExpInstance
*This
, DWORD last_index
)
71 This
->last_index
= last_index
;
72 jsval_release(This
->last_index_val
);
73 This
->last_index_val
= jsval_number(last_index
);
76 static HRESULT
do_regexp_match_next(script_ctx_t
*ctx
, RegExpInstance
*regexp
, DWORD rem_flags
,
77 jsstr_t
*str
, const WCHAR
**cp
, match_result_t
**parens
, DWORD
*parens_size
,
78 DWORD
*parens_cnt
, match_result_t
*ret
)
84 hres
= MatchRegExpNext(regexp
->jsregexp
, str
->str
, jsstr_length(str
),
85 cp
, &ctx
->tmp_heap
, &result
, &matchlen
);
89 if(rem_flags
& REM_RESET_INDEX
)
90 set_last_index(regexp
, 0);
95 if(regexp
->jsregexp
->parenCount
> *parens_size
) {
96 match_result_t
*new_parens
;
99 new_parens
= heap_realloc(*parens
, sizeof(match_result_t
)*regexp
->jsregexp
->parenCount
);
101 new_parens
= heap_alloc(sizeof(match_result_t
)*regexp
->jsregexp
->parenCount
);
103 return E_OUTOFMEMORY
;
105 *parens_size
= regexp
->jsregexp
->parenCount
;
106 *parens
= new_parens
;
110 if(!(rem_flags
& REM_NO_CTX_UPDATE
) && ctx
->last_match
!= str
) {
111 jsstr_release(ctx
->last_match
);
112 ctx
->last_match
= jsstr_addref(str
);
118 *parens_cnt
= regexp
->jsregexp
->parenCount
;
120 for(i
=0; i
< regexp
->jsregexp
->parenCount
; i
++) {
121 if(result
->parens
[i
].index
== -1) {
122 (*parens
)[i
].str
= NULL
;
123 (*parens
)[i
].len
= 0;
125 (*parens
)[i
].str
= str
->str
+ result
->parens
[i
].index
;
126 (*parens
)[i
].len
= result
->parens
[i
].length
;
131 if(!(rem_flags
& REM_NO_CTX_UPDATE
)) {
132 DWORD i
, n
= min(sizeof(ctx
->match_parens
)/sizeof(ctx
->match_parens
[0]), regexp
->jsregexp
->parenCount
);
134 for(i
=0; i
< n
; i
++) {
135 if(result
->parens
[i
].index
== -1) {
136 ctx
->match_parens
[i
].str
= NULL
;
137 ctx
->match_parens
[i
].len
= 0;
139 ctx
->match_parens
[i
].str
= ctx
->last_match
->str
+ result
->parens
[i
].index
;
140 ctx
->match_parens
[i
].len
= result
->parens
[i
].length
;
144 if(n
< sizeof(ctx
->match_parens
)/sizeof(ctx
->match_parens
[0]))
145 memset(ctx
->match_parens
+n
, 0, sizeof(ctx
->match_parens
) - n
*sizeof(ctx
->match_parens
[0]));
148 ret
->str
= result
->cp
-matchlen
;
150 set_last_index(regexp
, result
->cp
-str
->str
);
152 if(!(rem_flags
& REM_NO_CTX_UPDATE
)) {
153 ctx
->last_match_index
= ret
->str
-str
->str
;
154 ctx
->last_match_length
= matchlen
;
160 HRESULT
regexp_match_next(script_ctx_t
*ctx
, jsdisp_t
*dispex
, DWORD rem_flags
, jsstr_t
*str
,
161 const WCHAR
**cp
, match_result_t
**parens
, DWORD
*parens_size
, DWORD
*parens_cnt
,
164 RegExpInstance
*regexp
= (RegExpInstance
*)dispex
;
168 if((rem_flags
& REM_CHECK_GLOBAL
) && !(regexp
->jsregexp
->flags
& JSREG_GLOB
))
171 mark
= heap_pool_mark(&ctx
->tmp_heap
);
173 hres
= do_regexp_match_next(ctx
, regexp
, rem_flags
, str
, cp
, parens
, parens_size
, parens_cnt
, ret
);
175 heap_pool_clear(mark
);
179 static HRESULT
regexp_match(script_ctx_t
*ctx
, jsdisp_t
*dispex
, jsstr_t
*str
, BOOL gflag
,
180 match_result_t
**match_result
, DWORD
*result_cnt
)
182 RegExpInstance
*This
= (RegExpInstance
*)dispex
;
183 match_result_t
*ret
= NULL
, cres
;
184 const WCHAR
*cp
= str
->str
;
185 DWORD i
=0, ret_size
= 0;
189 mark
= heap_pool_mark(&ctx
->tmp_heap
);
192 hres
= do_regexp_match_next(ctx
, This
, 0, str
, &cp
, NULL
, NULL
, NULL
, &cres
);
193 if(hres
== S_FALSE
) {
203 match_result_t
*old_ret
= ret
;
205 ret
= heap_realloc(old_ret
, (ret_size
<<= 1) * sizeof(match_result_t
));
209 ret
= heap_alloc((ret_size
=4) * sizeof(match_result_t
));
212 hres
= E_OUTOFMEMORY
;
219 if(!gflag
&& !(This
->jsregexp
->flags
& JSREG_GLOB
)) {
225 heap_pool_clear(mark
);
236 static HRESULT
RegExp_source(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
242 case DISPATCH_PROPERTYGET
: {
243 RegExpInstance
*This
= regexp_from_vdisp(jsthis
);
244 *r
= jsval_string(jsstr_addref(This
->str
));
248 FIXME("Unimplemented flags %x\n", flags
);
255 static HRESULT
RegExp_global(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
262 static HRESULT
RegExp_ignoreCase(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
269 static HRESULT
RegExp_multiline(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
276 static INT
index_from_val(script_ctx_t
*ctx
, jsval_t v
)
281 hres
= to_number(ctx
, v
, &n
);
283 clear_ei(ctx
); /* FIXME: Move ignoring exceptions to to_primitive */
288 return is_int32(n
) ? n
: 0;
291 static HRESULT
RegExp_lastIndex(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
297 case DISPATCH_PROPERTYGET
: {
298 RegExpInstance
*regexp
= regexp_from_vdisp(jsthis
);
300 return jsval_copy(regexp
->last_index_val
, r
);
302 case DISPATCH_PROPERTYPUT
: {
303 RegExpInstance
*regexp
= regexp_from_vdisp(jsthis
);
306 hres
= jsval_copy(argv
[0], ®exp
->last_index_val
);
310 regexp
->last_index
= index_from_val(ctx
, argv
[0]);
314 FIXME("unimplemented flags: %x\n", flags
);
321 static HRESULT
RegExp_toString(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
328 static HRESULT
create_match_array(script_ctx_t
*ctx
, jsstr_t
*input
, const match_result_t
*result
,
329 const match_result_t
*parens
, DWORD parens_cnt
, IDispatch
**ret
)
336 static const WCHAR indexW
[] = {'i','n','d','e','x',0};
337 static const WCHAR inputW
[] = {'i','n','p','u','t',0};
338 static const WCHAR lastIndexW
[] = {'l','a','s','t','I','n','d','e','x',0};
339 static const WCHAR zeroW
[] = {'0',0};
341 hres
= create_array(ctx
, parens_cnt
+1, &array
);
345 for(i
=0; i
< parens_cnt
; i
++) {
346 str
= jsstr_alloc_len(parens
[i
].str
, parens
[i
].len
);
348 hres
= E_OUTOFMEMORY
;
352 hres
= jsdisp_propput_idx(array
, i
+1, jsval_string(str
));
358 while(SUCCEEDED(hres
)) {
359 hres
= jsdisp_propput_name(array
, indexW
, jsval_number(result
->str
-input
->str
));
363 hres
= jsdisp_propput_name(array
, lastIndexW
, jsval_number(result
->str
-input
->str
+result
->len
));
367 hres
= jsdisp_propput_name(array
, inputW
, jsval_string(jsstr_addref(input
)));
371 str
= jsstr_alloc_len(result
->str
, result
->len
);
373 hres
= E_OUTOFMEMORY
;
376 hres
= jsdisp_propput_name(array
, zeroW
, jsval_string(str
));
382 jsdisp_release(array
);
386 *ret
= to_disp(array
);
390 static HRESULT
run_exec(script_ctx_t
*ctx
, vdisp_t
*jsthis
, jsval_t arg
, jsstr_t
**input
,
391 match_result_t
*match
, match_result_t
**parens
, DWORD
*parens_cnt
, BOOL
*ret
)
393 RegExpInstance
*regexp
;
394 DWORD parens_size
= 0, last_index
= 0;
399 if(!is_vclass(jsthis
, JSCLASS_REGEXP
)) {
400 FIXME("Not a RegExp\n");
404 regexp
= regexp_from_vdisp(jsthis
);
406 hres
= to_string(ctx
, arg
, &string
);
410 if(regexp
->jsregexp
->flags
& JSREG_GLOB
) {
411 if(regexp
->last_index
< 0) {
412 jsstr_release(string
);
413 set_last_index(regexp
, 0);
416 *input
= jsstr_empty();
420 last_index
= regexp
->last_index
;
423 cp
= string
->str
+ last_index
;
424 hres
= regexp_match_next(ctx
, ®exp
->dispex
, REM_RESET_INDEX
, string
, &cp
, parens
,
425 parens
? &parens_size
: NULL
, parens_cnt
, match
);
427 jsstr_release(string
);
435 jsstr_release(string
);
439 static HRESULT
RegExp_exec(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
442 match_result_t
*parens
= NULL
, match
;
443 DWORD parens_cnt
= 0;
450 hres
= run_exec(ctx
, jsthis
, argc
? argv
[0] : jsval_string(jsstr_empty()), &string
, &match
, &parens
, &parens_cnt
, &b
);
460 hres
= create_match_array(ctx
, string
, &match
, parens
, parens_cnt
, &ret
);
462 *r
= jsval_disp(ret
);
469 jsstr_release(string
);
473 static HRESULT
RegExp_test(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
476 match_result_t match
;
484 undef_str
= jsstr_alloc(undefinedW
);
486 return E_OUTOFMEMORY
;
489 hres
= run_exec(ctx
, jsthis
, argc
? argv
[0] : jsval_string(undef_str
), NULL
, &match
, NULL
, NULL
, &b
);
491 jsstr_release(undef_str
);
500 static HRESULT
RegExp_value(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
507 return throw_type_error(ctx
, JS_E_FUNCTION_EXPECTED
, NULL
);
509 FIXME("unimplemented flags %x\n", flags
);
516 static void RegExp_destructor(jsdisp_t
*dispex
)
518 RegExpInstance
*This
= (RegExpInstance
*)dispex
;
521 js_DestroyRegExp(This
->jsregexp
);
522 jsval_release(This
->last_index_val
);
523 jsstr_release(This
->str
);
527 static const builtin_prop_t RegExp_props
[] = {
528 {execW
, RegExp_exec
, PROPF_METHOD
|1},
529 {globalW
, RegExp_global
, 0},
530 {ignoreCaseW
, RegExp_ignoreCase
, 0},
531 {lastIndexW
, RegExp_lastIndex
, 0},
532 {multilineW
, RegExp_multiline
, 0},
533 {sourceW
, RegExp_source
, 0},
534 {testW
, RegExp_test
, PROPF_METHOD
|1},
535 {toStringW
, RegExp_toString
, PROPF_METHOD
}
538 static const builtin_info_t RegExp_info
= {
540 {NULL
, RegExp_value
, 0},
541 sizeof(RegExp_props
)/sizeof(*RegExp_props
),
547 static const builtin_prop_t RegExpInst_props
[] = {
548 {globalW
, RegExp_global
, 0},
549 {ignoreCaseW
, RegExp_ignoreCase
, 0},
550 {lastIndexW
, RegExp_lastIndex
, 0},
551 {multilineW
, RegExp_multiline
, 0},
552 {sourceW
, RegExp_source
, 0}
555 static const builtin_info_t RegExpInst_info
= {
557 {NULL
, RegExp_value
, 0},
558 sizeof(RegExpInst_props
)/sizeof(*RegExpInst_props
),
564 static HRESULT
alloc_regexp(script_ctx_t
*ctx
, jsdisp_t
*object_prototype
, RegExpInstance
**ret
)
566 RegExpInstance
*regexp
;
569 regexp
= heap_alloc_zero(sizeof(RegExpInstance
));
571 return E_OUTOFMEMORY
;
574 hres
= init_dispex(®exp
->dispex
, ctx
, &RegExp_info
, object_prototype
);
576 hres
= init_dispex_from_constr(®exp
->dispex
, ctx
, &RegExpInst_info
, ctx
->regexp_constr
);
587 HRESULT
create_regexp(script_ctx_t
*ctx
, jsstr_t
*src
, DWORD flags
, jsdisp_t
**ret
)
589 RegExpInstance
*regexp
;
592 TRACE("%s %x\n", debugstr_jsstr(src
), flags
);
594 hres
= alloc_regexp(ctx
, NULL
, ®exp
);
598 regexp
->str
= jsstr_addref(src
);
599 regexp
->last_index_val
= jsval_number(0);
601 regexp
->jsregexp
= js_NewRegExp(ctx
, &ctx
->tmp_heap
, regexp
->str
->str
,
602 jsstr_length(regexp
->str
), flags
, FALSE
);
603 if(!regexp
->jsregexp
) {
604 WARN("js_NewRegExp failed\n");
605 jsdisp_release(®exp
->dispex
);
609 *ret
= ®exp
->dispex
;
613 HRESULT
create_regexp_var(script_ctx_t
*ctx
, jsval_t src_arg
, jsval_t
*flags_arg
, jsdisp_t
**ret
)
615 jsstr_t
*src
, *opt
= NULL
;
619 if(is_object_instance(src_arg
)) {
622 obj
= iface_to_jsdisp((IUnknown
*)get_object(src_arg
));
624 if(is_class(obj
, JSCLASS_REGEXP
)) {
625 RegExpInstance
*regexp
= (RegExpInstance
*)obj
;
627 hres
= create_regexp(ctx
, regexp
->str
, regexp
->jsregexp
->flags
, ret
);
636 if(!is_string(src_arg
)) {
637 FIXME("src_arg = %s\n", debugstr_jsval(src_arg
));
641 src
= get_string(src_arg
);
644 if(!is_string(*flags_arg
)) {
645 FIXME("unimplemented for %s\n", debugstr_jsval(*flags_arg
));
649 opt
= get_string(*flags_arg
);
652 hres
= parse_regexp_flags(opt
? opt
->str
: NULL
, opt
? jsstr_length(opt
) : 0, &flags
);
656 return create_regexp(ctx
, src
, flags
, ret
);
659 HRESULT
regexp_string_match(script_ctx_t
*ctx
, jsdisp_t
*re
, jsstr_t
*str
, jsval_t
*r
)
661 static const WCHAR indexW
[] = {'i','n','d','e','x',0};
662 static const WCHAR inputW
[] = {'i','n','p','u','t',0};
663 static const WCHAR lastIndexW
[] = {'l','a','s','t','I','n','d','e','x',0};
665 RegExpInstance
*regexp
= (RegExpInstance
*)re
;
666 match_result_t
*match_result
;
667 unsigned match_cnt
, i
;
671 if(!(regexp
->jsregexp
->flags
& JSREG_GLOB
)) {
672 match_result_t match
, *parens
= NULL
;
673 DWORD parens_cnt
, parens_size
= 0;
674 const WCHAR
*cp
= str
->str
;
676 hres
= regexp_match_next(ctx
, ®exp
->dispex
, 0, str
, &cp
, &parens
, &parens_size
, &parens_cnt
, &match
);
686 hres
= create_match_array(ctx
, str
, &match
, parens
, parens_cnt
, &ret
);
688 *r
= jsval_disp(ret
);
698 hres
= regexp_match(ctx
, ®exp
->dispex
, str
, FALSE
, &match_result
, &match_cnt
);
710 hres
= create_array(ctx
, match_cnt
, &array
);
714 for(i
=0; i
< match_cnt
; i
++) {
717 tmp_str
= jsstr_alloc_len(match_result
[i
].str
, match_result
[i
].len
);
719 hres
= E_OUTOFMEMORY
;
723 hres
= jsdisp_propput_idx(array
, i
, jsval_string(tmp_str
));
724 jsstr_release(tmp_str
);
729 while(SUCCEEDED(hres
)) {
730 hres
= jsdisp_propput_name(array
, indexW
, jsval_number(match_result
[match_cnt
-1].str
-str
->str
));
734 hres
= jsdisp_propput_name(array
, lastIndexW
,
735 jsval_number(match_result
[match_cnt
-1].str
-str
->str
+match_result
[match_cnt
-1].len
));
739 hres
= jsdisp_propput_name(array
, inputW
, jsval_string(str
));
743 heap_free(match_result
);
745 if(SUCCEEDED(hres
) && r
)
746 *r
= jsval_obj(array
);
748 jsdisp_release(array
);
752 static HRESULT
global_idx(script_ctx_t
*ctx
, DWORD flags
, DWORD idx
, jsval_t
*r
)
755 case DISPATCH_PROPERTYGET
: {
758 ret
= jsstr_alloc_len(ctx
->match_parens
[idx
].str
, ctx
->match_parens
[idx
].len
);
760 return E_OUTOFMEMORY
;
762 *r
= jsval_string(ret
);
765 case DISPATCH_PROPERTYPUT
:
768 FIXME("unsupported flags\n");
775 static HRESULT
RegExpConstr_idx1(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
776 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
779 return global_idx(ctx
, flags
, 0, r
);
782 static HRESULT
RegExpConstr_idx2(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
783 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
786 return global_idx(ctx
, flags
, 1, r
);
789 static HRESULT
RegExpConstr_idx3(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
790 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
793 return global_idx(ctx
, flags
, 2, r
);
796 static HRESULT
RegExpConstr_idx4(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
797 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
800 return global_idx(ctx
, flags
, 3, r
);
803 static HRESULT
RegExpConstr_idx5(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
804 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
807 return global_idx(ctx
, flags
, 4, r
);
810 static HRESULT
RegExpConstr_idx6(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
811 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
814 return global_idx(ctx
, flags
, 5, r
);
817 static HRESULT
RegExpConstr_idx7(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
818 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
821 return global_idx(ctx
, flags
, 6, r
);
824 static HRESULT
RegExpConstr_idx8(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
825 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
828 return global_idx(ctx
, flags
, 7, r
);
831 static HRESULT
RegExpConstr_idx9(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
832 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
835 return global_idx(ctx
, flags
, 8, r
);
838 static HRESULT
RegExpConstr_leftContext(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
839 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
844 case DISPATCH_PROPERTYGET
: {
847 ret
= jsstr_alloc_len(ctx
->last_match
->str
, ctx
->last_match_index
);
849 return E_OUTOFMEMORY
;
851 *r
= jsval_string(ret
);
854 case DISPATCH_PROPERTYPUT
:
857 FIXME("unsupported flags\n");
864 static HRESULT
RegExpConstr_rightContext(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
865 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
870 case DISPATCH_PROPERTYGET
: {
873 ret
= jsstr_alloc(ctx
->last_match
->str
+ctx
->last_match_index
+ctx
->last_match_length
);
875 return E_OUTOFMEMORY
;
877 *r
= jsval_string(ret
);
880 case DISPATCH_PROPERTYPUT
:
883 FIXME("unsupported flags\n");
890 static HRESULT
RegExpConstr_value(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
896 case DISPATCH_METHOD
:
898 if(is_object_instance(argv
[0])) {
899 jsdisp_t
*jsdisp
= iface_to_jsdisp((IUnknown
*)get_object(argv
[0]));
901 if(is_class(jsdisp
, JSCLASS_REGEXP
)) {
902 if(argc
> 1 && !is_undefined(argv
[1])) {
903 jsdisp_release(jsdisp
);
904 return throw_regexp_error(ctx
, JS_E_REGEXP_SYNTAX
, NULL
);
908 *r
= jsval_obj(jsdisp
);
910 jsdisp_release(jsdisp
);
913 jsdisp_release(jsdisp
);
918 case DISPATCH_CONSTRUCT
: {
927 hres
= create_regexp_var(ctx
, argv
[0], argc
> 1 ? argv
+1 : NULL
, &ret
);
938 FIXME("unimplemented flags: %x\n", flags
);
945 static const builtin_prop_t RegExpConstr_props
[] = {
946 {idx1W
, RegExpConstr_idx1
, 0},
947 {idx2W
, RegExpConstr_idx2
, 0},
948 {idx3W
, RegExpConstr_idx3
, 0},
949 {idx4W
, RegExpConstr_idx4
, 0},
950 {idx5W
, RegExpConstr_idx5
, 0},
951 {idx6W
, RegExpConstr_idx6
, 0},
952 {idx7W
, RegExpConstr_idx7
, 0},
953 {idx8W
, RegExpConstr_idx8
, 0},
954 {idx9W
, RegExpConstr_idx9
, 0},
955 {leftContextW
, RegExpConstr_leftContext
, 0},
956 {rightContextW
, RegExpConstr_rightContext
, 0}
959 static const builtin_info_t RegExpConstr_info
= {
961 {NULL
, Function_value
, 0},
962 sizeof(RegExpConstr_props
)/sizeof(*RegExpConstr_props
),
968 HRESULT
create_regexp_constr(script_ctx_t
*ctx
, jsdisp_t
*object_prototype
, jsdisp_t
**ret
)
970 RegExpInstance
*regexp
;
973 static const WCHAR RegExpW
[] = {'R','e','g','E','x','p',0};
975 hres
= alloc_regexp(ctx
, object_prototype
, ®exp
);
979 hres
= create_builtin_constructor(ctx
, RegExpConstr_value
, RegExpW
, &RegExpConstr_info
,
980 PROPF_CONSTR
|2, ®exp
->dispex
, ret
);
982 jsdisp_release(®exp
->dispex
);
986 HRESULT
parse_regexp_flags(const WCHAR
*str
, DWORD str_len
, DWORD
*ret
)
991 for (p
= str
; p
< str
+str_len
; p
++) {
1000 flags
|= JSREG_MULTILINE
;
1003 flags
|= JSREG_STICKY
;
1006 WARN("wrong flag %c\n", *p
);