jscript: Remove unused code (Clang).
[wine/multimedia.git] / dlls / jscript / engine.c
blobde6075552aad12eb0f030b22d0eedf466d445d09
1 /*
2 * Copyright 2008,2011 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "config.h"
20 #include "wine/port.h"
22 #include <math.h>
23 #include <assert.h>
25 #include "jscript.h"
26 #include "engine.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
32 static const WCHAR booleanW[] = {'b','o','o','l','e','a','n',0};
33 static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0};
34 static const WCHAR numberW[] = {'n','u','m','b','e','r',0};
35 static const WCHAR objectW[] = {'o','b','j','e','c','t',0};
36 static const WCHAR stringW[] = {'s','t','r','i','n','g',0};
37 static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
38 static const WCHAR unknownW[] = {'u','n','k','n','o','w','n',0};
40 struct _except_frame_t {
41 unsigned stack_top;
42 scope_chain_t *scope;
43 unsigned catch_off;
44 BSTR ident;
46 except_frame_t *next;
49 typedef struct {
50 enum {
51 EXPRVAL_JSVAL,
52 EXPRVAL_IDREF,
53 EXPRVAL_INVALID
54 } type;
55 union {
56 jsval_t val;
57 struct {
58 IDispatch *disp;
59 DISPID id;
60 } idref;
61 } u;
62 } exprval_t;
64 static HRESULT stack_push(exec_ctx_t *ctx, jsval_t v)
66 if(!ctx->stack_size) {
67 ctx->stack = heap_alloc(16*sizeof(*ctx->stack));
68 if(!ctx->stack)
69 return E_OUTOFMEMORY;
70 ctx->stack_size = 16;
71 }else if(ctx->stack_size == ctx->top) {
72 jsval_t *new_stack;
74 new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(*new_stack));
75 if(!new_stack) {
76 jsval_release(v);
77 return E_OUTOFMEMORY;
80 ctx->stack = new_stack;
81 ctx->stack_size *= 2;
84 ctx->stack[ctx->top++] = v;
85 return S_OK;
88 static inline HRESULT stack_push_string(exec_ctx_t *ctx, const WCHAR *str)
90 jsstr_t *v;
92 v = jsstr_alloc(str);
93 if(!v)
94 return E_OUTOFMEMORY;
96 return stack_push(ctx, jsval_string(v));
99 static HRESULT stack_push_objid(exec_ctx_t *ctx, IDispatch *disp, DISPID id)
101 HRESULT hres;
103 hres = stack_push(ctx, jsval_disp(disp));
104 if(FAILED(hres))
105 return hres;
107 return stack_push(ctx, jsval_number(id));
110 static inline jsval_t stack_top(exec_ctx_t *ctx)
112 assert(ctx->top);
113 return ctx->stack[ctx->top-1];
116 static inline jsval_t stack_topn(exec_ctx_t *ctx, unsigned n)
118 assert(ctx->top > n);
119 return ctx->stack[ctx->top-1-n];
122 static inline jsval_t *stack_args(exec_ctx_t *ctx, unsigned n)
124 if(!n)
125 return NULL;
126 assert(ctx->top > n-1);
127 return ctx->stack + ctx->top-n;
130 static inline jsval_t stack_pop(exec_ctx_t *ctx)
132 assert(ctx->top);
133 return ctx->stack[--ctx->top];
136 static void stack_popn(exec_ctx_t *ctx, unsigned n)
138 while(n--)
139 jsval_release(stack_pop(ctx));
142 static HRESULT stack_pop_number(exec_ctx_t *ctx, double *r)
144 jsval_t v;
145 HRESULT hres;
147 v = stack_pop(ctx);
148 hres = to_number(ctx->script, v, r);
149 jsval_release(v);
150 return hres;
153 static HRESULT stack_pop_object(exec_ctx_t *ctx, IDispatch **r)
155 jsval_t v;
156 HRESULT hres;
158 v = stack_pop(ctx);
159 if(is_object_instance(v)) {
160 if(!get_object(v))
161 return throw_type_error(ctx->script, JS_E_OBJECT_REQUIRED, NULL);
162 *r = get_object(v);
163 return S_OK;
166 hres = to_object(ctx->script, v, r);
167 jsval_release(v);
168 return hres;
171 static inline HRESULT stack_pop_int(exec_ctx_t *ctx, INT *r)
173 return to_int32(ctx->script, stack_pop(ctx), r);
176 static inline HRESULT stack_pop_uint(exec_ctx_t *ctx, DWORD *r)
178 return to_uint32(ctx->script, stack_pop(ctx), r);
181 static inline IDispatch *stack_pop_objid(exec_ctx_t *ctx, DISPID *id)
183 assert(is_number(stack_top(ctx)) && is_object_instance(stack_topn(ctx, 1)));
185 *id = get_number(stack_pop(ctx));
186 return get_object(stack_pop(ctx));
189 static inline IDispatch *stack_topn_objid(exec_ctx_t *ctx, unsigned n, DISPID *id)
191 assert(is_number(stack_topn(ctx, n)) && is_object_instance(stack_topn(ctx, n+1)));
193 *id = get_number(stack_topn(ctx, n));
194 return get_object(stack_topn(ctx, n+1));
197 static void exprval_release(exprval_t *val)
199 switch(val->type) {
200 case EXPRVAL_JSVAL:
201 jsval_release(val->u.val);
202 return;
203 case EXPRVAL_IDREF:
204 if(val->u.idref.disp)
205 IDispatch_Release(val->u.idref.disp);
206 return;
207 case EXPRVAL_INVALID:
208 return;
212 /* ECMA-262 3rd Edition 8.7.1 */
213 static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsval_t *ret)
215 switch(val->type) {
216 case EXPRVAL_JSVAL:
217 *ret = val->u.val;
218 val->u.val = jsval_undefined();
219 return S_OK;
220 case EXPRVAL_IDREF:
221 if(!val->u.idref.disp) {
222 FIXME("throw ReferenceError\n");
223 return E_FAIL;
226 return disp_propget(ctx, val->u.idref.disp, val->u.idref.id, ret);
227 case EXPRVAL_INVALID:
228 assert(0);
231 ERR("type %d\n", val->type);
232 return E_FAIL;
235 static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id)
237 val->type = EXPRVAL_IDREF;
238 val->u.idref.disp = disp;
239 val->u.idref.id = id;
241 if(disp)
242 IDispatch_AddRef(disp);
245 HRESULT scope_push(scope_chain_t *scope, jsdisp_t *jsobj, IDispatch *obj, scope_chain_t **ret)
247 scope_chain_t *new_scope;
249 new_scope = heap_alloc(sizeof(scope_chain_t));
250 if(!new_scope)
251 return E_OUTOFMEMORY;
253 new_scope->ref = 1;
255 IDispatch_AddRef(obj);
256 new_scope->jsobj = jsobj;
257 new_scope->obj = obj;
259 if(scope) {
260 scope_addref(scope);
261 new_scope->next = scope;
262 }else {
263 new_scope->next = NULL;
266 *ret = new_scope;
267 return S_OK;
270 static void scope_pop(scope_chain_t **scope)
272 scope_chain_t *tmp;
274 tmp = *scope;
275 *scope = tmp->next;
276 scope_release(tmp);
279 void clear_ei(script_ctx_t *ctx)
281 memset(&ctx->ei.ei, 0, sizeof(ctx->ei.ei));
282 jsval_release(ctx->ei.val);
283 ctx->ei.val = jsval_undefined();
286 void scope_release(scope_chain_t *scope)
288 if(--scope->ref)
289 return;
291 if(scope->next)
292 scope_release(scope->next);
294 IDispatch_Release(scope->obj);
295 heap_free(scope);
298 HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, jsdisp_t *var_disp,
299 scope_chain_t *scope, BOOL is_global, exec_ctx_t **ret)
301 exec_ctx_t *ctx;
303 ctx = heap_alloc_zero(sizeof(exec_ctx_t));
304 if(!ctx)
305 return E_OUTOFMEMORY;
307 ctx->ref = 1;
308 ctx->is_global = is_global;
309 ctx->ret = jsval_undefined();
311 /* ECMA-262 3rd Edition 11.2.3.7 */
312 if(this_obj) {
313 jsdisp_t *jsthis;
315 jsthis = iface_to_jsdisp((IUnknown*)this_obj);
316 if(jsthis) {
317 if(jsthis->builtin_info->class == JSCLASS_GLOBAL || jsthis->builtin_info->class == JSCLASS_NONE)
318 this_obj = NULL;
319 jsdisp_release(jsthis);
323 if(this_obj)
324 ctx->this_obj = this_obj;
325 else if(script_ctx->host_global)
326 ctx->this_obj = script_ctx->host_global;
327 else
328 ctx->this_obj = to_disp(script_ctx->global);
329 IDispatch_AddRef(ctx->this_obj);
331 jsdisp_addref(var_disp);
332 ctx->var_disp = var_disp;
334 script_addref(script_ctx);
335 ctx->script = script_ctx;
337 if(scope) {
338 scope_addref(scope);
339 ctx->scope_chain = scope;
342 *ret = ctx;
343 return S_OK;
346 void exec_release(exec_ctx_t *ctx)
348 if(--ctx->ref)
349 return;
351 if(ctx->scope_chain)
352 scope_release(ctx->scope_chain);
353 if(ctx->var_disp)
354 jsdisp_release(ctx->var_disp);
355 if(ctx->this_obj)
356 IDispatch_Release(ctx->this_obj);
357 if(ctx->script)
358 script_release(ctx->script);
359 jsval_release(ctx->ret);
360 heap_free(ctx->stack);
361 heap_free(ctx);
364 static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, const WCHAR *name, BSTR name_bstr, DWORD flags, DISPID *id)
366 IDispatchEx *dispex;
367 jsdisp_t *jsdisp;
368 BSTR bstr;
369 HRESULT hres;
371 jsdisp = iface_to_jsdisp((IUnknown*)disp);
372 if(jsdisp) {
373 hres = jsdisp_get_id(jsdisp, name, flags, id);
374 jsdisp_release(jsdisp);
375 return hres;
378 if(name_bstr) {
379 bstr = name_bstr;
380 }else {
381 bstr = SysAllocString(name);
382 if(!bstr)
383 return E_OUTOFMEMORY;
386 *id = 0;
387 hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
388 if(SUCCEEDED(hres)) {
389 hres = IDispatchEx_GetDispID(dispex, bstr, make_grfdex(ctx, flags|fdexNameCaseSensitive), id);
390 IDispatchEx_Release(dispex);
391 }else {
392 TRACE("using IDispatch\n");
393 hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &bstr, 1, 0, id);
396 if(name_bstr != bstr)
397 SysFreeString(bstr);
398 return hres;
401 static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret)
403 IObjectIdentity *identity;
404 IUnknown *unk1, *unk2;
405 HRESULT hres;
407 if(disp1 == disp2) {
408 *ret = TRUE;
409 return S_OK;
412 if(!disp1 || !disp2) {
413 *ret = FALSE;
414 return S_OK;
417 hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1);
418 if(FAILED(hres))
419 return hres;
421 hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2);
422 if(FAILED(hres)) {
423 IUnknown_Release(unk1);
424 return hres;
427 if(unk1 == unk2) {
428 *ret = TRUE;
429 }else {
430 hres = IUnknown_QueryInterface(unk1, &IID_IObjectIdentity, (void**)&identity);
431 if(SUCCEEDED(hres)) {
432 hres = IObjectIdentity_IsEqualObject(identity, unk2);
433 IObjectIdentity_Release(identity);
434 *ret = hres == S_OK;
435 }else {
436 *ret = FALSE;
440 IUnknown_Release(unk1);
441 IUnknown_Release(unk2);
442 return S_OK;
445 /* ECMA-262 3rd Edition 11.9.6 */
446 static HRESULT equal2_values(jsval_t lval, jsval_t rval, BOOL *ret)
448 jsval_type_t type = jsval_type(lval);
450 TRACE("\n");
452 if(type != jsval_type(rval)) {
453 if(is_null_instance(lval))
454 *ret = is_null_instance(rval);
455 else
456 *ret = FALSE;
457 return S_OK;
460 switch(type) {
461 case JSV_UNDEFINED:
462 case JSV_NULL:
463 *ret = TRUE;
464 break;
465 case JSV_OBJECT:
466 return disp_cmp(get_object(lval), get_object(rval), ret);
467 case JSV_STRING:
468 *ret = jsstr_eq(get_string(lval), get_string(rval));
469 break;
470 case JSV_NUMBER:
471 *ret = get_number(lval) == get_number(rval);
472 break;
473 case JSV_BOOL:
474 *ret = !get_bool(lval) == !get_bool(rval);
475 break;
476 case JSV_VARIANT:
477 FIXME("VARIANT not implemented\n");
478 return E_NOTIMPL;
481 return S_OK;
484 static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
486 named_item_t *item;
487 DISPID id;
488 HRESULT hres;
490 for(item = ctx->named_items; item; item = item->next) {
491 if(item->flags & SCRIPTITEM_GLOBALMEMBERS) {
492 hres = disp_get_id(ctx, item->disp, identifier, identifier, 0, &id);
493 if(SUCCEEDED(hres)) {
494 if(ret)
495 exprval_set_idref(ret, item->disp, id);
496 return TRUE;
501 return FALSE;
504 /* ECMA-262 3rd Edition 10.1.4 */
505 static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
507 scope_chain_t *scope;
508 named_item_t *item;
509 DISPID id = 0;
510 HRESULT hres;
512 TRACE("%s\n", debugstr_w(identifier));
514 for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) {
515 if(scope->jsobj)
516 hres = jsdisp_get_id(scope->jsobj, identifier, fdexNameImplicit, &id);
517 else
518 hres = disp_get_id(ctx, scope->obj, identifier, identifier, fdexNameImplicit, &id);
519 if(SUCCEEDED(hres)) {
520 exprval_set_idref(ret, scope->obj, id);
521 return S_OK;
525 hres = jsdisp_get_id(ctx->global, identifier, 0, &id);
526 if(SUCCEEDED(hres)) {
527 exprval_set_idref(ret, to_disp(ctx->global), id);
528 return S_OK;
531 for(item = ctx->named_items; item; item = item->next) {
532 if((item->flags & SCRIPTITEM_ISVISIBLE) && !strcmpW(item->name, identifier)) {
533 if(!item->disp) {
534 IUnknown *unk;
536 if(!ctx->site)
537 break;
539 hres = IActiveScriptSite_GetItemInfo(ctx->site, identifier,
540 SCRIPTINFO_IUNKNOWN, &unk, NULL);
541 if(FAILED(hres)) {
542 WARN("GetItemInfo failed: %08x\n", hres);
543 break;
546 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
547 IUnknown_Release(unk);
548 if(FAILED(hres)) {
549 WARN("object does not implement IDispatch\n");
550 break;
554 IDispatch_AddRef(item->disp);
555 ret->type = EXPRVAL_JSVAL;
556 ret->u.val = jsval_disp(item->disp);
557 return S_OK;
561 if(lookup_global_members(ctx, identifier, ret))
562 return S_OK;
564 ret->type = EXPRVAL_INVALID;
565 return S_OK;
568 static inline BSTR get_op_bstr(exec_ctx_t *ctx, int i){
569 return ctx->code->instrs[ctx->ip].u.arg[i].bstr;
572 static inline unsigned get_op_uint(exec_ctx_t *ctx, int i){
573 return ctx->code->instrs[ctx->ip].u.arg[i].uint;
576 static inline unsigned get_op_int(exec_ctx_t *ctx, int i){
577 return ctx->code->instrs[ctx->ip].u.arg[i].lng;
580 static inline jsstr_t *get_op_str(exec_ctx_t *ctx, int i){
581 return ctx->code->instrs[ctx->ip].u.arg[i].str;
584 static inline double get_op_double(exec_ctx_t *ctx){
585 return ctx->code->instrs[ctx->ip].u.dbl;
588 /* ECMA-262 3rd Edition 12.2 */
589 static HRESULT interp_var_set(exec_ctx_t *ctx)
591 const BSTR name = get_op_bstr(ctx, 0);
592 jsval_t val;
593 HRESULT hres;
595 TRACE("%s\n", debugstr_w(name));
597 val = stack_pop(ctx);
598 hres = jsdisp_propput_name(ctx->var_disp, name, val);
599 jsval_release(val);
600 return hres;
603 /* ECMA-262 3rd Edition 12.6.4 */
604 static HRESULT interp_forin(exec_ctx_t *ctx)
606 const HRESULT arg = get_op_uint(ctx, 0);
607 IDispatch *var_obj, *obj = NULL;
608 IDispatchEx *dispex;
609 DISPID id, var_id;
610 BSTR name = NULL;
611 HRESULT hres;
613 TRACE("\n");
615 assert(is_number(stack_top(ctx)));
616 id = get_number(stack_top(ctx));
618 var_obj = stack_topn_objid(ctx, 1, &var_id);
619 if(!var_obj) {
620 FIXME("invalid ref\n");
621 return E_FAIL;
624 if(is_object_instance(stack_topn(ctx, 3)))
625 obj = get_object(stack_topn(ctx, 3));
627 if(obj) {
628 hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
629 if(SUCCEEDED(hres)) {
630 hres = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, id, &id);
631 if(hres == S_OK)
632 hres = IDispatchEx_GetMemberName(dispex, id, &name);
633 IDispatchEx_Release(dispex);
634 if(FAILED(hres))
635 return hres;
636 }else {
637 TRACE("No IDispatchEx\n");
641 if(name) {
642 jsstr_t *str;
644 str = jsstr_alloc_len(name, SysStringLen(name));
645 SysFreeString(name);
646 if(!str)
647 return E_OUTOFMEMORY;
649 stack_pop(ctx);
650 stack_push(ctx, jsval_number(id)); /* safe, just after pop() */
652 hres = disp_propput(ctx->script, var_obj, var_id, jsval_string(str));
653 jsstr_release(str);
654 if(FAILED(hres))
655 return hres;
657 ctx->ip++;
658 }else {
659 stack_popn(ctx, 4);
660 ctx->ip = arg;
662 return S_OK;
665 /* ECMA-262 3rd Edition 12.10 */
666 static HRESULT interp_push_scope(exec_ctx_t *ctx)
668 IDispatch *disp;
669 jsval_t v;
670 HRESULT hres;
672 TRACE("\n");
674 v = stack_pop(ctx);
675 hres = to_object(ctx->script, v, &disp);
676 jsval_release(v);
677 if(FAILED(hres))
678 return hres;
680 hres = scope_push(ctx->scope_chain, to_jsdisp(disp), disp, &ctx->scope_chain);
681 IDispatch_Release(disp);
682 return hres;
685 /* ECMA-262 3rd Edition 12.10 */
686 static HRESULT interp_pop_scope(exec_ctx_t *ctx)
688 TRACE("\n");
690 scope_pop(&ctx->scope_chain);
691 return S_OK;
694 /* ECMA-262 3rd Edition 12.13 */
695 static HRESULT interp_case(exec_ctx_t *ctx)
697 const unsigned arg = get_op_uint(ctx, 0);
698 jsval_t v;
699 BOOL b;
700 HRESULT hres;
702 TRACE("\n");
704 v = stack_pop(ctx);
705 hres = equal2_values(stack_top(ctx), v, &b);
706 jsval_release(v);
707 if(FAILED(hres))
708 return hres;
710 if(b) {
711 stack_popn(ctx, 1);
712 ctx->ip = arg;
713 }else {
714 ctx->ip++;
716 return S_OK;
719 /* ECMA-262 3rd Edition 12.13 */
720 static HRESULT interp_throw(exec_ctx_t *ctx)
722 TRACE("\n");
724 jsval_release(ctx->script->ei.val);
725 ctx->script->ei.val = stack_pop(ctx);
726 return DISP_E_EXCEPTION;
729 static HRESULT interp_throw_ref(exec_ctx_t *ctx)
731 const HRESULT arg = get_op_uint(ctx, 0);
733 TRACE("%08x\n", arg);
735 return throw_reference_error(ctx->script, arg, NULL);
738 static HRESULT interp_throw_type(exec_ctx_t *ctx)
740 const HRESULT hres = get_op_uint(ctx, 0);
741 jsstr_t *str = get_op_str(ctx, 1);
742 const WCHAR *ptr;
744 TRACE("%08x %s\n", hres, debugstr_jsstr(str));
746 ptr = jsstr_flatten(str);
747 return ptr ? throw_type_error(ctx->script, hres, ptr) : E_OUTOFMEMORY;
750 /* ECMA-262 3rd Edition 12.14 */
751 static HRESULT interp_push_except(exec_ctx_t *ctx)
753 const unsigned arg1 = get_op_uint(ctx, 0);
754 const BSTR arg2 = get_op_bstr(ctx, 1);
755 except_frame_t *except;
756 unsigned stack_top;
758 TRACE("\n");
760 stack_top = ctx->top;
762 if(!arg2) {
763 HRESULT hres;
765 hres = stack_push(ctx, jsval_bool(TRUE));
766 if(FAILED(hres))
767 return hres;
768 hres = stack_push(ctx, jsval_bool(TRUE));
769 if(FAILED(hres))
770 return hres;
773 except = heap_alloc(sizeof(*except));
774 if(!except)
775 return E_OUTOFMEMORY;
777 except->stack_top = stack_top;
778 except->scope = ctx->scope_chain;
779 except->catch_off = arg1;
780 except->ident = arg2;
781 except->next = ctx->except_frame;
782 ctx->except_frame = except;
783 return S_OK;
786 /* ECMA-262 3rd Edition 12.14 */
787 static HRESULT interp_pop_except(exec_ctx_t *ctx)
789 except_frame_t *except;
791 TRACE("\n");
793 except = ctx->except_frame;
794 assert(except != NULL);
796 ctx->except_frame = except->next;
797 heap_free(except);
798 return S_OK;
801 /* ECMA-262 3rd Edition 12.14 */
802 static HRESULT interp_end_finally(exec_ctx_t *ctx)
804 jsval_t v;
806 TRACE("\n");
808 v = stack_pop(ctx);
809 assert(is_bool(v));
811 if(!get_bool(v)) {
812 TRACE("passing exception\n");
814 ctx->script->ei.val = stack_pop(ctx);
815 return DISP_E_EXCEPTION;
818 stack_pop(ctx);
819 return S_OK;
822 /* ECMA-262 3rd Edition 13 */
823 static HRESULT interp_func(exec_ctx_t *ctx)
825 unsigned func_idx = get_op_uint(ctx, 0);
826 jsdisp_t *dispex;
827 HRESULT hres;
829 TRACE("%d\n", func_idx);
831 hres = create_source_function(ctx->script, ctx->code, ctx->func_code->funcs+func_idx,
832 ctx->scope_chain, &dispex);
833 if(FAILED(hres))
834 return hres;
836 return stack_push(ctx, jsval_obj(dispex));
839 /* ECMA-262 3rd Edition 11.2.1 */
840 static HRESULT interp_array(exec_ctx_t *ctx)
842 jsstr_t *name_str;
843 const WCHAR *name;
844 jsval_t v, namev;
845 IDispatch *obj;
846 DISPID id;
847 HRESULT hres;
849 TRACE("\n");
851 namev = stack_pop(ctx);
853 hres = stack_pop_object(ctx, &obj);
854 if(FAILED(hres)) {
855 jsval_release(namev);
856 return hres;
859 hres = to_flat_string(ctx->script, namev, &name_str, &name);
860 jsval_release(namev);
861 if(FAILED(hres)) {
862 IDispatch_Release(obj);
863 return hres;
866 hres = disp_get_id(ctx->script, obj, name, NULL, 0, &id);
867 jsstr_release(name_str);
868 if(SUCCEEDED(hres)) {
869 hres = disp_propget(ctx->script, obj, id, &v);
870 }else if(hres == DISP_E_UNKNOWNNAME) {
871 v = jsval_undefined();
872 hres = S_OK;
874 IDispatch_Release(obj);
875 if(FAILED(hres))
876 return hres;
878 return stack_push(ctx, v);
881 /* ECMA-262 3rd Edition 11.2.1 */
882 static HRESULT interp_member(exec_ctx_t *ctx)
884 const BSTR arg = get_op_bstr(ctx, 0);
885 IDispatch *obj;
886 jsval_t v;
887 DISPID id;
888 HRESULT hres;
890 TRACE("\n");
892 hres = stack_pop_object(ctx, &obj);
893 if(FAILED(hres))
894 return hres;
896 hres = disp_get_id(ctx->script, obj, arg, arg, 0, &id);
897 if(SUCCEEDED(hres)) {
898 hres = disp_propget(ctx->script, obj, id, &v);
899 }else if(hres == DISP_E_UNKNOWNNAME) {
900 v = jsval_undefined();
901 hres = S_OK;
903 IDispatch_Release(obj);
904 if(FAILED(hres))
905 return hres;
907 return stack_push(ctx, v);
910 /* ECMA-262 3rd Edition 11.2.1 */
911 static HRESULT interp_memberid(exec_ctx_t *ctx)
913 const unsigned arg = get_op_uint(ctx, 0);
914 jsval_t objv, namev;
915 const WCHAR *name;
916 jsstr_t *name_str;
917 IDispatch *obj;
918 DISPID id;
919 HRESULT hres;
921 TRACE("%x\n", arg);
923 namev = stack_pop(ctx);
924 objv = stack_pop(ctx);
926 hres = to_object(ctx->script, objv, &obj);
927 jsval_release(objv);
928 if(SUCCEEDED(hres)) {
929 hres = to_flat_string(ctx->script, namev, &name_str, &name);
930 if(FAILED(hres))
931 IDispatch_Release(obj);
933 jsval_release(namev);
934 if(FAILED(hres))
935 return hres;
937 hres = disp_get_id(ctx->script, obj, name, NULL, arg, &id);
938 jsstr_release(name_str);
939 if(FAILED(hres)) {
940 IDispatch_Release(obj);
941 if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
942 obj = NULL;
943 id = JS_E_INVALID_PROPERTY;
944 }else {
945 ERR("failed %08x\n", hres);
946 return hres;
950 return stack_push_objid(ctx, obj, id);
953 /* ECMA-262 3rd Edition 11.2.1 */
954 static HRESULT interp_refval(exec_ctx_t *ctx)
956 IDispatch *disp;
957 jsval_t v;
958 DISPID id;
959 HRESULT hres;
961 TRACE("\n");
963 disp = stack_topn_objid(ctx, 0, &id);
964 if(!disp)
965 return throw_reference_error(ctx->script, JS_E_ILLEGAL_ASSIGN, NULL);
967 hres = disp_propget(ctx->script, disp, id, &v);
968 if(FAILED(hres))
969 return hres;
971 return stack_push(ctx, v);
974 /* ECMA-262 3rd Edition 11.2.2 */
975 static HRESULT interp_new(exec_ctx_t *ctx)
977 const unsigned argc = get_op_uint(ctx, 0);
978 jsval_t r, constr;
979 HRESULT hres;
981 TRACE("%d\n", argc);
983 constr = stack_topn(ctx, argc);
985 /* NOTE: Should use to_object here */
987 if(is_null(constr))
988 return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL);
989 else if(!is_object_instance(constr))
990 return throw_type_error(ctx->script, JS_E_INVALID_ACTION, NULL);
991 else if(!get_object(constr))
992 return throw_type_error(ctx->script, JS_E_INVALID_PROPERTY, NULL);
994 hres = disp_call_value(ctx->script, get_object(constr), NULL, DISPATCH_CONSTRUCT, argc, stack_args(ctx, argc), &r);
995 if(FAILED(hres))
996 return hres;
998 stack_popn(ctx, argc+1);
999 return stack_push(ctx, r);
1002 /* ECMA-262 3rd Edition 11.2.3 */
1003 static HRESULT interp_call(exec_ctx_t *ctx)
1005 const unsigned argn = get_op_uint(ctx, 0);
1006 const int do_ret = get_op_int(ctx, 1);
1007 jsval_t r, obj;
1008 HRESULT hres;
1010 TRACE("%d %d\n", argn, do_ret);
1012 obj = stack_topn(ctx, argn);
1013 if(!is_object_instance(obj))
1014 return throw_type_error(ctx->script, JS_E_INVALID_PROPERTY, NULL);
1016 hres = disp_call_value(ctx->script, get_object(obj), NULL, DISPATCH_METHOD, argn, stack_args(ctx, argn),
1017 do_ret ? &r : NULL);
1018 if(FAILED(hres))
1019 return hres;
1021 stack_popn(ctx, argn+1);
1022 return do_ret ? stack_push(ctx, r) : S_OK;
1025 /* ECMA-262 3rd Edition 11.2.3 */
1026 static HRESULT interp_call_member(exec_ctx_t *ctx)
1028 const unsigned argn = get_op_uint(ctx, 0);
1029 const int do_ret = get_op_int(ctx, 1);
1030 IDispatch *obj;
1031 jsval_t r;
1032 DISPID id;
1033 HRESULT hres;
1035 TRACE("%d %d\n", argn, do_ret);
1037 obj = stack_topn_objid(ctx, argn, &id);
1038 if(!obj)
1039 return throw_type_error(ctx->script, id, NULL);
1041 hres = disp_call(ctx->script, obj, id, DISPATCH_METHOD, argn, stack_args(ctx, argn), do_ret ? &r : NULL);
1042 if(FAILED(hres))
1043 return hres;
1045 stack_popn(ctx, argn+2);
1046 return do_ret ? stack_push(ctx, r) : S_OK;
1050 /* ECMA-262 3rd Edition 11.1.1 */
1051 static HRESULT interp_this(exec_ctx_t *ctx)
1053 TRACE("\n");
1055 IDispatch_AddRef(ctx->this_obj);
1056 return stack_push(ctx, jsval_disp(ctx->this_obj));
1059 /* ECMA-262 3rd Edition 10.1.4 */
1060 static HRESULT interp_ident(exec_ctx_t *ctx)
1062 const BSTR arg = get_op_bstr(ctx, 0);
1063 exprval_t exprval;
1064 jsval_t v;
1065 HRESULT hres;
1067 TRACE("%s\n", debugstr_w(arg));
1069 hres = identifier_eval(ctx->script, arg, &exprval);
1070 if(FAILED(hres))
1071 return hres;
1073 if(exprval.type == EXPRVAL_INVALID)
1074 return throw_type_error(ctx->script, JS_E_UNDEFINED_VARIABLE, arg);
1076 hres = exprval_to_value(ctx->script, &exprval, &v);
1077 exprval_release(&exprval);
1078 if(FAILED(hres))
1079 return hres;
1081 return stack_push(ctx, v);
1084 /* ECMA-262 3rd Edition 10.1.4 */
1085 static HRESULT interp_identid(exec_ctx_t *ctx)
1087 const BSTR arg = get_op_bstr(ctx, 0);
1088 const unsigned flags = get_op_uint(ctx, 1);
1089 exprval_t exprval;
1090 HRESULT hres;
1092 TRACE("%s %x\n", debugstr_w(arg), flags);
1094 hres = identifier_eval(ctx->script, arg, &exprval);
1095 if(FAILED(hres))
1096 return hres;
1098 if(exprval.type == EXPRVAL_INVALID && (flags & fdexNameEnsure)) {
1099 DISPID id;
1101 hres = jsdisp_get_id(ctx->script->global, arg, fdexNameEnsure, &id);
1102 if(FAILED(hres))
1103 return hres;
1105 exprval_set_idref(&exprval, to_disp(ctx->script->global), id);
1108 if(exprval.type != EXPRVAL_IDREF) {
1109 WARN("invalid ref\n");
1110 exprval_release(&exprval);
1111 return stack_push_objid(ctx, NULL, JS_E_OBJECT_EXPECTED);
1114 return stack_push_objid(ctx, exprval.u.idref.disp, exprval.u.idref.id);
1117 /* ECMA-262 3rd Edition 7.8.1 */
1118 static HRESULT interp_null(exec_ctx_t *ctx)
1120 TRACE("\n");
1122 return stack_push(ctx, jsval_null());
1125 /* ECMA-262 3rd Edition 7.8.2 */
1126 static HRESULT interp_bool(exec_ctx_t *ctx)
1128 const int arg = get_op_int(ctx, 0);
1130 TRACE("%s\n", arg ? "true" : "false");
1132 return stack_push(ctx, jsval_bool(arg));
1135 /* ECMA-262 3rd Edition 7.8.3 */
1136 static HRESULT interp_int(exec_ctx_t *ctx)
1138 const int arg = get_op_int(ctx, 0);
1140 TRACE("%d\n", arg);
1142 return stack_push(ctx, jsval_number(arg));
1145 /* ECMA-262 3rd Edition 7.8.3 */
1146 static HRESULT interp_double(exec_ctx_t *ctx)
1148 const double arg = get_op_double(ctx);
1150 TRACE("%lf\n", arg);
1152 return stack_push(ctx, jsval_number(arg));
1155 /* ECMA-262 3rd Edition 7.8.4 */
1156 static HRESULT interp_str(exec_ctx_t *ctx)
1158 jsstr_t *str = get_op_str(ctx, 0);
1160 TRACE("%s\n", debugstr_jsstr(str));
1162 return stack_push(ctx, jsval_string(jsstr_addref(str)));
1165 /* ECMA-262 3rd Edition 7.8 */
1166 static HRESULT interp_regexp(exec_ctx_t *ctx)
1168 jsstr_t *source = get_op_str(ctx, 0);
1169 const unsigned flags = get_op_uint(ctx, 1);
1170 jsdisp_t *regexp;
1171 HRESULT hres;
1173 TRACE("%s %x\n", debugstr_jsstr(source), flags);
1175 hres = create_regexp(ctx->script, source, flags, &regexp);
1176 if(FAILED(hres))
1177 return hres;
1179 return stack_push(ctx, jsval_obj(regexp));
1182 /* ECMA-262 3rd Edition 11.1.4 */
1183 static HRESULT interp_carray(exec_ctx_t *ctx)
1185 const unsigned arg = get_op_uint(ctx, 0);
1186 jsdisp_t *array;
1187 jsval_t val;
1188 unsigned i;
1189 HRESULT hres;
1191 TRACE("%u\n", arg);
1193 hres = create_array(ctx->script, arg, &array);
1194 if(FAILED(hres))
1195 return hres;
1197 i = arg;
1198 while(i--) {
1199 val = stack_pop(ctx);
1200 hres = jsdisp_propput_idx(array, i, val);
1201 jsval_release(val);
1202 if(FAILED(hres)) {
1203 jsdisp_release(array);
1204 return hres;
1208 return stack_push(ctx, jsval_obj(array));
1211 /* ECMA-262 3rd Edition 11.1.5 */
1212 static HRESULT interp_new_obj(exec_ctx_t *ctx)
1214 jsdisp_t *obj;
1215 HRESULT hres;
1217 TRACE("\n");
1219 hres = create_object(ctx->script, NULL, &obj);
1220 if(FAILED(hres))
1221 return hres;
1223 return stack_push(ctx, jsval_obj(obj));
1226 /* ECMA-262 3rd Edition 11.1.5 */
1227 static HRESULT interp_obj_prop(exec_ctx_t *ctx)
1229 const BSTR name = get_op_bstr(ctx, 0);
1230 jsdisp_t *obj;
1231 jsval_t val;
1232 HRESULT hres;
1234 TRACE("%s\n", debugstr_w(name));
1236 val = stack_pop(ctx);
1238 assert(is_object_instance(stack_top(ctx)));
1239 obj = as_jsdisp(get_object(stack_top(ctx)));
1241 hres = jsdisp_propput_name(obj, name, val);
1242 jsval_release(val);
1243 return hres;
1246 /* ECMA-262 3rd Edition 11.11 */
1247 static HRESULT interp_cnd_nz(exec_ctx_t *ctx)
1249 const unsigned arg = get_op_uint(ctx, 0);
1250 BOOL b;
1251 HRESULT hres;
1253 TRACE("\n");
1255 hres = to_boolean(stack_top(ctx), &b);
1256 if(FAILED(hres))
1257 return hres;
1259 if(b) {
1260 ctx->ip = arg;
1261 }else {
1262 stack_popn(ctx, 1);
1263 ctx->ip++;
1265 return S_OK;
1268 /* ECMA-262 3rd Edition 11.11 */
1269 static HRESULT interp_cnd_z(exec_ctx_t *ctx)
1271 const unsigned arg = get_op_uint(ctx, 0);
1272 BOOL b;
1273 HRESULT hres;
1275 TRACE("\n");
1277 hres = to_boolean(stack_top(ctx), &b);
1278 if(FAILED(hres))
1279 return hres;
1281 if(b) {
1282 stack_popn(ctx, 1);
1283 ctx->ip++;
1284 }else {
1285 ctx->ip = arg;
1287 return S_OK;
1290 /* ECMA-262 3rd Edition 11.10 */
1291 static HRESULT interp_or(exec_ctx_t *ctx)
1293 INT l, r;
1294 HRESULT hres;
1296 TRACE("\n");
1298 hres = stack_pop_int(ctx, &r);
1299 if(FAILED(hres))
1300 return hres;
1302 hres = stack_pop_int(ctx, &l);
1303 if(FAILED(hres))
1304 return hres;
1306 return stack_push(ctx, jsval_number(l|r));
1309 /* ECMA-262 3rd Edition 11.10 */
1310 static HRESULT interp_xor(exec_ctx_t *ctx)
1312 INT l, r;
1313 HRESULT hres;
1315 TRACE("\n");
1317 hres = stack_pop_int(ctx, &r);
1318 if(FAILED(hres))
1319 return hres;
1321 hres = stack_pop_int(ctx, &l);
1322 if(FAILED(hres))
1323 return hres;
1325 return stack_push(ctx, jsval_number(l^r));
1328 /* ECMA-262 3rd Edition 11.10 */
1329 static HRESULT interp_and(exec_ctx_t *ctx)
1331 INT l, r;
1332 HRESULT hres;
1334 TRACE("\n");
1336 hres = stack_pop_int(ctx, &r);
1337 if(FAILED(hres))
1338 return hres;
1340 hres = stack_pop_int(ctx, &l);
1341 if(FAILED(hres))
1342 return hres;
1344 return stack_push(ctx, jsval_number(l&r));
1347 /* ECMA-262 3rd Edition 11.8.6 */
1348 static HRESULT interp_instanceof(exec_ctx_t *ctx)
1350 jsdisp_t *obj, *iter, *tmp = NULL;
1351 jsval_t prot, v;
1352 BOOL ret = FALSE;
1353 HRESULT hres;
1355 static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
1357 v = stack_pop(ctx);
1358 if(!is_object_instance(v) || !get_object(v)) {
1359 jsval_release(v);
1360 return throw_type_error(ctx->script, JS_E_FUNCTION_EXPECTED, NULL);
1363 obj = iface_to_jsdisp((IUnknown*)get_object(v));
1364 IDispatch_Release(get_object(v));
1365 if(!obj) {
1366 FIXME("non-jsdisp objects not supported\n");
1367 return E_FAIL;
1370 if(is_class(obj, JSCLASS_FUNCTION)) {
1371 hres = jsdisp_propget_name(obj, prototypeW, &prot);
1372 }else {
1373 hres = throw_type_error(ctx->script, JS_E_FUNCTION_EXPECTED, NULL);
1375 jsdisp_release(obj);
1376 if(FAILED(hres))
1377 return hres;
1379 v = stack_pop(ctx);
1381 if(is_object_instance(prot)) {
1382 if(is_object_instance(v))
1383 tmp = iface_to_jsdisp((IUnknown*)get_object(v));
1384 for(iter = tmp; !ret && iter; iter = iter->prototype) {
1385 hres = disp_cmp(get_object(prot), to_disp(iter), &ret);
1386 if(FAILED(hres))
1387 break;
1390 if(tmp)
1391 jsdisp_release(tmp);
1392 }else {
1393 FIXME("prototype is not an object\n");
1394 hres = E_FAIL;
1397 jsval_release(prot);
1398 jsval_release(v);
1399 if(FAILED(hres))
1400 return hres;
1402 return stack_push(ctx, jsval_bool(ret));
1405 /* ECMA-262 3rd Edition 11.8.7 */
1406 static HRESULT interp_in(exec_ctx_t *ctx)
1408 const WCHAR *str;
1409 jsstr_t *jsstr;
1410 jsval_t obj, v;
1411 DISPID id = 0;
1412 BOOL ret;
1413 HRESULT hres;
1415 TRACE("\n");
1417 obj = stack_pop(ctx);
1418 if(!is_object_instance(obj) || !get_object(obj)) {
1419 jsval_release(obj);
1420 return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL);
1423 v = stack_pop(ctx);
1424 hres = to_flat_string(ctx->script, v, &jsstr, &str);
1425 jsval_release(v);
1426 if(FAILED(hres)) {
1427 IDispatch_Release(get_object(obj));
1428 return hres;
1431 hres = disp_get_id(ctx->script, get_object(obj), str, NULL, 0, &id);
1432 IDispatch_Release(get_object(obj));
1433 jsstr_release(jsstr);
1434 if(SUCCEEDED(hres))
1435 ret = TRUE;
1436 else if(hres == DISP_E_UNKNOWNNAME)
1437 ret = FALSE;
1438 else
1439 return hres;
1441 return stack_push(ctx, jsval_bool(ret));
1444 /* ECMA-262 3rd Edition 11.6.1 */
1445 static HRESULT add_eval(script_ctx_t *ctx, jsval_t lval, jsval_t rval, jsval_t *ret)
1447 jsval_t r, l;
1448 HRESULT hres;
1450 hres = to_primitive(ctx, lval, &l, NO_HINT);
1451 if(FAILED(hres))
1452 return hres;
1454 hres = to_primitive(ctx, rval, &r, NO_HINT);
1455 if(FAILED(hres)) {
1456 jsval_release(l);
1457 return hres;
1460 if(is_string(l) || is_string(r)) {
1461 jsstr_t *lstr, *rstr = NULL;
1463 hres = to_string(ctx, l, &lstr);
1464 if(SUCCEEDED(hres))
1465 hres = to_string(ctx, r, &rstr);
1467 if(SUCCEEDED(hres)) {
1468 jsstr_t *ret_str;
1470 ret_str = jsstr_concat(lstr, rstr);
1471 if(ret_str)
1472 *ret = jsval_string(ret_str);
1473 else
1474 hres = E_OUTOFMEMORY;
1477 jsstr_release(lstr);
1478 if(rstr)
1479 jsstr_release(rstr);
1480 }else {
1481 double nl, nr;
1483 hres = to_number(ctx, l, &nl);
1484 if(SUCCEEDED(hres)) {
1485 hres = to_number(ctx, r, &nr);
1486 if(SUCCEEDED(hres))
1487 *ret = jsval_number(nl+nr);
1491 jsval_release(r);
1492 jsval_release(l);
1493 return hres;
1496 /* ECMA-262 3rd Edition 11.6.1 */
1497 static HRESULT interp_add(exec_ctx_t *ctx)
1499 jsval_t l, r, ret;
1500 HRESULT hres;
1502 r = stack_pop(ctx);
1503 l = stack_pop(ctx);
1505 TRACE("%s + %s\n", debugstr_jsval(l), debugstr_jsval(r));
1507 hres = add_eval(ctx->script, l, r, &ret);
1508 jsval_release(l);
1509 jsval_release(r);
1510 if(FAILED(hres))
1511 return hres;
1513 return stack_push(ctx, ret);
1516 /* ECMA-262 3rd Edition 11.6.2 */
1517 static HRESULT interp_sub(exec_ctx_t *ctx)
1519 double l, r;
1520 HRESULT hres;
1522 TRACE("\n");
1524 hres = stack_pop_number(ctx, &r);
1525 if(FAILED(hres))
1526 return hres;
1528 hres = stack_pop_number(ctx, &l);
1529 if(FAILED(hres))
1530 return hres;
1532 return stack_push(ctx, jsval_number(l-r));
1535 /* ECMA-262 3rd Edition 11.5.1 */
1536 static HRESULT interp_mul(exec_ctx_t *ctx)
1538 double l, r;
1539 HRESULT hres;
1541 TRACE("\n");
1543 hres = stack_pop_number(ctx, &r);
1544 if(FAILED(hres))
1545 return hres;
1547 hres = stack_pop_number(ctx, &l);
1548 if(FAILED(hres))
1549 return hres;
1551 return stack_push(ctx, jsval_number(l*r));
1554 /* ECMA-262 3rd Edition 11.5.2 */
1555 static HRESULT interp_div(exec_ctx_t *ctx)
1557 double l, r;
1558 HRESULT hres;
1560 TRACE("\n");
1562 hres = stack_pop_number(ctx, &r);
1563 if(FAILED(hres))
1564 return hres;
1566 hres = stack_pop_number(ctx, &l);
1567 if(FAILED(hres))
1568 return hres;
1570 return stack_push(ctx, jsval_number(l/r));
1573 /* ECMA-262 3rd Edition 11.5.3 */
1574 static HRESULT interp_mod(exec_ctx_t *ctx)
1576 double l, r;
1577 HRESULT hres;
1579 TRACE("\n");
1581 hres = stack_pop_number(ctx, &r);
1582 if(FAILED(hres))
1583 return hres;
1585 hres = stack_pop_number(ctx, &l);
1586 if(FAILED(hres))
1587 return hres;
1589 return stack_push(ctx, jsval_number(fmod(l, r)));
1592 /* ECMA-262 3rd Edition 11.4.2 */
1593 static HRESULT interp_delete(exec_ctx_t *ctx)
1595 jsval_t objv, namev;
1596 IDispatch *obj;
1597 jsstr_t *name;
1598 BOOL ret;
1599 HRESULT hres;
1601 TRACE("\n");
1603 namev = stack_pop(ctx);
1604 objv = stack_pop(ctx);
1606 hres = to_object(ctx->script, objv, &obj);
1607 jsval_release(objv);
1608 if(FAILED(hres)) {
1609 jsval_release(namev);
1610 return hres;
1613 hres = to_string(ctx->script, namev, &name);
1614 jsval_release(namev);
1615 if(FAILED(hres)) {
1616 IDispatch_Release(obj);
1617 return hres;
1620 hres = disp_delete_name(ctx->script, obj, name, &ret);
1621 IDispatch_Release(obj);
1622 jsstr_release(name);
1623 if(FAILED(hres))
1624 return hres;
1626 return stack_push(ctx, jsval_bool(ret));
1629 /* ECMA-262 3rd Edition 11.4.2 */
1630 static HRESULT interp_delete_ident(exec_ctx_t *ctx)
1632 const BSTR arg = get_op_bstr(ctx, 0);
1633 exprval_t exprval;
1634 BOOL ret;
1635 HRESULT hres;
1637 TRACE("%s\n", debugstr_w(arg));
1639 hres = identifier_eval(ctx->script, arg, &exprval);
1640 if(FAILED(hres))
1641 return hres;
1643 switch(exprval.type) {
1644 case EXPRVAL_IDREF:
1645 hres = disp_delete(exprval.u.idref.disp, exprval.u.idref.id, &ret);
1646 IDispatch_Release(exprval.u.idref.disp);
1647 if(FAILED(hres))
1648 return ret;
1649 break;
1650 case EXPRVAL_INVALID:
1651 ret = TRUE;
1652 break;
1653 default:
1654 FIXME("Unsupported exprval\n");
1655 exprval_release(&exprval);
1656 return E_NOTIMPL;
1660 return stack_push(ctx, jsval_bool(ret));
1663 /* ECMA-262 3rd Edition 11.4.2 */
1664 static HRESULT interp_void(exec_ctx_t *ctx)
1666 TRACE("\n");
1668 stack_popn(ctx, 1);
1669 return stack_push(ctx, jsval_undefined());
1672 /* ECMA-262 3rd Edition 11.4.3 */
1673 static HRESULT typeof_string(jsval_t v, const WCHAR **ret)
1675 switch(jsval_type(v)) {
1676 case JSV_UNDEFINED:
1677 *ret = undefinedW;
1678 break;
1679 case JSV_NULL:
1680 *ret = objectW;
1681 break;
1682 case JSV_OBJECT: {
1683 jsdisp_t *dispex;
1685 if(get_object(v) && (dispex = iface_to_jsdisp((IUnknown*)get_object(v)))) {
1686 *ret = is_class(dispex, JSCLASS_FUNCTION) ? functionW : objectW;
1687 jsdisp_release(dispex);
1688 }else {
1689 *ret = objectW;
1691 break;
1693 case JSV_STRING:
1694 *ret = stringW;
1695 break;
1696 case JSV_NUMBER:
1697 *ret = numberW;
1698 break;
1699 case JSV_BOOL:
1700 *ret = booleanW;
1701 break;
1702 case JSV_VARIANT:
1703 FIXME("unhandled variant %s\n", debugstr_variant(get_variant(v)));
1704 return E_NOTIMPL;
1707 return S_OK;
1710 /* ECMA-262 3rd Edition 11.4.3 */
1711 static HRESULT interp_typeofid(exec_ctx_t *ctx)
1713 const WCHAR *ret;
1714 IDispatch *obj;
1715 jsval_t v;
1716 DISPID id;
1717 HRESULT hres;
1719 TRACE("\n");
1721 obj = stack_pop_objid(ctx, &id);
1722 if(!obj)
1723 return stack_push(ctx, jsval_string(jsstr_undefined()));
1725 hres = disp_propget(ctx->script, obj, id, &v);
1726 IDispatch_Release(obj);
1727 if(FAILED(hres))
1728 return stack_push_string(ctx, unknownW);
1730 hres = typeof_string(v, &ret);
1731 jsval_release(v);
1732 if(FAILED(hres))
1733 return hres;
1735 return stack_push_string(ctx, ret);
1738 /* ECMA-262 3rd Edition 11.4.3 */
1739 static HRESULT interp_typeofident(exec_ctx_t *ctx)
1741 const BSTR arg = get_op_bstr(ctx, 0);
1742 exprval_t exprval;
1743 const WCHAR *ret;
1744 jsval_t v;
1745 HRESULT hres;
1747 TRACE("%s\n", debugstr_w(arg));
1749 hres = identifier_eval(ctx->script, arg, &exprval);
1750 if(FAILED(hres))
1751 return hres;
1753 if(exprval.type == EXPRVAL_INVALID) {
1754 hres = stack_push(ctx, jsval_string(jsstr_undefined()));
1755 exprval_release(&exprval);
1756 return hres;
1759 hres = exprval_to_value(ctx->script, &exprval, &v);
1760 exprval_release(&exprval);
1761 if(FAILED(hres))
1762 return hres;
1764 hres = typeof_string(v, &ret);
1765 jsval_release(v);
1766 if(FAILED(hres))
1767 return hres;
1769 return stack_push_string(ctx, ret);
1772 /* ECMA-262 3rd Edition 11.4.3 */
1773 static HRESULT interp_typeof(exec_ctx_t *ctx)
1775 const WCHAR *ret;
1776 jsval_t v;
1777 HRESULT hres;
1779 TRACE("\n");
1781 v = stack_pop(ctx);
1782 hres = typeof_string(v, &ret);
1783 jsval_release(v);
1784 if(FAILED(hres))
1785 return hres;
1787 return stack_push_string(ctx, ret);
1790 /* ECMA-262 3rd Edition 11.4.7 */
1791 static HRESULT interp_minus(exec_ctx_t *ctx)
1793 double n;
1794 HRESULT hres;
1796 TRACE("\n");
1798 hres = stack_pop_number(ctx, &n);
1799 if(FAILED(hres))
1800 return hres;
1802 return stack_push(ctx, jsval_number(-n));
1805 /* ECMA-262 3rd Edition 11.4.6 */
1806 static HRESULT interp_tonum(exec_ctx_t *ctx)
1808 jsval_t v;
1809 double n;
1810 HRESULT hres;
1812 TRACE("\n");
1814 v = stack_pop(ctx);
1815 hres = to_number(ctx->script, v, &n);
1816 jsval_release(v);
1817 if(FAILED(hres))
1818 return hres;
1820 return stack_push(ctx, jsval_number(n));
1823 /* ECMA-262 3rd Edition 11.3.1 */
1824 static HRESULT interp_postinc(exec_ctx_t *ctx)
1826 const int arg = get_op_int(ctx, 0);
1827 IDispatch *obj;
1828 DISPID id;
1829 jsval_t v;
1830 HRESULT hres;
1832 TRACE("%d\n", arg);
1834 obj = stack_pop_objid(ctx, &id);
1835 if(!obj)
1836 return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL);
1838 hres = disp_propget(ctx->script, obj, id, &v);
1839 if(SUCCEEDED(hres)) {
1840 double n;
1842 hres = to_number(ctx->script, v, &n);
1843 if(SUCCEEDED(hres))
1844 hres = disp_propput(ctx->script, obj, id, jsval_number(n+(double)arg));
1845 if(FAILED(hres))
1846 jsval_release(v);
1848 IDispatch_Release(obj);
1849 if(FAILED(hres))
1850 return hres;
1852 return stack_push(ctx, v);
1855 /* ECMA-262 3rd Edition 11.4.4, 11.4.5 */
1856 static HRESULT interp_preinc(exec_ctx_t *ctx)
1858 const int arg = get_op_int(ctx, 0);
1859 IDispatch *obj;
1860 double ret;
1861 DISPID id;
1862 jsval_t v;
1863 HRESULT hres;
1865 TRACE("%d\n", arg);
1867 obj = stack_pop_objid(ctx, &id);
1868 if(!obj)
1869 return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL);
1871 hres = disp_propget(ctx->script, obj, id, &v);
1872 if(SUCCEEDED(hres)) {
1873 double n;
1875 hres = to_number(ctx->script, v, &n);
1876 jsval_release(v);
1877 if(SUCCEEDED(hres)) {
1878 ret = n+(double)arg;
1879 hres = disp_propput(ctx->script, obj, id, jsval_number(ret));
1882 IDispatch_Release(obj);
1883 if(FAILED(hres))
1884 return hres;
1886 return stack_push(ctx, jsval_number(ret));
1889 /* ECMA-262 3rd Edition 11.9.3 */
1890 static HRESULT equal_values(script_ctx_t *ctx, jsval_t lval, jsval_t rval, BOOL *ret)
1892 if(jsval_type(lval) == jsval_type(rval) || (is_number(lval) && is_number(rval)))
1893 return equal2_values(lval, rval, ret);
1895 /* FIXME: NULL disps should be handled in more general way */
1896 if(is_object_instance(lval) && !get_object(lval))
1897 return equal_values(ctx, jsval_null(), rval, ret);
1898 if(is_object_instance(rval) && !get_object(rval))
1899 return equal_values(ctx, lval, jsval_null(), ret);
1901 if((is_null(lval) && is_undefined(rval)) || (is_undefined(lval) && is_null(rval))) {
1902 *ret = TRUE;
1903 return S_OK;
1906 if(is_string(lval) && is_number(rval)) {
1907 double n;
1908 HRESULT hres;
1910 hres = to_number(ctx, lval, &n);
1911 if(FAILED(hres))
1912 return hres;
1914 /* FIXME: optimize */
1915 return equal_values(ctx, jsval_number(n), rval, ret);
1918 if(is_string(rval) && is_number(lval)) {
1919 double n;
1920 HRESULT hres;
1922 hres = to_number(ctx, rval, &n);
1923 if(FAILED(hres))
1924 return hres;
1926 /* FIXME: optimize */
1927 return equal_values(ctx, lval, jsval_number(n), ret);
1930 if(is_bool(rval))
1931 return equal_values(ctx, lval, jsval_number(get_bool(rval) ? 1 : 0), ret);
1933 if(is_bool(lval))
1934 return equal_values(ctx, jsval_number(get_bool(lval) ? 1 : 0), rval, ret);
1937 if(is_object_instance(rval) && (is_string(lval) || is_number(lval))) {
1938 jsval_t prim;
1939 HRESULT hres;
1941 hres = to_primitive(ctx, rval, &prim, NO_HINT);
1942 if(FAILED(hres))
1943 return hres;
1945 hres = equal_values(ctx, lval, prim, ret);
1946 jsval_release(prim);
1947 return hres;
1951 if(is_object_instance(lval) && (is_string(rval) || is_number(rval))) {
1952 jsval_t prim;
1953 HRESULT hres;
1955 hres = to_primitive(ctx, lval, &prim, NO_HINT);
1956 if(FAILED(hres))
1957 return hres;
1959 hres = equal_values(ctx, prim, rval, ret);
1960 jsval_release(prim);
1961 return hres;
1965 *ret = FALSE;
1966 return S_OK;
1969 /* ECMA-262 3rd Edition 11.9.1 */
1970 static HRESULT interp_eq(exec_ctx_t *ctx)
1972 jsval_t l, r;
1973 BOOL b;
1974 HRESULT hres;
1976 r = stack_pop(ctx);
1977 l = stack_pop(ctx);
1979 TRACE("%s == %s\n", debugstr_jsval(l), debugstr_jsval(r));
1981 hres = equal_values(ctx->script, l, r, &b);
1982 jsval_release(l);
1983 jsval_release(r);
1984 if(FAILED(hres))
1985 return hres;
1987 return stack_push(ctx, jsval_bool(b));
1990 /* ECMA-262 3rd Edition 11.9.2 */
1991 static HRESULT interp_neq(exec_ctx_t *ctx)
1993 jsval_t l, r;
1994 BOOL b;
1995 HRESULT hres;
1997 r = stack_pop(ctx);
1998 l = stack_pop(ctx);
2000 TRACE("%s != %s\n", debugstr_jsval(l), debugstr_jsval(r));
2002 hres = equal_values(ctx->script, l, r, &b);
2003 jsval_release(l);
2004 jsval_release(r);
2005 if(FAILED(hres))
2006 return hres;
2008 return stack_push(ctx, jsval_bool(!b));
2011 /* ECMA-262 3rd Edition 11.9.4 */
2012 static HRESULT interp_eq2(exec_ctx_t *ctx)
2014 jsval_t l, r;
2015 BOOL b;
2016 HRESULT hres;
2018 r = stack_pop(ctx);
2019 l = stack_pop(ctx);
2021 TRACE("%s === %s\n", debugstr_jsval(l), debugstr_jsval(r));
2023 hres = equal2_values(r, l, &b);
2024 jsval_release(l);
2025 jsval_release(r);
2026 if(FAILED(hres))
2027 return hres;
2029 return stack_push(ctx, jsval_bool(b));
2032 /* ECMA-262 3rd Edition 11.9.5 */
2033 static HRESULT interp_neq2(exec_ctx_t *ctx)
2035 jsval_t l, r;
2036 BOOL b;
2037 HRESULT hres;
2039 TRACE("\n");
2041 r = stack_pop(ctx);
2042 l = stack_pop(ctx);
2044 hres = equal2_values(r, l, &b);
2045 jsval_release(l);
2046 jsval_release(r);
2047 if(FAILED(hres))
2048 return hres;
2050 return stack_push(ctx, jsval_bool(!b));
2053 /* ECMA-262 3rd Edition 11.8.5 */
2054 static HRESULT less_eval(script_ctx_t *ctx, jsval_t lval, jsval_t rval, BOOL greater, BOOL *ret)
2056 double ln, rn;
2057 jsval_t l, r;
2058 HRESULT hres;
2060 hres = to_primitive(ctx, lval, &l, NO_HINT);
2061 if(FAILED(hres))
2062 return hres;
2064 hres = to_primitive(ctx, rval, &r, NO_HINT);
2065 if(FAILED(hres)) {
2066 jsval_release(l);
2067 return hres;
2070 if(is_string(l) && is_string(r)) {
2071 *ret = (jsstr_cmp(get_string(l), get_string(r)) < 0) ^ greater;
2072 jsstr_release(get_string(l));
2073 jsstr_release(get_string(r));
2074 return S_OK;
2077 hres = to_number(ctx, l, &ln);
2078 jsval_release(l);
2079 if(SUCCEEDED(hres))
2080 hres = to_number(ctx, r, &rn);
2081 jsval_release(r);
2082 if(FAILED(hres))
2083 return hres;
2085 *ret = !isnan(ln) && !isnan(rn) && ((ln < rn) ^ greater);
2086 return S_OK;
2089 /* ECMA-262 3rd Edition 11.8.1 */
2090 static HRESULT interp_lt(exec_ctx_t *ctx)
2092 jsval_t l, r;
2093 BOOL b;
2094 HRESULT hres;
2096 r = stack_pop(ctx);
2097 l = stack_pop(ctx);
2099 TRACE("%s < %s\n", debugstr_jsval(l), debugstr_jsval(r));
2101 hres = less_eval(ctx->script, l, r, FALSE, &b);
2102 jsval_release(l);
2103 jsval_release(r);
2104 if(FAILED(hres))
2105 return hres;
2107 return stack_push(ctx, jsval_bool(b));
2110 /* ECMA-262 3rd Edition 11.8.1 */
2111 static HRESULT interp_lteq(exec_ctx_t *ctx)
2113 jsval_t l, r;
2114 BOOL b;
2115 HRESULT hres;
2117 r = stack_pop(ctx);
2118 l = stack_pop(ctx);
2120 TRACE("%s <= %s\n", debugstr_jsval(l), debugstr_jsval(r));
2122 hres = less_eval(ctx->script, r, l, TRUE, &b);
2123 jsval_release(l);
2124 jsval_release(r);
2125 if(FAILED(hres))
2126 return hres;
2128 return stack_push(ctx, jsval_bool(b));
2131 /* ECMA-262 3rd Edition 11.8.2 */
2132 static HRESULT interp_gt(exec_ctx_t *ctx)
2134 jsval_t l, r;
2135 BOOL b;
2136 HRESULT hres;
2138 r = stack_pop(ctx);
2139 l = stack_pop(ctx);
2141 TRACE("%s > %s\n", debugstr_jsval(l), debugstr_jsval(r));
2143 hres = less_eval(ctx->script, r, l, FALSE, &b);
2144 jsval_release(l);
2145 jsval_release(r);
2146 if(FAILED(hres))
2147 return hres;
2149 return stack_push(ctx, jsval_bool(b));
2152 /* ECMA-262 3rd Edition 11.8.4 */
2153 static HRESULT interp_gteq(exec_ctx_t *ctx)
2155 jsval_t l, r;
2156 BOOL b;
2157 HRESULT hres;
2159 r = stack_pop(ctx);
2160 l = stack_pop(ctx);
2162 TRACE("%s >= %s\n", debugstr_jsval(l), debugstr_jsval(r));
2164 hres = less_eval(ctx->script, l, r, TRUE, &b);
2165 jsval_release(l);
2166 jsval_release(r);
2167 if(FAILED(hres))
2168 return hres;
2170 return stack_push(ctx, jsval_bool(b));
2173 /* ECMA-262 3rd Edition 11.4.8 */
2174 static HRESULT interp_bneg(exec_ctx_t *ctx)
2176 jsval_t v;
2177 INT i;
2178 HRESULT hres;
2180 TRACE("\n");
2182 v = stack_pop(ctx);
2183 hres = to_int32(ctx->script, v, &i);
2184 jsval_release(v);
2185 if(FAILED(hres))
2186 return hres;
2188 return stack_push(ctx, jsval_number(~i));
2191 /* ECMA-262 3rd Edition 11.4.9 */
2192 static HRESULT interp_neg(exec_ctx_t *ctx)
2194 jsval_t v;
2195 BOOL b;
2196 HRESULT hres;
2198 TRACE("\n");
2200 v = stack_pop(ctx);
2201 hres = to_boolean(v, &b);
2202 jsval_release(v);
2203 if(FAILED(hres))
2204 return hres;
2206 return stack_push(ctx, jsval_bool(!b));
2209 /* ECMA-262 3rd Edition 11.7.1 */
2210 static HRESULT interp_lshift(exec_ctx_t *ctx)
2212 DWORD r;
2213 INT l;
2214 HRESULT hres;
2216 hres = stack_pop_uint(ctx, &r);
2217 if(FAILED(hres))
2218 return hres;
2220 hres = stack_pop_int(ctx, &l);
2221 if(FAILED(hres))
2222 return hres;
2224 return stack_push(ctx, jsval_number(l << (r&0x1f)));
2227 /* ECMA-262 3rd Edition 11.7.2 */
2228 static HRESULT interp_rshift(exec_ctx_t *ctx)
2230 DWORD r;
2231 INT l;
2232 HRESULT hres;
2234 hres = stack_pop_uint(ctx, &r);
2235 if(FAILED(hres))
2236 return hres;
2238 hres = stack_pop_int(ctx, &l);
2239 if(FAILED(hres))
2240 return hres;
2242 return stack_push(ctx, jsval_number(l >> (r&0x1f)));
2245 /* ECMA-262 3rd Edition 11.7.3 */
2246 static HRESULT interp_rshift2(exec_ctx_t *ctx)
2248 DWORD r, l;
2249 HRESULT hres;
2251 hres = stack_pop_uint(ctx, &r);
2252 if(FAILED(hres))
2253 return hres;
2255 hres = stack_pop_uint(ctx, &l);
2256 if(FAILED(hres))
2257 return hres;
2259 return stack_push(ctx, jsval_number(l >> (r&0x1f)));
2262 /* ECMA-262 3rd Edition 11.13.1 */
2263 static HRESULT interp_assign(exec_ctx_t *ctx)
2265 IDispatch *disp;
2266 DISPID id;
2267 jsval_t v;
2268 HRESULT hres;
2270 TRACE("\n");
2272 v = stack_pop(ctx);
2274 disp = stack_pop_objid(ctx, &id);
2275 if(!disp) {
2276 jsval_release(v);
2277 return throw_reference_error(ctx->script, JS_E_ILLEGAL_ASSIGN, NULL);
2280 hres = disp_propput(ctx->script, disp, id, v);
2281 IDispatch_Release(disp);
2282 if(FAILED(hres)) {
2283 jsval_release(v);
2284 return hres;
2287 return stack_push(ctx, v);
2290 /* JScript extension */
2291 static HRESULT interp_assign_call(exec_ctx_t *ctx)
2293 const unsigned argc = get_op_uint(ctx, 0);
2294 IDispatch *disp;
2295 jsval_t v;
2296 DISPID id;
2297 HRESULT hres;
2299 TRACE("%u\n", argc);
2301 disp = stack_topn_objid(ctx, argc+1, &id);
2302 if(!disp)
2303 return throw_reference_error(ctx->script, JS_E_ILLEGAL_ASSIGN, NULL);
2305 hres = disp_call(ctx->script, disp, id, DISPATCH_PROPERTYPUT, argc+1, stack_args(ctx, argc+1), NULL);
2306 if(FAILED(hres))
2307 return hres;
2309 v = stack_pop(ctx);
2310 stack_popn(ctx, argc+2);
2311 return stack_push(ctx, v);
2314 static HRESULT interp_undefined(exec_ctx_t *ctx)
2316 TRACE("\n");
2318 return stack_push(ctx, jsval_undefined());
2321 static HRESULT interp_jmp(exec_ctx_t *ctx)
2323 const unsigned arg = get_op_uint(ctx, 0);
2325 TRACE("%u\n", arg);
2327 ctx->ip = arg;
2328 return S_OK;
2331 static HRESULT interp_jmp_z(exec_ctx_t *ctx)
2333 const unsigned arg = get_op_uint(ctx, 0);
2334 BOOL b;
2335 jsval_t v;
2336 HRESULT hres;
2338 TRACE("\n");
2340 v = stack_pop(ctx);
2341 hres = to_boolean(v, &b);
2342 jsval_release(v);
2343 if(FAILED(hres))
2344 return hres;
2346 if(b)
2347 ctx->ip++;
2348 else
2349 ctx->ip = arg;
2350 return S_OK;
2353 static HRESULT interp_pop(exec_ctx_t *ctx)
2355 const unsigned arg = get_op_uint(ctx, 0);
2357 TRACE("%u\n", arg);
2359 stack_popn(ctx, arg);
2360 return S_OK;
2363 static HRESULT interp_ret(exec_ctx_t *ctx)
2365 TRACE("\n");
2367 ctx->ip = -1;
2368 return S_OK;
2371 static HRESULT interp_setret(exec_ctx_t *ctx)
2373 TRACE("\n");
2375 jsval_release(ctx->ret);
2376 ctx->ret = stack_pop(ctx);
2377 return S_OK;
2380 typedef HRESULT (*op_func_t)(exec_ctx_t*);
2382 static const op_func_t op_funcs[] = {
2383 #define X(x,a,b,c) interp_##x,
2384 OP_LIST
2385 #undef X
2388 static const unsigned op_move[] = {
2389 #define X(a,x,b,c) x,
2390 OP_LIST
2391 #undef X
2394 static HRESULT unwind_exception(exec_ctx_t *ctx)
2396 except_frame_t *except_frame;
2397 jsval_t except_val;
2398 BSTR ident;
2399 HRESULT hres;
2401 except_frame = ctx->except_frame;
2402 ctx->except_frame = except_frame->next;
2404 assert(except_frame->stack_top <= ctx->top);
2405 stack_popn(ctx, ctx->top - except_frame->stack_top);
2407 while(except_frame->scope != ctx->scope_chain)
2408 scope_pop(&ctx->scope_chain);
2410 ctx->ip = except_frame->catch_off;
2412 except_val = ctx->script->ei.val;
2413 ctx->script->ei.val = jsval_undefined();
2414 clear_ei(ctx->script);
2416 ident = except_frame->ident;
2417 heap_free(except_frame);
2419 if(ident) {
2420 jsdisp_t *scope_obj;
2422 hres = create_dispex(ctx->script, NULL, NULL, &scope_obj);
2423 if(SUCCEEDED(hres)) {
2424 hres = jsdisp_propput_name(scope_obj, ident, except_val);
2425 if(FAILED(hres))
2426 jsdisp_release(scope_obj);
2428 jsval_release(except_val);
2429 if(FAILED(hres))
2430 return hres;
2432 hres = scope_push(ctx->scope_chain, scope_obj, to_disp(scope_obj), &ctx->scope_chain);
2433 jsdisp_release(scope_obj);
2434 }else {
2435 hres = stack_push(ctx, except_val);
2436 if(FAILED(hres))
2437 return hres;
2439 hres = stack_push(ctx, jsval_bool(FALSE));
2442 return hres;
2445 static HRESULT enter_bytecode(script_ctx_t *ctx, bytecode_t *code, function_code_t *func, jsval_t *ret)
2447 exec_ctx_t *exec_ctx = ctx->exec_ctx;
2448 except_frame_t *prev_except_frame;
2449 function_code_t *prev_func;
2450 unsigned prev_ip, prev_top;
2451 scope_chain_t *prev_scope;
2452 bytecode_t *prev_code;
2453 jsop_t op;
2454 HRESULT hres = S_OK;
2456 TRACE("\n");
2458 prev_top = exec_ctx->top;
2459 prev_scope = exec_ctx->scope_chain;
2460 prev_except_frame = exec_ctx->except_frame;
2461 prev_ip = exec_ctx->ip;
2462 prev_code = exec_ctx->code;
2463 prev_func = exec_ctx->func_code;
2464 exec_ctx->ip = func->instr_off;
2465 exec_ctx->except_frame = NULL;
2466 exec_ctx->code = code;
2467 exec_ctx->func_code = func;
2469 while(exec_ctx->ip != -1) {
2470 op = code->instrs[exec_ctx->ip].op;
2471 hres = op_funcs[op](exec_ctx);
2472 if(FAILED(hres)) {
2473 TRACE("EXCEPTION %08x\n", hres);
2475 if(!exec_ctx->except_frame)
2476 break;
2478 hres = unwind_exception(exec_ctx);
2479 if(FAILED(hres))
2480 break;
2481 }else {
2482 exec_ctx->ip += op_move[op];
2486 exec_ctx->ip = prev_ip;
2487 exec_ctx->except_frame = prev_except_frame;
2488 exec_ctx->code = prev_code;
2489 exec_ctx->func_code = prev_func;
2491 if(FAILED(hres)) {
2492 while(exec_ctx->scope_chain != prev_scope)
2493 scope_pop(&exec_ctx->scope_chain);
2494 stack_popn(exec_ctx, exec_ctx->top-prev_top);
2495 return hres;
2498 assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top);
2499 assert(exec_ctx->scope_chain == prev_scope);
2500 assert(exec_ctx->top == prev_top);
2502 *ret = exec_ctx->ret;
2503 exec_ctx->ret = jsval_undefined();
2504 return S_OK;
2507 HRESULT exec_source(exec_ctx_t *ctx, bytecode_t *code, function_code_t *func, BOOL from_eval, jsval_t *ret)
2509 exec_ctx_t *prev_ctx;
2510 jsval_t val;
2511 unsigned i;
2512 HRESULT hres = S_OK;
2514 for(i = 0; i < func->func_cnt; i++) {
2515 jsdisp_t *func_obj;
2517 if(!func->funcs[i].name)
2518 continue;
2520 hres = create_source_function(ctx->script, code, func->funcs+i, ctx->scope_chain, &func_obj);
2521 if(FAILED(hres))
2522 return hres;
2524 hres = jsdisp_propput_name(ctx->var_disp, func->funcs[i].name, jsval_obj(func_obj));
2525 jsdisp_release(func_obj);
2526 if(FAILED(hres))
2527 return hres;
2530 for(i=0; i < func->var_cnt; i++) {
2531 if(!ctx->is_global || !lookup_global_members(ctx->script, func->variables[i], NULL)) {
2532 DISPID id = 0;
2534 hres = jsdisp_get_id(ctx->var_disp, func->variables[i], fdexNameEnsure, &id);
2535 if(FAILED(hres))
2536 return hres;
2540 prev_ctx = ctx->script->exec_ctx;
2541 ctx->script->exec_ctx = ctx;
2543 hres = enter_bytecode(ctx->script, code, func, &val);
2544 assert(ctx->script->exec_ctx == ctx);
2545 ctx->script->exec_ctx = prev_ctx;
2546 if(FAILED(hres))
2547 return hres;
2549 if(ret)
2550 *ret = val;
2551 else
2552 jsval_release(val);
2553 return S_OK;