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