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 inline RegExpInstance
*regexp_from_jsdisp(jsdisp_t
*jsdisp
)
63 return CONTAINING_RECORD(jsdisp
, RegExpInstance
, dispex
);
66 static inline RegExpInstance
*regexp_from_vdisp(vdisp_t
*vdisp
)
68 return regexp_from_jsdisp(vdisp
->u
.jsdisp
);
71 static void set_last_index(RegExpInstance
*This
, DWORD last_index
)
73 This
->last_index
= last_index
;
74 jsval_release(This
->last_index_val
);
75 This
->last_index_val
= jsval_number(last_index
);
78 static HRESULT
do_regexp_match_next(script_ctx_t
*ctx
, RegExpInstance
*regexp
,
79 DWORD rem_flags
, jsstr_t
*jsstr
, const WCHAR
*str
, match_state_t
*ret
)
83 hres
= regexp_execute(regexp
->jsregexp
, ctx
, &ctx
->tmp_heap
,
84 str
, jsstr_length(jsstr
), ret
);
88 if(rem_flags
& REM_RESET_INDEX
)
89 set_last_index(regexp
, 0);
93 if(!(rem_flags
& REM_NO_CTX_UPDATE
) && ctx
->last_match
!= jsstr
) {
94 jsstr_release(ctx
->last_match
);
95 ctx
->last_match
= jsstr_addref(jsstr
);
98 if(!(rem_flags
& REM_NO_CTX_UPDATE
)) {
99 DWORD i
, n
= min(sizeof(ctx
->match_parens
)/sizeof(ctx
->match_parens
[0]), ret
->paren_count
);
101 for(i
=0; i
< n
; i
++) {
102 if(ret
->parens
[i
].index
== -1) {
103 ctx
->match_parens
[i
].index
= 0;
104 ctx
->match_parens
[i
].length
= 0;
106 ctx
->match_parens
[i
].index
= ret
->parens
[i
].index
;
107 ctx
->match_parens
[i
].length
= ret
->parens
[i
].length
;
111 if(n
< sizeof(ctx
->match_parens
)/sizeof(ctx
->match_parens
[0]))
112 memset(ctx
->match_parens
+n
, 0, sizeof(ctx
->match_parens
) - n
*sizeof(ctx
->match_parens
[0]));
115 set_last_index(regexp
, ret
->cp
-str
);
117 if(!(rem_flags
& REM_NO_CTX_UPDATE
)) {
118 ctx
->last_match_index
= ret
->cp
-str
-ret
->match_len
;
119 ctx
->last_match_length
= ret
->match_len
;
125 HRESULT
regexp_match_next(script_ctx_t
*ctx
, jsdisp_t
*dispex
,
126 DWORD rem_flags
, jsstr_t
*jsstr
, match_state_t
**ret
)
128 RegExpInstance
*regexp
= (RegExpInstance
*)dispex
;
129 match_state_t
*match
;
134 if((rem_flags
& REM_CHECK_GLOBAL
) && !(regexp
->jsregexp
->flags
& REG_GLOB
)) {
135 if(rem_flags
& REM_ALLOC_RESULT
)
140 str
= jsstr_flatten(jsstr
);
142 return E_OUTOFMEMORY
;
144 if(rem_flags
& REM_ALLOC_RESULT
) {
145 match
= alloc_match_state(regexp
->jsregexp
, NULL
, str
);
147 return E_OUTOFMEMORY
;
151 mark
= heap_pool_mark(&ctx
->tmp_heap
);
153 if(rem_flags
& REM_NO_PARENS
) {
154 match
= alloc_match_state(regexp
->jsregexp
, &ctx
->tmp_heap
, NULL
);
156 heap_pool_clear(mark
);
157 return E_OUTOFMEMORY
;
159 match
->cp
= (*ret
)->cp
;
160 match
->match_len
= (*ret
)->match_len
;
165 hres
= do_regexp_match_next(ctx
, regexp
, rem_flags
, jsstr
, str
, match
);
167 if(rem_flags
& REM_NO_PARENS
) {
168 (*ret
)->cp
= match
->cp
;
169 (*ret
)->match_len
= match
->match_len
;
172 heap_pool_clear(mark
);
174 if(hres
!= S_OK
&& (rem_flags
& REM_ALLOC_RESULT
)) {
182 static HRESULT
regexp_match(script_ctx_t
*ctx
, jsdisp_t
*dispex
, jsstr_t
*jsstr
, BOOL gflag
,
183 match_result_t
**match_result
, DWORD
*result_cnt
)
185 RegExpInstance
*This
= (RegExpInstance
*)dispex
;
186 match_result_t
*ret
= NULL
;
187 match_state_t
*result
;
188 DWORD i
=0, ret_size
= 0;
193 mark
= heap_pool_mark(&ctx
->tmp_heap
);
195 str
= jsstr_flatten(jsstr
);
197 return E_OUTOFMEMORY
;
199 result
= alloc_match_state(This
->jsregexp
, &ctx
->tmp_heap
, str
);
201 heap_pool_clear(mark
);
202 return E_OUTOFMEMORY
;
206 hres
= do_regexp_match_next(ctx
, This
, 0, jsstr
, str
, result
);
207 if(hres
== S_FALSE
) {
217 match_result_t
*old_ret
= ret
;
219 ret
= heap_realloc(old_ret
, (ret_size
<<= 1) * sizeof(match_result_t
));
223 ret
= heap_alloc((ret_size
=4) * sizeof(match_result_t
));
226 hres
= E_OUTOFMEMORY
;
231 ret
[i
].index
= result
->cp
- str
- result
->match_len
;
232 ret
[i
++].length
= result
->match_len
;
234 if(!gflag
&& !(This
->jsregexp
->flags
& REG_GLOB
)) {
240 heap_pool_clear(mark
);
251 static HRESULT
RegExp_get_source(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
255 *r
= jsval_string(jsstr_addref(regexp_from_jsdisp(jsthis
)->str
));
259 static HRESULT
RegExp_set_source(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t value
)
265 static HRESULT
RegExp_get_global(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
271 static HRESULT
RegExp_set_global(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t value
)
277 static HRESULT
RegExp_get_ignoreCase(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
283 static HRESULT
RegExp_set_ignoreCase(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t value
)
289 static HRESULT
RegExp_get_multiline(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
295 static HRESULT
RegExp_set_multiline(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t value
)
301 static INT
index_from_val(script_ctx_t
*ctx
, jsval_t v
)
306 hres
= to_number(ctx
, v
, &n
);
308 clear_ei(ctx
); /* FIXME: Move ignoring exceptions to to_primitive */
313 return is_int32(n
) ? n
: 0;
316 static HRESULT
RegExp_get_lastIndex(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
318 RegExpInstance
*regexp
= regexp_from_jsdisp(jsthis
);
322 return jsval_copy(regexp
->last_index_val
, r
);
325 static HRESULT
RegExp_set_lastIndex(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t value
)
327 RegExpInstance
*regexp
= regexp_from_jsdisp(jsthis
);
332 hres
= jsval_copy(value
, ®exp
->last_index_val
);
336 regexp
->last_index
= index_from_val(ctx
, value
);
340 static HRESULT
RegExp_toString(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
343 RegExpInstance
*regexp
;
350 if(!is_vclass(jsthis
, JSCLASS_REGEXP
)) {
351 FIXME("Not a RegExp\n");
355 regexp
= regexp_from_vdisp(jsthis
);
360 len
= jsstr_length(regexp
->str
) + 2;
362 f
= regexp
->jsregexp
->flags
;
367 if(f
& REG_MULTILINE
)
370 ptr
= jsstr_alloc_buf(len
, &ret
);
372 return E_OUTOFMEMORY
;
375 ptr
+= jsstr_flush(regexp
->str
, ptr
);
382 if(f
& REG_MULTILINE
)
385 *r
= jsval_string(ret
);
389 static HRESULT
create_match_array(script_ctx_t
*ctx
, jsstr_t
*input_str
,
390 const match_state_t
*result
, IDispatch
**ret
)
398 static const WCHAR indexW
[] = {'i','n','d','e','x',0};
399 static const WCHAR inputW
[] = {'i','n','p','u','t',0};
400 static const WCHAR lastIndexW
[] = {'l','a','s','t','I','n','d','e','x',0};
401 static const WCHAR zeroW
[] = {'0',0};
403 input
= jsstr_flatten(input_str
);
405 return E_OUTOFMEMORY
;
407 hres
= create_array(ctx
, result
->paren_count
+1, &array
);
411 for(i
=0; i
< result
->paren_count
; i
++) {
412 if(result
->parens
[i
].index
!= -1)
413 str
= jsstr_substr(input_str
, result
->parens
[i
].index
, result
->parens
[i
].length
);
417 hres
= E_OUTOFMEMORY
;
421 hres
= jsdisp_propput_idx(array
, i
+1, jsval_string(str
));
427 while(SUCCEEDED(hres
)) {
428 hres
= jsdisp_propput_name(array
, indexW
, jsval_number(result
->cp
-input
-result
->match_len
));
432 hres
= jsdisp_propput_name(array
, lastIndexW
, jsval_number(result
->cp
-input
));
436 hres
= jsdisp_propput_name(array
, inputW
, jsval_string(jsstr_addref(input_str
)));
440 str
= jsstr_alloc_len(result
->cp
-result
->match_len
, result
->match_len
);
442 hres
= E_OUTOFMEMORY
;
445 hres
= jsdisp_propput_name(array
, zeroW
, jsval_string(str
));
451 jsdisp_release(array
);
455 *ret
= to_disp(array
);
459 static HRESULT
run_exec(script_ctx_t
*ctx
, vdisp_t
*jsthis
, jsval_t arg
,
460 jsstr_t
**input
, match_state_t
**result
, BOOL
*ret
)
462 RegExpInstance
*regexp
;
463 match_state_t
*match
;
464 DWORD last_index
= 0;
469 if(!is_vclass(jsthis
, JSCLASS_REGEXP
)) {
470 FIXME("Not a RegExp\n");
474 regexp
= regexp_from_vdisp(jsthis
);
476 hres
= to_flat_string(ctx
, arg
, &jsstr
, &string
);
480 if(regexp
->jsregexp
->flags
& REG_GLOB
) {
481 if(regexp
->last_index
< 0) {
482 jsstr_release(jsstr
);
483 set_last_index(regexp
, 0);
486 *input
= jsstr_empty();
490 last_index
= regexp
->last_index
;
493 match
= alloc_match_state(regexp
->jsregexp
, &ctx
->tmp_heap
, string
+last_index
);
495 jsstr_release(jsstr
);
496 return E_OUTOFMEMORY
;
499 hres
= regexp_match_next(ctx
, ®exp
->dispex
, REM_RESET_INDEX
, jsstr
, &match
);
501 jsstr_release(jsstr
);
510 jsstr_release(jsstr
);
514 static HRESULT
RegExp_exec(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
517 match_state_t
*match
;
525 mark
= heap_pool_mark(&ctx
->tmp_heap
);
527 hres
= run_exec(ctx
, jsthis
, argc
? argv
[0] : jsval_string(jsstr_empty()), &string
, &match
, &b
);
529 heap_pool_clear(mark
);
537 hres
= create_match_array(ctx
, string
, match
, &ret
);
539 *r
= jsval_disp(ret
);
545 heap_pool_clear(mark
);
546 jsstr_release(string
);
550 static HRESULT
RegExp_test(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
553 match_state_t
*match
;
561 mark
= heap_pool_mark(&ctx
->tmp_heap
);
562 hres
= run_exec(ctx
, jsthis
, argc
? argv
[0] : jsval_string(undef_str
= jsstr_undefined()), NULL
, &match
, &b
);
563 heap_pool_clear(mark
);
565 jsstr_release(undef_str
);
574 static HRESULT
RegExp_value(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
581 return throw_type_error(ctx
, JS_E_FUNCTION_EXPECTED
, NULL
);
583 FIXME("unimplemented flags %x\n", flags
);
590 static void RegExp_destructor(jsdisp_t
*dispex
)
592 RegExpInstance
*This
= (RegExpInstance
*)dispex
;
595 regexp_destroy(This
->jsregexp
);
596 jsval_release(This
->last_index_val
);
597 jsstr_release(This
->str
);
601 static const builtin_prop_t RegExp_props
[] = {
602 {execW
, RegExp_exec
, PROPF_METHOD
|1},
603 {globalW
, NULL
,0, RegExp_get_global
, RegExp_set_global
},
604 {ignoreCaseW
, NULL
,0, RegExp_get_ignoreCase
, RegExp_set_ignoreCase
},
605 {lastIndexW
, NULL
,0, RegExp_get_lastIndex
, RegExp_set_lastIndex
},
606 {multilineW
, NULL
,0, RegExp_get_multiline
, RegExp_set_multiline
},
607 {sourceW
, NULL
,0, RegExp_get_source
, RegExp_set_source
},
608 {testW
, RegExp_test
, PROPF_METHOD
|1},
609 {toStringW
, RegExp_toString
, PROPF_METHOD
}
612 static const builtin_info_t RegExp_info
= {
614 {NULL
, RegExp_value
, 0},
615 sizeof(RegExp_props
)/sizeof(*RegExp_props
),
621 static const builtin_prop_t RegExpInst_props
[] = {
622 {globalW
, NULL
,0, RegExp_get_global
, RegExp_set_global
},
623 {ignoreCaseW
, NULL
,0, RegExp_get_ignoreCase
, RegExp_set_ignoreCase
},
624 {lastIndexW
, NULL
,0, RegExp_get_lastIndex
, RegExp_set_lastIndex
},
625 {multilineW
, NULL
,0, RegExp_get_multiline
, RegExp_set_multiline
},
626 {sourceW
, NULL
,0, RegExp_get_source
, RegExp_set_source
}
629 static const builtin_info_t RegExpInst_info
= {
631 {NULL
, RegExp_value
, 0},
632 sizeof(RegExpInst_props
)/sizeof(*RegExpInst_props
),
638 static HRESULT
alloc_regexp(script_ctx_t
*ctx
, jsdisp_t
*object_prototype
, RegExpInstance
**ret
)
640 RegExpInstance
*regexp
;
643 regexp
= heap_alloc_zero(sizeof(RegExpInstance
));
645 return E_OUTOFMEMORY
;
648 hres
= init_dispex(®exp
->dispex
, ctx
, &RegExp_info
, object_prototype
);
650 hres
= init_dispex_from_constr(®exp
->dispex
, ctx
, &RegExpInst_info
, ctx
->regexp_constr
);
661 HRESULT
create_regexp(script_ctx_t
*ctx
, jsstr_t
*src
, DWORD flags
, jsdisp_t
**ret
)
663 RegExpInstance
*regexp
;
667 TRACE("%s %x\n", debugstr_jsstr(src
), flags
);
669 str
= jsstr_flatten(src
);
671 return E_OUTOFMEMORY
;
673 hres
= alloc_regexp(ctx
, NULL
, ®exp
);
677 regexp
->str
= jsstr_addref(src
);
678 regexp
->last_index_val
= jsval_number(0);
680 regexp
->jsregexp
= regexp_new(ctx
, &ctx
->tmp_heap
, str
, jsstr_length(regexp
->str
), flags
, FALSE
);
681 if(!regexp
->jsregexp
) {
682 WARN("regexp_new failed\n");
683 jsdisp_release(®exp
->dispex
);
687 *ret
= ®exp
->dispex
;
691 HRESULT
create_regexp_var(script_ctx_t
*ctx
, jsval_t src_arg
, jsval_t
*flags_arg
, jsdisp_t
**ret
)
693 unsigned flags
, opt_len
= 0;
694 const WCHAR
*opt
= NULL
;
698 if(is_object_instance(src_arg
)) {
701 obj
= iface_to_jsdisp((IUnknown
*)get_object(src_arg
));
703 if(is_class(obj
, JSCLASS_REGEXP
)) {
704 RegExpInstance
*regexp
= (RegExpInstance
*)obj
;
706 hres
= create_regexp(ctx
, regexp
->str
, regexp
->jsregexp
->flags
, ret
);
715 if(!is_string(src_arg
)) {
716 FIXME("src_arg = %s\n", debugstr_jsval(src_arg
));
720 src
= get_string(src_arg
);
725 if(!is_string(*flags_arg
)) {
726 FIXME("unimplemented for %s\n", debugstr_jsval(*flags_arg
));
730 opt_str
= get_string(*flags_arg
);
731 opt
= jsstr_flatten(opt_str
);
733 return E_OUTOFMEMORY
;
734 opt_len
= jsstr_length(opt_str
);
737 hres
= parse_regexp_flags(opt
, opt_len
, &flags
);
741 return create_regexp(ctx
, src
, flags
, ret
);
744 HRESULT
regexp_string_match(script_ctx_t
*ctx
, jsdisp_t
*re
, jsstr_t
*jsstr
, jsval_t
*r
)
746 static const WCHAR indexW
[] = {'i','n','d','e','x',0};
747 static const WCHAR inputW
[] = {'i','n','p','u','t',0};
748 static const WCHAR lastIndexW
[] = {'l','a','s','t','I','n','d','e','x',0};
750 RegExpInstance
*regexp
= (RegExpInstance
*)re
;
751 match_result_t
*match_result
;
752 unsigned match_cnt
, i
;
757 str
= jsstr_flatten(jsstr
);
759 return E_OUTOFMEMORY
;
761 if(!(regexp
->jsregexp
->flags
& REG_GLOB
)) {
762 match_state_t
*match
;
765 mark
= heap_pool_mark(&ctx
->tmp_heap
);
766 match
= alloc_match_state(regexp
->jsregexp
, &ctx
->tmp_heap
, str
);
768 heap_pool_clear(mark
);
769 return E_OUTOFMEMORY
;
772 hres
= regexp_match_next(ctx
, ®exp
->dispex
, 0, jsstr
, &match
);
774 heap_pool_clear(mark
);
782 hres
= create_match_array(ctx
, jsstr
, match
, &ret
);
784 *r
= jsval_disp(ret
);
790 heap_pool_clear(mark
);
794 hres
= regexp_match(ctx
, ®exp
->dispex
, jsstr
, FALSE
, &match_result
, &match_cnt
);
806 hres
= create_array(ctx
, match_cnt
, &array
);
810 for(i
=0; i
< match_cnt
; i
++) {
813 tmp_str
= jsstr_substr(jsstr
, match_result
[i
].index
, match_result
[i
].length
);
815 hres
= E_OUTOFMEMORY
;
819 hres
= jsdisp_propput_idx(array
, i
, jsval_string(tmp_str
));
820 jsstr_release(tmp_str
);
825 while(SUCCEEDED(hres
)) {
826 hres
= jsdisp_propput_name(array
, indexW
, jsval_number(match_result
[match_cnt
-1].index
));
830 hres
= jsdisp_propput_name(array
, lastIndexW
,
831 jsval_number(match_result
[match_cnt
-1].index
+ match_result
[match_cnt
-1].length
));
835 hres
= jsdisp_propput_name(array
, inputW
, jsval_string(jsstr
));
839 heap_free(match_result
);
841 if(SUCCEEDED(hres
) && r
)
842 *r
= jsval_obj(array
);
844 jsdisp_release(array
);
848 static HRESULT
global_idx(script_ctx_t
*ctx
, DWORD idx
, jsval_t
*r
)
852 ret
= jsstr_substr(ctx
->last_match
, ctx
->match_parens
[idx
].index
, ctx
->match_parens
[idx
].length
);
854 return E_OUTOFMEMORY
;
856 *r
= jsval_string(ret
);
860 static HRESULT
RegExpConstr_get_idx1(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
863 return global_idx(ctx
, 0, r
);
866 static HRESULT
RegExpConstr_get_idx2(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
869 return global_idx(ctx
, 1, r
);
872 static HRESULT
RegExpConstr_get_idx3(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
875 return global_idx(ctx
, 2, r
);
878 static HRESULT
RegExpConstr_get_idx4(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
881 return global_idx(ctx
, 3, r
);
884 static HRESULT
RegExpConstr_get_idx5(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
887 return global_idx(ctx
, 4, r
);
890 static HRESULT
RegExpConstr_get_idx6(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
893 return global_idx(ctx
, 5, r
);
896 static HRESULT
RegExpConstr_get_idx7(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
899 return global_idx(ctx
, 6, r
);
902 static HRESULT
RegExpConstr_get_idx8(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
905 return global_idx(ctx
, 7, r
);
908 static HRESULT
RegExpConstr_get_idx9(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
911 return global_idx(ctx
, 8, r
);
914 static HRESULT
RegExpConstr_get_leftContext(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
920 ret
= jsstr_substr(ctx
->last_match
, 0, ctx
->last_match_index
);
922 return E_OUTOFMEMORY
;
924 *r
= jsval_string(ret
);
928 static HRESULT
RegExpConstr_get_rightContext(script_ctx_t
*ctx
, jsdisp_t
*jsthis
, jsval_t
*r
)
934 ret
= jsstr_substr(ctx
->last_match
, ctx
->last_match_index
+ctx
->last_match_length
,
935 jsstr_length(ctx
->last_match
) - ctx
->last_match_index
- ctx
->last_match_length
);
937 return E_OUTOFMEMORY
;
939 *r
= jsval_string(ret
);
943 static HRESULT
RegExpConstr_value(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
949 case DISPATCH_METHOD
:
951 if(is_object_instance(argv
[0])) {
952 jsdisp_t
*jsdisp
= iface_to_jsdisp((IUnknown
*)get_object(argv
[0]));
954 if(is_class(jsdisp
, JSCLASS_REGEXP
)) {
955 if(argc
> 1 && !is_undefined(argv
[1])) {
956 jsdisp_release(jsdisp
);
957 return throw_regexp_error(ctx
, JS_E_REGEXP_SYNTAX
, NULL
);
961 *r
= jsval_obj(jsdisp
);
963 jsdisp_release(jsdisp
);
966 jsdisp_release(jsdisp
);
971 case DISPATCH_CONSTRUCT
: {
980 hres
= create_regexp_var(ctx
, argv
[0], argc
> 1 ? argv
+1 : NULL
, &ret
);
991 FIXME("unimplemented flags: %x\n", flags
);
998 static const builtin_prop_t RegExpConstr_props
[] = {
999 {idx1W
, NULL
,0, RegExpConstr_get_idx1
, builtin_set_const
},
1000 {idx2W
, NULL
,0, RegExpConstr_get_idx2
, builtin_set_const
},
1001 {idx3W
, NULL
,0, RegExpConstr_get_idx3
, builtin_set_const
},
1002 {idx4W
, NULL
,0, RegExpConstr_get_idx4
, builtin_set_const
},
1003 {idx5W
, NULL
,0, RegExpConstr_get_idx5
, builtin_set_const
},
1004 {idx6W
, NULL
,0, RegExpConstr_get_idx6
, builtin_set_const
},
1005 {idx7W
, NULL
,0, RegExpConstr_get_idx7
, builtin_set_const
},
1006 {idx8W
, NULL
,0, RegExpConstr_get_idx8
, builtin_set_const
},
1007 {idx9W
, NULL
,0, RegExpConstr_get_idx9
, builtin_set_const
},
1008 {leftContextW
, NULL
,0, RegExpConstr_get_leftContext
, builtin_set_const
},
1009 {rightContextW
, NULL
,0, RegExpConstr_get_rightContext
, builtin_set_const
}
1012 static const builtin_info_t RegExpConstr_info
= {
1014 DEFAULT_FUNCTION_VALUE
,
1015 sizeof(RegExpConstr_props
)/sizeof(*RegExpConstr_props
),
1021 HRESULT
create_regexp_constr(script_ctx_t
*ctx
, jsdisp_t
*object_prototype
, jsdisp_t
**ret
)
1023 RegExpInstance
*regexp
;
1026 static const WCHAR RegExpW
[] = {'R','e','g','E','x','p',0};
1028 hres
= alloc_regexp(ctx
, object_prototype
, ®exp
);
1032 hres
= create_builtin_constructor(ctx
, RegExpConstr_value
, RegExpW
, &RegExpConstr_info
,
1033 PROPF_CONSTR
|2, ®exp
->dispex
, ret
);
1035 jsdisp_release(®exp
->dispex
);
1039 HRESULT
parse_regexp_flags(const WCHAR
*str
, DWORD str_len
, DWORD
*ret
)
1044 for (p
= str
; p
< str
+str_len
; p
++) {
1053 flags
|= REG_MULTILINE
;
1056 flags
|= REG_STICKY
;
1059 WARN("wrong flag %c\n", *p
);