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