jscript: Always use bytecode for for statement.
[wine] / dlls / jscript / engine.c
1 /*
2  * Copyright 2008 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20 #include "wine/port.h"
21
22 #include <math.h>
23 #include <assert.h>
24
25 #include "jscript.h"
26 #include "engine.h"
27
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
31
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};
39
40 struct _return_type_t {
41     enum{
42         RT_NORMAL,
43         RT_RETURN,
44         RT_BREAK,
45         RT_CONTINUE
46     } type;
47     jsexcept_t ei;
48 };
49
50 struct _except_frame_t {
51     unsigned stack_top;
52     scope_chain_t *scope;
53     unsigned catch_off;
54     BSTR ident;
55
56     except_frame_t *next;
57 };
58
59 static inline HRESULT stat_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
60 {
61     return stat->eval(ctx, stat, rt, ret);
62 }
63
64 static HRESULT expr_eval(script_ctx_t*,expression_t*,jsexcept_t*,VARIANT*);
65
66 static HRESULT stack_push(exec_ctx_t *ctx, VARIANT *v)
67 {
68     if(!ctx->stack_size) {
69         ctx->stack = heap_alloc(16*sizeof(VARIANT));
70         if(!ctx->stack)
71             return E_OUTOFMEMORY;
72         ctx->stack_size = 16;
73     }else if(ctx->stack_size == ctx->top) {
74         VARIANT *new_stack;
75
76         new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(VARIANT));
77         if(!new_stack) {
78             VariantClear(v);
79             return E_OUTOFMEMORY;
80         }
81
82         ctx->stack = new_stack;
83         ctx->stack_size *= 2;
84     }
85
86     ctx->stack[ctx->top++] = *v;
87     return S_OK;
88 }
89
90 static HRESULT stack_push_bool(exec_ctx_t *ctx, BOOL b)
91 {
92     VARIANT v;
93
94     V_VT(&v) = VT_BOOL;
95     V_BOOL(&v) = b ? VARIANT_TRUE : VARIANT_FALSE;
96     return stack_push(ctx, &v);
97 }
98
99 static inline HRESULT stack_push_number(exec_ctx_t *ctx, double number)
100 {
101     VARIANT v;
102
103     num_set_val(&v, number);
104     return stack_push(ctx, &v);
105 }
106
107 static inline HRESULT stack_push_int(exec_ctx_t *ctx, INT n)
108 {
109     VARIANT v;
110
111     V_VT(&v) = VT_I4;
112     V_I4(&v) = n;
113     return stack_push(ctx, &v);
114 }
115
116 static inline HRESULT stack_push_string(exec_ctx_t *ctx, const WCHAR *str)
117 {
118     VARIANT v;
119
120     V_VT(&v) = VT_BSTR;
121     V_BSTR(&v) = SysAllocString(str);
122     return V_BSTR(&v) ? stack_push(ctx, &v) : E_OUTOFMEMORY;
123 }
124
125 static HRESULT stack_push_objid(exec_ctx_t *ctx, IDispatch *disp, DISPID id)
126 {
127     VARIANT v;
128     HRESULT hres;
129
130     V_VT(&v) = VT_DISPATCH;
131     V_DISPATCH(&v) = disp;
132     hres = stack_push(ctx, &v);
133     if(FAILED(hres))
134         return hres;
135
136     V_VT(&v) = VT_INT;
137     V_INT(&v) = id;
138     return stack_push(ctx, &v);
139 }
140
141 static inline VARIANT *stack_top(exec_ctx_t *ctx)
142 {
143     assert(ctx->top);
144     return ctx->stack + ctx->top-1;
145 }
146
147 static inline VARIANT *stack_topn(exec_ctx_t *ctx, unsigned n)
148 {
149     assert(ctx->top > n);
150     return ctx->stack + ctx->top-1-n;
151 }
152
153 static inline VARIANT *stack_pop(exec_ctx_t *ctx)
154 {
155     assert(ctx->top);
156     return ctx->stack + --ctx->top;
157 }
158
159 static void stack_popn(exec_ctx_t *ctx, unsigned n)
160 {
161     while(n--)
162         VariantClear(stack_pop(ctx));
163 }
164
165 static HRESULT stack_pop_number(exec_ctx_t *ctx, VARIANT *r)
166 {
167     VARIANT *v;
168     HRESULT hres;
169
170     v = stack_pop(ctx);
171     hres = to_number(ctx->parser->script, v, ctx->ei, r);
172     VariantClear(v);
173     return hres;
174 }
175
176 static HRESULT stack_pop_object(exec_ctx_t *ctx, IDispatch **r)
177 {
178     VARIANT *v;
179     HRESULT hres;
180
181     v = stack_pop(ctx);
182     if(V_VT(v) == VT_DISPATCH) {
183         if(!V_DISPATCH(v))
184             return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_REQUIRED, NULL);
185         *r = V_DISPATCH(v);
186         return S_OK;
187     }
188
189     hres = to_object(ctx->parser->script, v, r);
190     VariantClear(v);
191     return hres;
192 }
193
194 static inline HRESULT stack_pop_int(exec_ctx_t *ctx, INT *r)
195 {
196     return to_int32(ctx->parser->script, stack_pop(ctx), ctx->ei, r);
197 }
198
199 static inline HRESULT stack_pop_uint(exec_ctx_t *ctx, DWORD *r)
200 {
201     return to_uint32(ctx->parser->script, stack_pop(ctx), ctx->ei, r);
202 }
203
204 static inline IDispatch *stack_pop_objid(exec_ctx_t *ctx, DISPID *id)
205 {
206     assert(V_VT(stack_top(ctx)) == VT_INT && V_VT(stack_topn(ctx, 1)) == VT_DISPATCH);
207
208     *id = V_INT(stack_pop(ctx));
209     return V_DISPATCH(stack_pop(ctx));
210 }
211
212 static inline IDispatch *stack_topn_objid(exec_ctx_t *ctx, unsigned n, DISPID *id)
213 {
214     assert(V_VT(stack_topn(ctx, n)) == VT_INT && V_VT(stack_topn(ctx, n+1)) == VT_DISPATCH);
215
216     *id = V_INT(stack_topn(ctx, n));
217     return V_DISPATCH(stack_topn(ctx, n+1));
218 }
219
220 static void exprval_release(exprval_t *val)
221 {
222     switch(val->type) {
223     case EXPRVAL_VARIANT:
224         if(V_VT(&val->u.var) != VT_EMPTY)
225             VariantClear(&val->u.var);
226         return;
227     case EXPRVAL_IDREF:
228         if(val->u.idref.disp)
229             IDispatch_Release(val->u.idref.disp);
230         return;
231     case EXPRVAL_INVALID:
232         return;
233     }
234 }
235
236 /* ECMA-262 3rd Edition    8.7.1 */
237 static HRESULT exprval_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
238 {
239     V_VT(ret) = VT_EMPTY;
240
241     switch(val->type) {
242     case EXPRVAL_VARIANT:
243         return VariantCopy(ret, &val->u.var);
244     case EXPRVAL_IDREF:
245         if(!val->u.idref.disp) {
246             FIXME("throw ReferenceError\n");
247             return E_FAIL;
248         }
249
250         return disp_propget(ctx, val->u.idref.disp, val->u.idref.id, ret, ei, NULL/*FIXME*/);
251     case EXPRVAL_INVALID:
252         assert(0);
253     }
254
255     ERR("type %d\n", val->type);
256     return E_FAIL;
257 }
258
259 static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
260 {
261     if(val->type == EXPRVAL_VARIANT) {
262         *ret = val->u.var;
263         V_VT(&val->u.var) = VT_EMPTY;
264         return S_OK;
265     }
266
267     return exprval_value(ctx, val, ei, ret);
268 }
269
270 static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id)
271 {
272     val->type = EXPRVAL_IDREF;
273     val->u.idref.disp = disp;
274     val->u.idref.id = id;
275
276     if(disp)
277         IDispatch_AddRef(disp);
278 }
279
280 HRESULT scope_push(scope_chain_t *scope, jsdisp_t *obj, scope_chain_t **ret)
281 {
282     scope_chain_t *new_scope;
283
284     new_scope = heap_alloc(sizeof(scope_chain_t));
285     if(!new_scope)
286         return E_OUTOFMEMORY;
287
288     new_scope->ref = 1;
289
290     jsdisp_addref(obj);
291     new_scope->obj = obj;
292
293     if(scope) {
294         scope_addref(scope);
295         new_scope->next = scope;
296     }else {
297         new_scope->next = NULL;
298     }
299
300     *ret = new_scope;
301     return S_OK;
302 }
303
304 static void scope_pop(scope_chain_t **scope)
305 {
306     scope_chain_t *tmp;
307
308     tmp = *scope;
309     *scope = tmp->next;
310     scope_release(tmp);
311 }
312
313 void scope_release(scope_chain_t *scope)
314 {
315     if(--scope->ref)
316         return;
317
318     if(scope->next)
319         scope_release(scope->next);
320
321     jsdisp_release(scope->obj);
322     heap_free(scope);
323 }
324
325 HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, jsdisp_t *var_disp,
326         scope_chain_t *scope, BOOL is_global, exec_ctx_t **ret)
327 {
328     exec_ctx_t *ctx;
329
330     ctx = heap_alloc_zero(sizeof(exec_ctx_t));
331     if(!ctx)
332         return E_OUTOFMEMORY;
333
334     ctx->ref = 1;
335     ctx->is_global = is_global;
336
337     if(this_obj)
338         ctx->this_obj = this_obj;
339     else if(script_ctx->host_global)
340         ctx->this_obj = script_ctx->host_global;
341     else
342         ctx->this_obj = to_disp(script_ctx->global);
343     IDispatch_AddRef(ctx->this_obj);
344
345     jsdisp_addref(var_disp);
346     ctx->var_disp = var_disp;
347
348     if(scope) {
349         scope_addref(scope);
350         ctx->scope_chain = scope;
351     }
352
353     *ret = ctx;
354     return S_OK;
355 }
356
357 void exec_release(exec_ctx_t *ctx)
358 {
359     if(--ctx->ref)
360         return;
361
362     if(ctx->scope_chain)
363         scope_release(ctx->scope_chain);
364     if(ctx->var_disp)
365         jsdisp_release(ctx->var_disp);
366     if(ctx->this_obj)
367         IDispatch_Release(ctx->this_obj);
368     heap_free(ctx->stack);
369     heap_free(ctx);
370 }
371
372 static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
373 {
374     IDispatchEx *dispex;
375     HRESULT hres;
376
377     hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
378     if(FAILED(hres)) {
379         TRACE("unsing IDispatch\n");
380
381         *id = 0;
382         return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
383     }
384
385     *id = 0;
386     hres = IDispatchEx_GetDispID(dispex, name, make_grfdex(ctx, flags|fdexNameCaseSensitive), id);
387     IDispatchEx_Release(dispex);
388     return hres;
389 }
390
391 static inline BOOL is_null(const VARIANT *v)
392 {
393     return V_VT(v) == VT_NULL || (V_VT(v) == VT_DISPATCH && !V_DISPATCH(v));
394 }
395
396 static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret)
397 {
398     IObjectIdentity *identity;
399     IUnknown *unk1, *unk2;
400     HRESULT hres;
401
402     if(disp1 == disp2) {
403         *ret = TRUE;
404         return S_OK;
405     }
406
407     if(!disp1 || !disp2) {
408         *ret = FALSE;
409         return S_OK;
410     }
411
412     hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1);
413     if(FAILED(hres))
414         return hres;
415
416     hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2);
417     if(FAILED(hres)) {
418         IUnknown_Release(unk1);
419         return hres;
420     }
421
422     if(unk1 == unk2) {
423         *ret = TRUE;
424     }else {
425         hres = IUnknown_QueryInterface(unk1, &IID_IObjectIdentity, (void**)&identity);
426         if(SUCCEEDED(hres)) {
427             hres = IObjectIdentity_IsEqualObject(identity, unk2);
428             IObjectIdentity_Release(identity);
429             *ret = hres == S_OK;
430         }else {
431             *ret = FALSE;
432         }
433     }
434
435     IUnknown_Release(unk1);
436     IUnknown_Release(unk2);
437     return S_OK;
438 }
439
440 /* ECMA-262 3rd Edition    11.9.6 */
441 static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
442 {
443     TRACE("\n");
444
445     if(V_VT(lval) != V_VT(rval)) {
446         if(is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval)))
447             *ret = num_val(lval) == num_val(rval);
448         else if(is_null(lval))
449             *ret = is_null(rval);
450         else
451             *ret = FALSE;
452         return S_OK;
453     }
454
455     switch(V_VT(lval)) {
456     case VT_EMPTY:
457     case VT_NULL:
458         *ret = VARIANT_TRUE;
459         break;
460     case VT_I4:
461         *ret = V_I4(lval) == V_I4(rval);
462         break;
463     case VT_R8:
464         *ret = V_R8(lval) == V_R8(rval);
465         break;
466     case VT_BSTR:
467         if(!V_BSTR(lval))
468             *ret = SysStringLen(V_BSTR(rval))?FALSE:TRUE;
469         else if(!V_BSTR(rval))
470             *ret = SysStringLen(V_BSTR(lval))?FALSE:TRUE;
471         else
472             *ret = !strcmpW(V_BSTR(lval), V_BSTR(rval));
473         break;
474     case VT_DISPATCH:
475         return disp_cmp(V_DISPATCH(lval), V_DISPATCH(rval), ret);
476     case VT_BOOL:
477         *ret = !V_BOOL(lval) == !V_BOOL(rval);
478         break;
479     default:
480         FIXME("unimplemented vt %d\n", V_VT(lval));
481         return E_NOTIMPL;
482     }
483
484     return S_OK;
485 }
486
487 static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
488 {
489     named_item_t *item;
490     DISPID id;
491     HRESULT hres;
492
493     for(item = ctx->named_items; item; item = item->next) {
494         if(item->flags & SCRIPTITEM_GLOBALMEMBERS) {
495             hres = disp_get_id(ctx, item->disp, identifier, 0, &id);
496             if(SUCCEEDED(hres)) {
497                 if(ret)
498                     exprval_set_idref(ret, item->disp, id);
499                 return TRUE;
500             }
501         }
502     }
503
504     return FALSE;
505 }
506
507 HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, BOOL from_eval,
508         jsexcept_t *ei, VARIANT *retv)
509 {
510     script_ctx_t *script = parser->script;
511     function_declaration_t *func;
512     parser_ctx_t *prev_parser;
513     var_list_t *var;
514     VARIANT val;
515     exec_ctx_t *prev_ctx;
516     return_type_t rt;
517     HRESULT hres = S_OK;
518
519     for(func = source->functions; func; func = func->next) {
520         jsdisp_t *func_obj;
521         VARIANT var;
522
523         hres = create_source_function(parser, func->expr->parameter_list, func->expr->source_elements,
524                 ctx->scope_chain, func->expr->src_str, func->expr->src_len, &func_obj);
525         if(FAILED(hres))
526             return hres;
527
528         var_set_jsdisp(&var, func_obj);
529         hres = jsdisp_propput_name(ctx->var_disp, func->expr->identifier, &var, ei, NULL);
530         jsdisp_release(func_obj);
531         if(FAILED(hres))
532             return hres;
533     }
534
535     for(var = source->variables; var; var = var->next) {
536         DISPID id = 0;
537         BSTR name;
538
539         name = SysAllocString(var->identifier);
540         if(!name)
541             return E_OUTOFMEMORY;
542
543         if(!ctx->is_global || !lookup_global_members(parser->script, name, NULL))
544             hres = jsdisp_get_id(ctx->var_disp, var->identifier, fdexNameEnsure, &id);
545         SysFreeString(name);
546         if(FAILED(hres))
547             return hres;
548     }
549
550     prev_ctx = script->exec_ctx;
551     script->exec_ctx = ctx;
552
553     prev_parser = ctx->parser;
554     ctx->parser = parser;
555
556     V_VT(&val) = VT_EMPTY;
557     memset(&rt, 0, sizeof(rt));
558     rt.type = RT_NORMAL;
559
560     if(source->statement) {
561         if(source->statement->instr_off == -1)
562             hres = compile_subscript_stat(ctx->parser, source->statement, TRUE, &source->statement->instr_off);
563         if(SUCCEEDED(hres))
564             hres = compiled_statement_eval(script, source->statement, &rt, &val);
565     }
566
567     script->exec_ctx = prev_ctx;
568     ctx->parser = prev_parser;
569
570     if(rt.type != RT_NORMAL && rt.type != RT_RETURN) {
571         FIXME("wrong rt %d\n", rt.type);
572         hres = E_FAIL;
573     }
574
575     *ei = rt.ei;
576     if(FAILED(hres)) {
577         VariantClear(&val);
578         return hres;
579     }
580
581     if(!retv || (!from_eval && rt.type != RT_RETURN))
582         VariantClear(&val);
583     if(retv)
584         *retv = val;
585     return S_OK;
586 }
587
588 /* ECMA-262 3rd Edition    10.1.4 */
589 static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, DWORD flags, jsexcept_t *ei, exprval_t *ret)
590 {
591     scope_chain_t *scope;
592     named_item_t *item;
593     DISPID id = 0;
594     HRESULT hres;
595
596     TRACE("%s\n", debugstr_w(identifier));
597
598     for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) {
599         hres = jsdisp_get_id(scope->obj, identifier, 0, &id);
600         if(SUCCEEDED(hres)) {
601             exprval_set_idref(ret, to_disp(scope->obj), id);
602             return S_OK;
603         }
604     }
605
606     hres = jsdisp_get_id(ctx->global, identifier, 0, &id);
607     if(SUCCEEDED(hres)) {
608         exprval_set_idref(ret, to_disp(ctx->global), id);
609         return S_OK;
610     }
611
612     for(item = ctx->named_items; item; item = item->next) {
613         if((item->flags & SCRIPTITEM_ISVISIBLE) && !strcmpW(item->name, identifier)) {
614             if(!item->disp) {
615                 IUnknown *unk;
616
617                 if(!ctx->site)
618                     break;
619
620                 hres = IActiveScriptSite_GetItemInfo(ctx->site, identifier,
621                                                      SCRIPTINFO_IUNKNOWN, &unk, NULL);
622                 if(FAILED(hres)) {
623                     WARN("GetItemInfo failed: %08x\n", hres);
624                     break;
625                 }
626
627                 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
628                 IUnknown_Release(unk);
629                 if(FAILED(hres)) {
630                     WARN("object does not implement IDispatch\n");
631                     break;
632                 }
633             }
634
635             ret->type = EXPRVAL_VARIANT;
636             V_VT(&ret->u.var) = VT_DISPATCH;
637             V_DISPATCH(&ret->u.var) = item->disp;
638             IDispatch_AddRef(item->disp);
639             return S_OK;
640         }
641     }
642
643     if(lookup_global_members(ctx, identifier, ret))
644         return S_OK;
645
646     if(flags & fdexNameEnsure) {
647         hres = jsdisp_get_id(ctx->global, identifier, fdexNameEnsure, &id);
648         if(FAILED(hres))
649             return hres;
650
651         exprval_set_idref(ret, to_disp(ctx->global), id);
652         return S_OK;
653     }
654
655     ret->type = EXPRVAL_INVALID;
656     return S_OK;
657 }
658
659 /* ECMA-262 3rd Edition    12.2 */
660 static HRESULT interp_var_set(exec_ctx_t *ctx)
661 {
662     const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
663     VARIANT *v;
664     HRESULT hres;
665
666     TRACE("%s\n", debugstr_w(name));
667
668     v = stack_pop(ctx);
669     hres = jsdisp_propput_name(ctx->var_disp, name, v, ctx->ei, NULL/*FIXME*/);
670     VariantClear(v);
671     return hres;
672 }
673
674 /* ECMA-262 3rd Edition    12.6.2 */
675 HRESULT while_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
676 {
677     while_statement_t *stat = (while_statement_t*)_stat;
678     VARIANT val, tmp;
679     VARIANT_BOOL b;
680     BOOL test_expr;
681     HRESULT hres;
682
683     TRACE("\n");
684
685     V_VT(&val) = VT_EMPTY;
686     test_expr = !stat->do_while;
687
688     while(1) {
689         if(test_expr) {
690             hres = expr_eval(ctx, stat->expr, &rt->ei, &tmp);
691             if(FAILED(hres))
692                 break;
693
694             hres = to_boolean(&tmp, &b);
695             VariantClear(&tmp);
696             if(FAILED(hres) || !b)
697                 break;
698         }else {
699             test_expr = TRUE;
700         }
701
702         hres = stat_eval(ctx, stat->statement, rt, &tmp);
703         if(FAILED(hres))
704             break;
705
706         VariantClear(&val);
707         val = tmp;
708
709         if(rt->type == RT_CONTINUE)
710             rt->type = RT_NORMAL;
711         if(rt->type != RT_NORMAL)
712             break;
713     }
714
715     if(FAILED(hres)) {
716         VariantClear(&val);
717         return hres;
718     }
719
720     if(rt->type == RT_BREAK)
721         rt->type = RT_NORMAL;
722
723     *ret = val;
724     return S_OK;
725 }
726
727 /* ECMA-262 3rd Edition    12.6.4 */
728 static HRESULT interp_forin(exec_ctx_t *ctx)
729 {
730     const HRESULT arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
731     IDispatch *var_obj, *obj = NULL;
732     IDispatchEx *dispex;
733     DISPID id, var_id;
734     BSTR name = NULL;
735     VARIANT *val;
736     HRESULT hres;
737
738     TRACE("\n");
739
740     val = stack_pop(ctx);
741
742     assert(V_VT(stack_top(ctx)) == VT_I4);
743     id = V_I4(stack_top(ctx));
744
745     var_obj = stack_topn_objid(ctx, 1, &var_id);
746     if(!var_obj) {
747         FIXME("invalid ref\n");
748         VariantClear(val);
749         return E_FAIL;
750     }
751
752     if(V_VT(stack_topn(ctx, 3)) == VT_DISPATCH)
753         obj = V_DISPATCH(stack_topn(ctx, 3));
754
755     if(obj) {
756         hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
757         if(SUCCEEDED(hres)) {
758             hres = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, id, &id);
759             if(hres == S_OK)
760                 hres = IDispatchEx_GetMemberName(dispex, id, &name);
761             IDispatchEx_Release(dispex);
762             if(FAILED(hres)) {
763                 VariantClear(val);
764                 return hres;
765             }
766         }else {
767             TRACE("No IDispatchEx\n");
768         }
769     }
770
771     if(name) {
772         VARIANT v;
773
774         VariantClear(val);
775
776         V_I4(stack_top(ctx)) = id;
777
778         V_VT(&v) = VT_BSTR;
779         V_BSTR(&v) = name;
780         hres = disp_propput(ctx->parser->script, var_obj, var_id, &v, ctx->ei, NULL/*FIXME*/);
781         SysFreeString(name);
782         if(FAILED(hres))
783             return hres;
784
785         ctx->ip++;
786     }else {
787         stack_popn(ctx, 4);
788         ctx->ip = arg;
789         return stack_push(ctx, val);
790     }
791     return S_OK;
792 }
793
794 /* ECMA-262 3rd Edition    12.7 */
795 HRESULT continue_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
796 {
797     branch_statement_t *stat = (branch_statement_t*)_stat;
798
799     TRACE("\n");
800
801     if(stat->identifier) {
802         FIXME("indentifier not implemented\n");
803         return E_NOTIMPL;
804     }
805
806     rt->type = RT_CONTINUE;
807     V_VT(ret) = VT_EMPTY;
808     return S_OK;
809 }
810
811 /* ECMA-262 3rd Edition    12.8 */
812 HRESULT break_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
813 {
814     branch_statement_t *stat = (branch_statement_t*)_stat;
815
816     TRACE("\n");
817
818     if(stat->identifier) {
819         FIXME("indentifier not implemented\n");
820         return E_NOTIMPL;
821     }
822
823     rt->type = RT_BREAK;
824     V_VT(ret) = VT_EMPTY;
825     return S_OK;
826 }
827
828 /* ECMA-262 3rd Edition    12.9 */
829 HRESULT return_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
830 {
831     expression_statement_t *stat = (expression_statement_t*)_stat;
832     HRESULT hres;
833
834     TRACE("\n");
835
836     if(stat->expr) {
837         hres = expr_eval(ctx, stat->expr, &rt->ei, ret);
838         if(FAILED(hres))
839             return hres;
840     }else {
841         V_VT(ret) = VT_EMPTY;
842     }
843
844     TRACE("= %s\n", debugstr_variant(ret));
845     rt->type = RT_RETURN;
846     return S_OK;
847 }
848
849 /* ECMA-262 3rd Edition    12.10 */
850 HRESULT interp_push_scope(exec_ctx_t *ctx)
851 {
852     IDispatch *disp;
853     jsdisp_t *obj;
854     VARIANT *v;
855     HRESULT hres;
856
857     TRACE("\n");
858
859     v = stack_pop(ctx);
860     hres = to_object(ctx->parser->script, v, &disp);
861     VariantClear(v);
862     if(FAILED(hres))
863         return hres;
864
865     obj = to_jsdisp(disp);
866     if(!obj) {
867         IDispatch_Release(disp);
868         FIXME("disp is not jsdisp\n");
869         return E_NOTIMPL;
870     }
871
872     hres = scope_push(ctx->scope_chain, obj, &ctx->scope_chain);
873     jsdisp_release(obj);
874     return hres;
875 }
876
877 /* ECMA-262 3rd Edition    12.10 */
878 HRESULT interp_pop_scope(exec_ctx_t *ctx)
879 {
880     TRACE("\n");
881
882     scope_pop(&ctx->scope_chain);
883     return S_OK;
884 }
885
886 /* ECMA-262 3rd Edition    12.12 */
887 HRESULT interp_label(exec_ctx_t *ctx)
888 {
889     FIXME("\n");
890     return E_NOTIMPL;
891 }
892
893 /* ECMA-262 3rd Edition    12.13 */
894 static HRESULT interp_case(exec_ctx_t *ctx)
895 {
896     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
897     VARIANT *v;
898     BOOL b;
899     HRESULT hres;
900
901     TRACE("\n");
902
903     v = stack_pop(ctx);
904     hres = equal2_values(stack_top(ctx), v, &b);
905     VariantClear(v);
906     if(FAILED(hres))
907         return hres;
908
909     if(b) {
910         stack_popn(ctx, 1);
911         ctx->ip = arg;
912     }else {
913         ctx->ip++;
914     }
915     return S_OK;
916 }
917
918 /* ECMA-262 3rd Edition    12.13 */
919 HRESULT switch_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
920 {
921     switch_statement_t *stat = (switch_statement_t*)_stat;
922     case_clausule_t *iter, *default_clausule = NULL;
923     statement_t *stat_iter;
924     VARIANT val, cval;
925     BOOL b;
926     HRESULT hres;
927
928     TRACE("\n");
929
930     hres = expr_eval(ctx, stat->expr, &rt->ei, &val);
931     if(FAILED(hres))
932         return hres;
933
934     for(iter = stat->case_list; iter; iter = iter->next) {
935         if(!iter->expr) {
936             default_clausule = iter;
937             continue;
938         }
939
940         hres = expr_eval(ctx, iter->expr, &rt->ei, &cval);
941         if(FAILED(hres))
942             break;
943
944         hres = equal2_values(&val, &cval, &b);
945         VariantClear(&cval);
946         if(FAILED(hres) || b)
947             break;
948     }
949
950     VariantClear(&val);
951     if(FAILED(hres))
952         return hres;
953
954     if(!iter)
955         iter = default_clausule;
956
957     V_VT(&val) = VT_EMPTY;
958     if(iter) {
959         VARIANT tmp;
960
961         for(stat_iter = iter->stat; stat_iter; stat_iter = stat_iter->next) {
962             hres = stat_eval(ctx, stat_iter, rt, &tmp);
963             if(FAILED(hres))
964                 break;
965
966             VariantClear(&val);
967             val = tmp;
968
969             if(rt->type != RT_NORMAL)
970                 break;
971         }
972     }
973
974     if(FAILED(hres)) {
975         VariantClear(&val);
976         return hres;
977     }
978
979     if(rt->type == RT_BREAK)
980         rt->type = RT_NORMAL;
981
982     *ret = val;
983     return S_OK;
984 }
985
986 /* ECMA-262 3rd Edition    12.13 */
987 static HRESULT interp_throw(exec_ctx_t *ctx)
988 {
989     TRACE("\n");
990
991     ctx->rt->ei.var = *stack_pop(ctx);
992     return DISP_E_EXCEPTION;
993 }
994
995 static HRESULT interp_throw_ref(exec_ctx_t *ctx)
996 {
997     const HRESULT arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
998
999     TRACE("%08x\n", arg);
1000
1001     return throw_reference_error(ctx->parser->script, ctx->ei, arg, NULL);
1002 }
1003
1004 static HRESULT interp_throw_type(exec_ctx_t *ctx)
1005 {
1006     const HRESULT hres = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1007     const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg2.str;
1008
1009     TRACE("%08x %s\n", hres, debugstr_w(str));
1010
1011     return throw_type_error(ctx->parser->script, ctx->ei, hres, str);
1012 }
1013
1014 /* ECMA-262 3rd Edition    12.14 */
1015 static HRESULT catch_eval(script_ctx_t *ctx, catch_block_t *block, return_type_t *rt, VARIANT *ret)
1016 {
1017     jsdisp_t *var_disp;
1018     VARIANT ex, val;
1019     HRESULT hres;
1020
1021     ex = rt->ei.var;
1022     memset(&rt->ei, 0, sizeof(jsexcept_t));
1023
1024     hres = create_dispex(ctx, NULL, NULL, &var_disp);
1025     if(SUCCEEDED(hres)) {
1026         hres = jsdisp_propput_name(var_disp, block->identifier, &ex, &rt->ei, NULL/*FIXME*/);
1027         if(SUCCEEDED(hres)) {
1028             hres = scope_push(ctx->exec_ctx->scope_chain, var_disp, &ctx->exec_ctx->scope_chain);
1029             if(SUCCEEDED(hres)) {
1030                 hres = stat_eval(ctx, block->statement, rt, &val);
1031                 scope_pop(&ctx->exec_ctx->scope_chain);
1032             }
1033         }
1034
1035         jsdisp_release(var_disp);
1036     }
1037
1038     VariantClear(&ex);
1039     if(FAILED(hres))
1040         return hres;
1041
1042     *ret = val;
1043     return S_OK;
1044 }
1045
1046 /* ECMA-262 3rd Edition    12.14 */
1047 HRESULT try_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1048 {
1049     try_statement_t *stat = (try_statement_t*)_stat;
1050     VARIANT val;
1051     HRESULT hres;
1052
1053     TRACE("\n");
1054
1055     hres = stat_eval(ctx, stat->try_statement, rt, &val);
1056     if(FAILED(hres)) {
1057         TRACE("EXCEPTION\n");
1058         if(!stat->catch_block)
1059             return hres;
1060
1061         hres = catch_eval(ctx, stat->catch_block, rt, &val);
1062         if(FAILED(hres))
1063             return hres;
1064     }
1065
1066     if(stat->finally_statement) {
1067         VariantClear(&val);
1068         hres = stat_eval(ctx, stat->finally_statement, rt, &val);
1069         if(FAILED(hres))
1070             return hres;
1071     }
1072
1073     *ret = val;
1074     return S_OK;
1075 }
1076
1077 /* ECMA-262 3rd Edition    12.14 */
1078 static HRESULT interp_push_except(exec_ctx_t *ctx)
1079 {
1080     const unsigned arg1 = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1081     const BSTR arg2 = ctx->parser->code->instrs[ctx->ip].arg2.bstr;
1082     except_frame_t *except;
1083     unsigned stack_top;
1084
1085     TRACE("\n");
1086
1087     stack_top = ctx->top;
1088
1089     if(!arg2) {
1090         HRESULT hres;
1091
1092         hres = stack_push_bool(ctx, TRUE);
1093         if(FAILED(hres))
1094             return hres;
1095         hres = stack_push_bool(ctx, TRUE);
1096         if(FAILED(hres))
1097             return hres;
1098     }
1099
1100     except = heap_alloc(sizeof(*except));
1101     if(!except)
1102         return E_OUTOFMEMORY;
1103
1104     except->stack_top = stack_top;
1105     except->scope = ctx->scope_chain;
1106     except->catch_off = arg1;
1107     except->ident = arg2;
1108     except->next = ctx->except_frame;
1109     ctx->except_frame = except;
1110     return S_OK;
1111 }
1112
1113 /* ECMA-262 3rd Edition    12.14 */
1114 static HRESULT interp_pop_except(exec_ctx_t *ctx)
1115 {
1116     except_frame_t *except;
1117
1118     TRACE("\n");
1119
1120     except = ctx->except_frame;
1121     assert(except != NULL);
1122
1123     ctx->except_frame = except->next;
1124     heap_free(except);
1125     return S_OK;
1126 }
1127
1128 /* ECMA-262 3rd Edition    12.14 */
1129 static HRESULT interp_end_finally(exec_ctx_t *ctx)
1130 {
1131     VARIANT *v;
1132
1133     TRACE("\n");
1134
1135     v = stack_pop(ctx);
1136
1137     assert(V_VT(stack_top(ctx)) == VT_BOOL);
1138     if(!V_BOOL(stack_top(ctx))) {
1139         TRACE("passing exception\n");
1140
1141         VariantClear(v);
1142         stack_popn(ctx, 1);
1143         ctx->rt->ei.var = *stack_pop(ctx);
1144         return DISP_E_EXCEPTION;
1145     }
1146
1147     stack_popn(ctx, 2);
1148     return stack_push(ctx, v);
1149 }
1150
1151 /* ECMA-262 3rd Edition    13 */
1152 static HRESULT interp_func(exec_ctx_t *ctx)
1153 {
1154     function_expression_t *expr = ctx->parser->code->instrs[ctx->ip].arg1.func;
1155     jsdisp_t *dispex;
1156     VARIANT v;
1157     HRESULT hres;
1158
1159     TRACE("\n");
1160
1161     hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain,
1162             expr->src_str, expr->src_len, &dispex);
1163     if(FAILED(hres))
1164         return hres;
1165
1166     var_set_jsdisp(&v, dispex);
1167     return stack_push(ctx, &v);
1168 }
1169
1170 /* ECMA-262 3rd Edition    11.2.1 */
1171 static HRESULT interp_array(exec_ctx_t *ctx)
1172 {
1173     VARIANT v, *namev;
1174     IDispatch *obj;
1175     DISPID id;
1176     BSTR name;
1177     HRESULT hres;
1178
1179     TRACE("\n");
1180
1181     namev = stack_pop(ctx);
1182
1183     hres = stack_pop_object(ctx, &obj);
1184     if(FAILED(hres)) {
1185         VariantClear(namev);
1186         return hres;
1187     }
1188
1189     hres = to_string(ctx->parser->script, namev, ctx->ei, &name);
1190     VariantClear(namev);
1191     if(FAILED(hres)) {
1192         IDispatch_Release(obj);
1193         return hres;
1194     }
1195
1196     hres = disp_get_id(ctx->parser->script, obj, name, 0, &id);
1197     SysFreeString(name);
1198     if(SUCCEEDED(hres)) {
1199         hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1200     }else if(hres == DISP_E_UNKNOWNNAME) {
1201         V_VT(&v) = VT_EMPTY;
1202         hres = S_OK;
1203     }
1204     IDispatch_Release(obj);
1205     if(FAILED(hres))
1206         return hres;
1207
1208     return stack_push(ctx, &v);
1209 }
1210
1211 /* ECMA-262 3rd Edition    11.2.1 */
1212 static HRESULT interp_member(exec_ctx_t *ctx)
1213 {
1214     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1215     IDispatch *obj;
1216     VARIANT v;
1217     DISPID id;
1218     HRESULT hres;
1219
1220     TRACE("\n");
1221
1222     hres = stack_pop_object(ctx, &obj);
1223     if(FAILED(hres))
1224         return hres;
1225
1226     hres = disp_get_id(ctx->parser->script, obj, arg, 0, &id);
1227     if(SUCCEEDED(hres)) {
1228         V_VT(&v) = VT_EMPTY;
1229         hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1230     }else if(hres == DISP_E_UNKNOWNNAME) {
1231         V_VT(&v) = VT_EMPTY;
1232         hres = S_OK;
1233     }
1234     IDispatch_Release(obj);
1235     if(FAILED(hres))
1236         return hres;
1237
1238     return stack_push(ctx, &v);
1239 }
1240
1241 /* ECMA-262 3rd Edition    11.2.1 */
1242 static HRESULT interp_memberid(exec_ctx_t *ctx)
1243 {
1244     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1245     VARIANT *objv, *namev;
1246     IDispatch *obj;
1247     BSTR name;
1248     DISPID id;
1249     HRESULT hres;
1250
1251     TRACE("%x\n", arg);
1252
1253     namev = stack_pop(ctx);
1254     objv = stack_pop(ctx);
1255
1256     hres = to_object(ctx->parser->script, objv, &obj);
1257     VariantClear(objv);
1258     if(SUCCEEDED(hres)) {
1259         hres = to_string(ctx->parser->script, namev, ctx->ei, &name);
1260         if(FAILED(hres))
1261             IDispatch_Release(obj);
1262     }
1263     VariantClear(namev);
1264     if(FAILED(hres))
1265         return hres;
1266
1267     hres = disp_get_id(ctx->parser->script, obj, name, arg, &id);
1268     SysFreeString(name);
1269     if(FAILED(hres)) {
1270         IDispatch_Release(obj);
1271         if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
1272             obj = NULL;
1273             id = JS_E_INVALID_PROPERTY;
1274         }else {
1275             return hres;
1276         }
1277     }
1278
1279     return stack_push_objid(ctx, obj, id);
1280 }
1281
1282 /* ECMA-262 3rd Edition    11.2.1 */
1283 static HRESULT interp_refval(exec_ctx_t *ctx)
1284 {
1285     IDispatch *disp;
1286     VARIANT v;
1287     DISPID id;
1288     HRESULT hres;
1289
1290     TRACE("\n");
1291
1292     disp = stack_topn_objid(ctx, 0, &id);
1293     if(!disp)
1294         return throw_reference_error(ctx->parser->script, ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
1295
1296     hres = disp_propget(ctx->parser->script, disp, id, &v, ctx->ei, NULL/*FIXME*/);
1297     if(FAILED(hres))
1298         return hres;
1299
1300     return stack_push(ctx, &v);
1301 }
1302
1303 static void jsstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, DISPPARAMS *dp)
1304 {
1305     VARIANT tmp;
1306     unsigned i;
1307
1308     dp->cArgs = arg_cnt;
1309     dp->rgdispidNamedArgs = NULL;
1310     dp->cNamedArgs = 0;
1311
1312     assert(ctx->top >= arg_cnt);
1313
1314     for(i=1; i*2 <= arg_cnt; i++) {
1315         tmp = ctx->stack[ctx->top-i];
1316         ctx->stack[ctx->top-i] = ctx->stack[ctx->top-arg_cnt+i-1];
1317         ctx->stack[ctx->top-arg_cnt+i-1] = tmp;
1318     }
1319
1320     dp->rgvarg = ctx->stack + ctx->top-arg_cnt;
1321 }
1322
1323 /* ECMA-262 3rd Edition    11.2.2 */
1324 static HRESULT interp_new(exec_ctx_t *ctx)
1325 {
1326     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1327     VARIANT *constr, v;
1328     DISPPARAMS dp;
1329     HRESULT hres;
1330
1331     TRACE("%d\n", arg);
1332
1333     constr = stack_topn(ctx, arg);
1334
1335     /* NOTE: Should use to_object here */
1336
1337     if(V_VT(constr) == VT_NULL)
1338         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1339     else if(V_VT(constr) != VT_DISPATCH)
1340         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_ACTION, NULL);
1341     else if(!V_DISPATCH(constr))
1342         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1343
1344     jsstack_to_dp(ctx, arg, &dp);
1345     hres = disp_call(ctx->parser->script, V_DISPATCH(constr), DISPID_VALUE,
1346             DISPATCH_CONSTRUCT, &dp, &v, ctx->ei, NULL/*FIXME*/);
1347     if(FAILED(hres))
1348         return hres;
1349
1350     stack_popn(ctx, arg+1);
1351     return stack_push(ctx, &v);
1352 }
1353
1354 /* ECMA-262 3rd Edition    11.2.3 */
1355 static HRESULT interp_call(exec_ctx_t *ctx)
1356 {
1357     const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1358     const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1359     VARIANT v, *objv;
1360     DISPPARAMS dp;
1361     HRESULT hres;
1362
1363     TRACE("%d %d\n", argn, do_ret);
1364
1365     objv = stack_topn(ctx, argn);
1366     if(V_VT(objv) != VT_DISPATCH)
1367         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1368
1369     jsstack_to_dp(ctx, argn, &dp);
1370     hres = disp_call(ctx->parser->script, V_DISPATCH(objv), DISPID_VALUE, DISPATCH_METHOD, &dp,
1371             do_ret ? &v : NULL, ctx->ei, NULL/*FIXME*/);
1372     if(FAILED(hres))
1373         return hres;
1374
1375     stack_popn(ctx, argn+1);
1376     return do_ret ? stack_push(ctx, &v) : S_OK;
1377
1378 }
1379
1380 /* ECMA-262 3rd Edition    11.2.3 */
1381 static HRESULT interp_call_member(exec_ctx_t *ctx)
1382 {
1383     const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1384     const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1385     IDispatch *obj;
1386     DISPPARAMS dp;
1387     VARIANT v;
1388     DISPID id;
1389     HRESULT hres;
1390
1391     TRACE("%d %d\n", argn, do_ret);
1392
1393     obj = stack_topn_objid(ctx, argn, &id);
1394     if(!obj)
1395         return throw_type_error(ctx->parser->script, ctx->ei, id, NULL);
1396
1397     jsstack_to_dp(ctx, argn, &dp);
1398     hres = disp_call(ctx->parser->script, obj, id, DISPATCH_METHOD, &dp, do_ret ? &v : NULL, ctx->ei, NULL/*FIXME*/);
1399     if(FAILED(hres))
1400         return hres;
1401
1402     stack_popn(ctx, argn+2);
1403     return do_ret ? stack_push(ctx, &v) : S_OK;
1404
1405 }
1406
1407 /* ECMA-262 3rd Edition    11.1.1 */
1408 static HRESULT interp_this(exec_ctx_t *ctx)
1409 {
1410     VARIANT v;
1411
1412     TRACE("\n");
1413
1414     V_VT(&v) = VT_DISPATCH;
1415     V_DISPATCH(&v) = ctx->this_obj;
1416     IDispatch_AddRef(ctx->this_obj);
1417     return stack_push(ctx, &v);
1418 }
1419
1420 /* ECMA-262 3rd Edition    10.1.4 */
1421 static HRESULT interp_ident(exec_ctx_t *ctx)
1422 {
1423     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1424     exprval_t exprval;
1425     VARIANT v;
1426     HRESULT hres;
1427
1428     TRACE("%s\n", debugstr_w(arg));
1429
1430     hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
1431     if(FAILED(hres))
1432         return hres;
1433
1434     if(exprval.type == EXPRVAL_INVALID)
1435         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_UNDEFINED_VARIABLE, arg);
1436
1437     hres = exprval_to_value(ctx->parser->script, &exprval, ctx->ei, &v);
1438     exprval_release(&exprval);
1439     if(FAILED(hres))
1440         return hres;
1441
1442     return stack_push(ctx, &v);
1443 }
1444
1445 /* ECMA-262 3rd Edition    10.1.4 */
1446 static HRESULT interp_identid(exec_ctx_t *ctx)
1447 {
1448     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1449     const unsigned flags = ctx->parser->code->instrs[ctx->ip].arg2.uint;
1450     exprval_t exprval;
1451     HRESULT hres;
1452
1453     TRACE("%s %x\n", debugstr_w(arg), flags);
1454
1455     hres = identifier_eval(ctx->parser->script, arg, flags, ctx->ei, &exprval);
1456     if(FAILED(hres))
1457         return hres;
1458
1459     if(exprval.type != EXPRVAL_IDREF) {
1460         WARN("invalid ref\n");
1461         exprval_release(&exprval);
1462         return stack_push_objid(ctx, NULL, JS_E_OBJECT_EXPECTED);
1463     }
1464
1465     return stack_push_objid(ctx, exprval.u.idref.disp, exprval.u.idref.id);
1466 }
1467
1468 /* ECMA-262 3rd Edition    7.8.1 */
1469 static HRESULT interp_null(exec_ctx_t *ctx)
1470 {
1471     VARIANT v;
1472
1473     TRACE("\n");
1474
1475     V_VT(&v) = VT_NULL;
1476     return stack_push(ctx, &v);
1477 }
1478
1479 /* ECMA-262 3rd Edition    7.8.2 */
1480 static HRESULT interp_bool(exec_ctx_t *ctx)
1481 {
1482     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1483
1484     TRACE("%s\n", arg ? "true" : "false");
1485
1486     return stack_push_bool(ctx, arg);
1487 }
1488
1489 /* ECMA-262 3rd Edition    7.8.3 */
1490 static HRESULT interp_int(exec_ctx_t *ctx)
1491 {
1492     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1493     VARIANT v;
1494
1495     TRACE("%d\n", arg);
1496
1497     V_VT(&v) = VT_I4;
1498     V_I4(&v) = arg;
1499     return stack_push(ctx, &v);
1500 }
1501
1502 /* ECMA-262 3rd Edition    7.8.3 */
1503 static HRESULT interp_double(exec_ctx_t *ctx)
1504 {
1505     const double arg = *ctx->parser->code->instrs[ctx->ip].arg1.dbl;
1506     VARIANT v;
1507
1508     TRACE("%lf\n", arg);
1509
1510     V_VT(&v) = VT_R8;
1511     V_R8(&v) = arg;
1512     return stack_push(ctx, &v);
1513 }
1514
1515 /* ECMA-262 3rd Edition    7.8.4 */
1516 static HRESULT interp_str(exec_ctx_t *ctx)
1517 {
1518     const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg1.str;
1519     VARIANT v;
1520
1521     TRACE("%s\n", debugstr_w(str));
1522
1523     V_VT(&v) = VT_BSTR;
1524     V_BSTR(&v) = SysAllocString(str);
1525     if(!V_BSTR(&v))
1526         return E_OUTOFMEMORY;
1527
1528     return stack_push(ctx, &v);
1529 }
1530
1531 /* ECMA-262 3rd Edition    7.8 */
1532 static HRESULT interp_regexp(exec_ctx_t *ctx)
1533 {
1534     const WCHAR *source = ctx->parser->code->instrs[ctx->ip].arg1.str;
1535     const LONG flags = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1536     jsdisp_t *regexp;
1537     VARIANT v;
1538     HRESULT hres;
1539
1540     TRACE("%s %x\n", debugstr_w(source), flags);
1541
1542     hres = create_regexp(ctx->parser->script, source, strlenW(source), flags, &regexp);
1543     if(FAILED(hres))
1544         return hres;
1545
1546     var_set_jsdisp(&v, regexp);
1547     return stack_push(ctx, &v);
1548 }
1549
1550 /* ECMA-262 3rd Edition    11.1.4 */
1551 static HRESULT interp_carray(exec_ctx_t *ctx)
1552 {
1553     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1554     jsdisp_t *array;
1555     VARIANT *v, r;
1556     unsigned i;
1557     HRESULT hres;
1558
1559     TRACE("%u\n", arg);
1560
1561     hres = create_array(ctx->parser->script, arg, &array);
1562     if(FAILED(hres))
1563         return hres;
1564
1565     i = arg;
1566     while(i--) {
1567         v = stack_pop(ctx);
1568         hres = jsdisp_propput_idx(array, i, v, ctx->ei, NULL/*FIXME*/);
1569         VariantClear(v);
1570         if(FAILED(hres)) {
1571             jsdisp_release(array);
1572             return hres;
1573         }
1574     }
1575
1576     var_set_jsdisp(&r, array);
1577     return stack_push(ctx, &r);
1578 }
1579
1580 /* ECMA-262 3rd Edition    11.1.5 */
1581 HRESULT interp_new_obj(exec_ctx_t *ctx)
1582 {
1583     jsdisp_t *obj;
1584     VARIANT v;
1585     HRESULT hres;
1586
1587     TRACE("\n");
1588
1589     hres = create_object(ctx->parser->script, NULL, &obj);
1590     if(FAILED(hres))
1591         return hres;
1592
1593     var_set_jsdisp(&v, obj);
1594     return stack_push(ctx, &v);
1595 }
1596
1597 /* ECMA-262 3rd Edition    11.1.5 */
1598 HRESULT interp_obj_prop(exec_ctx_t *ctx)
1599 {
1600     const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1601     jsdisp_t *obj;
1602     VARIANT *v;
1603     HRESULT hres;
1604
1605     TRACE("%s\n", debugstr_w(name));
1606
1607     v = stack_pop(ctx);
1608
1609     assert(V_VT(stack_top(ctx)) == VT_DISPATCH);
1610     obj = as_jsdisp(V_DISPATCH(stack_top(ctx)));
1611
1612     hres = jsdisp_propput_name(obj, name, v, ctx->ei, NULL/*FIXME*/);
1613     VariantClear(v);
1614     return hres;
1615 }
1616
1617 /* ECMA-262 3rd Edition    11.11 */
1618 static HRESULT interp_cnd_nz(exec_ctx_t *ctx)
1619 {
1620     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1621     VARIANT_BOOL b;
1622     HRESULT hres;
1623
1624     TRACE("\n");
1625
1626     hres = to_boolean(stack_top(ctx), &b);
1627     if(FAILED(hres))
1628         return hres;
1629
1630     if(b) {
1631         ctx->ip = arg;
1632     }else {
1633         stack_popn(ctx, 1);
1634         ctx->ip++;
1635     }
1636     return S_OK;
1637 }
1638
1639 /* ECMA-262 3rd Edition    11.11 */
1640 static HRESULT interp_cnd_z(exec_ctx_t *ctx)
1641 {
1642     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1643     VARIANT_BOOL b;
1644     HRESULT hres;
1645
1646     TRACE("\n");
1647
1648     hres = to_boolean(stack_top(ctx), &b);
1649     if(FAILED(hres))
1650         return hres;
1651
1652     if(b) {
1653         stack_popn(ctx, 1);
1654         ctx->ip++;
1655     }else {
1656         ctx->ip = arg;
1657     }
1658     return S_OK;
1659 }
1660
1661 /* ECMA-262 3rd Edition    11.10 */
1662 static HRESULT interp_or(exec_ctx_t *ctx)
1663 {
1664     INT l, r;
1665     HRESULT hres;
1666
1667     TRACE("\n");
1668
1669     hres = stack_pop_int(ctx, &r);
1670     if(FAILED(hres))
1671         return hres;
1672
1673     hres = stack_pop_int(ctx, &l);
1674     if(FAILED(hres))
1675         return hres;
1676
1677     return stack_push_int(ctx, l|r);
1678 }
1679
1680 /* ECMA-262 3rd Edition    11.10 */
1681 static HRESULT interp_xor(exec_ctx_t *ctx)
1682 {
1683     INT l, r;
1684     HRESULT hres;
1685
1686     TRACE("\n");
1687
1688     hres = stack_pop_int(ctx, &r);
1689     if(FAILED(hres))
1690         return hres;
1691
1692     hres = stack_pop_int(ctx, &l);
1693     if(FAILED(hres))
1694         return hres;
1695
1696     return stack_push_int(ctx, l^r);
1697 }
1698
1699 /* ECMA-262 3rd Edition    11.10 */
1700 static HRESULT interp_and(exec_ctx_t *ctx)
1701 {
1702     INT l, r;
1703     HRESULT hres;
1704
1705     TRACE("\n");
1706
1707     hres = stack_pop_int(ctx, &r);
1708     if(FAILED(hres))
1709         return hres;
1710
1711     hres = stack_pop_int(ctx, &l);
1712     if(FAILED(hres))
1713         return hres;
1714
1715     return stack_push_int(ctx, l&r);
1716 }
1717
1718 /* ECMA-262 3rd Edition    11.8.6 */
1719 static HRESULT interp_instanceof(exec_ctx_t *ctx)
1720 {
1721     jsdisp_t *obj, *iter, *tmp = NULL;
1722     VARIANT prot, *v;
1723     BOOL ret = FALSE;
1724     HRESULT hres;
1725
1726     static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
1727
1728     v = stack_pop(ctx);
1729     if(V_VT(v) != VT_DISPATCH || !V_DISPATCH(v)) {
1730         VariantClear(v);
1731         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
1732     }
1733
1734     obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
1735     IDispatch_Release(V_DISPATCH(v));
1736     if(!obj) {
1737         FIXME("non-jsdisp objects not supported\n");
1738         return E_FAIL;
1739     }
1740
1741     if(is_class(obj, JSCLASS_FUNCTION)) {
1742         hres = jsdisp_propget_name(obj, prototypeW, &prot, ctx->ei, NULL/*FIXME*/);
1743     }else {
1744         hres = throw_type_error(ctx->parser->script, ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
1745     }
1746     jsdisp_release(obj);
1747     if(FAILED(hres))
1748         return hres;
1749
1750     v = stack_pop(ctx);
1751
1752     if(V_VT(&prot) == VT_DISPATCH) {
1753         if(V_VT(v) == VT_DISPATCH)
1754             tmp = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
1755         for(iter = tmp; !ret && iter; iter = iter->prototype) {
1756             hres = disp_cmp(V_DISPATCH(&prot), to_disp(iter), &ret);
1757             if(FAILED(hres))
1758                 break;
1759         }
1760
1761         if(tmp)
1762             jsdisp_release(tmp);
1763     }else {
1764         FIXME("prototype is not an object\n");
1765         hres = E_FAIL;
1766     }
1767
1768     VariantClear(&prot);
1769     VariantClear(v);
1770     if(FAILED(hres))
1771         return hres;
1772
1773     return stack_push_bool(ctx, ret);
1774 }
1775
1776 /* ECMA-262 3rd Edition    11.8.7 */
1777 static HRESULT interp_in(exec_ctx_t *ctx)
1778 {
1779     VARIANT *obj, *v;
1780     DISPID id = 0;
1781     BOOL ret;
1782     BSTR str;
1783     HRESULT hres;
1784
1785     TRACE("\n");
1786
1787     obj = stack_pop(ctx);
1788     v = stack_pop(ctx);
1789
1790     if(V_VT(obj) != VT_DISPATCH || !V_DISPATCH(obj)) {
1791         VariantClear(obj);
1792         VariantClear(v);
1793         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1794     }
1795
1796     hres = to_string(ctx->parser->script, v, ctx->ei, &str);
1797     VariantClear(v);
1798     if(FAILED(hres)) {
1799         IDispatch_Release(V_DISPATCH(obj));
1800         return hres;
1801     }
1802
1803     hres = disp_get_id(ctx->parser->script, V_DISPATCH(obj), str, 0, &id);
1804     IDispatch_Release(V_DISPATCH(obj));
1805     SysFreeString(str);
1806     if(SUCCEEDED(hres))
1807         ret = TRUE;
1808     else if(hres == DISP_E_UNKNOWNNAME)
1809         ret = FALSE;
1810     else
1811         return hres;
1812
1813     return stack_push_bool(ctx, ret);
1814 }
1815
1816 /* ECMA-262 3rd Edition    11.6.1 */
1817 static HRESULT add_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
1818 {
1819     VARIANT r, l;
1820     HRESULT hres;
1821
1822     hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
1823     if(FAILED(hres))
1824         return hres;
1825
1826     hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
1827     if(FAILED(hres)) {
1828         VariantClear(&l);
1829         return hres;
1830     }
1831
1832     if(V_VT(&l) == VT_BSTR || V_VT(&r) == VT_BSTR) {
1833         BSTR lstr = NULL, rstr = NULL;
1834
1835         if(V_VT(&l) == VT_BSTR)
1836             lstr = V_BSTR(&l);
1837         else
1838             hres = to_string(ctx, &l, ei, &lstr);
1839
1840         if(SUCCEEDED(hres)) {
1841             if(V_VT(&r) == VT_BSTR)
1842                 rstr = V_BSTR(&r);
1843             else
1844                 hres = to_string(ctx, &r, ei, &rstr);
1845         }
1846
1847         if(SUCCEEDED(hres)) {
1848             int len1, len2;
1849
1850             len1 = SysStringLen(lstr);
1851             len2 = SysStringLen(rstr);
1852
1853             V_VT(retv) = VT_BSTR;
1854             V_BSTR(retv) = SysAllocStringLen(NULL, len1+len2);
1855             memcpy(V_BSTR(retv), lstr, len1*sizeof(WCHAR));
1856             memcpy(V_BSTR(retv)+len1, rstr, (len2+1)*sizeof(WCHAR));
1857         }
1858
1859         if(V_VT(&l) != VT_BSTR)
1860             SysFreeString(lstr);
1861         if(V_VT(&r) != VT_BSTR)
1862             SysFreeString(rstr);
1863     }else {
1864         VARIANT nl, nr;
1865
1866         hres = to_number(ctx, &l, ei, &nl);
1867         if(SUCCEEDED(hres)) {
1868             hres = to_number(ctx, &r, ei, &nr);
1869             if(SUCCEEDED(hres))
1870                 num_set_val(retv, num_val(&nl) + num_val(&nr));
1871         }
1872     }
1873
1874     VariantClear(&r);
1875     VariantClear(&l);
1876     return hres;
1877 }
1878
1879 /* ECMA-262 3rd Edition    11.6.1 */
1880 static HRESULT interp_add(exec_ctx_t *ctx)
1881 {
1882     VARIANT *l, *r, ret;
1883     HRESULT hres;
1884
1885     r = stack_pop(ctx);
1886     l = stack_pop(ctx);
1887
1888     TRACE("%s + %s\n", debugstr_variant(l), debugstr_variant(r));
1889
1890     hres = add_eval(ctx->parser->script, l, r, ctx->ei, &ret);
1891     VariantClear(l);
1892     VariantClear(r);
1893     if(FAILED(hres))
1894         return hres;
1895
1896     return stack_push(ctx, &ret);
1897 }
1898
1899 /* ECMA-262 3rd Edition    11.6.2 */
1900 static HRESULT interp_sub(exec_ctx_t *ctx)
1901 {
1902     VARIANT l, r;
1903     HRESULT hres;
1904
1905     TRACE("\n");
1906
1907     hres = stack_pop_number(ctx, &r);
1908     if(FAILED(hres))
1909         return hres;
1910
1911     hres = stack_pop_number(ctx, &l);
1912     if(FAILED(hres))
1913         return hres;
1914
1915     return stack_push_number(ctx, num_val(&l)-num_val(&r));
1916 }
1917
1918 /* ECMA-262 3rd Edition    11.5.1 */
1919 static HRESULT interp_mul(exec_ctx_t *ctx)
1920 {
1921     VARIANT l, r;
1922     HRESULT hres;
1923
1924     TRACE("\n");
1925
1926     hres = stack_pop_number(ctx, &r);
1927     if(FAILED(hres))
1928         return hres;
1929
1930     hres = stack_pop_number(ctx, &l);
1931     if(FAILED(hres))
1932         return hres;
1933
1934     return stack_push_number(ctx, num_val(&l)*num_val(&r));
1935 }
1936
1937 /* ECMA-262 3rd Edition    11.5.2 */
1938 static HRESULT interp_div(exec_ctx_t *ctx)
1939 {
1940     VARIANT l, r;
1941     HRESULT hres;
1942
1943     TRACE("\n");
1944
1945     hres = stack_pop_number(ctx, &r);
1946     if(FAILED(hres))
1947         return hres;
1948
1949     hres = stack_pop_number(ctx, &l);
1950     if(FAILED(hres))
1951         return hres;
1952
1953     return stack_push_number(ctx, num_val(&l)/num_val(&r));
1954 }
1955
1956 /* ECMA-262 3rd Edition    11.5.3 */
1957 static HRESULT interp_mod(exec_ctx_t *ctx)
1958 {
1959     VARIANT l, r;
1960     HRESULT hres;
1961
1962     TRACE("\n");
1963
1964     hres = stack_pop_number(ctx, &r);
1965     if(FAILED(hres))
1966         return hres;
1967
1968     hres = stack_pop_number(ctx, &l);
1969     if(FAILED(hres))
1970         return hres;
1971
1972     return stack_push_number(ctx, fmod(num_val(&l), num_val(&r)));
1973 }
1974
1975 /* ECMA-262 3rd Edition    11.4.2 */
1976 static HRESULT interp_delete(exec_ctx_t *ctx)
1977 {
1978     VARIANT *obj_var, *name_var;
1979     IDispatchEx *dispex;
1980     IDispatch *obj;
1981     BSTR name;
1982     BOOL ret;
1983     HRESULT hres;
1984
1985     TRACE("\n");
1986
1987     name_var = stack_pop(ctx);
1988     obj_var = stack_pop(ctx);
1989
1990     hres = to_object(ctx->parser->script, obj_var, &obj);
1991     VariantClear(obj_var);
1992     if(FAILED(hres)) {
1993         VariantClear(name_var);
1994         return hres;
1995     }
1996
1997     hres = to_string(ctx->parser->script, name_var, ctx->ei, &name);
1998     VariantClear(name_var);
1999     if(FAILED(hres)) {
2000         IDispatch_Release(obj);
2001         return hres;
2002     }
2003
2004     hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
2005     if(SUCCEEDED(hres)) {
2006         hres = IDispatchEx_DeleteMemberByName(dispex, name, make_grfdex(ctx->parser->script, fdexNameCaseSensitive));
2007         ret = TRUE;
2008         IDispatchEx_Release(dispex);
2009     }else {
2010         hres = S_OK;
2011         ret = FALSE;
2012     }
2013
2014     IDispatch_Release(obj);
2015     SysFreeString(name);
2016     if(FAILED(hres))
2017         return hres;
2018
2019     return stack_push_bool(ctx, ret);
2020 }
2021
2022 /* ECMA-262 3rd Edition    11.4.2 */
2023 static HRESULT interp_delete_ident(exec_ctx_t *ctx)
2024 {
2025     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2026     IDispatchEx *dispex;
2027     exprval_t exprval;
2028     BOOL ret = FALSE;
2029     HRESULT hres;
2030
2031     TRACE("%s\n", debugstr_w(arg));
2032
2033     hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
2034     if(FAILED(hres))
2035         return hres;
2036
2037     if(exprval.type != EXPRVAL_IDREF) {
2038         FIXME("Unsupported exprval\n");
2039         exprval_release(&exprval);
2040         return E_NOTIMPL;
2041     }
2042
2043     hres = IDispatch_QueryInterface(exprval.u.idref.disp, &IID_IDispatchEx, (void**)&dispex);
2044     IDispatch_Release(exprval.u.idref.disp);
2045     if(SUCCEEDED(hres)) {
2046         hres = IDispatchEx_DeleteMemberByDispID(dispex, exprval.u.idref.id);
2047         IDispatchEx_Release(dispex);
2048         if(FAILED(hres))
2049             return hres;
2050
2051         ret = TRUE;
2052     }
2053
2054     return stack_push_bool(ctx, ret);
2055 }
2056
2057 /* ECMA-262 3rd Edition    11.4.2 */
2058 static HRESULT interp_void(exec_ctx_t *ctx)
2059 {
2060     VARIANT v;
2061
2062     TRACE("\n");
2063
2064     stack_popn(ctx, 1);
2065
2066     V_VT(&v) = VT_EMPTY;
2067     return stack_push(ctx, &v);
2068 }
2069
2070 /* ECMA-262 3rd Edition    11.4.3 */
2071 static HRESULT typeof_string(VARIANT *v, const WCHAR **ret)
2072 {
2073     switch(V_VT(v)) {
2074     case VT_EMPTY:
2075         *ret = undefinedW;
2076         break;
2077     case VT_NULL:
2078         *ret = objectW;
2079         break;
2080     case VT_BOOL:
2081         *ret = booleanW;
2082         break;
2083     case VT_I4:
2084     case VT_R8:
2085         *ret = numberW;
2086         break;
2087     case VT_BSTR:
2088         *ret = stringW;
2089         break;
2090     case VT_DISPATCH: {
2091         jsdisp_t *dispex;
2092
2093         if(V_DISPATCH(v) && (dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(v)))) {
2094             *ret = is_class(dispex, JSCLASS_FUNCTION) ? functionW : objectW;
2095             jsdisp_release(dispex);
2096         }else {
2097             *ret = objectW;
2098         }
2099         break;
2100     }
2101     default:
2102         FIXME("unhandled vt %d\n", V_VT(v));
2103         return E_NOTIMPL;
2104     }
2105
2106     return S_OK;
2107 }
2108
2109 /* ECMA-262 3rd Edition    11.4.3 */
2110 static HRESULT interp_typeofid(exec_ctx_t *ctx)
2111 {
2112     const WCHAR *ret;
2113     IDispatch *obj;
2114     VARIANT v;
2115     DISPID id;
2116     HRESULT hres;
2117
2118     static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
2119
2120     TRACE("\n");
2121
2122     obj = stack_pop_objid(ctx, &id);
2123     if(!obj)
2124         return stack_push_string(ctx, undefinedW);
2125
2126     V_VT(&v) = VT_EMPTY;
2127     hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2128     IDispatch_Release(obj);
2129     if(FAILED(hres))
2130         return stack_push_string(ctx, unknownW);
2131
2132     hres = typeof_string(&v, &ret);
2133     VariantClear(&v);
2134     if(FAILED(hres))
2135         return hres;
2136
2137     return stack_push_string(ctx, ret);
2138 }
2139
2140 /* ECMA-262 3rd Edition    11.4.3 */
2141 static HRESULT interp_typeofident(exec_ctx_t *ctx)
2142 {
2143     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2144     exprval_t exprval;
2145     const WCHAR *ret;
2146     VARIANT v;
2147     HRESULT hres;
2148
2149     TRACE("%s\n", debugstr_w(arg));
2150
2151     hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
2152     if(FAILED(hres))
2153         return hres;
2154
2155     if(exprval.type == EXPRVAL_INVALID) {
2156         hres = stack_push_string(ctx, undefinedW);
2157         exprval_release(&exprval);
2158         return hres;
2159     }
2160
2161     hres = exprval_to_value(ctx->parser->script, &exprval, ctx->ei, &v);
2162     exprval_release(&exprval);
2163     if(FAILED(hres))
2164         return hres;
2165
2166     hres = typeof_string(&v, &ret);
2167     VariantClear(&v);
2168     if(FAILED(hres))
2169         return hres;
2170
2171     return stack_push_string(ctx, ret);
2172 }
2173
2174 /* ECMA-262 3rd Edition    11.4.3 */
2175 static HRESULT interp_typeof(exec_ctx_t *ctx)
2176 {
2177     const WCHAR *ret;
2178     VARIANT *v;
2179     HRESULT hres;
2180
2181     TRACE("\n");
2182
2183     v = stack_pop(ctx);
2184     hres = typeof_string(v, &ret);
2185     VariantClear(v);
2186     if(FAILED(hres))
2187         return hres;
2188
2189     return stack_push_string(ctx, ret);
2190 }
2191
2192 /* ECMA-262 3rd Edition    11.4.7 */
2193 static HRESULT interp_minus(exec_ctx_t *ctx)
2194 {
2195     VARIANT n;
2196     HRESULT hres;
2197
2198     TRACE("\n");
2199
2200     hres = stack_pop_number(ctx, &n);
2201     if(FAILED(hres))
2202         return hres;
2203
2204     return stack_push_number(ctx, -num_val(&n));
2205 }
2206
2207 /* ECMA-262 3rd Edition    11.4.6 */
2208 static HRESULT interp_tonum(exec_ctx_t *ctx)
2209 {
2210     VARIANT *v, num;
2211     HRESULT hres;
2212
2213     TRACE("\n");
2214
2215     v = stack_pop(ctx);
2216     hres = to_number(ctx->parser->script, v, ctx->ei, &num);
2217     VariantClear(v);
2218     if(FAILED(hres))
2219         return hres;
2220
2221     return stack_push(ctx, &num);
2222 }
2223
2224 /* ECMA-262 3rd Edition    11.3.1 */
2225 static HRESULT interp_postinc(exec_ctx_t *ctx)
2226 {
2227     const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2228     IDispatch *obj;
2229     DISPID id;
2230     VARIANT v;
2231     HRESULT hres;
2232
2233     TRACE("%d\n", arg);
2234
2235     obj = stack_pop_objid(ctx, &id);
2236     if(!obj)
2237         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2238
2239     hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2240     if(SUCCEEDED(hres)) {
2241         VARIANT n, inc;
2242
2243         hres = to_number(ctx->parser->script, &v, ctx->ei, &n);
2244         if(SUCCEEDED(hres)) {
2245             num_set_val(&inc, num_val(&n)+(double)arg);
2246             hres = disp_propput(ctx->parser->script, obj, id, &inc, ctx->ei, NULL/*FIXME*/);
2247         }
2248         if(FAILED(hres))
2249             VariantClear(&v);
2250     }
2251     IDispatch_Release(obj);
2252     if(FAILED(hres))
2253         return hres;
2254
2255     return stack_push(ctx, &v);
2256 }
2257
2258 /* ECMA-262 3rd Edition    11.4.4, 11.4.5 */
2259 static HRESULT interp_preinc(exec_ctx_t *ctx)
2260 {
2261     const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2262     IDispatch *obj;
2263     DISPID id;
2264     VARIANT v;
2265     HRESULT hres;
2266
2267     TRACE("%d\n", arg);
2268
2269     obj = stack_pop_objid(ctx, &id);
2270     if(!obj)
2271         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2272
2273     hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2274     if(SUCCEEDED(hres)) {
2275         VARIANT n;
2276
2277         hres = to_number(ctx->parser->script, &v, ctx->ei, &n);
2278         VariantClear(&v);
2279         if(SUCCEEDED(hres)) {
2280             num_set_val(&v, num_val(&n)+(double)arg);
2281             hres = disp_propput(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2282         }
2283     }
2284     IDispatch_Release(obj);
2285     if(FAILED(hres))
2286         return hres;
2287
2288     return stack_push(ctx, &v);
2289 }
2290
2291 /* ECMA-262 3rd Edition    11.9.3 */
2292 static HRESULT equal_values(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, BOOL *ret)
2293 {
2294     if(V_VT(lval) == V_VT(rval) || (is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval))))
2295        return equal2_values(lval, rval, ret);
2296
2297     /* FIXME: NULL disps should be handled in more general way */
2298     if(V_VT(lval) == VT_DISPATCH && !V_DISPATCH(lval)) {
2299         VARIANT v;
2300         V_VT(&v) = VT_NULL;
2301         return equal_values(ctx, &v, rval, ei, ret);
2302     }
2303
2304     if(V_VT(rval) == VT_DISPATCH && !V_DISPATCH(rval)) {
2305         VARIANT v;
2306         V_VT(&v) = VT_NULL;
2307         return equal_values(ctx, lval, &v, ei, ret);
2308     }
2309
2310     if((V_VT(lval) == VT_NULL && V_VT(rval) == VT_EMPTY) ||
2311        (V_VT(lval) == VT_EMPTY && V_VT(rval) == VT_NULL)) {
2312         *ret = TRUE;
2313         return S_OK;
2314     }
2315
2316     if(V_VT(lval) == VT_BSTR && is_num_vt(V_VT(rval))) {
2317         VARIANT v;
2318         HRESULT hres;
2319
2320         hres = to_number(ctx, lval, ei, &v);
2321         if(FAILED(hres))
2322             return hres;
2323
2324         return equal_values(ctx, &v, rval, ei, ret);
2325     }
2326
2327     if(V_VT(rval) == VT_BSTR && is_num_vt(V_VT(lval))) {
2328         VARIANT v;
2329         HRESULT hres;
2330
2331         hres = to_number(ctx, rval, ei, &v);
2332         if(FAILED(hres))
2333             return hres;
2334
2335         return equal_values(ctx, lval, &v, ei, ret);
2336     }
2337
2338     if(V_VT(rval) == VT_BOOL) {
2339         VARIANT v;
2340
2341         V_VT(&v) = VT_I4;
2342         V_I4(&v) = V_BOOL(rval) ? 1 : 0;
2343         return equal_values(ctx, lval, &v, ei, ret);
2344     }
2345
2346     if(V_VT(lval) == VT_BOOL) {
2347         VARIANT v;
2348
2349         V_VT(&v) = VT_I4;
2350         V_I4(&v) = V_BOOL(lval) ? 1 : 0;
2351         return equal_values(ctx, &v, rval, ei, ret);
2352     }
2353
2354
2355     if(V_VT(rval) == VT_DISPATCH && (V_VT(lval) == VT_BSTR || is_num_vt(V_VT(lval)))) {
2356         VARIANT v;
2357         HRESULT hres;
2358
2359         hres = to_primitive(ctx, rval, ei, &v, NO_HINT);
2360         if(FAILED(hres))
2361             return hres;
2362
2363         hres = equal_values(ctx, lval, &v, ei, ret);
2364
2365         VariantClear(&v);
2366         return hres;
2367     }
2368
2369
2370     if(V_VT(lval) == VT_DISPATCH && (V_VT(rval) == VT_BSTR || is_num_vt(V_VT(rval)))) {
2371         VARIANT v;
2372         HRESULT hres;
2373
2374         hres = to_primitive(ctx, lval, ei, &v, NO_HINT);
2375         if(FAILED(hres))
2376             return hres;
2377
2378         hres = equal_values(ctx, &v, rval, ei, ret);
2379
2380         VariantClear(&v);
2381         return hres;
2382     }
2383
2384
2385     *ret = FALSE;
2386     return S_OK;
2387 }
2388
2389 /* ECMA-262 3rd Edition    11.9.1 */
2390 static HRESULT interp_eq(exec_ctx_t *ctx)
2391 {
2392     VARIANT *l, *r;
2393     BOOL b;
2394     HRESULT hres;
2395
2396     r = stack_pop(ctx);
2397     l = stack_pop(ctx);
2398
2399     TRACE("%s == %s\n", debugstr_variant(l), debugstr_variant(r));
2400
2401     hres = equal_values(ctx->parser->script, l, r, ctx->ei, &b);
2402     VariantClear(l);
2403     VariantClear(r);
2404     if(FAILED(hres))
2405         return hres;
2406
2407     return stack_push_bool(ctx, b);
2408 }
2409
2410 /* ECMA-262 3rd Edition    11.9.2 */
2411 static HRESULT interp_neq(exec_ctx_t *ctx)
2412 {
2413     VARIANT *l, *r;
2414     BOOL b;
2415     HRESULT hres;
2416
2417     r = stack_pop(ctx);
2418     l = stack_pop(ctx);
2419
2420     TRACE("%s != %s\n", debugstr_variant(l), debugstr_variant(r));
2421
2422     hres = equal_values(ctx->parser->script, l, r, ctx->ei, &b);
2423     VariantClear(l);
2424     VariantClear(r);
2425     if(FAILED(hres))
2426         return hres;
2427
2428     return stack_push_bool(ctx, !b);
2429 }
2430
2431 /* ECMA-262 3rd Edition    11.9.4 */
2432 static HRESULT interp_eq2(exec_ctx_t *ctx)
2433 {
2434     VARIANT *l, *r;
2435     BOOL b;
2436     HRESULT hres;
2437
2438     TRACE("\n");
2439
2440     r = stack_pop(ctx);
2441     l = stack_pop(ctx);
2442
2443     hres = equal2_values(r, l, &b);
2444     VariantClear(l);
2445     VariantClear(r);
2446     if(FAILED(hres))
2447         return hres;
2448
2449     return stack_push_bool(ctx, b);
2450 }
2451
2452 /* ECMA-262 3rd Edition    11.9.5 */
2453 static HRESULT interp_neq2(exec_ctx_t *ctx)
2454 {
2455     VARIANT *l, *r;
2456     BOOL b;
2457     HRESULT hres;
2458
2459     TRACE("\n");
2460
2461     r = stack_pop(ctx);
2462     l = stack_pop(ctx);
2463
2464     hres = equal2_values(r, l, &b);
2465     VariantClear(l);
2466     VariantClear(r);
2467     if(FAILED(hres))
2468         return hres;
2469
2470     return stack_push_bool(ctx, !b);
2471 }
2472
2473 /* ECMA-262 3rd Edition    11.8.5 */
2474 static HRESULT less_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL greater, jsexcept_t *ei, BOOL *ret)
2475 {
2476     VARIANT l, r, ln, rn;
2477     HRESULT hres;
2478
2479     hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2480     if(FAILED(hres))
2481         return hres;
2482
2483     hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
2484     if(FAILED(hres)) {
2485         VariantClear(&l);
2486         return hres;
2487     }
2488
2489     if(V_VT(&l) == VT_BSTR && V_VT(&r) == VT_BSTR) {
2490         *ret = (strcmpW(V_BSTR(&l), V_BSTR(&r)) < 0) ^ greater;
2491         SysFreeString(V_BSTR(&l));
2492         SysFreeString(V_BSTR(&r));
2493         return S_OK;
2494     }
2495
2496     hres = to_number(ctx, &l, ei, &ln);
2497     VariantClear(&l);
2498     if(SUCCEEDED(hres))
2499         hres = to_number(ctx, &r, ei, &rn);
2500     VariantClear(&r);
2501     if(FAILED(hres))
2502         return hres;
2503
2504     if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) {
2505         *ret = (V_I4(&ln) < V_I4(&rn)) ^ greater;
2506     }else  {
2507         DOUBLE ld = num_val(&ln);
2508         DOUBLE rd = num_val(&rn);
2509
2510         *ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater);
2511     }
2512
2513     return S_OK;
2514 }
2515
2516 /* ECMA-262 3rd Edition    11.8.1 */
2517 static HRESULT interp_lt(exec_ctx_t *ctx)
2518 {
2519     VARIANT *l, *r;
2520     BOOL b;
2521     HRESULT hres;
2522
2523     r = stack_pop(ctx);
2524     l = stack_pop(ctx);
2525
2526     TRACE("%s < %s\n", debugstr_variant(l), debugstr_variant(r));
2527
2528     hres = less_eval(ctx->parser->script, l, r, FALSE, ctx->ei, &b);
2529     VariantClear(l);
2530     VariantClear(r);
2531     if(FAILED(hres))
2532         return hres;
2533
2534     return stack_push_bool(ctx, b);
2535 }
2536
2537 /* ECMA-262 3rd Edition    11.8.1 */
2538 static HRESULT interp_lteq(exec_ctx_t *ctx)
2539 {
2540     VARIANT *l, *r;
2541     BOOL b;
2542     HRESULT hres;
2543
2544     r = stack_pop(ctx);
2545     l = stack_pop(ctx);
2546
2547     TRACE("%s <= %s\n", debugstr_variant(l), debugstr_variant(r));
2548
2549     hres = less_eval(ctx->parser->script, r, l, TRUE, ctx->ei, &b);
2550     VariantClear(l);
2551     VariantClear(r);
2552     if(FAILED(hres))
2553         return hres;
2554
2555     return stack_push_bool(ctx, b);
2556 }
2557
2558 /* ECMA-262 3rd Edition    11.8.2 */
2559 static HRESULT interp_gt(exec_ctx_t *ctx)
2560 {
2561     VARIANT *l, *r;
2562     BOOL b;
2563     HRESULT hres;
2564
2565     r = stack_pop(ctx);
2566     l = stack_pop(ctx);
2567
2568     TRACE("%s > %s\n", debugstr_variant(l), debugstr_variant(r));
2569
2570     hres = less_eval(ctx->parser->script, r, l, FALSE, ctx->ei, &b);
2571     VariantClear(l);
2572     VariantClear(r);
2573     if(FAILED(hres))
2574         return hres;
2575
2576     return stack_push_bool(ctx, b);
2577 }
2578
2579 /* ECMA-262 3rd Edition    11.8.4 */
2580 static HRESULT interp_gteq(exec_ctx_t *ctx)
2581 {
2582     VARIANT *l, *r;
2583     BOOL b;
2584     HRESULT hres;
2585
2586     r = stack_pop(ctx);
2587     l = stack_pop(ctx);
2588
2589     TRACE("%s >= %s\n", debugstr_variant(l), debugstr_variant(r));
2590
2591     hres = less_eval(ctx->parser->script, l, r, TRUE, ctx->ei, &b);
2592     VariantClear(l);
2593     VariantClear(r);
2594     if(FAILED(hres))
2595         return hres;
2596
2597     return stack_push_bool(ctx, b);
2598 }
2599
2600 /* ECMA-262 3rd Edition    11.4.8 */
2601 static HRESULT interp_bneg(exec_ctx_t *ctx)
2602 {
2603     VARIANT *v, r;
2604     INT i;
2605     HRESULT hres;
2606
2607     TRACE("\n");
2608
2609     v = stack_pop(ctx);
2610     hres = to_int32(ctx->parser->script, v, ctx->ei, &i);
2611     VariantClear(v);
2612     if(FAILED(hres))
2613         return hres;
2614
2615     V_VT(&r) = VT_I4;
2616     V_I4(&r) = ~i;
2617     return stack_push(ctx, &r);
2618 }
2619
2620 /* ECMA-262 3rd Edition    11.4.9 */
2621 static HRESULT interp_neg(exec_ctx_t *ctx)
2622 {
2623     VARIANT *v;
2624     VARIANT_BOOL b;
2625     HRESULT hres;
2626
2627     TRACE("\n");
2628
2629     v = stack_pop(ctx);
2630     hres = to_boolean(v, &b);
2631     VariantClear(v);
2632     if(FAILED(hres))
2633         return hres;
2634
2635     return stack_push_bool(ctx, !b);
2636 }
2637
2638 /* ECMA-262 3rd Edition    11.7.1 */
2639 static HRESULT interp_lshift(exec_ctx_t *ctx)
2640 {
2641     DWORD r;
2642     INT l;
2643     HRESULT hres;
2644
2645     hres = stack_pop_uint(ctx, &r);
2646     if(FAILED(hres))
2647         return hres;
2648
2649     hres = stack_pop_int(ctx, &l);
2650     if(FAILED(hres))
2651         return hres;
2652
2653     return stack_push_int(ctx, l << (r&0x1f));
2654 }
2655
2656 /* ECMA-262 3rd Edition    11.7.2 */
2657 static HRESULT interp_rshift(exec_ctx_t *ctx)
2658 {
2659     DWORD r;
2660     INT l;
2661     HRESULT hres;
2662
2663     hres = stack_pop_uint(ctx, &r);
2664     if(FAILED(hres))
2665         return hres;
2666
2667     hres = stack_pop_int(ctx, &l);
2668     if(FAILED(hres))
2669         return hres;
2670
2671     return stack_push_int(ctx, l >> (r&0x1f));
2672 }
2673
2674 /* ECMA-262 3rd Edition    11.7.3 */
2675 static HRESULT interp_rshift2(exec_ctx_t *ctx)
2676 {
2677     DWORD r, l;
2678     HRESULT hres;
2679
2680     hres = stack_pop_uint(ctx, &r);
2681     if(FAILED(hres))
2682         return hres;
2683
2684     hres = stack_pop_uint(ctx, &l);
2685     if(FAILED(hres))
2686         return hres;
2687
2688     return stack_push_int(ctx, l >> (r&0x1f));
2689 }
2690
2691 /* ECMA-262 3rd Edition    11.13.1 */
2692 static HRESULT interp_assign(exec_ctx_t *ctx)
2693 {
2694     IDispatch *disp;
2695     DISPID id;
2696     VARIANT *v;
2697     HRESULT hres;
2698
2699     TRACE("\n");
2700
2701     v = stack_pop(ctx);
2702     disp = stack_pop_objid(ctx, &id);
2703
2704     if(!disp)
2705         return throw_reference_error(ctx->parser->script, ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
2706
2707     hres = disp_propput(ctx->parser->script, disp, id, v, ctx->ei, NULL/*FIXME*/);
2708     IDispatch_Release(disp);
2709     if(FAILED(hres)) {
2710         VariantClear(v);
2711         return hres;
2712     }
2713
2714     return stack_push(ctx, v);
2715 }
2716
2717 static HRESULT interp_undefined(exec_ctx_t *ctx)
2718 {
2719     VARIANT v;
2720
2721     TRACE("\n");
2722
2723     V_VT(&v) = VT_EMPTY;
2724     return stack_push(ctx, &v);
2725 }
2726
2727 static HRESULT interp_jmp(exec_ctx_t *ctx)
2728 {
2729     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
2730
2731     TRACE("\n");
2732
2733     ctx->ip = arg;
2734     return S_OK;
2735 }
2736
2737 static HRESULT interp_jmp_z(exec_ctx_t *ctx)
2738 {
2739     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
2740     VARIANT_BOOL b;
2741     VARIANT *v;
2742     HRESULT hres;
2743
2744     TRACE("\n");
2745
2746     v = stack_pop(ctx);
2747     hres = to_boolean(v, &b);
2748     VariantClear(v);
2749     if(FAILED(hres))
2750         return hres;
2751
2752     if(b)
2753         ctx->ip++;
2754     else
2755         ctx->ip = arg;
2756     return S_OK;
2757 }
2758
2759 static HRESULT interp_pop(exec_ctx_t *ctx)
2760 {
2761     TRACE("\n");
2762
2763     stack_popn(ctx, 1);
2764     return S_OK;
2765 }
2766
2767 static HRESULT interp_ret(exec_ctx_t *ctx)
2768 {
2769     TRACE("\n");
2770
2771     ctx->ip = -1;
2772     return S_OK;
2773 }
2774
2775 static HRESULT interp_tree(exec_ctx_t *ctx)
2776 {
2777     instr_t *instr = ctx->parser->code->instrs+ctx->ip;
2778     VARIANT v;
2779     HRESULT hres;
2780
2781     TRACE("\n");
2782
2783     hres = stat_eval(ctx->parser->script, instr->arg1.stat, ctx->rt, &v);
2784     if(FAILED(hres))
2785         return hres;
2786
2787     return stack_push(ctx, &v);
2788 }
2789
2790 typedef HRESULT (*op_func_t)(exec_ctx_t*);
2791
2792 static const op_func_t op_funcs[] = {
2793 #define X(x,a,b,c) interp_##x,
2794 OP_LIST
2795 #undef X
2796 };
2797
2798 static const unsigned op_move[] = {
2799 #define X(a,x,b,c) x,
2800 OP_LIST
2801 #undef X
2802 };
2803
2804 static HRESULT unwind_exception(exec_ctx_t *ctx)
2805 {
2806     except_frame_t *except_frame;
2807     VARIANT except_val;
2808     BSTR ident;
2809     HRESULT hres;
2810
2811     except_frame = ctx->except_frame;
2812     ctx->except_frame = except_frame->next;
2813
2814     assert(except_frame->stack_top <= ctx->top);
2815     stack_popn(ctx, ctx->top - except_frame->stack_top);
2816
2817     while(except_frame->scope != ctx->scope_chain)
2818         scope_pop(&ctx->scope_chain);
2819
2820     ctx->ip = except_frame->catch_off;
2821
2822     assert(ctx->rt->type == RT_NORMAL);
2823     except_val = ctx->rt->ei.var;
2824     memset(&ctx->rt->ei, 0, sizeof(ctx->rt->ei));
2825
2826     ident = except_frame->ident;
2827     heap_free(except_frame);
2828
2829     if(ident) {
2830         jsdisp_t *scope_obj;
2831
2832         hres = create_dispex(ctx->parser->script, NULL, NULL, &scope_obj);
2833         if(SUCCEEDED(hres)) {
2834             hres = jsdisp_propput_name(scope_obj, ident, &except_val, &ctx->rt->ei, NULL/*FIXME*/);
2835             if(FAILED(hres))
2836                 jsdisp_release(scope_obj);
2837         }
2838         VariantClear(&except_val);
2839         if(FAILED(hres))
2840             return hres;
2841
2842         hres = scope_push(ctx->scope_chain, scope_obj, &ctx->scope_chain);
2843         jsdisp_release(scope_obj);
2844     }else {
2845         VARIANT v;
2846
2847         hres = stack_push(ctx, &except_val);
2848         if(FAILED(hres))
2849             return hres;
2850
2851         hres = stack_push_bool(ctx, FALSE);
2852         if(FAILED(hres))
2853             return hres;
2854
2855         V_VT(&v) = VT_EMPTY;
2856         hres = stack_push(ctx, &v);
2857     }
2858
2859     return hres;
2860 }
2861
2862 HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
2863 {
2864     exec_ctx_t *exec_ctx = ctx->exec_ctx;
2865     except_frame_t *prev_except_frame;
2866     unsigned prev_ip, prev_top;
2867     scope_chain_t *prev_scope;
2868     return_type_t *prev_rt;
2869     jsexcept_t *prev_ei;
2870     jsop_t op;
2871     HRESULT hres = S_OK;
2872
2873     TRACE("\n");
2874
2875     if(stat->instr_off == -1) {
2876         hres = compile_subscript_stat(exec_ctx->parser, stat, FALSE, &stat->instr_off);
2877         if(FAILED(hres))
2878             return hres;
2879     }
2880
2881     prev_rt = exec_ctx->rt;
2882     prev_top = exec_ctx->top;
2883     prev_scope = exec_ctx->scope_chain;
2884     prev_except_frame = exec_ctx->except_frame;
2885     prev_ip = exec_ctx->ip;
2886     prev_ei = exec_ctx->ei;
2887     exec_ctx->ip = stat->instr_off;
2888     exec_ctx->rt = rt;
2889     exec_ctx->ei = &rt->ei;
2890     exec_ctx->except_frame = NULL;
2891
2892     while(exec_ctx->ip != -1 && exec_ctx->rt->type == RT_NORMAL) {
2893         op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
2894         hres = op_funcs[op](exec_ctx);
2895         if(FAILED(hres)) {
2896             TRACE("EXCEPTION\n");
2897
2898             if(!exec_ctx->except_frame)
2899                 break;
2900
2901             hres = unwind_exception(exec_ctx);
2902             if(FAILED(hres))
2903                 break;
2904         }else {
2905             exec_ctx->ip += op_move[op];
2906         }
2907     }
2908
2909     exec_ctx->rt = prev_rt;
2910     exec_ctx->ip = prev_ip;
2911     exec_ctx->ei = prev_ei;
2912     exec_ctx->except_frame = prev_except_frame;
2913
2914     if(FAILED(hres) || rt->type != RT_NORMAL) {
2915         while(exec_ctx->scope_chain != prev_scope)
2916             scope_pop(&exec_ctx->scope_chain);
2917     }
2918     if(FAILED(hres)) {
2919         stack_popn(exec_ctx, exec_ctx->top-prev_top);
2920         return hres;
2921     }
2922
2923     assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top);
2924     assert(exec_ctx->scope_chain == prev_scope);
2925
2926     if(exec_ctx->top == prev_top)
2927         V_VT(ret) = VT_EMPTY;
2928     else
2929         *ret = *stack_pop(exec_ctx);
2930     return S_OK;
2931 }
2932
2933 static HRESULT expr_eval(script_ctx_t *ctx, expression_t *expr, jsexcept_t *ei, VARIANT *ret)
2934 {
2935     exec_ctx_t *exec_ctx = ctx->exec_ctx;
2936     unsigned prev_ip, prev_top;
2937     jsexcept_t *prev_ei;
2938     jsop_t op;
2939     HRESULT hres = S_OK;
2940
2941     TRACE("\n");
2942
2943     if(expr->instr_off == -1) {
2944         hres = compile_subscript(ctx->exec_ctx->parser, expr, &expr->instr_off);
2945         if(FAILED(hres))
2946             return hres;
2947     }
2948
2949     prev_top = exec_ctx->top;
2950     prev_ip = exec_ctx->ip;
2951     prev_ei = exec_ctx->ei;
2952     exec_ctx->ip = expr->instr_off;
2953     exec_ctx->ei = ei;
2954
2955     while(exec_ctx->ip != -1) {
2956         op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
2957         hres = op_funcs[op](exec_ctx);
2958         if(FAILED(hres))
2959             break;
2960         exec_ctx->ip += op_move[op];
2961     }
2962
2963     exec_ctx->ip = prev_ip;
2964     exec_ctx->ei = prev_ei;
2965
2966     if(FAILED(hres)) {
2967         stack_popn(exec_ctx, exec_ctx->top-prev_top);
2968         return hres;
2969     }
2970
2971     assert(exec_ctx->top == prev_top+1);
2972
2973     if(exec_ctx->top == prev_top)
2974         V_VT(ret) = VT_EMPTY;
2975     else
2976         *ret = *stack_pop(exec_ctx);
2977     return S_OK;
2978 }