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