ReactOS  0.4.14-dev-583-g2a1ba2c
jsutils.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Jacek Caban for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  */
18 
19 #ifdef __REACTOS__
20 #include <wine/config.h>
21 #include <wine/port.h>
22 #endif
23 
24 #include <math.h>
25 #include <assert.h>
26 
27 #include "jscript.h"
28 #include "engine.h"
29 
30 #include "wine/debug.h"
31 
34 
35 const char *debugstr_jsval(const jsval_t v)
36 {
37  switch(jsval_type(v)) {
38  case JSV_UNDEFINED:
39  return "undefined";
40  case JSV_NULL:
41  return "null";
42  case JSV_OBJECT:
43  return wine_dbg_sprintf("obj(%p)", get_object(v));
44  case JSV_STRING:
45  return wine_dbg_sprintf("str(%s)", debugstr_jsstr(get_string(v)));
46  case JSV_NUMBER:
47  return wine_dbg_sprintf("%lf", get_number(v));
48  case JSV_BOOL:
49  return get_bool(v) ? "true" : "false";
50  case JSV_VARIANT:
52  }
53 
54  assert(0);
55  return NULL;
56 }
57 
58 BOOL is_finite(double n)
59 {
60  return !isnan(n) && !isinf(n);
61 }
62 
63 #define MIN_BLOCK_SIZE 128
64 #define ARENA_FREE_FILLER 0xaa
65 
66 static inline DWORD block_size(DWORD block)
67 {
68  return MIN_BLOCK_SIZE << block;
69 }
70 
72 {
73  memset(heap, 0, sizeof(*heap));
74  list_init(&heap->custom_blocks);
75 }
76 
78 {
79  struct list *list;
80  void *tmp;
81 
82  if(!heap->block_cnt) {
83  if(!heap->blocks) {
84  heap->blocks = heap_alloc(sizeof(void*));
85  if(!heap->blocks)
86  return NULL;
87  }
88 
89  tmp = heap_alloc(block_size(0));
90  if(!tmp)
91  return NULL;
92 
93  heap->blocks[0] = tmp;
94  heap->block_cnt = 1;
95  }
96 
97  if(heap->offset + size <= block_size(heap->last_block)) {
98  tmp = ((BYTE*)heap->blocks[heap->last_block])+heap->offset;
99  heap->offset += size;
100  return tmp;
101  }
102 
103  if(size <= block_size(heap->last_block+1)) {
104  if(heap->last_block+1 == heap->block_cnt) {
105  tmp = heap_realloc(heap->blocks, (heap->block_cnt+1)*sizeof(void*));
106  if(!tmp)
107  return NULL;
108 
109  heap->blocks = tmp;
110  heap->blocks[heap->block_cnt] = heap_alloc(block_size(heap->block_cnt));
111  if(!heap->blocks[heap->block_cnt])
112  return NULL;
113 
114  heap->block_cnt++;
115  }
116 
117  heap->last_block++;
118  heap->offset = size;
119  return heap->blocks[heap->last_block];
120  }
121 
122  list = heap_alloc(size + sizeof(struct list));
123  if(!list)
124  return NULL;
125 
127  return list+1;
128 }
129 
130 void *heap_pool_grow(heap_pool_t *heap, void *mem, DWORD size, DWORD inc)
131 {
132  void *ret;
133 
134  if(mem == (BYTE*)heap->blocks[heap->last_block] + heap->offset-size
135  && heap->offset+inc < block_size(heap->last_block)) {
136  heap->offset += inc;
137  return mem;
138  }
139 
140  ret = heap_pool_alloc(heap, size+inc);
141  if(ret) /* FIXME: avoid copying for custom blocks */
142  memcpy(ret, mem, size);
143  return ret;
144 }
145 
147 {
148  struct list *tmp;
149 
150  if(!heap)
151  return;
152 
153  while((tmp = list_head(&heap->custom_blocks))) {
154  list_remove(tmp);
155  heap_free(tmp);
156  }
157 
158  if(WARN_ON(heap)) {
159  DWORD i;
160 
161  for(i=0; i < heap->block_cnt; i++)
163  }
164 
165  heap->last_block = heap->offset = 0;
166  heap->mark = FALSE;
167 }
168 
170 {
171  DWORD i;
172 
173  heap_pool_clear(heap);
174 
175  for(i=0; i < heap->block_cnt; i++)
176  heap_free(heap->blocks[i]);
177  heap_free(heap->blocks);
178 
179  heap_pool_init(heap);
180 }
181 
183 {
184  if(heap->mark)
185  return NULL;
186 
187  heap->mark = TRUE;
188  return heap;
189 }
190 
192 {
193  switch(jsval_type(val)) {
194  case JSV_OBJECT:
195  if(get_object(val))
196  IDispatch_Release(get_object(val));
197  break;
198  case JSV_STRING:
200  break;
201  case JSV_VARIANT:
204  break;
205  default:
206  break;
207  }
208 }
209 
211 {
212  VARIANT *v;
213  HRESULT hres;
214 
216  __JSVAL_VAR(*val) = v = heap_alloc(sizeof(VARIANT));
217  if(!v) {
218  *val = jsval_undefined();
219  return E_OUTOFMEMORY;
220  }
221 
222  V_VT(v) = VT_EMPTY;
223  hres = VariantCopy(v, var);
224  if(FAILED(hres)) {
225  *val = jsval_undefined();
226  heap_free(v);
227  }
228  return hres;
229 }
230 
232 {
233  switch(jsval_type(v)) {
234  case JSV_UNDEFINED:
235  case JSV_NULL:
236  case JSV_NUMBER:
237  case JSV_BOOL:
238  *r = v;
239  return S_OK;
240  case JSV_OBJECT:
241  if(get_object(v))
242  IDispatch_AddRef(get_object(v));
243  *r = v;
244  return S_OK;
245  case JSV_STRING: {
247  *r = v;
248  return S_OK;
249  }
250  case JSV_VARIANT:
251  return jsval_variant(r, get_variant(v));
252  }
253 
254  assert(0);
255  return E_FAIL;
256 }
257 
259 {
260  if(V_VT(var) == (VT_VARIANT|VT_BYREF))
261  var = V_VARIANTREF(var);
262 
263  switch(V_VT(var)) {
264  case VT_EMPTY:
265  *r = jsval_undefined();
266  return S_OK;
267  case VT_NULL:
268  *r = jsval_null();
269  return S_OK;
270  case VT_BOOL:
271  *r = jsval_bool(V_BOOL(var));
272  return S_OK;
273  case VT_I4:
274  *r = jsval_number(V_I4(var));
275  return S_OK;
276  case VT_R8:
277  *r = jsval_number(V_R8(var));
278  return S_OK;
279  case VT_BSTR: {
280  jsstr_t *str;
281 
282  if(V_BSTR(var)) {
284  if(!str)
285  return E_OUTOFMEMORY;
286  }else {
287  str = jsstr_null_bstr();
288  }
289 
290  *r = jsval_string(str);
291  return S_OK;
292  }
293  case VT_DISPATCH: {
294  if(V_DISPATCH(var))
295  IDispatch_AddRef(V_DISPATCH(var));
296  *r = jsval_disp(V_DISPATCH(var));
297  return S_OK;
298  }
299  case VT_I1:
300  *r = jsval_number(V_I1(var));
301  return S_OK;
302  case VT_UI1:
303  *r = jsval_number(V_UI1(var));
304  return S_OK;
305  case VT_I2:
306  *r = jsval_number(V_I2(var));
307  return S_OK;
308  case VT_UI2:
309  *r = jsval_number(V_UI2(var));
310  return S_OK;
311  case VT_INT:
312  *r = jsval_number(V_INT(var));
313  return S_OK;
314  case VT_UI4:
315  *r = jsval_number(V_UI4(var));
316  return S_OK;
317  case VT_UI8:
318  /*
319  * Native doesn't support VT_UI8 here, but it's needed for IE9+ APIs
320  * (native IE9 doesn't use jscript.dll for JavaScript).
321  */
322  *r = jsval_number(V_UI8(var));
323  return S_OK;
324  case VT_R4:
325  *r = jsval_number(V_R4(var));
326  return S_OK;
327  case VT_UNKNOWN:
328  if(V_UNKNOWN(var)) {
329  IDispatch *disp;
330  HRESULT hres;
331 
332  hres = IUnknown_QueryInterface(V_UNKNOWN(var), &IID_IDispatch, (void**)&disp);
333  if(SUCCEEDED(hres)) {
334  *r = jsval_disp(disp);
335  return S_OK;
336  }
337  }else {
338  *r = jsval_disp(NULL);
339  return S_OK;
340  }
341  /* fall through */
342  default:
343  return jsval_variant(r, var);
344  }
345 }
346 
348 {
349  switch(jsval_type(val)) {
350  case JSV_UNDEFINED:
351  V_VT(retv) = VT_EMPTY;
352  return S_OK;
353  case JSV_NULL:
354  V_VT(retv) = VT_NULL;
355  return S_OK;
356  case JSV_OBJECT:
357  V_VT(retv) = VT_DISPATCH;
358  if(get_object(val))
359  IDispatch_AddRef(get_object(val));
360  V_DISPATCH(retv) = get_object(val);
361  return S_OK;
362  case JSV_STRING: {
364 
365  V_VT(retv) = VT_BSTR;
366  if(is_null_bstr(str)) {
367  V_BSTR(retv) = NULL;
368  }else {
370  if(V_BSTR(retv))
371  jsstr_flush(str, V_BSTR(retv));
372  else
373  return E_OUTOFMEMORY;
374  }
375  return S_OK;
376  }
377  case JSV_NUMBER: {
378  double n = get_number(val);
379 
380  if(is_int32(n)) {
381  V_VT(retv) = VT_I4;
382  V_I4(retv) = n;
383  }else {
384  V_VT(retv) = VT_R8;
385  V_R8(retv) = n;
386  }
387 
388  return S_OK;
389  }
390  case JSV_BOOL:
391  V_VT(retv) = VT_BOOL;
392  V_BOOL(retv) = get_bool(val) ? VARIANT_TRUE : VARIANT_FALSE;
393  return S_OK;
394  case JSV_VARIANT:
395  V_VT(retv) = VT_EMPTY;
396  return VariantCopy(retv, get_variant(val));
397  }
398 
399  assert(0);
400  return E_FAIL;
401 }
402 
403 /* ECMA-262 3rd Edition 9.1 */
405 {
406  if(is_object_instance(val)) {
407  jsdisp_t *jsdisp;
408  jsval_t prim;
409  DISPID id;
410  HRESULT hres;
411 
412  static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
413  static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
414 
415  if(!get_object(val)) {
416  *ret = jsval_null();
417  return S_OK;
418  }
419 
420  jsdisp = iface_to_jsdisp(get_object(val));
421  if(!jsdisp)
422  return disp_propget(ctx, get_object(val), DISPID_VALUE, ret);
423 
424  if(hint == NO_HINT)
426 
427  /* Native implementation doesn't throw TypeErrors, returns strange values */
428 
429  hres = jsdisp_get_id(jsdisp, hint == HINT_STRING ? toStringW : valueOfW, 0, &id);
430  if(SUCCEEDED(hres)) {
431  hres = jsdisp_call(jsdisp, id, DISPATCH_METHOD, 0, NULL, &prim);
432  if(FAILED(hres)) {
433  WARN("call error - forwarding exception\n");
434  jsdisp_release(jsdisp);
435  return hres;
436  }else if(!is_object_instance(prim)) {
437  jsdisp_release(jsdisp);
438  *ret = prim;
439  return S_OK;
440  }else {
441  IDispatch_Release(get_object(prim));
442  }
443  }
444 
445  hres = jsdisp_get_id(jsdisp, hint == HINT_STRING ? valueOfW : toStringW, 0, &id);
446  if(SUCCEEDED(hres)) {
447  hres = jsdisp_call(jsdisp, id, DISPATCH_METHOD, 0, NULL, &prim);
448  if(FAILED(hres)) {
449  WARN("call error - forwarding exception\n");
450  jsdisp_release(jsdisp);
451  return hres;
452  }else if(!is_object_instance(prim)) {
453  jsdisp_release(jsdisp);
454  *ret = prim;
455  return S_OK;
456  }else {
457  IDispatch_Release(get_object(prim));
458  }
459  }
460 
461  jsdisp_release(jsdisp);
462 
463  WARN("failed\n");
465  }
466 
467  return jsval_copy(val, ret);
468 
469 }
470 
471 /* ECMA-262 3rd Edition 9.2 */
473 {
474  switch(jsval_type(val)) {
475  case JSV_UNDEFINED:
476  case JSV_NULL:
477  *ret = FALSE;
478  return S_OK;
479  case JSV_OBJECT:
480  *ret = get_object(val) != NULL;
481  return S_OK;
482  case JSV_STRING:
483  *ret = jsstr_length(get_string(val)) != 0;
484  return S_OK;
485  case JSV_NUMBER:
486  *ret = !isnan(get_number(val)) && get_number(val);
487  return S_OK;
488  case JSV_BOOL:
489  *ret = get_bool(val);
490  return S_OK;
491  case JSV_VARIANT:
492  FIXME("unimplemented for variant %s\n", debugstr_variant(get_variant(val)));
493  return E_NOTIMPL;
494  }
495 
496  assert(0);
497  return E_FAIL;
498 }
499 
500 static int hex_to_int(WCHAR c)
501 {
502  if('0' <= c && c <= '9')
503  return c-'0';
504 
505  if('a' <= c && c <= 'f')
506  return c-'a'+10;
507 
508  if('A' <= c && c <= 'F')
509  return c-'A'+10;
510 
511  return -1;
512 }
513 
514 /* ECMA-262 3rd Edition 9.3.1 */
516 {
517  const WCHAR *ptr;
518  BOOL neg = FALSE;
519  DOUBLE d = 0.0;
520 
521  static const WCHAR infinityW[] = {'I','n','f','i','n','i','t','y'};
522 
523  ptr = jsstr_flatten(str);
524  if(!ptr)
525  return E_OUTOFMEMORY;
526 
527  while(iswspace(*ptr))
528  ptr++;
529 
530  if(*ptr == '-') {
531  neg = TRUE;
532  ptr++;
533  }else if(*ptr == '+') {
534  ptr++;
535  }
536 
537  if(!wcsncmp(ptr, infinityW, ARRAY_SIZE(infinityW))) {
538  ptr += ARRAY_SIZE(infinityW);
539  while(*ptr && iswspace(*ptr))
540  ptr++;
541 
542  if(*ptr)
543  *ret = NAN;
544  else
545  *ret = neg ? -INFINITY : INFINITY;
546  return S_OK;
547  }
548 
549  if(*ptr == '0' && ptr[1] == 'x') {
550  DWORD l = 0;
551 
552  ptr += 2;
553  while((l = hex_to_int(*ptr)) != -1) {
554  d = d*16 + l;
555  ptr++;
556  }
557 
558  *ret = d;
559  return S_OK;
560  }
561 
562  while(iswdigit(*ptr))
563  d = d*10 + (*ptr++ - '0');
564 
565  if(*ptr == 'e' || *ptr == 'E') {
566  BOOL eneg = FALSE;
567  LONG l = 0;
568 
569  ptr++;
570  if(*ptr == '-') {
571  ptr++;
572  eneg = TRUE;
573  }else if(*ptr == '+') {
574  ptr++;
575  }
576 
577  while(iswdigit(*ptr))
578  l = l*10 + (*ptr++ - '0');
579  if(eneg)
580  l = -l;
581 
582  d *= pow(10, l);
583  }else if(*ptr == '.') {
584  DOUBLE dec = 0.1;
585 
586  ptr++;
587  while(iswdigit(*ptr)) {
588  d += dec * (*ptr++ - '0');
589  dec *= 0.1;
590  }
591  }
592 
593  while(iswspace(*ptr))
594  ptr++;
595 
596  if(*ptr) {
597  *ret = NAN;
598  return S_OK;
599  }
600 
601  if(neg)
602  d = -d;
603 
604  *ret = d;
605  return S_OK;
606 }
607 
608 /* ECMA-262 3rd Edition 9.3 */
610 {
611  switch(jsval_type(val)) {
612  case JSV_UNDEFINED:
613  *ret = NAN;
614  return S_OK;
615  case JSV_NULL:
616  *ret = 0;
617  return S_OK;
618  case JSV_NUMBER:
619  *ret = get_number(val);
620  return S_OK;
621  case JSV_STRING:
622  return str_to_number(get_string(val), ret);
623  case JSV_OBJECT: {
624  jsval_t prim;
625  HRESULT hres;
626 
627  hres = to_primitive(ctx, val, &prim, HINT_NUMBER);
628  if(FAILED(hres))
629  return hres;
630 
631  hres = to_number(ctx, prim, ret);
633  return hres;
634  }
635  case JSV_BOOL:
636  *ret = get_bool(val) ? 1 : 0;
637  return S_OK;
638  case JSV_VARIANT:
639  FIXME("unimplemented for variant %s\n", debugstr_variant(get_variant(val)));
640  return E_NOTIMPL;
641  };
642 
643  assert(0);
644  return E_FAIL;
645 }
646 
647 /* ECMA-262 3rd Edition 9.4 */
649 {
650  double n;
651  HRESULT hres;
652 
653  hres = to_number(ctx, v, &n);
654  if(FAILED(hres))
655  return hres;
656 
657  if(isnan(n))
658  *ret = 0;
659  else
660  *ret = n >= 0.0 ? floor(n) : -floor(-n);
661  return S_OK;
662 }
663 
664 /* ECMA-262 3rd Edition 9.5 */
666 {
667  double n;
668  HRESULT hres;
669 
670  const double p32 = (double)0xffffffff + 1;
671 
672  hres = to_number(ctx, v, &n);
673  if(FAILED(hres))
674  return hres;
675 
676  if(is_finite(n))
677  n = n > 0 ? fmod(n, p32) : -fmod(-n, p32);
678  else
679  n = 0;
680 
681  *ret = (UINT32)n;
682  return S_OK;
683 }
684 
685 /* ECMA-262 3rd Edition 9.6 */
687 {
688  INT32 n;
689  HRESULT hres;
690 
691  hres = to_int32(ctx, val, &n);
692  if(SUCCEEDED(hres))
693  *ret = n;
694  return hres;
695 }
696 
697 static jsstr_t *int_to_string(int i)
698 {
699  WCHAR buf[12], *p;
700  BOOL neg = FALSE;
701 
702  if(!i) {
703  static const WCHAR zeroW[] = {'0',0};
704  return jsstr_alloc(zeroW);
705  }
706 
707  if(i < 0) {
708  neg = TRUE;
709  i = -i;
710  }
711 
712  p = buf + ARRAY_SIZE(buf)-1;
713  *p-- = 0;
714  while(i) {
715  *p-- = i%10 + '0';
716  i /= 10;
717  }
718 
719  if(neg)
720  *p = '-';
721  else
722  p++;
723 
724  return jsstr_alloc(p);
725 }
726 
728 {
729  static const WCHAR InfinityW[] = {'-','I','n','f','i','n','i','t','y',0};
730 
731  if(isnan(n)) {
732  *str = jsstr_nan();
733  }else if(isinf(n)) {
734  *str = jsstr_alloc(n<0 ? InfinityW : InfinityW+1);
735  }else if(is_int32(n)) {
736  *str = int_to_string(n);
737  }else {
738  VARIANT strv, v;
739  HRESULT hres;
740 
741  /* FIXME: Don't use VariantChangeTypeEx */
742  V_VT(&v) = VT_R8;
743  V_R8(&v) = n;
744  V_VT(&strv) = VT_EMPTY;
746  if(FAILED(hres))
747  return hres;
748 
749  *str = jsstr_alloc(V_BSTR(&strv));
750  SysFreeString(V_BSTR(&strv));
751  }
752 
753  return *str ? S_OK : E_OUTOFMEMORY;
754 }
755 
756 /* ECMA-262 3rd Edition 9.8 */
758 {
759  static const WCHAR nullW[] = {'n','u','l','l',0};
760  static const WCHAR trueW[] = {'t','r','u','e',0};
761  static const WCHAR falseW[] = {'f','a','l','s','e',0};
762 
763  switch(jsval_type(val)) {
764  case JSV_UNDEFINED:
765  *str = jsstr_undefined();
766  return S_OK;
767  case JSV_NULL:
768  *str = jsstr_alloc(nullW);
769  break;
770  case JSV_NUMBER:
772  case JSV_STRING:
774  break;
775  case JSV_OBJECT: {
776  jsval_t prim;
777  HRESULT hres;
778 
779  hres = to_primitive(ctx, val, &prim, HINT_STRING);
780  if(FAILED(hres))
781  return hres;
782 
783  hres = to_string(ctx, prim, str);
785  return hres;
786  }
787  case JSV_BOOL:
789  break;
790  default:
791  FIXME("unsupported %s\n", debugstr_jsval(val));
792  return E_NOTIMPL;
793  }
794 
795  return *str ? S_OK : E_OUTOFMEMORY;
796 }
797 
799 {
800  HRESULT hres;
801 
802  hres = to_string(ctx, val, str);
803  if(FAILED(hres))
804  return hres;
805 
806  *ret_str = jsstr_flatten(*str);
807  if(!*ret_str) {
808  jsstr_release(*str);
809  return E_OUTOFMEMORY;
810  }
811 
812  return S_OK;
813 }
814 
815 /* ECMA-262 3rd Edition 9.9 */
817 {
818  jsdisp_t *dispex;
819  HRESULT hres;
820 
821  switch(jsval_type(val)) {
822  case JSV_STRING:
823  hres = create_string(ctx, get_string(val), &dispex);
824  if(FAILED(hres))
825  return hres;
826 
827  *disp = to_disp(dispex);
828  break;
829  case JSV_NUMBER:
830  hres = create_number(ctx, get_number(val), &dispex);
831  if(FAILED(hres))
832  return hres;
833 
834  *disp = to_disp(dispex);
835  break;
836  case JSV_OBJECT:
837  if(get_object(val)) {
838  *disp = get_object(val);
839  IDispatch_AddRef(*disp);
840  }else {
841  jsdisp_t *obj;
842 
843  hres = create_object(ctx, NULL, &obj);
844  if(FAILED(hres))
845  return hres;
846 
847  *disp = to_disp(obj);
848  }
849  break;
850  case JSV_BOOL:
851  hres = create_bool(ctx, get_bool(val), &dispex);
852  if(FAILED(hres))
853  return hres;
854 
855  *disp = to_disp(dispex);
856  break;
857  case JSV_UNDEFINED:
858  case JSV_NULL:
859  WARN("object expected\n");
861  case JSV_VARIANT:
862  switch(V_VT(get_variant(val))) {
863  case VT_ARRAY|VT_VARIANT:
864  hres = create_vbarray(ctx, V_ARRAY(get_variant(val)), &dispex);
865  if(FAILED(hres))
866  return hres;
867 
868  *disp = to_disp(dispex);
869  break;
870 
871  default:
872  FIXME("Unsupported %s\n", debugstr_variant(get_variant(val)));
873  return E_NOTIMPL;
874  }
875  break;
876  }
877 
878  return S_OK;
879 }
880 
882 {
883  jsval_t val;
884  HRESULT hres;
885 
886  clear_ei(ctx);
888  if(FAILED(hres))
889  return hres;
890 
891  switch(vt) {
892  case VT_I2:
893  case VT_I4: {
894  INT i;
895 
896  hres = to_int32(ctx, val, &i);
897  if(SUCCEEDED(hres)) {
898  if(vt == VT_I4)
899  V_I4(dst) = i;
900  else
901  V_I2(dst) = i;
902  }
903  break;
904  }
905  case VT_UI2: {
906  UINT32 i;
907 
908  hres = to_uint32(ctx, val, &i);
909  if(SUCCEEDED(hres))
910  V_UI2(dst) = i;
911  break;
912  }
913  case VT_R8: {
914  double n;
915  hres = to_number(ctx, val, &n);
916  if(SUCCEEDED(hres))
917  V_R8(dst) = n;
918  break;
919  }
920  case VT_R4: {
921  double n;
922 
923  hres = to_number(ctx, val, &n);
924  if(SUCCEEDED(hres))
925  V_R4(dst) = n;
926  break;
927  }
928  case VT_BOOL: {
929  BOOL b;
930 
931  hres = to_boolean(val, &b);
932  if(SUCCEEDED(hres))
933  V_BOOL(dst) = b ? VARIANT_TRUE : VARIANT_FALSE;
934  break;
935  }
936  case VT_BSTR: {
937  jsstr_t *str;
938 
939  hres = to_string(ctx, val, &str);
940  if(FAILED(hres))
941  break;
942 
943  if(is_null_bstr(str)) {
944  V_BSTR(dst) = NULL;
945  break;
946  }
947 
949  if(V_BSTR(dst))
951  else
953  break;
954  }
955  case VT_EMPTY:
956  hres = V_VT(src) == VT_EMPTY ? S_OK : E_NOTIMPL;
957  break;
958  case VT_NULL:
959  hres = V_VT(src) == VT_NULL ? S_OK : E_NOTIMPL;
960  break;
961  default:
962  FIXME("vt %d not implemented\n", vt);
963  hres = E_NOTIMPL;
964  }
965 
967  if(FAILED(hres))
968  return hres;
969 
970  V_VT(dst) = vt;
971  return S_OK;
972 }
973 
975 {
976  return CONTAINING_RECORD(iface, JSCaller, IServiceProvider_iface);
977 }
978 
980 {
982 
983  if(IsEqualGUID(&IID_IUnknown, riid)) {
984  TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
985  *ppv = &This->IServiceProvider_iface;
986  }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
987  TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
988  *ppv = &This->IServiceProvider_iface;
989  }else {
990  WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
991  *ppv = NULL;
992  return E_NOINTERFACE;
993  }
994 
995  IUnknown_AddRef((IUnknown*)*ppv);
996  return S_OK;
997 }
998 
1000 {
1002  LONG ref = InterlockedIncrement(&This->ref);
1003 
1004  TRACE("(%p) ref=%d\n", This, ref);
1005 
1006  return ref;
1007 }
1008 
1010 {
1012  LONG ref = InterlockedIncrement(&This->ref);
1013 
1014  TRACE("(%p) ref=%d\n", This, ref);
1015 
1016  if(!ref) {
1017  assert(!This->ctx);
1018  heap_free(This);
1019  }
1020 
1021  return ref;
1022 }
1023 
1025  REFIID riid, void **ppv)
1026 {
1028 
1029  if(IsEqualGUID(guidService, &SID_VariantConversion) && This->ctx && This->ctx->active_script) {
1030  TRACE("(%p)->(SID_VariantConversion)\n", This);
1031  return IActiveScript_QueryInterface(This->ctx->active_script, riid, ppv);
1032  }
1033 
1034  FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1035 
1036  *ppv = NULL;
1037  return E_NOINTERFACE;
1038 }
1039 
1040 static const IServiceProviderVtbl ServiceProviderVtbl = {
1045 };
1046 
1048 {
1049  JSCaller *ret;
1050 
1051  ret = heap_alloc(sizeof(*ret));
1052  if(!ret)
1053  return E_OUTOFMEMORY;
1054 
1055  ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
1056  ret->ref = 1;
1057  ret->ctx = ctx;
1058 
1059  ctx->jscaller = ret;
1060  return S_OK;
1061 }
static unsigned int block
Definition: xmlmemory.c:118
jsstr_t * jsstr_alloc_len(const WCHAR *buf, unsigned len)
Definition: jsstr.c:86
Definition: jsval.h:54
jsstr_t * jsstr_nan(void)
Definition: jsstr.c:283
static jsstr_t * jsstr_alloc(const WCHAR *str)
Definition: jsstr.h:103
static const IServiceProviderVtbl ServiceProviderVtbl
Definition: jsutils.c:1040
static const WCHAR * jsstr_flatten(jsstr_t *str)
Definition: jsstr.h:139
disp
Definition: i386-dis.c:3181
void jsval_release(jsval_t val)
Definition: jsutils.c:191
#define MAKELCID(lgid, srtid)
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
static HRESULT str_to_number(jsstr_t *str, double *ret)
Definition: jsutils.c:515
#define E_NOINTERFACE
Definition: winerror.h:2364
Definition: compat.h:1947
jsstr_t * jsstr_null_bstr(void)
Definition: jsstr.c:298
void heap_pool_clear(heap_pool_t *heap)
Definition: jsutils.c:146
static ULONG WINAPI JSCaller_AddRef(IServiceProvider *iface)
Definition: jsutils.c:999
Definition: scsiwmi.h:51
BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
Definition: oleaut.c:339
Definition: compat.h:1959
jsstr_t * jsstr_undefined(void)
Definition: jsstr.c:293
Definition: jsstr.h:39
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define ARENA_FREE_FILLER
Definition: jsutils.c:64
static jsval_t jsval_null(void)
Definition: jsval.h:130
static IDispatch * get_object(jsval_t v)
Definition: jsval.h:219
REFIID riid
Definition: precomp.h:44
static jsstr_t * jsstr_addref(jsstr_t *str)
Definition: jsstr.h:116
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
HRESULT double_to_string(double n, jsstr_t **str)
Definition: jsutils.c:727
#define V_R8(A)
Definition: oleauto.h:262
#define V_ARRAY(A)
Definition: oleauto.h:222
#define iswdigit(_c)
Definition: ctype.h:667
#define WARN(fmt,...)
Definition: debug.h:111
HRESULT create_string(script_ctx_t *, jsstr_t *, jsdisp_t **) DECLSPEC_HIDDEN
Definition: string.c:1787
#define V_I2(A)
Definition: oleauto.h:245
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
REFIID LPVOID * ppv
Definition: atlbase.h:39
static const WCHAR toStringW[]
Definition: array.c:50
GLdouble n
Definition: glext.h:7729
static unsigned jsstr_flush(jsstr_t *str, WCHAR *buf)
Definition: jsstr.h:148
#define assert(x)
Definition: debug.h:53
ios_base &_STLP_CALL dec(ios_base &__s)
Definition: _ios_base.h:321
WINE_DECLARE_DEBUG_CHANNEL(heap)
static unsigned jsstr_length(jsstr_t *str)
Definition: jsstr.h:58
static void jsstr_release(jsstr_t *str)
Definition: jsstr.h:110
HRESULT to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *ret, hint_t hint)
Definition: jsutils.c:404
void clear_ei(script_ctx_t *ctx)
Definition: engine.c:430
static const WCHAR valueOfW[]
Definition: bool.c:35
void heap_pool_free(heap_pool_t *heap)
Definition: jsutils.c:169
#define E_FAIL
Definition: ddrawi.h:102
int32_t INT
Definition: typedefs.h:56
Definition: send.c:47
static void * heap_realloc(void *mem, size_t len)
Definition: appwiz.h:70
#define V_UI8(A)
Definition: oleauto.h:272
static char * get_string(void)
Definition: ppl.yy.c:4402
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
#define SUBLANG_ENGLISH_US
Definition: nls.h:222
#define JS_E_TO_PRIMITIVE
Definition: jscript.h:528
#define V_I4(A)
Definition: oleauto.h:247
#define DISPATCH_METHOD
Definition: oleauto.h:1006
static DWORD block_size(DWORD block)
Definition: jsutils.c:66
HRESULT jsdisp_call(jsdisp_t *disp, DISPID id, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
Definition: dispex.c:1113
GLsizei GLsizei GLuint * obj
Definition: glext.h:6042
__WINE_SERVER_LIST_INLINE struct list * list_head(const struct list *list)
Definition: list.h:131
heap_pool_t * heap_pool_mark(heap_pool_t *heap)
Definition: jsutils.c:182
const char * wine_dbg_sprintf(const char *format,...)
Definition: compat.c:271
#define V_DISPATCH(A)
Definition: oleauto.h:239
#define MIN_BLOCK_SIZE
Definition: jsutils.c:63
BOOL mark
Definition: jscript.h:65
#define WARN_ON(c)
Definition: module.h:255
static HRESULT WINAPI JSCaller_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
Definition: jsutils.c:979
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HRESULT to_boolean(jsval_t val, BOOL *ret)
Definition: jsutils.c:472
#define __JSVAL_VAR(x)
Definition: jsval.h:97
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
HRESULT create_jscaller(script_ctx_t *ctx)
Definition: jsutils.c:1047
unsigned int UINT32
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
float pow(float __x, int __y)
Definition: _cmath.h:458
HRESULT jsval_copy(jsval_t v, jsval_t *r)
Definition: jsutils.c:231
static BOOL is_class(jsdisp_t *jsdisp, jsclass_t class)
Definition: jscript.h:504
HRESULT to_object(script_ctx_t *ctx, jsval_t val, IDispatch **disp)
Definition: jsutils.c:816
static BOOL get_bool(D3DXPARAMETER_TYPE type, const void *data)
HRESULT to_string(script_ctx_t *ctx, jsval_t val, jsstr_t **str)
Definition: jsutils.c:757
GLenum GLint ref
Definition: glext.h:6028
#define FIXME(fmt,...)
Definition: debug.h:110
static PVOID ptr
Definition: dispmode.c:27
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:80
HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val)
Definition: dispex.c:1458
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
void * heap_pool_alloc(heap_pool_t *heap, DWORD size)
Definition: jsutils.c:77
HRESULT jsval_to_variant(jsval_t val, VARIANT *retv)
Definition: jsutils.c:347
#define V_UI2(A)
Definition: oleauto.h:268
#define V_I1(A)
Definition: oleauto.h:243
static BOOL is_object_instance(jsval_t v)
Definition: jsval.h:166
HRESULT variant_to_jsval(VARIANT *var, jsval_t *r)
Definition: jsutils.c:258
static jsval_t jsval_string(jsstr_t *str)
Definition: jsval.h:109
HRESULT create_number(script_ctx_t *, double, jsdisp_t **) DECLSPEC_HIDDEN
Definition: number.c:632
#define debugstr_guid
Definition: kernel32.h:35
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define b
Definition: ke_i.h:79
GLuint GLfloat * val
Definition: glext.h:7180
JSCaller * jscaller
Definition: jscript.h:424
r l[0]
Definition: byte_order.h:167
static int hex_to_int(WCHAR c)
Definition: jsutils.c:500
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
#define V_R4(A)
Definition: oleauto.h:260
_Check_return_ double __cdecl fmod(_In_ double x, _In_ double y)
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define TRACE(s)
Definition: solgame.cpp:4
const char * debugstr_jsstr(jsstr_t *str)
Definition: jsstr.c:37
Definition: jsval.h:46
static jsval_t jsval_disp(IDispatch *obj)
Definition: jsval.h:117
GLsizeiptr size
Definition: glext.h:5919
HRESULT hres
Definition: protocol.c:465
HRESULT create_bool(script_ctx_t *ctx, BOOL b, jsdisp_t **ret)
Definition: bool.c:216
#define d
Definition: ke_i.h:81
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define SORT_DEFAULT
LONG HRESULT
Definition: typedefs.h:77
BOOL is_finite(double n)
Definition: jsutils.c:58
const GUID IID_IUnknown
int isinf(double x)
#define V_UI1(A)
Definition: oleauto.h:266
static const WCHAR falseW[]
Definition: json.c:34
#define WINAPI
Definition: msvc.h:6
const GLubyte * c
Definition: glext.h:8905
#define V_BOOL(A)
Definition: oleauto.h:224
unsigned long DWORD
Definition: ntddk_ex.h:95
#define NAN
Definition: misc.c:46
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:85
HRESULT to_uint32(script_ctx_t *ctx, jsval_t val, UINT32 *ret)
Definition: jsutils.c:686
_Check_return_ _CRTIMP int __cdecl wcsncmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
#define LANG_ENGLISH
Definition: nls.h:52
static VARIANT * get_variant(jsval_t v)
Definition: jsval.h:234
#define iswspace(_c)
Definition: ctype.h:669
#define V_UI4(A)
Definition: oleauto.h:270
const GUID IID_IDispatch
static double get_number(jsval_t v)
Definition: jsval.h:224
int ret
static HRESULT jsval_variant(jsval_t *val, VARIANT *var)
Definition: jsutils.c:210
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
Definition: compat.h:1948
HRESULT to_flat_string(script_ctx_t *ctx, jsval_t val, jsstr_t **str, const WCHAR **ret_str)
Definition: jsutils.c:798
static jsval_type_t jsval_type(jsval_t v)
Definition: jsval.h:210
const char * debugstr_jsval(const jsval_t v)
Definition: jsutils.c:35
#define V_VT(A)
Definition: oleauto.h:211
DWORD offset
Definition: jscript.h:64
struct list custom_blocks
Definition: jscript.h:66
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
unsigned char BYTE
Definition: mem.h:68
HRESULT to_int32(script_ctx_t *ctx, jsval_t v, INT *ret)
Definition: jsutils.c:665
Definition: _list.h:228
HRESULT jsdisp_get_id(jsdisp_t *jsdisp, const WCHAR *name, DWORD flags, DISPID *id)
Definition: dispex.c:1067
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:196
GLenum src
Definition: glext.h:6340
#define V_UNKNOWN(A)
Definition: oleauto.h:281
#define V_BSTR(A)
Definition: oleauto.h:226
static IDispatch * to_disp(jsdisp_t *jsdisp)
Definition: jscript.h:245
int isnan(double x)
jsdisp_t * iface_to_jsdisp(IDispatch *iface)
Definition: dispex.c:1060
static jsval_t jsval_undefined(void)
Definition: jsval.h:137
static const char * debugstr_variant(const VARIANT *var)
Definition: container.c:46
static VARIANTARG static DISPID
Definition: ordinal.c:49
#define S_OK
Definition: intsafe.h:59
DWORD hint
Definition: vfdcmd.c:88
#define InterlockedIncrement
Definition: armddk.h:53
static JSCaller * impl_from_IServiceProvider(IServiceProvider *iface)
Definition: jsutils.c:974
const GLdouble * v
Definition: gl.h:2040
BOOL is_null_bstr(jsstr_t *str)
Definition: jsstr.c:303
hint_t
Definition: jscript.h:337
void ** blocks
Definition: jscript.h:61
#define ARRAY_SIZE(a)
Definition: main.h:24
WINE_DEFAULT_DEBUG_CHANNEL(jscript)
static jsstr_t * int_to_string(int i)
Definition: jsutils.c:697
#define E_NOTIMPL
Definition: ddrawi.h:99
GLenum GLenum dst
Definition: glext.h:6340
#define V_INT(x)
Definition: webchild.h:78
unsigned short VARTYPE
Definition: compat.h:1903
#define list
Definition: rosglue.h:35
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
HRESULT variant_change_type(script_ctx_t *ctx, VARIANT *dst, VARIANT *src, VARTYPE vt)
Definition: jsutils.c:881
DWORD last_block
Definition: jscript.h:63
static void jsdisp_release(jsdisp_t *jsdisp)
Definition: jscript.h:268
static const WCHAR InfinityW[]
Definition: global.c:35
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
LOCAL int prim(arg_t *ap)
Definition: match.c:440
void heap_pool_init(heap_pool_t *heap)
Definition: jsutils.c:71
void * heap_pool_grow(heap_pool_t *heap, void *mem, DWORD size, DWORD inc)
Definition: jsutils.c:130
Definition: mem.c:156
HRESULT to_number(script_ctx_t *ctx, jsval_t val, double *ret)
Definition: jsutils.c:609
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
unsigned int ULONG
Definition: retypes.h:1
GLenum GLuint id
Definition: glext.h:5579
#define MAKELANGID(p, s)
Definition: nls.h:15
HRESULT create_object(script_ctx_t *, jsdisp_t *, jsdisp_t **) DECLSPEC_HIDDEN
Definition: object.c:731
signed int INT32
double DOUBLE
Definition: typedefs.h:68
HRESULT throw_type_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str)
Definition: error.c:440
Definition: jsval.h:50
static jsval_t jsval_bool(BOOL b)
Definition: jsval.h:101
#define V_VARIANTREF(A)
Definition: oleauto.h:283
static ULONG WINAPI JSCaller_Release(IServiceProvider *iface)
Definition: jsutils.c:1009
GLfloat GLfloat p
Definition: glext.h:8902
static const WCHAR trueW[]
Definition: json.c:33
_Check_return_ _CRTIMP double __cdecl floor(_In_ double x)
HRESULT WINAPI VariantCopy(VARIANTARG *pvargDest, VARIANTARG *pvargSrc)
Definition: variant.c:748
static HRESULT WINAPI JSCaller_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv)
Definition: jsutils.c:1024
HRESULT to_integer(script_ctx_t *ctx, jsval_t v, double *ret)
Definition: jsutils.c:648
#define memset(x, y, z)
Definition: compat.h:39
static BOOL is_int32(double d)
Definition: jscript.h:514
HRESULT create_vbarray(script_ctx_t *, SAFEARRAY *, jsdisp_t **) DECLSPEC_HIDDEN
Definition: vbarray.c:347
DWORD block_cnt
Definition: jscript.h:62
#define JS_E_OBJECT_EXPECTED
Definition: jscript.h:555
static const WCHAR nullW[]
Definition: json.c:32
Definition: compat.h:1949
Definition: compat.h:1946
#define SUCCEEDED(hr)
Definition: intsafe.h:57
#define INFINITY
Definition: misc.c:36
static jsval_t jsval_number(double n)
Definition: jsval.h:144
HRESULT WINAPI VariantChangeTypeEx(VARIANTARG *pvargDest, VARIANTARG *pvargSrc, LCID lcid, USHORT wFlags, VARTYPE vt)
Definition: variant.c:988
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
#define __JSVAL_TYPE(x)
Definition: jsval.h:93