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