jscript: Use bytecode for '<=' expression implementation.
[wine/multimedia.git] / dlls / jscript / engine.c
blob76cc0c87bc9ff6d8166a15f4640657048e1e3e24
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 #define EXPR_NOVAL 0x0001
33 #define EXPR_NEWREF 0x0002
35 struct _return_type_t {
36 enum{
37 RT_NORMAL,
38 RT_RETURN,
39 RT_BREAK,
40 RT_CONTINUE
41 } type;
42 jsexcept_t ei;
45 static inline HRESULT stat_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
47 return stat->eval(ctx, stat, rt, ret);
50 static inline HRESULT expr_eval(script_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
52 return expr->eval(ctx, expr, flags, ei, ret);
55 static HRESULT stack_push(exec_ctx_t *ctx, VARIANT *v)
57 if(!ctx->stack_size) {
58 ctx->stack = heap_alloc(16*sizeof(VARIANT));
59 if(!ctx->stack)
60 return E_OUTOFMEMORY;
61 ctx->stack_size = 16;
62 }else if(ctx->stack_size == ctx->top) {
63 VARIANT *new_stack;
65 new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(VARIANT));
66 if(!new_stack) {
67 VariantClear(v);
68 return E_OUTOFMEMORY;
71 ctx->stack = new_stack;
72 ctx->stack_size *= 2;
75 ctx->stack[ctx->top++] = *v;
76 return S_OK;
79 static HRESULT stack_push_bool(exec_ctx_t *ctx, BOOL b)
81 VARIANT v;
83 V_VT(&v) = VT_BOOL;
84 V_BOOL(&v) = b ? VARIANT_TRUE : VARIANT_FALSE;
85 return stack_push(ctx, &v);
88 static inline HRESULT stack_push_number(exec_ctx_t *ctx, double number)
90 VARIANT v;
92 num_set_val(&v, number);
93 return stack_push(ctx, &v);
96 static inline HRESULT stack_push_int(exec_ctx_t *ctx, INT n)
98 VARIANT v;
100 V_VT(&v) = VT_I4;
101 V_I4(&v) = n;
102 return stack_push(ctx, &v);
105 static inline VARIANT *stack_top(exec_ctx_t *ctx)
107 assert(ctx->top);
108 return ctx->stack + ctx->top-1;
111 static inline VARIANT *stack_topn(exec_ctx_t *ctx, unsigned n)
113 assert(ctx->top > n);
114 return ctx->stack + ctx->top-1-n;
117 static inline VARIANT *stack_pop(exec_ctx_t *ctx)
119 assert(ctx->top);
120 return ctx->stack + --ctx->top;
123 static void stack_popn(exec_ctx_t *ctx, unsigned n)
125 while(n--)
126 VariantClear(stack_pop(ctx));
129 static HRESULT stack_pop_number(exec_ctx_t *ctx, VARIANT *r)
131 VARIANT *v;
132 HRESULT hres;
134 v = stack_pop(ctx);
135 hres = to_number(ctx->parser->script, v, &ctx->ei, r);
136 VariantClear(v);
137 return hres;
140 static inline HRESULT stack_pop_int(exec_ctx_t *ctx, INT *r)
142 return to_int32(ctx->parser->script, stack_pop(ctx), &ctx->ei, r);
145 static void exprval_release(exprval_t *val)
147 switch(val->type) {
148 case EXPRVAL_VARIANT:
149 if(V_VT(&val->u.var) != VT_EMPTY)
150 VariantClear(&val->u.var);
151 return;
152 case EXPRVAL_IDREF:
153 if(val->u.idref.disp)
154 IDispatch_Release(val->u.idref.disp);
155 return;
156 case EXPRVAL_INVALID:
157 SysFreeString(val->u.identifier);
161 /* ECMA-262 3rd Edition 8.7.1 */
162 static HRESULT exprval_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
164 V_VT(ret) = VT_EMPTY;
166 switch(val->type) {
167 case EXPRVAL_VARIANT:
168 return VariantCopy(ret, &val->u.var);
169 case EXPRVAL_IDREF:
170 if(!val->u.idref.disp) {
171 FIXME("throw ReferenceError\n");
172 return E_FAIL;
175 return disp_propget(ctx, val->u.idref.disp, val->u.idref.id, ret, ei, NULL/*FIXME*/);
176 case EXPRVAL_INVALID:
177 return throw_type_error(ctx, ei, JS_E_UNDEFINED_VARIABLE, val->u.identifier);
180 ERR("type %d\n", val->type);
181 return E_FAIL;
184 static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
186 if(val->type == EXPRVAL_VARIANT) {
187 *ret = val->u.var;
188 V_VT(&val->u.var) = VT_EMPTY;
189 return S_OK;
192 return exprval_value(ctx, val, ei, ret);
195 static HRESULT exprval_to_boolean(script_ctx_t *ctx, exprval_t *exprval, jsexcept_t *ei, VARIANT_BOOL *b)
197 if(exprval->type != EXPRVAL_VARIANT) {
198 VARIANT val;
199 HRESULT hres;
201 hres = exprval_to_value(ctx, exprval, ei, &val);
202 if(FAILED(hres))
203 return hres;
205 hres = to_boolean(&val, b);
206 VariantClear(&val);
207 return hres;
210 return to_boolean(&exprval->u.var, b);
213 static void exprval_init(exprval_t *val)
215 val->type = EXPRVAL_VARIANT;
216 V_VT(&val->u.var) = VT_EMPTY;
219 static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id)
221 val->type = EXPRVAL_IDREF;
222 val->u.idref.disp = disp;
223 val->u.idref.id = id;
225 if(disp)
226 IDispatch_AddRef(disp);
229 HRESULT scope_push(scope_chain_t *scope, jsdisp_t *obj, scope_chain_t **ret)
231 scope_chain_t *new_scope;
233 new_scope = heap_alloc(sizeof(scope_chain_t));
234 if(!new_scope)
235 return E_OUTOFMEMORY;
237 new_scope->ref = 1;
239 jsdisp_addref(obj);
240 new_scope->obj = obj;
242 if(scope) {
243 scope_addref(scope);
244 new_scope->next = scope;
245 }else {
246 new_scope->next = NULL;
249 *ret = new_scope;
250 return S_OK;
253 static void scope_pop(scope_chain_t **scope)
255 scope_chain_t *tmp;
257 tmp = *scope;
258 *scope = tmp->next;
259 scope_release(tmp);
262 void scope_release(scope_chain_t *scope)
264 if(--scope->ref)
265 return;
267 if(scope->next)
268 scope_release(scope->next);
270 jsdisp_release(scope->obj);
271 heap_free(scope);
274 HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, jsdisp_t *var_disp,
275 scope_chain_t *scope, BOOL is_global, exec_ctx_t **ret)
277 exec_ctx_t *ctx;
279 ctx = heap_alloc_zero(sizeof(exec_ctx_t));
280 if(!ctx)
281 return E_OUTOFMEMORY;
283 ctx->ref = 1;
284 ctx->is_global = is_global;
286 if(this_obj)
287 ctx->this_obj = this_obj;
288 else if(script_ctx->host_global)
289 ctx->this_obj = script_ctx->host_global;
290 else
291 ctx->this_obj = to_disp(script_ctx->global);
292 IDispatch_AddRef(ctx->this_obj);
294 jsdisp_addref(var_disp);
295 ctx->var_disp = var_disp;
297 if(scope) {
298 scope_addref(scope);
299 ctx->scope_chain = scope;
302 *ret = ctx;
303 return S_OK;
306 void exec_release(exec_ctx_t *ctx)
308 if(--ctx->ref)
309 return;
311 if(ctx->scope_chain)
312 scope_release(ctx->scope_chain);
313 if(ctx->var_disp)
314 jsdisp_release(ctx->var_disp);
315 if(ctx->this_obj)
316 IDispatch_Release(ctx->this_obj);
317 heap_free(ctx->stack);
318 heap_free(ctx);
321 static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
323 IDispatchEx *dispex;
324 HRESULT hres;
326 hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
327 if(FAILED(hres)) {
328 TRACE("unsing IDispatch\n");
330 *id = 0;
331 return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
334 *id = 0;
335 hres = IDispatchEx_GetDispID(dispex, name, make_grfdex(ctx, flags|fdexNameCaseSensitive), id);
336 IDispatchEx_Release(dispex);
337 return hres;
340 /* ECMA-262 3rd Edition 8.7.2 */
341 static HRESULT put_value(script_ctx_t *ctx, exprval_t *ref, VARIANT *v, jsexcept_t *ei)
343 if(ref->type != EXPRVAL_IDREF)
344 return throw_reference_error(ctx, ei, JS_E_ILLEGAL_ASSIGN, NULL);
346 return disp_propput(ctx, ref->u.idref.disp, ref->u.idref.id, v, ei, NULL/*FIXME*/);
349 static inline BOOL is_null(const VARIANT *v)
351 return V_VT(v) == VT_NULL || (V_VT(v) == VT_DISPATCH && !V_DISPATCH(v));
354 static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret)
356 IObjectIdentity *identity;
357 IUnknown *unk1, *unk2;
358 HRESULT hres;
360 if(disp1 == disp2) {
361 *ret = TRUE;
362 return S_OK;
365 if(!disp1 || !disp2) {
366 *ret = FALSE;
367 return S_OK;
370 hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1);
371 if(FAILED(hres))
372 return hres;
374 hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2);
375 if(FAILED(hres)) {
376 IUnknown_Release(unk1);
377 return hres;
380 if(unk1 == unk2) {
381 *ret = TRUE;
382 }else {
383 hres = IUnknown_QueryInterface(unk1, &IID_IObjectIdentity, (void**)&identity);
384 if(SUCCEEDED(hres)) {
385 hres = IObjectIdentity_IsEqualObject(identity, unk2);
386 IObjectIdentity_Release(identity);
387 *ret = hres == S_OK;
388 }else {
389 *ret = FALSE;
393 IUnknown_Release(unk1);
394 IUnknown_Release(unk2);
395 return S_OK;
398 /* ECMA-262 3rd Edition 11.9.6 */
399 static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
401 TRACE("\n");
403 if(V_VT(lval) != V_VT(rval)) {
404 if(is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval)))
405 *ret = num_val(lval) == num_val(rval);
406 else if(is_null(lval))
407 *ret = is_null(rval);
408 else
409 *ret = FALSE;
410 return S_OK;
413 switch(V_VT(lval)) {
414 case VT_EMPTY:
415 case VT_NULL:
416 *ret = VARIANT_TRUE;
417 break;
418 case VT_I4:
419 *ret = V_I4(lval) == V_I4(rval);
420 break;
421 case VT_R8:
422 *ret = V_R8(lval) == V_R8(rval);
423 break;
424 case VT_BSTR:
425 if(!V_BSTR(lval))
426 *ret = SysStringLen(V_BSTR(rval))?FALSE:TRUE;
427 else if(!V_BSTR(rval))
428 *ret = SysStringLen(V_BSTR(lval))?FALSE:TRUE;
429 else
430 *ret = !strcmpW(V_BSTR(lval), V_BSTR(rval));
431 break;
432 case VT_DISPATCH:
433 return disp_cmp(V_DISPATCH(lval), V_DISPATCH(rval), ret);
434 case VT_BOOL:
435 *ret = !V_BOOL(lval) == !V_BOOL(rval);
436 break;
437 default:
438 FIXME("unimplemented vt %d\n", V_VT(lval));
439 return E_NOTIMPL;
442 return S_OK;
445 static HRESULT literal_to_var(script_ctx_t *ctx, literal_t *literal, VARIANT *v)
447 switch(literal->type) {
448 case LT_NULL:
449 V_VT(v) = VT_NULL;
450 break;
451 case LT_INT:
452 V_VT(v) = VT_I4;
453 V_I4(v) = literal->u.lval;
454 break;
455 case LT_DOUBLE:
456 V_VT(v) = VT_R8;
457 V_R8(v) = literal->u.dval;
458 break;
459 case LT_STRING: {
460 BSTR str = SysAllocString(literal->u.wstr);
461 if(!str)
462 return E_OUTOFMEMORY;
464 V_VT(v) = VT_BSTR;
465 V_BSTR(v) = str;
466 break;
468 case LT_BOOL:
469 V_VT(v) = VT_BOOL;
470 V_BOOL(v) = literal->u.bval;
471 break;
472 case LT_REGEXP: {
473 jsdisp_t *regexp;
474 HRESULT hres;
476 hres = create_regexp(ctx, literal->u.regexp.str, literal->u.regexp.str_len,
477 literal->u.regexp.flags, &regexp);
478 if(FAILED(hres))
479 return hres;
481 var_set_jsdisp(v, regexp);
485 return S_OK;
488 static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
490 named_item_t *item;
491 DISPID id;
492 HRESULT hres;
494 for(item = ctx->named_items; item; item = item->next) {
495 if(item->flags & SCRIPTITEM_GLOBALMEMBERS) {
496 hres = disp_get_id(ctx, item->disp, identifier, 0, &id);
497 if(SUCCEEDED(hres)) {
498 if(ret)
499 exprval_set_idref(ret, item->disp, id);
500 return TRUE;
505 return FALSE;
508 HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, BOOL from_eval,
509 jsexcept_t *ei, VARIANT *retv)
511 script_ctx_t *script = parser->script;
512 function_declaration_t *func;
513 parser_ctx_t *prev_parser;
514 var_list_t *var;
515 VARIANT val, tmp;
516 statement_t *stat;
517 exec_ctx_t *prev_ctx;
518 return_type_t rt;
519 HRESULT hres = S_OK;
521 for(func = source->functions; func; func = func->next) {
522 jsdisp_t *func_obj;
523 VARIANT var;
525 hres = create_source_function(parser, func->expr->parameter_list, func->expr->source_elements,
526 ctx->scope_chain, func->expr->src_str, func->expr->src_len, &func_obj);
527 if(FAILED(hres))
528 return hres;
530 var_set_jsdisp(&var, func_obj);
531 hres = jsdisp_propput_name(ctx->var_disp, func->expr->identifier, &var, ei, NULL);
532 jsdisp_release(func_obj);
533 if(FAILED(hres))
534 return hres;
537 for(var = source->variables; var; var = var->next) {
538 DISPID id = 0;
539 BSTR name;
541 name = SysAllocString(var->identifier);
542 if(!name)
543 return E_OUTOFMEMORY;
545 if(!ctx->is_global || !lookup_global_members(parser->script, name, NULL))
546 hres = jsdisp_get_id(ctx->var_disp, var->identifier, fdexNameEnsure, &id);
547 SysFreeString(name);
548 if(FAILED(hres))
549 return hres;
552 prev_ctx = script->exec_ctx;
553 script->exec_ctx = ctx;
555 prev_parser = ctx->parser;
556 ctx->parser = parser;
558 V_VT(&val) = VT_EMPTY;
559 memset(&rt, 0, sizeof(rt));
560 rt.type = RT_NORMAL;
562 for(stat = source->statement; stat; stat = stat->next) {
563 hres = stat_eval(script, stat, &rt, &tmp);
564 if(FAILED(hres))
565 break;
567 VariantClear(&val);
568 val = tmp;
569 if(rt.type != RT_NORMAL)
570 break;
573 script->exec_ctx = prev_ctx;
574 ctx->parser = prev_parser;
576 if(rt.type != RT_NORMAL && rt.type != RT_RETURN) {
577 FIXME("wrong rt %d\n", rt.type);
578 hres = E_FAIL;
581 *ei = rt.ei;
582 if(FAILED(hres)) {
583 VariantClear(&val);
584 return hres;
587 if(!retv || (!from_eval && rt.type != RT_RETURN))
588 VariantClear(&val);
589 if(retv)
590 *retv = val;
591 return S_OK;
594 /* ECMA-262 3rd Edition 10.1.4 */
595 static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, DWORD flags, jsexcept_t *ei, exprval_t *ret)
597 scope_chain_t *scope;
598 named_item_t *item;
599 DISPID id = 0;
600 HRESULT hres;
602 TRACE("%s\n", debugstr_w(identifier));
604 for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) {
605 hres = jsdisp_get_id(scope->obj, identifier, 0, &id);
606 if(SUCCEEDED(hres)) {
607 exprval_set_idref(ret, to_disp(scope->obj), id);
608 return S_OK;
612 hres = jsdisp_get_id(ctx->global, identifier, 0, &id);
613 if(SUCCEEDED(hres)) {
614 exprval_set_idref(ret, to_disp(ctx->global), id);
615 return S_OK;
618 for(item = ctx->named_items; item; item = item->next) {
619 if((item->flags & SCRIPTITEM_ISVISIBLE) && !strcmpW(item->name, identifier)) {
620 if(!item->disp) {
621 IUnknown *unk;
623 if(!ctx->site)
624 break;
626 hres = IActiveScriptSite_GetItemInfo(ctx->site, identifier,
627 SCRIPTINFO_IUNKNOWN, &unk, NULL);
628 if(FAILED(hres)) {
629 WARN("GetItemInfo failed: %08x\n", hres);
630 break;
633 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
634 IUnknown_Release(unk);
635 if(FAILED(hres)) {
636 WARN("object does not implement IDispatch\n");
637 break;
641 ret->type = EXPRVAL_VARIANT;
642 V_VT(&ret->u.var) = VT_DISPATCH;
643 V_DISPATCH(&ret->u.var) = item->disp;
644 IDispatch_AddRef(item->disp);
645 return S_OK;
649 if(lookup_global_members(ctx, identifier, ret))
650 return S_OK;
652 if(flags & EXPR_NEWREF) {
653 hres = jsdisp_get_id(ctx->global, identifier, fdexNameEnsure, &id);
654 if(FAILED(hres))
655 return hres;
657 exprval_set_idref(ret, to_disp(ctx->global), id);
658 return S_OK;
661 ret->type = EXPRVAL_INVALID;
662 ret->u.identifier = SysAllocString(identifier);
663 if(!ret->u.identifier)
664 return E_OUTOFMEMORY;
666 return S_OK;
669 /* ECMA-262 3rd Edition 12.1 */
670 HRESULT block_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
672 block_statement_t *stat = (block_statement_t*)_stat;
673 VARIANT val, tmp;
674 statement_t *iter;
675 HRESULT hres = S_OK;
677 TRACE("\n");
679 V_VT(&val) = VT_EMPTY;
680 for(iter = stat->stat_list; iter; iter = iter->next) {
681 hres = stat_eval(ctx, iter, rt, &tmp);
682 if(FAILED(hres))
683 break;
685 VariantClear(&val);
686 val = tmp;
687 if(rt->type != RT_NORMAL)
688 break;
691 if(FAILED(hres)) {
692 VariantClear(&val);
693 return hres;
696 *ret = val;
697 return S_OK;
700 /* ECMA-262 3rd Edition 12.2 */
701 static HRESULT variable_list_eval(script_ctx_t *ctx, variable_declaration_t *var_list, jsexcept_t *ei)
703 variable_declaration_t *iter;
704 HRESULT hres = S_OK;
706 for(iter = var_list; iter; iter = iter->next) {
707 exprval_t exprval;
708 VARIANT val;
710 if(!iter->expr)
711 continue;
713 hres = expr_eval(ctx, iter->expr, 0, ei, &exprval);
714 if(FAILED(hres))
715 break;
717 hres = exprval_to_value(ctx, &exprval, ei, &val);
718 exprval_release(&exprval);
719 if(FAILED(hres))
720 break;
722 hres = jsdisp_propput_name(ctx->exec_ctx->var_disp, iter->identifier, &val, ei, NULL/*FIXME*/);
723 VariantClear(&val);
724 if(FAILED(hres))
725 break;
728 return hres;
731 /* ECMA-262 3rd Edition 12.2 */
732 HRESULT var_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
734 var_statement_t *stat = (var_statement_t*)_stat;
735 HRESULT hres;
737 TRACE("\n");
739 hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
740 if(FAILED(hres))
741 return hres;
743 V_VT(ret) = VT_EMPTY;
744 return S_OK;
747 /* ECMA-262 3rd Edition 12.3 */
748 HRESULT empty_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
750 TRACE("\n");
752 V_VT(ret) = VT_EMPTY;
753 return S_OK;
756 /* ECMA-262 3rd Edition 12.4 */
757 HRESULT expression_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
759 expression_statement_t *stat = (expression_statement_t*)_stat;
760 exprval_t exprval;
761 VARIANT val;
762 HRESULT hres;
764 TRACE("\n");
766 hres = expr_eval(ctx, stat->expr, EXPR_NOVAL, &rt->ei, &exprval);
767 if(FAILED(hres))
768 return hres;
770 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
771 exprval_release(&exprval);
772 if(FAILED(hres))
773 return hres;
775 *ret = val;
776 TRACE("= %s\n", debugstr_variant(ret));
777 return S_OK;
780 /* ECMA-262 3rd Edition 12.5 */
781 HRESULT if_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
783 if_statement_t *stat = (if_statement_t*)_stat;
784 exprval_t exprval;
785 VARIANT_BOOL b;
786 HRESULT hres;
788 TRACE("\n");
790 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
791 if(FAILED(hres))
792 return hres;
794 hres = exprval_to_boolean(ctx, &exprval, &rt->ei, &b);
795 exprval_release(&exprval);
796 if(FAILED(hres))
797 return hres;
799 if(b)
800 hres = stat_eval(ctx, stat->if_stat, rt, ret);
801 else if(stat->else_stat)
802 hres = stat_eval(ctx, stat->else_stat, rt, ret);
803 else
804 V_VT(ret) = VT_EMPTY;
806 return hres;
809 /* ECMA-262 3rd Edition 12.6.2 */
810 HRESULT while_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
812 while_statement_t *stat = (while_statement_t*)_stat;
813 exprval_t exprval;
814 VARIANT val, tmp;
815 VARIANT_BOOL b;
816 BOOL test_expr;
817 HRESULT hres;
819 TRACE("\n");
821 V_VT(&val) = VT_EMPTY;
822 test_expr = !stat->do_while;
824 while(1) {
825 if(test_expr) {
826 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
827 if(FAILED(hres))
828 break;
830 hres = exprval_to_boolean(ctx, &exprval, &rt->ei, &b);
831 exprval_release(&exprval);
832 if(FAILED(hres) || !b)
833 break;
834 }else {
835 test_expr = TRUE;
838 hres = stat_eval(ctx, stat->statement, rt, &tmp);
839 if(FAILED(hres))
840 break;
842 VariantClear(&val);
843 val = tmp;
845 if(rt->type == RT_CONTINUE)
846 rt->type = RT_NORMAL;
847 if(rt->type != RT_NORMAL)
848 break;
851 if(FAILED(hres)) {
852 VariantClear(&val);
853 return hres;
856 if(rt->type == RT_BREAK)
857 rt->type = RT_NORMAL;
859 *ret = val;
860 return S_OK;
863 /* ECMA-262 3rd Edition 12.6.3 */
864 HRESULT for_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
866 for_statement_t *stat = (for_statement_t*)_stat;
867 VARIANT val, tmp, retv;
868 exprval_t exprval;
869 VARIANT_BOOL b;
870 HRESULT hres;
872 TRACE("\n");
874 if(stat->variable_list) {
875 hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
876 if(FAILED(hres))
877 return hres;
878 }else if(stat->begin_expr) {
879 hres = expr_eval(ctx, stat->begin_expr, EXPR_NEWREF, &rt->ei, &exprval);
880 if(FAILED(hres))
881 return hres;
883 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
884 exprval_release(&exprval);
885 if(FAILED(hres))
886 return hres;
888 VariantClear(&val);
891 V_VT(&retv) = VT_EMPTY;
893 while(1) {
894 if(stat->expr) {
895 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
896 if(FAILED(hres))
897 break;
899 hres = exprval_to_boolean(ctx, &exprval, &rt->ei, &b);
900 exprval_release(&exprval);
901 if(FAILED(hres) || !b)
902 break;
905 hres = stat_eval(ctx, stat->statement, rt, &tmp);
906 if(FAILED(hres))
907 break;
909 VariantClear(&retv);
910 retv = tmp;
912 if(rt->type == RT_CONTINUE)
913 rt->type = RT_NORMAL;
914 else if(rt->type != RT_NORMAL)
915 break;
917 if(stat->end_expr) {
918 hres = expr_eval(ctx, stat->end_expr, 0, &rt->ei, &exprval);
919 if(FAILED(hres))
920 break;
922 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
923 exprval_release(&exprval);
924 if(FAILED(hres))
925 break;
927 VariantClear(&val);
931 if(FAILED(hres)) {
932 VariantClear(&retv);
933 return hres;
936 if(rt->type == RT_BREAK)
937 rt->type = RT_NORMAL;
939 *ret = retv;
940 return S_OK;
943 /* ECMA-262 3rd Edition 12.6.4 */
944 HRESULT forin_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
946 forin_statement_t *stat = (forin_statement_t*)_stat;
947 VARIANT val, name, retv, tmp;
948 DISPID id = DISPID_STARTENUM;
949 BSTR str, identifier = NULL;
950 IDispatchEx *in_obj;
951 exprval_t exprval;
952 HRESULT hres;
954 TRACE("\n");
956 if(stat->variable) {
957 hres = variable_list_eval(ctx, stat->variable, &rt->ei);
958 if(FAILED(hres))
959 return hres;
962 hres = expr_eval(ctx, stat->in_expr, EXPR_NEWREF, &rt->ei, &exprval);
963 if(FAILED(hres))
964 return hres;
966 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
967 exprval_release(&exprval);
968 if(FAILED(hres))
969 return hres;
971 if(V_VT(&val) != VT_DISPATCH) {
972 TRACE("in vt %d\n", V_VT(&val));
973 VariantClear(&val);
974 V_VT(ret) = VT_EMPTY;
975 return S_OK;
978 hres = IDispatch_QueryInterface(V_DISPATCH(&val), &IID_IDispatchEx, (void**)&in_obj);
979 IDispatch_Release(V_DISPATCH(&val));
980 if(FAILED(hres)) {
981 TRACE("Object doesn't support IDispatchEx\n");
982 V_VT(ret) = VT_EMPTY;
983 return S_OK;
986 V_VT(&retv) = VT_EMPTY;
988 if(stat->variable)
989 identifier = SysAllocString(stat->variable->identifier);
991 while(1) {
992 hres = IDispatchEx_GetNextDispID(in_obj, fdexEnumDefault, id, &id);
993 if(FAILED(hres) || hres == S_FALSE)
994 break;
996 hres = IDispatchEx_GetMemberName(in_obj, id, &str);
997 if(FAILED(hres))
998 break;
1000 TRACE("iter %s\n", debugstr_w(str));
1002 if(stat->variable)
1003 hres = identifier_eval(ctx, identifier, 0, NULL, &exprval);
1004 else
1005 hres = expr_eval(ctx, stat->expr, EXPR_NEWREF, &rt->ei, &exprval);
1006 if(SUCCEEDED(hres)) {
1007 V_VT(&name) = VT_BSTR;
1008 V_BSTR(&name) = str;
1009 hres = put_value(ctx, &exprval, &name, &rt->ei);
1010 exprval_release(&exprval);
1012 SysFreeString(str);
1013 if(FAILED(hres))
1014 break;
1016 hres = stat_eval(ctx, stat->statement, rt, &tmp);
1017 if(FAILED(hres))
1018 break;
1020 VariantClear(&retv);
1021 retv = tmp;
1023 if(rt->type == RT_CONTINUE)
1024 rt->type = RT_NORMAL;
1025 else if(rt->type != RT_NORMAL)
1026 break;
1029 SysFreeString(identifier);
1030 IDispatchEx_Release(in_obj);
1031 if(FAILED(hres)) {
1032 VariantClear(&retv);
1033 return hres;
1036 if(rt->type == RT_BREAK)
1037 rt->type = RT_NORMAL;
1039 *ret = retv;
1040 return S_OK;
1043 /* ECMA-262 3rd Edition 12.7 */
1044 HRESULT continue_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1046 branch_statement_t *stat = (branch_statement_t*)_stat;
1048 TRACE("\n");
1050 if(stat->identifier) {
1051 FIXME("indentifier not implemented\n");
1052 return E_NOTIMPL;
1055 rt->type = RT_CONTINUE;
1056 V_VT(ret) = VT_EMPTY;
1057 return S_OK;
1060 /* ECMA-262 3rd Edition 12.8 */
1061 HRESULT break_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1063 branch_statement_t *stat = (branch_statement_t*)_stat;
1065 TRACE("\n");
1067 if(stat->identifier) {
1068 FIXME("indentifier not implemented\n");
1069 return E_NOTIMPL;
1072 rt->type = RT_BREAK;
1073 V_VT(ret) = VT_EMPTY;
1074 return S_OK;
1077 /* ECMA-262 3rd Edition 12.9 */
1078 HRESULT return_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1080 expression_statement_t *stat = (expression_statement_t*)_stat;
1081 HRESULT hres;
1083 TRACE("\n");
1085 if(stat->expr) {
1086 exprval_t exprval;
1088 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
1089 if(FAILED(hres))
1090 return hres;
1092 hres = exprval_to_value(ctx, &exprval, &rt->ei, ret);
1093 exprval_release(&exprval);
1094 if(FAILED(hres))
1095 return hres;
1096 }else {
1097 V_VT(ret) = VT_EMPTY;
1100 TRACE("= %s\n", debugstr_variant(ret));
1101 rt->type = RT_RETURN;
1102 return S_OK;
1105 /* ECMA-262 3rd Edition 12.10 */
1106 HRESULT with_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1108 with_statement_t *stat = (with_statement_t*)_stat;
1109 exprval_t exprval;
1110 IDispatch *disp;
1111 jsdisp_t *obj;
1112 VARIANT val;
1113 HRESULT hres;
1115 TRACE("\n");
1117 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
1118 if(FAILED(hres))
1119 return hres;
1121 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
1122 exprval_release(&exprval);
1123 if(FAILED(hres))
1124 return hres;
1126 hres = to_object(ctx, &val, &disp);
1127 VariantClear(&val);
1128 if(FAILED(hres))
1129 return hres;
1131 obj = iface_to_jsdisp((IUnknown*)disp);
1132 IDispatch_Release(disp);
1133 if(!obj) {
1134 FIXME("disp id not jsdisp\n");
1135 return E_NOTIMPL;
1138 hres = scope_push(ctx->exec_ctx->scope_chain, obj, &ctx->exec_ctx->scope_chain);
1139 jsdisp_release(obj);
1140 if(FAILED(hres))
1141 return hres;
1143 hres = stat_eval(ctx, stat->statement, rt, ret);
1145 scope_pop(&ctx->exec_ctx->scope_chain);
1146 return hres;
1149 /* ECMA-262 3rd Edition 12.12 */
1150 HRESULT labelled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
1152 FIXME("\n");
1153 return E_NOTIMPL;
1156 /* ECMA-262 3rd Edition 12.13 */
1157 HRESULT switch_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1159 switch_statement_t *stat = (switch_statement_t*)_stat;
1160 case_clausule_t *iter, *default_clausule = NULL;
1161 statement_t *stat_iter;
1162 VARIANT val, cval;
1163 exprval_t exprval;
1164 BOOL b;
1165 HRESULT hres;
1167 TRACE("\n");
1169 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
1170 if(FAILED(hres))
1171 return hres;
1173 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
1174 exprval_release(&exprval);
1175 if(FAILED(hres))
1176 return hres;
1178 for(iter = stat->case_list; iter; iter = iter->next) {
1179 if(!iter->expr) {
1180 default_clausule = iter;
1181 continue;
1184 hres = expr_eval(ctx, iter->expr, 0, &rt->ei, &exprval);
1185 if(FAILED(hres))
1186 break;
1188 hres = exprval_to_value(ctx, &exprval, &rt->ei, &cval);
1189 exprval_release(&exprval);
1190 if(FAILED(hres))
1191 break;
1193 hres = equal2_values(&val, &cval, &b);
1194 VariantClear(&cval);
1195 if(FAILED(hres) || b)
1196 break;
1199 VariantClear(&val);
1200 if(FAILED(hres))
1201 return hres;
1203 if(!iter)
1204 iter = default_clausule;
1206 V_VT(&val) = VT_EMPTY;
1207 if(iter) {
1208 VARIANT tmp;
1210 for(stat_iter = iter->stat; stat_iter; stat_iter = stat_iter->next) {
1211 hres = stat_eval(ctx, stat_iter, rt, &tmp);
1212 if(FAILED(hres))
1213 break;
1215 VariantClear(&val);
1216 val = tmp;
1218 if(rt->type != RT_NORMAL)
1219 break;
1223 if(FAILED(hres)) {
1224 VariantClear(&val);
1225 return hres;
1228 if(rt->type == RT_BREAK)
1229 rt->type = RT_NORMAL;
1231 *ret = val;
1232 return S_OK;
1235 /* ECMA-262 3rd Edition 12.13 */
1236 HRESULT throw_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1238 expression_statement_t *stat = (expression_statement_t*)_stat;
1239 exprval_t exprval;
1240 VARIANT val;
1241 HRESULT hres;
1243 TRACE("\n");
1245 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
1246 if(FAILED(hres))
1247 return hres;
1249 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
1250 exprval_release(&exprval);
1251 if(FAILED(hres))
1252 return hres;
1254 rt->ei.var = val;
1255 return DISP_E_EXCEPTION;
1258 /* ECMA-262 3rd Edition 12.14 */
1259 static HRESULT catch_eval(script_ctx_t *ctx, catch_block_t *block, return_type_t *rt, VARIANT *ret)
1261 jsdisp_t *var_disp;
1262 VARIANT ex, val;
1263 HRESULT hres;
1265 ex = rt->ei.var;
1266 memset(&rt->ei, 0, sizeof(jsexcept_t));
1268 hres = create_dispex(ctx, NULL, NULL, &var_disp);
1269 if(SUCCEEDED(hres)) {
1270 hres = jsdisp_propput_name(var_disp, block->identifier, &ex, &rt->ei, NULL/*FIXME*/);
1271 if(SUCCEEDED(hres)) {
1272 hres = scope_push(ctx->exec_ctx->scope_chain, var_disp, &ctx->exec_ctx->scope_chain);
1273 if(SUCCEEDED(hres)) {
1274 hres = stat_eval(ctx, block->statement, rt, &val);
1275 scope_pop(&ctx->exec_ctx->scope_chain);
1279 jsdisp_release(var_disp);
1282 VariantClear(&ex);
1283 if(FAILED(hres))
1284 return hres;
1286 *ret = val;
1287 return S_OK;
1290 /* ECMA-262 3rd Edition 12.14 */
1291 HRESULT try_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1293 try_statement_t *stat = (try_statement_t*)_stat;
1294 VARIANT val;
1295 HRESULT hres;
1297 TRACE("\n");
1299 hres = stat_eval(ctx, stat->try_statement, rt, &val);
1300 if(FAILED(hres)) {
1301 TRACE("EXCEPTION\n");
1302 if(!stat->catch_block)
1303 return hres;
1305 hres = catch_eval(ctx, stat->catch_block, rt, &val);
1306 if(FAILED(hres))
1307 return hres;
1310 if(stat->finally_statement) {
1311 VariantClear(&val);
1312 hres = stat_eval(ctx, stat->finally_statement, rt, &val);
1313 if(FAILED(hres))
1314 return hres;
1317 *ret = val;
1318 return S_OK;
1321 static HRESULT return_bool(exprval_t *ret, DWORD b)
1323 ret->type = EXPRVAL_VARIANT;
1324 V_VT(&ret->u.var) = VT_BOOL;
1325 V_BOOL(&ret->u.var) = b ? VARIANT_TRUE : VARIANT_FALSE;
1327 return S_OK;
1330 static HRESULT get_binary_expr_values(script_ctx_t *ctx, binary_expression_t *expr, jsexcept_t *ei, VARIANT *lval, VARIANT *rval)
1332 exprval_t exprval;
1333 HRESULT hres;
1335 hres = expr_eval(ctx, expr->expression1, 0, ei, &exprval);
1336 if(FAILED(hres))
1337 return hres;
1339 hres = exprval_to_value(ctx, &exprval, ei, lval);
1340 exprval_release(&exprval);
1341 if(FAILED(hres))
1342 return hres;
1344 hres = expr_eval(ctx, expr->expression2, 0, ei, &exprval);
1345 if(SUCCEEDED(hres)) {
1346 hres = exprval_to_value(ctx, &exprval, ei, rval);
1347 exprval_release(&exprval);
1350 if(FAILED(hres)) {
1351 VariantClear(lval);
1352 return hres;
1355 return S_OK;
1358 typedef HRESULT (*oper_t)(script_ctx_t*,VARIANT*,VARIANT*,jsexcept_t*,VARIANT*);
1360 static HRESULT binary_expr_eval(script_ctx_t *ctx, binary_expression_t *expr, oper_t oper, jsexcept_t *ei,
1361 exprval_t *ret)
1363 VARIANT lval, rval, retv;
1364 HRESULT hres;
1366 hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval);
1367 if(FAILED(hres))
1368 return hres;
1370 hres = oper(ctx, &lval, &rval, ei, &retv);
1371 VariantClear(&lval);
1372 VariantClear(&rval);
1373 if(FAILED(hres))
1374 return hres;
1376 ret->type = EXPRVAL_VARIANT;
1377 ret->u.var = retv;
1378 return S_OK;
1381 /* ECMA-262 3rd Edition 11.13.2 */
1382 static HRESULT assign_oper_eval(script_ctx_t *ctx, expression_t *lexpr, expression_t *rexpr, oper_t oper,
1383 jsexcept_t *ei, exprval_t *ret)
1385 VARIANT retv, lval, rval;
1386 exprval_t exprval, exprvalr;
1387 HRESULT hres;
1389 hres = expr_eval(ctx, lexpr, EXPR_NEWREF, ei, &exprval);
1390 if(FAILED(hres))
1391 return hres;
1393 hres = exprval_value(ctx, &exprval, ei, &lval);
1394 if(SUCCEEDED(hres)) {
1395 hres = expr_eval(ctx, rexpr, 0, ei, &exprvalr);
1396 if(SUCCEEDED(hres)) {
1397 hres = exprval_value(ctx, &exprvalr, ei, &rval);
1398 exprval_release(&exprvalr);
1400 if(SUCCEEDED(hres)) {
1401 hres = oper(ctx, &lval, &rval, ei, &retv);
1402 VariantClear(&rval);
1404 VariantClear(&lval);
1407 if(SUCCEEDED(hres)) {
1408 hres = put_value(ctx, &exprval, &retv, ei);
1409 if(FAILED(hres))
1410 VariantClear(&retv);
1412 exprval_release(&exprval);
1414 if(FAILED(hres))
1415 return hres;
1417 ret->type = EXPRVAL_VARIANT;
1418 ret->u.var = retv;
1419 return S_OK;
1422 /* ECMA-262 3rd Edition 13 */
1423 HRESULT function_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1425 function_expression_t *expr = (function_expression_t*)_expr;
1426 VARIANT var;
1427 HRESULT hres;
1429 TRACE("\n");
1431 if(expr->identifier) {
1432 hres = jsdisp_propget_name(ctx->exec_ctx->var_disp, expr->identifier, &var, ei, NULL/*FIXME*/);
1433 if(FAILED(hres))
1434 return hres;
1435 }else {
1436 jsdisp_t *dispex;
1438 hres = create_source_function(ctx->exec_ctx->parser, expr->parameter_list, expr->source_elements, ctx->exec_ctx->scope_chain,
1439 expr->src_str, expr->src_len, &dispex);
1440 if(FAILED(hres))
1441 return hres;
1443 var_set_jsdisp(&var, dispex);
1446 ret->type = EXPRVAL_VARIANT;
1447 ret->u.var = var;
1448 return S_OK;
1451 /* ECMA-262 3rd Edition 11.2.1 */
1452 HRESULT array_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1454 array_expression_t *expr = (array_expression_t*)_expr;
1455 exprval_t exprval;
1456 VARIANT member, val;
1457 DISPID id;
1458 BSTR str;
1459 IDispatch *obj = NULL;
1460 HRESULT hres;
1462 TRACE("\n");
1464 hres = expr_eval(ctx, expr->member_expr, 0, ei, &exprval);
1465 if(FAILED(hres))
1466 return hres;
1468 hres = exprval_to_value(ctx, &exprval, ei, &member);
1469 exprval_release(&exprval);
1470 if(FAILED(hres))
1471 return hres;
1473 hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
1474 if(SUCCEEDED(hres)) {
1475 hres = exprval_to_value(ctx, &exprval, ei, &val);
1476 exprval_release(&exprval);
1479 if(SUCCEEDED(hres)) {
1480 hres = to_object(ctx, &member, &obj);
1481 if(FAILED(hres))
1482 VariantClear(&val);
1484 VariantClear(&member);
1485 if(SUCCEEDED(hres)) {
1486 hres = to_string(ctx, &val, ei, &str);
1487 VariantClear(&val);
1488 if(SUCCEEDED(hres)) {
1489 hres = disp_get_id(ctx, obj, str, flags & EXPR_NEWREF ? fdexNameEnsure : 0, &id);
1490 SysFreeString(str);
1493 if(SUCCEEDED(hres)) {
1494 exprval_set_idref(ret, obj, id);
1495 }else if(!(flags & EXPR_NEWREF) && hres == DISP_E_UNKNOWNNAME) {
1496 exprval_init(ret);
1497 hres = S_OK;
1500 IDispatch_Release(obj);
1503 return hres;
1506 /* ECMA-262 3rd Edition 11.2.1 */
1507 HRESULT member_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1509 member_expression_t *expr = (member_expression_t*)_expr;
1510 IDispatch *obj = NULL;
1511 exprval_t exprval;
1512 VARIANT member;
1513 DISPID id;
1514 BSTR str;
1515 HRESULT hres;
1517 TRACE("\n");
1519 hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
1520 if(FAILED(hres))
1521 return hres;
1523 hres = exprval_to_value(ctx, &exprval, ei, &member);
1524 exprval_release(&exprval);
1525 if(FAILED(hres))
1526 return hres;
1528 hres = to_object(ctx, &member, &obj);
1529 VariantClear(&member);
1530 if(FAILED(hres))
1531 return hres;
1533 str = SysAllocString(expr->identifier);
1534 if(!str) {
1535 IDispatch_Release(obj);
1536 return E_OUTOFMEMORY;
1539 hres = disp_get_id(ctx, obj, str, flags & EXPR_NEWREF ? fdexNameEnsure : 0, &id);
1540 SysFreeString(str);
1541 if(SUCCEEDED(hres)) {
1542 exprval_set_idref(ret, obj, id);
1543 }else if(!(flags & EXPR_NEWREF) && hres == DISP_E_UNKNOWNNAME) {
1544 exprval_init(ret);
1545 hres = S_OK;
1548 IDispatch_Release(obj);
1549 return hres;
1552 static void free_dp(DISPPARAMS *dp)
1554 DWORD i;
1556 for(i=0; i < dp->cArgs; i++)
1557 VariantClear(dp->rgvarg+i);
1558 heap_free(dp->rgvarg);
1561 static HRESULT args_to_param(script_ctx_t *ctx, argument_t *args, jsexcept_t *ei, DISPPARAMS *dp)
1563 VARIANTARG *vargs;
1564 exprval_t exprval;
1565 argument_t *iter;
1566 DWORD cnt = 0, i;
1567 HRESULT hres = S_OK;
1569 memset(dp, 0, sizeof(*dp));
1570 if(!args)
1571 return S_OK;
1573 for(iter = args; iter; iter = iter->next)
1574 cnt++;
1576 vargs = heap_alloc_zero(cnt * sizeof(*vargs));
1577 if(!vargs)
1578 return E_OUTOFMEMORY;
1580 for(i = cnt, iter = args; iter; iter = iter->next) {
1581 hres = expr_eval(ctx, iter->expr, 0, ei, &exprval);
1582 if(FAILED(hres))
1583 break;
1585 hres = exprval_to_value(ctx, &exprval, ei, vargs + (--i));
1586 exprval_release(&exprval);
1587 if(FAILED(hres))
1588 break;
1591 if(FAILED(hres)) {
1592 free_dp(dp);
1593 return hres;
1596 dp->rgvarg = vargs;
1597 dp->cArgs = cnt;
1598 return S_OK;
1601 static void jsstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, DISPPARAMS *dp)
1603 VARIANT tmp;
1604 unsigned i;
1606 dp->cArgs = arg_cnt;
1607 dp->rgdispidNamedArgs = NULL;
1608 dp->cNamedArgs = 0;
1610 assert(ctx->top >= arg_cnt);
1612 for(i=1; i*2 <= arg_cnt; i++) {
1613 tmp = ctx->stack[ctx->top-i];
1614 ctx->stack[ctx->top-i] = ctx->stack[ctx->top-arg_cnt+i-1];
1615 ctx->stack[ctx->top-arg_cnt+i-1] = tmp;
1618 dp->rgvarg = ctx->stack + ctx->top-arg_cnt;
1621 /* ECMA-262 3rd Edition 11.2.2 */
1622 static HRESULT interp_new(exec_ctx_t *ctx)
1624 const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1625 VARIANT *constr, v;
1626 DISPPARAMS dp;
1627 HRESULT hres;
1629 TRACE("%d\n", arg);
1631 constr = stack_topn(ctx, arg);
1633 /* NOTE: Should use to_object here */
1635 if(V_VT(constr) == VT_NULL)
1636 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1637 else if(V_VT(constr) != VT_DISPATCH)
1638 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_INVALID_ACTION, NULL);
1639 else if(!V_DISPATCH(constr))
1640 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1642 jsstack_to_dp(ctx, arg, &dp);
1643 hres = disp_call(ctx->parser->script, V_DISPATCH(constr), DISPID_VALUE,
1644 DISPATCH_CONSTRUCT, &dp, &v, &ctx->ei, NULL/*FIXME*/);
1645 if(FAILED(hres))
1646 return hres;
1648 stack_popn(ctx, arg+1);
1649 return stack_push(ctx, &v);
1652 /* ECMA-262 3rd Edition 11.2.3 */
1653 HRESULT call_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1655 call_expression_t *expr = (call_expression_t*)_expr;
1656 VARIANT var;
1657 exprval_t exprval;
1658 DISPPARAMS dp;
1659 HRESULT hres;
1661 TRACE("\n");
1663 hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
1664 if(FAILED(hres))
1665 return hres;
1667 hres = args_to_param(ctx, expr->argument_list, ei, &dp);
1668 if(SUCCEEDED(hres)) {
1669 switch(exprval.type) {
1670 case EXPRVAL_VARIANT:
1671 if(V_VT(&exprval.u.var) == VT_DISPATCH)
1672 hres = disp_call(ctx, V_DISPATCH(&exprval.u.var), DISPID_VALUE,
1673 DISPATCH_METHOD, &dp, flags & EXPR_NOVAL ? NULL : &var, ei, NULL/*FIXME*/);
1674 else
1675 hres = throw_type_error(ctx, ei, JS_E_INVALID_PROPERTY, NULL);
1676 break;
1677 case EXPRVAL_IDREF:
1678 hres = disp_call(ctx, exprval.u.idref.disp, exprval.u.idref.id,
1679 DISPATCH_METHOD, &dp, flags & EXPR_NOVAL ? NULL : &var, ei, NULL/*FIXME*/);
1680 break;
1681 case EXPRVAL_INVALID:
1682 hres = throw_type_error(ctx, ei, JS_E_OBJECT_EXPECTED, NULL);
1683 break;
1684 default:
1685 FIXME("unimplemented type %d\n", exprval.type);
1686 hres = E_NOTIMPL;
1689 free_dp(&dp);
1692 exprval_release(&exprval);
1693 if(FAILED(hres))
1694 return hres;
1696 ret->type = EXPRVAL_VARIANT;
1697 if(flags & EXPR_NOVAL) {
1698 V_VT(&ret->u.var) = VT_EMPTY;
1699 }else {
1700 TRACE("= %s\n", debugstr_variant(&var));
1701 ret->u.var = var;
1703 return S_OK;
1706 /* ECMA-262 3rd Edition 11.1.1 */
1707 static HRESULT interp_this(exec_ctx_t *ctx)
1709 VARIANT v;
1711 TRACE("\n");
1713 V_VT(&v) = VT_DISPATCH;
1714 V_DISPATCH(&v) = ctx->this_obj;
1715 IDispatch_AddRef(ctx->this_obj);
1716 return stack_push(ctx, &v);
1719 /* ECMA-262 3rd Edition 10.1.4 */
1720 HRESULT identifier_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1722 identifier_expression_t *expr = (identifier_expression_t*)_expr;
1723 BSTR identifier;
1724 HRESULT hres;
1726 TRACE("\n");
1728 identifier = SysAllocString(expr->identifier);
1729 if(!identifier)
1730 return E_OUTOFMEMORY;
1732 hres = identifier_eval(ctx, identifier, flags, ei, ret);
1734 SysFreeString(identifier);
1735 return hres;
1738 /* ECMA-262 3rd Edition 10.1.4 */
1739 static HRESULT interp_ident(exec_ctx_t *ctx)
1741 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1742 exprval_t exprval;
1743 VARIANT v;
1744 HRESULT hres;
1746 TRACE("%s\n", debugstr_w(arg));
1748 hres = identifier_eval(ctx->parser->script, arg, 0, &ctx->ei, &exprval);
1749 if(FAILED(hres))
1750 return hres;
1752 hres = exprval_to_value(ctx->parser->script, &exprval, &ctx->ei, &v);
1753 exprval_release(&exprval);
1754 if(FAILED(hres))
1755 return hres;
1757 return stack_push(ctx, &v);
1760 /* ECMA-262 3rd Edition 7.8.1 */
1761 static HRESULT interp_null(exec_ctx_t *ctx)
1763 VARIANT v;
1765 TRACE("\n");
1767 V_VT(&v) = VT_NULL;
1768 return stack_push(ctx, &v);
1771 /* ECMA-262 3rd Edition 7.8.2 */
1772 static HRESULT interp_bool(exec_ctx_t *ctx)
1774 const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1776 TRACE("%s\n", arg ? "true" : "false");
1778 return stack_push_bool(ctx, arg);
1781 /* ECMA-262 3rd Edition 7.8.3 */
1782 static HRESULT interp_int(exec_ctx_t *ctx)
1784 const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1785 VARIANT v;
1787 TRACE("%d\n", arg);
1789 V_VT(&v) = VT_I4;
1790 V_I4(&v) = arg;
1791 return stack_push(ctx, &v);
1794 /* ECMA-262 3rd Edition 7.8.3 */
1795 static HRESULT interp_double(exec_ctx_t *ctx)
1797 const double arg = *ctx->parser->code->instrs[ctx->ip].arg1.dbl;
1798 VARIANT v;
1800 TRACE("%lf\n", arg);
1802 V_VT(&v) = VT_R8;
1803 V_R8(&v) = arg;
1804 return stack_push(ctx, &v);
1807 /* ECMA-262 3rd Edition 7.8.4 */
1808 static HRESULT interp_str(exec_ctx_t *ctx)
1810 const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg1.str;
1811 VARIANT v;
1813 TRACE("%s\n", debugstr_w(str));
1815 V_VT(&v) = VT_BSTR;
1816 V_BSTR(&v) = SysAllocString(str);
1817 if(!V_BSTR(&v))
1818 return E_OUTOFMEMORY;
1820 return stack_push(ctx, &v);
1823 /* ECMA-262 3rd Edition 7.8 */
1824 static HRESULT interp_regexp(exec_ctx_t *ctx)
1826 const WCHAR *source = ctx->parser->code->instrs[ctx->ip].arg1.str;
1827 const LONG flags = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1828 jsdisp_t *regexp;
1829 VARIANT v;
1830 HRESULT hres;
1832 TRACE("%s %x\n", debugstr_w(source), flags);
1834 hres = create_regexp(ctx->parser->script, source, strlenW(source), flags, &regexp);
1835 if(FAILED(hres))
1836 return hres;
1838 var_set_jsdisp(&v, regexp);
1839 return stack_push(ctx, &v);
1842 /* ECMA-262 3rd Edition 11.1.4 */
1843 HRESULT array_literal_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1845 array_literal_expression_t *expr = (array_literal_expression_t*)_expr;
1846 DWORD length = 0, i = 0;
1847 array_element_t *elem;
1848 jsdisp_t *array;
1849 exprval_t exprval;
1850 VARIANT val;
1851 HRESULT hres;
1853 TRACE("\n");
1855 for(elem = expr->element_list; elem; elem = elem->next)
1856 length += elem->elision+1;
1857 length += expr->length;
1859 hres = create_array(ctx, length, &array);
1860 if(FAILED(hres))
1861 return hres;
1863 for(elem = expr->element_list; elem; elem = elem->next) {
1864 i += elem->elision;
1866 hres = expr_eval(ctx, elem->expr, 0, ei, &exprval);
1867 if(FAILED(hres))
1868 break;
1870 hres = exprval_to_value(ctx, &exprval, ei, &val);
1871 exprval_release(&exprval);
1872 if(FAILED(hres))
1873 break;
1875 hres = jsdisp_propput_idx(array, i, &val, ei, NULL/*FIXME*/);
1876 VariantClear(&val);
1877 if(FAILED(hres))
1878 break;
1880 i++;
1883 if(FAILED(hres)) {
1884 jsdisp_release(array);
1885 return hres;
1888 ret->type = EXPRVAL_VARIANT;
1889 var_set_jsdisp(&ret->u.var, array);
1890 return S_OK;
1893 /* ECMA-262 3rd Edition 11.1.5 */
1894 HRESULT property_value_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1896 property_value_expression_t *expr = (property_value_expression_t*)_expr;
1897 VARIANT val, tmp;
1898 jsdisp_t *obj;
1899 prop_val_t *iter;
1900 exprval_t exprval;
1901 BSTR name;
1902 HRESULT hres;
1904 TRACE("\n");
1906 hres = create_object(ctx, NULL, &obj);
1907 if(FAILED(hres))
1908 return hres;
1910 for(iter = expr->property_list; iter; iter = iter->next) {
1911 hres = literal_to_var(ctx, iter->name, &tmp);
1912 if(FAILED(hres))
1913 break;
1915 hres = to_string(ctx, &tmp, ei, &name);
1916 VariantClear(&tmp);
1917 if(FAILED(hres))
1918 break;
1920 hres = expr_eval(ctx, iter->value, 0, ei, &exprval);
1921 if(SUCCEEDED(hres)) {
1922 hres = exprval_to_value(ctx, &exprval, ei, &val);
1923 exprval_release(&exprval);
1924 if(SUCCEEDED(hres)) {
1925 hres = jsdisp_propput_name(obj, name, &val, ei, NULL/*FIXME*/);
1926 VariantClear(&val);
1930 SysFreeString(name);
1931 if(FAILED(hres))
1932 break;
1935 if(FAILED(hres)) {
1936 jsdisp_release(obj);
1937 return hres;
1940 ret->type = EXPRVAL_VARIANT;
1941 var_set_jsdisp(&ret->u.var, obj);
1942 return S_OK;
1945 /* ECMA-262 3rd Edition 11.11 */
1946 static HRESULT interp_jmp_nz(exec_ctx_t *ctx)
1948 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1949 VARIANT_BOOL b;
1950 HRESULT hres;
1952 TRACE("\n");
1954 hres = to_boolean(stack_top(ctx), &b);
1955 if(FAILED(hres))
1956 return hres;
1958 if(b) {
1959 ctx->ip = arg;
1960 }else {
1961 stack_popn(ctx, 1);
1962 ctx->ip++;
1964 return S_OK;
1967 /* ECMA-262 3rd Edition 11.11 */
1968 static HRESULT interp_jmp_z(exec_ctx_t *ctx)
1970 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1971 VARIANT_BOOL b;
1972 HRESULT hres;
1974 TRACE("\n");
1976 hres = to_boolean(stack_top(ctx), &b);
1977 if(FAILED(hres))
1978 return hres;
1980 if(b) {
1981 stack_popn(ctx, 1);
1982 ctx->ip++;
1983 }else {
1984 ctx->ip = arg;
1986 return S_OK;
1989 /* ECMA-262 3rd Edition 11.10 */
1990 static HRESULT bitor_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
1992 INT li, ri;
1993 HRESULT hres;
1995 hres = to_int32(ctx, lval, ei, &li);
1996 if(FAILED(hres))
1997 return hres;
1999 hres = to_int32(ctx, rval, ei, &ri);
2000 if(FAILED(hres))
2001 return hres;
2003 V_VT(retv) = VT_I4;
2004 V_I4(retv) = li|ri;
2005 return S_OK;
2008 /* ECMA-262 3rd Edition 11.10 */
2009 static HRESULT interp_or(exec_ctx_t *ctx)
2011 INT l, r;
2012 HRESULT hres;
2014 TRACE("\n");
2016 hres = stack_pop_int(ctx, &r);
2017 if(FAILED(hres))
2018 return hres;
2020 hres = stack_pop_int(ctx, &l);
2021 if(FAILED(hres))
2022 return hres;
2024 return stack_push_int(ctx, l|r);
2027 /* ECMA-262 3rd Edition 11.10 */
2028 static HRESULT xor_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
2030 INT li, ri;
2031 HRESULT hres;
2033 hres = to_int32(ctx, lval, ei, &li);
2034 if(FAILED(hres))
2035 return hres;
2037 hres = to_int32(ctx, rval, ei, &ri);
2038 if(FAILED(hres))
2039 return hres;
2041 V_VT(retv) = VT_I4;
2042 V_I4(retv) = li^ri;
2043 return S_OK;
2046 /* ECMA-262 3rd Edition 11.10 */
2047 static HRESULT interp_xor(exec_ctx_t *ctx)
2049 INT l, r;
2050 HRESULT hres;
2052 TRACE("\n");
2054 hres = stack_pop_int(ctx, &r);
2055 if(FAILED(hres))
2056 return hres;
2058 hres = stack_pop_int(ctx, &l);
2059 if(FAILED(hres))
2060 return hres;
2062 return stack_push_int(ctx, l^r);
2065 /* ECMA-262 3rd Edition 11.10 */
2066 static HRESULT bitand_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
2068 INT li, ri;
2069 HRESULT hres;
2071 hres = to_int32(ctx, lval, ei, &li);
2072 if(FAILED(hres))
2073 return hres;
2075 hres = to_int32(ctx, rval, ei, &ri);
2076 if(FAILED(hres))
2077 return hres;
2079 V_VT(retv) = VT_I4;
2080 V_I4(retv) = li&ri;
2081 return S_OK;
2084 /* ECMA-262 3rd Edition 11.10 */
2085 HRESULT binary_and_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
2087 binary_expression_t *expr = (binary_expression_t*)_expr;
2089 TRACE("\n");
2091 return binary_expr_eval(ctx, expr, bitand_eval, ei, ret);
2094 /* ECMA-262 3rd Edition 11.8.6 */
2095 static HRESULT instanceof_eval(script_ctx_t *ctx, VARIANT *inst, VARIANT *objv, jsexcept_t *ei, VARIANT *retv)
2097 jsdisp_t *obj, *iter, *tmp = NULL;
2098 VARIANT_BOOL ret = VARIANT_FALSE;
2099 BOOL b;
2100 VARIANT var;
2101 HRESULT hres;
2103 static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
2105 if(V_VT(objv) != VT_DISPATCH || !V_DISPATCH(objv))
2106 return throw_type_error(ctx, ei, JS_E_FUNCTION_EXPECTED, NULL);
2108 obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(objv));
2109 if(!obj) {
2110 FIXME("non-jsdisp objects not supported\n");
2111 return E_FAIL;
2114 if(is_class(obj, JSCLASS_FUNCTION)) {
2115 hres = jsdisp_propget_name(obj, prototypeW, &var, ei, NULL/*FIXME*/);
2116 }else {
2117 hres = throw_type_error(ctx, ei, JS_E_FUNCTION_EXPECTED, NULL);
2119 jsdisp_release(obj);
2120 if(FAILED(hres))
2121 return hres;
2123 if(V_VT(&var) == VT_DISPATCH) {
2124 if(V_VT(inst) == VT_DISPATCH)
2125 tmp = iface_to_jsdisp((IUnknown*)V_DISPATCH(inst));
2126 for(iter = tmp; iter; iter = iter->prototype) {
2127 hres = disp_cmp(V_DISPATCH(&var), to_disp(iter), &b);
2128 if(FAILED(hres))
2129 break;
2130 if(b) {
2131 ret = VARIANT_TRUE;
2132 break;
2136 if(tmp)
2137 jsdisp_release(tmp);
2138 }else {
2139 FIXME("prototype is not an object\n");
2140 hres = E_FAIL;
2143 VariantClear(&var);
2144 if(FAILED(hres))
2145 return hres;
2147 V_VT(retv) = VT_BOOL;
2148 V_BOOL(retv) = ret;
2149 return S_OK;
2152 /* ECMA-262 3rd Edition 11.8.6 */
2153 HRESULT instanceof_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
2155 binary_expression_t *expr = (binary_expression_t*)_expr;
2157 TRACE("\n");
2159 return binary_expr_eval(ctx, expr, instanceof_eval, ei, ret);
2162 /* ECMA-262 3rd Edition 11.8.7 */
2163 static HRESULT interp_in(exec_ctx_t *ctx)
2165 VARIANT *obj, *v;
2166 DISPID id = 0;
2167 BOOL ret;
2168 BSTR str;
2169 HRESULT hres;
2171 TRACE("\n");
2173 obj = stack_pop(ctx);
2174 v = stack_pop(ctx);
2176 if(V_VT(obj) != VT_DISPATCH || !V_DISPATCH(obj)) {
2177 VariantClear(obj);
2178 VariantClear(v);
2179 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2182 hres = to_string(ctx->parser->script, v, &ctx->ei, &str);
2183 VariantClear(v);
2184 if(FAILED(hres)) {
2185 IDispatch_Release(V_DISPATCH(obj));
2186 return hres;
2189 hres = disp_get_id(ctx->parser->script, V_DISPATCH(obj), str, 0, &id);
2190 IDispatch_Release(V_DISPATCH(obj));
2191 SysFreeString(str);
2192 if(SUCCEEDED(hres))
2193 ret = TRUE;
2194 else if(hres == DISP_E_UNKNOWNNAME)
2195 ret = FALSE;
2196 else
2197 return hres;
2199 return stack_push_bool(ctx, ret);
2202 /* ECMA-262 3rd Edition 11.6.1 */
2203 static HRESULT add_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
2205 VARIANT r, l;
2206 HRESULT hres;
2208 hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2209 if(FAILED(hres))
2210 return hres;
2212 hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
2213 if(FAILED(hres)) {
2214 VariantClear(&l);
2215 return hres;
2218 if(V_VT(&l) == VT_BSTR || V_VT(&r) == VT_BSTR) {
2219 BSTR lstr = NULL, rstr = NULL;
2221 if(V_VT(&l) == VT_BSTR)
2222 lstr = V_BSTR(&l);
2223 else
2224 hres = to_string(ctx, &l, ei, &lstr);
2226 if(SUCCEEDED(hres)) {
2227 if(V_VT(&r) == VT_BSTR)
2228 rstr = V_BSTR(&r);
2229 else
2230 hres = to_string(ctx, &r, ei, &rstr);
2233 if(SUCCEEDED(hres)) {
2234 int len1, len2;
2236 len1 = SysStringLen(lstr);
2237 len2 = SysStringLen(rstr);
2239 V_VT(retv) = VT_BSTR;
2240 V_BSTR(retv) = SysAllocStringLen(NULL, len1+len2);
2241 memcpy(V_BSTR(retv), lstr, len1*sizeof(WCHAR));
2242 memcpy(V_BSTR(retv)+len1, rstr, (len2+1)*sizeof(WCHAR));
2245 if(V_VT(&l) != VT_BSTR)
2246 SysFreeString(lstr);
2247 if(V_VT(&r) != VT_BSTR)
2248 SysFreeString(rstr);
2249 }else {
2250 VARIANT nl, nr;
2252 hres = to_number(ctx, &l, ei, &nl);
2253 if(SUCCEEDED(hres)) {
2254 hres = to_number(ctx, &r, ei, &nr);
2255 if(SUCCEEDED(hres))
2256 num_set_val(retv, num_val(&nl) + num_val(&nr));
2260 VariantClear(&r);
2261 VariantClear(&l);
2262 return hres;
2265 /* ECMA-262 3rd Edition 11.6.1 */
2266 static HRESULT interp_add(exec_ctx_t *ctx)
2268 VARIANT *l, *r, ret;
2269 HRESULT hres;
2271 r = stack_pop(ctx);
2272 l = stack_pop(ctx);
2274 TRACE("%s + %s\n", debugstr_variant(l), debugstr_variant(r));
2276 hres = add_eval(ctx->parser->script, l, r, &ctx->ei, &ret);
2277 VariantClear(l);
2278 VariantClear(r);
2279 if(FAILED(hres))
2280 return hres;
2282 return stack_push(ctx, &ret);
2285 /* ECMA-262 3rd Edition 11.6.2 */
2286 static HRESULT sub_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
2288 VARIANT lnum, rnum;
2289 HRESULT hres;
2291 hres = to_number(ctx, lval, ei, &lnum);
2292 if(FAILED(hres))
2293 return hres;
2295 hres = to_number(ctx, rval, ei, &rnum);
2296 if(FAILED(hres))
2297 return hres;
2299 num_set_val(retv, num_val(&lnum) - num_val(&rnum));
2300 return S_OK;
2303 /* ECMA-262 3rd Edition 11.6.2 */
2304 static HRESULT interp_sub(exec_ctx_t *ctx)
2306 VARIANT l, r;
2307 HRESULT hres;
2309 TRACE("\n");
2311 hres = stack_pop_number(ctx, &r);
2312 if(FAILED(hres))
2313 return hres;
2315 hres = stack_pop_number(ctx, &l);
2316 if(FAILED(hres))
2317 return hres;
2319 return stack_push_number(ctx, num_val(&l)-num_val(&r));
2322 /* ECMA-262 3rd Edition 11.5.1 */
2323 static HRESULT mul_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
2325 VARIANT lnum, rnum;
2326 HRESULT hres;
2328 hres = to_number(ctx, lval, ei, &lnum);
2329 if(FAILED(hres))
2330 return hres;
2332 hres = to_number(ctx, rval, ei, &rnum);
2333 if(FAILED(hres))
2334 return hres;
2336 num_set_val(retv, num_val(&lnum) * num_val(&rnum));
2337 return S_OK;
2340 /* ECMA-262 3rd Edition 11.5.1 */
2341 static HRESULT interp_mul(exec_ctx_t *ctx)
2343 VARIANT l, r;
2344 HRESULT hres;
2346 TRACE("\n");
2348 hres = stack_pop_number(ctx, &r);
2349 if(FAILED(hres))
2350 return hres;
2352 hres = stack_pop_number(ctx, &l);
2353 if(FAILED(hres))
2354 return hres;
2356 return stack_push_number(ctx, num_val(&l)*num_val(&r));
2359 /* ECMA-262 3rd Edition 11.5.2 */
2360 static HRESULT div_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
2362 VARIANT lnum, rnum;
2363 HRESULT hres;
2365 hres = to_number(ctx, lval, ei, &lnum);
2366 if(FAILED(hres))
2367 return hres;
2369 hres = to_number(ctx, rval, ei, &rnum);
2370 if(FAILED(hres))
2371 return hres;
2373 num_set_val(retv, num_val(&lnum) / num_val(&rnum));
2374 return S_OK;
2377 /* ECMA-262 3rd Edition 11.5.2 */
2378 static HRESULT interp_div(exec_ctx_t *ctx)
2380 VARIANT l, r;
2381 HRESULT hres;
2383 TRACE("\n");
2385 hres = stack_pop_number(ctx, &r);
2386 if(FAILED(hres))
2387 return hres;
2389 hres = stack_pop_number(ctx, &l);
2390 if(FAILED(hres))
2391 return hres;
2393 return stack_push_number(ctx, num_val(&l)/num_val(&r));
2396 /* ECMA-262 3rd Edition 11.5.3 */
2397 static HRESULT mod_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
2399 VARIANT lnum, rnum;
2400 HRESULT hres;
2402 hres = to_number(ctx, lval, ei, &lnum);
2403 if(FAILED(hres))
2404 return hres;
2406 hres = to_number(ctx, rval, ei, &rnum);
2407 if(FAILED(hres))
2408 return hres;
2410 num_set_val(retv, fmod(num_val(&lnum), num_val(&rnum)));
2411 return S_OK;
2414 /* ECMA-262 3rd Edition 11.5.3 */
2415 static HRESULT interp_mod(exec_ctx_t *ctx)
2417 VARIANT l, r;
2418 HRESULT hres;
2420 TRACE("\n");
2422 hres = stack_pop_number(ctx, &r);
2423 if(FAILED(hres))
2424 return hres;
2426 hres = stack_pop_number(ctx, &l);
2427 if(FAILED(hres))
2428 return hres;
2430 return stack_push_number(ctx, fmod(num_val(&l), num_val(&r)));
2433 /* ECMA-262 3rd Edition 11.4.2 */
2434 HRESULT delete_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
2436 unary_expression_t *expr = (unary_expression_t*)_expr;
2437 VARIANT_BOOL b = VARIANT_FALSE;
2438 exprval_t exprval;
2439 HRESULT hres;
2441 TRACE("\n");
2443 hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
2444 if(FAILED(hres))
2445 return hres;
2447 switch(exprval.type) {
2448 case EXPRVAL_IDREF: {
2449 IDispatchEx *dispex;
2451 hres = IDispatch_QueryInterface(exprval.u.idref.disp, &IID_IDispatchEx, (void**)&dispex);
2452 if(SUCCEEDED(hres)) {
2453 hres = IDispatchEx_DeleteMemberByDispID(dispex, exprval.u.idref.id);
2454 b = VARIANT_TRUE;
2455 IDispatchEx_Release(dispex);
2457 break;
2459 default:
2460 FIXME("unsupported type %d\n", exprval.type);
2461 hres = E_NOTIMPL;
2464 exprval_release(&exprval);
2465 if(FAILED(hres))
2466 return hres;
2468 return return_bool(ret, b);
2471 /* ECMA-262 3rd Edition 11.4.2 */
2472 static HRESULT interp_delete(exec_ctx_t *ctx)
2474 VARIANT *obj_var, *name_var;
2475 IDispatchEx *dispex;
2476 IDispatch *obj;
2477 BSTR name;
2478 BOOL ret;
2479 HRESULT hres;
2481 TRACE("\n");
2483 name_var = stack_pop(ctx);
2484 obj_var = stack_pop(ctx);
2486 hres = to_object(ctx->parser->script, obj_var, &obj);
2487 VariantClear(obj_var);
2488 if(FAILED(hres)) {
2489 VariantClear(name_var);
2490 return hres;
2493 hres = to_string(ctx->parser->script, name_var, &ctx->ei, &name);
2494 VariantClear(name_var);
2495 if(FAILED(hres)) {
2496 IDispatch_Release(obj);
2497 return hres;
2500 hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
2501 if(SUCCEEDED(hres)) {
2502 hres = IDispatchEx_DeleteMemberByName(dispex, name, make_grfdex(ctx->parser->script, fdexNameCaseSensitive));
2503 ret = TRUE;
2504 IDispatchEx_Release(dispex);
2505 }else {
2506 hres = S_OK;
2507 ret = FALSE;
2510 IDispatch_Release(obj);
2511 SysFreeString(name);
2512 if(FAILED(hres))
2513 return hres;
2515 return stack_push_bool(ctx, ret);
2518 /* ECMA-262 3rd Edition 11.4.2 */
2519 static HRESULT interp_void(exec_ctx_t *ctx)
2521 VARIANT v;
2523 TRACE("\n");
2525 stack_popn(ctx, 1);
2527 V_VT(&v) = VT_EMPTY;
2528 return stack_push(ctx, &v);
2531 /* ECMA-262 3rd Edition 11.4.3 */
2532 static HRESULT typeof_exprval(script_ctx_t *ctx, exprval_t *exprval, jsexcept_t *ei, const WCHAR **ret)
2534 VARIANT val;
2535 HRESULT hres;
2537 static const WCHAR booleanW[] = {'b','o','o','l','e','a','n',0};
2538 static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0};
2539 static const WCHAR numberW[] = {'n','u','m','b','e','r',0};
2540 static const WCHAR objectW[] = {'o','b','j','e','c','t',0};
2541 static const WCHAR stringW[] = {'s','t','r','i','n','g',0};
2542 static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
2543 static const WCHAR unknownW[] = {'u','n','k','n','o','w','n',0};
2545 if(exprval->type == EXPRVAL_INVALID) {
2546 *ret = undefinedW;
2547 return S_OK;
2550 hres = exprval_to_value(ctx, exprval, ei, &val);
2551 if(FAILED(hres)) {
2552 if(exprval->type == EXPRVAL_IDREF) {
2553 *ret = unknownW;
2554 return S_OK;
2556 return hres;
2559 switch(V_VT(&val)) {
2560 case VT_EMPTY:
2561 *ret = undefinedW;
2562 break;
2563 case VT_NULL:
2564 *ret = objectW;
2565 break;
2566 case VT_BOOL:
2567 *ret = booleanW;
2568 break;
2569 case VT_I4:
2570 case VT_R8:
2571 *ret = numberW;
2572 break;
2573 case VT_BSTR:
2574 *ret = stringW;
2575 break;
2576 case VT_DISPATCH: {
2577 jsdisp_t *dispex;
2579 if(V_DISPATCH(&val) && (dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(&val)))) {
2580 *ret = is_class(dispex, JSCLASS_FUNCTION) ? functionW : objectW;
2581 jsdisp_release(dispex);
2582 }else {
2583 *ret = objectW;
2585 break;
2587 default:
2588 FIXME("unhandled vt %d\n", V_VT(&val));
2589 hres = E_NOTIMPL;
2592 VariantClear(&val);
2593 return hres;
2596 HRESULT typeof_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
2598 unary_expression_t *expr = (unary_expression_t*)_expr;
2599 const WCHAR *str = NULL;
2600 exprval_t exprval;
2601 HRESULT hres;
2603 TRACE("\n");
2605 hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
2606 if(FAILED(hres))
2607 return hres;
2609 hres = typeof_exprval(ctx, &exprval, ei, &str);
2610 exprval_release(&exprval);
2611 if(FAILED(hres))
2612 return hres;
2614 ret->type = EXPRVAL_VARIANT;
2615 V_VT(&ret->u.var) = VT_BSTR;
2616 V_BSTR(&ret->u.var) = SysAllocString(str);
2617 if(!V_BSTR(&ret->u.var))
2618 return E_OUTOFMEMORY;
2620 return S_OK;
2623 /* ECMA-262 3rd Edition 11.4.7 */
2624 static HRESULT interp_minus(exec_ctx_t *ctx)
2626 VARIANT n;
2627 HRESULT hres;
2629 TRACE("\n");
2631 hres = stack_pop_number(ctx, &n);
2632 if(FAILED(hres))
2633 return hres;
2635 return stack_push_number(ctx, -num_val(&n));
2638 /* ECMA-262 3rd Edition 11.4.6 */
2639 static HRESULT interp_tonum(exec_ctx_t *ctx)
2641 VARIANT *v, num;
2642 HRESULT hres;
2644 TRACE("\n");
2646 v = stack_pop(ctx);
2647 hres = to_number(ctx->parser->script, v, &ctx->ei, &num);
2648 VariantClear(v);
2649 if(FAILED(hres))
2650 return hres;
2652 return stack_push(ctx, &num);
2655 /* ECMA-262 3rd Edition 11.3.1 */
2656 HRESULT post_increment_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
2658 unary_expression_t *expr = (unary_expression_t*)_expr;
2659 VARIANT val, num;
2660 exprval_t exprval;
2661 HRESULT hres;
2663 TRACE("\n");
2665 hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
2666 if(FAILED(hres))
2667 return hres;
2669 hres = exprval_value(ctx, &exprval, ei, &val);
2670 if(SUCCEEDED(hres)) {
2671 hres = to_number(ctx, &val, ei, &num);
2672 VariantClear(&val);
2675 if(SUCCEEDED(hres)) {
2676 VARIANT inc;
2677 num_set_val(&inc, num_val(&num)+1.0);
2678 hres = put_value(ctx, &exprval, &inc, ei);
2681 exprval_release(&exprval);
2682 if(FAILED(hres))
2683 return hres;
2685 ret->type = EXPRVAL_VARIANT;
2686 ret->u.var = num;
2687 return S_OK;
2690 /* ECMA-262 3rd Edition 11.3.2 */
2691 HRESULT post_decrement_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
2693 unary_expression_t *expr = (unary_expression_t*)_expr;
2694 VARIANT val, num;
2695 exprval_t exprval;
2696 HRESULT hres;
2698 TRACE("\n");
2700 hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
2701 if(FAILED(hres))
2702 return hres;
2704 hres = exprval_value(ctx, &exprval, ei, &val);
2705 if(SUCCEEDED(hres)) {
2706 hres = to_number(ctx, &val, ei, &num);
2707 VariantClear(&val);
2710 if(SUCCEEDED(hres)) {
2711 VARIANT dec;
2712 num_set_val(&dec, num_val(&num)-1.0);
2713 hres = put_value(ctx, &exprval, &dec, ei);
2716 exprval_release(&exprval);
2717 if(FAILED(hres))
2718 return hres;
2720 ret->type = EXPRVAL_VARIANT;
2721 ret->u.var = num;
2722 return S_OK;
2725 /* ECMA-262 3rd Edition 11.4.4 */
2726 HRESULT pre_increment_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
2728 unary_expression_t *expr = (unary_expression_t*)_expr;
2729 VARIANT val, num;
2730 exprval_t exprval;
2731 HRESULT hres;
2733 TRACE("\n");
2735 hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
2736 if(FAILED(hres))
2737 return hres;
2739 hres = exprval_value(ctx, &exprval, ei, &val);
2740 if(SUCCEEDED(hres)) {
2741 hres = to_number(ctx, &val, ei, &num);
2742 VariantClear(&val);
2745 if(SUCCEEDED(hres)) {
2746 num_set_val(&val, num_val(&num)+1.0);
2747 hres = put_value(ctx, &exprval, &val, ei);
2750 exprval_release(&exprval);
2751 if(FAILED(hres))
2752 return hres;
2754 ret->type = EXPRVAL_VARIANT;
2755 ret->u.var = val;
2756 return S_OK;
2759 /* ECMA-262 3rd Edition 11.4.5 */
2760 HRESULT pre_decrement_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
2762 unary_expression_t *expr = (unary_expression_t*)_expr;
2763 VARIANT val, num;
2764 exprval_t exprval;
2765 HRESULT hres;
2767 TRACE("\n");
2769 hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
2770 if(FAILED(hres))
2771 return hres;
2773 hres = exprval_value(ctx, &exprval, ei, &val);
2774 if(SUCCEEDED(hres)) {
2775 hres = to_number(ctx, &val, ei, &num);
2776 VariantClear(&val);
2779 if(SUCCEEDED(hres)) {
2780 num_set_val(&val, num_val(&num)-1.0);
2781 hres = put_value(ctx, &exprval, &val, ei);
2784 exprval_release(&exprval);
2785 if(FAILED(hres))
2786 return hres;
2788 ret->type = EXPRVAL_VARIANT;
2789 ret->u.var = val;
2790 return S_OK;
2793 /* ECMA-262 3rd Edition 11.9.3 */
2794 static HRESULT equal_values(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, BOOL *ret)
2796 if(V_VT(lval) == V_VT(rval) || (is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval))))
2797 return equal2_values(lval, rval, ret);
2799 /* FIXME: NULL disps should be handled in more general way */
2800 if(V_VT(lval) == VT_DISPATCH && !V_DISPATCH(lval)) {
2801 VARIANT v;
2802 V_VT(&v) = VT_NULL;
2803 return equal_values(ctx, &v, rval, ei, ret);
2806 if(V_VT(rval) == VT_DISPATCH && !V_DISPATCH(rval)) {
2807 VARIANT v;
2808 V_VT(&v) = VT_NULL;
2809 return equal_values(ctx, lval, &v, ei, ret);
2812 if((V_VT(lval) == VT_NULL && V_VT(rval) == VT_EMPTY) ||
2813 (V_VT(lval) == VT_EMPTY && V_VT(rval) == VT_NULL)) {
2814 *ret = TRUE;
2815 return S_OK;
2818 if(V_VT(lval) == VT_BSTR && is_num_vt(V_VT(rval))) {
2819 VARIANT v;
2820 HRESULT hres;
2822 hres = to_number(ctx, lval, ei, &v);
2823 if(FAILED(hres))
2824 return hres;
2826 return equal_values(ctx, &v, rval, ei, ret);
2829 if(V_VT(rval) == VT_BSTR && is_num_vt(V_VT(lval))) {
2830 VARIANT v;
2831 HRESULT hres;
2833 hres = to_number(ctx, rval, ei, &v);
2834 if(FAILED(hres))
2835 return hres;
2837 return equal_values(ctx, lval, &v, ei, ret);
2840 if(V_VT(rval) == VT_BOOL) {
2841 VARIANT v;
2843 V_VT(&v) = VT_I4;
2844 V_I4(&v) = V_BOOL(rval) ? 1 : 0;
2845 return equal_values(ctx, lval, &v, ei, ret);
2848 if(V_VT(lval) == VT_BOOL) {
2849 VARIANT v;
2851 V_VT(&v) = VT_I4;
2852 V_I4(&v) = V_BOOL(lval) ? 1 : 0;
2853 return equal_values(ctx, &v, rval, ei, ret);
2857 if(V_VT(rval) == VT_DISPATCH && (V_VT(lval) == VT_BSTR || is_num_vt(V_VT(lval)))) {
2858 VARIANT v;
2859 HRESULT hres;
2861 hres = to_primitive(ctx, rval, ei, &v, NO_HINT);
2862 if(FAILED(hres))
2863 return hres;
2865 hres = equal_values(ctx, lval, &v, ei, ret);
2867 VariantClear(&v);
2868 return hres;
2872 if(V_VT(lval) == VT_DISPATCH && (V_VT(rval) == VT_BSTR || is_num_vt(V_VT(rval)))) {
2873 VARIANT v;
2874 HRESULT hres;
2876 hres = to_primitive(ctx, lval, ei, &v, NO_HINT);
2877 if(FAILED(hres))
2878 return hres;
2880 hres = equal_values(ctx, &v, rval, ei, ret);
2882 VariantClear(&v);
2883 return hres;
2887 *ret = FALSE;
2888 return S_OK;
2891 /* ECMA-262 3rd Edition 11.9.1 */
2892 static HRESULT interp_eq(exec_ctx_t *ctx)
2894 VARIANT *l, *r;
2895 BOOL b;
2896 HRESULT hres;
2898 r = stack_pop(ctx);
2899 l = stack_pop(ctx);
2901 TRACE("%s == %s\n", debugstr_variant(l), debugstr_variant(r));
2903 hres = equal_values(ctx->parser->script, l, r, &ctx->ei, &b);
2904 VariantClear(l);
2905 VariantClear(r);
2906 if(FAILED(hres))
2907 return hres;
2909 return stack_push_bool(ctx, b);
2912 /* ECMA-262 3rd Edition 11.9.2 */
2913 static HRESULT interp_neq(exec_ctx_t *ctx)
2915 VARIANT *l, *r;
2916 BOOL b;
2917 HRESULT hres;
2919 r = stack_pop(ctx);
2920 l = stack_pop(ctx);
2922 TRACE("%s != %s\n", debugstr_variant(l), debugstr_variant(r));
2924 hres = equal_values(ctx->parser->script, l, r, &ctx->ei, &b);
2925 VariantClear(l);
2926 VariantClear(r);
2927 if(FAILED(hres))
2928 return hres;
2930 return stack_push_bool(ctx, !b);
2933 /* ECMA-262 3rd Edition 11.9.4 */
2934 static HRESULT interp_eq2(exec_ctx_t *ctx)
2936 VARIANT *l, *r;
2937 BOOL b;
2938 HRESULT hres;
2940 TRACE("\n");
2942 r = stack_pop(ctx);
2943 l = stack_pop(ctx);
2945 hres = equal2_values(r, l, &b);
2946 VariantClear(l);
2947 VariantClear(r);
2948 if(FAILED(hres))
2949 return hres;
2951 return stack_push_bool(ctx, b);
2954 /* ECMA-262 3rd Edition 11.9.5 */
2955 static HRESULT interp_neq2(exec_ctx_t *ctx)
2957 VARIANT *l, *r;
2958 BOOL b;
2959 HRESULT hres;
2961 TRACE("\n");
2963 r = stack_pop(ctx);
2964 l = stack_pop(ctx);
2966 hres = equal2_values(r, l, &b);
2967 VariantClear(l);
2968 VariantClear(r);
2969 if(FAILED(hres))
2970 return hres;
2972 return stack_push_bool(ctx, !b);
2975 /* ECMA-262 3rd Edition 11.8.5 */
2976 static HRESULT less_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL greater, jsexcept_t *ei, BOOL *ret)
2978 VARIANT l, r, ln, rn;
2979 HRESULT hres;
2981 hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2982 if(FAILED(hres))
2983 return hres;
2985 hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
2986 if(FAILED(hres)) {
2987 VariantClear(&l);
2988 return hres;
2991 if(V_VT(&l) == VT_BSTR && V_VT(&r) == VT_BSTR) {
2992 *ret = (strcmpW(V_BSTR(&l), V_BSTR(&r)) < 0) ^ greater;
2993 SysFreeString(V_BSTR(&l));
2994 SysFreeString(V_BSTR(&r));
2995 return S_OK;
2998 hres = to_number(ctx, &l, ei, &ln);
2999 VariantClear(&l);
3000 if(SUCCEEDED(hres))
3001 hres = to_number(ctx, &r, ei, &rn);
3002 VariantClear(&r);
3003 if(FAILED(hres))
3004 return hres;
3006 if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) {
3007 *ret = (V_I4(&ln) < V_I4(&rn)) ^ greater;
3008 }else {
3009 DOUBLE ld = num_val(&ln);
3010 DOUBLE rd = num_val(&rn);
3012 *ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater);
3015 return S_OK;
3018 /* ECMA-262 3rd Edition 11.8.1 */
3019 static HRESULT interp_lt(exec_ctx_t *ctx)
3021 VARIANT *l, *r;
3022 BOOL b;
3023 HRESULT hres;
3025 r = stack_pop(ctx);
3026 l = stack_pop(ctx);
3028 TRACE("%s < %s\n", debugstr_variant(l), debugstr_variant(r));
3030 hres = less_eval(ctx->parser->script, l, r, FALSE, &ctx->ei, &b);
3031 VariantClear(l);
3032 VariantClear(r);
3033 if(FAILED(hres))
3034 return hres;
3036 return stack_push_bool(ctx, b);
3039 /* ECMA-262 3rd Edition 11.8.1 */
3040 static HRESULT interp_lteq(exec_ctx_t *ctx)
3042 VARIANT *l, *r;
3043 BOOL b;
3044 HRESULT hres;
3046 r = stack_pop(ctx);
3047 l = stack_pop(ctx);
3049 TRACE("%s <= %s\n", debugstr_variant(l), debugstr_variant(r));
3051 hres = less_eval(ctx->parser->script, r, l, TRUE, &ctx->ei, &b);
3052 VariantClear(l);
3053 VariantClear(r);
3054 if(FAILED(hres))
3055 return hres;
3057 return stack_push_bool(ctx, b);
3060 /* ECMA-262 3rd Edition 11.8.2 */
3061 HRESULT greater_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3063 binary_expression_t *expr = (binary_expression_t*)_expr;
3064 VARIANT rval, lval;
3065 BOOL b;
3066 HRESULT hres;
3068 TRACE("\n");
3070 hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval);
3071 if(FAILED(hres))
3072 return hres;
3074 hres = less_eval(ctx, &rval, &lval, FALSE, ei, &b);
3075 VariantClear(&lval);
3076 VariantClear(&rval);
3077 if(FAILED(hres))
3078 return hres;
3080 return return_bool(ret, b);
3083 /* ECMA-262 3rd Edition 11.8.4 */
3084 HRESULT greatereq_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3086 binary_expression_t *expr = (binary_expression_t*)_expr;
3087 VARIANT rval, lval;
3088 BOOL b;
3089 HRESULT hres;
3091 TRACE("\n");
3093 hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval);
3094 if(FAILED(hres))
3095 return hres;
3097 hres = less_eval(ctx, &lval, &rval, TRUE, ei, &b);
3098 VariantClear(&lval);
3099 VariantClear(&rval);
3100 if(FAILED(hres))
3101 return hres;
3103 return return_bool(ret, b);
3106 /* ECMA-262 3rd Edition 11.4.8 */
3107 static HRESULT interp_bneg(exec_ctx_t *ctx)
3109 VARIANT *v, r;
3110 INT i;
3111 HRESULT hres;
3113 TRACE("\n");
3115 v = stack_pop(ctx);
3116 hres = to_int32(ctx->parser->script, v, &ctx->ei, &i);
3117 VariantClear(v);
3118 if(FAILED(hres))
3119 return hres;
3121 V_VT(&r) = VT_I4;
3122 V_I4(&r) = ~i;
3123 return stack_push(ctx, &r);
3126 /* ECMA-262 3rd Edition 11.4.9 */
3127 static HRESULT interp_neg(exec_ctx_t *ctx)
3129 VARIANT *v;
3130 VARIANT_BOOL b;
3131 HRESULT hres;
3133 TRACE("\n");
3135 v = stack_pop(ctx);
3136 hres = to_boolean(v, &b);
3137 VariantClear(v);
3138 if(FAILED(hres))
3139 return hres;
3141 return stack_push_bool(ctx, !b);
3144 /* ECMA-262 3rd Edition 11.7.1 */
3145 static HRESULT lshift_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
3147 DWORD ri;
3148 INT li;
3149 HRESULT hres;
3151 hres = to_int32(ctx, lval, ei, &li);
3152 if(FAILED(hres))
3153 return hres;
3155 hres = to_uint32(ctx, rval, ei, &ri);
3156 if(FAILED(hres))
3157 return hres;
3159 V_VT(retv) = VT_I4;
3160 V_I4(retv) = li << (ri&0x1f);
3161 return S_OK;
3164 /* ECMA-262 3rd Edition 11.7.1 */
3165 HRESULT left_shift_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3167 binary_expression_t *expr = (binary_expression_t*)_expr;
3169 TRACE("\n");
3171 return binary_expr_eval(ctx, expr, lshift_eval, ei, ret);
3174 /* ECMA-262 3rd Edition 11.7.2 */
3175 static HRESULT rshift_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
3177 DWORD ri;
3178 INT li;
3179 HRESULT hres;
3181 hres = to_int32(ctx, lval, ei, &li);
3182 if(FAILED(hres))
3183 return hres;
3185 hres = to_uint32(ctx, rval, ei, &ri);
3186 if(FAILED(hres))
3187 return hres;
3189 V_VT(retv) = VT_I4;
3190 V_I4(retv) = li >> (ri&0x1f);
3191 return S_OK;
3194 /* ECMA-262 3rd Edition 11.7.2 */
3195 HRESULT right_shift_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3197 binary_expression_t *expr = (binary_expression_t*)_expr;
3199 TRACE("\n");
3201 return binary_expr_eval(ctx, expr, rshift_eval, ei, ret);
3204 /* ECMA-262 3rd Edition 11.7.3 */
3205 static HRESULT rshift2_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
3207 DWORD li, ri;
3208 HRESULT hres;
3210 hres = to_uint32(ctx, lval, ei, &li);
3211 if(FAILED(hres))
3212 return hres;
3214 hres = to_uint32(ctx, rval, ei, &ri);
3215 if(FAILED(hres))
3216 return hres;
3218 V_VT(retv) = VT_I4;
3219 V_I4(retv) = li >> (ri&0x1f);
3220 return S_OK;
3223 /* ECMA-262 3rd Edition 11.7.3 */
3224 HRESULT right2_shift_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3226 binary_expression_t *expr = (binary_expression_t*)_expr;
3228 TRACE("\n");
3230 return binary_expr_eval(ctx, expr, rshift2_eval, ei, ret);
3233 /* ECMA-262 3rd Edition 11.13.1 */
3234 HRESULT assign_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3236 binary_expression_t *expr = (binary_expression_t*)_expr;
3237 exprval_t exprval, exprvalr;
3238 VARIANT rval;
3239 HRESULT hres;
3241 TRACE("\n");
3243 hres = expr_eval(ctx, expr->expression1, EXPR_NEWREF, ei, &exprval);
3244 if(FAILED(hres))
3245 return hres;
3247 hres = expr_eval(ctx, expr->expression2, 0, ei, &exprvalr);
3248 if(SUCCEEDED(hres)) {
3249 hres = exprval_to_value(ctx, &exprvalr, ei, &rval);
3250 exprval_release(&exprvalr);
3253 if(SUCCEEDED(hres)) {
3254 hres = put_value(ctx, &exprval, &rval, ei);
3255 if(FAILED(hres))
3256 VariantClear(&rval);
3259 exprval_release(&exprval);
3260 if(FAILED(hres))
3261 return hres;
3263 ret->type = EXPRVAL_VARIANT;
3264 ret->u.var = rval;
3265 return S_OK;
3268 /* ECMA-262 3rd Edition 11.13.2 */
3269 HRESULT assign_lshift_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3271 binary_expression_t *expr = (binary_expression_t*)_expr;
3273 TRACE("\n");
3275 return assign_oper_eval(ctx, expr->expression1, expr->expression2, lshift_eval, ei, ret);
3278 /* ECMA-262 3rd Edition 11.13.2 */
3279 HRESULT assign_rshift_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3281 binary_expression_t *expr = (binary_expression_t*)_expr;
3283 TRACE("\n");
3285 return assign_oper_eval(ctx, expr->expression1, expr->expression2, rshift_eval, ei, ret);
3288 /* ECMA-262 3rd Edition 11.13.2 */
3289 HRESULT assign_rrshift_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3291 binary_expression_t *expr = (binary_expression_t*)_expr;
3293 TRACE("\n");
3295 return assign_oper_eval(ctx, expr->expression1, expr->expression2, rshift2_eval, ei, ret);
3298 /* ECMA-262 3rd Edition 11.13.2 */
3299 HRESULT assign_add_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3301 binary_expression_t *expr = (binary_expression_t*)_expr;
3303 TRACE("\n");
3305 return assign_oper_eval(ctx, expr->expression1, expr->expression2, add_eval, ei, ret);
3308 /* ECMA-262 3rd Edition 11.13.2 */
3309 HRESULT assign_sub_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3311 binary_expression_t *expr = (binary_expression_t*)_expr;
3313 TRACE("\n");
3315 return assign_oper_eval(ctx, expr->expression1, expr->expression2, sub_eval, ei, ret);
3318 /* ECMA-262 3rd Edition 11.13.2 */
3319 HRESULT assign_mul_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3321 binary_expression_t *expr = (binary_expression_t*)_expr;
3323 TRACE("\n");
3325 return assign_oper_eval(ctx, expr->expression1, expr->expression2, mul_eval, ei, ret);
3328 /* ECMA-262 3rd Edition 11.13.2 */
3329 HRESULT assign_div_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3331 binary_expression_t *expr = (binary_expression_t*)_expr;
3333 TRACE("\n");
3335 return assign_oper_eval(ctx, expr->expression1, expr->expression2, div_eval, ei, ret);
3338 /* ECMA-262 3rd Edition 11.13.2 */
3339 HRESULT assign_mod_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3341 binary_expression_t *expr = (binary_expression_t*)_expr;
3343 TRACE("\n");
3345 return assign_oper_eval(ctx, expr->expression1, expr->expression2, mod_eval, ei, ret);
3348 /* ECMA-262 3rd Edition 11.13.2 */
3349 HRESULT assign_and_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3351 binary_expression_t *expr = (binary_expression_t*)_expr;
3353 TRACE("\n");
3355 return assign_oper_eval(ctx, expr->expression1, expr->expression2, bitand_eval, ei, ret);
3358 /* ECMA-262 3rd Edition 11.13.2 */
3359 HRESULT assign_or_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3361 binary_expression_t *expr = (binary_expression_t*)_expr;
3363 TRACE("\n");
3365 return assign_oper_eval(ctx, expr->expression1, expr->expression2, bitor_eval, ei, ret);
3368 /* ECMA-262 3rd Edition 11.13.2 */
3369 HRESULT assign_xor_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3371 binary_expression_t *expr = (binary_expression_t*)_expr;
3373 TRACE("\n");
3375 return assign_oper_eval(ctx, expr->expression1, expr->expression2, xor_eval, ei, ret);
3378 static HRESULT interp_jmp(exec_ctx_t *ctx)
3380 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
3382 TRACE("\n");
3384 ctx->ip = arg;
3385 return S_OK;
3388 static HRESULT interp_pop(exec_ctx_t *ctx)
3390 TRACE("\n");
3392 stack_popn(ctx, 1);
3393 return S_OK;
3396 static HRESULT interp_ret(exec_ctx_t *ctx)
3398 TRACE("\n");
3400 ctx->ip = -1;
3401 return S_OK;
3404 static HRESULT interp_tree(exec_ctx_t *ctx)
3406 instr_t *instr = ctx->parser->code->instrs+ctx->ip;
3407 exprval_t val;
3408 VARIANT v;
3409 HRESULT hres;
3411 TRACE("\n");
3413 hres = expr_eval(ctx->parser->script, instr->arg1.expr, 0, &ctx->ei, &val);
3414 if(FAILED(hres))
3415 return hres;
3417 hres = exprval_to_value(ctx->parser->script, &val, &ctx->ei, &v);
3418 exprval_release(&val);
3419 if(FAILED(hres))
3420 return hres;
3422 return stack_push(ctx, &v);
3425 typedef HRESULT (*op_func_t)(exec_ctx_t*);
3427 static const op_func_t op_funcs[] = {
3428 #define X(x,a,b,c) interp_##x,
3429 OP_LIST
3430 #undef X
3433 static const unsigned op_move[] = {
3434 #define X(a,x,b,c) x,
3435 OP_LIST
3436 #undef X
3439 HRESULT interp_expression_eval(script_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3441 exec_ctx_t *exec_ctx = ctx->exec_ctx;
3442 unsigned prev_ip, prev_top;
3443 jsop_t op;
3444 HRESULT hres = S_OK;
3446 TRACE("\n");
3448 prev_top = exec_ctx->top;
3449 prev_ip = exec_ctx->ip;
3450 exec_ctx->ip = expr->instr_off;
3452 while(exec_ctx->ip != -1) {
3453 op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
3454 hres = op_funcs[op](exec_ctx);
3455 if(FAILED(hres))
3456 break;
3457 exec_ctx->ip += op_move[op];
3460 exec_ctx->ip = prev_ip;
3462 if(FAILED(hres)) {
3463 stack_popn(exec_ctx, exec_ctx->top-prev_top);
3464 *ei = exec_ctx->ei;
3465 memset(&exec_ctx->ei, 0, sizeof(exec_ctx->ei));
3466 return hres;
3469 assert(exec_ctx->top == prev_top+1);
3471 ret->type = EXPRVAL_VARIANT;
3472 ret->u.var = *stack_pop(exec_ctx);
3473 return S_OK;
3476 HRESULT compiled_expression_eval(script_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3478 HRESULT hres;
3480 TRACE("\n");
3482 hres = compile_subscript(ctx->exec_ctx->parser, expr, &expr->instr_off);
3483 if(FAILED(hres))
3484 return hres;
3486 if(expr->eval == compiled_expression_eval)
3487 expr->eval = interp_expression_eval;
3489 return expr->eval(ctx, expr, flags, ei, ret);