widl: Always check the runtimeclass interfaces presence.
[wine/zf.git] / dlls / jscript / global.c
blob33869cd5fc6603c614a0d8f84ee0bd61fd644975
1 /*
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
20 #include <math.h>
21 #include <limits.h>
23 #include "jscript.h"
24 #include "engine.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
30 static int uri_char_table[] = {
31 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 00-0f */
32 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 10-1f */
33 0,2,0,0,1,0,1,2,2,2,2,1,1,2,2,1, /* 20-2f */
34 2,2,2,2,2,2,2,2,2,2,1,1,0,1,0,1, /* 30-3f */
35 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 40-4f */
36 2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2, /* 50-5f */
37 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 60-6f */
38 2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,0, /* 70-7f */
41 /* 1 - reserved */
42 /* 2 - unescaped */
44 static inline BOOL is_uri_reserved(WCHAR c)
46 return c < 128 && uri_char_table[c] == 1;
49 static inline BOOL is_uri_unescaped(WCHAR c)
51 return c < 128 && uri_char_table[c] == 2;
54 /* Check that the character is one of the 69 non-blank characters as defined by ECMA-262 B.2.1 */
55 static inline BOOL is_ecma_nonblank(const WCHAR c)
57 return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
58 c == '@' || c == '*' || c == '_' || c == '+' || c == '-' || c == '.' || c == '/');
61 static WCHAR int_to_char(int i)
63 if(i < 10)
64 return '0'+i;
65 return 'A'+i-10;
68 static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
69 jsval_t *r)
71 jsstr_t *ret_str, *str;
72 const WCHAR *ptr, *buf;
73 DWORD len = 0;
74 WCHAR *ret;
75 HRESULT hres;
77 TRACE("\n");
79 if(!argc) {
80 if(r)
81 *r = jsval_string(jsstr_undefined());
82 return S_OK;
85 hres = to_flat_string(ctx, argv[0], &str, &buf);
86 if(FAILED(hres))
87 return hres;
89 for(ptr = buf; *ptr; ptr++) {
90 if(*ptr > 0xff)
91 len += 6;
92 else if(is_ecma_nonblank(*ptr))
93 len++;
94 else
95 len += 3;
98 ret_str = jsstr_alloc_buf(len, &ret);
99 if(!ret_str) {
100 jsstr_release(str);
101 return E_OUTOFMEMORY;
104 len = 0;
105 for(ptr = buf; *ptr; ptr++) {
106 if(*ptr > 0xff) {
107 ret[len++] = '%';
108 ret[len++] = 'u';
109 ret[len++] = int_to_char(*ptr >> 12);
110 ret[len++] = int_to_char((*ptr >> 8) & 0xf);
111 ret[len++] = int_to_char((*ptr >> 4) & 0xf);
112 ret[len++] = int_to_char(*ptr & 0xf);
114 else if(is_ecma_nonblank(*ptr))
115 ret[len++] = *ptr;
116 else {
117 ret[len++] = '%';
118 ret[len++] = int_to_char(*ptr >> 4);
119 ret[len++] = int_to_char(*ptr & 0xf);
123 jsstr_release(str);
125 if(r)
126 *r = jsval_string(ret_str);
127 else
128 jsstr_release(ret_str);
129 return S_OK;
132 /* ECMA-262 3rd Edition 15.1.2.1 */
133 HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
134 jsval_t *r)
136 call_frame_t *frame = ctx->call_ctx;
137 DWORD exec_flags = EXEC_EVAL;
138 bytecode_t *code;
139 const WCHAR *src;
140 HRESULT hres;
142 TRACE("\n");
144 if(!argc) {
145 if(r)
146 *r = jsval_undefined();
147 return S_OK;
150 if(!is_string(argv[0])) {
151 if(r)
152 return jsval_copy(argv[0], r);
153 return S_OK;
156 src = jsstr_flatten(get_string(argv[0]));
157 if(!src)
158 return E_OUTOFMEMORY;
160 TRACE("parsing %s\n", debugstr_jsval(argv[0]));
161 hres = compile_script(ctx, src, 0, 0, NULL, NULL, TRUE, FALSE, frame ? frame->bytecode->named_item : NULL, &code);
162 if(FAILED(hres)) {
163 WARN("parse (%s) failed: %08x\n", debugstr_jsval(argv[0]), hres);
164 return hres;
167 if(!frame || (frame->flags & EXEC_GLOBAL))
168 exec_flags |= EXEC_GLOBAL;
169 if(flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE)
170 exec_flags |= EXEC_RETURN_TO_INTERP;
171 hres = exec_source(ctx, exec_flags, code, &code->global_code, frame ? frame->scope : NULL,
172 frame ? frame->this_obj : NULL, NULL, 0, NULL, r);
173 release_bytecode(code);
174 return hres;
177 static HRESULT JSGlobal_isNaN(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
178 jsval_t *r)
180 BOOL ret = TRUE;
181 double n;
182 HRESULT hres;
184 TRACE("\n");
186 if(argc) {
187 hres = to_number(ctx, argv[0], &n);
188 if(FAILED(hres))
189 return hres;
191 if(!isnan(n))
192 ret = FALSE;
195 if(r)
196 *r = jsval_bool(ret);
197 return S_OK;
200 static HRESULT JSGlobal_isFinite(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
201 jsval_t *r)
203 BOOL ret = FALSE;
204 HRESULT hres;
206 TRACE("\n");
208 if(argc) {
209 double n;
211 hres = to_number(ctx, argv[0], &n);
212 if(FAILED(hres))
213 return hres;
215 ret = isfinite(n);
218 if(r)
219 *r = jsval_bool(ret);
220 return S_OK;
223 static INT char_to_int(WCHAR c)
225 if('0' <= c && c <= '9')
226 return c - '0';
227 if('a' <= c && c <= 'z')
228 return c - 'a' + 10;
229 if('A' <= c && c <= 'Z')
230 return c - 'A' + 10;
231 return 100;
234 static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
235 jsval_t *r)
237 BOOL neg = FALSE, empty = TRUE;
238 const WCHAR *ptr;
239 DOUBLE ret = 0.0;
240 INT radix=0, i;
241 jsstr_t *str;
242 HRESULT hres;
244 if(!argc) {
245 if(r)
246 *r = jsval_number(NAN);
247 return S_OK;
250 if(argc >= 2) {
251 hres = to_int32(ctx, argv[1], &radix);
252 if(FAILED(hres))
253 return hres;
255 if(radix && (radix < 2 || radix > 36)) {
256 WARN("radix %d out of range\n", radix);
257 if(r)
258 *r = jsval_number(NAN);
259 return S_OK;
263 hres = to_flat_string(ctx, argv[0], &str, &ptr);
264 if(FAILED(hres))
265 return hres;
267 while(iswspace(*ptr))
268 ptr++;
270 switch(*ptr) {
271 case '+':
272 ptr++;
273 break;
274 case '-':
275 neg = TRUE;
276 ptr++;
277 break;
280 if(!radix) {
281 if(*ptr == '0') {
282 if(ptr[1] == 'x' || ptr[1] == 'X') {
283 radix = 16;
284 ptr += 2;
285 }else {
286 radix = 8;
287 ptr++;
288 empty = FALSE;
290 }else {
291 radix = 10;
293 }else if(radix == 16 && *ptr == '0' && (ptr[1] == 'x' || ptr[1] == 'X')) {
294 ptr += 2;
297 i = char_to_int(*ptr++);
298 if(i < radix) {
299 do {
300 ret = ret*radix + i;
301 i = char_to_int(*ptr++);
302 }while(i < radix);
303 }else if(empty) {
304 ret = NAN;
307 jsstr_release(str);
309 if(neg)
310 ret = -ret;
312 if(r)
313 *r = jsval_number(ret);
314 return S_OK;
317 static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
318 jsval_t *r)
320 LONGLONG d = 0, hlp;
321 jsstr_t *val_str;
322 int exp = 0;
323 const WCHAR *str;
324 BOOL ret_nan = TRUE, positive = TRUE;
325 HRESULT hres;
327 if(!argc) {
328 if(r)
329 *r = jsval_number(NAN);
330 return S_OK;
333 TRACE("%s\n", debugstr_jsval(argv[0]));
335 hres = to_flat_string(ctx, argv[0], &val_str, &str);
336 if(FAILED(hres))
337 return hres;
339 while(iswspace(*str)) str++;
341 if(*str == '+')
342 str++;
343 else if(*str == '-') {
344 positive = FALSE;
345 str++;
348 if(is_digit(*str))
349 ret_nan = FALSE;
351 while(is_digit(*str)) {
352 hlp = d*10 + *(str++) - '0';
353 if(d>MAXLONGLONG/10 || hlp<0) {
354 exp++;
355 break;
357 else
358 d = hlp;
360 while(is_digit(*str)) {
361 exp++;
362 str++;
365 if(*str == '.') str++;
367 if(is_digit(*str))
368 ret_nan = FALSE;
370 while(is_digit(*str)) {
371 hlp = d*10 + *(str++) - '0';
372 if(d>MAXLONGLONG/10 || hlp<0)
373 break;
375 d = hlp;
376 exp--;
378 while(is_digit(*str))
379 str++;
381 if(*str && !ret_nan && (*str=='e' || *str=='E')) {
382 int sign = 1, e = 0;
384 str++;
385 if(*str == '+')
386 str++;
387 else if(*str == '-') {
388 sign = -1;
389 str++;
392 while(is_digit(*str)) {
393 if(e>INT_MAX/10 || (e = e*10 + *str++ - '0')<0)
394 e = INT_MAX;
396 e *= sign;
398 if(exp<0 && e<0 && exp+e>0) exp = INT_MIN;
399 else if(exp>0 && e>0 && exp+e<0) exp = INT_MAX;
400 else exp += e;
403 jsstr_release(val_str);
405 if(ret_nan) {
406 if(r)
407 *r = jsval_number(NAN);
408 return S_OK;
411 if(!positive)
412 d = -d;
413 if(r)
414 *r = jsval_number(exp>0 ? d*pow(10, exp) : d/pow(10, -exp));
415 return S_OK;
418 static inline int hex_to_int(const WCHAR wch) {
419 if(towupper(wch)>='A' && towupper(wch)<='F') return towupper(wch)-'A'+10;
420 if(is_digit(wch)) return wch-'0';
421 return -1;
424 static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
425 jsval_t *r)
427 jsstr_t *ret_str, *str;
428 const WCHAR *ptr, *buf;
429 DWORD len = 0;
430 WCHAR *ret;
431 HRESULT hres;
433 TRACE("\n");
435 if(!argc) {
436 if(r)
437 *r = jsval_string(jsstr_undefined());
438 return S_OK;
441 hres = to_flat_string(ctx, argv[0], &str, &buf);
442 if(FAILED(hres))
443 return hres;
445 for(ptr = buf; *ptr; ptr++) {
446 if(*ptr == '%') {
447 if(hex_to_int(*(ptr+1))!=-1 && hex_to_int(*(ptr+2))!=-1)
448 ptr += 2;
449 else if(*(ptr+1)=='u' && hex_to_int(*(ptr+2))!=-1 && hex_to_int(*(ptr+3))!=-1
450 && hex_to_int(*(ptr+4))!=-1 && hex_to_int(*(ptr+5))!=-1)
451 ptr += 5;
454 len++;
457 ret_str = jsstr_alloc_buf(len, &ret);
458 if(!ret_str) {
459 jsstr_release(str);
460 return E_OUTOFMEMORY;
463 len = 0;
464 for(ptr = buf; *ptr; ptr++) {
465 if(*ptr == '%') {
466 if(hex_to_int(*(ptr+1))!=-1 && hex_to_int(*(ptr+2))!=-1) {
467 ret[len] = (hex_to_int(*(ptr+1))<<4) + hex_to_int(*(ptr+2));
468 ptr += 2;
470 else if(*(ptr+1)=='u' && hex_to_int(*(ptr+2))!=-1 && hex_to_int(*(ptr+3))!=-1
471 && hex_to_int(*(ptr+4))!=-1 && hex_to_int(*(ptr+5))!=-1) {
472 ret[len] = (hex_to_int(*(ptr+2))<<12) + (hex_to_int(*(ptr+3))<<8)
473 + (hex_to_int(*(ptr+4))<<4) + hex_to_int(*(ptr+5));
474 ptr += 5;
476 else
477 ret[len] = *ptr;
479 else
480 ret[len] = *ptr;
482 len++;
485 jsstr_release(str);
487 if(r)
488 *r = jsval_string(ret_str);
489 else
490 jsstr_release(ret_str);
491 return S_OK;
494 static HRESULT JSGlobal_GetObject(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
495 jsval_t *r)
497 FIXME("\n");
498 return E_NOTIMPL;
501 static HRESULT JSGlobal_ScriptEngine(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
502 jsval_t *r)
504 TRACE("\n");
506 if(r) {
507 jsstr_t *ret;
509 ret = jsstr_alloc(L"JScript");
510 if(!ret)
511 return E_OUTOFMEMORY;
513 *r = jsval_string(ret);
516 return S_OK;
519 static HRESULT JSGlobal_ScriptEngineMajorVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
520 jsval_t *r)
522 TRACE("\n");
524 if(r)
525 *r = jsval_number(JSCRIPT_MAJOR_VERSION);
526 return S_OK;
529 static HRESULT JSGlobal_ScriptEngineMinorVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
530 jsval_t *r)
532 TRACE("\n");
534 if(r)
535 *r = jsval_number(JSCRIPT_MINOR_VERSION);
536 return S_OK;
539 static HRESULT JSGlobal_ScriptEngineBuildVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
540 jsval_t *r)
542 TRACE("\n");
544 if(r)
545 *r = jsval_number(JSCRIPT_BUILD_VERSION);
546 return S_OK;
549 static HRESULT JSGlobal_CollectGarbage(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
550 jsval_t *r)
552 static int once = 0;
553 if (!once++)
554 FIXME(": stub\n");
555 return S_OK;
558 static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
559 jsval_t *r)
561 const WCHAR *ptr, *uri;
562 jsstr_t *str, *ret;
563 DWORD len = 0, i;
564 char buf[4];
565 WCHAR *rptr;
566 HRESULT hres;
568 TRACE("\n");
570 if(!argc) {
571 if(r)
572 *r = jsval_string(jsstr_undefined());
573 return S_OK;
576 hres = to_flat_string(ctx, argv[0], &str, &uri);
577 if(FAILED(hres))
578 return hres;
580 for(ptr = uri; *ptr; ptr++) {
581 if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') {
582 len++;
583 }else {
584 i = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, ptr, 1, NULL, 0, NULL, NULL)*3;
585 if(!i) {
586 jsstr_release(str);
587 return JS_E_INVALID_URI_CHAR;
590 len += i;
594 ret = jsstr_alloc_buf(len, &rptr);
595 if(!ret) {
596 jsstr_release(str);
597 return E_OUTOFMEMORY;
600 for(ptr = uri; *ptr; ptr++) {
601 if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') {
602 *rptr++ = *ptr;
603 }else {
604 len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, ptr, 1, buf, sizeof(buf), NULL, NULL);
605 for(i=0; i<len; i++) {
606 *rptr++ = '%';
607 *rptr++ = int_to_char((BYTE)buf[i] >> 4);
608 *rptr++ = int_to_char(buf[i] & 0x0f);
613 TRACE("%s -> %s\n", debugstr_jsstr(str), debugstr_jsstr(ret));
614 jsstr_release(str);
616 if(r)
617 *r = jsval_string(ret);
618 else
619 jsstr_release(ret);
620 return S_OK;
623 static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
624 jsval_t *r)
626 const WCHAR *ptr, *uri;
627 jsstr_t *str, *ret_str;
628 unsigned len = 0;
629 int i, val, res;
630 WCHAR *ret;
631 char buf[4];
632 WCHAR out;
633 HRESULT hres;
635 TRACE("\n");
637 if(!argc) {
638 if(r)
639 *r = jsval_string(jsstr_undefined());
640 return S_OK;
643 hres = to_flat_string(ctx, argv[0], &str, &uri);
644 if(FAILED(hres))
645 return hres;
647 for(ptr = uri; *ptr; ptr++) {
648 if(*ptr != '%') {
649 len++;
650 }else {
651 res = 0;
652 for(i=0; i<4; i++) {
653 if(ptr[i*3]!='%' || hex_to_int(ptr[i*3+1])==-1 || (val=hex_to_int(ptr[i*3+2]))==-1)
654 break;
655 val += hex_to_int(ptr[i*3+1])<<4;
656 buf[i] = val;
658 res = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, buf, i+1, &out, 1);
659 if(res)
660 break;
663 if(!res) {
664 jsstr_release(str);
665 return JS_E_INVALID_URI_CODING;
668 ptr += i*3+2;
669 len++;
673 ret_str = jsstr_alloc_buf(len, &ret);
674 if(!ret_str) {
675 jsstr_release(str);
676 return E_OUTOFMEMORY;
679 for(ptr = uri; *ptr; ptr++) {
680 if(*ptr != '%') {
681 *ret++ = *ptr;
682 }else {
683 for(i=0; i<4; i++) {
684 if(ptr[i*3]!='%' || hex_to_int(ptr[i*3+1])==-1 || (val=hex_to_int(ptr[i*3+2]))==-1)
685 break;
686 val += hex_to_int(ptr[i*3+1])<<4;
687 buf[i] = val;
689 res = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, buf, i+1, ret, 1);
690 if(res)
691 break;
694 ptr += i*3+2;
695 ret++;
699 TRACE("%s -> %s\n", debugstr_jsstr(str), debugstr_jsstr(ret_str));
700 jsstr_release(str);
702 if(r)
703 *r = jsval_string(ret_str);
704 else
705 jsstr_release(ret_str);
706 return S_OK;
709 static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
710 jsval_t *r)
712 jsstr_t *str, *ret_str;
713 char buf[4];
714 const WCHAR *ptr, *uri;
715 DWORD len = 0, size, i;
716 WCHAR *ret;
717 HRESULT hres;
719 TRACE("\n");
721 if(!argc) {
722 if(r)
723 *r = jsval_string(jsstr_undefined());
724 return S_OK;
727 hres = to_flat_string(ctx, argv[0], &str, &uri);
728 if(FAILED(hres))
729 return hres;
731 for(ptr = uri; *ptr; ptr++) {
732 if(is_uri_unescaped(*ptr))
733 len++;
734 else {
735 size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, ptr, 1, NULL, 0, NULL, NULL);
736 if(!size) {
737 jsstr_release(str);
738 return JS_E_INVALID_URI_CHAR;
740 len += size*3;
744 ret_str = jsstr_alloc_buf(len, &ret);
745 if(!ret_str) {
746 jsstr_release(str);
747 return E_OUTOFMEMORY;
750 for(ptr = uri; *ptr; ptr++) {
751 if(is_uri_unescaped(*ptr)) {
752 *ret++ = *ptr;
753 }else {
754 size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, ptr, 1, buf, sizeof(buf), NULL, NULL);
755 for(i=0; i<size; i++) {
756 *ret++ = '%';
757 *ret++ = int_to_char((BYTE)buf[i] >> 4);
758 *ret++ = int_to_char(buf[i] & 0x0f);
763 jsstr_release(str);
765 if(r)
766 *r = jsval_string(ret_str);
767 else
768 jsstr_release(ret_str);
769 return S_OK;
772 /* ECMA-262 3rd Edition 15.1.3.2 */
773 static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
774 jsval_t *r)
776 const WCHAR *ptr, *uri;
777 jsstr_t *str, *ret;
778 WCHAR *out_ptr;
779 DWORD len = 0;
780 HRESULT hres;
782 TRACE("\n");
784 if(!argc) {
785 if(r)
786 *r = jsval_string(jsstr_undefined());
787 return S_OK;
790 hres = to_flat_string(ctx, argv[0], &str, &uri);
791 if(FAILED(hres))
792 return hres;
794 ptr = uri;
795 while(*ptr) {
796 if(*ptr == '%') {
797 char octets[4];
798 unsigned char mask = 0x80;
799 int i, size, num_bytes = 0;
800 if(hex_to_int(*(ptr+1)) < 0 || hex_to_int(*(ptr+2)) < 0) {
801 FIXME("Throw URIError: Invalid hex sequence\n");
802 jsstr_release(str);
803 return E_FAIL;
805 octets[0] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
806 ptr += 3;
807 while(octets[0] & mask) {
808 mask = mask >> 1;
809 ++num_bytes;
811 if(num_bytes == 1 || num_bytes > 4) {
812 FIXME("Throw URIError: Invalid initial UTF character\n");
813 jsstr_release(str);
814 return E_FAIL;
816 for(i = 1; i < num_bytes; ++i) {
817 if(*ptr != '%'){
818 FIXME("Throw URIError: Incomplete UTF sequence\n");
819 jsstr_release(str);
820 return E_FAIL;
822 if(hex_to_int(*(ptr+1)) < 0 || hex_to_int(*(ptr+2)) < 0) {
823 FIXME("Throw URIError: Invalid hex sequence\n");
824 jsstr_release(str);
825 return E_FAIL;
827 octets[i] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
828 ptr += 3;
830 size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, octets,
831 num_bytes ? num_bytes : 1, NULL, 0);
832 if(size == 0) {
833 FIXME("Throw URIError: Invalid UTF sequence\n");
834 jsstr_release(str);
835 return E_FAIL;
837 len += size;
838 }else {
839 ++ptr;
840 ++len;
844 ret = jsstr_alloc_buf(len, &out_ptr);
845 if(!ret) {
846 jsstr_release(str);
847 return E_OUTOFMEMORY;
850 ptr = uri;
851 while(*ptr) {
852 if(*ptr == '%') {
853 char octets[4];
854 unsigned char mask = 0x80;
855 int i, size, num_bytes = 0;
856 octets[0] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
857 ptr += 3;
858 while(octets[0] & mask) {
859 mask = mask >> 1;
860 ++num_bytes;
862 for(i = 1; i < num_bytes; ++i) {
863 octets[i] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
864 ptr += 3;
866 size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, octets,
867 num_bytes ? num_bytes : 1, out_ptr, len);
868 len -= size;
869 out_ptr += size;
870 }else {
871 *out_ptr++ = *ptr++;
872 --len;
876 jsstr_release(str);
878 if(r)
879 *r = jsval_string(ret);
880 else
881 jsstr_release(ret);
882 return S_OK;
885 static const builtin_prop_t JSGlobal_props[] = {
886 {L"CollectGarbage", JSGlobal_CollectGarbage, PROPF_METHOD},
887 {L"GetObject", JSGlobal_GetObject, PROPF_METHOD|2},
888 {L"ScriptEngine", JSGlobal_ScriptEngine, PROPF_METHOD},
889 {L"ScriptEngineBuildVersion", JSGlobal_ScriptEngineBuildVersion, PROPF_METHOD},
890 {L"ScriptEngineMajorVersion", JSGlobal_ScriptEngineMajorVersion, PROPF_METHOD},
891 {L"ScriptEngineMinorVersion", JSGlobal_ScriptEngineMinorVersion, PROPF_METHOD},
892 {L"decodeURI", JSGlobal_decodeURI, PROPF_METHOD|1},
893 {L"decodeURIComponent", JSGlobal_decodeURIComponent, PROPF_METHOD|1},
894 {L"encodeURI", JSGlobal_encodeURI, PROPF_METHOD|1},
895 {L"encodeURIComponent", JSGlobal_encodeURIComponent, PROPF_METHOD|1},
896 {L"escape", JSGlobal_escape, PROPF_METHOD|1},
897 {L"eval", JSGlobal_eval, PROPF_METHOD|1},
898 {L"isFinite", JSGlobal_isFinite, PROPF_METHOD|1},
899 {L"isNaN", JSGlobal_isNaN, PROPF_METHOD|1},
900 {L"parseFloat", JSGlobal_parseFloat, PROPF_METHOD|1},
901 {L"parseInt", JSGlobal_parseInt, PROPF_METHOD|2},
902 {L"unescape", JSGlobal_unescape, PROPF_METHOD|1}
905 static const builtin_info_t JSGlobal_info = {
906 JSCLASS_GLOBAL,
907 {NULL, NULL, 0},
908 ARRAY_SIZE(JSGlobal_props),
909 JSGlobal_props,
910 NULL,
911 NULL
914 static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype)
916 HRESULT hres;
918 hres = init_function_constr(ctx, object_prototype);
919 if(FAILED(hres))
920 return hres;
922 hres = jsdisp_define_data_property(ctx->global, L"Function", PROPF_WRITABLE,
923 jsval_obj(ctx->function_constr));
924 if(FAILED(hres))
925 return hres;
927 hres = create_object_constr(ctx, object_prototype, &ctx->object_constr);
928 if(FAILED(hres))
929 return hres;
931 hres = jsdisp_define_data_property(ctx->global, L"Object", PROPF_WRITABLE,
932 jsval_obj(ctx->object_constr));
933 if(FAILED(hres))
934 return hres;
936 hres = create_array_constr(ctx, object_prototype, &ctx->array_constr);
937 if(FAILED(hres))
938 return hres;
940 hres = jsdisp_define_data_property(ctx->global, L"Array", PROPF_WRITABLE,
941 jsval_obj(ctx->array_constr));
942 if(FAILED(hres))
943 return hres;
945 hres = create_bool_constr(ctx, object_prototype, &ctx->bool_constr);
946 if(FAILED(hres))
947 return hres;
949 hres = jsdisp_define_data_property(ctx->global, L"Boolean", PROPF_WRITABLE,
950 jsval_obj(ctx->bool_constr));
951 if(FAILED(hres))
952 return hres;
954 hres = create_date_constr(ctx, object_prototype, &ctx->date_constr);
955 if(FAILED(hres))
956 return hres;
958 hres = jsdisp_define_data_property(ctx->global, L"Date", PROPF_WRITABLE,
959 jsval_obj(ctx->date_constr));
960 if(FAILED(hres))
961 return hres;
963 hres = create_enumerator_constr(ctx, object_prototype, &ctx->enumerator_constr);
964 if(FAILED(hres))
965 return hres;
967 hres = jsdisp_define_data_property(ctx->global, L"Enumerator", PROPF_WRITABLE,
968 jsval_obj(ctx->enumerator_constr));
969 if(FAILED(hres))
970 return hres;
972 hres = init_error_constr(ctx, object_prototype);
973 if(FAILED(hres))
974 return hres;
976 hres = jsdisp_define_data_property(ctx->global, L"Error", PROPF_WRITABLE,
977 jsval_obj(ctx->error_constr));
978 if(FAILED(hres))
979 return hres;
981 hres = jsdisp_define_data_property(ctx->global, L"EvalError", PROPF_WRITABLE,
982 jsval_obj(ctx->eval_error_constr));
983 if(FAILED(hres))
984 return hres;
986 hres = jsdisp_define_data_property(ctx->global, L"RangeError", PROPF_WRITABLE,
987 jsval_obj(ctx->range_error_constr));
988 if(FAILED(hres))
989 return hres;
991 hres = jsdisp_define_data_property(ctx->global, L"ReferenceError", PROPF_WRITABLE,
992 jsval_obj(ctx->reference_error_constr));
993 if(FAILED(hres))
994 return hres;
996 hres = jsdisp_define_data_property(ctx->global, L"RegExpError", PROPF_WRITABLE,
997 jsval_obj(ctx->regexp_error_constr));
998 if(FAILED(hres))
999 return hres;
1001 hres = jsdisp_define_data_property(ctx->global, L"SyntaxError", PROPF_WRITABLE,
1002 jsval_obj(ctx->syntax_error_constr));
1003 if(FAILED(hres))
1004 return hres;
1006 hres = jsdisp_define_data_property(ctx->global, L"TypeError", PROPF_WRITABLE,
1007 jsval_obj(ctx->type_error_constr));
1008 if(FAILED(hres))
1009 return hres;
1011 hres = jsdisp_define_data_property(ctx->global, L"URIError", PROPF_WRITABLE,
1012 jsval_obj(ctx->uri_error_constr));
1013 if(FAILED(hres))
1014 return hres;
1016 hres = create_number_constr(ctx, object_prototype, &ctx->number_constr);
1017 if(FAILED(hres))
1018 return hres;
1020 hres = jsdisp_define_data_property(ctx->global, L"Number", PROPF_WRITABLE,
1021 jsval_obj(ctx->number_constr));
1022 if(FAILED(hres))
1023 return hres;
1025 hres = create_regexp_constr(ctx, object_prototype, &ctx->regexp_constr);
1026 if(FAILED(hres))
1027 return hres;
1029 hres = jsdisp_define_data_property(ctx->global, L"RegExp", PROPF_WRITABLE,
1030 jsval_obj(ctx->regexp_constr));
1031 if(FAILED(hres))
1032 return hres;
1034 hres = create_string_constr(ctx, object_prototype, &ctx->string_constr);
1035 if(FAILED(hres))
1036 return hres;
1038 hres = jsdisp_define_data_property(ctx->global, L"String", PROPF_WRITABLE,
1039 jsval_obj(ctx->string_constr));
1040 if(FAILED(hres))
1041 return hres;
1043 hres = create_vbarray_constr(ctx, object_prototype, &ctx->vbarray_constr);
1044 if(FAILED(hres))
1045 return hres;
1047 hres = jsdisp_define_data_property(ctx->global, L"VBArray", PROPF_WRITABLE,
1048 jsval_obj(ctx->vbarray_constr));
1049 if(FAILED(hres))
1050 return hres;
1052 return S_OK;
1055 HRESULT init_global(script_ctx_t *ctx)
1057 unsigned const_flags = ctx->version >= SCRIPTLANGUAGEVERSION_ES5 ? 0 : PROPF_WRITABLE;
1058 jsdisp_t *math, *constr;
1059 HRESULT hres;
1061 if(ctx->global)
1062 return S_OK;
1064 hres = create_dispex(ctx, &JSGlobal_info, NULL, &ctx->global);
1065 if(FAILED(hres))
1066 return hres;
1068 hres = create_object_prototype(ctx, &ctx->object_prototype);
1069 if(FAILED(hres))
1070 return hres;
1072 hres = init_constructors(ctx, ctx->object_prototype);
1073 if(FAILED(hres))
1074 return hres;
1076 hres = create_math(ctx, &math);
1077 if(FAILED(hres))
1078 return hres;
1080 hres = jsdisp_define_data_property(ctx->global, L"Math", PROPF_WRITABLE, jsval_obj(math));
1081 jsdisp_release(math);
1082 if(FAILED(hres))
1083 return hres;
1085 if(ctx->version >= 2) {
1086 jsdisp_t *json;
1088 hres = create_json(ctx, &json);
1089 if(FAILED(hres))
1090 return hres;
1092 hres = jsdisp_define_data_property(ctx->global, L"JSON", PROPF_WRITABLE, jsval_obj(json));
1093 jsdisp_release(json);
1094 if(FAILED(hres))
1095 return hres;
1098 hres = create_activex_constr(ctx, &constr);
1099 if(FAILED(hres))
1100 return hres;
1102 hres = jsdisp_define_data_property(ctx->global, L"ActiveXObject", PROPF_WRITABLE,
1103 jsval_obj(constr));
1104 jsdisp_release(constr);
1105 if(FAILED(hres))
1106 return hres;
1108 hres = jsdisp_define_data_property(ctx->global, L"undefined", const_flags, jsval_undefined());
1109 if(FAILED(hres))
1110 return hres;
1112 hres = jsdisp_define_data_property(ctx->global, L"NaN", const_flags, jsval_number(NAN));
1113 if(FAILED(hres))
1114 return hres;
1116 hres = jsdisp_define_data_property(ctx->global, L"Infinity", const_flags, jsval_number(INFINITY));
1117 return hres;