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