jscript: Always use bytecode for for..in 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 variable_list_eval(script_ctx_t *ctx, variable_declaration_t *var_list, jsexcept_t *ei)
661 {
662     variable_declaration_t *iter;
663     HRESULT hres = S_OK;
664
665     for(iter = var_list; iter; iter = iter->next) {
666         VARIANT val;
667
668         if(!iter->expr)
669             continue;
670
671         hres = expr_eval(ctx, iter->expr, ei, &val);
672         if(FAILED(hres))
673             break;
674
675         hres = jsdisp_propput_name(ctx->exec_ctx->var_disp, iter->identifier, &val, ei, NULL/*FIXME*/);
676         VariantClear(&val);
677         if(FAILED(hres))
678             break;
679     }
680
681     return hres;
682 }
683
684 /* ECMA-262 3rd Edition    12.2 */
685 static HRESULT interp_var_set(exec_ctx_t *ctx)
686 {
687     const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
688     VARIANT *v;
689     HRESULT hres;
690
691     TRACE("%s\n", debugstr_w(name));
692
693     v = stack_pop(ctx);
694     hres = jsdisp_propput_name(ctx->var_disp, name, v, ctx->ei, NULL/*FIXME*/);
695     VariantClear(v);
696     return hres;
697 }
698
699 /* ECMA-262 3rd Edition    12.6.2 */
700 HRESULT while_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
701 {
702     while_statement_t *stat = (while_statement_t*)_stat;
703     VARIANT val, tmp;
704     VARIANT_BOOL b;
705     BOOL test_expr;
706     HRESULT hres;
707
708     TRACE("\n");
709
710     V_VT(&val) = VT_EMPTY;
711     test_expr = !stat->do_while;
712
713     while(1) {
714         if(test_expr) {
715             hres = expr_eval(ctx, stat->expr, &rt->ei, &tmp);
716             if(FAILED(hres))
717                 break;
718
719             hres = to_boolean(&tmp, &b);
720             VariantClear(&tmp);
721             if(FAILED(hres) || !b)
722                 break;
723         }else {
724             test_expr = TRUE;
725         }
726
727         hres = stat_eval(ctx, stat->statement, rt, &tmp);
728         if(FAILED(hres))
729             break;
730
731         VariantClear(&val);
732         val = tmp;
733
734         if(rt->type == RT_CONTINUE)
735             rt->type = RT_NORMAL;
736         if(rt->type != RT_NORMAL)
737             break;
738     }
739
740     if(FAILED(hres)) {
741         VariantClear(&val);
742         return hres;
743     }
744
745     if(rt->type == RT_BREAK)
746         rt->type = RT_NORMAL;
747
748     *ret = val;
749     return S_OK;
750 }
751
752 /* ECMA-262 3rd Edition    12.6.3 */
753 HRESULT for_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
754 {
755     for_statement_t *stat = (for_statement_t*)_stat;
756     VARIANT val, tmp, retv;
757     VARIANT_BOOL b;
758     HRESULT hres;
759
760     TRACE("\n");
761
762     if(stat->variable_list) {
763         hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
764         if(FAILED(hres))
765             return hres;
766     }else if(stat->begin_expr) {
767         hres = expr_eval(ctx, stat->begin_expr, &rt->ei, &val);
768         if(FAILED(hres))
769             return hres;
770
771         VariantClear(&val);
772     }
773
774     V_VT(&retv) = VT_EMPTY;
775
776     while(1) {
777         if(stat->expr) {
778             hres = expr_eval(ctx, stat->expr, &rt->ei, &tmp);
779             if(FAILED(hres))
780                 break;
781
782             hres = to_boolean(&tmp, &b);
783             VariantClear(&tmp);
784             if(FAILED(hres) || !b)
785                 break;
786         }
787
788         hres = stat_eval(ctx, stat->statement, rt, &tmp);
789         if(FAILED(hres))
790             break;
791
792         VariantClear(&retv);
793         retv = tmp;
794
795         if(rt->type == RT_CONTINUE)
796             rt->type = RT_NORMAL;
797         else if(rt->type != RT_NORMAL)
798             break;
799
800         if(stat->end_expr) {
801             hres = expr_eval(ctx, stat->end_expr, &rt->ei, &val);
802             if(FAILED(hres))
803                 break;
804
805             VariantClear(&val);
806         }
807     }
808
809     if(FAILED(hres)) {
810         VariantClear(&retv);
811         return hres;
812     }
813
814     if(rt->type == RT_BREAK)
815         rt->type = RT_NORMAL;
816
817     *ret = retv;
818     return S_OK;
819 }
820
821 /* ECMA-262 3rd Edition    12.6.4 */
822 static HRESULT interp_forin(exec_ctx_t *ctx)
823 {
824     const HRESULT arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
825     IDispatch *var_obj, *obj = NULL;
826     IDispatchEx *dispex;
827     DISPID id, var_id;
828     BSTR name = NULL;
829     VARIANT *val;
830     HRESULT hres;
831
832     TRACE("\n");
833
834     val = stack_pop(ctx);
835
836     assert(V_VT(stack_top(ctx)) == VT_I4);
837     id = V_I4(stack_top(ctx));
838
839     var_obj = stack_topn_objid(ctx, 1, &var_id);
840     if(!var_obj) {
841         FIXME("invalid ref\n");
842         VariantClear(val);
843         return E_FAIL;
844     }
845
846     if(V_VT(stack_topn(ctx, 3)) == VT_DISPATCH)
847         obj = V_DISPATCH(stack_topn(ctx, 3));
848
849     if(obj) {
850         hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
851         if(SUCCEEDED(hres)) {
852             hres = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, id, &id);
853             if(hres == S_OK)
854                 hres = IDispatchEx_GetMemberName(dispex, id, &name);
855             IDispatchEx_Release(dispex);
856             if(FAILED(hres)) {
857                 VariantClear(val);
858                 return hres;
859             }
860         }else {
861             TRACE("No IDispatchEx\n");
862         }
863     }
864
865     if(name) {
866         VARIANT v;
867
868         VariantClear(val);
869
870         V_I4(stack_top(ctx)) = id;
871
872         V_VT(&v) = VT_BSTR;
873         V_BSTR(&v) = name;
874         hres = disp_propput(ctx->parser->script, var_obj, var_id, &v, ctx->ei, NULL/*FIXME*/);
875         SysFreeString(name);
876         if(FAILED(hres))
877             return hres;
878
879         ctx->ip++;
880     }else {
881         stack_popn(ctx, 4);
882         ctx->ip = arg;
883         return stack_push(ctx, val);
884     }
885     return S_OK;
886 }
887
888 /* ECMA-262 3rd Edition    12.7 */
889 HRESULT continue_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
890 {
891     branch_statement_t *stat = (branch_statement_t*)_stat;
892
893     TRACE("\n");
894
895     if(stat->identifier) {
896         FIXME("indentifier not implemented\n");
897         return E_NOTIMPL;
898     }
899
900     rt->type = RT_CONTINUE;
901     V_VT(ret) = VT_EMPTY;
902     return S_OK;
903 }
904
905 /* ECMA-262 3rd Edition    12.8 */
906 HRESULT break_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
907 {
908     branch_statement_t *stat = (branch_statement_t*)_stat;
909
910     TRACE("\n");
911
912     if(stat->identifier) {
913         FIXME("indentifier not implemented\n");
914         return E_NOTIMPL;
915     }
916
917     rt->type = RT_BREAK;
918     V_VT(ret) = VT_EMPTY;
919     return S_OK;
920 }
921
922 /* ECMA-262 3rd Edition    12.9 */
923 HRESULT return_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
924 {
925     expression_statement_t *stat = (expression_statement_t*)_stat;
926     HRESULT hres;
927
928     TRACE("\n");
929
930     if(stat->expr) {
931         hres = expr_eval(ctx, stat->expr, &rt->ei, ret);
932         if(FAILED(hres))
933             return hres;
934     }else {
935         V_VT(ret) = VT_EMPTY;
936     }
937
938     TRACE("= %s\n", debugstr_variant(ret));
939     rt->type = RT_RETURN;
940     return S_OK;
941 }
942
943 /* ECMA-262 3rd Edition    12.10 */
944 HRESULT interp_push_scope(exec_ctx_t *ctx)
945 {
946     IDispatch *disp;
947     jsdisp_t *obj;
948     VARIANT *v;
949     HRESULT hres;
950
951     TRACE("\n");
952
953     v = stack_pop(ctx);
954     hres = to_object(ctx->parser->script, v, &disp);
955     VariantClear(v);
956     if(FAILED(hres))
957         return hres;
958
959     obj = to_jsdisp(disp);
960     if(!obj) {
961         IDispatch_Release(disp);
962         FIXME("disp is not jsdisp\n");
963         return E_NOTIMPL;
964     }
965
966     hres = scope_push(ctx->scope_chain, obj, &ctx->scope_chain);
967     jsdisp_release(obj);
968     return hres;
969 }
970
971 /* ECMA-262 3rd Edition    12.10 */
972 HRESULT interp_pop_scope(exec_ctx_t *ctx)
973 {
974     TRACE("\n");
975
976     scope_pop(&ctx->scope_chain);
977     return S_OK;
978 }
979
980 /* ECMA-262 3rd Edition    12.12 */
981 HRESULT interp_label(exec_ctx_t *ctx)
982 {
983     FIXME("\n");
984     return E_NOTIMPL;
985 }
986
987 /* ECMA-262 3rd Edition    12.13 */
988 static HRESULT interp_case(exec_ctx_t *ctx)
989 {
990     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
991     VARIANT *v;
992     BOOL b;
993     HRESULT hres;
994
995     TRACE("\n");
996
997     v = stack_pop(ctx);
998     hres = equal2_values(stack_top(ctx), v, &b);
999     VariantClear(v);
1000     if(FAILED(hres))
1001         return hres;
1002
1003     if(b) {
1004         stack_popn(ctx, 1);
1005         ctx->ip = arg;
1006     }else {
1007         ctx->ip++;
1008     }
1009     return S_OK;
1010 }
1011
1012 /* ECMA-262 3rd Edition    12.13 */
1013 HRESULT switch_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1014 {
1015     switch_statement_t *stat = (switch_statement_t*)_stat;
1016     case_clausule_t *iter, *default_clausule = NULL;
1017     statement_t *stat_iter;
1018     VARIANT val, cval;
1019     BOOL b;
1020     HRESULT hres;
1021
1022     TRACE("\n");
1023
1024     hres = expr_eval(ctx, stat->expr, &rt->ei, &val);
1025     if(FAILED(hres))
1026         return hres;
1027
1028     for(iter = stat->case_list; iter; iter = iter->next) {
1029         if(!iter->expr) {
1030             default_clausule = iter;
1031             continue;
1032         }
1033
1034         hres = expr_eval(ctx, iter->expr, &rt->ei, &cval);
1035         if(FAILED(hres))
1036             break;
1037
1038         hres = equal2_values(&val, &cval, &b);
1039         VariantClear(&cval);
1040         if(FAILED(hres) || b)
1041             break;
1042     }
1043
1044     VariantClear(&val);
1045     if(FAILED(hres))
1046         return hres;
1047
1048     if(!iter)
1049         iter = default_clausule;
1050
1051     V_VT(&val) = VT_EMPTY;
1052     if(iter) {
1053         VARIANT tmp;
1054
1055         for(stat_iter = iter->stat; stat_iter; stat_iter = stat_iter->next) {
1056             hres = stat_eval(ctx, stat_iter, rt, &tmp);
1057             if(FAILED(hres))
1058                 break;
1059
1060             VariantClear(&val);
1061             val = tmp;
1062
1063             if(rt->type != RT_NORMAL)
1064                 break;
1065         }
1066     }
1067
1068     if(FAILED(hres)) {
1069         VariantClear(&val);
1070         return hres;
1071     }
1072
1073     if(rt->type == RT_BREAK)
1074         rt->type = RT_NORMAL;
1075
1076     *ret = val;
1077     return S_OK;
1078 }
1079
1080 /* ECMA-262 3rd Edition    12.13 */
1081 static HRESULT interp_throw(exec_ctx_t *ctx)
1082 {
1083     TRACE("\n");
1084
1085     ctx->rt->ei.var = *stack_pop(ctx);
1086     return DISP_E_EXCEPTION;
1087 }
1088
1089 static HRESULT interp_throw_ref(exec_ctx_t *ctx)
1090 {
1091     const HRESULT arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1092
1093     TRACE("%08x\n", arg);
1094
1095     return throw_reference_error(ctx->parser->script, ctx->ei, arg, NULL);
1096 }
1097
1098 static HRESULT interp_throw_type(exec_ctx_t *ctx)
1099 {
1100     const HRESULT hres = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1101     const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg2.str;
1102
1103     TRACE("%08x %s\n", hres, debugstr_w(str));
1104
1105     return throw_type_error(ctx->parser->script, ctx->ei, hres, str);
1106 }
1107
1108 /* ECMA-262 3rd Edition    12.14 */
1109 static HRESULT catch_eval(script_ctx_t *ctx, catch_block_t *block, return_type_t *rt, VARIANT *ret)
1110 {
1111     jsdisp_t *var_disp;
1112     VARIANT ex, val;
1113     HRESULT hres;
1114
1115     ex = rt->ei.var;
1116     memset(&rt->ei, 0, sizeof(jsexcept_t));
1117
1118     hres = create_dispex(ctx, NULL, NULL, &var_disp);
1119     if(SUCCEEDED(hres)) {
1120         hres = jsdisp_propput_name(var_disp, block->identifier, &ex, &rt->ei, NULL/*FIXME*/);
1121         if(SUCCEEDED(hres)) {
1122             hres = scope_push(ctx->exec_ctx->scope_chain, var_disp, &ctx->exec_ctx->scope_chain);
1123             if(SUCCEEDED(hres)) {
1124                 hres = stat_eval(ctx, block->statement, rt, &val);
1125                 scope_pop(&ctx->exec_ctx->scope_chain);
1126             }
1127         }
1128
1129         jsdisp_release(var_disp);
1130     }
1131
1132     VariantClear(&ex);
1133     if(FAILED(hres))
1134         return hres;
1135
1136     *ret = val;
1137     return S_OK;
1138 }
1139
1140 /* ECMA-262 3rd Edition    12.14 */
1141 HRESULT try_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1142 {
1143     try_statement_t *stat = (try_statement_t*)_stat;
1144     VARIANT val;
1145     HRESULT hres;
1146
1147     TRACE("\n");
1148
1149     hres = stat_eval(ctx, stat->try_statement, rt, &val);
1150     if(FAILED(hres)) {
1151         TRACE("EXCEPTION\n");
1152         if(!stat->catch_block)
1153             return hres;
1154
1155         hres = catch_eval(ctx, stat->catch_block, rt, &val);
1156         if(FAILED(hres))
1157             return hres;
1158     }
1159
1160     if(stat->finally_statement) {
1161         VariantClear(&val);
1162         hres = stat_eval(ctx, stat->finally_statement, rt, &val);
1163         if(FAILED(hres))
1164             return hres;
1165     }
1166
1167     *ret = val;
1168     return S_OK;
1169 }
1170
1171 /* ECMA-262 3rd Edition    12.14 */
1172 static HRESULT interp_push_except(exec_ctx_t *ctx)
1173 {
1174     const unsigned arg1 = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1175     const BSTR arg2 = ctx->parser->code->instrs[ctx->ip].arg2.bstr;
1176     except_frame_t *except;
1177     unsigned stack_top;
1178
1179     TRACE("\n");
1180
1181     stack_top = ctx->top;
1182
1183     if(!arg2) {
1184         HRESULT hres;
1185
1186         hres = stack_push_bool(ctx, TRUE);
1187         if(FAILED(hres))
1188             return hres;
1189         hres = stack_push_bool(ctx, TRUE);
1190         if(FAILED(hres))
1191             return hres;
1192     }
1193
1194     except = heap_alloc(sizeof(*except));
1195     if(!except)
1196         return E_OUTOFMEMORY;
1197
1198     except->stack_top = stack_top;
1199     except->scope = ctx->scope_chain;
1200     except->catch_off = arg1;
1201     except->ident = arg2;
1202     except->next = ctx->except_frame;
1203     ctx->except_frame = except;
1204     return S_OK;
1205 }
1206
1207 /* ECMA-262 3rd Edition    12.14 */
1208 static HRESULT interp_pop_except(exec_ctx_t *ctx)
1209 {
1210     except_frame_t *except;
1211
1212     TRACE("\n");
1213
1214     except = ctx->except_frame;
1215     assert(except != NULL);
1216
1217     ctx->except_frame = except->next;
1218     heap_free(except);
1219     return S_OK;
1220 }
1221
1222 /* ECMA-262 3rd Edition    12.14 */
1223 static HRESULT interp_end_finally(exec_ctx_t *ctx)
1224 {
1225     VARIANT *v;
1226
1227     TRACE("\n");
1228
1229     v = stack_pop(ctx);
1230
1231     assert(V_VT(stack_top(ctx)) == VT_BOOL);
1232     if(!V_BOOL(stack_top(ctx))) {
1233         TRACE("passing exception\n");
1234
1235         VariantClear(v);
1236         stack_popn(ctx, 1);
1237         ctx->rt->ei.var = *stack_pop(ctx);
1238         return DISP_E_EXCEPTION;
1239     }
1240
1241     stack_popn(ctx, 2);
1242     return stack_push(ctx, v);
1243 }
1244
1245 /* ECMA-262 3rd Edition    13 */
1246 static HRESULT interp_func(exec_ctx_t *ctx)
1247 {
1248     function_expression_t *expr = ctx->parser->code->instrs[ctx->ip].arg1.func;
1249     jsdisp_t *dispex;
1250     VARIANT v;
1251     HRESULT hres;
1252
1253     TRACE("\n");
1254
1255     hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain,
1256             expr->src_str, expr->src_len, &dispex);
1257     if(FAILED(hres))
1258         return hres;
1259
1260     var_set_jsdisp(&v, dispex);
1261     return stack_push(ctx, &v);
1262 }
1263
1264 /* ECMA-262 3rd Edition    11.2.1 */
1265 static HRESULT interp_array(exec_ctx_t *ctx)
1266 {
1267     VARIANT v, *namev;
1268     IDispatch *obj;
1269     DISPID id;
1270     BSTR name;
1271     HRESULT hres;
1272
1273     TRACE("\n");
1274
1275     namev = stack_pop(ctx);
1276
1277     hres = stack_pop_object(ctx, &obj);
1278     if(FAILED(hres)) {
1279         VariantClear(namev);
1280         return hres;
1281     }
1282
1283     hres = to_string(ctx->parser->script, namev, ctx->ei, &name);
1284     VariantClear(namev);
1285     if(FAILED(hres)) {
1286         IDispatch_Release(obj);
1287         return hres;
1288     }
1289
1290     hres = disp_get_id(ctx->parser->script, obj, name, 0, &id);
1291     SysFreeString(name);
1292     if(SUCCEEDED(hres)) {
1293         hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1294     }else if(hres == DISP_E_UNKNOWNNAME) {
1295         V_VT(&v) = VT_EMPTY;
1296         hres = S_OK;
1297     }
1298     IDispatch_Release(obj);
1299     if(FAILED(hres))
1300         return hres;
1301
1302     return stack_push(ctx, &v);
1303 }
1304
1305 /* ECMA-262 3rd Edition    11.2.1 */
1306 static HRESULT interp_member(exec_ctx_t *ctx)
1307 {
1308     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1309     IDispatch *obj;
1310     VARIANT v;
1311     DISPID id;
1312     HRESULT hres;
1313
1314     TRACE("\n");
1315
1316     hres = stack_pop_object(ctx, &obj);
1317     if(FAILED(hres))
1318         return hres;
1319
1320     hres = disp_get_id(ctx->parser->script, obj, arg, 0, &id);
1321     if(SUCCEEDED(hres)) {
1322         V_VT(&v) = VT_EMPTY;
1323         hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1324     }else if(hres == DISP_E_UNKNOWNNAME) {
1325         V_VT(&v) = VT_EMPTY;
1326         hres = S_OK;
1327     }
1328     IDispatch_Release(obj);
1329     if(FAILED(hres))
1330         return hres;
1331
1332     return stack_push(ctx, &v);
1333 }
1334
1335 /* ECMA-262 3rd Edition    11.2.1 */
1336 static HRESULT interp_memberid(exec_ctx_t *ctx)
1337 {
1338     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1339     VARIANT *objv, *namev;
1340     IDispatch *obj;
1341     BSTR name;
1342     DISPID id;
1343     HRESULT hres;
1344
1345     TRACE("%x\n", arg);
1346
1347     namev = stack_pop(ctx);
1348     objv = stack_pop(ctx);
1349
1350     hres = to_object(ctx->parser->script, objv, &obj);
1351     VariantClear(objv);
1352     if(SUCCEEDED(hres)) {
1353         hres = to_string(ctx->parser->script, namev, ctx->ei, &name);
1354         if(FAILED(hres))
1355             IDispatch_Release(obj);
1356     }
1357     VariantClear(namev);
1358     if(FAILED(hres))
1359         return hres;
1360
1361     hres = disp_get_id(ctx->parser->script, obj, name, arg, &id);
1362     SysFreeString(name);
1363     if(FAILED(hres)) {
1364         IDispatch_Release(obj);
1365         if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
1366             obj = NULL;
1367             id = JS_E_INVALID_PROPERTY;
1368         }else {
1369             return hres;
1370         }
1371     }
1372
1373     return stack_push_objid(ctx, obj, id);
1374 }
1375
1376 /* ECMA-262 3rd Edition    11.2.1 */
1377 static HRESULT interp_refval(exec_ctx_t *ctx)
1378 {
1379     IDispatch *disp;
1380     VARIANT v;
1381     DISPID id;
1382     HRESULT hres;
1383
1384     TRACE("\n");
1385
1386     disp = stack_topn_objid(ctx, 0, &id);
1387     if(!disp)
1388         return throw_reference_error(ctx->parser->script, ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
1389
1390     hres = disp_propget(ctx->parser->script, disp, id, &v, ctx->ei, NULL/*FIXME*/);
1391     if(FAILED(hres))
1392         return hres;
1393
1394     return stack_push(ctx, &v);
1395 }
1396
1397 static void jsstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, DISPPARAMS *dp)
1398 {
1399     VARIANT tmp;
1400     unsigned i;
1401
1402     dp->cArgs = arg_cnt;
1403     dp->rgdispidNamedArgs = NULL;
1404     dp->cNamedArgs = 0;
1405
1406     assert(ctx->top >= arg_cnt);
1407
1408     for(i=1; i*2 <= arg_cnt; i++) {
1409         tmp = ctx->stack[ctx->top-i];
1410         ctx->stack[ctx->top-i] = ctx->stack[ctx->top-arg_cnt+i-1];
1411         ctx->stack[ctx->top-arg_cnt+i-1] = tmp;
1412     }
1413
1414     dp->rgvarg = ctx->stack + ctx->top-arg_cnt;
1415 }
1416
1417 /* ECMA-262 3rd Edition    11.2.2 */
1418 static HRESULT interp_new(exec_ctx_t *ctx)
1419 {
1420     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1421     VARIANT *constr, v;
1422     DISPPARAMS dp;
1423     HRESULT hres;
1424
1425     TRACE("%d\n", arg);
1426
1427     constr = stack_topn(ctx, arg);
1428
1429     /* NOTE: Should use to_object here */
1430
1431     if(V_VT(constr) == VT_NULL)
1432         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1433     else if(V_VT(constr) != VT_DISPATCH)
1434         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_ACTION, NULL);
1435     else if(!V_DISPATCH(constr))
1436         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1437
1438     jsstack_to_dp(ctx, arg, &dp);
1439     hres = disp_call(ctx->parser->script, V_DISPATCH(constr), DISPID_VALUE,
1440             DISPATCH_CONSTRUCT, &dp, &v, ctx->ei, NULL/*FIXME*/);
1441     if(FAILED(hres))
1442         return hres;
1443
1444     stack_popn(ctx, arg+1);
1445     return stack_push(ctx, &v);
1446 }
1447
1448 /* ECMA-262 3rd Edition    11.2.3 */
1449 static HRESULT interp_call(exec_ctx_t *ctx)
1450 {
1451     const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1452     const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1453     VARIANT v, *objv;
1454     DISPPARAMS dp;
1455     HRESULT hres;
1456
1457     TRACE("%d %d\n", argn, do_ret);
1458
1459     objv = stack_topn(ctx, argn);
1460     if(V_VT(objv) != VT_DISPATCH)
1461         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1462
1463     jsstack_to_dp(ctx, argn, &dp);
1464     hres = disp_call(ctx->parser->script, V_DISPATCH(objv), DISPID_VALUE, DISPATCH_METHOD, &dp,
1465             do_ret ? &v : NULL, ctx->ei, NULL/*FIXME*/);
1466     if(FAILED(hres))
1467         return hres;
1468
1469     stack_popn(ctx, argn+1);
1470     return do_ret ? stack_push(ctx, &v) : S_OK;
1471
1472 }
1473
1474 /* ECMA-262 3rd Edition    11.2.3 */
1475 static HRESULT interp_call_member(exec_ctx_t *ctx)
1476 {
1477     const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1478     const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1479     IDispatch *obj;
1480     DISPPARAMS dp;
1481     VARIANT v;
1482     DISPID id;
1483     HRESULT hres;
1484
1485     TRACE("%d %d\n", argn, do_ret);
1486
1487     obj = stack_topn_objid(ctx, argn, &id);
1488     if(!obj)
1489         return throw_type_error(ctx->parser->script, ctx->ei, id, NULL);
1490
1491     jsstack_to_dp(ctx, argn, &dp);
1492     hres = disp_call(ctx->parser->script, obj, id, DISPATCH_METHOD, &dp, do_ret ? &v : NULL, ctx->ei, NULL/*FIXME*/);
1493     if(FAILED(hres))
1494         return hres;
1495
1496     stack_popn(ctx, argn+2);
1497     return do_ret ? stack_push(ctx, &v) : S_OK;
1498
1499 }
1500
1501 /* ECMA-262 3rd Edition    11.1.1 */
1502 static HRESULT interp_this(exec_ctx_t *ctx)
1503 {
1504     VARIANT v;
1505
1506     TRACE("\n");
1507
1508     V_VT(&v) = VT_DISPATCH;
1509     V_DISPATCH(&v) = ctx->this_obj;
1510     IDispatch_AddRef(ctx->this_obj);
1511     return stack_push(ctx, &v);
1512 }
1513
1514 /* ECMA-262 3rd Edition    10.1.4 */
1515 static HRESULT interp_ident(exec_ctx_t *ctx)
1516 {
1517     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1518     exprval_t exprval;
1519     VARIANT v;
1520     HRESULT hres;
1521
1522     TRACE("%s\n", debugstr_w(arg));
1523
1524     hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
1525     if(FAILED(hres))
1526         return hres;
1527
1528     if(exprval.type == EXPRVAL_INVALID)
1529         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_UNDEFINED_VARIABLE, arg);
1530
1531     hres = exprval_to_value(ctx->parser->script, &exprval, ctx->ei, &v);
1532     exprval_release(&exprval);
1533     if(FAILED(hres))
1534         return hres;
1535
1536     return stack_push(ctx, &v);
1537 }
1538
1539 /* ECMA-262 3rd Edition    10.1.4 */
1540 static HRESULT interp_identid(exec_ctx_t *ctx)
1541 {
1542     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1543     const unsigned flags = ctx->parser->code->instrs[ctx->ip].arg2.uint;
1544     exprval_t exprval;
1545     HRESULT hres;
1546
1547     TRACE("%s %x\n", debugstr_w(arg), flags);
1548
1549     hres = identifier_eval(ctx->parser->script, arg, flags, ctx->ei, &exprval);
1550     if(FAILED(hres))
1551         return hres;
1552
1553     if(exprval.type != EXPRVAL_IDREF) {
1554         WARN("invalid ref\n");
1555         exprval_release(&exprval);
1556         return stack_push_objid(ctx, NULL, JS_E_OBJECT_EXPECTED);
1557     }
1558
1559     return stack_push_objid(ctx, exprval.u.idref.disp, exprval.u.idref.id);
1560 }
1561
1562 /* ECMA-262 3rd Edition    7.8.1 */
1563 static HRESULT interp_null(exec_ctx_t *ctx)
1564 {
1565     VARIANT v;
1566
1567     TRACE("\n");
1568
1569     V_VT(&v) = VT_NULL;
1570     return stack_push(ctx, &v);
1571 }
1572
1573 /* ECMA-262 3rd Edition    7.8.2 */
1574 static HRESULT interp_bool(exec_ctx_t *ctx)
1575 {
1576     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1577
1578     TRACE("%s\n", arg ? "true" : "false");
1579
1580     return stack_push_bool(ctx, arg);
1581 }
1582
1583 /* ECMA-262 3rd Edition    7.8.3 */
1584 static HRESULT interp_int(exec_ctx_t *ctx)
1585 {
1586     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1587     VARIANT v;
1588
1589     TRACE("%d\n", arg);
1590
1591     V_VT(&v) = VT_I4;
1592     V_I4(&v) = arg;
1593     return stack_push(ctx, &v);
1594 }
1595
1596 /* ECMA-262 3rd Edition    7.8.3 */
1597 static HRESULT interp_double(exec_ctx_t *ctx)
1598 {
1599     const double arg = *ctx->parser->code->instrs[ctx->ip].arg1.dbl;
1600     VARIANT v;
1601
1602     TRACE("%lf\n", arg);
1603
1604     V_VT(&v) = VT_R8;
1605     V_R8(&v) = arg;
1606     return stack_push(ctx, &v);
1607 }
1608
1609 /* ECMA-262 3rd Edition    7.8.4 */
1610 static HRESULT interp_str(exec_ctx_t *ctx)
1611 {
1612     const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg1.str;
1613     VARIANT v;
1614
1615     TRACE("%s\n", debugstr_w(str));
1616
1617     V_VT(&v) = VT_BSTR;
1618     V_BSTR(&v) = SysAllocString(str);
1619     if(!V_BSTR(&v))
1620         return E_OUTOFMEMORY;
1621
1622     return stack_push(ctx, &v);
1623 }
1624
1625 /* ECMA-262 3rd Edition    7.8 */
1626 static HRESULT interp_regexp(exec_ctx_t *ctx)
1627 {
1628     const WCHAR *source = ctx->parser->code->instrs[ctx->ip].arg1.str;
1629     const LONG flags = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1630     jsdisp_t *regexp;
1631     VARIANT v;
1632     HRESULT hres;
1633
1634     TRACE("%s %x\n", debugstr_w(source), flags);
1635
1636     hres = create_regexp(ctx->parser->script, source, strlenW(source), flags, &regexp);
1637     if(FAILED(hres))
1638         return hres;
1639
1640     var_set_jsdisp(&v, regexp);
1641     return stack_push(ctx, &v);
1642 }
1643
1644 /* ECMA-262 3rd Edition    11.1.4 */
1645 static HRESULT interp_carray(exec_ctx_t *ctx)
1646 {
1647     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1648     jsdisp_t *array;
1649     VARIANT *v, r;
1650     unsigned i;
1651     HRESULT hres;
1652
1653     TRACE("%u\n", arg);
1654
1655     hres = create_array(ctx->parser->script, arg, &array);
1656     if(FAILED(hres))
1657         return hres;
1658
1659     i = arg;
1660     while(i--) {
1661         v = stack_pop(ctx);
1662         hres = jsdisp_propput_idx(array, i, v, ctx->ei, NULL/*FIXME*/);
1663         VariantClear(v);
1664         if(FAILED(hres)) {
1665             jsdisp_release(array);
1666             return hres;
1667         }
1668     }
1669
1670     var_set_jsdisp(&r, array);
1671     return stack_push(ctx, &r);
1672 }
1673
1674 /* ECMA-262 3rd Edition    11.1.5 */
1675 HRESULT interp_new_obj(exec_ctx_t *ctx)
1676 {
1677     jsdisp_t *obj;
1678     VARIANT v;
1679     HRESULT hres;
1680
1681     TRACE("\n");
1682
1683     hres = create_object(ctx->parser->script, NULL, &obj);
1684     if(FAILED(hres))
1685         return hres;
1686
1687     var_set_jsdisp(&v, obj);
1688     return stack_push(ctx, &v);
1689 }
1690
1691 /* ECMA-262 3rd Edition    11.1.5 */
1692 HRESULT interp_obj_prop(exec_ctx_t *ctx)
1693 {
1694     const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1695     jsdisp_t *obj;
1696     VARIANT *v;
1697     HRESULT hres;
1698
1699     TRACE("%s\n", debugstr_w(name));
1700
1701     v = stack_pop(ctx);
1702
1703     assert(V_VT(stack_top(ctx)) == VT_DISPATCH);
1704     obj = as_jsdisp(V_DISPATCH(stack_top(ctx)));
1705
1706     hres = jsdisp_propput_name(obj, name, v, ctx->ei, NULL/*FIXME*/);
1707     VariantClear(v);
1708     return hres;
1709 }
1710
1711 /* ECMA-262 3rd Edition    11.11 */
1712 static HRESULT interp_cnd_nz(exec_ctx_t *ctx)
1713 {
1714     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1715     VARIANT_BOOL b;
1716     HRESULT hres;
1717
1718     TRACE("\n");
1719
1720     hres = to_boolean(stack_top(ctx), &b);
1721     if(FAILED(hres))
1722         return hres;
1723
1724     if(b) {
1725         ctx->ip = arg;
1726     }else {
1727         stack_popn(ctx, 1);
1728         ctx->ip++;
1729     }
1730     return S_OK;
1731 }
1732
1733 /* ECMA-262 3rd Edition    11.11 */
1734 static HRESULT interp_cnd_z(exec_ctx_t *ctx)
1735 {
1736     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1737     VARIANT_BOOL b;
1738     HRESULT hres;
1739
1740     TRACE("\n");
1741
1742     hres = to_boolean(stack_top(ctx), &b);
1743     if(FAILED(hres))
1744         return hres;
1745
1746     if(b) {
1747         stack_popn(ctx, 1);
1748         ctx->ip++;
1749     }else {
1750         ctx->ip = arg;
1751     }
1752     return S_OK;
1753 }
1754
1755 /* ECMA-262 3rd Edition    11.10 */
1756 static HRESULT interp_or(exec_ctx_t *ctx)
1757 {
1758     INT l, r;
1759     HRESULT hres;
1760
1761     TRACE("\n");
1762
1763     hres = stack_pop_int(ctx, &r);
1764     if(FAILED(hres))
1765         return hres;
1766
1767     hres = stack_pop_int(ctx, &l);
1768     if(FAILED(hres))
1769         return hres;
1770
1771     return stack_push_int(ctx, l|r);
1772 }
1773
1774 /* ECMA-262 3rd Edition    11.10 */
1775 static HRESULT interp_xor(exec_ctx_t *ctx)
1776 {
1777     INT l, r;
1778     HRESULT hres;
1779
1780     TRACE("\n");
1781
1782     hres = stack_pop_int(ctx, &r);
1783     if(FAILED(hres))
1784         return hres;
1785
1786     hres = stack_pop_int(ctx, &l);
1787     if(FAILED(hres))
1788         return hres;
1789
1790     return stack_push_int(ctx, l^r);
1791 }
1792
1793 /* ECMA-262 3rd Edition    11.10 */
1794 static HRESULT interp_and(exec_ctx_t *ctx)
1795 {
1796     INT l, r;
1797     HRESULT hres;
1798
1799     TRACE("\n");
1800
1801     hres = stack_pop_int(ctx, &r);
1802     if(FAILED(hres))
1803         return hres;
1804
1805     hres = stack_pop_int(ctx, &l);
1806     if(FAILED(hres))
1807         return hres;
1808
1809     return stack_push_int(ctx, l&r);
1810 }
1811
1812 /* ECMA-262 3rd Edition    11.8.6 */
1813 static HRESULT interp_instanceof(exec_ctx_t *ctx)
1814 {
1815     jsdisp_t *obj, *iter, *tmp = NULL;
1816     VARIANT prot, *v;
1817     BOOL ret = FALSE;
1818     HRESULT hres;
1819
1820     static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
1821
1822     v = stack_pop(ctx);
1823     if(V_VT(v) != VT_DISPATCH || !V_DISPATCH(v)) {
1824         VariantClear(v);
1825         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
1826     }
1827
1828     obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
1829     IDispatch_Release(V_DISPATCH(v));
1830     if(!obj) {
1831         FIXME("non-jsdisp objects not supported\n");
1832         return E_FAIL;
1833     }
1834
1835     if(is_class(obj, JSCLASS_FUNCTION)) {
1836         hres = jsdisp_propget_name(obj, prototypeW, &prot, ctx->ei, NULL/*FIXME*/);
1837     }else {
1838         hres = throw_type_error(ctx->parser->script, ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
1839     }
1840     jsdisp_release(obj);
1841     if(FAILED(hres))
1842         return hres;
1843
1844     v = stack_pop(ctx);
1845
1846     if(V_VT(&prot) == VT_DISPATCH) {
1847         if(V_VT(v) == VT_DISPATCH)
1848             tmp = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
1849         for(iter = tmp; !ret && iter; iter = iter->prototype) {
1850             hres = disp_cmp(V_DISPATCH(&prot), to_disp(iter), &ret);
1851             if(FAILED(hres))
1852                 break;
1853         }
1854
1855         if(tmp)
1856             jsdisp_release(tmp);
1857     }else {
1858         FIXME("prototype is not an object\n");
1859         hres = E_FAIL;
1860     }
1861
1862     VariantClear(&prot);
1863     VariantClear(v);
1864     if(FAILED(hres))
1865         return hres;
1866
1867     return stack_push_bool(ctx, ret);
1868 }
1869
1870 /* ECMA-262 3rd Edition    11.8.7 */
1871 static HRESULT interp_in(exec_ctx_t *ctx)
1872 {
1873     VARIANT *obj, *v;
1874     DISPID id = 0;
1875     BOOL ret;
1876     BSTR str;
1877     HRESULT hres;
1878
1879     TRACE("\n");
1880
1881     obj = stack_pop(ctx);
1882     v = stack_pop(ctx);
1883
1884     if(V_VT(obj) != VT_DISPATCH || !V_DISPATCH(obj)) {
1885         VariantClear(obj);
1886         VariantClear(v);
1887         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1888     }
1889
1890     hres = to_string(ctx->parser->script, v, ctx->ei, &str);
1891     VariantClear(v);
1892     if(FAILED(hres)) {
1893         IDispatch_Release(V_DISPATCH(obj));
1894         return hres;
1895     }
1896
1897     hres = disp_get_id(ctx->parser->script, V_DISPATCH(obj), str, 0, &id);
1898     IDispatch_Release(V_DISPATCH(obj));
1899     SysFreeString(str);
1900     if(SUCCEEDED(hres))
1901         ret = TRUE;
1902     else if(hres == DISP_E_UNKNOWNNAME)
1903         ret = FALSE;
1904     else
1905         return hres;
1906
1907     return stack_push_bool(ctx, ret);
1908 }
1909
1910 /* ECMA-262 3rd Edition    11.6.1 */
1911 static HRESULT add_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
1912 {
1913     VARIANT r, l;
1914     HRESULT hres;
1915
1916     hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
1917     if(FAILED(hres))
1918         return hres;
1919
1920     hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
1921     if(FAILED(hres)) {
1922         VariantClear(&l);
1923         return hres;
1924     }
1925
1926     if(V_VT(&l) == VT_BSTR || V_VT(&r) == VT_BSTR) {
1927         BSTR lstr = NULL, rstr = NULL;
1928
1929         if(V_VT(&l) == VT_BSTR)
1930             lstr = V_BSTR(&l);
1931         else
1932             hres = to_string(ctx, &l, ei, &lstr);
1933
1934         if(SUCCEEDED(hres)) {
1935             if(V_VT(&r) == VT_BSTR)
1936                 rstr = V_BSTR(&r);
1937             else
1938                 hres = to_string(ctx, &r, ei, &rstr);
1939         }
1940
1941         if(SUCCEEDED(hres)) {
1942             int len1, len2;
1943
1944             len1 = SysStringLen(lstr);
1945             len2 = SysStringLen(rstr);
1946
1947             V_VT(retv) = VT_BSTR;
1948             V_BSTR(retv) = SysAllocStringLen(NULL, len1+len2);
1949             memcpy(V_BSTR(retv), lstr, len1*sizeof(WCHAR));
1950             memcpy(V_BSTR(retv)+len1, rstr, (len2+1)*sizeof(WCHAR));
1951         }
1952
1953         if(V_VT(&l) != VT_BSTR)
1954             SysFreeString(lstr);
1955         if(V_VT(&r) != VT_BSTR)
1956             SysFreeString(rstr);
1957     }else {
1958         VARIANT nl, nr;
1959
1960         hres = to_number(ctx, &l, ei, &nl);
1961         if(SUCCEEDED(hres)) {
1962             hres = to_number(ctx, &r, ei, &nr);
1963             if(SUCCEEDED(hres))
1964                 num_set_val(retv, num_val(&nl) + num_val(&nr));
1965         }
1966     }
1967
1968     VariantClear(&r);
1969     VariantClear(&l);
1970     return hres;
1971 }
1972
1973 /* ECMA-262 3rd Edition    11.6.1 */
1974 static HRESULT interp_add(exec_ctx_t *ctx)
1975 {
1976     VARIANT *l, *r, ret;
1977     HRESULT hres;
1978
1979     r = stack_pop(ctx);
1980     l = stack_pop(ctx);
1981
1982     TRACE("%s + %s\n", debugstr_variant(l), debugstr_variant(r));
1983
1984     hres = add_eval(ctx->parser->script, l, r, ctx->ei, &ret);
1985     VariantClear(l);
1986     VariantClear(r);
1987     if(FAILED(hres))
1988         return hres;
1989
1990     return stack_push(ctx, &ret);
1991 }
1992
1993 /* ECMA-262 3rd Edition    11.6.2 */
1994 static HRESULT interp_sub(exec_ctx_t *ctx)
1995 {
1996     VARIANT l, r;
1997     HRESULT hres;
1998
1999     TRACE("\n");
2000
2001     hres = stack_pop_number(ctx, &r);
2002     if(FAILED(hres))
2003         return hres;
2004
2005     hres = stack_pop_number(ctx, &l);
2006     if(FAILED(hres))
2007         return hres;
2008
2009     return stack_push_number(ctx, num_val(&l)-num_val(&r));
2010 }
2011
2012 /* ECMA-262 3rd Edition    11.5.1 */
2013 static HRESULT interp_mul(exec_ctx_t *ctx)
2014 {
2015     VARIANT l, r;
2016     HRESULT hres;
2017
2018     TRACE("\n");
2019
2020     hres = stack_pop_number(ctx, &r);
2021     if(FAILED(hres))
2022         return hres;
2023
2024     hres = stack_pop_number(ctx, &l);
2025     if(FAILED(hres))
2026         return hres;
2027
2028     return stack_push_number(ctx, num_val(&l)*num_val(&r));
2029 }
2030
2031 /* ECMA-262 3rd Edition    11.5.2 */
2032 static HRESULT interp_div(exec_ctx_t *ctx)
2033 {
2034     VARIANT l, r;
2035     HRESULT hres;
2036
2037     TRACE("\n");
2038
2039     hres = stack_pop_number(ctx, &r);
2040     if(FAILED(hres))
2041         return hres;
2042
2043     hres = stack_pop_number(ctx, &l);
2044     if(FAILED(hres))
2045         return hres;
2046
2047     return stack_push_number(ctx, num_val(&l)/num_val(&r));
2048 }
2049
2050 /* ECMA-262 3rd Edition    11.5.3 */
2051 static HRESULT interp_mod(exec_ctx_t *ctx)
2052 {
2053     VARIANT l, r;
2054     HRESULT hres;
2055
2056     TRACE("\n");
2057
2058     hres = stack_pop_number(ctx, &r);
2059     if(FAILED(hres))
2060         return hres;
2061
2062     hres = stack_pop_number(ctx, &l);
2063     if(FAILED(hres))
2064         return hres;
2065
2066     return stack_push_number(ctx, fmod(num_val(&l), num_val(&r)));
2067 }
2068
2069 /* ECMA-262 3rd Edition    11.4.2 */
2070 static HRESULT interp_delete(exec_ctx_t *ctx)
2071 {
2072     VARIANT *obj_var, *name_var;
2073     IDispatchEx *dispex;
2074     IDispatch *obj;
2075     BSTR name;
2076     BOOL ret;
2077     HRESULT hres;
2078
2079     TRACE("\n");
2080
2081     name_var = stack_pop(ctx);
2082     obj_var = stack_pop(ctx);
2083
2084     hres = to_object(ctx->parser->script, obj_var, &obj);
2085     VariantClear(obj_var);
2086     if(FAILED(hres)) {
2087         VariantClear(name_var);
2088         return hres;
2089     }
2090
2091     hres = to_string(ctx->parser->script, name_var, ctx->ei, &name);
2092     VariantClear(name_var);
2093     if(FAILED(hres)) {
2094         IDispatch_Release(obj);
2095         return hres;
2096     }
2097
2098     hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
2099     if(SUCCEEDED(hres)) {
2100         hres = IDispatchEx_DeleteMemberByName(dispex, name, make_grfdex(ctx->parser->script, fdexNameCaseSensitive));
2101         ret = TRUE;
2102         IDispatchEx_Release(dispex);
2103     }else {
2104         hres = S_OK;
2105         ret = FALSE;
2106     }
2107
2108     IDispatch_Release(obj);
2109     SysFreeString(name);
2110     if(FAILED(hres))
2111         return hres;
2112
2113     return stack_push_bool(ctx, ret);
2114 }
2115
2116 /* ECMA-262 3rd Edition    11.4.2 */
2117 static HRESULT interp_delete_ident(exec_ctx_t *ctx)
2118 {
2119     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2120     IDispatchEx *dispex;
2121     exprval_t exprval;
2122     BOOL ret = FALSE;
2123     HRESULT hres;
2124
2125     TRACE("%s\n", debugstr_w(arg));
2126
2127     hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
2128     if(FAILED(hres))
2129         return hres;
2130
2131     if(exprval.type != EXPRVAL_IDREF) {
2132         FIXME("Unsupported exprval\n");
2133         exprval_release(&exprval);
2134         return E_NOTIMPL;
2135     }
2136
2137     hres = IDispatch_QueryInterface(exprval.u.idref.disp, &IID_IDispatchEx, (void**)&dispex);
2138     IDispatch_Release(exprval.u.idref.disp);
2139     if(SUCCEEDED(hres)) {
2140         hres = IDispatchEx_DeleteMemberByDispID(dispex, exprval.u.idref.id);
2141         IDispatchEx_Release(dispex);
2142         if(FAILED(hres))
2143             return hres;
2144
2145         ret = TRUE;
2146     }
2147
2148     return stack_push_bool(ctx, ret);
2149 }
2150
2151 /* ECMA-262 3rd Edition    11.4.2 */
2152 static HRESULT interp_void(exec_ctx_t *ctx)
2153 {
2154     VARIANT v;
2155
2156     TRACE("\n");
2157
2158     stack_popn(ctx, 1);
2159
2160     V_VT(&v) = VT_EMPTY;
2161     return stack_push(ctx, &v);
2162 }
2163
2164 /* ECMA-262 3rd Edition    11.4.3 */
2165 static HRESULT typeof_string(VARIANT *v, const WCHAR **ret)
2166 {
2167     switch(V_VT(v)) {
2168     case VT_EMPTY:
2169         *ret = undefinedW;
2170         break;
2171     case VT_NULL:
2172         *ret = objectW;
2173         break;
2174     case VT_BOOL:
2175         *ret = booleanW;
2176         break;
2177     case VT_I4:
2178     case VT_R8:
2179         *ret = numberW;
2180         break;
2181     case VT_BSTR:
2182         *ret = stringW;
2183         break;
2184     case VT_DISPATCH: {
2185         jsdisp_t *dispex;
2186
2187         if(V_DISPATCH(v) && (dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(v)))) {
2188             *ret = is_class(dispex, JSCLASS_FUNCTION) ? functionW : objectW;
2189             jsdisp_release(dispex);
2190         }else {
2191             *ret = objectW;
2192         }
2193         break;
2194     }
2195     default:
2196         FIXME("unhandled vt %d\n", V_VT(v));
2197         return E_NOTIMPL;
2198     }
2199
2200     return S_OK;
2201 }
2202
2203 /* ECMA-262 3rd Edition    11.4.3 */
2204 static HRESULT interp_typeofid(exec_ctx_t *ctx)
2205 {
2206     const WCHAR *ret;
2207     IDispatch *obj;
2208     VARIANT v;
2209     DISPID id;
2210     HRESULT hres;
2211
2212     static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
2213
2214     TRACE("\n");
2215
2216     obj = stack_pop_objid(ctx, &id);
2217     if(!obj)
2218         return stack_push_string(ctx, undefinedW);
2219
2220     V_VT(&v) = VT_EMPTY;
2221     hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2222     IDispatch_Release(obj);
2223     if(FAILED(hres))
2224         return stack_push_string(ctx, unknownW);
2225
2226     hres = typeof_string(&v, &ret);
2227     VariantClear(&v);
2228     if(FAILED(hres))
2229         return hres;
2230
2231     return stack_push_string(ctx, ret);
2232 }
2233
2234 /* ECMA-262 3rd Edition    11.4.3 */
2235 static HRESULT interp_typeofident(exec_ctx_t *ctx)
2236 {
2237     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2238     exprval_t exprval;
2239     const WCHAR *ret;
2240     VARIANT v;
2241     HRESULT hres;
2242
2243     TRACE("%s\n", debugstr_w(arg));
2244
2245     hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
2246     if(FAILED(hres))
2247         return hres;
2248
2249     if(exprval.type == EXPRVAL_INVALID) {
2250         hres = stack_push_string(ctx, undefinedW);
2251         exprval_release(&exprval);
2252         return hres;
2253     }
2254
2255     hres = exprval_to_value(ctx->parser->script, &exprval, ctx->ei, &v);
2256     exprval_release(&exprval);
2257     if(FAILED(hres))
2258         return hres;
2259
2260     hres = typeof_string(&v, &ret);
2261     VariantClear(&v);
2262     if(FAILED(hres))
2263         return hres;
2264
2265     return stack_push_string(ctx, ret);
2266 }
2267
2268 /* ECMA-262 3rd Edition    11.4.3 */
2269 static HRESULT interp_typeof(exec_ctx_t *ctx)
2270 {
2271     const WCHAR *ret;
2272     VARIANT *v;
2273     HRESULT hres;
2274
2275     TRACE("\n");
2276
2277     v = stack_pop(ctx);
2278     hres = typeof_string(v, &ret);
2279     VariantClear(v);
2280     if(FAILED(hres))
2281         return hres;
2282
2283     return stack_push_string(ctx, ret);
2284 }
2285
2286 /* ECMA-262 3rd Edition    11.4.7 */
2287 static HRESULT interp_minus(exec_ctx_t *ctx)
2288 {
2289     VARIANT n;
2290     HRESULT hres;
2291
2292     TRACE("\n");
2293
2294     hres = stack_pop_number(ctx, &n);
2295     if(FAILED(hres))
2296         return hres;
2297
2298     return stack_push_number(ctx, -num_val(&n));
2299 }
2300
2301 /* ECMA-262 3rd Edition    11.4.6 */
2302 static HRESULT interp_tonum(exec_ctx_t *ctx)
2303 {
2304     VARIANT *v, num;
2305     HRESULT hres;
2306
2307     TRACE("\n");
2308
2309     v = stack_pop(ctx);
2310     hres = to_number(ctx->parser->script, v, ctx->ei, &num);
2311     VariantClear(v);
2312     if(FAILED(hres))
2313         return hres;
2314
2315     return stack_push(ctx, &num);
2316 }
2317
2318 /* ECMA-262 3rd Edition    11.3.1 */
2319 static HRESULT interp_postinc(exec_ctx_t *ctx)
2320 {
2321     const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2322     IDispatch *obj;
2323     DISPID id;
2324     VARIANT v;
2325     HRESULT hres;
2326
2327     TRACE("%d\n", arg);
2328
2329     obj = stack_pop_objid(ctx, &id);
2330     if(!obj)
2331         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2332
2333     hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2334     if(SUCCEEDED(hres)) {
2335         VARIANT n, inc;
2336
2337         hres = to_number(ctx->parser->script, &v, ctx->ei, &n);
2338         if(SUCCEEDED(hres)) {
2339             num_set_val(&inc, num_val(&n)+(double)arg);
2340             hres = disp_propput(ctx->parser->script, obj, id, &inc, ctx->ei, NULL/*FIXME*/);
2341         }
2342         if(FAILED(hres))
2343             VariantClear(&v);
2344     }
2345     IDispatch_Release(obj);
2346     if(FAILED(hres))
2347         return hres;
2348
2349     return stack_push(ctx, &v);
2350 }
2351
2352 /* ECMA-262 3rd Edition    11.4.4, 11.4.5 */
2353 static HRESULT interp_preinc(exec_ctx_t *ctx)
2354 {
2355     const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2356     IDispatch *obj;
2357     DISPID id;
2358     VARIANT v;
2359     HRESULT hres;
2360
2361     TRACE("%d\n", arg);
2362
2363     obj = stack_pop_objid(ctx, &id);
2364     if(!obj)
2365         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2366
2367     hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2368     if(SUCCEEDED(hres)) {
2369         VARIANT n;
2370
2371         hres = to_number(ctx->parser->script, &v, ctx->ei, &n);
2372         VariantClear(&v);
2373         if(SUCCEEDED(hres)) {
2374             num_set_val(&v, num_val(&n)+(double)arg);
2375             hres = disp_propput(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2376         }
2377     }
2378     IDispatch_Release(obj);
2379     if(FAILED(hres))
2380         return hres;
2381
2382     return stack_push(ctx, &v);
2383 }
2384
2385 /* ECMA-262 3rd Edition    11.9.3 */
2386 static HRESULT equal_values(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, BOOL *ret)
2387 {
2388     if(V_VT(lval) == V_VT(rval) || (is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval))))
2389        return equal2_values(lval, rval, ret);
2390
2391     /* FIXME: NULL disps should be handled in more general way */
2392     if(V_VT(lval) == VT_DISPATCH && !V_DISPATCH(lval)) {
2393         VARIANT v;
2394         V_VT(&v) = VT_NULL;
2395         return equal_values(ctx, &v, rval, ei, ret);
2396     }
2397
2398     if(V_VT(rval) == VT_DISPATCH && !V_DISPATCH(rval)) {
2399         VARIANT v;
2400         V_VT(&v) = VT_NULL;
2401         return equal_values(ctx, lval, &v, ei, ret);
2402     }
2403
2404     if((V_VT(lval) == VT_NULL && V_VT(rval) == VT_EMPTY) ||
2405        (V_VT(lval) == VT_EMPTY && V_VT(rval) == VT_NULL)) {
2406         *ret = TRUE;
2407         return S_OK;
2408     }
2409
2410     if(V_VT(lval) == VT_BSTR && is_num_vt(V_VT(rval))) {
2411         VARIANT v;
2412         HRESULT hres;
2413
2414         hres = to_number(ctx, lval, ei, &v);
2415         if(FAILED(hres))
2416             return hres;
2417
2418         return equal_values(ctx, &v, rval, ei, ret);
2419     }
2420
2421     if(V_VT(rval) == VT_BSTR && is_num_vt(V_VT(lval))) {
2422         VARIANT v;
2423         HRESULT hres;
2424
2425         hres = to_number(ctx, rval, ei, &v);
2426         if(FAILED(hres))
2427             return hres;
2428
2429         return equal_values(ctx, lval, &v, ei, ret);
2430     }
2431
2432     if(V_VT(rval) == VT_BOOL) {
2433         VARIANT v;
2434
2435         V_VT(&v) = VT_I4;
2436         V_I4(&v) = V_BOOL(rval) ? 1 : 0;
2437         return equal_values(ctx, lval, &v, ei, ret);
2438     }
2439
2440     if(V_VT(lval) == VT_BOOL) {
2441         VARIANT v;
2442
2443         V_VT(&v) = VT_I4;
2444         V_I4(&v) = V_BOOL(lval) ? 1 : 0;
2445         return equal_values(ctx, &v, rval, ei, ret);
2446     }
2447
2448
2449     if(V_VT(rval) == VT_DISPATCH && (V_VT(lval) == VT_BSTR || is_num_vt(V_VT(lval)))) {
2450         VARIANT v;
2451         HRESULT hres;
2452
2453         hres = to_primitive(ctx, rval, ei, &v, NO_HINT);
2454         if(FAILED(hres))
2455             return hres;
2456
2457         hres = equal_values(ctx, lval, &v, ei, ret);
2458
2459         VariantClear(&v);
2460         return hres;
2461     }
2462
2463
2464     if(V_VT(lval) == VT_DISPATCH && (V_VT(rval) == VT_BSTR || is_num_vt(V_VT(rval)))) {
2465         VARIANT v;
2466         HRESULT hres;
2467
2468         hres = to_primitive(ctx, lval, ei, &v, NO_HINT);
2469         if(FAILED(hres))
2470             return hres;
2471
2472         hres = equal_values(ctx, &v, rval, ei, ret);
2473
2474         VariantClear(&v);
2475         return hres;
2476     }
2477
2478
2479     *ret = FALSE;
2480     return S_OK;
2481 }
2482
2483 /* ECMA-262 3rd Edition    11.9.1 */
2484 static HRESULT interp_eq(exec_ctx_t *ctx)
2485 {
2486     VARIANT *l, *r;
2487     BOOL b;
2488     HRESULT hres;
2489
2490     r = stack_pop(ctx);
2491     l = stack_pop(ctx);
2492
2493     TRACE("%s == %s\n", debugstr_variant(l), debugstr_variant(r));
2494
2495     hres = equal_values(ctx->parser->script, l, r, ctx->ei, &b);
2496     VariantClear(l);
2497     VariantClear(r);
2498     if(FAILED(hres))
2499         return hres;
2500
2501     return stack_push_bool(ctx, b);
2502 }
2503
2504 /* ECMA-262 3rd Edition    11.9.2 */
2505 static HRESULT interp_neq(exec_ctx_t *ctx)
2506 {
2507     VARIANT *l, *r;
2508     BOOL b;
2509     HRESULT hres;
2510
2511     r = stack_pop(ctx);
2512     l = stack_pop(ctx);
2513
2514     TRACE("%s != %s\n", debugstr_variant(l), debugstr_variant(r));
2515
2516     hres = equal_values(ctx->parser->script, l, r, ctx->ei, &b);
2517     VariantClear(l);
2518     VariantClear(r);
2519     if(FAILED(hres))
2520         return hres;
2521
2522     return stack_push_bool(ctx, !b);
2523 }
2524
2525 /* ECMA-262 3rd Edition    11.9.4 */
2526 static HRESULT interp_eq2(exec_ctx_t *ctx)
2527 {
2528     VARIANT *l, *r;
2529     BOOL b;
2530     HRESULT hres;
2531
2532     TRACE("\n");
2533
2534     r = stack_pop(ctx);
2535     l = stack_pop(ctx);
2536
2537     hres = equal2_values(r, l, &b);
2538     VariantClear(l);
2539     VariantClear(r);
2540     if(FAILED(hres))
2541         return hres;
2542
2543     return stack_push_bool(ctx, b);
2544 }
2545
2546 /* ECMA-262 3rd Edition    11.9.5 */
2547 static HRESULT interp_neq2(exec_ctx_t *ctx)
2548 {
2549     VARIANT *l, *r;
2550     BOOL b;
2551     HRESULT hres;
2552
2553     TRACE("\n");
2554
2555     r = stack_pop(ctx);
2556     l = stack_pop(ctx);
2557
2558     hres = equal2_values(r, l, &b);
2559     VariantClear(l);
2560     VariantClear(r);
2561     if(FAILED(hres))
2562         return hres;
2563
2564     return stack_push_bool(ctx, !b);
2565 }
2566
2567 /* ECMA-262 3rd Edition    11.8.5 */
2568 static HRESULT less_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL greater, jsexcept_t *ei, BOOL *ret)
2569 {
2570     VARIANT l, r, ln, rn;
2571     HRESULT hres;
2572
2573     hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2574     if(FAILED(hres))
2575         return hres;
2576
2577     hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
2578     if(FAILED(hres)) {
2579         VariantClear(&l);
2580         return hres;
2581     }
2582
2583     if(V_VT(&l) == VT_BSTR && V_VT(&r) == VT_BSTR) {
2584         *ret = (strcmpW(V_BSTR(&l), V_BSTR(&r)) < 0) ^ greater;
2585         SysFreeString(V_BSTR(&l));
2586         SysFreeString(V_BSTR(&r));
2587         return S_OK;
2588     }
2589
2590     hres = to_number(ctx, &l, ei, &ln);
2591     VariantClear(&l);
2592     if(SUCCEEDED(hres))
2593         hres = to_number(ctx, &r, ei, &rn);
2594     VariantClear(&r);
2595     if(FAILED(hres))
2596         return hres;
2597
2598     if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) {
2599         *ret = (V_I4(&ln) < V_I4(&rn)) ^ greater;
2600     }else  {
2601         DOUBLE ld = num_val(&ln);
2602         DOUBLE rd = num_val(&rn);
2603
2604         *ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater);
2605     }
2606
2607     return S_OK;
2608 }
2609
2610 /* ECMA-262 3rd Edition    11.8.1 */
2611 static HRESULT interp_lt(exec_ctx_t *ctx)
2612 {
2613     VARIANT *l, *r;
2614     BOOL b;
2615     HRESULT hres;
2616
2617     r = stack_pop(ctx);
2618     l = stack_pop(ctx);
2619
2620     TRACE("%s < %s\n", debugstr_variant(l), debugstr_variant(r));
2621
2622     hres = less_eval(ctx->parser->script, l, r, FALSE, ctx->ei, &b);
2623     VariantClear(l);
2624     VariantClear(r);
2625     if(FAILED(hres))
2626         return hres;
2627
2628     return stack_push_bool(ctx, b);
2629 }
2630
2631 /* ECMA-262 3rd Edition    11.8.1 */
2632 static HRESULT interp_lteq(exec_ctx_t *ctx)
2633 {
2634     VARIANT *l, *r;
2635     BOOL b;
2636     HRESULT hres;
2637
2638     r = stack_pop(ctx);
2639     l = stack_pop(ctx);
2640
2641     TRACE("%s <= %s\n", debugstr_variant(l), debugstr_variant(r));
2642
2643     hres = less_eval(ctx->parser->script, r, l, TRUE, ctx->ei, &b);
2644     VariantClear(l);
2645     VariantClear(r);
2646     if(FAILED(hres))
2647         return hres;
2648
2649     return stack_push_bool(ctx, b);
2650 }
2651
2652 /* ECMA-262 3rd Edition    11.8.2 */
2653 static HRESULT interp_gt(exec_ctx_t *ctx)
2654 {
2655     VARIANT *l, *r;
2656     BOOL b;
2657     HRESULT hres;
2658
2659     r = stack_pop(ctx);
2660     l = stack_pop(ctx);
2661
2662     TRACE("%s > %s\n", debugstr_variant(l), debugstr_variant(r));
2663
2664     hres = less_eval(ctx->parser->script, r, l, FALSE, ctx->ei, &b);
2665     VariantClear(l);
2666     VariantClear(r);
2667     if(FAILED(hres))
2668         return hres;
2669
2670     return stack_push_bool(ctx, b);
2671 }
2672
2673 /* ECMA-262 3rd Edition    11.8.4 */
2674 static HRESULT interp_gteq(exec_ctx_t *ctx)
2675 {
2676     VARIANT *l, *r;
2677     BOOL b;
2678     HRESULT hres;
2679
2680     r = stack_pop(ctx);
2681     l = stack_pop(ctx);
2682
2683     TRACE("%s >= %s\n", debugstr_variant(l), debugstr_variant(r));
2684
2685     hres = less_eval(ctx->parser->script, l, r, TRUE, ctx->ei, &b);
2686     VariantClear(l);
2687     VariantClear(r);
2688     if(FAILED(hres))
2689         return hres;
2690
2691     return stack_push_bool(ctx, b);
2692 }
2693
2694 /* ECMA-262 3rd Edition    11.4.8 */
2695 static HRESULT interp_bneg(exec_ctx_t *ctx)
2696 {
2697     VARIANT *v, r;
2698     INT i;
2699     HRESULT hres;
2700
2701     TRACE("\n");
2702
2703     v = stack_pop(ctx);
2704     hres = to_int32(ctx->parser->script, v, ctx->ei, &i);
2705     VariantClear(v);
2706     if(FAILED(hres))
2707         return hres;
2708
2709     V_VT(&r) = VT_I4;
2710     V_I4(&r) = ~i;
2711     return stack_push(ctx, &r);
2712 }
2713
2714 /* ECMA-262 3rd Edition    11.4.9 */
2715 static HRESULT interp_neg(exec_ctx_t *ctx)
2716 {
2717     VARIANT *v;
2718     VARIANT_BOOL b;
2719     HRESULT hres;
2720
2721     TRACE("\n");
2722
2723     v = stack_pop(ctx);
2724     hres = to_boolean(v, &b);
2725     VariantClear(v);
2726     if(FAILED(hres))
2727         return hres;
2728
2729     return stack_push_bool(ctx, !b);
2730 }
2731
2732 /* ECMA-262 3rd Edition    11.7.1 */
2733 static HRESULT interp_lshift(exec_ctx_t *ctx)
2734 {
2735     DWORD r;
2736     INT l;
2737     HRESULT hres;
2738
2739     hres = stack_pop_uint(ctx, &r);
2740     if(FAILED(hres))
2741         return hres;
2742
2743     hres = stack_pop_int(ctx, &l);
2744     if(FAILED(hres))
2745         return hres;
2746
2747     return stack_push_int(ctx, l << (r&0x1f));
2748 }
2749
2750 /* ECMA-262 3rd Edition    11.7.2 */
2751 static HRESULT interp_rshift(exec_ctx_t *ctx)
2752 {
2753     DWORD r;
2754     INT l;
2755     HRESULT hres;
2756
2757     hres = stack_pop_uint(ctx, &r);
2758     if(FAILED(hres))
2759         return hres;
2760
2761     hres = stack_pop_int(ctx, &l);
2762     if(FAILED(hres))
2763         return hres;
2764
2765     return stack_push_int(ctx, l >> (r&0x1f));
2766 }
2767
2768 /* ECMA-262 3rd Edition    11.7.3 */
2769 static HRESULT interp_rshift2(exec_ctx_t *ctx)
2770 {
2771     DWORD r, l;
2772     HRESULT hres;
2773
2774     hres = stack_pop_uint(ctx, &r);
2775     if(FAILED(hres))
2776         return hres;
2777
2778     hres = stack_pop_uint(ctx, &l);
2779     if(FAILED(hres))
2780         return hres;
2781
2782     return stack_push_int(ctx, l >> (r&0x1f));
2783 }
2784
2785 /* ECMA-262 3rd Edition    11.13.1 */
2786 static HRESULT interp_assign(exec_ctx_t *ctx)
2787 {
2788     IDispatch *disp;
2789     DISPID id;
2790     VARIANT *v;
2791     HRESULT hres;
2792
2793     TRACE("\n");
2794
2795     v = stack_pop(ctx);
2796     disp = stack_pop_objid(ctx, &id);
2797
2798     if(!disp)
2799         return throw_reference_error(ctx->parser->script, ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
2800
2801     hres = disp_propput(ctx->parser->script, disp, id, v, ctx->ei, NULL/*FIXME*/);
2802     IDispatch_Release(disp);
2803     if(FAILED(hres)) {
2804         VariantClear(v);
2805         return hres;
2806     }
2807
2808     return stack_push(ctx, v);
2809 }
2810
2811 static HRESULT interp_undefined(exec_ctx_t *ctx)
2812 {
2813     VARIANT v;
2814
2815     TRACE("\n");
2816
2817     V_VT(&v) = VT_EMPTY;
2818     return stack_push(ctx, &v);
2819 }
2820
2821 static HRESULT interp_jmp(exec_ctx_t *ctx)
2822 {
2823     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
2824
2825     TRACE("\n");
2826
2827     ctx->ip = arg;
2828     return S_OK;
2829 }
2830
2831 static HRESULT interp_jmp_z(exec_ctx_t *ctx)
2832 {
2833     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
2834     VARIANT_BOOL b;
2835     VARIANT *v;
2836     HRESULT hres;
2837
2838     TRACE("\n");
2839
2840     v = stack_pop(ctx);
2841     hres = to_boolean(v, &b);
2842     VariantClear(v);
2843     if(FAILED(hres))
2844         return hres;
2845
2846     if(b)
2847         ctx->ip++;
2848     else
2849         ctx->ip = arg;
2850     return S_OK;
2851 }
2852
2853 static HRESULT interp_pop(exec_ctx_t *ctx)
2854 {
2855     TRACE("\n");
2856
2857     stack_popn(ctx, 1);
2858     return S_OK;
2859 }
2860
2861 static HRESULT interp_ret(exec_ctx_t *ctx)
2862 {
2863     TRACE("\n");
2864
2865     ctx->ip = -1;
2866     return S_OK;
2867 }
2868
2869 static HRESULT interp_tree(exec_ctx_t *ctx)
2870 {
2871     instr_t *instr = ctx->parser->code->instrs+ctx->ip;
2872     VARIANT v;
2873     HRESULT hres;
2874
2875     TRACE("\n");
2876
2877     hres = stat_eval(ctx->parser->script, instr->arg1.stat, ctx->rt, &v);
2878     if(FAILED(hres))
2879         return hres;
2880
2881     return stack_push(ctx, &v);
2882 }
2883
2884 typedef HRESULT (*op_func_t)(exec_ctx_t*);
2885
2886 static const op_func_t op_funcs[] = {
2887 #define X(x,a,b,c) interp_##x,
2888 OP_LIST
2889 #undef X
2890 };
2891
2892 static const unsigned op_move[] = {
2893 #define X(a,x,b,c) x,
2894 OP_LIST
2895 #undef X
2896 };
2897
2898 static HRESULT unwind_exception(exec_ctx_t *ctx)
2899 {
2900     except_frame_t *except_frame;
2901     VARIANT except_val;
2902     BSTR ident;
2903     HRESULT hres;
2904
2905     except_frame = ctx->except_frame;
2906     ctx->except_frame = except_frame->next;
2907
2908     assert(except_frame->stack_top <= ctx->top);
2909     stack_popn(ctx, ctx->top - except_frame->stack_top);
2910
2911     while(except_frame->scope != ctx->scope_chain)
2912         scope_pop(&ctx->scope_chain);
2913
2914     ctx->ip = except_frame->catch_off;
2915
2916     assert(ctx->rt->type == RT_NORMAL);
2917     except_val = ctx->rt->ei.var;
2918     memset(&ctx->rt->ei, 0, sizeof(ctx->rt->ei));
2919
2920     ident = except_frame->ident;
2921     heap_free(except_frame);
2922
2923     if(ident) {
2924         jsdisp_t *scope_obj;
2925
2926         hres = create_dispex(ctx->parser->script, NULL, NULL, &scope_obj);
2927         if(SUCCEEDED(hres)) {
2928             hres = jsdisp_propput_name(scope_obj, ident, &except_val, &ctx->rt->ei, NULL/*FIXME*/);
2929             if(FAILED(hres))
2930                 jsdisp_release(scope_obj);
2931         }
2932         VariantClear(&except_val);
2933         if(FAILED(hres))
2934             return hres;
2935
2936         hres = scope_push(ctx->scope_chain, scope_obj, &ctx->scope_chain);
2937         jsdisp_release(scope_obj);
2938     }else {
2939         VARIANT v;
2940
2941         hres = stack_push(ctx, &except_val);
2942         if(FAILED(hres))
2943             return hres;
2944
2945         hres = stack_push_bool(ctx, FALSE);
2946         if(FAILED(hres))
2947             return hres;
2948
2949         V_VT(&v) = VT_EMPTY;
2950         hres = stack_push(ctx, &v);
2951     }
2952
2953     return hres;
2954 }
2955
2956 HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
2957 {
2958     exec_ctx_t *exec_ctx = ctx->exec_ctx;
2959     except_frame_t *prev_except_frame;
2960     unsigned prev_ip, prev_top;
2961     scope_chain_t *prev_scope;
2962     return_type_t *prev_rt;
2963     jsexcept_t *prev_ei;
2964     jsop_t op;
2965     HRESULT hres = S_OK;
2966
2967     TRACE("\n");
2968
2969     if(stat->instr_off == -1) {
2970         hres = compile_subscript_stat(exec_ctx->parser, stat, FALSE, &stat->instr_off);
2971         if(FAILED(hres))
2972             return hres;
2973     }
2974
2975     prev_rt = exec_ctx->rt;
2976     prev_top = exec_ctx->top;
2977     prev_scope = exec_ctx->scope_chain;
2978     prev_except_frame = exec_ctx->except_frame;
2979     prev_ip = exec_ctx->ip;
2980     prev_ei = exec_ctx->ei;
2981     exec_ctx->ip = stat->instr_off;
2982     exec_ctx->rt = rt;
2983     exec_ctx->ei = &rt->ei;
2984     exec_ctx->except_frame = NULL;
2985
2986     while(exec_ctx->ip != -1 && exec_ctx->rt->type == RT_NORMAL) {
2987         op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
2988         hres = op_funcs[op](exec_ctx);
2989         if(FAILED(hres)) {
2990             TRACE("EXCEPTION\n");
2991
2992             if(!exec_ctx->except_frame)
2993                 break;
2994
2995             hres = unwind_exception(exec_ctx);
2996             if(FAILED(hres))
2997                 break;
2998         }else {
2999             exec_ctx->ip += op_move[op];
3000         }
3001     }
3002
3003     exec_ctx->rt = prev_rt;
3004     exec_ctx->ip = prev_ip;
3005     exec_ctx->ei = prev_ei;
3006     exec_ctx->except_frame = prev_except_frame;
3007
3008     if(FAILED(hres) || rt->type != RT_NORMAL) {
3009         while(exec_ctx->scope_chain != prev_scope)
3010             scope_pop(&exec_ctx->scope_chain);
3011     }
3012     if(FAILED(hres)) {
3013         stack_popn(exec_ctx, exec_ctx->top-prev_top);
3014         return hres;
3015     }
3016
3017     assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top);
3018     assert(exec_ctx->scope_chain == prev_scope);
3019
3020     if(exec_ctx->top == prev_top)
3021         V_VT(ret) = VT_EMPTY;
3022     else
3023         *ret = *stack_pop(exec_ctx);
3024     return S_OK;
3025 }
3026
3027 static HRESULT expr_eval(script_ctx_t *ctx, expression_t *expr, jsexcept_t *ei, VARIANT *ret)
3028 {
3029     exec_ctx_t *exec_ctx = ctx->exec_ctx;
3030     unsigned prev_ip, prev_top;
3031     jsexcept_t *prev_ei;
3032     jsop_t op;
3033     HRESULT hres = S_OK;
3034
3035     TRACE("\n");
3036
3037     if(expr->instr_off == -1) {
3038         hres = compile_subscript(ctx->exec_ctx->parser, expr, &expr->instr_off);
3039         if(FAILED(hres))
3040             return hres;
3041     }
3042
3043     prev_top = exec_ctx->top;
3044     prev_ip = exec_ctx->ip;
3045     prev_ei = exec_ctx->ei;
3046     exec_ctx->ip = expr->instr_off;
3047     exec_ctx->ei = ei;
3048
3049     while(exec_ctx->ip != -1) {
3050         op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
3051         hres = op_funcs[op](exec_ctx);
3052         if(FAILED(hres))
3053             break;
3054         exec_ctx->ip += op_move[op];
3055     }
3056
3057     exec_ctx->ip = prev_ip;
3058     exec_ctx->ei = prev_ei;
3059
3060     if(FAILED(hres)) {
3061         stack_popn(exec_ctx, exec_ctx->top-prev_top);
3062         return hres;
3063     }
3064
3065     assert(exec_ctx->top == prev_top+1);
3066
3067     if(exec_ctx->top == prev_top)
3068         V_VT(ret) = VT_EMPTY;
3069     else
3070         *ret = *stack_pop(exec_ctx);
3071     return S_OK;
3072 }