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