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