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