ReactOS 0.4.15-dev-8227-g32d615f
engine.c
Go to the documentation of this file.
1/*
2 * Copyright 2008,2011 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
33
34static const WCHAR booleanW[] = {'b','o','o','l','e','a','n',0};
35static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0};
36static const WCHAR numberW[] = {'n','u','m','b','e','r',0};
37static const WCHAR objectW[] = {'o','b','j','e','c','t',0};
38static const WCHAR stringW[] = {'s','t','r','i','n','g',0};
39static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
40static const WCHAR unknownW[] = {'u','n','k','n','o','w','n',0};
41
43 unsigned stack_top;
45 unsigned catch_off;
46 unsigned finally_off;
47
49};
50
51typedef struct {
52 enum {
56 EXPRVAL_INVALID
58 union {
60 struct {
63 } idref;
64 unsigned off;
66 } u;
67} exprval_t;
68
70{
71 if(!ctx->stack_size) {
72 ctx->stack = heap_alloc(16*sizeof(*ctx->stack));
73 if(!ctx->stack)
74 return E_OUTOFMEMORY;
75 ctx->stack_size = 16;
76 }else if(ctx->stack_size == ctx->stack_top) {
77 jsval_t *new_stack;
78
79 new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(*new_stack));
80 if(!new_stack) {
82 return E_OUTOFMEMORY;
83 }
84
85 ctx->stack = new_stack;
86 ctx->stack_size *= 2;
87 }
88
89 ctx->stack[ctx->stack_top++] = v;
90 return S_OK;
91}
92
94{
95 jsstr_t *v;
96
97 v = jsstr_alloc(str);
98 if(!v)
99 return E_OUTOFMEMORY;
100
101 return stack_push(ctx, jsval_string(v));
102}
103
105{
106 assert(ctx->stack_top > ctx->call_ctx->stack_base);
107 return ctx->stack[ctx->stack_top-1];
108}
109
110static inline jsval_t *stack_top_ref(script_ctx_t *ctx, unsigned n)
111{
112 assert(ctx->stack_top > ctx->call_ctx->stack_base+n);
113 return ctx->stack+ctx->stack_top-1-n;
114}
115
116static inline jsval_t stack_topn(script_ctx_t *ctx, unsigned n)
117{
118 return *stack_top_ref(ctx, n);
119}
120
121static inline jsval_t *stack_args(script_ctx_t *ctx, unsigned n)
122{
123 if(!n)
124 return NULL;
125 assert(ctx->stack_top > ctx->call_ctx->stack_base+n-1);
126 return ctx->stack + ctx->stack_top-n;
127}
128
130{
131 assert(ctx->stack_top > ctx->call_ctx->stack_base);
132 return ctx->stack[--ctx->stack_top];
133}
134
135static void stack_popn(script_ctx_t *ctx, unsigned n)
136{
137 while(n--)
139}
140
142{
143 jsval_t v;
145
146 v = stack_pop(ctx);
147 hres = to_number(ctx, v, r);
149 return hres;
150}
151
153{
154 jsval_t v;
156
157 v = stack_pop(ctx);
158 if(is_object_instance(v)) {
159 if(!get_object(v))
161 *r = get_object(v);
162 return S_OK;
163 }
164
165 hres = to_object(ctx, v, r);
167 return hres;
168}
169
171{
172 return to_int32(ctx, stack_pop(ctx), r);
173}
174
176{
177 return to_uint32(ctx, stack_pop(ctx), r);
178}
179
180static inline unsigned local_off(call_frame_t *frame, int ref)
181{
182 return ref < 0
183 ? frame->arguments_off - ref-1
184 : frame->variables_off + ref;
185}
186
187static inline BSTR local_name(call_frame_t *frame, int ref)
188{
189 return ref < 0 ? frame->function->params[-ref-1] : frame->function->variables[ref].name;
190}
191
192/* Steals input reference even on failure. */
194{
196
197 switch(val->type) {
198 case EXPRVAL_JSVAL:
199 assert(0);
200 case EXPRVAL_IDREF:
201 hres = stack_push(ctx, jsval_disp(val->u.idref.disp));
202 if(SUCCEEDED(hres))
203 hres = stack_push(ctx, jsval_number(val->u.idref.id));
204 else
205 IDispatch_Release(val->u.idref.disp);
206 return hres;
207 case EXPRVAL_STACK_REF:
208 hres = stack_push(ctx, jsval_number(val->u.off));
209 if(SUCCEEDED(hres))
211 return hres;
212 case EXPRVAL_INVALID:
214 if(SUCCEEDED(hres))
215 hres = stack_push(ctx, jsval_number(val->u.hres));
216 return hres;
217 }
218
219 assert(0);
220 return E_FAIL;
221}
222
224{
225 jsval_t v = stack_topn(ctx, n+1);
226
227 switch(jsval_type(v)) {
228 case JSV_NUMBER: {
229 call_frame_t *frame = ctx->call_ctx;
230 unsigned off = get_number(v);
231
232 if(!frame->base_scope->frame && off >= frame->arguments_off) {
233 DISPID id;
234 BSTR name;
236
237 /* Got stack reference in deoptimized code. Need to convert it back to variable object reference. */
238
239 assert(off < frame->variables_off + frame->function->var_cnt);
240 name = off >= frame->variables_off
241 ? frame->function->variables[off - frame->variables_off].name
242 : frame->function->params[off - frame->arguments_off];
243 hres = jsdisp_get_id(ctx->call_ctx->base_scope->jsobj, name, 0, &id);
244 if(FAILED(hres)) {
245 r->type = EXPRVAL_INVALID;
246 r->u.hres = hres;
247 return FALSE;
248 }
249
252 r->type = EXPRVAL_IDREF;
253 r->u.idref.disp = frame->base_scope->obj;
254 r->u.idref.id = id;
255 return TRUE;
256 }
257
258 r->type = EXPRVAL_STACK_REF;
259 r->u.off = off;
260 return TRUE;
261 }
262 case JSV_OBJECT:
263 r->type = EXPRVAL_IDREF;
264 r->u.idref.disp = get_object(v);
266 r->u.idref.id = get_number(stack_topn(ctx, n));
267 return TRUE;
268 case JSV_UNDEFINED:
269 r->type = EXPRVAL_INVALID;
271 r->u.hres = get_number(stack_topn(ctx, n));
272 return FALSE;
273 default:
274 assert(0);
275 return FALSE;
276 }
277}
278
280{
282 ctx->stack_top -= 2;
283 return ret;
284}
285
287{
288 switch(ref->type) {
289 case EXPRVAL_STACK_REF: {
290 jsval_t *r = ctx->stack + ref->u.off;
292 return jsval_copy(v, r);
293 }
294 case EXPRVAL_IDREF:
295 return disp_propput(ctx, ref->u.idref.disp, ref->u.idref.id, v);
296 default:
297 assert(0);
298 return E_FAIL;
299 }
300}
301
303{
304 switch(ref->type) {
305 case EXPRVAL_STACK_REF:
306 return jsval_copy(ctx->stack[ref->u.off], r);
307 case EXPRVAL_IDREF:
308 return disp_propget(ctx, ref->u.idref.disp, ref->u.idref.id, r);
309 default:
310 assert(0);
311 return E_FAIL;
312 }
313}
314
316{
317 switch(ref->type) {
318 case EXPRVAL_STACK_REF: {
319 jsval_t v = ctx->stack[ref->u.off];
320
321 if(!is_object_instance(v)) {
322 FIXME("invoke %s\n", debugstr_jsval(v));
323 return E_FAIL;
324 }
325
327 }
328 case EXPRVAL_IDREF:
329 return disp_call(ctx, ref->u.idref.disp, ref->u.idref.id, flags, argc, argv, r);
330 default:
331 assert(0);
332 return E_FAIL;
333 }
334}
335
336/* ECMA-262 3rd Edition 8.7.1 */
337/* Steals input reference. */
339{
341
342 if(ref->type == EXPRVAL_JSVAL) {
343 *r = ref->u.val;
344 return S_OK;
345 }
346
348
349 if(ref->type == EXPRVAL_IDREF)
350 IDispatch_Release(ref->u.idref.disp);
351 return hres;
352}
353
355{
356 switch(val->type) {
357 case EXPRVAL_JSVAL:
358 jsval_release(val->u.val);
359 return;
360 case EXPRVAL_IDREF:
361 if(val->u.idref.disp)
362 IDispatch_Release(val->u.idref.disp);
363 return;
364 case EXPRVAL_STACK_REF:
365 case EXPRVAL_INVALID:
366 return;
367 }
368}
369
371{
372 val->type = EXPRVAL_INVALID;
373 val->u.hres = hres;
374}
375
377{
378 ref->type = EXPRVAL_IDREF;
379#ifdef __REACTOS__ /* FIXME: Inspect */
380 IDispatch_AddRef(obj);
381 ref->u.idref.disp = obj;
382#else
383 IDispatch_AddRef(ref->u.idref.disp = obj);
384#endif
385 ref->u.idref.id = id;
386}
387
388static inline jsval_t steal_ret(call_frame_t *frame)
389{
390 jsval_t r = frame->ret;
391 frame->ret = jsval_undefined();
392 return r;
393}
394
395static inline void clear_acc(script_ctx_t *ctx)
396{
397 jsval_release(ctx->acc);
398 ctx->acc = jsval_undefined();
399}
400
402{
403 scope_chain_t *new_scope;
404
405 new_scope = heap_alloc(sizeof(scope_chain_t));
406 if(!new_scope)
407 return E_OUTOFMEMORY;
408
409 new_scope->ref = 1;
410
411 IDispatch_AddRef(obj);
412 new_scope->jsobj = jsobj;
413 new_scope->obj = obj;
414 new_scope->frame = NULL;
415 new_scope->next = scope ? scope_addref(scope) : NULL;
416
417 *ret = new_scope;
418 return S_OK;
419}
420
421static void scope_pop(scope_chain_t **scope)
422{
423 scope_chain_t *tmp;
424
425 tmp = *scope;
426 *scope = tmp->next;
427 scope_release(tmp);
428}
429
431{
432 memset(&ctx->ei.ei, 0, sizeof(ctx->ei.ei));
433 jsval_release(ctx->ei.val);
434 ctx->ei.val = jsval_undefined();
435}
436
438{
439 if(--scope->ref)
440 return;
441
442 if(scope->next)
443 scope_release(scope->next);
444
445 IDispatch_Release(scope->obj);
446 heap_free(scope);
447}
448
449static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, const WCHAR *name, BSTR name_bstr, DWORD flags, DISPID *id)
450{
451 IDispatchEx *dispex;
452 jsdisp_t *jsdisp;
453 BSTR bstr;
455
456 jsdisp = iface_to_jsdisp(disp);
457 if(jsdisp) {
458 hres = jsdisp_get_id(jsdisp, name, flags, id);
459 jsdisp_release(jsdisp);
460 return hres;
461 }
462
463 if(name_bstr) {
464 bstr = name_bstr;
465 }else {
466 bstr = SysAllocString(name);
467 if(!bstr)
468 return E_OUTOFMEMORY;
469 }
470
471 *id = 0;
472 hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
473 if(SUCCEEDED(hres)) {
474 hres = IDispatchEx_GetDispID(dispex, bstr, make_grfdex(ctx, flags|fdexNameCaseSensitive), id);
475 IDispatchEx_Release(dispex);
476 }else {
477 TRACE("using IDispatch\n");
478 hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &bstr, 1, 0, id);
479 }
480
481 if(name_bstr != bstr)
482 SysFreeString(bstr);
483 return hres;
484}
485
486static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret)
487{
489 IUnknown *unk1, *unk2;
491
492 if(disp1 == disp2) {
493 *ret = TRUE;
494 return S_OK;
495 }
496
497 if(!disp1 || !disp2) {
498 *ret = FALSE;
499 return S_OK;
500 }
501
502 hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1);
503 if(FAILED(hres))
504 return hres;
505
506 hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2);
507 if(FAILED(hres)) {
508 IUnknown_Release(unk1);
509 return hres;
510 }
511
512 if(unk1 == unk2) {
513 *ret = TRUE;
514 }else {
515 hres = IUnknown_QueryInterface(unk1, &IID_IObjectIdentity, (void**)&identity);
516 if(SUCCEEDED(hres)) {
517 hres = IObjectIdentity_IsEqualObject(identity, unk2);
518 IObjectIdentity_Release(identity);
519 *ret = hres == S_OK;
520 }else {
521 *ret = FALSE;
522 }
523 }
524
525 IUnknown_Release(unk1);
526 IUnknown_Release(unk2);
527 return S_OK;
528}
529
530/* ECMA-262 3rd Edition 11.9.6 */
532{
534
535 TRACE("\n");
536
537 if(type != jsval_type(rval)) {
538 if(is_null_instance(lval))
540 else
541 *ret = FALSE;
542 return S_OK;
543 }
544
545 switch(type) {
546 case JSV_UNDEFINED:
547 case JSV_NULL:
548 *ret = TRUE;
549 break;
550 case JSV_OBJECT:
551 return disp_cmp(get_object(lval), get_object(rval), ret);
552 case JSV_STRING:
554 break;
555 case JSV_NUMBER:
556 *ret = get_number(lval) == get_number(rval);
557 break;
558 case JSV_BOOL:
559 *ret = !get_bool(lval) == !get_bool(rval);
560 break;
561 case JSV_VARIANT:
562 FIXME("VARIANT not implemented\n");
563 return E_NOTIMPL;
564 }
565
566 return S_OK;
567}
568
569/*
570 * Transfers local variables from stack to variable object.
571 * It's slow, so we want to avoid it as much as possible.
572 */
574{
575 unsigned i;
577
578 if(!frame->base_scope || !frame->base_scope->frame)
579 return S_OK;
580
581 TRACE("detaching %p\n", frame);
582
583 assert(frame == frame->base_scope->frame);
584 assert(frame->variable_obj == frame->base_scope->jsobj);
585
586 if(!from_release && !frame->arguments_obj) {
588 if(FAILED(hres))
589 return hres;
590 }
591
592 frame->base_scope->frame = NULL;
593
594 for(i = 0; i < frame->function->locals_cnt; i++) {
596 ctx->stack[local_off(frame, frame->function->locals[i].ref)]);
597 if(FAILED(hres))
598 return hres;
599 }
600
601 return S_OK;
602}
603
605{
607 DISPID id;
609
610 for(item = ctx->named_items; item; item = item->next) {
611 if(item->flags & SCRIPTITEM_GLOBALMEMBERS) {
612 hres = disp_get_id(ctx, item->disp, identifier, identifier, 0, &id);
613 if(SUCCEEDED(hres)) {
614 if(ret)
615 exprval_set_disp_ref(ret, item->disp, id);
616 return TRUE;
617 }
618 }
619 }
620
621 return FALSE;
622}
623
624static int __cdecl local_ref_cmp(const void *key, const void *ref)
625{
626 return wcscmp((const WCHAR*)key, ((const local_ref_t*)ref)->name);
627}
628
629local_ref_t *lookup_local(const function_code_t *function, const WCHAR *identifier)
630{
631 return bsearch(identifier, function->locals, function->locals_cnt, sizeof(*function->locals), local_ref_cmp);
632}
633
634/* ECMA-262 3rd Edition 10.1.4 */
636{
637 scope_chain_t *scope;
639 DISPID id = 0;
641
642 TRACE("%s\n", debugstr_w(identifier));
643
644 if(ctx->call_ctx) {
645 for(scope = ctx->call_ctx->scope; scope; scope = scope->next) {
646 if(scope->frame) {
647 function_code_t *func = scope->frame->function;
648 local_ref_t *ref = lookup_local(func, identifier);
649 static const WCHAR argumentsW[] = {'a','r','g','u','m','e','n','t','s',0};
650
651 if(ref) {
652 ret->type = EXPRVAL_STACK_REF;
653 ret->u.off = local_off(scope->frame, ref->ref);
654 TRACE("returning ref %d for %d\n", ret->u.off, ref->ref);
655 return S_OK;
656 }
657
658 if(!wcscmp(identifier, argumentsW)) {
660 if(FAILED(hres))
661 return hres;
662 }
663 }
664 if(scope->jsobj)
665 hres = jsdisp_get_id(scope->jsobj, identifier, fdexNameImplicit, &id);
666 else
667 hres = disp_get_id(ctx, scope->obj, identifier, identifier, fdexNameImplicit, &id);
668 if(SUCCEEDED(hres)) {
669 exprval_set_disp_ref(ret, scope->obj, id);
670 return S_OK;
671 }
672 }
673 }
674
675 hres = jsdisp_get_id(ctx->global, identifier, 0, &id);
676 if(SUCCEEDED(hres)) {
677 exprval_set_disp_ref(ret, to_disp(ctx->global), id);
678 return S_OK;
679 }
680
681 for(item = ctx->named_items; item; item = item->next) {
682 if((item->flags & SCRIPTITEM_ISVISIBLE) && !wcscmp(item->name, identifier)) {
683 if(!item->disp) {
684 IUnknown *unk;
685
686 if(!ctx->site)
687 break;
688
689 hres = IActiveScriptSite_GetItemInfo(ctx->site, identifier,
690 SCRIPTINFO_IUNKNOWN, &unk, NULL);
691 if(FAILED(hres)) {
692 WARN("GetItemInfo failed: %08x\n", hres);
693 break;
694 }
695
696 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
697 IUnknown_Release(unk);
698 if(FAILED(hres)) {
699 WARN("object does not implement IDispatch\n");
700 break;
701 }
702 }
703
704 IDispatch_AddRef(item->disp);
705 ret->type = EXPRVAL_JSVAL;
706 ret->u.val = jsval_disp(item->disp);
707 return S_OK;
708 }
709 }
710
711 if(lookup_global_members(ctx, identifier, ret))
712 return S_OK;
713
715 return S_OK;
716}
717
718static inline BSTR get_op_bstr(script_ctx_t *ctx, int i)
719{
720 call_frame_t *frame = ctx->call_ctx;
721 return frame->bytecode->instrs[frame->ip].u.arg[i].bstr;
722}
723
724static inline unsigned get_op_uint(script_ctx_t *ctx, int i)
725{
726 call_frame_t *frame = ctx->call_ctx;
727 return frame->bytecode->instrs[frame->ip].u.arg[i].uint;
728}
729
730static inline unsigned get_op_int(script_ctx_t *ctx, int i)
731{
732 call_frame_t *frame = ctx->call_ctx;
733 return frame->bytecode->instrs[frame->ip].u.arg[i].lng;
734}
735
736static inline jsstr_t *get_op_str(script_ctx_t *ctx, int i)
737{
738 call_frame_t *frame = ctx->call_ctx;
739 return frame->bytecode->instrs[frame->ip].u.arg[i].str;
740}
741
742static inline double get_op_double(script_ctx_t *ctx)
743{
744 call_frame_t *frame = ctx->call_ctx;
745 return frame->bytecode->instrs[frame->ip].u.dbl;
746}
747
748static inline void jmp_next(script_ctx_t *ctx)
749{
750 ctx->call_ctx->ip++;
751}
752
753static inline void jmp_abs(script_ctx_t *ctx, unsigned dst)
754{
755 ctx->call_ctx->ip = dst;
756}
757
758/* ECMA-262 3rd Edition 12.6.4 */
760{
761 const HRESULT arg = get_op_uint(ctx, 0);
762 IDispatch *obj = NULL;
763 IDispatchEx *dispex;
764 exprval_t prop_ref;
765 DISPID id;
766 BSTR name = NULL;
768
769 TRACE("\n");
770
772 id = get_number(stack_top(ctx));
773
774 if(!stack_topn_exprval(ctx, 1, &prop_ref)) {
775 FIXME("invalid ref: %08x\n", prop_ref.u.hres);
776 return E_FAIL;
777 }
778
781
782 if(obj) {
783 hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
784 if(SUCCEEDED(hres)) {
785 hres = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, id, &id);
786 if(hres == S_OK)
787 hres = IDispatchEx_GetMemberName(dispex, id, &name);
788 IDispatchEx_Release(dispex);
789 if(FAILED(hres))
790 return hres;
791 }else {
792 TRACE("No IDispatchEx\n");
793 }
794 }
795
796 if(name) {
797 jsstr_t *str;
798
801 if(!str)
802 return E_OUTOFMEMORY;
803
804 stack_pop(ctx);
805 stack_push(ctx, jsval_number(id)); /* safe, just after pop() */
806
807 hres = exprval_propput(ctx, &prop_ref, jsval_string(str));
809 if(FAILED(hres))
810 return hres;
811
812 jmp_next(ctx);
813 }else {
814 stack_popn(ctx, 4);
815 jmp_abs(ctx, arg);
816 }
817 return S_OK;
818}
819
820/* ECMA-262 3rd Edition 12.10 */
822{
823 IDispatch *disp;
824 jsval_t v;
826
827 TRACE("\n");
828
829 v = stack_pop(ctx);
830 hres = to_object(ctx, v, &disp);
832 if(FAILED(hres))
833 return hres;
834
835 hres = scope_push(ctx->call_ctx->scope, to_jsdisp(disp), disp, &ctx->call_ctx->scope);
836 IDispatch_Release(disp);
837 return hres;
838}
839
840/* ECMA-262 3rd Edition 12.10 */
842{
843 TRACE("\n");
844
845 scope_pop(&ctx->call_ctx->scope);
846 return S_OK;
847}
848
849/* ECMA-262 3rd Edition 12.13 */
851{
852 const unsigned arg = get_op_uint(ctx, 0);
853 jsval_t v;
854 BOOL b;
856
857 TRACE("\n");
858
859 v = stack_pop(ctx);
862 if(FAILED(hres))
863 return hres;
864
865 if(b) {
866 stack_popn(ctx, 1);
867 jmp_abs(ctx, arg);
868 }else {
869 jmp_next(ctx);
870 }
871 return S_OK;
872}
873
874/* ECMA-262 3rd Edition 12.13 */
876{
877 TRACE("\n");
878
879 jsval_release(ctx->ei.val);
880 ctx->ei.val = stack_pop(ctx);
881 return DISP_E_EXCEPTION;
882}
883
885{
886 const HRESULT arg = get_op_uint(ctx, 0);
887
888 TRACE("%08x\n", arg);
889
891}
892
894{
895 const HRESULT hres = get_op_uint(ctx, 0);
896 jsstr_t *str = get_op_str(ctx, 1);
897 const WCHAR *ptr;
898
899 TRACE("%08x %s\n", hres, debugstr_jsstr(str));
900
903}
904
905/* ECMA-262 3rd Edition 12.14 */
907{
908 const unsigned catch_off = get_op_uint(ctx, 0);
909 const unsigned finally_off = get_op_uint(ctx, 1);
910 call_frame_t *frame = ctx->call_ctx;
912
913 TRACE("\n");
914
915 except = heap_alloc(sizeof(*except));
916 if(!except)
917 return E_OUTOFMEMORY;
918
919 except->stack_top = ctx->stack_top;
920 except->scope = frame->scope;
921 except->catch_off = catch_off;
922 except->finally_off = finally_off;
923 except->next = frame->except_frame;
924 frame->except_frame = except;
925 return S_OK;
926}
927
928/* ECMA-262 3rd Edition 12.14 */
930{
931 const unsigned ret_off = get_op_uint(ctx, 0);
932 call_frame_t *frame = ctx->call_ctx;
934 unsigned finally_off;
935
936 TRACE("%u\n", ret_off);
937
938 except = frame->except_frame;
939 assert(except != NULL);
940
941 finally_off = except->finally_off;
942 frame->except_frame = except->next;
944
945 if(finally_off) {
947
948 hres = stack_push(ctx, jsval_number(ret_off));
949 if(FAILED(hres))
950 return hres;
952 if(FAILED(hres))
953 return hres;
954 frame->ip = finally_off;
955 }else {
956 frame->ip = ret_off;
957 }
958
959 return S_OK;
960}
961
962/* ECMA-262 3rd Edition 12.14 */
964{
965 call_frame_t *frame = ctx->call_ctx;
966 jsval_t v;
967
968 TRACE("\n");
969
970 v = stack_pop(ctx);
971 assert(is_bool(v));
972
973 if(!get_bool(v)) {
974 TRACE("passing exception\n");
975
976 ctx->ei.val = stack_pop(ctx);
977 return DISP_E_EXCEPTION;
978 }
979
980 v = stack_pop(ctx);
982 frame->ip = get_number(v);
983 return S_OK;
984}
985
987{
988 const BSTR ident = get_op_bstr(ctx, 0);
989 jsdisp_t *scope_obj;
990 jsval_t v;
992
993 hres = create_dispex(ctx, NULL, NULL, &scope_obj);
994 if(FAILED(hres))
995 return hres;
996
997 v = stack_pop(ctx);
998 hres = jsdisp_propput_name(scope_obj, ident, v);
1000 if(SUCCEEDED(hres))
1001 hres = scope_push(ctx->call_ctx->scope, scope_obj, to_disp(scope_obj), &ctx->call_ctx->scope);
1002 jsdisp_release(scope_obj);
1003 return hres;
1004}
1005
1006/* ECMA-262 3rd Edition 13 */
1008{
1009 unsigned func_idx = get_op_uint(ctx, 0);
1010 call_frame_t *frame = ctx->call_ctx;
1011 jsdisp_t *dispex;
1012 HRESULT hres;
1013
1014 TRACE("%d\n", func_idx);
1015
1016 hres = create_source_function(ctx, frame->bytecode, frame->function->funcs+func_idx,
1017 frame->scope, &dispex);
1018 if(FAILED(hres))
1019 return hres;
1020
1021 return stack_push(ctx, jsval_obj(dispex));
1022}
1023
1024/* ECMA-262 3rd Edition 11.2.1 */
1026{
1027 jsstr_t *name_str;
1028 const WCHAR *name;
1029 jsval_t v, namev;
1030 IDispatch *obj;
1031 DISPID id;
1032 HRESULT hres;
1033
1034 TRACE("\n");
1035
1036 namev = stack_pop(ctx);
1037
1039 if(FAILED(hres)) {
1040 jsval_release(namev);
1041 return hres;
1042 }
1043
1044 hres = to_flat_string(ctx, namev, &name_str, &name);
1045 jsval_release(namev);
1046 if(FAILED(hres)) {
1047 IDispatch_Release(obj);
1048 return hres;
1049 }
1050
1051 hres = disp_get_id(ctx, obj, name, NULL, 0, &id);
1052 jsstr_release(name_str);
1053 if(SUCCEEDED(hres)) {
1054 hres = disp_propget(ctx, obj, id, &v);
1055 }else if(hres == DISP_E_UNKNOWNNAME) {
1056 v = jsval_undefined();
1057 hres = S_OK;
1058 }
1059 IDispatch_Release(obj);
1060 if(FAILED(hres))
1061 return hres;
1062
1063 return stack_push(ctx, v);
1064}
1065
1066/* ECMA-262 3rd Edition 11.2.1 */
1068{
1069 const BSTR arg = get_op_bstr(ctx, 0);
1070 IDispatch *obj;
1071 jsval_t v;
1072 DISPID id;
1073 HRESULT hres;
1074
1075 TRACE("\n");
1076
1078 if(FAILED(hres))
1079 return hres;
1080
1081 hres = disp_get_id(ctx, obj, arg, arg, 0, &id);
1082 if(SUCCEEDED(hres)) {
1083 hres = disp_propget(ctx, obj, id, &v);
1084 }else if(hres == DISP_E_UNKNOWNNAME) {
1085 v = jsval_undefined();
1086 hres = S_OK;
1087 }
1088 IDispatch_Release(obj);
1089 if(FAILED(hres))
1090 return hres;
1091
1092 return stack_push(ctx, v);
1093}
1094
1095/* ECMA-262 3rd Edition 11.2.1 */
1097{
1098 const unsigned arg = get_op_uint(ctx, 0);
1099 jsval_t objv, namev;
1100 const WCHAR *name;
1101 jsstr_t *name_str;
1102 IDispatch *obj;
1103 exprval_t ref;
1104 DISPID id;
1105 HRESULT hres;
1106
1107 TRACE("%x\n", arg);
1108
1109 namev = stack_pop(ctx);
1110 objv = stack_pop(ctx);
1111
1112 hres = to_object(ctx, objv, &obj);
1113 jsval_release(objv);
1114 if(SUCCEEDED(hres)) {
1115 hres = to_flat_string(ctx, namev, &name_str, &name);
1116 if(FAILED(hres))
1117 IDispatch_Release(obj);
1118 }
1119 jsval_release(namev);
1120 if(FAILED(hres))
1121 return hres;
1122
1123 hres = disp_get_id(ctx, obj, name, NULL, arg, &id);
1124 jsstr_release(name_str);
1125 if(SUCCEEDED(hres)) {
1126 ref.type = EXPRVAL_IDREF;
1127 ref.u.idref.disp = obj;
1128 ref.u.idref.id = id;
1129 }else {
1130 IDispatch_Release(obj);
1131 if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
1133 hres = S_OK;
1134 }else {
1135 ERR("failed %08x\n", hres);
1136 return hres;
1137 }
1138 }
1139
1140 return stack_push_exprval(ctx, &ref);
1141}
1142
1143/* ECMA-262 3rd Edition 11.2.1 */
1145{
1146 exprval_t ref;
1147 jsval_t v;
1148 HRESULT hres;
1149
1150 TRACE("\n");
1151
1152 if(!stack_topn_exprval(ctx, 0, &ref))
1154
1155 hres = exprval_propget(ctx, &ref, &v);
1156 if(FAILED(hres))
1157 return hres;
1158
1159 return stack_push(ctx, v);
1160}
1161
1162/* ECMA-262 3rd Edition 11.2.2 */
1164{
1165 const unsigned argc = get_op_uint(ctx, 0);
1166 jsval_t constr;
1167
1168 TRACE("%d\n", argc);
1169
1170 constr = stack_topn(ctx, argc);
1171
1172 /* NOTE: Should use to_object here */
1173
1174 if(is_null(constr))
1176 else if(!is_object_instance(constr))
1178 else if(!get_object(constr))
1180
1181 clear_acc(ctx);
1182 return disp_call_value(ctx, get_object(constr), NULL, DISPATCH_CONSTRUCT | DISPATCH_JSCRIPT_CALLEREXECSSOURCE,
1183 argc, stack_args(ctx, argc), &ctx->acc);
1184}
1185
1186/* ECMA-262 3rd Edition 11.2.3 */
1188{
1189 const unsigned argn = get_op_uint(ctx, 0);
1190 const int do_ret = get_op_int(ctx, 1);
1191 jsval_t obj;
1192
1193 TRACE("%d %d\n", argn, do_ret);
1194
1195 obj = stack_topn(ctx, argn);
1198
1199 clear_acc(ctx);
1201 argn, stack_args(ctx, argn), do_ret ? &ctx->acc : NULL);
1202}
1203
1204/* ECMA-262 3rd Edition 11.2.3 */
1206{
1207 const unsigned argn = get_op_uint(ctx, 0);
1208 const int do_ret = get_op_int(ctx, 1);
1209 exprval_t ref;
1210
1211 TRACE("%d %d\n", argn, do_ret);
1212
1213 if(!stack_topn_exprval(ctx, argn, &ref))
1214 return throw_type_error(ctx, ref.u.hres, NULL);
1215
1216 clear_acc(ctx);
1218 argn, stack_args(ctx, argn), do_ret ? &ctx->acc : NULL);
1219}
1220
1221/* ECMA-262 3rd Edition 11.1.1 */
1223{
1224 call_frame_t *frame = ctx->call_ctx;
1225
1226 TRACE("\n");
1227
1228 IDispatch_AddRef(frame->this_obj);
1229 return stack_push(ctx, jsval_disp(frame->this_obj));
1230}
1231
1233{
1234 exprval_t exprval;
1235 HRESULT hres;
1236
1237 hres = identifier_eval(ctx, identifier, &exprval);
1238 if(FAILED(hres))
1239 return hres;
1240
1241 if(exprval.type == EXPRVAL_INVALID && (flags & fdexNameEnsure)) {
1242 DISPID id;
1243
1244 hres = jsdisp_get_id(ctx->global, identifier, fdexNameEnsure, &id);
1245 if(FAILED(hres))
1246 return hres;
1247
1248 exprval_set_disp_ref(&exprval, to_disp(ctx->global), id);
1249 }
1250
1251 if(exprval.type == EXPRVAL_JSVAL || exprval.type == EXPRVAL_INVALID) {
1252 WARN("invalid ref\n");
1253 exprval_release(&exprval);
1255 }
1256
1257 return stack_push_exprval(ctx, &exprval);
1258}
1259
1261{
1262 exprval_t exprval;
1263 jsval_t v;
1264 HRESULT hres;
1265
1266 hres = identifier_eval(ctx, identifier, &exprval);
1267 if(FAILED(hres))
1268 return hres;
1269
1270 if(exprval.type == EXPRVAL_INVALID)
1271 return throw_type_error(ctx, exprval.u.hres, identifier);
1272
1273 hres = exprval_to_value(ctx, &exprval, &v);
1274 if(FAILED(hres))
1275 return hres;
1276
1277 return stack_push(ctx, v);
1278}
1279
1281{
1282 const int arg = get_op_int(ctx, 0);
1283 const unsigned flags = get_op_uint(ctx, 1);
1284 call_frame_t *frame = ctx->call_ctx;
1285 exprval_t ref;
1286
1287 TRACE("%d\n", arg);
1288
1289 if(!frame->base_scope || !frame->base_scope->frame)
1290 return interp_identifier_ref(ctx, local_name(frame, arg), flags);
1291
1292 ref.type = EXPRVAL_STACK_REF;
1293 ref.u.off = local_off(frame, arg);
1294 return stack_push_exprval(ctx, &ref);
1295}
1296
1298{
1299 const int arg = get_op_int(ctx, 0);
1300 call_frame_t *frame = ctx->call_ctx;
1301 jsval_t copy;
1302 HRESULT hres;
1303
1304 TRACE("%d: %s\n", arg, debugstr_w(local_name(frame, arg)));
1305
1306 if(!frame->base_scope || !frame->base_scope->frame)
1307 return identifier_value(ctx, local_name(frame, arg));
1308
1309 hres = jsval_copy(ctx->stack[local_off(frame, arg)], &copy);
1310 if(FAILED(hres))
1311 return hres;
1312
1313 return stack_push(ctx, copy);
1314}
1315
1316/* ECMA-262 3rd Edition 10.1.4 */
1318{
1319 const BSTR arg = get_op_bstr(ctx, 0);
1320
1321 TRACE("%s\n", debugstr_w(arg));
1322
1323 return identifier_value(ctx, arg);
1324}
1325
1326/* ECMA-262 3rd Edition 10.1.4 */
1328{
1329 const BSTR arg = get_op_bstr(ctx, 0);
1330 const unsigned flags = get_op_uint(ctx, 1);
1331
1332 TRACE("%s %x\n", debugstr_w(arg), flags);
1333
1335}
1336
1337/* ECMA-262 3rd Edition 7.8.1 */
1339{
1340 TRACE("\n");
1341
1342 return stack_push(ctx, jsval_null());
1343}
1344
1345/* ECMA-262 3rd Edition 7.8.2 */
1347{
1348 const int arg = get_op_int(ctx, 0);
1349
1350 TRACE("%s\n", arg ? "true" : "false");
1351
1352 return stack_push(ctx, jsval_bool(arg));
1353}
1354
1355/* ECMA-262 3rd Edition 7.8.3 */
1357{
1358 const int arg = get_op_int(ctx, 0);
1359
1360 TRACE("%d\n", arg);
1361
1362 return stack_push(ctx, jsval_number(arg));
1363}
1364
1365/* ECMA-262 3rd Edition 7.8.3 */
1367{
1368 const double arg = get_op_double(ctx);
1369
1370 TRACE("%lf\n", arg);
1371
1372 return stack_push(ctx, jsval_number(arg));
1373}
1374
1375/* ECMA-262 3rd Edition 7.8.4 */
1377{
1378 jsstr_t *str = get_op_str(ctx, 0);
1379
1380 TRACE("%s\n", debugstr_jsstr(str));
1381
1383}
1384
1385/* ECMA-262 3rd Edition 7.8 */
1387{
1389 const unsigned flags = get_op_uint(ctx, 1);
1390 jsdisp_t *regexp;
1391 HRESULT hres;
1392
1393 TRACE("%s %x\n", debugstr_jsstr(source), flags);
1394
1395 hres = create_regexp(ctx, source, flags, &regexp);
1396 if(FAILED(hres))
1397 return hres;
1398
1399 return stack_push(ctx, jsval_obj(regexp));
1400}
1401
1402/* ECMA-262 3rd Edition 11.1.4 */
1404{
1405 const unsigned arg = get_op_uint(ctx, 0);
1406 jsdisp_t *array;
1407 HRESULT hres;
1408
1409 TRACE("%u\n", arg);
1410
1412 if(FAILED(hres))
1413 return hres;
1414
1415 return stack_push(ctx, jsval_obj(array));
1416}
1417
1419{
1420 const unsigned index = get_op_uint(ctx, 0);
1422 HRESULT hres;
1423
1424 value = stack_pop(ctx);
1425
1426 TRACE("[%u] = %s\n", index, debugstr_jsval(value));
1427
1428 array = stack_top(ctx);
1430
1433 return hres;
1434}
1435
1436/* ECMA-262 3rd Edition 11.1.5 */
1438{
1439 jsdisp_t *obj;
1440 HRESULT hres;
1441
1442 TRACE("\n");
1443
1445 if(FAILED(hres))
1446 return hres;
1447
1448 return stack_push(ctx, jsval_obj(obj));
1449}
1450
1451/* ECMA-262 3rd Edition 11.1.5 */
1453{
1454 jsstr_t *name_arg = get_op_str(ctx, 0);
1455 unsigned type = get_op_uint(ctx, 1);
1456 const WCHAR *name;
1457 jsdisp_t *obj;
1458 jsval_t val;
1459 HRESULT hres;
1460
1461 TRACE("%s\n", debugstr_jsstr(name_arg));
1462
1463 val = stack_pop(ctx);
1464
1465 /* FIXME: we should pass it as jsstr_t */
1466 name = jsstr_flatten(name_arg);
1467
1470
1473 }else {
1475 jsdisp_t *func;
1476
1479
1480 desc.mask = desc.flags;
1482 desc.explicit_getter = TRUE;
1483 desc.getter = func;
1484 }else {
1485 desc.explicit_setter = TRUE;
1486 desc.setter = func;
1487 }
1488
1491 }
1492
1494 return hres;
1495}
1496
1497/* ECMA-262 3rd Edition 11.11 */
1499{
1500 const unsigned arg = get_op_uint(ctx, 0);
1501 BOOL b;
1502 HRESULT hres;
1503
1504 TRACE("\n");
1505
1507 if(FAILED(hres))
1508 return hres;
1509
1510 if(b) {
1511 jmp_abs(ctx, arg);
1512 }else {
1513 stack_popn(ctx, 1);
1514 jmp_next(ctx);
1515 }
1516 return S_OK;
1517}
1518
1519/* ECMA-262 3rd Edition 11.11 */
1521{
1522 const unsigned arg = get_op_uint(ctx, 0);
1523 BOOL b;
1524 HRESULT hres;
1525
1526 TRACE("\n");
1527
1529 if(FAILED(hres))
1530 return hres;
1531
1532 if(b) {
1533 stack_popn(ctx, 1);
1534 jmp_next(ctx);
1535 }else {
1536 jmp_abs(ctx, arg);
1537 }
1538 return S_OK;
1539}
1540
1541/* ECMA-262 3rd Edition 11.10 */
1543{
1544 INT l, r;
1545 HRESULT hres;
1546
1547 TRACE("\n");
1548
1549 hres = stack_pop_int(ctx, &r);
1550 if(FAILED(hres))
1551 return hres;
1552
1553 hres = stack_pop_int(ctx, &l);
1554 if(FAILED(hres))
1555 return hres;
1556
1557 return stack_push(ctx, jsval_number(l|r));
1558}
1559
1560/* ECMA-262 3rd Edition 11.10 */
1562{
1563 INT l, r;
1564 HRESULT hres;
1565
1566 TRACE("\n");
1567
1568 hres = stack_pop_int(ctx, &r);
1569 if(FAILED(hres))
1570 return hres;
1571
1572 hres = stack_pop_int(ctx, &l);
1573 if(FAILED(hres))
1574 return hres;
1575
1576 return stack_push(ctx, jsval_number(l^r));
1577}
1578
1579/* ECMA-262 3rd Edition 11.10 */
1581{
1582 INT l, r;
1583 HRESULT hres;
1584
1585 TRACE("\n");
1586
1587 hres = stack_pop_int(ctx, &r);
1588 if(FAILED(hres))
1589 return hres;
1590
1591 hres = stack_pop_int(ctx, &l);
1592 if(FAILED(hres))
1593 return hres;
1594
1595 return stack_push(ctx, jsval_number(l&r));
1596}
1597
1598/* ECMA-262 3rd Edition 11.8.6 */
1600{
1601 jsdisp_t *obj, *iter, *tmp = NULL;
1602 jsval_t prot, v;
1603 BOOL ret = FALSE;
1604 HRESULT hres;
1605
1606 static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
1607
1608 v = stack_pop(ctx);
1609 if(!is_object_instance(v) || !get_object(v)) {
1612 }
1613
1615 IDispatch_Release(get_object(v));
1616 if(!obj) {
1617 FIXME("non-jsdisp objects not supported\n");
1618 return E_FAIL;
1619 }
1620
1623 }else {
1625 }
1627 if(FAILED(hres))
1628 return hres;
1629
1630 v = stack_pop(ctx);
1631
1632 if(is_object_instance(prot)) {
1635 for(iter = tmp; !ret && iter; iter = iter->prototype) {
1636 hres = disp_cmp(get_object(prot), to_disp(iter), &ret);
1637 if(FAILED(hres))
1638 break;
1639 }
1640
1641 if(tmp)
1642 jsdisp_release(tmp);
1643 }else {
1644 FIXME("prototype is not an object\n");
1645 hres = E_FAIL;
1646 }
1647
1648 jsval_release(prot);
1650 if(FAILED(hres))
1651 return hres;
1652
1653 return stack_push(ctx, jsval_bool(ret));
1654}
1655
1656/* ECMA-262 3rd Edition 11.8.7 */
1658{
1659 const WCHAR *str;
1660 jsstr_t *jsstr;
1661 jsval_t obj, v;
1662 DISPID id = 0;
1663 BOOL ret;
1664 HRESULT hres;
1665
1666 TRACE("\n");
1667
1668 obj = stack_pop(ctx);
1672 }
1673
1674 v = stack_pop(ctx);
1675 hres = to_flat_string(ctx, v, &jsstr, &str);
1677 if(FAILED(hres)) {
1678 IDispatch_Release(get_object(obj));
1679 return hres;
1680 }
1681
1682 hres = disp_get_id(ctx, get_object(obj), str, NULL, 0, &id);
1683 IDispatch_Release(get_object(obj));
1684 jsstr_release(jsstr);
1685 if(SUCCEEDED(hres))
1686 ret = TRUE;
1687 else if(hres == DISP_E_UNKNOWNNAME)
1688 ret = FALSE;
1689 else
1690 return hres;
1691
1692 return stack_push(ctx, jsval_bool(ret));
1693}
1694
1695/* ECMA-262 3rd Edition 11.6.1 */
1697{
1698 jsval_t r, l;
1699 HRESULT hres;
1700
1701 hres = to_primitive(ctx, lval, &l, NO_HINT);
1702 if(FAILED(hres))
1703 return hres;
1704
1706 if(FAILED(hres)) {
1708 return hres;
1709 }
1710
1711 if(is_string(l) || is_string(r)) {
1712 jsstr_t *lstr, *rstr = NULL;
1713
1714 hres = to_string(ctx, l, &lstr);
1715 if(SUCCEEDED(hres))
1716 hres = to_string(ctx, r, &rstr);
1717
1718 if(SUCCEEDED(hres)) {
1719 jsstr_t *ret_str;
1720
1721 ret_str = jsstr_concat(lstr, rstr);
1722 if(ret_str)
1723 *ret = jsval_string(ret_str);
1724 else
1726 }
1727
1728 jsstr_release(lstr);
1729 if(rstr)
1731 }else {
1732 double nl, nr;
1733
1734 hres = to_number(ctx, l, &nl);
1735 if(SUCCEEDED(hres)) {
1736 hres = to_number(ctx, r, &nr);
1737 if(SUCCEEDED(hres))
1738 *ret = jsval_number(nl+nr);
1739 }
1740 }
1741
1744 return hres;
1745}
1746
1747/* ECMA-262 3rd Edition 11.6.1 */
1749{
1750 jsval_t l, r, ret;
1751 HRESULT hres;
1752
1753 r = stack_pop(ctx);
1754 l = stack_pop(ctx);
1755
1756 TRACE("%s + %s\n", debugstr_jsval(l), debugstr_jsval(r));
1757
1758 hres = add_eval(ctx, l, r, &ret);
1761 if(FAILED(hres))
1762 return hres;
1763
1764 return stack_push(ctx, ret);
1765}
1766
1767/* ECMA-262 3rd Edition 11.6.2 */
1769{
1770 double l, r;
1771 HRESULT hres;
1772
1773 TRACE("\n");
1774
1776 if(FAILED(hres))
1777 return hres;
1778
1780 if(FAILED(hres))
1781 return hres;
1782
1783 return stack_push(ctx, jsval_number(l-r));
1784}
1785
1786/* ECMA-262 3rd Edition 11.5.1 */
1788{
1789 double l, r;
1790 HRESULT hres;
1791
1792 TRACE("\n");
1793
1795 if(FAILED(hres))
1796 return hres;
1797
1799 if(FAILED(hres))
1800 return hres;
1801
1802 return stack_push(ctx, jsval_number(l*r));
1803}
1804
1805/* ECMA-262 3rd Edition 11.5.2 */
1807{
1808 double l, r;
1809 HRESULT hres;
1810
1811 TRACE("\n");
1812
1814 if(FAILED(hres))
1815 return hres;
1816
1818 if(FAILED(hres))
1819 return hres;
1820
1821 return stack_push(ctx, jsval_number(l/r));
1822}
1823
1824/* ECMA-262 3rd Edition 11.5.3 */
1826{
1827 double l, r;
1828 HRESULT hres;
1829
1830 TRACE("\n");
1831
1833 if(FAILED(hres))
1834 return hres;
1835
1837 if(FAILED(hres))
1838 return hres;
1839
1840 return stack_push(ctx, jsval_number(fmod(l, r)));
1841}
1842
1843/* ECMA-262 3rd Edition 11.4.2 */
1845{
1846 jsval_t objv, namev;
1847 IDispatch *obj;
1848 jsstr_t *name;
1849 BOOL ret;
1850 HRESULT hres;
1851
1852 TRACE("\n");
1853
1854 namev = stack_pop(ctx);
1855 objv = stack_pop(ctx);
1856
1857 hres = to_object(ctx, objv, &obj);
1858 jsval_release(objv);
1859 if(FAILED(hres)) {
1860 jsval_release(namev);
1861 return hres;
1862 }
1863
1864 hres = to_string(ctx, namev, &name);
1865 jsval_release(namev);
1866 if(FAILED(hres)) {
1867 IDispatch_Release(obj);
1868 return hres;
1869 }
1870
1872 IDispatch_Release(obj);
1874 if(FAILED(hres))
1875 return hres;
1876
1877 return stack_push(ctx, jsval_bool(ret));
1878}
1879
1880/* ECMA-262 3rd Edition 11.4.2 */
1882{
1883 const BSTR arg = get_op_bstr(ctx, 0);
1884 exprval_t exprval;
1885 BOOL ret;
1886 HRESULT hres;
1887
1888 TRACE("%s\n", debugstr_w(arg));
1889
1890 hres = identifier_eval(ctx, arg, &exprval);
1891 if(FAILED(hres))
1892 return hres;
1893
1894 switch(exprval.type) {
1895 case EXPRVAL_STACK_REF:
1896 ret = FALSE;
1897 break;
1898 case EXPRVAL_IDREF:
1899 hres = disp_delete(exprval.u.idref.disp, exprval.u.idref.id, &ret);
1900 IDispatch_Release(exprval.u.idref.disp);
1901 if(FAILED(hres))
1902 return hres;
1903 break;
1904 case EXPRVAL_INVALID:
1905 ret = TRUE;
1906 break;
1907 default:
1908 FIXME("Unsupported exprval\n");
1909 exprval_release(&exprval);
1910 return E_NOTIMPL;
1911 }
1912
1913
1914 return stack_push(ctx, jsval_bool(ret));
1915}
1916
1917/* ECMA-262 3rd Edition 11.4.2 */
1919{
1920 TRACE("\n");
1921
1922 stack_popn(ctx, 1);
1923 return stack_push(ctx, jsval_undefined());
1924}
1925
1926/* ECMA-262 3rd Edition 11.4.3 */
1928{
1929 switch(jsval_type(v)) {
1930 case JSV_UNDEFINED:
1931 *ret = undefinedW;
1932 break;
1933 case JSV_NULL:
1934 *ret = objectW;
1935 break;
1936 case JSV_OBJECT: {
1937 jsdisp_t *dispex;
1938
1939 if(get_object(v) && (dispex = iface_to_jsdisp(get_object(v)))) {
1941 jsdisp_release(dispex);
1942 }else {
1943 *ret = objectW;
1944 }
1945 break;
1946 }
1947 case JSV_STRING:
1948 *ret = stringW;
1949 break;
1950 case JSV_NUMBER:
1951 *ret = numberW;
1952 break;
1953 case JSV_BOOL:
1954 *ret = booleanW;
1955 break;
1956 case JSV_VARIANT:
1957 FIXME("unhandled variant %s\n", debugstr_variant(get_variant(v)));
1958 return E_NOTIMPL;
1959 }
1960
1961 return S_OK;
1962}
1963
1964/* ECMA-262 3rd Edition 11.4.3 */
1966{
1967 const WCHAR *ret;
1968 exprval_t ref;
1969 jsval_t v;
1970 HRESULT hres;
1971
1972 TRACE("\n");
1973
1974 if(!stack_pop_exprval(ctx, &ref))
1976
1977 hres = exprval_propget(ctx, &ref, &v);
1979 if(FAILED(hres))
1981
1982 hres = typeof_string(v, &ret);
1984 if(FAILED(hres))
1985 return hres;
1986
1987 return stack_push_string(ctx, ret);
1988}
1989
1990/* ECMA-262 3rd Edition 11.4.3 */
1992{
1993 const BSTR arg = get_op_bstr(ctx, 0);
1994 exprval_t exprval;
1995 const WCHAR *ret;
1996 jsval_t v;
1997 HRESULT hres;
1998
1999 TRACE("%s\n", debugstr_w(arg));
2000
2001 hres = identifier_eval(ctx, arg, &exprval);
2002 if(FAILED(hres))
2003 return hres;
2004
2005 if(exprval.type == EXPRVAL_INVALID)
2007
2008 hres = exprval_to_value(ctx, &exprval, &v);
2009 if(FAILED(hres))
2010 return hres;
2011
2012 hres = typeof_string(v, &ret);
2014 if(FAILED(hres))
2015 return hres;
2016
2017 return stack_push_string(ctx, ret);
2018}
2019
2020/* ECMA-262 3rd Edition 11.4.3 */
2022{
2023 const WCHAR *ret;
2024 jsval_t v;
2025 HRESULT hres;
2026
2027 TRACE("\n");
2028
2029 v = stack_pop(ctx);
2030 hres = typeof_string(v, &ret);
2032 if(FAILED(hres))
2033 return hres;
2034
2035 return stack_push_string(ctx, ret);
2036}
2037
2038/* ECMA-262 3rd Edition 11.4.7 */
2040{
2041 double n;
2042 HRESULT hres;
2043
2044 TRACE("\n");
2045
2047 if(FAILED(hres))
2048 return hres;
2049
2050 return stack_push(ctx, jsval_number(-n));
2051}
2052
2053/* ECMA-262 3rd Edition 11.4.6 */
2055{
2056 jsval_t v;
2057 double n;
2058 HRESULT hres;
2059
2060 TRACE("\n");
2061
2062 v = stack_pop(ctx);
2063 hres = to_number(ctx, v, &n);
2065 if(FAILED(hres))
2066 return hres;
2067
2068 return stack_push(ctx, jsval_number(n));
2069}
2070
2071/* ECMA-262 3rd Edition 11.3.1 */
2073{
2074 const int arg = get_op_int(ctx, 0);
2075 exprval_t ref;
2076 jsval_t v;
2077 HRESULT hres;
2078
2079 TRACE("%d\n", arg);
2080
2081 if(!stack_pop_exprval(ctx, &ref))
2083
2084 hres = exprval_propget(ctx, &ref, &v);
2085 if(SUCCEEDED(hres)) {
2086 double n;
2087
2088 hres = to_number(ctx, v, &n);
2089 if(SUCCEEDED(hres))
2090 hres = exprval_propput(ctx, &ref, jsval_number(n+(double)arg));
2091 if(FAILED(hres))
2093 }
2095 if(FAILED(hres))
2096 return hres;
2097
2098 return stack_push(ctx, v);
2099}
2100
2101/* ECMA-262 3rd Edition 11.4.4, 11.4.5 */
2103{
2104 const int arg = get_op_int(ctx, 0);
2105 exprval_t ref;
2106 double ret;
2107 jsval_t v;
2108 HRESULT hres;
2109
2110 TRACE("%d\n", arg);
2111
2112 if(!stack_pop_exprval(ctx, &ref))
2114
2115 hres = exprval_propget(ctx, &ref, &v);
2116 if(SUCCEEDED(hres)) {
2117 double n;
2118
2119 hres = to_number(ctx, v, &n);
2121 if(SUCCEEDED(hres)) {
2122 ret = n+(double)arg;
2124 }
2125 }
2127 if(FAILED(hres))
2128 return hres;
2129
2130 return stack_push(ctx, jsval_number(ret));
2131}
2132
2133/* ECMA-262 3rd Edition 11.9.3 */
2135{
2136 if(jsval_type(lval) == jsval_type(rval) || (is_number(lval) && is_number(rval)))
2137 return jsval_strict_equal(lval, rval, ret);
2138
2139 /* FIXME: NULL disps should be handled in more general way */
2140 if(is_object_instance(lval) && !get_object(lval))
2141 return equal_values(ctx, jsval_null(), rval, ret);
2143 return equal_values(ctx, lval, jsval_null(), ret);
2144
2145 if((is_null(lval) && is_undefined(rval)) || (is_undefined(lval) && is_null(rval))) {
2146 *ret = TRUE;
2147 return S_OK;
2148 }
2149
2150 if(is_string(lval) && is_number(rval)) {
2151 double n;
2152 HRESULT hres;
2153
2154 hres = to_number(ctx, lval, &n);
2155 if(FAILED(hres))
2156 return hres;
2157
2158 /* FIXME: optimize */
2159 return equal_values(ctx, jsval_number(n), rval, ret);
2160 }
2161
2162 if(is_string(rval) && is_number(lval)) {
2163 double n;
2164 HRESULT hres;
2165
2166 hres = to_number(ctx, rval, &n);
2167 if(FAILED(hres))
2168 return hres;
2169
2170 /* FIXME: optimize */
2171 return equal_values(ctx, lval, jsval_number(n), ret);
2172 }
2173
2174 if(is_bool(rval))
2175 return equal_values(ctx, lval, jsval_number(get_bool(rval) ? 1 : 0), ret);
2176
2177 if(is_bool(lval))
2178 return equal_values(ctx, jsval_number(get_bool(lval) ? 1 : 0), rval, ret);
2179
2180
2181 if(is_object_instance(rval) && (is_string(lval) || is_number(lval))) {
2182 jsval_t prim;
2183 HRESULT hres;
2184
2186 if(FAILED(hres))
2187 return hres;
2188
2189 hres = equal_values(ctx, lval, prim, ret);
2191 return hres;
2192 }
2193
2194
2195 if(is_object_instance(lval) && (is_string(rval) || is_number(rval))) {
2196 jsval_t prim;
2197 HRESULT hres;
2198
2199 hres = to_primitive(ctx, lval, &prim, NO_HINT);
2200 if(FAILED(hres))
2201 return hres;
2202
2205 return hres;
2206 }
2207
2208
2209 *ret = FALSE;
2210 return S_OK;
2211}
2212
2213/* ECMA-262 3rd Edition 11.9.1 */
2215{
2216 jsval_t l, r;
2217 BOOL b;
2218 HRESULT hres;
2219
2220 r = stack_pop(ctx);
2221 l = stack_pop(ctx);
2222
2223 TRACE("%s == %s\n", debugstr_jsval(l), debugstr_jsval(r));
2224
2225 hres = equal_values(ctx, l, r, &b);
2228 if(FAILED(hres))
2229 return hres;
2230
2231 return stack_push(ctx, jsval_bool(b));
2232}
2233
2234/* ECMA-262 3rd Edition 11.9.2 */
2236{
2237 jsval_t l, r;
2238 BOOL b;
2239 HRESULT hres;
2240
2241 r = stack_pop(ctx);
2242 l = stack_pop(ctx);
2243
2244 TRACE("%s != %s\n", debugstr_jsval(l), debugstr_jsval(r));
2245
2246 hres = equal_values(ctx, l, r, &b);
2249 if(FAILED(hres))
2250 return hres;
2251
2252 return stack_push(ctx, jsval_bool(!b));
2253}
2254
2255/* ECMA-262 3rd Edition 11.9.4 */
2257{
2258 jsval_t l, r;
2259 BOOL b;
2260 HRESULT hres;
2261
2262 r = stack_pop(ctx);
2263 l = stack_pop(ctx);
2264
2265 TRACE("%s === %s\n", debugstr_jsval(l), debugstr_jsval(r));
2266
2267 hres = jsval_strict_equal(r, l, &b);
2270 if(FAILED(hres))
2271 return hres;
2272
2273 return stack_push(ctx, jsval_bool(b));
2274}
2275
2276/* ECMA-262 3rd Edition 11.9.5 */
2278{
2279 jsval_t l, r;
2280 BOOL b;
2281 HRESULT hres;
2282
2283 TRACE("\n");
2284
2285 r = stack_pop(ctx);
2286 l = stack_pop(ctx);
2287
2288 hres = jsval_strict_equal(r, l, &b);
2291 if(FAILED(hres))
2292 return hres;
2293
2294 return stack_push(ctx, jsval_bool(!b));
2295}
2296
2297/* ECMA-262 3rd Edition 11.8.5 */
2299{
2300 double ln, rn;
2301 jsval_t l, r;
2302 HRESULT hres;
2303
2304 hres = to_primitive(ctx, lval, &l, NO_HINT);
2305 if(FAILED(hres))
2306 return hres;
2307
2309 if(FAILED(hres)) {
2311 return hres;
2312 }
2313
2314 if(is_string(l) && is_string(r)) {
2315 *ret = (jsstr_cmp(get_string(l), get_string(r)) < 0) ^ greater;
2318 return S_OK;
2319 }
2320
2321 hres = to_number(ctx, l, &ln);
2323 if(SUCCEEDED(hres))
2324 hres = to_number(ctx, r, &rn);
2326 if(FAILED(hres))
2327 return hres;
2328
2329 *ret = !isnan(ln) && !isnan(rn) && ((ln < rn) ^ greater);
2330 return S_OK;
2331}
2332
2333/* ECMA-262 3rd Edition 11.8.1 */
2335{
2336 jsval_t l, r;
2337 BOOL b;
2338 HRESULT hres;
2339
2340 r = stack_pop(ctx);
2341 l = stack_pop(ctx);
2342
2343 TRACE("%s < %s\n", debugstr_jsval(l), debugstr_jsval(r));
2344
2345 hres = less_eval(ctx, l, r, FALSE, &b);
2348 if(FAILED(hres))
2349 return hres;
2350
2351 return stack_push(ctx, jsval_bool(b));
2352}
2353
2354/* ECMA-262 3rd Edition 11.8.1 */
2356{
2357 jsval_t l, r;
2358 BOOL b;
2359 HRESULT hres;
2360
2361 r = stack_pop(ctx);
2362 l = stack_pop(ctx);
2363
2364 TRACE("%s <= %s\n", debugstr_jsval(l), debugstr_jsval(r));
2365
2366 hres = less_eval(ctx, r, l, TRUE, &b);
2369 if(FAILED(hres))
2370 return hres;
2371
2372 return stack_push(ctx, jsval_bool(b));
2373}
2374
2375/* ECMA-262 3rd Edition 11.8.2 */
2377{
2378 jsval_t l, r;
2379 BOOL b;
2380 HRESULT hres;
2381
2382 r = stack_pop(ctx);
2383 l = stack_pop(ctx);
2384
2385 TRACE("%s > %s\n", debugstr_jsval(l), debugstr_jsval(r));
2386
2387 hres = less_eval(ctx, r, l, FALSE, &b);
2390 if(FAILED(hres))
2391 return hres;
2392
2393 return stack_push(ctx, jsval_bool(b));
2394}
2395
2396/* ECMA-262 3rd Edition 11.8.4 */
2398{
2399 jsval_t l, r;
2400 BOOL b;
2401 HRESULT hres;
2402
2403 r = stack_pop(ctx);
2404 l = stack_pop(ctx);
2405
2406 TRACE("%s >= %s\n", debugstr_jsval(l), debugstr_jsval(r));
2407
2408 hres = less_eval(ctx, l, r, TRUE, &b);
2411 if(FAILED(hres))
2412 return hres;
2413
2414 return stack_push(ctx, jsval_bool(b));
2415}
2416
2417/* ECMA-262 3rd Edition 11.4.8 */
2419{
2420 jsval_t v;
2421 INT i;
2422 HRESULT hres;
2423
2424 TRACE("\n");
2425
2426 v = stack_pop(ctx);
2427 hres = to_int32(ctx, v, &i);
2429 if(FAILED(hres))
2430 return hres;
2431
2432 return stack_push(ctx, jsval_number(~i));
2433}
2434
2435/* ECMA-262 3rd Edition 11.4.9 */
2437{
2438 jsval_t v;
2439 BOOL b;
2440 HRESULT hres;
2441
2442 TRACE("\n");
2443
2444 v = stack_pop(ctx);
2445 hres = to_boolean(v, &b);
2447 if(FAILED(hres))
2448 return hres;
2449
2450 return stack_push(ctx, jsval_bool(!b));
2451}
2452
2453/* ECMA-262 3rd Edition 11.7.1 */
2455{
2456 DWORD r;
2457 INT l;
2458 HRESULT hres;
2459
2460 hres = stack_pop_uint(ctx, &r);
2461 if(FAILED(hres))
2462 return hres;
2463
2464 hres = stack_pop_int(ctx, &l);
2465 if(FAILED(hres))
2466 return hres;
2467
2468 return stack_push(ctx, jsval_number(l << (r&0x1f)));
2469}
2470
2471/* ECMA-262 3rd Edition 11.7.2 */
2473{
2474 DWORD r;
2475 INT l;
2476 HRESULT hres;
2477
2478 hres = stack_pop_uint(ctx, &r);
2479 if(FAILED(hres))
2480 return hres;
2481
2482 hres = stack_pop_int(ctx, &l);
2483 if(FAILED(hres))
2484 return hres;
2485
2486 return stack_push(ctx, jsval_number(l >> (r&0x1f)));
2487}
2488
2489/* ECMA-262 3rd Edition 11.7.3 */
2491{
2492 DWORD r, l;
2493 HRESULT hres;
2494
2495 hres = stack_pop_uint(ctx, &r);
2496 if(FAILED(hres))
2497 return hres;
2498
2499 hres = stack_pop_uint(ctx, &l);
2500 if(FAILED(hres))
2501 return hres;
2502
2503 return stack_push(ctx, jsval_number(l >> (r&0x1f)));
2504}
2505
2506/* ECMA-262 3rd Edition 11.13.1 */
2508{
2509 exprval_t ref;
2510 jsval_t v;
2511 HRESULT hres;
2512
2513 TRACE("\n");
2514
2515 v = stack_pop(ctx);
2516
2517 if(!stack_pop_exprval(ctx, &ref)) {
2520 }
2521
2524 if(FAILED(hres)) {
2526 return hres;
2527 }
2528
2529 return stack_push(ctx, v);
2530}
2531
2532/* JScript extension */
2534{
2535 const unsigned argc = get_op_uint(ctx, 0);
2536 exprval_t ref;
2537 jsval_t v;
2538 HRESULT hres;
2539
2540 TRACE("%u\n", argc);
2541
2542 if(!stack_topn_exprval(ctx, argc+1, &ref))
2544
2546 if(FAILED(hres))
2547 return hres;
2548
2549 v = stack_pop(ctx);
2550 stack_popn(ctx, argc+2);
2551 return stack_push(ctx, v);
2552}
2553
2555{
2556 TRACE("\n");
2557
2558 return stack_push(ctx, jsval_undefined());
2559}
2560
2562{
2563 const unsigned arg = get_op_uint(ctx, 0);
2564
2565 TRACE("%u\n", arg);
2566
2567 jmp_abs(ctx, arg);
2568 return S_OK;
2569}
2570
2572{
2573 const unsigned arg = get_op_uint(ctx, 0);
2574 BOOL b;
2575 jsval_t v;
2576 HRESULT hres;
2577
2578 TRACE("\n");
2579
2580 v = stack_pop(ctx);
2581 hres = to_boolean(v, &b);
2583 if(FAILED(hres))
2584 return hres;
2585
2586 if(b)
2587 jmp_next(ctx);
2588 else
2589 jmp_abs(ctx, arg);
2590 return S_OK;
2591}
2592
2594{
2595 const unsigned arg = get_op_uint(ctx, 0);
2596
2597 TRACE("%u\n", arg);
2598
2599 stack_popn(ctx, arg);
2600 return S_OK;
2601}
2602
2604{
2605 const unsigned clear_ret = get_op_uint(ctx, 0);
2606 call_frame_t *frame = ctx->call_ctx;
2607
2608 TRACE("\n");
2609
2610 if(clear_ret)
2611 jsval_release(steal_ret(frame));
2612
2613 if((frame->flags & EXEC_CONSTRUCTOR) && !is_object_instance(frame->ret)) {
2614 jsval_release(frame->ret);
2615 IDispatch_AddRef(frame->this_obj);
2616 frame->ret = jsval_disp(frame->this_obj);
2617 }
2618
2619 jmp_abs(ctx, -1);
2620 return S_OK;
2621}
2622
2624{
2625 call_frame_t *frame = ctx->call_ctx;
2626
2627 TRACE("\n");
2628
2629 jsval_release(frame->ret);
2630 frame->ret = stack_pop(ctx);
2631 return S_OK;
2632}
2633
2635{
2636 HRESULT hres;
2637
2638 TRACE("\n");
2639
2640 hres = stack_push(ctx, ctx->acc);
2641 if(SUCCEEDED(hres))
2642 ctx->acc = jsval_undefined();
2643 return hres;
2644}
2645
2647
2648static const op_func_t op_funcs[] = {
2649#define X(x,a,b,c) interp_##x,
2650OP_LIST
2651#undef X
2652};
2653
2654static const unsigned op_move[] = {
2655#define X(a,x,b,c) x,
2656OP_LIST
2657#undef X
2658};
2659
2661{
2662 call_frame_t *frame = ctx->call_ctx;
2663
2664 frame->stack_base -= frame->pop_locals + frame->pop_variables;
2665
2666 assert(frame->scope == frame->base_scope);
2667
2668 /* If current scope will be kept alive, we need to transfer local variables to its variable object. */
2669 if(frame->scope && frame->scope->ref > 1) {
2671 if(FAILED(hres))
2672 ERR("Failed to detach variable object: %08x\n", hres);
2673 }
2674
2675 if(frame->arguments_obj)
2677 if(frame->scope)
2678 scope_release(frame->scope);
2679
2680 if(frame->pop_variables)
2681 stack_popn(ctx, frame->pop_variables);
2682 stack_popn(ctx, frame->pop_locals);
2683
2684 ctx->call_ctx = frame->prev_frame;
2685
2686 if(frame->function_instance)
2688 if(frame->variable_obj)
2690 if(frame->this_obj)
2691 IDispatch_Release(frame->this_obj);
2692 jsval_release(frame->ret);
2693 release_bytecode(frame->bytecode);
2694 heap_free(frame);
2695}
2696
2698{
2699 unsigned depth = 0, i;
2700 call_frame_t *frame;
2701
2702 for(frame = ctx->call_ctx; frame; frame = frame->prev_frame) {
2703 WARN("%u\t", depth);
2704 depth++;
2705
2706 if(frame->this_obj && frame->this_obj != to_disp(ctx->global) && frame->this_obj != ctx->host_global)
2707 WARN("%p->", frame->this_obj);
2708 WARN("%s(", frame->function->name ? debugstr_w(frame->function->name) : "[unnamed]");
2709 if(frame->base_scope && frame->base_scope->frame) {
2710 for(i=0; i < frame->argc; i++) {
2711 if(i < frame->function->param_cnt)
2712 WARN("%s%s=%s", i ? ", " : "", debugstr_w(frame->function->params[i]),
2713 debugstr_jsval(ctx->stack[local_off(frame, -i-1)]));
2714 else
2715 WARN("%s%s", i ? ", " : "", debugstr_jsval(ctx->stack[local_off(frame, -i-1)]));
2716 }
2717 }else {
2718 WARN("[detached frame]");
2719 }
2720 WARN(")\n");
2721
2722 if(!(frame->flags & EXEC_RETURN_TO_INTERP)) {
2723 WARN("%u\t[native code]\n", depth);
2724 depth++;
2725 }
2726 }
2727}
2728
2730{
2731 except_frame_t *except_frame;
2732 call_frame_t *frame;
2733 jsval_t except_val;
2734 unsigned catch_off;
2735 HRESULT hres;
2736
2737 if(WARN_ON(jscript)) {
2738 jsdisp_t *error_obj;
2739 jsval_t msg;
2740
2741 static const WCHAR messageW[] = {'m','e','s','s','a','g','e',0};
2742
2743 WARN("Exception %08x %s", exception_hres, debugstr_jsval(ctx->ei.val));
2744 if(jsval_type(ctx->ei.val) == JSV_OBJECT) {
2745 error_obj = to_jsdisp(get_object(ctx->ei.val));
2746 if(error_obj) {
2747 hres = jsdisp_propget_name(error_obj, messageW, &msg);
2748 if(SUCCEEDED(hres)) {
2749 WARN(" (message %s)", debugstr_jsval(msg));
2751 }
2752 }
2753 }
2754 WARN(" in:\n");
2755
2757 }
2758
2759 for(frame = ctx->call_ctx; !frame->except_frame; frame = ctx->call_ctx) {
2760 DWORD flags;
2761
2762 while(frame->scope != frame->base_scope)
2763 scope_pop(&frame->scope);
2764
2765 stack_popn(ctx, ctx->stack_top-frame->stack_base);
2766
2767 flags = frame->flags;
2770 return exception_hres;
2771 }
2772
2773 except_frame = frame->except_frame;
2774 catch_off = except_frame->catch_off;
2775
2776 assert(except_frame->stack_top <= ctx->stack_top);
2777 stack_popn(ctx, ctx->stack_top - except_frame->stack_top);
2778
2779 while(except_frame->scope != frame->scope)
2780 scope_pop(&frame->scope);
2781
2782 frame->ip = catch_off ? catch_off : except_frame->finally_off;
2783 if(catch_off) assert(frame->bytecode->instrs[frame->ip].op == OP_enter_catch);
2784
2785 except_val = ctx->ei.val;
2786 ctx->ei.val = jsval_undefined();
2787 clear_ei(ctx);
2788
2789 /* keep current except_frame if we're entering catch block with finally block associated */
2790 if(catch_off && except_frame->finally_off) {
2791 except_frame->catch_off = 0;
2792 }else {
2793 frame->except_frame = except_frame->next;
2794 heap_free(except_frame);
2795 }
2796
2797 hres = stack_push(ctx, except_val);
2798 if(FAILED(hres))
2799 return hres;
2800
2801 if(!catch_off)
2803 return hres;
2804}
2805
2807{
2808 call_frame_t *frame;
2809 jsop_t op;
2810 HRESULT hres = S_OK;
2811
2812 TRACE("\n");
2813
2814 while(1) {
2815 frame = ctx->call_ctx;
2816 op = frame->bytecode->instrs[frame->ip].op;
2817 hres = op_funcs[op](ctx);
2818 if(FAILED(hres)) {
2820 if(FAILED(hres))
2821 return hres;
2822 }else if(frame->ip == -1) {
2823 const DWORD return_to_interp = frame->flags & EXEC_RETURN_TO_INTERP;
2824
2825 assert(ctx->stack_top == frame->stack_base);
2826 assert(frame->scope == frame->base_scope);
2827
2828 if(return_to_interp) {
2829 jsval_release(ctx->acc);
2830 ctx->acc = steal_ret(frame);
2831 }else if(r) {
2832 *r = steal_ret(frame);
2833 }
2835 if(!return_to_interp)
2836 break;
2837 }else {
2838 frame->ip += op_move[op];
2839 }
2840 }
2841
2842 return S_OK;
2843}
2844
2846{
2848 exprval_t exprval;
2849 IDispatch *disp;
2850 jsval_t v;
2851 HRESULT hres;
2852
2853 hres = identifier_eval(ctx, func->event_target, &exprval);
2854 if(FAILED(hres))
2855 return hres;
2856
2857 hres = exprval_to_value(ctx, &exprval, &v);
2858 if(FAILED(hres))
2859 return hres;
2860
2861 if(!is_object_instance(v)) {
2862 FIXME("Can't bind to %s\n", debugstr_jsval(v));
2864 }
2865
2866 disp = get_object(v);
2867 hres = IDispatch_QueryInterface(disp, &IID_IBindEventHandler, (void**)&target);
2868 if(SUCCEEDED(hres)) {
2869 hres = IBindEventHandler_BindHandler(target, func->name, (IDispatch*)&func_obj->IDispatchEx_iface);
2870 IBindEventHandler_Release(target);
2871 if(FAILED(hres))
2872 WARN("BindEvent failed: %08x\n", hres);
2873 }else {
2874 FIXME("No IBindEventHandler, not yet supported binding\n");
2875 }
2876
2877 IDispatch_Release(disp);
2878 return hres;
2879}
2880
2881static HRESULT setup_scope(script_ctx_t *ctx, call_frame_t *frame, scope_chain_t *scope_chain, jsdisp_t *variable_object, unsigned argc, jsval_t *argv)
2882{
2883 const unsigned orig_stack = ctx->stack_top;
2884 scope_chain_t *scope;
2885 unsigned i;
2886 jsval_t v;
2887 HRESULT hres;
2888
2889 /* If arguments are already on the stack, we may use them. */
2890 if(argv + argc == ctx->stack + ctx->stack_top) {
2891 frame->arguments_off = argv - ctx->stack;
2892 i = argc;
2893 }else {
2894 frame->arguments_off = ctx->stack_top;
2895 for(i = 0; i < argc; i++) {
2896 hres = jsval_copy(argv[i], &v);
2897 if(SUCCEEDED(hres))
2898 hres = stack_push(ctx, v);
2899 if(FAILED(hres)) {
2900 stack_popn(ctx, i);
2901 return hres;
2902 }
2903 }
2904 }
2905
2906 /* If fewer than declared arguments were passed, fill remaining with undefined value. */
2907 for(; i < frame->function->param_cnt; i++) {
2909 if(FAILED(hres)) {
2910 stack_popn(ctx, ctx->stack_top - orig_stack);
2911 return hres;
2912 }
2913 }
2914
2915 frame->pop_locals = ctx->stack_top - orig_stack;
2916
2917 frame->variables_off = ctx->stack_top;
2918
2919 for(i = 0; i < frame->function->var_cnt; i++) {
2921 if(FAILED(hres)) {
2922 stack_popn(ctx, ctx->stack_top - orig_stack);
2923 return hres;
2924 }
2925 }
2926
2927 frame->pop_variables = i;
2928
2929 hres = scope_push(scope_chain, variable_object, to_disp(variable_object), &scope);
2930 if(FAILED(hres)) {
2931 stack_popn(ctx, ctx->stack_top - orig_stack);
2932 return hres;
2933 }
2934
2935 for(i = 0; i < frame->function->func_cnt; i++) {
2936 if(frame->function->funcs[i].name && !frame->function->funcs[i].event_target) {
2937 jsdisp_t *func_obj;
2938 unsigned off;
2939
2940 hres = create_source_function(ctx, frame->bytecode, frame->function->funcs+i, scope, &func_obj);
2941 if(FAILED(hres)) {
2942 stack_popn(ctx, ctx->stack_top - orig_stack);
2943 scope_release(scope);
2944 return hres;
2945 }
2946
2947 off = local_off(frame, frame->function->funcs[i].local_ref);
2948 jsval_release(ctx->stack[off]);
2949 ctx->stack[off] = jsval_obj(func_obj);
2950 }
2951 }
2952
2953 scope->frame = frame;
2954 frame->base_scope = frame->scope = scope;
2955 return S_OK;
2956}
2957
2959 IDispatch *this_obj, jsdisp_t *function_instance, jsdisp_t *variable_obj, unsigned argc, jsval_t *argv, jsval_t *r)
2960{
2961 call_frame_t *frame;
2962 unsigned i;
2963 HRESULT hres;
2964
2965 for(i = 0; i < function->func_cnt; i++) {
2966 jsdisp_t *func_obj;
2967
2968 if(!function->funcs[i].event_target)
2969 continue;
2970
2971 hres = create_source_function(ctx, bytecode, function->funcs+i, scope, &func_obj);
2972 if(FAILED(hres))
2973 return hres;
2974
2975 hres = bind_event_target(ctx, function->funcs+i, func_obj);
2976 jsdisp_release(func_obj);
2977 if(FAILED(hres))
2978 return hres;
2979 }
2980
2981 if(flags & (EXEC_GLOBAL | EXEC_EVAL)) {
2982 for(i=0; i < function->var_cnt; i++) {
2983 TRACE("[%d] %s %d\n", i, debugstr_w(function->variables[i].name), function->variables[i].func_id);
2984 if(function->variables[i].func_id != -1) {
2985 jsdisp_t *func_obj;
2986
2987 hres = create_source_function(ctx, bytecode, function->funcs+function->variables[i].func_id, scope, &func_obj);
2988 if(FAILED(hres))
2989 return hres;
2990
2991 hres = jsdisp_propput_name(variable_obj, function->variables[i].name, jsval_obj(func_obj));
2992 jsdisp_release(func_obj);
2993 }else if(!(flags & EXEC_GLOBAL) || !lookup_global_members(ctx, function->variables[i].name, NULL)) {
2994 DISPID id = 0;
2995
2996 hres = jsdisp_get_id(variable_obj, function->variables[i].name, fdexNameEnsure, &id);
2997 if(FAILED(hres))
2998 return hres;
2999 }
3000 }
3001 }
3002
3003 /* ECMA-262 3rd Edition 11.2.3.7 */
3004 if(this_obj) {
3005 jsdisp_t *jsthis;
3006
3007 jsthis = iface_to_jsdisp(this_obj);
3008 if(jsthis) {
3009 if(jsthis->builtin_info->class == JSCLASS_GLOBAL || jsthis->builtin_info->class == JSCLASS_NONE)
3010 this_obj = NULL;
3011 jsdisp_release(jsthis);
3012 }
3013 }
3014
3015 if(ctx->call_ctx && (flags & EXEC_EVAL)) {
3016 hres = detach_variable_object(ctx, ctx->call_ctx, FALSE);
3017 if(FAILED(hres))
3018 return hres;
3019 }
3020
3021 frame = heap_alloc_zero(sizeof(*frame));
3022 if(!frame)
3023 return E_OUTOFMEMORY;
3024
3025 frame->function = function;
3026 frame->ret = jsval_undefined();
3027 frame->argc = argc;
3028 frame->bytecode = bytecode_addref(bytecode);
3029
3030 if(!(flags & (EXEC_GLOBAL|EXEC_EVAL))) {
3031 hres = setup_scope(ctx, frame, scope, variable_obj, argc, argv);
3032 if(FAILED(hres)) {
3033 release_bytecode(frame->bytecode);
3034 heap_free(frame);
3035 return hres;
3036 }
3037 }else if(scope) {
3038 frame->base_scope = frame->scope = scope_addref(scope);
3039 }
3040
3041 frame->ip = function->instr_off;
3042 frame->stack_base = ctx->stack_top;
3043 if(this_obj)
3044 frame->this_obj = this_obj;
3045 else if(ctx->host_global)
3046 frame->this_obj = ctx->host_global;
3047 else
3048 frame->this_obj = to_disp(ctx->global);
3049 IDispatch_AddRef(frame->this_obj);
3050
3051 if(function_instance)
3052 frame->function_instance = jsdisp_addref(function_instance);
3053
3054 frame->flags = flags;
3055 frame->variable_obj = jsdisp_addref(variable_obj);
3056
3057 frame->prev_frame = ctx->call_ctx;
3058 ctx->call_ctx = frame;
3059
3061 /*
3062 * We're called directly from interpreter, so we may just setup call frame and return.
3063 * Already running interpreter will take care of execution.
3064 */
3065 if(r)
3066 *r = jsval_undefined();
3067 return S_OK;
3068 }
3069
3070 return enter_bytecode(ctx, r);
3071}
static int argc
Definition: ServiceArgs.c:12
#define __cdecl
Definition: accygwin.h:79
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
static void * heap_realloc(void *mem, size_t len)
Definition: appwiz.h:71
HRESULT create_array(script_ctx_t *ctx, DWORD length, jsdisp_t **ret)
Definition: array.c:1381
#define msg(x)
Definition: auth_time.c:54
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:114
#define WARN(fmt,...)
Definition: debug.h:115
#define ERR(fmt,...)
Definition: debug.h:113
#define except(x)
Definition: btrfs_drv.h:136
r l[0]
Definition: byte_order.h:168
float rval
Definition: cylfrac.c:48
static BOOL get_bool(D3DXPARAMETER_TYPE type, const void *data)
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT op
Definition: effect.c:236
void(* interp_func)(GLcontext *, GLuint, GLuint, GLfloat, GLuint, GLuint)
Definition: types.h:253
OLECHAR * BSTR
Definition: compat.h:2293
static const WCHAR messageW[]
Definition: error.c:33
HRESULT throw_type_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str)
Definition: error.c:440
HRESULT throw_reference_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str)
Definition: error.c:425
static const WCHAR prototypeW[]
Definition: function.c:94
static const WCHAR argumentsW[]
Definition: function.c:101
#define assert(x)
Definition: debug.h:53
static HRESULT interp_identid(script_ctx_t *ctx)
Definition: engine.c:1327
static HRESULT interp_push_except(script_ctx_t *ctx)
Definition: engine.c:906
static void pop_call_frame(script_ctx_t *ctx)
Definition: engine.c:2660
static HRESULT interp_undefined(script_ctx_t *ctx)
Definition: engine.c:2554
static jsval_t stack_topn(script_ctx_t *ctx, unsigned n)
Definition: engine.c:116
static HRESULT exprval_propget(script_ctx_t *ctx, exprval_t *ref, jsval_t *r)
Definition: engine.c:302
static HRESULT interp_assign(script_ctx_t *ctx)
Definition: engine.c:2507
static HRESULT interp_case(script_ctx_t *ctx)
Definition: engine.c:850
static void print_backtrace(script_ctx_t *ctx)
Definition: engine.c:2697
static HRESULT stack_pop_int(script_ctx_t *ctx, INT *r)
Definition: engine.c:170
static HRESULT interp_setret(script_ctx_t *ctx)
Definition: engine.c:2623
static HRESULT stack_push(script_ctx_t *ctx, jsval_t v)
Definition: engine.c:69
static HRESULT interp_carray_set(script_ctx_t *ctx)
Definition: engine.c:1418
static HRESULT interp_local(script_ctx_t *ctx)
Definition: engine.c:1297
static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, const WCHAR *name, BSTR name_bstr, DWORD flags, DISPID *id)
Definition: engine.c:449
static HRESULT interp_eq2(script_ctx_t *ctx)
Definition: engine.c:2256
static HRESULT interp_add(script_ctx_t *ctx)
Definition: engine.c:1748
static HRESULT exprval_call(script_ctx_t *ctx, exprval_t *ref, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
Definition: engine.c:315
static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres)
Definition: engine.c:2729
static unsigned get_op_int(script_ctx_t *ctx, int i)
Definition: engine.c:730
static HRESULT stack_pop_object(script_ctx_t *ctx, IDispatch **r)
Definition: engine.c:152
static HRESULT detach_variable_object(script_ctx_t *ctx, call_frame_t *frame, BOOL from_release)
Definition: engine.c:573
static HRESULT bind_event_target(script_ctx_t *ctx, function_code_t *func, jsdisp_t *func_obj)
Definition: engine.c:2845
void clear_ei(script_ctx_t *ctx)
Definition: engine.c:430
static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
Definition: engine.c:604
static HRESULT setup_scope(script_ctx_t *ctx, call_frame_t *frame, scope_chain_t *scope_chain, jsdisp_t *variable_object, unsigned argc, jsval_t *argv)
Definition: engine.c:2881
static HRESULT interp_forin(script_ctx_t *ctx)
Definition: engine.c:759
static HRESULT interp_lshift(script_ctx_t *ctx)
Definition: engine.c:2454
static HRESULT interp_array(script_ctx_t *ctx)
Definition: engine.c:1025
static HRESULT interp_member(script_ctx_t *ctx)
Definition: engine.c:1067
static HRESULT interp_eq(script_ctx_t *ctx)
Definition: engine.c:2214
static HRESULT stack_pop_uint(script_ctx_t *ctx, DWORD *r)
Definition: engine.c:175
static HRESULT interp_typeof(script_ctx_t *ctx)
Definition: engine.c:2021
static HRESULT interp_memberid(script_ctx_t *ctx)
Definition: engine.c:1096
static HRESULT interp_minus(script_ctx_t *ctx)
Definition: engine.c:2039
static HRESULT identifier_value(script_ctx_t *ctx, BSTR identifier)
Definition: engine.c:1260
static HRESULT interp_regexp(script_ctx_t *ctx)
Definition: engine.c:1386
static HRESULT interp_identifier_ref(script_ctx_t *ctx, BSTR identifier, unsigned flags)
Definition: engine.c:1232
static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
Definition: engine.c:635
static HRESULT interp_neq(script_ctx_t *ctx)
Definition: engine.c:2235
static jsval_t stack_pop(script_ctx_t *ctx)
Definition: engine.c:129
static const unsigned op_move[]
Definition: engine.c:2654
static HRESULT interp_end_finally(script_ctx_t *ctx)
Definition: engine.c:963
static void exprval_set_disp_ref(exprval_t *ref, IDispatch *obj, DISPID id)
Definition: engine.c:376
static HRESULT interp_delete(script_ctx_t *ctx)
Definition: engine.c:1844
static HRESULT interp_new(script_ctx_t *ctx)
Definition: engine.c:1163
static HRESULT interp_gteq(script_ctx_t *ctx)
Definition: engine.c:2397
static HRESULT interp_tonum(script_ctx_t *ctx)
Definition: engine.c:2054
void scope_release(scope_chain_t *scope)
Definition: engine.c:437
static HRESULT stack_push_exprval(script_ctx_t *ctx, exprval_t *val)
Definition: engine.c:193
static HRESULT interp_in(script_ctx_t *ctx)
Definition: engine.c:1657
static HRESULT interp_typeofident(script_ctx_t *ctx)
Definition: engine.c:1991
static HRESULT interp_and(script_ctx_t *ctx)
Definition: engine.c:1580
static HRESULT interp_pop(script_ctx_t *ctx)
Definition: engine.c:2593
static jsval_t * stack_top_ref(script_ctx_t *ctx, unsigned n)
Definition: engine.c:110
static HRESULT interp_jmp(script_ctx_t *ctx)
Definition: engine.c:2561
static HRESULT interp_push_acc(script_ctx_t *ctx)
Definition: engine.c:2634
static HRESULT interp_mod(script_ctx_t *ctx)
Definition: engine.c:1825
static HRESULT interp_bool(script_ctx_t *ctx)
Definition: engine.c:1346
static HRESULT scope_push(scope_chain_t *scope, jsdisp_t *jsobj, IDispatch *obj, scope_chain_t **ret)
Definition: engine.c:401
static HRESULT interp_rshift(script_ctx_t *ctx)
Definition: engine.c:2472
static HRESULT interp_lteq(script_ctx_t *ctx)
Definition: engine.c:2355
static HRESULT interp_call(script_ctx_t *ctx)
Definition: engine.c:1187
static const op_func_t op_funcs[]
Definition: engine.c:2648
static HRESULT interp_refval(script_ctx_t *ctx)
Definition: engine.c:1144
static HRESULT interp_xor(script_ctx_t *ctx)
Definition: engine.c:1561
static HRESULT interp_call_member(script_ctx_t *ctx)
Definition: engine.c:1205
static HRESULT interp_pop_scope(script_ctx_t *ctx)
Definition: engine.c:841
static jsval_t * stack_args(script_ctx_t *ctx, unsigned n)
Definition: engine.c:121
HRESULT(* op_func_t)(script_ctx_t *)
Definition: engine.c:2646
static HRESULT interp_jmp_z(script_ctx_t *ctx)
Definition: engine.c:2571
static HRESULT interp_pop_except(script_ctx_t *ctx)
Definition: engine.c:929
static HRESULT interp_local_ref(script_ctx_t *ctx)
Definition: engine.c:1280
static HRESULT interp_bneg(script_ctx_t *ctx)
Definition: engine.c:2418
static HRESULT interp_this(script_ctx_t *ctx)
Definition: engine.c:1222
static BSTR get_op_bstr(script_ctx_t *ctx, int i)
Definition: engine.c:718
static HRESULT interp_throw(script_ctx_t *ctx)
Definition: engine.c:875
static void exprval_set_exception(exprval_t *val, HRESULT hres)
Definition: engine.c:370
static HRESULT interp_postinc(script_ctx_t *ctx)
Definition: engine.c:2072
static HRESULT interp_void(script_ctx_t *ctx)
Definition: engine.c:1918
static void jmp_abs(script_ctx_t *ctx, unsigned dst)
Definition: engine.c:753
static jsstr_t * get_op_str(script_ctx_t *ctx, int i)
Definition: engine.c:736
static HRESULT interp_gt(script_ctx_t *ctx)
Definition: engine.c:2376
static const WCHAR booleanW[]
Definition: engine.c:34
static void scope_pop(scope_chain_t **scope)
Definition: engine.c:421
local_ref_t * lookup_local(const function_code_t *function, const WCHAR *identifier)
Definition: engine.c:629
static void jmp_next(script_ctx_t *ctx)
Definition: engine.c:748
static HRESULT interp_ret(script_ctx_t *ctx)
Definition: engine.c:2603
static HRESULT exprval_propput(script_ctx_t *ctx, exprval_t *ref, jsval_t v)
Definition: engine.c:286
static HRESULT interp_throw_type(script_ctx_t *ctx)
Definition: engine.c:893
static HRESULT interp_neq2(script_ctx_t *ctx)
Definition: engine.c:2277
static void clear_acc(script_ctx_t *ctx)
Definition: engine.c:395
static HRESULT interp_cnd_nz(script_ctx_t *ctx)
Definition: engine.c:1498
static double get_op_double(script_ctx_t *ctx)
Definition: engine.c:742
static HRESULT interp_sub(script_ctx_t *ctx)
Definition: engine.c:1768
static HRESULT interp_new_obj(script_ctx_t *ctx)
Definition: engine.c:1437
static jsval_t steal_ret(call_frame_t *frame)
Definition: engine.c:388
static HRESULT interp_throw_ref(script_ctx_t *ctx)
Definition: engine.c:884
static HRESULT interp_rshift2(script_ctx_t *ctx)
Definition: engine.c:2490
static HRESULT interp_or(script_ctx_t *ctx)
Definition: engine.c:1542
static HRESULT interp_instanceof(script_ctx_t *ctx)
Definition: engine.c:1599
static HRESULT interp_cnd_z(script_ctx_t *ctx)
Definition: engine.c:1520
static HRESULT interp_delete_ident(script_ctx_t *ctx)
Definition: engine.c:1881
static HRESULT interp_neg(script_ctx_t *ctx)
Definition: engine.c:2436
static const WCHAR undefinedW[]
Definition: engine.c:39
static unsigned get_op_uint(script_ctx_t *ctx, int i)
Definition: engine.c:724
static jsval_t stack_top(script_ctx_t *ctx)
Definition: engine.c:104
static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *ref, jsval_t *r)
Definition: engine.c:338
static void exprval_release(exprval_t *val)
Definition: engine.c:354
static unsigned local_off(call_frame_t *frame, int ref)
Definition: engine.c:180
static const WCHAR stringW[]
Definition: engine.c:38
static HRESULT interp_carray(script_ctx_t *ctx)
Definition: engine.c:1403
static HRESULT interp_double(script_ctx_t *ctx)
Definition: engine.c:1366
static HRESULT equal_values(script_ctx_t *ctx, jsval_t lval, jsval_t rval, BOOL *ret)
Definition: engine.c:2134
static HRESULT interp_str(script_ctx_t *ctx)
Definition: engine.c:1376
static HRESULT enter_bytecode(script_ctx_t *ctx, jsval_t *r)
Definition: engine.c:2806
static const WCHAR unknownW[]
Definition: engine.c:40
static BOOL stack_pop_exprval(script_ctx_t *ctx, exprval_t *r)
Definition: engine.c:279
static const WCHAR objectW[]
Definition: engine.c:37
static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret)
Definition: engine.c:486
static void stack_popn(script_ctx_t *ctx, unsigned n)
Definition: engine.c:135
static HRESULT typeof_string(jsval_t v, const WCHAR **ret)
Definition: engine.c:1927
static HRESULT interp_ident(script_ctx_t *ctx)
Definition: engine.c:1317
static HRESULT interp_enter_catch(script_ctx_t *ctx)
Definition: engine.c:986
static HRESULT interp_null(script_ctx_t *ctx)
Definition: engine.c:1338
static HRESULT interp_int(script_ctx_t *ctx)
Definition: engine.c:1356
static HRESULT add_eval(script_ctx_t *ctx, jsval_t lval, jsval_t rval, jsval_t *ret)
Definition: engine.c:1696
static HRESULT stack_push_string(script_ctx_t *ctx, const WCHAR *str)
Definition: engine.c:93
static HRESULT less_eval(script_ctx_t *ctx, jsval_t lval, jsval_t rval, BOOL greater, BOOL *ret)
Definition: engine.c:2298
static BSTR local_name(call_frame_t *frame, int ref)
Definition: engine.c:187
static HRESULT interp_push_scope(script_ctx_t *ctx)
Definition: engine.c:821
HRESULT jsval_strict_equal(jsval_t lval, jsval_t rval, BOOL *ret)
Definition: engine.c:531
static const WCHAR numberW[]
Definition: engine.c:36
static HRESULT stack_pop_number(script_ctx_t *ctx, double *r)
Definition: engine.c:141
static HRESULT interp_preinc(script_ctx_t *ctx)
Definition: engine.c:2102
HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, function_code_t *function, scope_chain_t *scope, IDispatch *this_obj, jsdisp_t *function_instance, jsdisp_t *variable_obj, unsigned argc, jsval_t *argv, jsval_t *r)
Definition: engine.c:2958
static HRESULT interp_obj_prop(script_ctx_t *ctx)
Definition: engine.c:1452
static int __cdecl local_ref_cmp(const void *key, const void *ref)
Definition: engine.c:624
static HRESULT interp_div(script_ctx_t *ctx)
Definition: engine.c:1806
static BOOL stack_topn_exprval(script_ctx_t *ctx, unsigned n, exprval_t *r)
Definition: engine.c:223
static const WCHAR functionW[]
Definition: engine.c:35
static HRESULT interp_typeofid(script_ctx_t *ctx)
Definition: engine.c:1965
static HRESULT interp_lt(script_ctx_t *ctx)
Definition: engine.c:2334
static HRESULT interp_assign_call(script_ctx_t *ctx)
Definition: engine.c:2533
static HRESULT interp_mul(script_ctx_t *ctx)
Definition: engine.c:1787
#define OP_LIST
Definition: engine.h:21
static scope_chain_t * scope_addref(scope_chain_t *scope)
Definition: engine.h:212
#define EXEC_GLOBAL
Definition: engine.h:248
@ PROPERTY_DEFINITION_GETTER
Definition: engine.h:136
@ PROPERTY_DEFINITION_VALUE
Definition: engine.h:135
HRESULT setup_arguments_object(script_ctx_t *, call_frame_t *) DECLSPEC_HIDDEN
Definition: function.c:192
#define EXEC_RETURN_TO_INTERP
Definition: engine.h:250
#define EXEC_EVAL
Definition: engine.h:251
void detach_arguments_object(jsdisp_t *) DECLSPEC_HIDDEN
Definition: function.c:229
jsop_t
Definition: engine.h:101
#define EXEC_CONSTRUCTOR
Definition: engine.h:249
HRESULT create_source_function(script_ctx_t *, bytecode_t *, function_code_t *, scope_chain_t *, jsdisp_t **) DECLSPEC_HIDDEN
Definition: function.c:767
static bytecode_t * bytecode_addref(bytecode_t *code)
Definition: engine.h:196
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
const GLdouble * v
Definition: gl.h:2040
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLenum func
Definition: glext.h:6028
GLdouble n
Definition: glext.h:7729
GLuint index
Definition: glext.h:6031
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint GLfloat * val
Definition: glext.h:7180
GLuint id
Definition: glext.h:5910
GLenum target
Definition: glext.h:7315
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
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 * u
Definition: glfuncs.h:240
static HRESULT to_string(VARIANT *src, BSTR *dst)
Definition: host.c:47
_Check_return_ double __cdecl fmod(_In_ double x, _In_ double y)
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
void release_bytecode(bytecode_t *code)
Definition: compile.c:2226
HRESULT jsdisp_propput_name(jsdisp_t *obj, const WCHAR *name, jsval_t val)
Definition: dispex.c:1344
HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val)
Definition: dispex.c:1458
HRESULT jsdisp_get_id(jsdisp_t *jsdisp, const WCHAR *name, DWORD flags, DISPID *id)
Definition: dispex.c:1067
HRESULT disp_delete(IDispatch *disp, DISPID id, BOOL *ret)
Definition: dispex.c:1511
jsdisp_t * iface_to_jsdisp(IDispatch *iface)
Definition: dispex.c:1060
HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, unsigned argc, jsval_t *argv, jsval_t *ret)
Definition: dispex.c:1136
HRESULT disp_delete_name(script_ctx_t *ctx, IDispatch *disp, jsstr_t *name, BOOL *ret)
Definition: dispex.c:1574
HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
Definition: dispex.c:1228
jsdisp_t * as_jsdisp(IDispatch *disp)
Definition: dispex.c:908
HRESULT create_dispex(script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype, jsdisp_t **dispex)
Definition: dispex.c:957
HRESULT jsdisp_propget_name(jsdisp_t *obj, const WCHAR *name, jsval_t *val)
Definition: dispex.c:1408
HRESULT jsdisp_propput_idx(jsdisp_t *obj, DWORD idx, jsval_t val)
Definition: dispex.c:1349
jsdisp_t * to_jsdisp(IDispatch *disp)
Definition: dispex.c:914
HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t val)
Definition: dispex.c:1359
HRESULT jsdisp_define_property(jsdisp_t *obj, const WCHAR *name, property_desc_t *desc)
Definition: dispex.c:1677
#define DISPATCH_JSCRIPT_CALLEREXECSSOURCE
Definition: jscript.h:115
HRESULT create_object(script_ctx_t *, jsdisp_t *, jsdisp_t **) DECLSPEC_HIDDEN
Definition: object.c:731
#define JS_E_ILLEGAL_ASSIGN
Definition: jscript.h:556
@ NO_HINT
Definition: jscript.h:338
#define JS_E_OBJECT_REQUIRED
Definition: jscript.h:531
HRESULT to_object(script_ctx_t *, jsval_t, IDispatch **) DECLSPEC_HIDDEN
Definition: jsutils.c:816
#define JS_E_OBJECT_EXPECTED
Definition: jscript.h:555
static void jsdisp_release(jsdisp_t *jsdisp)
Definition: jscript.h:268
#define PROPF_CONFIGURABLE
Definition: jscript.h:102
HRESULT to_primitive(script_ctx_t *, jsval_t, jsval_t *, hint_t) DECLSPEC_HIDDEN
Definition: jsutils.c:404
HRESULT to_number(script_ctx_t *, jsval_t, double *) DECLSPEC_HIDDEN
Definition: jsutils.c:609
HRESULT to_int32(script_ctx_t *, jsval_t, INT *) DECLSPEC_HIDDEN
Definition: jsutils.c:665
#define JS_E_FUNCTION_EXPECTED
Definition: jscript.h:552
HRESULT to_uint32(script_ctx_t *, jsval_t, UINT32 *) DECLSPEC_HIDDEN
Definition: jsutils.c:686
static IDispatch * to_disp(jsdisp_t *jsdisp)
Definition: jscript.h:245
#define JS_E_UNDEFINED_VARIABLE
Definition: jscript.h:557
static DWORD make_grfdex(script_ctx_t *ctx, DWORD flags)
Definition: jscript.h:519
@ JSCLASS_FUNCTION
Definition: jscript.h:126
@ JSCLASS_NONE
Definition: jscript.h:120
@ JSCLASS_GLOBAL
Definition: jscript.h:127
#define JS_E_INVALID_PROPERTY
Definition: jscript.h:533
const char * debugstr_jsval(const jsval_t) DECLSPEC_HIDDEN
Definition: jsutils.c:35
static jsdisp_t * jsdisp_addref(jsdisp_t *jsdisp)
Definition: jscript.h:262
#define PROPF_ENUMERABLE
Definition: jscript.h:100
HRESULT to_boolean(jsval_t, BOOL *) DECLSPEC_HIDDEN
Definition: jsutils.c:472
#define JS_E_INVALID_ACTION
Definition: jscript.h:534
HRESULT to_flat_string(script_ctx_t *, jsval_t, jsstr_t **, const WCHAR **) DECLSPEC_HIDDEN
Definition: jsutils.c:798
HRESULT create_regexp(script_ctx_t *, jsstr_t *, DWORD, jsdisp_t **) DECLSPEC_HIDDEN
Definition: jsregexp.c:644
static BOOL is_class(jsdisp_t *jsdisp, jsclass_t class)
Definition: jscript.h:504
jsstr_t * jsstr_alloc_len(const WCHAR *buf, unsigned len)
Definition: jsstr.c:86
int jsstr_cmp(jsstr_t *str1, jsstr_t *str2)
Definition: jsstr.c:189
jsstr_t * jsstr_undefined(void)
Definition: jsstr.c:293
jsstr_t * jsstr_concat(jsstr_t *str1, jsstr_t *str2)
Definition: jsstr.c:211
const char * debugstr_jsstr(jsstr_t *str)
Definition: jsstr.c:37
static jsstr_t * jsstr_addref(jsstr_t *str)
Definition: jsstr.h:116
static const WCHAR * jsstr_flatten(jsstr_t *str)
Definition: jsstr.h:139
static BOOL jsstr_eq(jsstr_t *left, jsstr_t *right)
Definition: jsstr.h:176
static void jsstr_release(jsstr_t *str)
Definition: jsstr.h:110
static jsstr_t * jsstr_alloc(const WCHAR *str)
Definition: jsstr.h:103
HRESULT jsval_copy(jsval_t v, jsval_t *r)
Definition: jsutils.c:231
void jsval_release(jsval_t val)
Definition: jsutils.c:191
static BOOL is_number(jsval_t v)
Definition: jsval.h:191
static VARIANT * get_variant(jsval_t v)
Definition: jsval.h:234
jsval_type_t
Definition: jsval.h:44
@ JSV_STRING
Definition: jsval.h:48
@ JSV_NUMBER
Definition: jsval.h:49
@ JSV_VARIANT
Definition: jsval.h:51
@ JSV_OBJECT
Definition: jsval.h:47
@ JSV_NULL
Definition: jsval.h:46
@ JSV_UNDEFINED
Definition: jsval.h:45
@ JSV_BOOL
Definition: jsval.h:50
static jsval_t jsval_null(void)
Definition: jsval.h:130
static jsval_t jsval_string(jsstr_t *str)
Definition: jsval.h:109
static jsval_t jsval_undefined(void)
Definition: jsval.h:137
static jsval_t jsval_obj(jsdisp_t *obj)
Definition: jsval.h:125
static jsval_t jsval_bool(BOOL b)
Definition: jsval.h:101
static BOOL is_null_instance(jsval_t v)
Definition: jsval.h:181
static jsval_type_t jsval_type(jsval_t v)
Definition: jsval.h:210
static jsstr_t * get_string(jsval_t v)
Definition: jsval.h:229
static BOOL is_undefined(jsval_t v)
Definition: jsval.h:171
static double get_number(jsval_t v)
Definition: jsval.h:224
static jsval_t jsval_disp(IDispatch *obj)
Definition: jsval.h:117
static IDispatch * get_object(jsval_t v)
Definition: jsval.h:219
static BOOL is_object_instance(jsval_t v)
Definition: jsval.h:166
static BOOL is_null(jsval_t v)
Definition: jsval.h:176
static jsval_t jsval_number(double n)
Definition: jsval.h:144
static BOOL is_bool(jsval_t v)
Definition: jsval.h:205
#define b
Definition: ke_i.h:79
#define debugstr_w
Definition: kernel32.h:32
#define isnan(x)
Definition: mingw_math.h:133
LOCAL int prim(arg_t *ap)
Definition: match.c:440
#define WARN_ON(c)
Definition: module.h:257
static PVOID ptr
Definition: dispmode.c:27
ULONG nr
Definition: thread.c:7
static const WCHAR desc[]
Definition: protectdata.c:36
static const char * debugstr_variant(const VARIANT *var)
Definition: container.c:46
HRESULT hres
Definition: protocol.c:465
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:80
static VARIANTARG static DISPID
Definition: ordinal.c:52
static DWORD unk1
Definition: cursoricon.c:1638
static ATOM item
Definition: dde.c:856
#define argv
Definition: mplay32.c:18
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:196
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
#define DISPATCH_PROPERTYPUT
Definition: oleauto.h:1008
#define DISPATCH_METHOD
Definition: oleauto.h:1006
const GUID IID_IDispatch
static BOOL is_string(parse_buffer *buf)
Definition: parsing.c:600
#define IID_NULL
Definition: guiddef.h:98
const WCHAR * str
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define memset(x, y, z)
Definition: compat.h:39
LOCAL char * rstr(char *s1, char *s2)
Definition: tree.c:165
#define TRACE(s)
Definition: solgame.cpp:4
instr_t * instrs
Definition: engine.h:175
IDispatch * this_obj
Definition: engine.h:230
except_frame_t * except_frame
Definition: engine.h:223
struct _call_frame_t * prev_frame
Definition: engine.h:245
unsigned variables_off
Definition: engine.h:239
unsigned ip
Definition: engine.h:222
unsigned argc
Definition: engine.h:236
unsigned pop_locals
Definition: engine.h:237
jsdisp_t * arguments_obj
Definition: engine.h:233
scope_chain_t * base_scope
Definition: engine.h:226
jsdisp_t * variable_obj
Definition: engine.h:232
function_code_t * function
Definition: engine.h:243
bytecode_t * bytecode
Definition: engine.h:242
unsigned arguments_off
Definition: engine.h:238
DWORD flags
Definition: engine.h:234
scope_chain_t * scope
Definition: engine.h:225
jsval_t ret
Definition: engine.h:228
unsigned pop_variables
Definition: engine.h:240
jsdisp_t * function_instance
Definition: engine.h:231
unsigned stack_base
Definition: engine.h:224
scope_chain_t * scope
Definition: engine.c:44
unsigned stack_top
Definition: engine.c:43
except_frame_t * next
Definition: engine.c:48
unsigned catch_off
Definition: engine.c:45
unsigned finally_off
Definition: engine.c:46
unsigned var_cnt
Definition: engine.h:157
struct _function_code_t::@447 * variables
struct _function_code_t * funcs
Definition: engine.h:155
unsigned func_cnt
Definition: engine.h:154
local_ref_t * locals
Definition: engine.h:167
BSTR * params
Definition: engine.h:164
unsigned locals_cnt
Definition: engine.h:166
unsigned param_cnt
Definition: engine.h:163
unsigned instr_off
Definition: engine.h:149
Definition: jsstr.h:39
Definition: jsval.h:54
IDispatch * obj
Definition: engine.h:205
struct _call_frame_t * frame
Definition: engine.h:206
struct _scope_chain_t * next
Definition: engine.h:207
jsdisp_t * jsobj
Definition: engine.h:204
jsclass_t class
Definition: jscript.h:219
struct define * next
Definition: compiler.c:65
union exprval_t::@444 u
HRESULT hres
Definition: engine.c:65
@ EXPRVAL_JSVAL
Definition: engine.c:53
@ EXPRVAL_STACK_REF
Definition: engine.c:55
@ EXPRVAL_IDREF
Definition: engine.c:54
unsigned off
Definition: engine.c:64
enum exprval_t::@443 type
struct exprval_t::@444::@445 idref
jsval_t val
Definition: engine.c:59
IDispatch * disp
Definition: engine.c:61
DISPID id
Definition: engine.c:62
instr_arg_t arg[2]
Definition: engine.h:129
union instr_t::@446 u
jsop_t op
Definition: engine.h:127
double dbl
Definition: engine.h:130
IDispatchEx IDispatchEx_iface
Definition: jscript.h:231
const builtin_info_t * builtin_info
Definition: jscript.h:242
jsdisp_t * prototype
Definition: jscript.h:240
Definition: copy.c:22
int ref
Definition: engine.h:142
BSTR name
Definition: engine.h:141
Definition: name.c:39
Definition: send.c:48
#define bsearch
int32_t INT
Definition: typedefs.h:58
unsigned uint
Definition: engine.h:112
LONG lng
Definition: engine.h:110
jsstr_t * str
Definition: engine.h:111
BSTR bstr
Definition: engine.h:109
Definition: pdh_main.c:94
int ret
_In_ ULONG _In_ ULONG_PTR ident
Definition: winddi.h:3994
#define HRESULT
Definition: msvc.h:7
#define DISP_E_EXCEPTION
Definition: winerror.h:2518
#define DISP_E_UNKNOWNNAME
Definition: winerror.h:2515
__wchar_t WCHAR
Definition: xmlstorage.h:180