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