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