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