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