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