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 emptyW
[] = {0};
63 static inline RegExpInstance
*regexp_from_vdisp(vdisp_t
*vdisp
)
65 return (RegExpInstance
*)vdisp
->u
.jsdisp
;
68 static void set_last_index(RegExpInstance
*This
, DWORD last_index
)
70 This
->last_index
= last_index
;
71 jsval_release(This
->last_index_val
);
72 This
->last_index_val
= jsval_number(last_index
);
75 static HRESULT
do_regexp_match_next(script_ctx_t
*ctx
, RegExpInstance
*regexp
,
76 DWORD rem_flags
, jsstr_t
*jsstr
, const WCHAR
*str
, match_state_t
*ret
)
80 hres
= regexp_execute(regexp
->jsregexp
, ctx
, &ctx
->tmp_heap
,
81 str
, jsstr_length(jsstr
), ret
);
85 if(rem_flags
& REM_RESET_INDEX
)
86 set_last_index(regexp
, 0);
90 if(!(rem_flags
& REM_NO_CTX_UPDATE
) && ctx
->last_match
!= jsstr
) {
91 jsstr_release(ctx
->last_match
);
92 ctx
->last_match
= jsstr_addref(jsstr
);
95 if(!(rem_flags
& REM_NO_CTX_UPDATE
)) {
96 DWORD i
, n
= min(sizeof(ctx
->match_parens
)/sizeof(ctx
->match_parens
[0]), ret
->paren_count
);
98 for(i
=0; i
< n
; i
++) {
99 if(ret
->parens
[i
].index
== -1) {
100 ctx
->match_parens
[i
].index
= 0;
101 ctx
->match_parens
[i
].length
= 0;
103 ctx
->match_parens
[i
].index
= ret
->parens
[i
].index
;
104 ctx
->match_parens
[i
].length
= ret
->parens
[i
].length
;
108 if(n
< sizeof(ctx
->match_parens
)/sizeof(ctx
->match_parens
[0]))
109 memset(ctx
->match_parens
+n
, 0, sizeof(ctx
->match_parens
) - n
*sizeof(ctx
->match_parens
[0]));
112 set_last_index(regexp
, ret
->cp
-str
);
114 if(!(rem_flags
& REM_NO_CTX_UPDATE
)) {
115 ctx
->last_match_index
= ret
->cp
-str
-ret
->match_len
;
116 ctx
->last_match_length
= ret
->match_len
;
122 HRESULT
regexp_match_next(script_ctx_t
*ctx
, jsdisp_t
*dispex
,
123 DWORD rem_flags
, jsstr_t
*jsstr
, match_state_t
**ret
)
125 RegExpInstance
*regexp
= (RegExpInstance
*)dispex
;
126 match_state_t
*match
;
131 if((rem_flags
& REM_CHECK_GLOBAL
) && !(regexp
->jsregexp
->flags
& REG_GLOB
)) {
132 if(rem_flags
& REM_ALLOC_RESULT
)
137 str
= jsstr_flatten(jsstr
);
139 return E_OUTOFMEMORY
;
141 if(rem_flags
& REM_ALLOC_RESULT
) {
142 match
= alloc_match_state(regexp
->jsregexp
, NULL
, str
);
144 return E_OUTOFMEMORY
;
148 mark
= heap_pool_mark(&ctx
->tmp_heap
);
150 if(rem_flags
& REM_NO_PARENS
) {
151 match
= alloc_match_state(regexp
->jsregexp
, &ctx
->tmp_heap
, NULL
);
153 heap_pool_clear(mark
);
154 return E_OUTOFMEMORY
;
156 match
->cp
= (*ret
)->cp
;
157 match
->match_len
= (*ret
)->match_len
;
162 hres
= do_regexp_match_next(ctx
, regexp
, rem_flags
, jsstr
, str
, match
);
164 if(rem_flags
& REM_NO_PARENS
) {
165 (*ret
)->cp
= match
->cp
;
166 (*ret
)->match_len
= match
->match_len
;
169 heap_pool_clear(mark
);
171 if(hres
!= S_OK
&& (rem_flags
& REM_ALLOC_RESULT
)) {
179 static HRESULT
regexp_match(script_ctx_t
*ctx
, jsdisp_t
*dispex
, jsstr_t
*jsstr
, BOOL gflag
,
180 match_result_t
**match_result
, DWORD
*result_cnt
)
182 RegExpInstance
*This
= (RegExpInstance
*)dispex
;
183 match_result_t
*ret
= NULL
;
184 match_state_t
*result
;
185 DWORD i
=0, ret_size
= 0;
190 mark
= heap_pool_mark(&ctx
->tmp_heap
);
192 str
= jsstr_flatten(jsstr
);
194 return E_OUTOFMEMORY
;
196 result
= alloc_match_state(This
->jsregexp
, &ctx
->tmp_heap
, str
);
198 heap_pool_clear(mark
);
199 return E_OUTOFMEMORY
;
203 hres
= do_regexp_match_next(ctx
, This
, 0, jsstr
, str
, result
);
204 if(hres
== S_FALSE
) {
214 match_result_t
*old_ret
= ret
;
216 ret
= heap_realloc(old_ret
, (ret_size
<<= 1) * sizeof(match_result_t
));
220 ret
= heap_alloc((ret_size
=4) * sizeof(match_result_t
));
223 hres
= E_OUTOFMEMORY
;
228 ret
[i
].index
= result
->cp
- str
- result
->match_len
;
229 ret
[i
++].length
= result
->match_len
;
231 if(!gflag
&& !(This
->jsregexp
->flags
& REG_GLOB
)) {
237 heap_pool_clear(mark
);
248 static HRESULT
RegExp_source(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
254 case DISPATCH_PROPERTYGET
: {
255 RegExpInstance
*This
= regexp_from_vdisp(jsthis
);
256 *r
= jsval_string(jsstr_addref(This
->str
));
260 FIXME("Unimplemented flags %x\n", flags
);
267 static HRESULT
RegExp_global(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
274 static HRESULT
RegExp_ignoreCase(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
281 static HRESULT
RegExp_multiline(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
288 static INT
index_from_val(script_ctx_t
*ctx
, jsval_t v
)
293 hres
= to_number(ctx
, v
, &n
);
295 clear_ei(ctx
); /* FIXME: Move ignoring exceptions to to_primitive */
300 return is_int32(n
) ? n
: 0;
303 static HRESULT
RegExp_lastIndex(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
309 case DISPATCH_PROPERTYGET
: {
310 RegExpInstance
*regexp
= regexp_from_vdisp(jsthis
);
312 return jsval_copy(regexp
->last_index_val
, r
);
314 case DISPATCH_PROPERTYPUT
: {
315 RegExpInstance
*regexp
= regexp_from_vdisp(jsthis
);
318 hres
= jsval_copy(argv
[0], ®exp
->last_index_val
);
322 regexp
->last_index
= index_from_val(ctx
, argv
[0]);
326 FIXME("unimplemented flags: %x\n", flags
);
333 static HRESULT
RegExp_toString(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
336 RegExpInstance
*regexp
;
343 if(!is_vclass(jsthis
, JSCLASS_REGEXP
)) {
344 FIXME("Not a RegExp\n");
348 regexp
= regexp_from_vdisp(jsthis
);
353 len
= jsstr_length(regexp
->str
) + 2;
355 f
= regexp
->jsregexp
->flags
;
360 if(f
& REG_MULTILINE
)
363 ptr
= jsstr_alloc_buf(len
, &ret
);
365 return E_OUTOFMEMORY
;
368 ptr
+= jsstr_flush(regexp
->str
, ptr
);
375 if(f
& REG_MULTILINE
)
378 *r
= jsval_string(ret
);
382 static HRESULT
create_match_array(script_ctx_t
*ctx
, jsstr_t
*input_str
,
383 const match_state_t
*result
, IDispatch
**ret
)
391 static const WCHAR indexW
[] = {'i','n','d','e','x',0};
392 static const WCHAR inputW
[] = {'i','n','p','u','t',0};
393 static const WCHAR lastIndexW
[] = {'l','a','s','t','I','n','d','e','x',0};
394 static const WCHAR zeroW
[] = {'0',0};
396 input
= jsstr_flatten(input_str
);
398 return E_OUTOFMEMORY
;
400 hres
= create_array(ctx
, result
->paren_count
+1, &array
);
404 for(i
=0; i
< result
->paren_count
; i
++) {
405 if(result
->parens
[i
].index
!= -1)
406 str
= jsstr_substr(input_str
, result
->parens
[i
].index
, result
->parens
[i
].length
);
410 hres
= E_OUTOFMEMORY
;
414 hres
= jsdisp_propput_idx(array
, i
+1, jsval_string(str
));
420 while(SUCCEEDED(hres
)) {
421 hres
= jsdisp_propput_name(array
, indexW
, jsval_number(result
->cp
-input
-result
->match_len
));
425 hres
= jsdisp_propput_name(array
, lastIndexW
, jsval_number(result
->cp
-input
));
429 hres
= jsdisp_propput_name(array
, inputW
, jsval_string(jsstr_addref(input_str
)));
433 str
= jsstr_alloc_len(result
->cp
-result
->match_len
, result
->match_len
);
435 hres
= E_OUTOFMEMORY
;
438 hres
= jsdisp_propput_name(array
, zeroW
, jsval_string(str
));
444 jsdisp_release(array
);
448 *ret
= to_disp(array
);
452 static HRESULT
run_exec(script_ctx_t
*ctx
, vdisp_t
*jsthis
, jsval_t arg
,
453 jsstr_t
**input
, match_state_t
**result
, BOOL
*ret
)
455 RegExpInstance
*regexp
;
456 match_state_t
*match
;
457 DWORD last_index
= 0;
462 if(!is_vclass(jsthis
, JSCLASS_REGEXP
)) {
463 FIXME("Not a RegExp\n");
467 regexp
= regexp_from_vdisp(jsthis
);
469 hres
= to_flat_string(ctx
, arg
, &jsstr
, &string
);
473 if(regexp
->jsregexp
->flags
& REG_GLOB
) {
474 if(regexp
->last_index
< 0) {
475 jsstr_release(jsstr
);
476 set_last_index(regexp
, 0);
479 *input
= jsstr_empty();
483 last_index
= regexp
->last_index
;
486 match
= alloc_match_state(regexp
->jsregexp
, &ctx
->tmp_heap
, string
+last_index
);
488 jsstr_release(jsstr
);
489 return E_OUTOFMEMORY
;
492 hres
= regexp_match_next(ctx
, ®exp
->dispex
, REM_RESET_INDEX
, jsstr
, &match
);
494 jsstr_release(jsstr
);
503 jsstr_release(jsstr
);
507 static HRESULT
RegExp_exec(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
510 match_state_t
*match
;
518 mark
= heap_pool_mark(&ctx
->tmp_heap
);
520 hres
= run_exec(ctx
, jsthis
, argc
? argv
[0] : jsval_string(jsstr_empty()), &string
, &match
, &b
);
522 heap_pool_clear(mark
);
530 hres
= create_match_array(ctx
, string
, match
, &ret
);
532 *r
= jsval_disp(ret
);
538 heap_pool_clear(mark
);
539 jsstr_release(string
);
543 static HRESULT
RegExp_test(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
546 match_state_t
*match
;
554 mark
= heap_pool_mark(&ctx
->tmp_heap
);
555 hres
= run_exec(ctx
, jsthis
, argc
? argv
[0] : jsval_string(undef_str
= jsstr_undefined()), NULL
, &match
, &b
);
556 heap_pool_clear(mark
);
558 jsstr_release(undef_str
);
567 static HRESULT
RegExp_value(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
574 return throw_type_error(ctx
, JS_E_FUNCTION_EXPECTED
, NULL
);
576 FIXME("unimplemented flags %x\n", flags
);
583 static void RegExp_destructor(jsdisp_t
*dispex
)
585 RegExpInstance
*This
= (RegExpInstance
*)dispex
;
588 regexp_destroy(This
->jsregexp
);
589 jsval_release(This
->last_index_val
);
590 jsstr_release(This
->str
);
594 static const builtin_prop_t RegExp_props
[] = {
595 {execW
, RegExp_exec
, PROPF_METHOD
|1},
596 {globalW
, RegExp_global
, 0},
597 {ignoreCaseW
, RegExp_ignoreCase
, 0},
598 {lastIndexW
, RegExp_lastIndex
, 0},
599 {multilineW
, RegExp_multiline
, 0},
600 {sourceW
, RegExp_source
, 0},
601 {testW
, RegExp_test
, PROPF_METHOD
|1},
602 {toStringW
, RegExp_toString
, PROPF_METHOD
}
605 static const builtin_info_t RegExp_info
= {
607 {NULL
, RegExp_value
, 0},
608 sizeof(RegExp_props
)/sizeof(*RegExp_props
),
614 static const builtin_prop_t RegExpInst_props
[] = {
615 {globalW
, RegExp_global
, 0},
616 {ignoreCaseW
, RegExp_ignoreCase
, 0},
617 {lastIndexW
, RegExp_lastIndex
, 0},
618 {multilineW
, RegExp_multiline
, 0},
619 {sourceW
, RegExp_source
, 0}
622 static const builtin_info_t RegExpInst_info
= {
624 {NULL
, RegExp_value
, 0},
625 sizeof(RegExpInst_props
)/sizeof(*RegExpInst_props
),
631 static HRESULT
alloc_regexp(script_ctx_t
*ctx
, jsdisp_t
*object_prototype
, RegExpInstance
**ret
)
633 RegExpInstance
*regexp
;
636 regexp
= heap_alloc_zero(sizeof(RegExpInstance
));
638 return E_OUTOFMEMORY
;
641 hres
= init_dispex(®exp
->dispex
, ctx
, &RegExp_info
, object_prototype
);
643 hres
= init_dispex_from_constr(®exp
->dispex
, ctx
, &RegExpInst_info
, ctx
->regexp_constr
);
654 HRESULT
create_regexp(script_ctx_t
*ctx
, jsstr_t
*src
, DWORD flags
, jsdisp_t
**ret
)
656 RegExpInstance
*regexp
;
660 TRACE("%s %x\n", debugstr_jsstr(src
), flags
);
662 str
= jsstr_flatten(src
);
664 return E_OUTOFMEMORY
;
666 hres
= alloc_regexp(ctx
, NULL
, ®exp
);
670 regexp
->str
= jsstr_addref(src
);
671 regexp
->last_index_val
= jsval_number(0);
673 regexp
->jsregexp
= regexp_new(ctx
, &ctx
->tmp_heap
, str
, jsstr_length(regexp
->str
), flags
, FALSE
);
674 if(!regexp
->jsregexp
) {
675 WARN("regexp_new failed\n");
676 jsdisp_release(®exp
->dispex
);
680 *ret
= ®exp
->dispex
;
684 HRESULT
create_regexp_var(script_ctx_t
*ctx
, jsval_t src_arg
, jsval_t
*flags_arg
, jsdisp_t
**ret
)
686 unsigned flags
, opt_len
= 0;
687 const WCHAR
*opt
= NULL
;
691 if(is_object_instance(src_arg
)) {
694 obj
= iface_to_jsdisp((IUnknown
*)get_object(src_arg
));
696 if(is_class(obj
, JSCLASS_REGEXP
)) {
697 RegExpInstance
*regexp
= (RegExpInstance
*)obj
;
699 hres
= create_regexp(ctx
, regexp
->str
, regexp
->jsregexp
->flags
, ret
);
708 if(!is_string(src_arg
)) {
709 FIXME("src_arg = %s\n", debugstr_jsval(src_arg
));
713 src
= get_string(src_arg
);
718 if(!is_string(*flags_arg
)) {
719 FIXME("unimplemented for %s\n", debugstr_jsval(*flags_arg
));
723 opt_str
= get_string(*flags_arg
);
724 opt
= jsstr_flatten(opt_str
);
726 return E_OUTOFMEMORY
;
727 opt_len
= jsstr_length(opt_str
);
730 hres
= parse_regexp_flags(opt
, opt_len
, &flags
);
734 return create_regexp(ctx
, src
, flags
, ret
);
737 HRESULT
regexp_string_match(script_ctx_t
*ctx
, jsdisp_t
*re
, jsstr_t
*jsstr
, jsval_t
*r
)
739 static const WCHAR indexW
[] = {'i','n','d','e','x',0};
740 static const WCHAR inputW
[] = {'i','n','p','u','t',0};
741 static const WCHAR lastIndexW
[] = {'l','a','s','t','I','n','d','e','x',0};
743 RegExpInstance
*regexp
= (RegExpInstance
*)re
;
744 match_result_t
*match_result
;
745 unsigned match_cnt
, i
;
750 str
= jsstr_flatten(jsstr
);
752 return E_OUTOFMEMORY
;
754 if(!(regexp
->jsregexp
->flags
& REG_GLOB
)) {
755 match_state_t
*match
;
758 mark
= heap_pool_mark(&ctx
->tmp_heap
);
759 match
= alloc_match_state(regexp
->jsregexp
, &ctx
->tmp_heap
, str
);
761 heap_pool_clear(mark
);
762 return E_OUTOFMEMORY
;
765 hres
= regexp_match_next(ctx
, ®exp
->dispex
, 0, jsstr
, &match
);
767 heap_pool_clear(mark
);
775 hres
= create_match_array(ctx
, jsstr
, match
, &ret
);
777 *r
= jsval_disp(ret
);
783 heap_pool_clear(mark
);
787 hres
= regexp_match(ctx
, ®exp
->dispex
, jsstr
, FALSE
, &match_result
, &match_cnt
);
799 hres
= create_array(ctx
, match_cnt
, &array
);
803 for(i
=0; i
< match_cnt
; i
++) {
806 tmp_str
= jsstr_substr(jsstr
, match_result
[i
].index
, match_result
[i
].length
);
808 hres
= E_OUTOFMEMORY
;
812 hres
= jsdisp_propput_idx(array
, i
, jsval_string(tmp_str
));
813 jsstr_release(tmp_str
);
818 while(SUCCEEDED(hres
)) {
819 hres
= jsdisp_propput_name(array
, indexW
, jsval_number(match_result
[match_cnt
-1].index
));
823 hres
= jsdisp_propput_name(array
, lastIndexW
,
824 jsval_number(match_result
[match_cnt
-1].index
+ match_result
[match_cnt
-1].length
));
828 hres
= jsdisp_propput_name(array
, inputW
, jsval_string(jsstr
));
832 heap_free(match_result
);
834 if(SUCCEEDED(hres
) && r
)
835 *r
= jsval_obj(array
);
837 jsdisp_release(array
);
841 static HRESULT
global_idx(script_ctx_t
*ctx
, DWORD flags
, DWORD idx
, jsval_t
*r
)
844 case DISPATCH_PROPERTYGET
: {
847 ret
= jsstr_substr(ctx
->last_match
, ctx
->match_parens
[idx
].index
, ctx
->match_parens
[idx
].length
);
849 return E_OUTOFMEMORY
;
851 *r
= jsval_string(ret
);
854 case DISPATCH_PROPERTYPUT
:
857 FIXME("unsupported flags\n");
864 static HRESULT
RegExpConstr_idx1(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
865 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
868 return global_idx(ctx
, flags
, 0, r
);
871 static HRESULT
RegExpConstr_idx2(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
872 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
875 return global_idx(ctx
, flags
, 1, r
);
878 static HRESULT
RegExpConstr_idx3(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
879 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
882 return global_idx(ctx
, flags
, 2, r
);
885 static HRESULT
RegExpConstr_idx4(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
886 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
889 return global_idx(ctx
, flags
, 3, r
);
892 static HRESULT
RegExpConstr_idx5(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
893 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
896 return global_idx(ctx
, flags
, 4, r
);
899 static HRESULT
RegExpConstr_idx6(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
900 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
903 return global_idx(ctx
, flags
, 5, r
);
906 static HRESULT
RegExpConstr_idx7(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
907 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
910 return global_idx(ctx
, flags
, 6, r
);
913 static HRESULT
RegExpConstr_idx8(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
914 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
917 return global_idx(ctx
, flags
, 7, r
);
920 static HRESULT
RegExpConstr_idx9(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
921 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
924 return global_idx(ctx
, flags
, 8, r
);
927 static HRESULT
RegExpConstr_leftContext(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
928 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
933 case DISPATCH_PROPERTYGET
: {
936 ret
= jsstr_substr(ctx
->last_match
, 0, ctx
->last_match_index
);
938 return E_OUTOFMEMORY
;
940 *r
= jsval_string(ret
);
943 case DISPATCH_PROPERTYPUT
:
946 FIXME("unsupported flags\n");
953 static HRESULT
RegExpConstr_rightContext(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
,
954 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
959 case DISPATCH_PROPERTYGET
: {
962 ret
= jsstr_substr(ctx
->last_match
, ctx
->last_match_index
+ctx
->last_match_length
,
963 jsstr_length(ctx
->last_match
) - ctx
->last_match_index
- ctx
->last_match_length
);
965 return E_OUTOFMEMORY
;
967 *r
= jsval_string(ret
);
970 case DISPATCH_PROPERTYPUT
:
973 FIXME("unsupported flags\n");
980 static HRESULT
RegExpConstr_value(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
986 case DISPATCH_METHOD
:
988 if(is_object_instance(argv
[0])) {
989 jsdisp_t
*jsdisp
= iface_to_jsdisp((IUnknown
*)get_object(argv
[0]));
991 if(is_class(jsdisp
, JSCLASS_REGEXP
)) {
992 if(argc
> 1 && !is_undefined(argv
[1])) {
993 jsdisp_release(jsdisp
);
994 return throw_regexp_error(ctx
, JS_E_REGEXP_SYNTAX
, NULL
);
998 *r
= jsval_obj(jsdisp
);
1000 jsdisp_release(jsdisp
);
1003 jsdisp_release(jsdisp
);
1008 case DISPATCH_CONSTRUCT
: {
1017 hres
= create_regexp_var(ctx
, argv
[0], argc
> 1 ? argv
+1 : NULL
, &ret
);
1022 *r
= jsval_obj(ret
);
1024 jsdisp_release(ret
);
1028 FIXME("unimplemented flags: %x\n", flags
);
1035 static const builtin_prop_t RegExpConstr_props
[] = {
1036 {idx1W
, RegExpConstr_idx1
, 0},
1037 {idx2W
, RegExpConstr_idx2
, 0},
1038 {idx3W
, RegExpConstr_idx3
, 0},
1039 {idx4W
, RegExpConstr_idx4
, 0},
1040 {idx5W
, RegExpConstr_idx5
, 0},
1041 {idx6W
, RegExpConstr_idx6
, 0},
1042 {idx7W
, RegExpConstr_idx7
, 0},
1043 {idx8W
, RegExpConstr_idx8
, 0},
1044 {idx9W
, RegExpConstr_idx9
, 0},
1045 {leftContextW
, RegExpConstr_leftContext
, 0},
1046 {rightContextW
, RegExpConstr_rightContext
, 0}
1049 static const builtin_info_t RegExpConstr_info
= {
1051 {NULL
, Function_value
, 0},
1052 sizeof(RegExpConstr_props
)/sizeof(*RegExpConstr_props
),
1058 HRESULT
create_regexp_constr(script_ctx_t
*ctx
, jsdisp_t
*object_prototype
, jsdisp_t
**ret
)
1060 RegExpInstance
*regexp
;
1063 static const WCHAR RegExpW
[] = {'R','e','g','E','x','p',0};
1065 hres
= alloc_regexp(ctx
, object_prototype
, ®exp
);
1069 hres
= create_builtin_constructor(ctx
, RegExpConstr_value
, RegExpW
, &RegExpConstr_info
,
1070 PROPF_CONSTR
|2, ®exp
->dispex
, ret
);
1072 jsdisp_release(®exp
->dispex
);
1076 HRESULT
parse_regexp_flags(const WCHAR
*str
, DWORD str_len
, DWORD
*ret
)
1081 for (p
= str
; p
< str
+str_len
; p
++) {
1090 flags
|= REG_MULTILINE
;
1093 flags
|= REG_STICKY
;
1096 WARN("wrong flag %c\n", *p
);