jscript: Get rid of no longer needed identifier in exprval_t.
[wine/testsucceed.git] / dlls / jscript / engine.c
blob14bd25075778a260da309a4c5cd72858029cea4c
1 /*
2 * Copyright 2008 Jacek Caban for CodeWeavers
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.
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.
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
19 #include "config.h"
20 #include "wine/port.h"
22 #include <math.h>
23 #include <assert.h>
25 #include "jscript.h"
26 #include "engine.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
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};
40 struct _return_type_t {
41 enum{
42 RT_NORMAL,
43 RT_RETURN,
44 RT_BREAK,
45 RT_CONTINUE
46 } type;
47 jsexcept_t ei;
50 static inline HRESULT stat_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
52 return stat->eval(ctx, stat, rt, ret);
55 static HRESULT expr_eval(script_ctx_t*,expression_t*,jsexcept_t*,VARIANT*);
57 static HRESULT stack_push(exec_ctx_t *ctx, VARIANT *v)
59 if(!ctx->stack_size) {
60 ctx->stack = heap_alloc(16*sizeof(VARIANT));
61 if(!ctx->stack)
62 return E_OUTOFMEMORY;
63 ctx->stack_size = 16;
64 }else if(ctx->stack_size == ctx->top) {
65 VARIANT *new_stack;
67 new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(VARIANT));
68 if(!new_stack) {
69 VariantClear(v);
70 return E_OUTOFMEMORY;
73 ctx->stack = new_stack;
74 ctx->stack_size *= 2;
77 ctx->stack[ctx->top++] = *v;
78 return S_OK;
81 static HRESULT stack_push_bool(exec_ctx_t *ctx, BOOL b)
83 VARIANT v;
85 V_VT(&v) = VT_BOOL;
86 V_BOOL(&v) = b ? VARIANT_TRUE : VARIANT_FALSE;
87 return stack_push(ctx, &v);
90 static inline HRESULT stack_push_number(exec_ctx_t *ctx, double number)
92 VARIANT v;
94 num_set_val(&v, number);
95 return stack_push(ctx, &v);
98 static inline HRESULT stack_push_int(exec_ctx_t *ctx, INT n)
100 VARIANT v;
102 V_VT(&v) = VT_I4;
103 V_I4(&v) = n;
104 return stack_push(ctx, &v);
107 static inline HRESULT stack_push_string(exec_ctx_t *ctx, const WCHAR *str)
109 VARIANT v;
111 V_VT(&v) = VT_BSTR;
112 V_BSTR(&v) = SysAllocString(str);
113 return V_BSTR(&v) ? stack_push(ctx, &v) : E_OUTOFMEMORY;
116 static HRESULT stack_push_objid(exec_ctx_t *ctx, IDispatch *disp, DISPID id)
118 VARIANT v;
119 HRESULT hres;
121 V_VT(&v) = VT_DISPATCH;
122 V_DISPATCH(&v) = disp;
123 hres = stack_push(ctx, &v);
124 if(FAILED(hres))
125 return hres;
127 V_VT(&v) = VT_INT;
128 V_INT(&v) = id;
129 return stack_push(ctx, &v);
132 static inline VARIANT *stack_top(exec_ctx_t *ctx)
134 assert(ctx->top);
135 return ctx->stack + ctx->top-1;
138 static inline VARIANT *stack_topn(exec_ctx_t *ctx, unsigned n)
140 assert(ctx->top > n);
141 return ctx->stack + ctx->top-1-n;
144 static inline VARIANT *stack_pop(exec_ctx_t *ctx)
146 assert(ctx->top);
147 return ctx->stack + --ctx->top;
150 static void stack_popn(exec_ctx_t *ctx, unsigned n)
152 while(n--)
153 VariantClear(stack_pop(ctx));
156 static HRESULT stack_pop_number(exec_ctx_t *ctx, VARIANT *r)
158 VARIANT *v;
159 HRESULT hres;
161 v = stack_pop(ctx);
162 hres = to_number(ctx->parser->script, v, ctx->ei, r);
163 VariantClear(v);
164 return hres;
167 static HRESULT stack_pop_object(exec_ctx_t *ctx, IDispatch **r)
169 VARIANT *v;
170 HRESULT hres;
172 v = stack_pop(ctx);
173 if(V_VT(v) == VT_DISPATCH) {
174 if(!V_DISPATCH(v))
175 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_REQUIRED, NULL);
176 *r = V_DISPATCH(v);
177 return S_OK;
180 hres = to_object(ctx->parser->script, v, r);
181 VariantClear(v);
182 return hres;
185 static inline HRESULT stack_pop_int(exec_ctx_t *ctx, INT *r)
187 return to_int32(ctx->parser->script, stack_pop(ctx), ctx->ei, r);
190 static inline HRESULT stack_pop_uint(exec_ctx_t *ctx, DWORD *r)
192 return to_uint32(ctx->parser->script, stack_pop(ctx), ctx->ei, r);
195 static inline IDispatch *stack_pop_objid(exec_ctx_t *ctx, DISPID *id)
197 assert(V_VT(stack_top(ctx)) == VT_INT && V_VT(stack_topn(ctx, 1)) == VT_DISPATCH);
199 *id = V_INT(stack_pop(ctx));
200 return V_DISPATCH(stack_pop(ctx));
203 static inline IDispatch *stack_topn_objid(exec_ctx_t *ctx, unsigned n, DISPID *id)
205 assert(V_VT(stack_topn(ctx, n)) == VT_INT && V_VT(stack_topn(ctx, n+1)) == VT_DISPATCH);
207 *id = V_INT(stack_topn(ctx, n));
208 return V_DISPATCH(stack_topn(ctx, n+1));
211 static void exprval_release(exprval_t *val)
213 switch(val->type) {
214 case EXPRVAL_VARIANT:
215 if(V_VT(&val->u.var) != VT_EMPTY)
216 VariantClear(&val->u.var);
217 return;
218 case EXPRVAL_IDREF:
219 if(val->u.idref.disp)
220 IDispatch_Release(val->u.idref.disp);
221 return;
222 case EXPRVAL_INVALID:
223 return;
227 /* ECMA-262 3rd Edition 8.7.1 */
228 static HRESULT exprval_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
230 V_VT(ret) = VT_EMPTY;
232 switch(val->type) {
233 case EXPRVAL_VARIANT:
234 return VariantCopy(ret, &val->u.var);
235 case EXPRVAL_IDREF:
236 if(!val->u.idref.disp) {
237 FIXME("throw ReferenceError\n");
238 return E_FAIL;
241 return disp_propget(ctx, val->u.idref.disp, val->u.idref.id, ret, ei, NULL/*FIXME*/);
242 case EXPRVAL_INVALID:
243 assert(0);
246 ERR("type %d\n", val->type);
247 return E_FAIL;
250 static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
252 if(val->type == EXPRVAL_VARIANT) {
253 *ret = val->u.var;
254 V_VT(&val->u.var) = VT_EMPTY;
255 return S_OK;
258 return exprval_value(ctx, val, ei, ret);
261 static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id)
263 val->type = EXPRVAL_IDREF;
264 val->u.idref.disp = disp;
265 val->u.idref.id = id;
267 if(disp)
268 IDispatch_AddRef(disp);
271 HRESULT scope_push(scope_chain_t *scope, jsdisp_t *obj, scope_chain_t **ret)
273 scope_chain_t *new_scope;
275 new_scope = heap_alloc(sizeof(scope_chain_t));
276 if(!new_scope)
277 return E_OUTOFMEMORY;
279 new_scope->ref = 1;
281 jsdisp_addref(obj);
282 new_scope->obj = obj;
284 if(scope) {
285 scope_addref(scope);
286 new_scope->next = scope;
287 }else {
288 new_scope->next = NULL;
291 *ret = new_scope;
292 return S_OK;
295 static void scope_pop(scope_chain_t **scope)
297 scope_chain_t *tmp;
299 tmp = *scope;
300 *scope = tmp->next;
301 scope_release(tmp);
304 void scope_release(scope_chain_t *scope)
306 if(--scope->ref)
307 return;
309 if(scope->next)
310 scope_release(scope->next);
312 jsdisp_release(scope->obj);
313 heap_free(scope);
316 HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, jsdisp_t *var_disp,
317 scope_chain_t *scope, BOOL is_global, exec_ctx_t **ret)
319 exec_ctx_t *ctx;
321 ctx = heap_alloc_zero(sizeof(exec_ctx_t));
322 if(!ctx)
323 return E_OUTOFMEMORY;
325 ctx->ref = 1;
326 ctx->is_global = is_global;
328 if(this_obj)
329 ctx->this_obj = this_obj;
330 else if(script_ctx->host_global)
331 ctx->this_obj = script_ctx->host_global;
332 else
333 ctx->this_obj = to_disp(script_ctx->global);
334 IDispatch_AddRef(ctx->this_obj);
336 jsdisp_addref(var_disp);
337 ctx->var_disp = var_disp;
339 if(scope) {
340 scope_addref(scope);
341 ctx->scope_chain = scope;
344 *ret = ctx;
345 return S_OK;
348 void exec_release(exec_ctx_t *ctx)
350 if(--ctx->ref)
351 return;
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 heap_free(ctx->stack);
360 heap_free(ctx);
363 static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
365 IDispatchEx *dispex;
366 HRESULT hres;
368 hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
369 if(FAILED(hres)) {
370 TRACE("unsing IDispatch\n");
372 *id = 0;
373 return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
376 *id = 0;
377 hres = IDispatchEx_GetDispID(dispex, name, make_grfdex(ctx, flags|fdexNameCaseSensitive), id);
378 IDispatchEx_Release(dispex);
379 return hres;
382 /* ECMA-262 3rd Edition 8.7.2 */
383 static HRESULT put_value(script_ctx_t *ctx, exprval_t *ref, VARIANT *v, jsexcept_t *ei)
385 if(ref->type != EXPRVAL_IDREF)
386 return throw_reference_error(ctx, ei, JS_E_ILLEGAL_ASSIGN, NULL);
388 return disp_propput(ctx, ref->u.idref.disp, ref->u.idref.id, v, ei, NULL/*FIXME*/);
391 static inline BOOL is_null(const VARIANT *v)
393 return V_VT(v) == VT_NULL || (V_VT(v) == VT_DISPATCH && !V_DISPATCH(v));
396 static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret)
398 IObjectIdentity *identity;
399 IUnknown *unk1, *unk2;
400 HRESULT hres;
402 if(disp1 == disp2) {
403 *ret = TRUE;
404 return S_OK;
407 if(!disp1 || !disp2) {
408 *ret = FALSE;
409 return S_OK;
412 hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1);
413 if(FAILED(hres))
414 return hres;
416 hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2);
417 if(FAILED(hres)) {
418 IUnknown_Release(unk1);
419 return hres;
422 if(unk1 == unk2) {
423 *ret = TRUE;
424 }else {
425 hres = IUnknown_QueryInterface(unk1, &IID_IObjectIdentity, (void**)&identity);
426 if(SUCCEEDED(hres)) {
427 hres = IObjectIdentity_IsEqualObject(identity, unk2);
428 IObjectIdentity_Release(identity);
429 *ret = hres == S_OK;
430 }else {
431 *ret = FALSE;
435 IUnknown_Release(unk1);
436 IUnknown_Release(unk2);
437 return S_OK;
440 /* ECMA-262 3rd Edition 11.9.6 */
441 static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
443 TRACE("\n");
445 if(V_VT(lval) != V_VT(rval)) {
446 if(is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval)))
447 *ret = num_val(lval) == num_val(rval);
448 else if(is_null(lval))
449 *ret = is_null(rval);
450 else
451 *ret = FALSE;
452 return S_OK;
455 switch(V_VT(lval)) {
456 case VT_EMPTY:
457 case VT_NULL:
458 *ret = VARIANT_TRUE;
459 break;
460 case VT_I4:
461 *ret = V_I4(lval) == V_I4(rval);
462 break;
463 case VT_R8:
464 *ret = V_R8(lval) == V_R8(rval);
465 break;
466 case VT_BSTR:
467 if(!V_BSTR(lval))
468 *ret = SysStringLen(V_BSTR(rval))?FALSE:TRUE;
469 else if(!V_BSTR(rval))
470 *ret = SysStringLen(V_BSTR(lval))?FALSE:TRUE;
471 else
472 *ret = !strcmpW(V_BSTR(lval), V_BSTR(rval));
473 break;
474 case VT_DISPATCH:
475 return disp_cmp(V_DISPATCH(lval), V_DISPATCH(rval), ret);
476 case VT_BOOL:
477 *ret = !V_BOOL(lval) == !V_BOOL(rval);
478 break;
479 default:
480 FIXME("unimplemented vt %d\n", V_VT(lval));
481 return E_NOTIMPL;
484 return S_OK;
487 static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
489 named_item_t *item;
490 DISPID id;
491 HRESULT hres;
493 for(item = ctx->named_items; item; item = item->next) {
494 if(item->flags & SCRIPTITEM_GLOBALMEMBERS) {
495 hres = disp_get_id(ctx, item->disp, identifier, 0, &id);
496 if(SUCCEEDED(hres)) {
497 if(ret)
498 exprval_set_idref(ret, item->disp, id);
499 return TRUE;
504 return FALSE;
507 HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, BOOL from_eval,
508 jsexcept_t *ei, VARIANT *retv)
510 script_ctx_t *script = parser->script;
511 function_declaration_t *func;
512 parser_ctx_t *prev_parser;
513 var_list_t *var;
514 VARIANT val;
515 exec_ctx_t *prev_ctx;
516 return_type_t rt;
517 HRESULT hres = S_OK;
519 for(func = source->functions; func; func = func->next) {
520 jsdisp_t *func_obj;
521 VARIANT var;
523 hres = create_source_function(parser, func->expr->parameter_list, func->expr->source_elements,
524 ctx->scope_chain, func->expr->src_str, func->expr->src_len, &func_obj);
525 if(FAILED(hres))
526 return hres;
528 var_set_jsdisp(&var, func_obj);
529 hres = jsdisp_propput_name(ctx->var_disp, func->expr->identifier, &var, ei, NULL);
530 jsdisp_release(func_obj);
531 if(FAILED(hres))
532 return hres;
535 for(var = source->variables; var; var = var->next) {
536 DISPID id = 0;
537 BSTR name;
539 name = SysAllocString(var->identifier);
540 if(!name)
541 return E_OUTOFMEMORY;
543 if(!ctx->is_global || !lookup_global_members(parser->script, name, NULL))
544 hres = jsdisp_get_id(ctx->var_disp, var->identifier, fdexNameEnsure, &id);
545 SysFreeString(name);
546 if(FAILED(hres))
547 return hres;
550 prev_ctx = script->exec_ctx;
551 script->exec_ctx = ctx;
553 prev_parser = ctx->parser;
554 ctx->parser = parser;
556 V_VT(&val) = VT_EMPTY;
557 memset(&rt, 0, sizeof(rt));
558 rt.type = RT_NORMAL;
560 if(source->statement) {
561 if(source->statement->instr_off == -1)
562 hres = compile_subscript_stat(ctx->parser, source->statement, TRUE, &source->statement->instr_off);
563 if(SUCCEEDED(hres))
564 hres = compiled_statement_eval(script, source->statement, &rt, &val);
567 script->exec_ctx = prev_ctx;
568 ctx->parser = prev_parser;
570 if(rt.type != RT_NORMAL && rt.type != RT_RETURN) {
571 FIXME("wrong rt %d\n", rt.type);
572 hres = E_FAIL;
575 *ei = rt.ei;
576 if(FAILED(hres)) {
577 VariantClear(&val);
578 return hres;
581 if(!retv || (!from_eval && rt.type != RT_RETURN))
582 VariantClear(&val);
583 if(retv)
584 *retv = val;
585 return S_OK;
588 /* ECMA-262 3rd Edition 10.1.4 */
589 static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, DWORD flags, jsexcept_t *ei, exprval_t *ret)
591 scope_chain_t *scope;
592 named_item_t *item;
593 DISPID id = 0;
594 HRESULT hres;
596 TRACE("%s\n", debugstr_w(identifier));
598 for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) {
599 hres = jsdisp_get_id(scope->obj, identifier, 0, &id);
600 if(SUCCEEDED(hres)) {
601 exprval_set_idref(ret, to_disp(scope->obj), id);
602 return S_OK;
606 hres = jsdisp_get_id(ctx->global, identifier, 0, &id);
607 if(SUCCEEDED(hres)) {
608 exprval_set_idref(ret, to_disp(ctx->global), id);
609 return S_OK;
612 for(item = ctx->named_items; item; item = item->next) {
613 if((item->flags & SCRIPTITEM_ISVISIBLE) && !strcmpW(item->name, identifier)) {
614 if(!item->disp) {
615 IUnknown *unk;
617 if(!ctx->site)
618 break;
620 hres = IActiveScriptSite_GetItemInfo(ctx->site, identifier,
621 SCRIPTINFO_IUNKNOWN, &unk, NULL);
622 if(FAILED(hres)) {
623 WARN("GetItemInfo failed: %08x\n", hres);
624 break;
627 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
628 IUnknown_Release(unk);
629 if(FAILED(hres)) {
630 WARN("object does not implement IDispatch\n");
631 break;
635 ret->type = EXPRVAL_VARIANT;
636 V_VT(&ret->u.var) = VT_DISPATCH;
637 V_DISPATCH(&ret->u.var) = item->disp;
638 IDispatch_AddRef(item->disp);
639 return S_OK;
643 if(lookup_global_members(ctx, identifier, ret))
644 return S_OK;
646 if(flags & fdexNameEnsure) {
647 hres = jsdisp_get_id(ctx->global, identifier, fdexNameEnsure, &id);
648 if(FAILED(hres))
649 return hres;
651 exprval_set_idref(ret, to_disp(ctx->global), id);
652 return S_OK;
655 ret->type = EXPRVAL_INVALID;
656 return S_OK;
659 /* ECMA-262 3rd Edition 12.2 */
660 static HRESULT variable_list_eval(script_ctx_t *ctx, variable_declaration_t *var_list, jsexcept_t *ei)
662 variable_declaration_t *iter;
663 HRESULT hres = S_OK;
665 for(iter = var_list; iter; iter = iter->next) {
666 VARIANT val;
668 if(!iter->expr)
669 continue;
671 hres = expr_eval(ctx, iter->expr, ei, &val);
672 if(FAILED(hres))
673 break;
675 hres = jsdisp_propput_name(ctx->exec_ctx->var_disp, iter->identifier, &val, ei, NULL/*FIXME*/);
676 VariantClear(&val);
677 if(FAILED(hres))
678 break;
681 return hres;
684 /* ECMA-262 3rd Edition 12.2 */
685 static HRESULT interp_var_set(exec_ctx_t *ctx)
687 const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
688 VARIANT *v;
689 HRESULT hres;
691 TRACE("%s\n", debugstr_w(name));
693 v = stack_pop(ctx);
694 hres = jsdisp_propput_name(ctx->var_disp, name, v, ctx->ei, NULL/*FIXME*/);
695 VariantClear(v);
696 return hres;
699 /* ECMA-262 3rd Edition 12.6.2 */
700 HRESULT while_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
702 while_statement_t *stat = (while_statement_t*)_stat;
703 VARIANT val, tmp;
704 VARIANT_BOOL b;
705 BOOL test_expr;
706 HRESULT hres;
708 TRACE("\n");
710 V_VT(&val) = VT_EMPTY;
711 test_expr = !stat->do_while;
713 while(1) {
714 if(test_expr) {
715 hres = expr_eval(ctx, stat->expr, &rt->ei, &tmp);
716 if(FAILED(hres))
717 break;
719 hres = to_boolean(&tmp, &b);
720 VariantClear(&tmp);
721 if(FAILED(hres) || !b)
722 break;
723 }else {
724 test_expr = TRUE;
727 hres = stat_eval(ctx, stat->statement, rt, &tmp);
728 if(FAILED(hres))
729 break;
731 VariantClear(&val);
732 val = tmp;
734 if(rt->type == RT_CONTINUE)
735 rt->type = RT_NORMAL;
736 if(rt->type != RT_NORMAL)
737 break;
740 if(FAILED(hres)) {
741 VariantClear(&val);
742 return hres;
745 if(rt->type == RT_BREAK)
746 rt->type = RT_NORMAL;
748 *ret = val;
749 return S_OK;
752 /* ECMA-262 3rd Edition 12.6.3 */
753 HRESULT for_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
755 for_statement_t *stat = (for_statement_t*)_stat;
756 VARIANT val, tmp, retv;
757 VARIANT_BOOL b;
758 HRESULT hres;
760 TRACE("\n");
762 if(stat->variable_list) {
763 hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
764 if(FAILED(hres))
765 return hres;
766 }else if(stat->begin_expr) {
767 hres = expr_eval(ctx, stat->begin_expr, &rt->ei, &val);
768 if(FAILED(hres))
769 return hres;
771 VariantClear(&val);
774 V_VT(&retv) = VT_EMPTY;
776 while(1) {
777 if(stat->expr) {
778 hres = expr_eval(ctx, stat->expr, &rt->ei, &tmp);
779 if(FAILED(hres))
780 break;
782 hres = to_boolean(&tmp, &b);
783 VariantClear(&tmp);
784 if(FAILED(hres) || !b)
785 break;
788 hres = stat_eval(ctx, stat->statement, rt, &tmp);
789 if(FAILED(hres))
790 break;
792 VariantClear(&retv);
793 retv = tmp;
795 if(rt->type == RT_CONTINUE)
796 rt->type = RT_NORMAL;
797 else if(rt->type != RT_NORMAL)
798 break;
800 if(stat->end_expr) {
801 hres = expr_eval(ctx, stat->end_expr, &rt->ei, &val);
802 if(FAILED(hres))
803 break;
805 VariantClear(&val);
809 if(FAILED(hres)) {
810 VariantClear(&retv);
811 return hres;
814 if(rt->type == RT_BREAK)
815 rt->type = RT_NORMAL;
817 *ret = retv;
818 return S_OK;
821 static HRESULT array_expression_eval(script_ctx_t*,expression_t*,jsexcept_t*,exprval_t*);
822 static HRESULT member_expression_eval(script_ctx_t*,expression_t*,jsexcept_t*,exprval_t*);
823 static HRESULT identifier_expression_eval(script_ctx_t*,expression_t*,jsexcept_t*,exprval_t*);
825 /* ECMA-262 3rd Edition 12.6.4 */
826 HRESULT forin_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
828 forin_statement_t *stat = (forin_statement_t*)_stat;
829 VARIANT val, name, retv, tmp;
830 DISPID id = DISPID_STARTENUM;
831 BSTR str, identifier = NULL;
832 IDispatchEx *in_obj;
833 exprval_t exprval;
834 HRESULT hres;
836 TRACE("\n");
838 if(stat->variable) {
839 hres = variable_list_eval(ctx, stat->variable, &rt->ei);
840 if(FAILED(hres))
841 return hres;
844 hres = expr_eval(ctx, stat->in_expr, &rt->ei, &val);
845 if(FAILED(hres))
846 return hres;
848 if(V_VT(&val) != VT_DISPATCH) {
849 TRACE("in vt %d\n", V_VT(&val));
850 VariantClear(&val);
851 V_VT(ret) = VT_EMPTY;
852 return S_OK;
855 hres = IDispatch_QueryInterface(V_DISPATCH(&val), &IID_IDispatchEx, (void**)&in_obj);
856 IDispatch_Release(V_DISPATCH(&val));
857 if(FAILED(hres)) {
858 TRACE("Object doesn't support IDispatchEx\n");
859 V_VT(ret) = VT_EMPTY;
860 return S_OK;
863 V_VT(&retv) = VT_EMPTY;
865 if(stat->variable)
866 identifier = SysAllocString(stat->variable->identifier);
868 while(1) {
869 hres = IDispatchEx_GetNextDispID(in_obj, fdexEnumDefault, id, &id);
870 if(FAILED(hres) || hres == S_FALSE)
871 break;
873 hres = IDispatchEx_GetMemberName(in_obj, id, &str);
874 if(FAILED(hres))
875 break;
877 TRACE("iter %s\n", debugstr_w(str));
879 if(stat->variable) {
880 hres = identifier_eval(ctx, identifier, 0, NULL, &exprval);
881 }else {
882 switch(stat->expr->type) {
883 case EXPR_ARRAY:
884 hres = array_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
885 break;
886 case EXPR_IDENT:
887 hres = identifier_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
888 break;
889 case EXPR_MEMBER:
890 hres = member_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
891 break;
892 default:
893 hres = expr_eval(ctx, stat->expr, &rt->ei, &tmp);
894 if(FAILED(hres))
895 break;
897 VariantClear(&tmp);
898 hres = throw_reference_error(ctx, &rt->ei, JS_E_ILLEGAL_ASSIGN, NULL);
899 break;
902 if(SUCCEEDED(hres)) {
903 V_VT(&name) = VT_BSTR;
904 V_BSTR(&name) = str;
905 hres = put_value(ctx, &exprval, &name, &rt->ei);
906 exprval_release(&exprval);
908 SysFreeString(str);
909 if(FAILED(hres))
910 break;
912 hres = stat_eval(ctx, stat->statement, rt, &tmp);
913 if(FAILED(hres))
914 break;
916 VariantClear(&retv);
917 retv = tmp;
919 if(rt->type == RT_CONTINUE)
920 rt->type = RT_NORMAL;
921 else if(rt->type != RT_NORMAL)
922 break;
925 SysFreeString(identifier);
926 IDispatchEx_Release(in_obj);
927 if(FAILED(hres)) {
928 VariantClear(&retv);
929 return hres;
932 if(rt->type == RT_BREAK)
933 rt->type = RT_NORMAL;
935 *ret = retv;
936 return S_OK;
939 /* ECMA-262 3rd Edition 12.7 */
940 HRESULT continue_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
942 branch_statement_t *stat = (branch_statement_t*)_stat;
944 TRACE("\n");
946 if(stat->identifier) {
947 FIXME("indentifier not implemented\n");
948 return E_NOTIMPL;
951 rt->type = RT_CONTINUE;
952 V_VT(ret) = VT_EMPTY;
953 return S_OK;
956 /* ECMA-262 3rd Edition 12.8 */
957 HRESULT break_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
959 branch_statement_t *stat = (branch_statement_t*)_stat;
961 TRACE("\n");
963 if(stat->identifier) {
964 FIXME("indentifier not implemented\n");
965 return E_NOTIMPL;
968 rt->type = RT_BREAK;
969 V_VT(ret) = VT_EMPTY;
970 return S_OK;
973 /* ECMA-262 3rd Edition 12.9 */
974 HRESULT return_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
976 expression_statement_t *stat = (expression_statement_t*)_stat;
977 HRESULT hres;
979 TRACE("\n");
981 if(stat->expr) {
982 hres = expr_eval(ctx, stat->expr, &rt->ei, ret);
983 if(FAILED(hres))
984 return hres;
985 }else {
986 V_VT(ret) = VT_EMPTY;
989 TRACE("= %s\n", debugstr_variant(ret));
990 rt->type = RT_RETURN;
991 return S_OK;
994 /* ECMA-262 3rd Edition 12.10 */
995 HRESULT with_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
997 with_statement_t *stat = (with_statement_t*)_stat;
998 IDispatch *disp;
999 jsdisp_t *obj;
1000 VARIANT val;
1001 HRESULT hres;
1003 TRACE("\n");
1005 hres = expr_eval(ctx, stat->expr, &rt->ei, &val);
1006 if(FAILED(hres))
1007 return hres;
1009 hres = to_object(ctx, &val, &disp);
1010 VariantClear(&val);
1011 if(FAILED(hres))
1012 return hres;
1014 obj = iface_to_jsdisp((IUnknown*)disp);
1015 IDispatch_Release(disp);
1016 if(!obj) {
1017 FIXME("disp id not jsdisp\n");
1018 return E_NOTIMPL;
1021 hres = scope_push(ctx->exec_ctx->scope_chain, obj, &ctx->exec_ctx->scope_chain);
1022 jsdisp_release(obj);
1023 if(FAILED(hres))
1024 return hres;
1026 hres = stat_eval(ctx, stat->statement, rt, ret);
1028 scope_pop(&ctx->exec_ctx->scope_chain);
1029 return hres;
1032 /* ECMA-262 3rd Edition 12.12 */
1033 HRESULT labelled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
1035 FIXME("\n");
1036 return E_NOTIMPL;
1039 /* ECMA-262 3rd Edition 12.13 */
1040 HRESULT switch_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1042 switch_statement_t *stat = (switch_statement_t*)_stat;
1043 case_clausule_t *iter, *default_clausule = NULL;
1044 statement_t *stat_iter;
1045 VARIANT val, cval;
1046 BOOL b;
1047 HRESULT hres;
1049 TRACE("\n");
1051 hres = expr_eval(ctx, stat->expr, &rt->ei, &val);
1052 if(FAILED(hres))
1053 return hres;
1055 for(iter = stat->case_list; iter; iter = iter->next) {
1056 if(!iter->expr) {
1057 default_clausule = iter;
1058 continue;
1061 hres = expr_eval(ctx, iter->expr, &rt->ei, &cval);
1062 if(FAILED(hres))
1063 break;
1065 hres = equal2_values(&val, &cval, &b);
1066 VariantClear(&cval);
1067 if(FAILED(hres) || b)
1068 break;
1071 VariantClear(&val);
1072 if(FAILED(hres))
1073 return hres;
1075 if(!iter)
1076 iter = default_clausule;
1078 V_VT(&val) = VT_EMPTY;
1079 if(iter) {
1080 VARIANT tmp;
1082 for(stat_iter = iter->stat; stat_iter; stat_iter = stat_iter->next) {
1083 hres = stat_eval(ctx, stat_iter, rt, &tmp);
1084 if(FAILED(hres))
1085 break;
1087 VariantClear(&val);
1088 val = tmp;
1090 if(rt->type != RT_NORMAL)
1091 break;
1095 if(FAILED(hres)) {
1096 VariantClear(&val);
1097 return hres;
1100 if(rt->type == RT_BREAK)
1101 rt->type = RT_NORMAL;
1103 *ret = val;
1104 return S_OK;
1107 /* ECMA-262 3rd Edition 12.13 */
1108 HRESULT throw_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1110 expression_statement_t *stat = (expression_statement_t*)_stat;
1111 VARIANT val;
1112 HRESULT hres;
1114 TRACE("\n");
1116 hres = expr_eval(ctx, stat->expr, &rt->ei, &val);
1117 if(FAILED(hres))
1118 return hres;
1120 rt->ei.var = val;
1121 return DISP_E_EXCEPTION;
1124 static HRESULT interp_throw(exec_ctx_t *ctx)
1126 const HRESULT arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1128 TRACE("%08x\n", arg);
1130 return throw_reference_error(ctx->parser->script, ctx->ei, arg, NULL);
1133 static HRESULT interp_throw_type(exec_ctx_t *ctx)
1135 const HRESULT hres = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1136 const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg2.str;
1138 TRACE("%08x %s\n", hres, debugstr_w(str));
1140 return throw_type_error(ctx->parser->script, ctx->ei, hres, str);
1143 /* ECMA-262 3rd Edition 12.14 */
1144 static HRESULT catch_eval(script_ctx_t *ctx, catch_block_t *block, return_type_t *rt, VARIANT *ret)
1146 jsdisp_t *var_disp;
1147 VARIANT ex, val;
1148 HRESULT hres;
1150 ex = rt->ei.var;
1151 memset(&rt->ei, 0, sizeof(jsexcept_t));
1153 hres = create_dispex(ctx, NULL, NULL, &var_disp);
1154 if(SUCCEEDED(hres)) {
1155 hres = jsdisp_propput_name(var_disp, block->identifier, &ex, &rt->ei, NULL/*FIXME*/);
1156 if(SUCCEEDED(hres)) {
1157 hres = scope_push(ctx->exec_ctx->scope_chain, var_disp, &ctx->exec_ctx->scope_chain);
1158 if(SUCCEEDED(hres)) {
1159 hres = stat_eval(ctx, block->statement, rt, &val);
1160 scope_pop(&ctx->exec_ctx->scope_chain);
1164 jsdisp_release(var_disp);
1167 VariantClear(&ex);
1168 if(FAILED(hres))
1169 return hres;
1171 *ret = val;
1172 return S_OK;
1175 /* ECMA-262 3rd Edition 12.14 */
1176 HRESULT try_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1178 try_statement_t *stat = (try_statement_t*)_stat;
1179 VARIANT val;
1180 HRESULT hres;
1182 TRACE("\n");
1184 hres = stat_eval(ctx, stat->try_statement, rt, &val);
1185 if(FAILED(hres)) {
1186 TRACE("EXCEPTION\n");
1187 if(!stat->catch_block)
1188 return hres;
1190 hres = catch_eval(ctx, stat->catch_block, rt, &val);
1191 if(FAILED(hres))
1192 return hres;
1195 if(stat->finally_statement) {
1196 VariantClear(&val);
1197 hres = stat_eval(ctx, stat->finally_statement, rt, &val);
1198 if(FAILED(hres))
1199 return hres;
1202 *ret = val;
1203 return S_OK;
1206 /* ECMA-262 3rd Edition 13 */
1207 static HRESULT interp_func(exec_ctx_t *ctx)
1209 function_expression_t *expr = ctx->parser->code->instrs[ctx->ip].arg1.func;
1210 jsdisp_t *dispex;
1211 VARIANT v;
1212 HRESULT hres;
1214 TRACE("\n");
1216 hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain,
1217 expr->src_str, expr->src_len, &dispex);
1218 if(FAILED(hres))
1219 return hres;
1221 var_set_jsdisp(&v, dispex);
1222 return stack_push(ctx, &v);
1225 /* ECMA-262 3rd Edition 11.2.1 */
1226 static HRESULT array_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1228 binary_expression_t *expr = (binary_expression_t*)_expr;
1229 VARIANT member, val;
1230 DISPID id;
1231 BSTR str;
1232 IDispatch *obj = NULL;
1233 HRESULT hres;
1235 TRACE("\n");
1237 hres = expr_eval(ctx, expr->expression1, ei, &member);
1238 if(FAILED(hres))
1239 return hres;
1241 hres = expr_eval(ctx, expr->expression2, ei, &val);
1242 if(SUCCEEDED(hres)) {
1243 hres = to_object(ctx, &member, &obj);
1244 if(FAILED(hres))
1245 VariantClear(&val);
1247 VariantClear(&member);
1248 if(SUCCEEDED(hres)) {
1249 hres = to_string(ctx, &val, ei, &str);
1250 VariantClear(&val);
1251 if(SUCCEEDED(hres)) {
1252 hres = disp_get_id(ctx, obj, str, fdexNameEnsure, &id);
1253 SysFreeString(str);
1256 if(SUCCEEDED(hres))
1257 exprval_set_idref(ret, obj, id);
1259 IDispatch_Release(obj);
1262 return hres;
1265 /* ECMA-262 3rd Edition 11.2.1 */
1266 static HRESULT interp_array(exec_ctx_t *ctx)
1268 VARIANT v, *namev;
1269 IDispatch *obj;
1270 DISPID id;
1271 BSTR name;
1272 HRESULT hres;
1274 TRACE("\n");
1276 namev = stack_pop(ctx);
1278 hres = stack_pop_object(ctx, &obj);
1279 if(FAILED(hres)) {
1280 VariantClear(namev);
1281 return hres;
1284 hres = to_string(ctx->parser->script, namev, ctx->ei, &name);
1285 VariantClear(namev);
1286 if(FAILED(hres)) {
1287 IDispatch_Release(obj);
1288 return hres;
1291 hres = disp_get_id(ctx->parser->script, obj, name, 0, &id);
1292 SysFreeString(name);
1293 if(SUCCEEDED(hres)) {
1294 hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1295 }else if(hres == DISP_E_UNKNOWNNAME) {
1296 V_VT(&v) = VT_EMPTY;
1297 hres = S_OK;
1299 IDispatch_Release(obj);
1300 if(FAILED(hres))
1301 return hres;
1303 return stack_push(ctx, &v);
1306 /* ECMA-262 3rd Edition 11.2.1 */
1307 static HRESULT member_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1309 member_expression_t *expr = (member_expression_t*)_expr;
1310 IDispatch *obj = NULL;
1311 VARIANT member;
1312 DISPID id;
1313 BSTR str;
1314 HRESULT hres;
1316 TRACE("\n");
1318 hres = expr_eval(ctx, expr->expression, ei, &member);
1319 if(FAILED(hres))
1320 return hres;
1322 hres = to_object(ctx, &member, &obj);
1323 VariantClear(&member);
1324 if(FAILED(hres))
1325 return hres;
1327 str = SysAllocString(expr->identifier);
1328 if(!str) {
1329 IDispatch_Release(obj);
1330 return E_OUTOFMEMORY;
1333 hres = disp_get_id(ctx, obj, str, fdexNameEnsure, &id);
1334 SysFreeString(str);
1335 if(SUCCEEDED(hres))
1336 exprval_set_idref(ret, obj, id);
1338 IDispatch_Release(obj);
1339 return hres;
1342 /* ECMA-262 3rd Edition 11.2.1 */
1343 static HRESULT interp_member(exec_ctx_t *ctx)
1345 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1346 IDispatch *obj;
1347 VARIANT v;
1348 DISPID id;
1349 HRESULT hres;
1351 TRACE("\n");
1353 hres = stack_pop_object(ctx, &obj);
1354 if(FAILED(hres))
1355 return hres;
1357 hres = disp_get_id(ctx->parser->script, obj, arg, 0, &id);
1358 if(SUCCEEDED(hres)) {
1359 V_VT(&v) = VT_EMPTY;
1360 hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1361 }else if(hres == DISP_E_UNKNOWNNAME) {
1362 V_VT(&v) = VT_EMPTY;
1363 hres = S_OK;
1365 IDispatch_Release(obj);
1366 if(FAILED(hres))
1367 return hres;
1369 return stack_push(ctx, &v);
1372 /* ECMA-262 3rd Edition 11.2.1 */
1373 static HRESULT interp_memberid(exec_ctx_t *ctx)
1375 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1376 VARIANT *objv, *namev;
1377 IDispatch *obj;
1378 BSTR name;
1379 DISPID id;
1380 HRESULT hres;
1382 TRACE("%x\n", arg);
1384 namev = stack_pop(ctx);
1385 objv = stack_pop(ctx);
1387 hres = to_object(ctx->parser->script, objv, &obj);
1388 VariantClear(objv);
1389 if(SUCCEEDED(hres)) {
1390 hres = to_string(ctx->parser->script, namev, ctx->ei, &name);
1391 if(FAILED(hres))
1392 IDispatch_Release(obj);
1394 VariantClear(namev);
1395 if(FAILED(hres))
1396 return hres;
1398 hres = disp_get_id(ctx->parser->script, obj, name, arg, &id);
1399 SysFreeString(name);
1400 if(FAILED(hres)) {
1401 IDispatch_Release(obj);
1402 if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
1403 obj = NULL;
1404 id = JS_E_INVALID_PROPERTY;
1405 }else {
1406 return hres;
1410 return stack_push_objid(ctx, obj, id);
1413 /* ECMA-262 3rd Edition 11.2.1 */
1414 static HRESULT interp_refval(exec_ctx_t *ctx)
1416 IDispatch *disp;
1417 VARIANT v;
1418 DISPID id;
1419 HRESULT hres;
1421 TRACE("\n");
1423 disp = stack_topn_objid(ctx, 0, &id);
1424 if(!disp)
1425 return throw_reference_error(ctx->parser->script, ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
1427 hres = disp_propget(ctx->parser->script, disp, id, &v, ctx->ei, NULL/*FIXME*/);
1428 if(FAILED(hres))
1429 return hres;
1431 return stack_push(ctx, &v);
1434 static void jsstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, DISPPARAMS *dp)
1436 VARIANT tmp;
1437 unsigned i;
1439 dp->cArgs = arg_cnt;
1440 dp->rgdispidNamedArgs = NULL;
1441 dp->cNamedArgs = 0;
1443 assert(ctx->top >= arg_cnt);
1445 for(i=1; i*2 <= arg_cnt; i++) {
1446 tmp = ctx->stack[ctx->top-i];
1447 ctx->stack[ctx->top-i] = ctx->stack[ctx->top-arg_cnt+i-1];
1448 ctx->stack[ctx->top-arg_cnt+i-1] = tmp;
1451 dp->rgvarg = ctx->stack + ctx->top-arg_cnt;
1454 /* ECMA-262 3rd Edition 11.2.2 */
1455 static HRESULT interp_new(exec_ctx_t *ctx)
1457 const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1458 VARIANT *constr, v;
1459 DISPPARAMS dp;
1460 HRESULT hres;
1462 TRACE("%d\n", arg);
1464 constr = stack_topn(ctx, arg);
1466 /* NOTE: Should use to_object here */
1468 if(V_VT(constr) == VT_NULL)
1469 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1470 else if(V_VT(constr) != VT_DISPATCH)
1471 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_ACTION, NULL);
1472 else if(!V_DISPATCH(constr))
1473 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1475 jsstack_to_dp(ctx, arg, &dp);
1476 hres = disp_call(ctx->parser->script, V_DISPATCH(constr), DISPID_VALUE,
1477 DISPATCH_CONSTRUCT, &dp, &v, ctx->ei, NULL/*FIXME*/);
1478 if(FAILED(hres))
1479 return hres;
1481 stack_popn(ctx, arg+1);
1482 return stack_push(ctx, &v);
1485 /* ECMA-262 3rd Edition 11.2.3 */
1486 static HRESULT interp_call(exec_ctx_t *ctx)
1488 const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1489 const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1490 VARIANT v, *objv;
1491 DISPPARAMS dp;
1492 HRESULT hres;
1494 TRACE("%d %d\n", argn, do_ret);
1496 objv = stack_topn(ctx, argn);
1497 if(V_VT(objv) != VT_DISPATCH)
1498 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1500 jsstack_to_dp(ctx, argn, &dp);
1501 hres = disp_call(ctx->parser->script, V_DISPATCH(objv), DISPID_VALUE, DISPATCH_METHOD, &dp,
1502 do_ret ? &v : NULL, ctx->ei, NULL/*FIXME*/);
1503 if(FAILED(hres))
1504 return hres;
1506 stack_popn(ctx, argn+1);
1507 return do_ret ? stack_push(ctx, &v) : S_OK;
1511 /* ECMA-262 3rd Edition 11.2.3 */
1512 static HRESULT interp_call_member(exec_ctx_t *ctx)
1514 const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1515 const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1516 IDispatch *obj;
1517 DISPPARAMS dp;
1518 VARIANT v;
1519 DISPID id;
1520 HRESULT hres;
1522 TRACE("%d %d\n", argn, do_ret);
1524 obj = stack_topn_objid(ctx, argn, &id);
1525 if(!obj)
1526 return throw_type_error(ctx->parser->script, ctx->ei, id, NULL);
1528 jsstack_to_dp(ctx, argn, &dp);
1529 hres = disp_call(ctx->parser->script, obj, id, DISPATCH_METHOD, &dp, do_ret ? &v : NULL, ctx->ei, NULL/*FIXME*/);
1530 if(FAILED(hres))
1531 return hres;
1533 stack_popn(ctx, argn+2);
1534 return do_ret ? stack_push(ctx, &v) : S_OK;
1538 /* ECMA-262 3rd Edition 11.1.1 */
1539 static HRESULT interp_this(exec_ctx_t *ctx)
1541 VARIANT v;
1543 TRACE("\n");
1545 V_VT(&v) = VT_DISPATCH;
1546 V_DISPATCH(&v) = ctx->this_obj;
1547 IDispatch_AddRef(ctx->this_obj);
1548 return stack_push(ctx, &v);
1551 /* ECMA-262 3rd Edition 10.1.4 */
1552 static HRESULT identifier_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1554 identifier_expression_t *expr = (identifier_expression_t*)_expr;
1555 BSTR identifier;
1556 HRESULT hres;
1558 TRACE("\n");
1560 identifier = SysAllocString(expr->identifier);
1561 if(!identifier)
1562 return E_OUTOFMEMORY;
1564 hres = identifier_eval(ctx, identifier, fdexNameEnsure, ei, ret);
1566 SysFreeString(identifier);
1567 return hres;
1570 /* ECMA-262 3rd Edition 10.1.4 */
1571 static HRESULT interp_ident(exec_ctx_t *ctx)
1573 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1574 exprval_t exprval;
1575 VARIANT v;
1576 HRESULT hres;
1578 TRACE("%s\n", debugstr_w(arg));
1580 hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
1581 if(FAILED(hres))
1582 return hres;
1584 if(exprval.type == EXPRVAL_INVALID)
1585 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_UNDEFINED_VARIABLE, arg);
1587 hres = exprval_to_value(ctx->parser->script, &exprval, ctx->ei, &v);
1588 exprval_release(&exprval);
1589 if(FAILED(hres))
1590 return hres;
1592 return stack_push(ctx, &v);
1595 /* ECMA-262 3rd Edition 10.1.4 */
1596 static HRESULT interp_identid(exec_ctx_t *ctx)
1598 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1599 const unsigned flags = ctx->parser->code->instrs[ctx->ip].arg2.uint;
1600 exprval_t exprval;
1601 HRESULT hres;
1603 TRACE("%s %x\n", debugstr_w(arg), flags);
1605 hres = identifier_eval(ctx->parser->script, arg, flags, ctx->ei, &exprval);
1606 if(FAILED(hres))
1607 return hres;
1609 if(exprval.type != EXPRVAL_IDREF) {
1610 WARN("invalid ref\n");
1611 exprval_release(&exprval);
1612 return stack_push_objid(ctx, NULL, JS_E_OBJECT_EXPECTED);
1615 return stack_push_objid(ctx, exprval.u.idref.disp, exprval.u.idref.id);
1618 /* ECMA-262 3rd Edition 7.8.1 */
1619 static HRESULT interp_null(exec_ctx_t *ctx)
1621 VARIANT v;
1623 TRACE("\n");
1625 V_VT(&v) = VT_NULL;
1626 return stack_push(ctx, &v);
1629 /* ECMA-262 3rd Edition 7.8.2 */
1630 static HRESULT interp_bool(exec_ctx_t *ctx)
1632 const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1634 TRACE("%s\n", arg ? "true" : "false");
1636 return stack_push_bool(ctx, arg);
1639 /* ECMA-262 3rd Edition 7.8.3 */
1640 static HRESULT interp_int(exec_ctx_t *ctx)
1642 const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1643 VARIANT v;
1645 TRACE("%d\n", arg);
1647 V_VT(&v) = VT_I4;
1648 V_I4(&v) = arg;
1649 return stack_push(ctx, &v);
1652 /* ECMA-262 3rd Edition 7.8.3 */
1653 static HRESULT interp_double(exec_ctx_t *ctx)
1655 const double arg = *ctx->parser->code->instrs[ctx->ip].arg1.dbl;
1656 VARIANT v;
1658 TRACE("%lf\n", arg);
1660 V_VT(&v) = VT_R8;
1661 V_R8(&v) = arg;
1662 return stack_push(ctx, &v);
1665 /* ECMA-262 3rd Edition 7.8.4 */
1666 static HRESULT interp_str(exec_ctx_t *ctx)
1668 const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg1.str;
1669 VARIANT v;
1671 TRACE("%s\n", debugstr_w(str));
1673 V_VT(&v) = VT_BSTR;
1674 V_BSTR(&v) = SysAllocString(str);
1675 if(!V_BSTR(&v))
1676 return E_OUTOFMEMORY;
1678 return stack_push(ctx, &v);
1681 /* ECMA-262 3rd Edition 7.8 */
1682 static HRESULT interp_regexp(exec_ctx_t *ctx)
1684 const WCHAR *source = ctx->parser->code->instrs[ctx->ip].arg1.str;
1685 const LONG flags = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1686 jsdisp_t *regexp;
1687 VARIANT v;
1688 HRESULT hres;
1690 TRACE("%s %x\n", debugstr_w(source), flags);
1692 hres = create_regexp(ctx->parser->script, source, strlenW(source), flags, &regexp);
1693 if(FAILED(hres))
1694 return hres;
1696 var_set_jsdisp(&v, regexp);
1697 return stack_push(ctx, &v);
1700 /* ECMA-262 3rd Edition 11.1.4 */
1701 static HRESULT interp_carray(exec_ctx_t *ctx)
1703 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1704 jsdisp_t *array;
1705 VARIANT *v, r;
1706 unsigned i;
1707 HRESULT hres;
1709 TRACE("%u\n", arg);
1711 hres = create_array(ctx->parser->script, arg, &array);
1712 if(FAILED(hres))
1713 return hres;
1715 i = arg;
1716 while(i--) {
1717 v = stack_pop(ctx);
1718 hres = jsdisp_propput_idx(array, i, v, ctx->ei, NULL/*FIXME*/);
1719 VariantClear(v);
1720 if(FAILED(hres)) {
1721 jsdisp_release(array);
1722 return hres;
1726 var_set_jsdisp(&r, array);
1727 return stack_push(ctx, &r);
1730 /* ECMA-262 3rd Edition 11.1.5 */
1731 HRESULT interp_new_obj(exec_ctx_t *ctx)
1733 jsdisp_t *obj;
1734 VARIANT v;
1735 HRESULT hres;
1737 TRACE("\n");
1739 hres = create_object(ctx->parser->script, NULL, &obj);
1740 if(FAILED(hres))
1741 return hres;
1743 var_set_jsdisp(&v, obj);
1744 return stack_push(ctx, &v);
1747 /* ECMA-262 3rd Edition 11.1.5 */
1748 HRESULT interp_obj_prop(exec_ctx_t *ctx)
1750 const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1751 jsdisp_t *obj;
1752 VARIANT *v;
1753 HRESULT hres;
1755 TRACE("%s\n", debugstr_w(name));
1757 v = stack_pop(ctx);
1759 assert(V_VT(stack_top(ctx)) == VT_DISPATCH);
1760 obj = as_jsdisp(V_DISPATCH(stack_top(ctx)));
1762 hres = jsdisp_propput_name(obj, name, v, ctx->ei, NULL/*FIXME*/);
1763 VariantClear(v);
1764 return hres;
1767 /* ECMA-262 3rd Edition 11.11 */
1768 static HRESULT interp_jmp_nz(exec_ctx_t *ctx)
1770 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1771 VARIANT_BOOL b;
1772 HRESULT hres;
1774 TRACE("\n");
1776 hres = to_boolean(stack_top(ctx), &b);
1777 if(FAILED(hres))
1778 return hres;
1780 if(b) {
1781 ctx->ip = arg;
1782 }else {
1783 stack_popn(ctx, 1);
1784 ctx->ip++;
1786 return S_OK;
1789 /* ECMA-262 3rd Edition 11.11 */
1790 static HRESULT interp_jmp_z(exec_ctx_t *ctx)
1792 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1793 VARIANT_BOOL b;
1794 HRESULT hres;
1796 TRACE("\n");
1798 hres = to_boolean(stack_top(ctx), &b);
1799 if(FAILED(hres))
1800 return hres;
1802 if(b) {
1803 stack_popn(ctx, 1);
1804 ctx->ip++;
1805 }else {
1806 ctx->ip = arg;
1808 return S_OK;
1811 /* ECMA-262 3rd Edition 11.10 */
1812 static HRESULT interp_or(exec_ctx_t *ctx)
1814 INT l, r;
1815 HRESULT hres;
1817 TRACE("\n");
1819 hres = stack_pop_int(ctx, &r);
1820 if(FAILED(hres))
1821 return hres;
1823 hres = stack_pop_int(ctx, &l);
1824 if(FAILED(hres))
1825 return hres;
1827 return stack_push_int(ctx, l|r);
1830 /* ECMA-262 3rd Edition 11.10 */
1831 static HRESULT interp_xor(exec_ctx_t *ctx)
1833 INT l, r;
1834 HRESULT hres;
1836 TRACE("\n");
1838 hres = stack_pop_int(ctx, &r);
1839 if(FAILED(hres))
1840 return hres;
1842 hres = stack_pop_int(ctx, &l);
1843 if(FAILED(hres))
1844 return hres;
1846 return stack_push_int(ctx, l^r);
1849 /* ECMA-262 3rd Edition 11.10 */
1850 static HRESULT interp_and(exec_ctx_t *ctx)
1852 INT l, r;
1853 HRESULT hres;
1855 TRACE("\n");
1857 hres = stack_pop_int(ctx, &r);
1858 if(FAILED(hres))
1859 return hres;
1861 hres = stack_pop_int(ctx, &l);
1862 if(FAILED(hres))
1863 return hres;
1865 return stack_push_int(ctx, l&r);
1868 /* ECMA-262 3rd Edition 11.8.6 */
1869 static HRESULT interp_instanceof(exec_ctx_t *ctx)
1871 jsdisp_t *obj, *iter, *tmp = NULL;
1872 VARIANT prot, *v;
1873 BOOL ret = FALSE;
1874 HRESULT hres;
1876 static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
1878 v = stack_pop(ctx);
1879 if(V_VT(v) != VT_DISPATCH || !V_DISPATCH(v)) {
1880 VariantClear(v);
1881 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
1884 obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
1885 IDispatch_Release(V_DISPATCH(v));
1886 if(!obj) {
1887 FIXME("non-jsdisp objects not supported\n");
1888 return E_FAIL;
1891 if(is_class(obj, JSCLASS_FUNCTION)) {
1892 hres = jsdisp_propget_name(obj, prototypeW, &prot, ctx->ei, NULL/*FIXME*/);
1893 }else {
1894 hres = throw_type_error(ctx->parser->script, ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
1896 jsdisp_release(obj);
1897 if(FAILED(hres))
1898 return hres;
1900 v = stack_pop(ctx);
1902 if(V_VT(&prot) == VT_DISPATCH) {
1903 if(V_VT(v) == VT_DISPATCH)
1904 tmp = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
1905 for(iter = tmp; !ret && iter; iter = iter->prototype) {
1906 hres = disp_cmp(V_DISPATCH(&prot), to_disp(iter), &ret);
1907 if(FAILED(hres))
1908 break;
1911 if(tmp)
1912 jsdisp_release(tmp);
1913 }else {
1914 FIXME("prototype is not an object\n");
1915 hres = E_FAIL;
1918 VariantClear(&prot);
1919 VariantClear(v);
1920 if(FAILED(hres))
1921 return hres;
1923 return stack_push_bool(ctx, ret);
1926 /* ECMA-262 3rd Edition 11.8.7 */
1927 static HRESULT interp_in(exec_ctx_t *ctx)
1929 VARIANT *obj, *v;
1930 DISPID id = 0;
1931 BOOL ret;
1932 BSTR str;
1933 HRESULT hres;
1935 TRACE("\n");
1937 obj = stack_pop(ctx);
1938 v = stack_pop(ctx);
1940 if(V_VT(obj) != VT_DISPATCH || !V_DISPATCH(obj)) {
1941 VariantClear(obj);
1942 VariantClear(v);
1943 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1946 hres = to_string(ctx->parser->script, v, ctx->ei, &str);
1947 VariantClear(v);
1948 if(FAILED(hres)) {
1949 IDispatch_Release(V_DISPATCH(obj));
1950 return hres;
1953 hres = disp_get_id(ctx->parser->script, V_DISPATCH(obj), str, 0, &id);
1954 IDispatch_Release(V_DISPATCH(obj));
1955 SysFreeString(str);
1956 if(SUCCEEDED(hres))
1957 ret = TRUE;
1958 else if(hres == DISP_E_UNKNOWNNAME)
1959 ret = FALSE;
1960 else
1961 return hres;
1963 return stack_push_bool(ctx, ret);
1966 /* ECMA-262 3rd Edition 11.6.1 */
1967 static HRESULT add_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
1969 VARIANT r, l;
1970 HRESULT hres;
1972 hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
1973 if(FAILED(hres))
1974 return hres;
1976 hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
1977 if(FAILED(hres)) {
1978 VariantClear(&l);
1979 return hres;
1982 if(V_VT(&l) == VT_BSTR || V_VT(&r) == VT_BSTR) {
1983 BSTR lstr = NULL, rstr = NULL;
1985 if(V_VT(&l) == VT_BSTR)
1986 lstr = V_BSTR(&l);
1987 else
1988 hres = to_string(ctx, &l, ei, &lstr);
1990 if(SUCCEEDED(hres)) {
1991 if(V_VT(&r) == VT_BSTR)
1992 rstr = V_BSTR(&r);
1993 else
1994 hres = to_string(ctx, &r, ei, &rstr);
1997 if(SUCCEEDED(hres)) {
1998 int len1, len2;
2000 len1 = SysStringLen(lstr);
2001 len2 = SysStringLen(rstr);
2003 V_VT(retv) = VT_BSTR;
2004 V_BSTR(retv) = SysAllocStringLen(NULL, len1+len2);
2005 memcpy(V_BSTR(retv), lstr, len1*sizeof(WCHAR));
2006 memcpy(V_BSTR(retv)+len1, rstr, (len2+1)*sizeof(WCHAR));
2009 if(V_VT(&l) != VT_BSTR)
2010 SysFreeString(lstr);
2011 if(V_VT(&r) != VT_BSTR)
2012 SysFreeString(rstr);
2013 }else {
2014 VARIANT nl, nr;
2016 hres = to_number(ctx, &l, ei, &nl);
2017 if(SUCCEEDED(hres)) {
2018 hres = to_number(ctx, &r, ei, &nr);
2019 if(SUCCEEDED(hres))
2020 num_set_val(retv, num_val(&nl) + num_val(&nr));
2024 VariantClear(&r);
2025 VariantClear(&l);
2026 return hres;
2029 /* ECMA-262 3rd Edition 11.6.1 */
2030 static HRESULT interp_add(exec_ctx_t *ctx)
2032 VARIANT *l, *r, ret;
2033 HRESULT hres;
2035 r = stack_pop(ctx);
2036 l = stack_pop(ctx);
2038 TRACE("%s + %s\n", debugstr_variant(l), debugstr_variant(r));
2040 hres = add_eval(ctx->parser->script, l, r, ctx->ei, &ret);
2041 VariantClear(l);
2042 VariantClear(r);
2043 if(FAILED(hres))
2044 return hres;
2046 return stack_push(ctx, &ret);
2049 /* ECMA-262 3rd Edition 11.6.2 */
2050 static HRESULT interp_sub(exec_ctx_t *ctx)
2052 VARIANT l, r;
2053 HRESULT hres;
2055 TRACE("\n");
2057 hres = stack_pop_number(ctx, &r);
2058 if(FAILED(hres))
2059 return hres;
2061 hres = stack_pop_number(ctx, &l);
2062 if(FAILED(hres))
2063 return hres;
2065 return stack_push_number(ctx, num_val(&l)-num_val(&r));
2068 /* ECMA-262 3rd Edition 11.5.1 */
2069 static HRESULT interp_mul(exec_ctx_t *ctx)
2071 VARIANT l, r;
2072 HRESULT hres;
2074 TRACE("\n");
2076 hres = stack_pop_number(ctx, &r);
2077 if(FAILED(hres))
2078 return hres;
2080 hres = stack_pop_number(ctx, &l);
2081 if(FAILED(hres))
2082 return hres;
2084 return stack_push_number(ctx, num_val(&l)*num_val(&r));
2087 /* ECMA-262 3rd Edition 11.5.2 */
2088 static HRESULT interp_div(exec_ctx_t *ctx)
2090 VARIANT l, r;
2091 HRESULT hres;
2093 TRACE("\n");
2095 hres = stack_pop_number(ctx, &r);
2096 if(FAILED(hres))
2097 return hres;
2099 hres = stack_pop_number(ctx, &l);
2100 if(FAILED(hres))
2101 return hres;
2103 return stack_push_number(ctx, num_val(&l)/num_val(&r));
2106 /* ECMA-262 3rd Edition 11.5.3 */
2107 static HRESULT interp_mod(exec_ctx_t *ctx)
2109 VARIANT l, r;
2110 HRESULT hres;
2112 TRACE("\n");
2114 hres = stack_pop_number(ctx, &r);
2115 if(FAILED(hres))
2116 return hres;
2118 hres = stack_pop_number(ctx, &l);
2119 if(FAILED(hres))
2120 return hres;
2122 return stack_push_number(ctx, fmod(num_val(&l), num_val(&r)));
2125 /* ECMA-262 3rd Edition 11.4.2 */
2126 static HRESULT interp_delete(exec_ctx_t *ctx)
2128 VARIANT *obj_var, *name_var;
2129 IDispatchEx *dispex;
2130 IDispatch *obj;
2131 BSTR name;
2132 BOOL ret;
2133 HRESULT hres;
2135 TRACE("\n");
2137 name_var = stack_pop(ctx);
2138 obj_var = stack_pop(ctx);
2140 hres = to_object(ctx->parser->script, obj_var, &obj);
2141 VariantClear(obj_var);
2142 if(FAILED(hres)) {
2143 VariantClear(name_var);
2144 return hres;
2147 hres = to_string(ctx->parser->script, name_var, ctx->ei, &name);
2148 VariantClear(name_var);
2149 if(FAILED(hres)) {
2150 IDispatch_Release(obj);
2151 return hres;
2154 hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
2155 if(SUCCEEDED(hres)) {
2156 hres = IDispatchEx_DeleteMemberByName(dispex, name, make_grfdex(ctx->parser->script, fdexNameCaseSensitive));
2157 ret = TRUE;
2158 IDispatchEx_Release(dispex);
2159 }else {
2160 hres = S_OK;
2161 ret = FALSE;
2164 IDispatch_Release(obj);
2165 SysFreeString(name);
2166 if(FAILED(hres))
2167 return hres;
2169 return stack_push_bool(ctx, ret);
2172 /* ECMA-262 3rd Edition 11.4.2 */
2173 static HRESULT interp_delete_ident(exec_ctx_t *ctx)
2175 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2176 IDispatchEx *dispex;
2177 exprval_t exprval;
2178 BOOL ret = FALSE;
2179 HRESULT hres;
2181 TRACE("%s\n", debugstr_w(arg));
2183 hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
2184 if(FAILED(hres))
2185 return hres;
2187 if(exprval.type != EXPRVAL_IDREF) {
2188 FIXME("Unsupported exprval\n");
2189 exprval_release(&exprval);
2190 return E_NOTIMPL;
2193 hres = IDispatch_QueryInterface(exprval.u.idref.disp, &IID_IDispatchEx, (void**)&dispex);
2194 IDispatch_Release(exprval.u.idref.disp);
2195 if(SUCCEEDED(hres)) {
2196 hres = IDispatchEx_DeleteMemberByDispID(dispex, exprval.u.idref.id);
2197 IDispatchEx_Release(dispex);
2198 if(FAILED(hres))
2199 return hres;
2201 ret = TRUE;
2204 return stack_push_bool(ctx, ret);
2207 /* ECMA-262 3rd Edition 11.4.2 */
2208 static HRESULT interp_void(exec_ctx_t *ctx)
2210 VARIANT v;
2212 TRACE("\n");
2214 stack_popn(ctx, 1);
2216 V_VT(&v) = VT_EMPTY;
2217 return stack_push(ctx, &v);
2220 /* ECMA-262 3rd Edition 11.4.3 */
2221 static HRESULT typeof_string(VARIANT *v, const WCHAR **ret)
2223 switch(V_VT(v)) {
2224 case VT_EMPTY:
2225 *ret = undefinedW;
2226 break;
2227 case VT_NULL:
2228 *ret = objectW;
2229 break;
2230 case VT_BOOL:
2231 *ret = booleanW;
2232 break;
2233 case VT_I4:
2234 case VT_R8:
2235 *ret = numberW;
2236 break;
2237 case VT_BSTR:
2238 *ret = stringW;
2239 break;
2240 case VT_DISPATCH: {
2241 jsdisp_t *dispex;
2243 if(V_DISPATCH(v) && (dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(v)))) {
2244 *ret = is_class(dispex, JSCLASS_FUNCTION) ? functionW : objectW;
2245 jsdisp_release(dispex);
2246 }else {
2247 *ret = objectW;
2249 break;
2251 default:
2252 FIXME("unhandled vt %d\n", V_VT(v));
2253 return E_NOTIMPL;
2256 return S_OK;
2259 /* ECMA-262 3rd Edition 11.4.3 */
2260 static HRESULT interp_typeofid(exec_ctx_t *ctx)
2262 const WCHAR *ret;
2263 IDispatch *obj;
2264 VARIANT v;
2265 DISPID id;
2266 HRESULT hres;
2268 static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
2270 TRACE("\n");
2272 obj = stack_pop_objid(ctx, &id);
2273 if(!obj)
2274 return stack_push_string(ctx, undefinedW);
2276 V_VT(&v) = VT_EMPTY;
2277 hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2278 IDispatch_Release(obj);
2279 if(FAILED(hres))
2280 return stack_push_string(ctx, unknownW);
2282 hres = typeof_string(&v, &ret);
2283 VariantClear(&v);
2284 if(FAILED(hres))
2285 return hres;
2287 return stack_push_string(ctx, ret);
2290 /* ECMA-262 3rd Edition 11.4.3 */
2291 static HRESULT interp_typeofident(exec_ctx_t *ctx)
2293 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2294 exprval_t exprval;
2295 const WCHAR *ret;
2296 VARIANT v;
2297 HRESULT hres;
2299 TRACE("%s\n", debugstr_w(arg));
2301 hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
2302 if(FAILED(hres))
2303 return hres;
2305 if(exprval.type == EXPRVAL_INVALID) {
2306 hres = stack_push_string(ctx, undefinedW);
2307 exprval_release(&exprval);
2308 return hres;
2311 hres = exprval_to_value(ctx->parser->script, &exprval, ctx->ei, &v);
2312 exprval_release(&exprval);
2313 if(FAILED(hres))
2314 return hres;
2316 hres = typeof_string(&v, &ret);
2317 VariantClear(&v);
2318 if(FAILED(hres))
2319 return hres;
2321 return stack_push_string(ctx, ret);
2324 /* ECMA-262 3rd Edition 11.4.3 */
2325 static HRESULT interp_typeof(exec_ctx_t *ctx)
2327 const WCHAR *ret;
2328 VARIANT *v;
2329 HRESULT hres;
2331 TRACE("\n");
2333 v = stack_pop(ctx);
2334 hres = typeof_string(v, &ret);
2335 VariantClear(v);
2336 if(FAILED(hres))
2337 return hres;
2339 return stack_push_string(ctx, ret);
2342 /* ECMA-262 3rd Edition 11.4.7 */
2343 static HRESULT interp_minus(exec_ctx_t *ctx)
2345 VARIANT n;
2346 HRESULT hres;
2348 TRACE("\n");
2350 hres = stack_pop_number(ctx, &n);
2351 if(FAILED(hres))
2352 return hres;
2354 return stack_push_number(ctx, -num_val(&n));
2357 /* ECMA-262 3rd Edition 11.4.6 */
2358 static HRESULT interp_tonum(exec_ctx_t *ctx)
2360 VARIANT *v, num;
2361 HRESULT hres;
2363 TRACE("\n");
2365 v = stack_pop(ctx);
2366 hres = to_number(ctx->parser->script, v, ctx->ei, &num);
2367 VariantClear(v);
2368 if(FAILED(hres))
2369 return hres;
2371 return stack_push(ctx, &num);
2374 /* ECMA-262 3rd Edition 11.3.1 */
2375 static HRESULT interp_postinc(exec_ctx_t *ctx)
2377 const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2378 IDispatch *obj;
2379 DISPID id;
2380 VARIANT v;
2381 HRESULT hres;
2383 TRACE("%d\n", arg);
2385 obj = stack_pop_objid(ctx, &id);
2386 if(!obj)
2387 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2389 hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2390 if(SUCCEEDED(hres)) {
2391 VARIANT n, inc;
2393 hres = to_number(ctx->parser->script, &v, ctx->ei, &n);
2394 if(SUCCEEDED(hres)) {
2395 num_set_val(&inc, num_val(&n)+(double)arg);
2396 hres = disp_propput(ctx->parser->script, obj, id, &inc, ctx->ei, NULL/*FIXME*/);
2398 if(FAILED(hres))
2399 VariantClear(&v);
2401 IDispatch_Release(obj);
2402 if(FAILED(hres))
2403 return hres;
2405 return stack_push(ctx, &v);
2408 /* ECMA-262 3rd Edition 11.4.4, 11.4.5 */
2409 static HRESULT interp_preinc(exec_ctx_t *ctx)
2411 const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2412 IDispatch *obj;
2413 DISPID id;
2414 VARIANT v;
2415 HRESULT hres;
2417 TRACE("%d\n", arg);
2419 obj = stack_pop_objid(ctx, &id);
2420 if(!obj)
2421 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2423 hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2424 if(SUCCEEDED(hres)) {
2425 VARIANT n;
2427 hres = to_number(ctx->parser->script, &v, ctx->ei, &n);
2428 VariantClear(&v);
2429 if(SUCCEEDED(hres)) {
2430 num_set_val(&v, num_val(&n)+(double)arg);
2431 hres = disp_propput(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2434 IDispatch_Release(obj);
2435 if(FAILED(hres))
2436 return hres;
2438 return stack_push(ctx, &v);
2441 /* ECMA-262 3rd Edition 11.9.3 */
2442 static HRESULT equal_values(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, BOOL *ret)
2444 if(V_VT(lval) == V_VT(rval) || (is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval))))
2445 return equal2_values(lval, rval, ret);
2447 /* FIXME: NULL disps should be handled in more general way */
2448 if(V_VT(lval) == VT_DISPATCH && !V_DISPATCH(lval)) {
2449 VARIANT v;
2450 V_VT(&v) = VT_NULL;
2451 return equal_values(ctx, &v, rval, ei, ret);
2454 if(V_VT(rval) == VT_DISPATCH && !V_DISPATCH(rval)) {
2455 VARIANT v;
2456 V_VT(&v) = VT_NULL;
2457 return equal_values(ctx, lval, &v, ei, ret);
2460 if((V_VT(lval) == VT_NULL && V_VT(rval) == VT_EMPTY) ||
2461 (V_VT(lval) == VT_EMPTY && V_VT(rval) == VT_NULL)) {
2462 *ret = TRUE;
2463 return S_OK;
2466 if(V_VT(lval) == VT_BSTR && is_num_vt(V_VT(rval))) {
2467 VARIANT v;
2468 HRESULT hres;
2470 hres = to_number(ctx, lval, ei, &v);
2471 if(FAILED(hres))
2472 return hres;
2474 return equal_values(ctx, &v, rval, ei, ret);
2477 if(V_VT(rval) == VT_BSTR && is_num_vt(V_VT(lval))) {
2478 VARIANT v;
2479 HRESULT hres;
2481 hres = to_number(ctx, rval, ei, &v);
2482 if(FAILED(hres))
2483 return hres;
2485 return equal_values(ctx, lval, &v, ei, ret);
2488 if(V_VT(rval) == VT_BOOL) {
2489 VARIANT v;
2491 V_VT(&v) = VT_I4;
2492 V_I4(&v) = V_BOOL(rval) ? 1 : 0;
2493 return equal_values(ctx, lval, &v, ei, ret);
2496 if(V_VT(lval) == VT_BOOL) {
2497 VARIANT v;
2499 V_VT(&v) = VT_I4;
2500 V_I4(&v) = V_BOOL(lval) ? 1 : 0;
2501 return equal_values(ctx, &v, rval, ei, ret);
2505 if(V_VT(rval) == VT_DISPATCH && (V_VT(lval) == VT_BSTR || is_num_vt(V_VT(lval)))) {
2506 VARIANT v;
2507 HRESULT hres;
2509 hres = to_primitive(ctx, rval, ei, &v, NO_HINT);
2510 if(FAILED(hres))
2511 return hres;
2513 hres = equal_values(ctx, lval, &v, ei, ret);
2515 VariantClear(&v);
2516 return hres;
2520 if(V_VT(lval) == VT_DISPATCH && (V_VT(rval) == VT_BSTR || is_num_vt(V_VT(rval)))) {
2521 VARIANT v;
2522 HRESULT hres;
2524 hres = to_primitive(ctx, lval, ei, &v, NO_HINT);
2525 if(FAILED(hres))
2526 return hres;
2528 hres = equal_values(ctx, &v, rval, ei, ret);
2530 VariantClear(&v);
2531 return hres;
2535 *ret = FALSE;
2536 return S_OK;
2539 /* ECMA-262 3rd Edition 11.9.1 */
2540 static HRESULT interp_eq(exec_ctx_t *ctx)
2542 VARIANT *l, *r;
2543 BOOL b;
2544 HRESULT hres;
2546 r = stack_pop(ctx);
2547 l = stack_pop(ctx);
2549 TRACE("%s == %s\n", debugstr_variant(l), debugstr_variant(r));
2551 hres = equal_values(ctx->parser->script, l, r, ctx->ei, &b);
2552 VariantClear(l);
2553 VariantClear(r);
2554 if(FAILED(hres))
2555 return hres;
2557 return stack_push_bool(ctx, b);
2560 /* ECMA-262 3rd Edition 11.9.2 */
2561 static HRESULT interp_neq(exec_ctx_t *ctx)
2563 VARIANT *l, *r;
2564 BOOL b;
2565 HRESULT hres;
2567 r = stack_pop(ctx);
2568 l = stack_pop(ctx);
2570 TRACE("%s != %s\n", debugstr_variant(l), debugstr_variant(r));
2572 hres = equal_values(ctx->parser->script, l, r, ctx->ei, &b);
2573 VariantClear(l);
2574 VariantClear(r);
2575 if(FAILED(hres))
2576 return hres;
2578 return stack_push_bool(ctx, !b);
2581 /* ECMA-262 3rd Edition 11.9.4 */
2582 static HRESULT interp_eq2(exec_ctx_t *ctx)
2584 VARIANT *l, *r;
2585 BOOL b;
2586 HRESULT hres;
2588 TRACE("\n");
2590 r = stack_pop(ctx);
2591 l = stack_pop(ctx);
2593 hres = equal2_values(r, l, &b);
2594 VariantClear(l);
2595 VariantClear(r);
2596 if(FAILED(hres))
2597 return hres;
2599 return stack_push_bool(ctx, b);
2602 /* ECMA-262 3rd Edition 11.9.5 */
2603 static HRESULT interp_neq2(exec_ctx_t *ctx)
2605 VARIANT *l, *r;
2606 BOOL b;
2607 HRESULT hres;
2609 TRACE("\n");
2611 r = stack_pop(ctx);
2612 l = stack_pop(ctx);
2614 hres = equal2_values(r, l, &b);
2615 VariantClear(l);
2616 VariantClear(r);
2617 if(FAILED(hres))
2618 return hres;
2620 return stack_push_bool(ctx, !b);
2623 /* ECMA-262 3rd Edition 11.8.5 */
2624 static HRESULT less_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL greater, jsexcept_t *ei, BOOL *ret)
2626 VARIANT l, r, ln, rn;
2627 HRESULT hres;
2629 hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2630 if(FAILED(hres))
2631 return hres;
2633 hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
2634 if(FAILED(hres)) {
2635 VariantClear(&l);
2636 return hres;
2639 if(V_VT(&l) == VT_BSTR && V_VT(&r) == VT_BSTR) {
2640 *ret = (strcmpW(V_BSTR(&l), V_BSTR(&r)) < 0) ^ greater;
2641 SysFreeString(V_BSTR(&l));
2642 SysFreeString(V_BSTR(&r));
2643 return S_OK;
2646 hres = to_number(ctx, &l, ei, &ln);
2647 VariantClear(&l);
2648 if(SUCCEEDED(hres))
2649 hres = to_number(ctx, &r, ei, &rn);
2650 VariantClear(&r);
2651 if(FAILED(hres))
2652 return hres;
2654 if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) {
2655 *ret = (V_I4(&ln) < V_I4(&rn)) ^ greater;
2656 }else {
2657 DOUBLE ld = num_val(&ln);
2658 DOUBLE rd = num_val(&rn);
2660 *ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater);
2663 return S_OK;
2666 /* ECMA-262 3rd Edition 11.8.1 */
2667 static HRESULT interp_lt(exec_ctx_t *ctx)
2669 VARIANT *l, *r;
2670 BOOL b;
2671 HRESULT hres;
2673 r = stack_pop(ctx);
2674 l = stack_pop(ctx);
2676 TRACE("%s < %s\n", debugstr_variant(l), debugstr_variant(r));
2678 hres = less_eval(ctx->parser->script, l, r, FALSE, ctx->ei, &b);
2679 VariantClear(l);
2680 VariantClear(r);
2681 if(FAILED(hres))
2682 return hres;
2684 return stack_push_bool(ctx, b);
2687 /* ECMA-262 3rd Edition 11.8.1 */
2688 static HRESULT interp_lteq(exec_ctx_t *ctx)
2690 VARIANT *l, *r;
2691 BOOL b;
2692 HRESULT hres;
2694 r = stack_pop(ctx);
2695 l = stack_pop(ctx);
2697 TRACE("%s <= %s\n", debugstr_variant(l), debugstr_variant(r));
2699 hres = less_eval(ctx->parser->script, r, l, TRUE, ctx->ei, &b);
2700 VariantClear(l);
2701 VariantClear(r);
2702 if(FAILED(hres))
2703 return hres;
2705 return stack_push_bool(ctx, b);
2708 /* ECMA-262 3rd Edition 11.8.2 */
2709 static HRESULT interp_gt(exec_ctx_t *ctx)
2711 VARIANT *l, *r;
2712 BOOL b;
2713 HRESULT hres;
2715 r = stack_pop(ctx);
2716 l = stack_pop(ctx);
2718 TRACE("%s > %s\n", debugstr_variant(l), debugstr_variant(r));
2720 hres = less_eval(ctx->parser->script, r, l, FALSE, ctx->ei, &b);
2721 VariantClear(l);
2722 VariantClear(r);
2723 if(FAILED(hres))
2724 return hres;
2726 return stack_push_bool(ctx, b);
2729 /* ECMA-262 3rd Edition 11.8.4 */
2730 static HRESULT interp_gteq(exec_ctx_t *ctx)
2732 VARIANT *l, *r;
2733 BOOL b;
2734 HRESULT hres;
2736 r = stack_pop(ctx);
2737 l = stack_pop(ctx);
2739 TRACE("%s >= %s\n", debugstr_variant(l), debugstr_variant(r));
2741 hres = less_eval(ctx->parser->script, l, r, TRUE, ctx->ei, &b);
2742 VariantClear(l);
2743 VariantClear(r);
2744 if(FAILED(hres))
2745 return hres;
2747 return stack_push_bool(ctx, b);
2750 /* ECMA-262 3rd Edition 11.4.8 */
2751 static HRESULT interp_bneg(exec_ctx_t *ctx)
2753 VARIANT *v, r;
2754 INT i;
2755 HRESULT hres;
2757 TRACE("\n");
2759 v = stack_pop(ctx);
2760 hres = to_int32(ctx->parser->script, v, ctx->ei, &i);
2761 VariantClear(v);
2762 if(FAILED(hres))
2763 return hres;
2765 V_VT(&r) = VT_I4;
2766 V_I4(&r) = ~i;
2767 return stack_push(ctx, &r);
2770 /* ECMA-262 3rd Edition 11.4.9 */
2771 static HRESULT interp_neg(exec_ctx_t *ctx)
2773 VARIANT *v;
2774 VARIANT_BOOL b;
2775 HRESULT hres;
2777 TRACE("\n");
2779 v = stack_pop(ctx);
2780 hres = to_boolean(v, &b);
2781 VariantClear(v);
2782 if(FAILED(hres))
2783 return hres;
2785 return stack_push_bool(ctx, !b);
2788 /* ECMA-262 3rd Edition 11.7.1 */
2789 static HRESULT interp_lshift(exec_ctx_t *ctx)
2791 DWORD r;
2792 INT l;
2793 HRESULT hres;
2795 hres = stack_pop_uint(ctx, &r);
2796 if(FAILED(hres))
2797 return hres;
2799 hres = stack_pop_int(ctx, &l);
2800 if(FAILED(hres))
2801 return hres;
2803 return stack_push_int(ctx, l << (r&0x1f));
2806 /* ECMA-262 3rd Edition 11.7.2 */
2807 static HRESULT interp_rshift(exec_ctx_t *ctx)
2809 DWORD r;
2810 INT l;
2811 HRESULT hres;
2813 hres = stack_pop_uint(ctx, &r);
2814 if(FAILED(hres))
2815 return hres;
2817 hres = stack_pop_int(ctx, &l);
2818 if(FAILED(hres))
2819 return hres;
2821 return stack_push_int(ctx, l >> (r&0x1f));
2824 /* ECMA-262 3rd Edition 11.7.3 */
2825 static HRESULT interp_rshift2(exec_ctx_t *ctx)
2827 DWORD r, l;
2828 HRESULT hres;
2830 hres = stack_pop_uint(ctx, &r);
2831 if(FAILED(hres))
2832 return hres;
2834 hres = stack_pop_uint(ctx, &l);
2835 if(FAILED(hres))
2836 return hres;
2838 return stack_push_int(ctx, l >> (r&0x1f));
2841 /* ECMA-262 3rd Edition 11.13.1 */
2842 static HRESULT interp_assign(exec_ctx_t *ctx)
2844 IDispatch *disp;
2845 DISPID id;
2846 VARIANT *v;
2847 HRESULT hres;
2849 TRACE("\n");
2851 v = stack_pop(ctx);
2852 disp = stack_pop_objid(ctx, &id);
2854 if(!disp)
2855 return throw_reference_error(ctx->parser->script, ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
2857 hres = disp_propput(ctx->parser->script, disp, id, v, ctx->ei, NULL/*FIXME*/);
2858 IDispatch_Release(disp);
2859 if(FAILED(hres)) {
2860 VariantClear(v);
2861 return hres;
2864 return stack_push(ctx, v);
2867 static HRESULT interp_undefined(exec_ctx_t *ctx)
2869 VARIANT v;
2871 TRACE("\n");
2873 V_VT(&v) = VT_EMPTY;
2874 return stack_push(ctx, &v);
2877 static HRESULT interp_jmp(exec_ctx_t *ctx)
2879 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
2881 TRACE("\n");
2883 ctx->ip = arg;
2884 return S_OK;
2887 static HRESULT interp_pop(exec_ctx_t *ctx)
2889 TRACE("\n");
2891 stack_popn(ctx, 1);
2892 return S_OK;
2895 static HRESULT interp_ret(exec_ctx_t *ctx)
2897 TRACE("\n");
2899 ctx->ip = -1;
2900 return S_OK;
2903 static HRESULT interp_tree(exec_ctx_t *ctx)
2905 instr_t *instr = ctx->parser->code->instrs+ctx->ip;
2906 VARIANT v;
2907 HRESULT hres;
2909 TRACE("\n");
2911 hres = stat_eval(ctx->parser->script, instr->arg1.stat, ctx->rt, &v);
2912 if(FAILED(hres))
2913 return hres;
2915 return stack_push(ctx, &v);
2918 typedef HRESULT (*op_func_t)(exec_ctx_t*);
2920 static const op_func_t op_funcs[] = {
2921 #define X(x,a,b,c) interp_##x,
2922 OP_LIST
2923 #undef X
2926 static const unsigned op_move[] = {
2927 #define X(a,x,b,c) x,
2928 OP_LIST
2929 #undef X
2932 HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
2934 exec_ctx_t *exec_ctx = ctx->exec_ctx;
2935 unsigned prev_ip, prev_top;
2936 return_type_t *prev_rt;
2937 jsexcept_t *prev_ei;
2938 jsop_t op;
2939 HRESULT hres = S_OK;
2941 TRACE("\n");
2943 if(stat->instr_off == -1) {
2944 hres = compile_subscript_stat(exec_ctx->parser, stat, FALSE, &stat->instr_off);
2945 if(FAILED(hres))
2946 return hres;
2949 prev_rt = exec_ctx->rt;
2950 prev_top = exec_ctx->top;
2951 prev_ip = exec_ctx->ip;
2952 prev_ei = exec_ctx->ei;
2953 exec_ctx->ip = stat->instr_off;
2954 exec_ctx->rt = rt;
2955 exec_ctx->ei = &rt->ei;
2957 while(exec_ctx->ip != -1 && exec_ctx->rt->type == RT_NORMAL) {
2958 op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
2959 hres = op_funcs[op](exec_ctx);
2960 if(FAILED(hres))
2961 break;
2962 exec_ctx->ip += op_move[op];
2965 exec_ctx->rt = prev_rt;
2966 exec_ctx->ip = prev_ip;
2967 exec_ctx->ei = prev_ei;
2969 if(FAILED(hres)) {
2970 stack_popn(exec_ctx, exec_ctx->top-prev_top);
2971 return hres;
2974 assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top);
2976 if(exec_ctx->top == prev_top)
2977 V_VT(ret) = VT_EMPTY;
2978 else
2979 *ret = *stack_pop(exec_ctx);
2980 return S_OK;
2983 static HRESULT expr_eval(script_ctx_t *ctx, expression_t *expr, jsexcept_t *ei, VARIANT *ret)
2985 exec_ctx_t *exec_ctx = ctx->exec_ctx;
2986 unsigned prev_ip, prev_top;
2987 jsexcept_t *prev_ei;
2988 jsop_t op;
2989 HRESULT hres = S_OK;
2991 TRACE("\n");
2993 if(expr->instr_off == -1) {
2994 hres = compile_subscript(ctx->exec_ctx->parser, expr, &expr->instr_off);
2995 if(FAILED(hres))
2996 return hres;
2999 prev_top = exec_ctx->top;
3000 prev_ip = exec_ctx->ip;
3001 prev_ei = exec_ctx->ei;
3002 exec_ctx->ip = expr->instr_off;
3003 exec_ctx->ei = ei;
3005 while(exec_ctx->ip != -1) {
3006 op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
3007 hres = op_funcs[op](exec_ctx);
3008 if(FAILED(hres))
3009 break;
3010 exec_ctx->ip += op_move[op];
3013 exec_ctx->ip = prev_ip;
3014 exec_ctx->ei = prev_ei;
3016 if(FAILED(hres)) {
3017 stack_popn(exec_ctx, exec_ctx->top-prev_top);
3018 return hres;
3021 assert(exec_ctx->top == prev_top+1);
3023 if(exec_ctx->top == prev_top)
3024 V_VT(ret) = VT_EMPTY;
3025 else
3026 *ret = *stack_pop(exec_ctx);
3027 return S_OK;