jscript: Get rid of no longer needed expression eval entry.
[wine.git] / dlls / jscript / engine.c
blob424659f14f16bdaedb95b0077d9fa5eb3b4b6aaa
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
34 static const WCHAR booleanW[] = {'b','o','o','l','e','a','n',0};
35 static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0};
36 static const WCHAR numberW[] = {'n','u','m','b','e','r',0};
37 static const WCHAR objectW[] = {'o','b','j','e','c','t',0};
38 static const WCHAR stringW[] = {'s','t','r','i','n','g',0};
39 static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
40 static const WCHAR unknownW[] = {'u','n','k','n','o','w','n',0};
42 struct _return_type_t {
43 enum{
44 RT_NORMAL,
45 RT_RETURN,
46 RT_BREAK,
47 RT_CONTINUE
48 } type;
49 jsexcept_t ei;
52 static inline HRESULT stat_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
54 return stat->eval(ctx, stat, rt, ret);
57 static inline HRESULT expr_eval(script_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
59 return compiled_expression_eval(ctx, expr, flags, ei, ret);
62 static HRESULT stack_push(exec_ctx_t *ctx, VARIANT *v)
64 if(!ctx->stack_size) {
65 ctx->stack = heap_alloc(16*sizeof(VARIANT));
66 if(!ctx->stack)
67 return E_OUTOFMEMORY;
68 ctx->stack_size = 16;
69 }else if(ctx->stack_size == ctx->top) {
70 VARIANT *new_stack;
72 new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(VARIANT));
73 if(!new_stack) {
74 VariantClear(v);
75 return E_OUTOFMEMORY;
78 ctx->stack = new_stack;
79 ctx->stack_size *= 2;
82 ctx->stack[ctx->top++] = *v;
83 return S_OK;
86 static HRESULT stack_push_bool(exec_ctx_t *ctx, BOOL b)
88 VARIANT v;
90 V_VT(&v) = VT_BOOL;
91 V_BOOL(&v) = b ? VARIANT_TRUE : VARIANT_FALSE;
92 return stack_push(ctx, &v);
95 static inline HRESULT stack_push_number(exec_ctx_t *ctx, double number)
97 VARIANT v;
99 num_set_val(&v, number);
100 return stack_push(ctx, &v);
103 static inline HRESULT stack_push_int(exec_ctx_t *ctx, INT n)
105 VARIANT v;
107 V_VT(&v) = VT_I4;
108 V_I4(&v) = n;
109 return stack_push(ctx, &v);
112 static inline HRESULT stack_push_string(exec_ctx_t *ctx, const WCHAR *str)
114 VARIANT v;
116 V_VT(&v) = VT_BSTR;
117 V_BSTR(&v) = SysAllocString(str);
118 return V_BSTR(&v) ? stack_push(ctx, &v) : E_OUTOFMEMORY;
121 static HRESULT stack_push_objid(exec_ctx_t *ctx, IDispatch *disp, DISPID id)
123 VARIANT v;
124 HRESULT hres;
126 V_VT(&v) = VT_DISPATCH;
127 V_DISPATCH(&v) = disp;
128 hres = stack_push(ctx, &v);
129 if(FAILED(hres))
130 return hres;
132 V_VT(&v) = VT_INT;
133 V_INT(&v) = id;
134 return stack_push(ctx, &v);
137 static inline VARIANT *stack_top(exec_ctx_t *ctx)
139 assert(ctx->top);
140 return ctx->stack + ctx->top-1;
143 static inline VARIANT *stack_topn(exec_ctx_t *ctx, unsigned n)
145 assert(ctx->top > n);
146 return ctx->stack + ctx->top-1-n;
149 static inline VARIANT *stack_pop(exec_ctx_t *ctx)
151 assert(ctx->top);
152 return ctx->stack + --ctx->top;
155 static void stack_popn(exec_ctx_t *ctx, unsigned n)
157 while(n--)
158 VariantClear(stack_pop(ctx));
161 static HRESULT stack_pop_number(exec_ctx_t *ctx, VARIANT *r)
163 VARIANT *v;
164 HRESULT hres;
166 v = stack_pop(ctx);
167 hres = to_number(ctx->parser->script, v, &ctx->ei, r);
168 VariantClear(v);
169 return hres;
172 static HRESULT stack_pop_object(exec_ctx_t *ctx, IDispatch **r)
174 VARIANT *v;
175 HRESULT hres;
177 v = stack_pop(ctx);
178 if(V_VT(v) == VT_DISPATCH) {
179 if(!V_DISPATCH(v))
180 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_OBJECT_REQUIRED, NULL);
181 *r = V_DISPATCH(v);
182 return S_OK;
185 hres = to_object(ctx->parser->script, v, r);
186 VariantClear(v);
187 return hres;
190 static inline HRESULT stack_pop_int(exec_ctx_t *ctx, INT *r)
192 return to_int32(ctx->parser->script, stack_pop(ctx), &ctx->ei, r);
195 static inline HRESULT stack_pop_uint(exec_ctx_t *ctx, DWORD *r)
197 return to_uint32(ctx->parser->script, stack_pop(ctx), &ctx->ei, r);
200 static inline IDispatch *stack_pop_objid(exec_ctx_t *ctx, DISPID *id)
202 assert(V_VT(stack_top(ctx)) == VT_INT && V_VT(stack_topn(ctx, 1)) == VT_DISPATCH);
204 *id = V_INT(stack_pop(ctx));
205 return V_DISPATCH(stack_pop(ctx));
208 static inline IDispatch *stack_topn_objid(exec_ctx_t *ctx, unsigned n, DISPID *id)
210 assert(V_VT(stack_topn(ctx, n)) == VT_INT && V_VT(stack_topn(ctx, n+1)) == VT_DISPATCH);
212 *id = V_INT(stack_topn(ctx, n));
213 return V_DISPATCH(stack_topn(ctx, n+1));
216 static void exprval_release(exprval_t *val)
218 switch(val->type) {
219 case EXPRVAL_VARIANT:
220 if(V_VT(&val->u.var) != VT_EMPTY)
221 VariantClear(&val->u.var);
222 return;
223 case EXPRVAL_IDREF:
224 if(val->u.idref.disp)
225 IDispatch_Release(val->u.idref.disp);
226 return;
227 case EXPRVAL_INVALID:
228 SysFreeString(val->u.identifier);
232 /* ECMA-262 3rd Edition 8.7.1 */
233 static HRESULT exprval_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
235 V_VT(ret) = VT_EMPTY;
237 switch(val->type) {
238 case EXPRVAL_VARIANT:
239 return VariantCopy(ret, &val->u.var);
240 case EXPRVAL_IDREF:
241 if(!val->u.idref.disp) {
242 FIXME("throw ReferenceError\n");
243 return E_FAIL;
246 return disp_propget(ctx, val->u.idref.disp, val->u.idref.id, ret, ei, NULL/*FIXME*/);
247 case EXPRVAL_INVALID:
248 return throw_type_error(ctx, ei, JS_E_UNDEFINED_VARIABLE, val->u.identifier);
251 ERR("type %d\n", val->type);
252 return E_FAIL;
255 static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
257 if(val->type == EXPRVAL_VARIANT) {
258 *ret = val->u.var;
259 V_VT(&val->u.var) = VT_EMPTY;
260 return S_OK;
263 return exprval_value(ctx, val, ei, ret);
266 static HRESULT exprval_to_boolean(script_ctx_t *ctx, exprval_t *exprval, jsexcept_t *ei, VARIANT_BOOL *b)
268 if(exprval->type != EXPRVAL_VARIANT) {
269 VARIANT val;
270 HRESULT hres;
272 hres = exprval_to_value(ctx, exprval, ei, &val);
273 if(FAILED(hres))
274 return hres;
276 hres = to_boolean(&val, b);
277 VariantClear(&val);
278 return hres;
281 return to_boolean(&exprval->u.var, b);
284 static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id)
286 val->type = EXPRVAL_IDREF;
287 val->u.idref.disp = disp;
288 val->u.idref.id = id;
290 if(disp)
291 IDispatch_AddRef(disp);
294 HRESULT scope_push(scope_chain_t *scope, jsdisp_t *obj, scope_chain_t **ret)
296 scope_chain_t *new_scope;
298 new_scope = heap_alloc(sizeof(scope_chain_t));
299 if(!new_scope)
300 return E_OUTOFMEMORY;
302 new_scope->ref = 1;
304 jsdisp_addref(obj);
305 new_scope->obj = obj;
307 if(scope) {
308 scope_addref(scope);
309 new_scope->next = scope;
310 }else {
311 new_scope->next = NULL;
314 *ret = new_scope;
315 return S_OK;
318 static void scope_pop(scope_chain_t **scope)
320 scope_chain_t *tmp;
322 tmp = *scope;
323 *scope = tmp->next;
324 scope_release(tmp);
327 void scope_release(scope_chain_t *scope)
329 if(--scope->ref)
330 return;
332 if(scope->next)
333 scope_release(scope->next);
335 jsdisp_release(scope->obj);
336 heap_free(scope);
339 HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, jsdisp_t *var_disp,
340 scope_chain_t *scope, BOOL is_global, exec_ctx_t **ret)
342 exec_ctx_t *ctx;
344 ctx = heap_alloc_zero(sizeof(exec_ctx_t));
345 if(!ctx)
346 return E_OUTOFMEMORY;
348 ctx->ref = 1;
349 ctx->is_global = is_global;
351 if(this_obj)
352 ctx->this_obj = this_obj;
353 else if(script_ctx->host_global)
354 ctx->this_obj = script_ctx->host_global;
355 else
356 ctx->this_obj = to_disp(script_ctx->global);
357 IDispatch_AddRef(ctx->this_obj);
359 jsdisp_addref(var_disp);
360 ctx->var_disp = var_disp;
362 if(scope) {
363 scope_addref(scope);
364 ctx->scope_chain = scope;
367 *ret = ctx;
368 return S_OK;
371 void exec_release(exec_ctx_t *ctx)
373 if(--ctx->ref)
374 return;
376 if(ctx->scope_chain)
377 scope_release(ctx->scope_chain);
378 if(ctx->var_disp)
379 jsdisp_release(ctx->var_disp);
380 if(ctx->this_obj)
381 IDispatch_Release(ctx->this_obj);
382 heap_free(ctx->stack);
383 heap_free(ctx);
386 static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
388 IDispatchEx *dispex;
389 HRESULT hres;
391 hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
392 if(FAILED(hres)) {
393 TRACE("unsing IDispatch\n");
395 *id = 0;
396 return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
399 *id = 0;
400 hres = IDispatchEx_GetDispID(dispex, name, make_grfdex(ctx, flags|fdexNameCaseSensitive), id);
401 IDispatchEx_Release(dispex);
402 return hres;
405 /* ECMA-262 3rd Edition 8.7.2 */
406 static HRESULT put_value(script_ctx_t *ctx, exprval_t *ref, VARIANT *v, jsexcept_t *ei)
408 if(ref->type != EXPRVAL_IDREF)
409 return throw_reference_error(ctx, ei, JS_E_ILLEGAL_ASSIGN, NULL);
411 return disp_propput(ctx, ref->u.idref.disp, ref->u.idref.id, v, ei, NULL/*FIXME*/);
414 static inline BOOL is_null(const VARIANT *v)
416 return V_VT(v) == VT_NULL || (V_VT(v) == VT_DISPATCH && !V_DISPATCH(v));
419 static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret)
421 IObjectIdentity *identity;
422 IUnknown *unk1, *unk2;
423 HRESULT hres;
425 if(disp1 == disp2) {
426 *ret = TRUE;
427 return S_OK;
430 if(!disp1 || !disp2) {
431 *ret = FALSE;
432 return S_OK;
435 hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1);
436 if(FAILED(hres))
437 return hres;
439 hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2);
440 if(FAILED(hres)) {
441 IUnknown_Release(unk1);
442 return hres;
445 if(unk1 == unk2) {
446 *ret = TRUE;
447 }else {
448 hres = IUnknown_QueryInterface(unk1, &IID_IObjectIdentity, (void**)&identity);
449 if(SUCCEEDED(hres)) {
450 hres = IObjectIdentity_IsEqualObject(identity, unk2);
451 IObjectIdentity_Release(identity);
452 *ret = hres == S_OK;
453 }else {
454 *ret = FALSE;
458 IUnknown_Release(unk1);
459 IUnknown_Release(unk2);
460 return S_OK;
463 /* ECMA-262 3rd Edition 11.9.6 */
464 static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
466 TRACE("\n");
468 if(V_VT(lval) != V_VT(rval)) {
469 if(is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval)))
470 *ret = num_val(lval) == num_val(rval);
471 else if(is_null(lval))
472 *ret = is_null(rval);
473 else
474 *ret = FALSE;
475 return S_OK;
478 switch(V_VT(lval)) {
479 case VT_EMPTY:
480 case VT_NULL:
481 *ret = VARIANT_TRUE;
482 break;
483 case VT_I4:
484 *ret = V_I4(lval) == V_I4(rval);
485 break;
486 case VT_R8:
487 *ret = V_R8(lval) == V_R8(rval);
488 break;
489 case VT_BSTR:
490 if(!V_BSTR(lval))
491 *ret = SysStringLen(V_BSTR(rval))?FALSE:TRUE;
492 else if(!V_BSTR(rval))
493 *ret = SysStringLen(V_BSTR(lval))?FALSE:TRUE;
494 else
495 *ret = !strcmpW(V_BSTR(lval), V_BSTR(rval));
496 break;
497 case VT_DISPATCH:
498 return disp_cmp(V_DISPATCH(lval), V_DISPATCH(rval), ret);
499 case VT_BOOL:
500 *ret = !V_BOOL(lval) == !V_BOOL(rval);
501 break;
502 default:
503 FIXME("unimplemented vt %d\n", V_VT(lval));
504 return E_NOTIMPL;
507 return S_OK;
510 static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
512 named_item_t *item;
513 DISPID id;
514 HRESULT hres;
516 for(item = ctx->named_items; item; item = item->next) {
517 if(item->flags & SCRIPTITEM_GLOBALMEMBERS) {
518 hres = disp_get_id(ctx, item->disp, identifier, 0, &id);
519 if(SUCCEEDED(hres)) {
520 if(ret)
521 exprval_set_idref(ret, item->disp, id);
522 return TRUE;
527 return FALSE;
530 HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, BOOL from_eval,
531 jsexcept_t *ei, VARIANT *retv)
533 script_ctx_t *script = parser->script;
534 function_declaration_t *func;
535 parser_ctx_t *prev_parser;
536 var_list_t *var;
537 VARIANT val, tmp;
538 statement_t *stat;
539 exec_ctx_t *prev_ctx;
540 return_type_t rt;
541 HRESULT hres = S_OK;
543 for(func = source->functions; func; func = func->next) {
544 jsdisp_t *func_obj;
545 VARIANT var;
547 hres = create_source_function(parser, func->expr->parameter_list, func->expr->source_elements,
548 ctx->scope_chain, func->expr->src_str, func->expr->src_len, &func_obj);
549 if(FAILED(hres))
550 return hres;
552 var_set_jsdisp(&var, func_obj);
553 hres = jsdisp_propput_name(ctx->var_disp, func->expr->identifier, &var, ei, NULL);
554 jsdisp_release(func_obj);
555 if(FAILED(hres))
556 return hres;
559 for(var = source->variables; var; var = var->next) {
560 DISPID id = 0;
561 BSTR name;
563 name = SysAllocString(var->identifier);
564 if(!name)
565 return E_OUTOFMEMORY;
567 if(!ctx->is_global || !lookup_global_members(parser->script, name, NULL))
568 hres = jsdisp_get_id(ctx->var_disp, var->identifier, fdexNameEnsure, &id);
569 SysFreeString(name);
570 if(FAILED(hres))
571 return hres;
574 prev_ctx = script->exec_ctx;
575 script->exec_ctx = ctx;
577 prev_parser = ctx->parser;
578 ctx->parser = parser;
580 V_VT(&val) = VT_EMPTY;
581 memset(&rt, 0, sizeof(rt));
582 rt.type = RT_NORMAL;
584 for(stat = source->statement; stat; stat = stat->next) {
585 hres = stat_eval(script, stat, &rt, &tmp);
586 if(FAILED(hres))
587 break;
589 VariantClear(&val);
590 val = tmp;
591 if(rt.type != RT_NORMAL)
592 break;
595 script->exec_ctx = prev_ctx;
596 ctx->parser = prev_parser;
598 if(rt.type != RT_NORMAL && rt.type != RT_RETURN) {
599 FIXME("wrong rt %d\n", rt.type);
600 hres = E_FAIL;
603 *ei = rt.ei;
604 if(FAILED(hres)) {
605 VariantClear(&val);
606 return hres;
609 if(!retv || (!from_eval && rt.type != RT_RETURN))
610 VariantClear(&val);
611 if(retv)
612 *retv = val;
613 return S_OK;
616 /* ECMA-262 3rd Edition 10.1.4 */
617 static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, DWORD flags, jsexcept_t *ei, exprval_t *ret)
619 scope_chain_t *scope;
620 named_item_t *item;
621 DISPID id = 0;
622 HRESULT hres;
624 TRACE("%s\n", debugstr_w(identifier));
626 for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) {
627 hres = jsdisp_get_id(scope->obj, identifier, 0, &id);
628 if(SUCCEEDED(hres)) {
629 exprval_set_idref(ret, to_disp(scope->obj), id);
630 return S_OK;
634 hres = jsdisp_get_id(ctx->global, identifier, 0, &id);
635 if(SUCCEEDED(hres)) {
636 exprval_set_idref(ret, to_disp(ctx->global), id);
637 return S_OK;
640 for(item = ctx->named_items; item; item = item->next) {
641 if((item->flags & SCRIPTITEM_ISVISIBLE) && !strcmpW(item->name, identifier)) {
642 if(!item->disp) {
643 IUnknown *unk;
645 if(!ctx->site)
646 break;
648 hres = IActiveScriptSite_GetItemInfo(ctx->site, identifier,
649 SCRIPTINFO_IUNKNOWN, &unk, NULL);
650 if(FAILED(hres)) {
651 WARN("GetItemInfo failed: %08x\n", hres);
652 break;
655 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
656 IUnknown_Release(unk);
657 if(FAILED(hres)) {
658 WARN("object does not implement IDispatch\n");
659 break;
663 ret->type = EXPRVAL_VARIANT;
664 V_VT(&ret->u.var) = VT_DISPATCH;
665 V_DISPATCH(&ret->u.var) = item->disp;
666 IDispatch_AddRef(item->disp);
667 return S_OK;
671 if(lookup_global_members(ctx, identifier, ret))
672 return S_OK;
674 if(flags & fdexNameEnsure) {
675 hres = jsdisp_get_id(ctx->global, identifier, fdexNameEnsure, &id);
676 if(FAILED(hres))
677 return hres;
679 exprval_set_idref(ret, to_disp(ctx->global), id);
680 return S_OK;
683 ret->type = EXPRVAL_INVALID;
684 ret->u.identifier = SysAllocString(identifier);
685 if(!ret->u.identifier)
686 return E_OUTOFMEMORY;
688 return S_OK;
691 /* ECMA-262 3rd Edition 12.1 */
692 HRESULT block_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
694 block_statement_t *stat = (block_statement_t*)_stat;
695 VARIANT val, tmp;
696 statement_t *iter;
697 HRESULT hres = S_OK;
699 TRACE("\n");
701 V_VT(&val) = VT_EMPTY;
702 for(iter = stat->stat_list; iter; iter = iter->next) {
703 hres = stat_eval(ctx, iter, rt, &tmp);
704 if(FAILED(hres))
705 break;
707 VariantClear(&val);
708 val = tmp;
709 if(rt->type != RT_NORMAL)
710 break;
713 if(FAILED(hres)) {
714 VariantClear(&val);
715 return hres;
718 *ret = val;
719 return S_OK;
722 /* ECMA-262 3rd Edition 12.2 */
723 static HRESULT variable_list_eval(script_ctx_t *ctx, variable_declaration_t *var_list, jsexcept_t *ei)
725 variable_declaration_t *iter;
726 HRESULT hres = S_OK;
728 for(iter = var_list; iter; iter = iter->next) {
729 exprval_t exprval;
730 VARIANT val;
732 if(!iter->expr)
733 continue;
735 hres = expr_eval(ctx, iter->expr, 0, ei, &exprval);
736 if(FAILED(hres))
737 break;
739 hres = exprval_to_value(ctx, &exprval, ei, &val);
740 exprval_release(&exprval);
741 if(FAILED(hres))
742 break;
744 hres = jsdisp_propput_name(ctx->exec_ctx->var_disp, iter->identifier, &val, ei, NULL/*FIXME*/);
745 VariantClear(&val);
746 if(FAILED(hres))
747 break;
750 return hres;
753 /* ECMA-262 3rd Edition 12.2 */
754 HRESULT var_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
756 var_statement_t *stat = (var_statement_t*)_stat;
757 HRESULT hres;
759 TRACE("\n");
761 hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
762 if(FAILED(hres))
763 return hres;
765 V_VT(ret) = VT_EMPTY;
766 return S_OK;
769 /* ECMA-262 3rd Edition 12.3 */
770 HRESULT empty_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
772 TRACE("\n");
774 V_VT(ret) = VT_EMPTY;
775 return S_OK;
778 /* ECMA-262 3rd Edition 12.4 */
779 HRESULT expression_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
781 expression_statement_t *stat = (expression_statement_t*)_stat;
782 exprval_t exprval;
783 VARIANT val;
784 HRESULT hres;
786 TRACE("\n");
788 hres = expr_eval(ctx, stat->expr, EXPR_NOVAL, &rt->ei, &exprval);
789 if(FAILED(hres))
790 return hres;
792 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
793 exprval_release(&exprval);
794 if(FAILED(hres))
795 return hres;
797 *ret = val;
798 TRACE("= %s\n", debugstr_variant(ret));
799 return S_OK;
802 /* ECMA-262 3rd Edition 12.5 */
803 HRESULT if_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
805 if_statement_t *stat = (if_statement_t*)_stat;
806 exprval_t exprval;
807 VARIANT_BOOL b;
808 HRESULT hres;
810 TRACE("\n");
812 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
813 if(FAILED(hres))
814 return hres;
816 hres = exprval_to_boolean(ctx, &exprval, &rt->ei, &b);
817 exprval_release(&exprval);
818 if(FAILED(hres))
819 return hres;
821 if(b)
822 hres = stat_eval(ctx, stat->if_stat, rt, ret);
823 else if(stat->else_stat)
824 hres = stat_eval(ctx, stat->else_stat, rt, ret);
825 else
826 V_VT(ret) = VT_EMPTY;
828 return hres;
831 /* ECMA-262 3rd Edition 12.6.2 */
832 HRESULT while_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
834 while_statement_t *stat = (while_statement_t*)_stat;
835 exprval_t exprval;
836 VARIANT val, tmp;
837 VARIANT_BOOL b;
838 BOOL test_expr;
839 HRESULT hres;
841 TRACE("\n");
843 V_VT(&val) = VT_EMPTY;
844 test_expr = !stat->do_while;
846 while(1) {
847 if(test_expr) {
848 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
849 if(FAILED(hres))
850 break;
852 hres = exprval_to_boolean(ctx, &exprval, &rt->ei, &b);
853 exprval_release(&exprval);
854 if(FAILED(hres) || !b)
855 break;
856 }else {
857 test_expr = TRUE;
860 hres = stat_eval(ctx, stat->statement, rt, &tmp);
861 if(FAILED(hres))
862 break;
864 VariantClear(&val);
865 val = tmp;
867 if(rt->type == RT_CONTINUE)
868 rt->type = RT_NORMAL;
869 if(rt->type != RT_NORMAL)
870 break;
873 if(FAILED(hres)) {
874 VariantClear(&val);
875 return hres;
878 if(rt->type == RT_BREAK)
879 rt->type = RT_NORMAL;
881 *ret = val;
882 return S_OK;
885 /* ECMA-262 3rd Edition 12.6.3 */
886 HRESULT for_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
888 for_statement_t *stat = (for_statement_t*)_stat;
889 VARIANT val, tmp, retv;
890 exprval_t exprval;
891 VARIANT_BOOL b;
892 HRESULT hres;
894 TRACE("\n");
896 if(stat->variable_list) {
897 hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
898 if(FAILED(hres))
899 return hres;
900 }else if(stat->begin_expr) {
901 hres = expr_eval(ctx, stat->begin_expr, 0, &rt->ei, &exprval);
902 if(FAILED(hres))
903 return hres;
905 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
906 exprval_release(&exprval);
907 if(FAILED(hres))
908 return hres;
910 VariantClear(&val);
913 V_VT(&retv) = VT_EMPTY;
915 while(1) {
916 if(stat->expr) {
917 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
918 if(FAILED(hres))
919 break;
921 hres = exprval_to_boolean(ctx, &exprval, &rt->ei, &b);
922 exprval_release(&exprval);
923 if(FAILED(hres) || !b)
924 break;
927 hres = stat_eval(ctx, stat->statement, rt, &tmp);
928 if(FAILED(hres))
929 break;
931 VariantClear(&retv);
932 retv = tmp;
934 if(rt->type == RT_CONTINUE)
935 rt->type = RT_NORMAL;
936 else if(rt->type != RT_NORMAL)
937 break;
939 if(stat->end_expr) {
940 hres = expr_eval(ctx, stat->end_expr, 0, &rt->ei, &exprval);
941 if(FAILED(hres))
942 break;
944 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
945 exprval_release(&exprval);
946 if(FAILED(hres))
947 break;
949 VariantClear(&val);
953 if(FAILED(hres)) {
954 VariantClear(&retv);
955 return hres;
958 if(rt->type == RT_BREAK)
959 rt->type = RT_NORMAL;
961 *ret = retv;
962 return S_OK;
965 static HRESULT array_expression_eval(script_ctx_t*,expression_t*,jsexcept_t*,exprval_t*);
966 static HRESULT member_expression_eval(script_ctx_t*,expression_t*,jsexcept_t*,exprval_t*);
967 static HRESULT identifier_expression_eval(script_ctx_t*,expression_t*,jsexcept_t*,exprval_t*);
969 /* ECMA-262 3rd Edition 12.6.4 */
970 HRESULT forin_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
972 forin_statement_t *stat = (forin_statement_t*)_stat;
973 VARIANT val, name, retv, tmp;
974 DISPID id = DISPID_STARTENUM;
975 BSTR str, identifier = NULL;
976 IDispatchEx *in_obj;
977 exprval_t exprval;
978 HRESULT hres;
980 TRACE("\n");
982 if(stat->variable) {
983 hres = variable_list_eval(ctx, stat->variable, &rt->ei);
984 if(FAILED(hres))
985 return hres;
988 hres = expr_eval(ctx, stat->in_expr, 0, &rt->ei, &exprval);
989 if(FAILED(hres))
990 return hres;
992 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
993 exprval_release(&exprval);
994 if(FAILED(hres))
995 return hres;
997 if(V_VT(&val) != VT_DISPATCH) {
998 TRACE("in vt %d\n", V_VT(&val));
999 VariantClear(&val);
1000 V_VT(ret) = VT_EMPTY;
1001 return S_OK;
1004 hres = IDispatch_QueryInterface(V_DISPATCH(&val), &IID_IDispatchEx, (void**)&in_obj);
1005 IDispatch_Release(V_DISPATCH(&val));
1006 if(FAILED(hres)) {
1007 TRACE("Object doesn't support IDispatchEx\n");
1008 V_VT(ret) = VT_EMPTY;
1009 return S_OK;
1012 V_VT(&retv) = VT_EMPTY;
1014 if(stat->variable)
1015 identifier = SysAllocString(stat->variable->identifier);
1017 while(1) {
1018 hres = IDispatchEx_GetNextDispID(in_obj, fdexEnumDefault, id, &id);
1019 if(FAILED(hres) || hres == S_FALSE)
1020 break;
1022 hres = IDispatchEx_GetMemberName(in_obj, id, &str);
1023 if(FAILED(hres))
1024 break;
1026 TRACE("iter %s\n", debugstr_w(str));
1028 if(stat->variable) {
1029 hres = identifier_eval(ctx, identifier, 0, NULL, &exprval);
1030 }else {
1031 switch(stat->expr->type) {
1032 case EXPR_ARRAY:
1033 hres = array_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
1034 break;
1035 case EXPR_IDENT:
1036 hres = identifier_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
1037 break;
1038 case EXPR_MEMBER:
1039 hres = member_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
1040 break;
1041 default:
1042 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
1045 if(SUCCEEDED(hres)) {
1046 V_VT(&name) = VT_BSTR;
1047 V_BSTR(&name) = str;
1048 hres = put_value(ctx, &exprval, &name, &rt->ei);
1049 exprval_release(&exprval);
1051 SysFreeString(str);
1052 if(FAILED(hres))
1053 break;
1055 hres = stat_eval(ctx, stat->statement, rt, &tmp);
1056 if(FAILED(hres))
1057 break;
1059 VariantClear(&retv);
1060 retv = tmp;
1062 if(rt->type == RT_CONTINUE)
1063 rt->type = RT_NORMAL;
1064 else if(rt->type != RT_NORMAL)
1065 break;
1068 SysFreeString(identifier);
1069 IDispatchEx_Release(in_obj);
1070 if(FAILED(hres)) {
1071 VariantClear(&retv);
1072 return hres;
1075 if(rt->type == RT_BREAK)
1076 rt->type = RT_NORMAL;
1078 *ret = retv;
1079 return S_OK;
1082 /* ECMA-262 3rd Edition 12.7 */
1083 HRESULT continue_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1085 branch_statement_t *stat = (branch_statement_t*)_stat;
1087 TRACE("\n");
1089 if(stat->identifier) {
1090 FIXME("indentifier not implemented\n");
1091 return E_NOTIMPL;
1094 rt->type = RT_CONTINUE;
1095 V_VT(ret) = VT_EMPTY;
1096 return S_OK;
1099 /* ECMA-262 3rd Edition 12.8 */
1100 HRESULT break_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1102 branch_statement_t *stat = (branch_statement_t*)_stat;
1104 TRACE("\n");
1106 if(stat->identifier) {
1107 FIXME("indentifier not implemented\n");
1108 return E_NOTIMPL;
1111 rt->type = RT_BREAK;
1112 V_VT(ret) = VT_EMPTY;
1113 return S_OK;
1116 /* ECMA-262 3rd Edition 12.9 */
1117 HRESULT return_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1119 expression_statement_t *stat = (expression_statement_t*)_stat;
1120 HRESULT hres;
1122 TRACE("\n");
1124 if(stat->expr) {
1125 exprval_t exprval;
1127 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
1128 if(FAILED(hres))
1129 return hres;
1131 hres = exprval_to_value(ctx, &exprval, &rt->ei, ret);
1132 exprval_release(&exprval);
1133 if(FAILED(hres))
1134 return hres;
1135 }else {
1136 V_VT(ret) = VT_EMPTY;
1139 TRACE("= %s\n", debugstr_variant(ret));
1140 rt->type = RT_RETURN;
1141 return S_OK;
1144 /* ECMA-262 3rd Edition 12.10 */
1145 HRESULT with_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1147 with_statement_t *stat = (with_statement_t*)_stat;
1148 exprval_t exprval;
1149 IDispatch *disp;
1150 jsdisp_t *obj;
1151 VARIANT val;
1152 HRESULT hres;
1154 TRACE("\n");
1156 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
1157 if(FAILED(hres))
1158 return hres;
1160 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
1161 exprval_release(&exprval);
1162 if(FAILED(hres))
1163 return hres;
1165 hres = to_object(ctx, &val, &disp);
1166 VariantClear(&val);
1167 if(FAILED(hres))
1168 return hres;
1170 obj = iface_to_jsdisp((IUnknown*)disp);
1171 IDispatch_Release(disp);
1172 if(!obj) {
1173 FIXME("disp id not jsdisp\n");
1174 return E_NOTIMPL;
1177 hres = scope_push(ctx->exec_ctx->scope_chain, obj, &ctx->exec_ctx->scope_chain);
1178 jsdisp_release(obj);
1179 if(FAILED(hres))
1180 return hres;
1182 hres = stat_eval(ctx, stat->statement, rt, ret);
1184 scope_pop(&ctx->exec_ctx->scope_chain);
1185 return hres;
1188 /* ECMA-262 3rd Edition 12.12 */
1189 HRESULT labelled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
1191 FIXME("\n");
1192 return E_NOTIMPL;
1195 /* ECMA-262 3rd Edition 12.13 */
1196 HRESULT switch_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1198 switch_statement_t *stat = (switch_statement_t*)_stat;
1199 case_clausule_t *iter, *default_clausule = NULL;
1200 statement_t *stat_iter;
1201 VARIANT val, cval;
1202 exprval_t exprval;
1203 BOOL b;
1204 HRESULT hres;
1206 TRACE("\n");
1208 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
1209 if(FAILED(hres))
1210 return hres;
1212 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
1213 exprval_release(&exprval);
1214 if(FAILED(hres))
1215 return hres;
1217 for(iter = stat->case_list; iter; iter = iter->next) {
1218 if(!iter->expr) {
1219 default_clausule = iter;
1220 continue;
1223 hres = expr_eval(ctx, iter->expr, 0, &rt->ei, &exprval);
1224 if(FAILED(hres))
1225 break;
1227 hres = exprval_to_value(ctx, &exprval, &rt->ei, &cval);
1228 exprval_release(&exprval);
1229 if(FAILED(hres))
1230 break;
1232 hres = equal2_values(&val, &cval, &b);
1233 VariantClear(&cval);
1234 if(FAILED(hres) || b)
1235 break;
1238 VariantClear(&val);
1239 if(FAILED(hres))
1240 return hres;
1242 if(!iter)
1243 iter = default_clausule;
1245 V_VT(&val) = VT_EMPTY;
1246 if(iter) {
1247 VARIANT tmp;
1249 for(stat_iter = iter->stat; stat_iter; stat_iter = stat_iter->next) {
1250 hres = stat_eval(ctx, stat_iter, rt, &tmp);
1251 if(FAILED(hres))
1252 break;
1254 VariantClear(&val);
1255 val = tmp;
1257 if(rt->type != RT_NORMAL)
1258 break;
1262 if(FAILED(hres)) {
1263 VariantClear(&val);
1264 return hres;
1267 if(rt->type == RT_BREAK)
1268 rt->type = RT_NORMAL;
1270 *ret = val;
1271 return S_OK;
1274 /* ECMA-262 3rd Edition 12.13 */
1275 HRESULT throw_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1277 expression_statement_t *stat = (expression_statement_t*)_stat;
1278 exprval_t exprval;
1279 VARIANT val;
1280 HRESULT hres;
1282 TRACE("\n");
1284 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
1285 if(FAILED(hres))
1286 return hres;
1288 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
1289 exprval_release(&exprval);
1290 if(FAILED(hres))
1291 return hres;
1293 rt->ei.var = val;
1294 return DISP_E_EXCEPTION;
1297 static HRESULT interp_throw(exec_ctx_t *ctx)
1299 const HRESULT arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1301 TRACE("%08x\n", arg);
1303 return throw_reference_error(ctx->parser->script, &ctx->ei, arg, NULL);
1306 static HRESULT interp_throw_type(exec_ctx_t *ctx)
1308 const HRESULT hres = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1309 const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg2.str;
1311 TRACE("%08x %s\n", hres, debugstr_w(str));
1313 return throw_type_error(ctx->parser->script, &ctx->ei, hres, str);
1316 /* ECMA-262 3rd Edition 12.14 */
1317 static HRESULT catch_eval(script_ctx_t *ctx, catch_block_t *block, return_type_t *rt, VARIANT *ret)
1319 jsdisp_t *var_disp;
1320 VARIANT ex, val;
1321 HRESULT hres;
1323 ex = rt->ei.var;
1324 memset(&rt->ei, 0, sizeof(jsexcept_t));
1326 hres = create_dispex(ctx, NULL, NULL, &var_disp);
1327 if(SUCCEEDED(hres)) {
1328 hres = jsdisp_propput_name(var_disp, block->identifier, &ex, &rt->ei, NULL/*FIXME*/);
1329 if(SUCCEEDED(hres)) {
1330 hres = scope_push(ctx->exec_ctx->scope_chain, var_disp, &ctx->exec_ctx->scope_chain);
1331 if(SUCCEEDED(hres)) {
1332 hres = stat_eval(ctx, block->statement, rt, &val);
1333 scope_pop(&ctx->exec_ctx->scope_chain);
1337 jsdisp_release(var_disp);
1340 VariantClear(&ex);
1341 if(FAILED(hres))
1342 return hres;
1344 *ret = val;
1345 return S_OK;
1348 /* ECMA-262 3rd Edition 12.14 */
1349 HRESULT try_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1351 try_statement_t *stat = (try_statement_t*)_stat;
1352 VARIANT val;
1353 HRESULT hres;
1355 TRACE("\n");
1357 hres = stat_eval(ctx, stat->try_statement, rt, &val);
1358 if(FAILED(hres)) {
1359 TRACE("EXCEPTION\n");
1360 if(!stat->catch_block)
1361 return hres;
1363 hres = catch_eval(ctx, stat->catch_block, rt, &val);
1364 if(FAILED(hres))
1365 return hres;
1368 if(stat->finally_statement) {
1369 VariantClear(&val);
1370 hres = stat_eval(ctx, stat->finally_statement, rt, &val);
1371 if(FAILED(hres))
1372 return hres;
1375 *ret = val;
1376 return S_OK;
1379 /* ECMA-262 3rd Edition 13 */
1380 static HRESULT interp_func(exec_ctx_t *ctx)
1382 function_expression_t *expr = ctx->parser->code->instrs[ctx->ip].arg1.func;
1383 jsdisp_t *dispex;
1384 VARIANT v;
1385 HRESULT hres;
1387 TRACE("\n");
1389 hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain,
1390 expr->src_str, expr->src_len, &dispex);
1391 if(FAILED(hres))
1392 return hres;
1394 var_set_jsdisp(&v, dispex);
1395 return stack_push(ctx, &v);
1398 /* ECMA-262 3rd Edition 11.2.1 */
1399 static HRESULT array_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1401 binary_expression_t *expr = (binary_expression_t*)_expr;
1402 exprval_t exprval;
1403 VARIANT member, val;
1404 DISPID id;
1405 BSTR str;
1406 IDispatch *obj = NULL;
1407 HRESULT hres;
1409 TRACE("\n");
1411 hres = expr_eval(ctx, expr->expression1, 0, ei, &exprval);
1412 if(FAILED(hres))
1413 return hres;
1415 hres = exprval_to_value(ctx, &exprval, ei, &member);
1416 exprval_release(&exprval);
1417 if(FAILED(hres))
1418 return hres;
1420 hres = expr_eval(ctx, expr->expression2, 0, ei, &exprval);
1421 if(SUCCEEDED(hres)) {
1422 hres = exprval_to_value(ctx, &exprval, ei, &val);
1423 exprval_release(&exprval);
1426 if(SUCCEEDED(hres)) {
1427 hres = to_object(ctx, &member, &obj);
1428 if(FAILED(hres))
1429 VariantClear(&val);
1431 VariantClear(&member);
1432 if(SUCCEEDED(hres)) {
1433 hres = to_string(ctx, &val, ei, &str);
1434 VariantClear(&val);
1435 if(SUCCEEDED(hres)) {
1436 hres = disp_get_id(ctx, obj, str, fdexNameEnsure, &id);
1437 SysFreeString(str);
1440 if(SUCCEEDED(hres))
1441 exprval_set_idref(ret, obj, id);
1443 IDispatch_Release(obj);
1446 return hres;
1449 /* ECMA-262 3rd Edition 11.2.1 */
1450 static HRESULT interp_array(exec_ctx_t *ctx)
1452 VARIANT v, *namev;
1453 IDispatch *obj;
1454 DISPID id;
1455 BSTR name;
1456 HRESULT hres;
1458 TRACE("\n");
1460 namev = stack_pop(ctx);
1462 hres = stack_pop_object(ctx, &obj);
1463 if(FAILED(hres)) {
1464 VariantClear(namev);
1465 return hres;
1468 hres = to_string(ctx->parser->script, namev, &ctx->ei, &name);
1469 VariantClear(namev);
1470 if(FAILED(hres)) {
1471 IDispatch_Release(obj);
1472 return hres;
1475 hres = disp_get_id(ctx->parser->script, obj, name, 0, &id);
1476 SysFreeString(name);
1477 if(SUCCEEDED(hres)) {
1478 hres = disp_propget(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/);
1479 }else if(hres == DISP_E_UNKNOWNNAME) {
1480 V_VT(&v) = VT_EMPTY;
1481 hres = S_OK;
1483 IDispatch_Release(obj);
1484 if(FAILED(hres))
1485 return hres;
1487 return stack_push(ctx, &v);
1490 /* ECMA-262 3rd Edition 11.2.1 */
1491 static HRESULT member_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1493 member_expression_t *expr = (member_expression_t*)_expr;
1494 IDispatch *obj = NULL;
1495 exprval_t exprval;
1496 VARIANT member;
1497 DISPID id;
1498 BSTR str;
1499 HRESULT hres;
1501 TRACE("\n");
1503 hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
1504 if(FAILED(hres))
1505 return hres;
1507 hres = exprval_to_value(ctx, &exprval, ei, &member);
1508 exprval_release(&exprval);
1509 if(FAILED(hres))
1510 return hres;
1512 hres = to_object(ctx, &member, &obj);
1513 VariantClear(&member);
1514 if(FAILED(hres))
1515 return hres;
1517 str = SysAllocString(expr->identifier);
1518 if(!str) {
1519 IDispatch_Release(obj);
1520 return E_OUTOFMEMORY;
1523 hres = disp_get_id(ctx, obj, str, fdexNameEnsure, &id);
1524 SysFreeString(str);
1525 if(SUCCEEDED(hres))
1526 exprval_set_idref(ret, obj, id);
1528 IDispatch_Release(obj);
1529 return hres;
1532 /* ECMA-262 3rd Edition 11.2.1 */
1533 static HRESULT interp_member(exec_ctx_t *ctx)
1535 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1536 IDispatch *obj;
1537 VARIANT v;
1538 DISPID id;
1539 HRESULT hres;
1541 TRACE("\n");
1543 hres = stack_pop_object(ctx, &obj);
1544 if(FAILED(hres))
1545 return hres;
1547 hres = disp_get_id(ctx->parser->script, obj, arg, 0, &id);
1548 if(SUCCEEDED(hres)) {
1549 V_VT(&v) = VT_EMPTY;
1550 hres = disp_propget(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/);
1551 }else if(hres == DISP_E_UNKNOWNNAME) {
1552 V_VT(&v) = VT_EMPTY;
1553 hres = S_OK;
1555 IDispatch_Release(obj);
1556 if(FAILED(hres))
1557 return hres;
1559 return stack_push(ctx, &v);
1562 /* ECMA-262 3rd Edition 11.2.1 */
1563 static HRESULT interp_memberid(exec_ctx_t *ctx)
1565 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1566 VARIANT *objv, *namev;
1567 IDispatch *obj;
1568 BSTR name;
1569 DISPID id;
1570 HRESULT hres;
1572 TRACE("%x\n", arg);
1574 namev = stack_pop(ctx);
1575 objv = stack_pop(ctx);
1577 hres = to_object(ctx->parser->script, objv, &obj);
1578 VariantClear(objv);
1579 if(SUCCEEDED(hres)) {
1580 hres = to_string(ctx->parser->script, namev, &ctx->ei, &name);
1581 if(FAILED(hres))
1582 IDispatch_Release(obj);
1584 VariantClear(namev);
1585 if(FAILED(hres))
1586 return hres;
1588 hres = disp_get_id(ctx->parser->script, obj, name, arg, &id);
1589 SysFreeString(name);
1590 if(FAILED(hres)) {
1591 IDispatch_Release(obj);
1592 if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
1593 obj = NULL;
1594 id = JS_E_INVALID_PROPERTY;
1595 }else {
1596 return hres;
1600 return stack_push_objid(ctx, obj, id);
1603 /* ECMA-262 3rd Edition 11.2.1 */
1604 static HRESULT interp_refval(exec_ctx_t *ctx)
1606 IDispatch *disp;
1607 VARIANT v;
1608 DISPID id;
1609 HRESULT hres;
1611 TRACE("\n");
1613 disp = stack_topn_objid(ctx, 0, &id);
1614 if(!disp)
1615 return throw_reference_error(ctx->parser->script, &ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
1617 hres = disp_propget(ctx->parser->script, disp, id, &v, &ctx->ei, NULL/*FIXME*/);
1618 if(FAILED(hres))
1619 return hres;
1621 return stack_push(ctx, &v);
1624 static void jsstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, DISPPARAMS *dp)
1626 VARIANT tmp;
1627 unsigned i;
1629 dp->cArgs = arg_cnt;
1630 dp->rgdispidNamedArgs = NULL;
1631 dp->cNamedArgs = 0;
1633 assert(ctx->top >= arg_cnt);
1635 for(i=1; i*2 <= arg_cnt; i++) {
1636 tmp = ctx->stack[ctx->top-i];
1637 ctx->stack[ctx->top-i] = ctx->stack[ctx->top-arg_cnt+i-1];
1638 ctx->stack[ctx->top-arg_cnt+i-1] = tmp;
1641 dp->rgvarg = ctx->stack + ctx->top-arg_cnt;
1644 /* ECMA-262 3rd Edition 11.2.2 */
1645 static HRESULT interp_new(exec_ctx_t *ctx)
1647 const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1648 VARIANT *constr, v;
1649 DISPPARAMS dp;
1650 HRESULT hres;
1652 TRACE("%d\n", arg);
1654 constr = stack_topn(ctx, arg);
1656 /* NOTE: Should use to_object here */
1658 if(V_VT(constr) == VT_NULL)
1659 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1660 else if(V_VT(constr) != VT_DISPATCH)
1661 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_INVALID_ACTION, NULL);
1662 else if(!V_DISPATCH(constr))
1663 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1665 jsstack_to_dp(ctx, arg, &dp);
1666 hres = disp_call(ctx->parser->script, V_DISPATCH(constr), DISPID_VALUE,
1667 DISPATCH_CONSTRUCT, &dp, &v, &ctx->ei, NULL/*FIXME*/);
1668 if(FAILED(hres))
1669 return hres;
1671 stack_popn(ctx, arg+1);
1672 return stack_push(ctx, &v);
1675 /* ECMA-262 3rd Edition 11.2.3 */
1676 static HRESULT interp_call(exec_ctx_t *ctx)
1678 const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1679 const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1680 VARIANT v, *objv;
1681 DISPPARAMS dp;
1682 HRESULT hres;
1684 TRACE("%d %d\n", argn, do_ret);
1686 objv = stack_topn(ctx, argn);
1687 if(V_VT(objv) != VT_DISPATCH)
1688 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1690 jsstack_to_dp(ctx, argn, &dp);
1691 hres = disp_call(ctx->parser->script, V_DISPATCH(objv), DISPID_VALUE, DISPATCH_METHOD, &dp,
1692 do_ret ? &v : NULL, &ctx->ei, NULL/*FIXME*/);
1693 if(FAILED(hres))
1694 return hres;
1696 stack_popn(ctx, argn+1);
1697 return do_ret ? stack_push(ctx, &v) : S_OK;
1701 /* ECMA-262 3rd Edition 11.2.3 */
1702 static HRESULT interp_call_member(exec_ctx_t *ctx)
1704 const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1705 const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1706 IDispatch *obj;
1707 DISPPARAMS dp;
1708 VARIANT v;
1709 DISPID id;
1710 HRESULT hres;
1712 TRACE("%d %d\n", argn, do_ret);
1714 obj = stack_topn_objid(ctx, argn, &id);
1715 if(!obj)
1716 return throw_type_error(ctx->parser->script, &ctx->ei, id, NULL);
1718 jsstack_to_dp(ctx, argn, &dp);
1719 hres = disp_call(ctx->parser->script, obj, id, DISPATCH_METHOD, &dp, do_ret ? &v : NULL, &ctx->ei, NULL/*FIXME*/);
1720 if(FAILED(hres))
1721 return hres;
1723 stack_popn(ctx, argn+2);
1724 return do_ret ? stack_push(ctx, &v) : S_OK;
1728 /* ECMA-262 3rd Edition 11.1.1 */
1729 static HRESULT interp_this(exec_ctx_t *ctx)
1731 VARIANT v;
1733 TRACE("\n");
1735 V_VT(&v) = VT_DISPATCH;
1736 V_DISPATCH(&v) = ctx->this_obj;
1737 IDispatch_AddRef(ctx->this_obj);
1738 return stack_push(ctx, &v);
1741 /* ECMA-262 3rd Edition 10.1.4 */
1742 static HRESULT identifier_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1744 identifier_expression_t *expr = (identifier_expression_t*)_expr;
1745 BSTR identifier;
1746 HRESULT hres;
1748 TRACE("\n");
1750 identifier = SysAllocString(expr->identifier);
1751 if(!identifier)
1752 return E_OUTOFMEMORY;
1754 hres = identifier_eval(ctx, identifier, fdexNameEnsure, ei, ret);
1756 SysFreeString(identifier);
1757 return hres;
1760 /* ECMA-262 3rd Edition 10.1.4 */
1761 static HRESULT interp_ident(exec_ctx_t *ctx)
1763 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1764 exprval_t exprval;
1765 VARIANT v;
1766 HRESULT hres;
1768 TRACE("%s\n", debugstr_w(arg));
1770 hres = identifier_eval(ctx->parser->script, arg, 0, &ctx->ei, &exprval);
1771 if(FAILED(hres))
1772 return hres;
1774 hres = exprval_to_value(ctx->parser->script, &exprval, &ctx->ei, &v);
1775 exprval_release(&exprval);
1776 if(FAILED(hres))
1777 return hres;
1779 return stack_push(ctx, &v);
1782 /* ECMA-262 3rd Edition 10.1.4 */
1783 static HRESULT interp_identid(exec_ctx_t *ctx)
1785 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1786 const unsigned flags = ctx->parser->code->instrs[ctx->ip].arg2.uint;
1787 exprval_t exprval;
1788 HRESULT hres;
1790 TRACE("%s %x\n", debugstr_w(arg), flags);
1792 hres = identifier_eval(ctx->parser->script, arg, flags, &ctx->ei, &exprval);
1793 if(FAILED(hres))
1794 return hres;
1796 if(exprval.type != EXPRVAL_IDREF) {
1797 WARN("invalid ref\n");
1798 exprval_release(&exprval);
1799 return stack_push_objid(ctx, NULL, JS_E_OBJECT_EXPECTED);
1802 return stack_push_objid(ctx, exprval.u.idref.disp, exprval.u.idref.id);
1805 /* ECMA-262 3rd Edition 7.8.1 */
1806 static HRESULT interp_null(exec_ctx_t *ctx)
1808 VARIANT v;
1810 TRACE("\n");
1812 V_VT(&v) = VT_NULL;
1813 return stack_push(ctx, &v);
1816 /* ECMA-262 3rd Edition 7.8.2 */
1817 static HRESULT interp_bool(exec_ctx_t *ctx)
1819 const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1821 TRACE("%s\n", arg ? "true" : "false");
1823 return stack_push_bool(ctx, arg);
1826 /* ECMA-262 3rd Edition 7.8.3 */
1827 static HRESULT interp_int(exec_ctx_t *ctx)
1829 const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1830 VARIANT v;
1832 TRACE("%d\n", arg);
1834 V_VT(&v) = VT_I4;
1835 V_I4(&v) = arg;
1836 return stack_push(ctx, &v);
1839 /* ECMA-262 3rd Edition 7.8.3 */
1840 static HRESULT interp_double(exec_ctx_t *ctx)
1842 const double arg = *ctx->parser->code->instrs[ctx->ip].arg1.dbl;
1843 VARIANT v;
1845 TRACE("%lf\n", arg);
1847 V_VT(&v) = VT_R8;
1848 V_R8(&v) = arg;
1849 return stack_push(ctx, &v);
1852 /* ECMA-262 3rd Edition 7.8.4 */
1853 static HRESULT interp_str(exec_ctx_t *ctx)
1855 const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg1.str;
1856 VARIANT v;
1858 TRACE("%s\n", debugstr_w(str));
1860 V_VT(&v) = VT_BSTR;
1861 V_BSTR(&v) = SysAllocString(str);
1862 if(!V_BSTR(&v))
1863 return E_OUTOFMEMORY;
1865 return stack_push(ctx, &v);
1868 /* ECMA-262 3rd Edition 7.8 */
1869 static HRESULT interp_regexp(exec_ctx_t *ctx)
1871 const WCHAR *source = ctx->parser->code->instrs[ctx->ip].arg1.str;
1872 const LONG flags = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1873 jsdisp_t *regexp;
1874 VARIANT v;
1875 HRESULT hres;
1877 TRACE("%s %x\n", debugstr_w(source), flags);
1879 hres = create_regexp(ctx->parser->script, source, strlenW(source), flags, &regexp);
1880 if(FAILED(hres))
1881 return hres;
1883 var_set_jsdisp(&v, regexp);
1884 return stack_push(ctx, &v);
1887 /* ECMA-262 3rd Edition 11.1.4 */
1888 static HRESULT interp_carray(exec_ctx_t *ctx)
1890 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1891 jsdisp_t *array;
1892 VARIANT *v, r;
1893 unsigned i;
1894 HRESULT hres;
1896 TRACE("%u\n", arg);
1898 hres = create_array(ctx->parser->script, arg, &array);
1899 if(FAILED(hres))
1900 return hres;
1902 i = arg;
1903 while(i--) {
1904 v = stack_pop(ctx);
1905 hres = jsdisp_propput_idx(array, i, v, &ctx->ei, NULL/*FIXME*/);
1906 VariantClear(v);
1907 if(FAILED(hres)) {
1908 jsdisp_release(array);
1909 return hres;
1913 var_set_jsdisp(&r, array);
1914 return stack_push(ctx, &r);
1917 /* ECMA-262 3rd Edition 11.1.5 */
1918 HRESULT interp_new_obj(exec_ctx_t *ctx)
1920 jsdisp_t *obj;
1921 VARIANT v;
1922 HRESULT hres;
1924 TRACE("\n");
1926 hres = create_object(ctx->parser->script, NULL, &obj);
1927 if(FAILED(hres))
1928 return hres;
1930 var_set_jsdisp(&v, obj);
1931 return stack_push(ctx, &v);
1934 /* ECMA-262 3rd Edition 11.1.5 */
1935 HRESULT interp_obj_prop(exec_ctx_t *ctx)
1937 const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1938 jsdisp_t *obj;
1939 VARIANT *v;
1940 HRESULT hres;
1942 TRACE("%s\n", debugstr_w(name));
1944 v = stack_pop(ctx);
1946 assert(V_VT(stack_top(ctx)) == VT_DISPATCH);
1947 obj = as_jsdisp(V_DISPATCH(stack_top(ctx)));
1949 hres = jsdisp_propput_name(obj, name, v, &ctx->ei, NULL/*FIXME*/);
1950 VariantClear(v);
1951 return hres;
1954 /* ECMA-262 3rd Edition 11.11 */
1955 static HRESULT interp_jmp_nz(exec_ctx_t *ctx)
1957 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1958 VARIANT_BOOL b;
1959 HRESULT hres;
1961 TRACE("\n");
1963 hres = to_boolean(stack_top(ctx), &b);
1964 if(FAILED(hres))
1965 return hres;
1967 if(b) {
1968 ctx->ip = arg;
1969 }else {
1970 stack_popn(ctx, 1);
1971 ctx->ip++;
1973 return S_OK;
1976 /* ECMA-262 3rd Edition 11.11 */
1977 static HRESULT interp_jmp_z(exec_ctx_t *ctx)
1979 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1980 VARIANT_BOOL b;
1981 HRESULT hres;
1983 TRACE("\n");
1985 hres = to_boolean(stack_top(ctx), &b);
1986 if(FAILED(hres))
1987 return hres;
1989 if(b) {
1990 stack_popn(ctx, 1);
1991 ctx->ip++;
1992 }else {
1993 ctx->ip = arg;
1995 return S_OK;
1998 /* ECMA-262 3rd Edition 11.10 */
1999 static HRESULT interp_or(exec_ctx_t *ctx)
2001 INT l, r;
2002 HRESULT hres;
2004 TRACE("\n");
2006 hres = stack_pop_int(ctx, &r);
2007 if(FAILED(hres))
2008 return hres;
2010 hres = stack_pop_int(ctx, &l);
2011 if(FAILED(hres))
2012 return hres;
2014 return stack_push_int(ctx, l|r);
2017 /* ECMA-262 3rd Edition 11.10 */
2018 static HRESULT interp_xor(exec_ctx_t *ctx)
2020 INT l, r;
2021 HRESULT hres;
2023 TRACE("\n");
2025 hres = stack_pop_int(ctx, &r);
2026 if(FAILED(hres))
2027 return hres;
2029 hres = stack_pop_int(ctx, &l);
2030 if(FAILED(hres))
2031 return hres;
2033 return stack_push_int(ctx, l^r);
2036 /* ECMA-262 3rd Edition 11.10 */
2037 static HRESULT interp_and(exec_ctx_t *ctx)
2039 INT l, r;
2040 HRESULT hres;
2042 TRACE("\n");
2044 hres = stack_pop_int(ctx, &r);
2045 if(FAILED(hres))
2046 return hres;
2048 hres = stack_pop_int(ctx, &l);
2049 if(FAILED(hres))
2050 return hres;
2052 return stack_push_int(ctx, l&r);
2055 /* ECMA-262 3rd Edition 11.8.6 */
2056 static HRESULT interp_instanceof(exec_ctx_t *ctx)
2058 jsdisp_t *obj, *iter, *tmp = NULL;
2059 VARIANT prot, *v;
2060 BOOL ret = FALSE;
2061 HRESULT hres;
2063 static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
2065 v = stack_pop(ctx);
2066 if(V_VT(v) != VT_DISPATCH || !V_DISPATCH(v)) {
2067 VariantClear(v);
2068 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
2071 obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
2072 IDispatch_Release(V_DISPATCH(v));
2073 if(!obj) {
2074 FIXME("non-jsdisp objects not supported\n");
2075 return E_FAIL;
2078 if(is_class(obj, JSCLASS_FUNCTION)) {
2079 hres = jsdisp_propget_name(obj, prototypeW, &prot, &ctx->ei, NULL/*FIXME*/);
2080 }else {
2081 hres = throw_type_error(ctx->parser->script, &ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
2083 jsdisp_release(obj);
2084 if(FAILED(hres))
2085 return hres;
2087 v = stack_pop(ctx);
2089 if(V_VT(&prot) == VT_DISPATCH) {
2090 if(V_VT(v) == VT_DISPATCH)
2091 tmp = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
2092 for(iter = tmp; !ret && iter; iter = iter->prototype) {
2093 hres = disp_cmp(V_DISPATCH(&prot), to_disp(iter), &ret);
2094 if(FAILED(hres))
2095 break;
2098 if(tmp)
2099 jsdisp_release(tmp);
2100 }else {
2101 FIXME("prototype is not an object\n");
2102 hres = E_FAIL;
2105 VariantClear(&prot);
2106 VariantClear(v);
2107 if(FAILED(hres))
2108 return hres;
2110 return stack_push_bool(ctx, ret);
2113 /* ECMA-262 3rd Edition 11.8.7 */
2114 static HRESULT interp_in(exec_ctx_t *ctx)
2116 VARIANT *obj, *v;
2117 DISPID id = 0;
2118 BOOL ret;
2119 BSTR str;
2120 HRESULT hres;
2122 TRACE("\n");
2124 obj = stack_pop(ctx);
2125 v = stack_pop(ctx);
2127 if(V_VT(obj) != VT_DISPATCH || !V_DISPATCH(obj)) {
2128 VariantClear(obj);
2129 VariantClear(v);
2130 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2133 hres = to_string(ctx->parser->script, v, &ctx->ei, &str);
2134 VariantClear(v);
2135 if(FAILED(hres)) {
2136 IDispatch_Release(V_DISPATCH(obj));
2137 return hres;
2140 hres = disp_get_id(ctx->parser->script, V_DISPATCH(obj), str, 0, &id);
2141 IDispatch_Release(V_DISPATCH(obj));
2142 SysFreeString(str);
2143 if(SUCCEEDED(hres))
2144 ret = TRUE;
2145 else if(hres == DISP_E_UNKNOWNNAME)
2146 ret = FALSE;
2147 else
2148 return hres;
2150 return stack_push_bool(ctx, ret);
2153 /* ECMA-262 3rd Edition 11.6.1 */
2154 static HRESULT add_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
2156 VARIANT r, l;
2157 HRESULT hres;
2159 hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2160 if(FAILED(hres))
2161 return hres;
2163 hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
2164 if(FAILED(hres)) {
2165 VariantClear(&l);
2166 return hres;
2169 if(V_VT(&l) == VT_BSTR || V_VT(&r) == VT_BSTR) {
2170 BSTR lstr = NULL, rstr = NULL;
2172 if(V_VT(&l) == VT_BSTR)
2173 lstr = V_BSTR(&l);
2174 else
2175 hres = to_string(ctx, &l, ei, &lstr);
2177 if(SUCCEEDED(hres)) {
2178 if(V_VT(&r) == VT_BSTR)
2179 rstr = V_BSTR(&r);
2180 else
2181 hres = to_string(ctx, &r, ei, &rstr);
2184 if(SUCCEEDED(hres)) {
2185 int len1, len2;
2187 len1 = SysStringLen(lstr);
2188 len2 = SysStringLen(rstr);
2190 V_VT(retv) = VT_BSTR;
2191 V_BSTR(retv) = SysAllocStringLen(NULL, len1+len2);
2192 memcpy(V_BSTR(retv), lstr, len1*sizeof(WCHAR));
2193 memcpy(V_BSTR(retv)+len1, rstr, (len2+1)*sizeof(WCHAR));
2196 if(V_VT(&l) != VT_BSTR)
2197 SysFreeString(lstr);
2198 if(V_VT(&r) != VT_BSTR)
2199 SysFreeString(rstr);
2200 }else {
2201 VARIANT nl, nr;
2203 hres = to_number(ctx, &l, ei, &nl);
2204 if(SUCCEEDED(hres)) {
2205 hres = to_number(ctx, &r, ei, &nr);
2206 if(SUCCEEDED(hres))
2207 num_set_val(retv, num_val(&nl) + num_val(&nr));
2211 VariantClear(&r);
2212 VariantClear(&l);
2213 return hres;
2216 /* ECMA-262 3rd Edition 11.6.1 */
2217 static HRESULT interp_add(exec_ctx_t *ctx)
2219 VARIANT *l, *r, ret;
2220 HRESULT hres;
2222 r = stack_pop(ctx);
2223 l = stack_pop(ctx);
2225 TRACE("%s + %s\n", debugstr_variant(l), debugstr_variant(r));
2227 hres = add_eval(ctx->parser->script, l, r, &ctx->ei, &ret);
2228 VariantClear(l);
2229 VariantClear(r);
2230 if(FAILED(hres))
2231 return hres;
2233 return stack_push(ctx, &ret);
2236 /* ECMA-262 3rd Edition 11.6.2 */
2237 static HRESULT interp_sub(exec_ctx_t *ctx)
2239 VARIANT l, r;
2240 HRESULT hres;
2242 TRACE("\n");
2244 hres = stack_pop_number(ctx, &r);
2245 if(FAILED(hres))
2246 return hres;
2248 hres = stack_pop_number(ctx, &l);
2249 if(FAILED(hres))
2250 return hres;
2252 return stack_push_number(ctx, num_val(&l)-num_val(&r));
2255 /* ECMA-262 3rd Edition 11.5.1 */
2256 static HRESULT interp_mul(exec_ctx_t *ctx)
2258 VARIANT l, r;
2259 HRESULT hres;
2261 TRACE("\n");
2263 hres = stack_pop_number(ctx, &r);
2264 if(FAILED(hres))
2265 return hres;
2267 hres = stack_pop_number(ctx, &l);
2268 if(FAILED(hres))
2269 return hres;
2271 return stack_push_number(ctx, num_val(&l)*num_val(&r));
2274 /* ECMA-262 3rd Edition 11.5.2 */
2275 static HRESULT interp_div(exec_ctx_t *ctx)
2277 VARIANT l, r;
2278 HRESULT hres;
2280 TRACE("\n");
2282 hres = stack_pop_number(ctx, &r);
2283 if(FAILED(hres))
2284 return hres;
2286 hres = stack_pop_number(ctx, &l);
2287 if(FAILED(hres))
2288 return hres;
2290 return stack_push_number(ctx, num_val(&l)/num_val(&r));
2293 /* ECMA-262 3rd Edition 11.5.3 */
2294 static HRESULT interp_mod(exec_ctx_t *ctx)
2296 VARIANT l, r;
2297 HRESULT hres;
2299 TRACE("\n");
2301 hres = stack_pop_number(ctx, &r);
2302 if(FAILED(hres))
2303 return hres;
2305 hres = stack_pop_number(ctx, &l);
2306 if(FAILED(hres))
2307 return hres;
2309 return stack_push_number(ctx, fmod(num_val(&l), num_val(&r)));
2312 /* ECMA-262 3rd Edition 11.4.2 */
2313 static HRESULT interp_delete(exec_ctx_t *ctx)
2315 VARIANT *obj_var, *name_var;
2316 IDispatchEx *dispex;
2317 IDispatch *obj;
2318 BSTR name;
2319 BOOL ret;
2320 HRESULT hres;
2322 TRACE("\n");
2324 name_var = stack_pop(ctx);
2325 obj_var = stack_pop(ctx);
2327 hres = to_object(ctx->parser->script, obj_var, &obj);
2328 VariantClear(obj_var);
2329 if(FAILED(hres)) {
2330 VariantClear(name_var);
2331 return hres;
2334 hres = to_string(ctx->parser->script, name_var, &ctx->ei, &name);
2335 VariantClear(name_var);
2336 if(FAILED(hres)) {
2337 IDispatch_Release(obj);
2338 return hres;
2341 hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
2342 if(SUCCEEDED(hres)) {
2343 hres = IDispatchEx_DeleteMemberByName(dispex, name, make_grfdex(ctx->parser->script, fdexNameCaseSensitive));
2344 ret = TRUE;
2345 IDispatchEx_Release(dispex);
2346 }else {
2347 hres = S_OK;
2348 ret = FALSE;
2351 IDispatch_Release(obj);
2352 SysFreeString(name);
2353 if(FAILED(hres))
2354 return hres;
2356 return stack_push_bool(ctx, ret);
2359 /* ECMA-262 3rd Edition 11.4.2 */
2360 static HRESULT interp_delete_ident(exec_ctx_t *ctx)
2362 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2363 IDispatchEx *dispex;
2364 exprval_t exprval;
2365 BOOL ret = FALSE;
2366 HRESULT hres;
2368 TRACE("%s\n", debugstr_w(arg));
2370 hres = identifier_eval(ctx->parser->script, arg, 0, &ctx->ei, &exprval);
2371 if(FAILED(hres))
2372 return hres;
2374 if(exprval.type != EXPRVAL_IDREF) {
2375 FIXME("Unsupported exprval\n");
2376 exprval_release(&exprval);
2377 return E_NOTIMPL;
2380 hres = IDispatch_QueryInterface(exprval.u.idref.disp, &IID_IDispatchEx, (void**)&dispex);
2381 IDispatch_Release(exprval.u.idref.disp);
2382 if(SUCCEEDED(hres)) {
2383 hres = IDispatchEx_DeleteMemberByDispID(dispex, exprval.u.idref.id);
2384 IDispatchEx_Release(dispex);
2385 if(FAILED(hres))
2386 return hres;
2388 ret = TRUE;
2391 return stack_push_bool(ctx, ret);
2394 /* ECMA-262 3rd Edition 11.4.2 */
2395 static HRESULT interp_void(exec_ctx_t *ctx)
2397 VARIANT v;
2399 TRACE("\n");
2401 stack_popn(ctx, 1);
2403 V_VT(&v) = VT_EMPTY;
2404 return stack_push(ctx, &v);
2407 /* ECMA-262 3rd Edition 11.4.3 */
2408 static HRESULT typeof_string(VARIANT *v, const WCHAR **ret)
2410 switch(V_VT(v)) {
2411 case VT_EMPTY:
2412 *ret = undefinedW;
2413 break;
2414 case VT_NULL:
2415 *ret = objectW;
2416 break;
2417 case VT_BOOL:
2418 *ret = booleanW;
2419 break;
2420 case VT_I4:
2421 case VT_R8:
2422 *ret = numberW;
2423 break;
2424 case VT_BSTR:
2425 *ret = stringW;
2426 break;
2427 case VT_DISPATCH: {
2428 jsdisp_t *dispex;
2430 if(V_DISPATCH(v) && (dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(v)))) {
2431 *ret = is_class(dispex, JSCLASS_FUNCTION) ? functionW : objectW;
2432 jsdisp_release(dispex);
2433 }else {
2434 *ret = objectW;
2436 break;
2438 default:
2439 FIXME("unhandled vt %d\n", V_VT(v));
2440 return E_NOTIMPL;
2443 return S_OK;
2446 /* ECMA-262 3rd Edition 11.4.3 */
2447 static HRESULT interp_typeofid(exec_ctx_t *ctx)
2449 const WCHAR *ret;
2450 IDispatch *obj;
2451 VARIANT v;
2452 DISPID id;
2453 HRESULT hres;
2455 static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
2457 TRACE("\n");
2459 obj = stack_pop_objid(ctx, &id);
2460 if(!obj)
2461 return stack_push_string(ctx, undefinedW);
2463 V_VT(&v) = VT_EMPTY;
2464 hres = disp_propget(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/);
2465 IDispatch_Release(obj);
2466 if(FAILED(hres))
2467 return stack_push_string(ctx, unknownW);
2469 hres = typeof_string(&v, &ret);
2470 VariantClear(&v);
2471 if(FAILED(hres))
2472 return hres;
2474 return stack_push_string(ctx, ret);
2477 /* ECMA-262 3rd Edition 11.4.3 */
2478 static HRESULT interp_typeofident(exec_ctx_t *ctx)
2480 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2481 exprval_t exprval;
2482 const WCHAR *ret;
2483 VARIANT v;
2484 HRESULT hres;
2486 TRACE("%s\n", debugstr_w(arg));
2488 hres = identifier_eval(ctx->parser->script, arg, 0, &ctx->ei, &exprval);
2489 if(FAILED(hres))
2490 return hres;
2492 if(exprval.type == EXPRVAL_INVALID) {
2493 hres = stack_push_string(ctx, undefinedW);
2494 exprval_release(&exprval);
2495 return hres;
2498 hres = exprval_to_value(ctx->parser->script, &exprval, &ctx->ei, &v);
2499 exprval_release(&exprval);
2500 if(FAILED(hres))
2501 return hres;
2503 hres = typeof_string(&v, &ret);
2504 VariantClear(&v);
2505 if(FAILED(hres))
2506 return hres;
2508 return stack_push_string(ctx, ret);
2511 /* ECMA-262 3rd Edition 11.4.3 */
2512 static HRESULT interp_typeof(exec_ctx_t *ctx)
2514 const WCHAR *ret;
2515 VARIANT *v;
2516 HRESULT hres;
2518 TRACE("\n");
2520 v = stack_pop(ctx);
2521 hres = typeof_string(v, &ret);
2522 VariantClear(v);
2523 if(FAILED(hres))
2524 return hres;
2526 return stack_push_string(ctx, ret);
2529 /* ECMA-262 3rd Edition 11.4.7 */
2530 static HRESULT interp_minus(exec_ctx_t *ctx)
2532 VARIANT n;
2533 HRESULT hres;
2535 TRACE("\n");
2537 hres = stack_pop_number(ctx, &n);
2538 if(FAILED(hres))
2539 return hres;
2541 return stack_push_number(ctx, -num_val(&n));
2544 /* ECMA-262 3rd Edition 11.4.6 */
2545 static HRESULT interp_tonum(exec_ctx_t *ctx)
2547 VARIANT *v, num;
2548 HRESULT hres;
2550 TRACE("\n");
2552 v = stack_pop(ctx);
2553 hres = to_number(ctx->parser->script, v, &ctx->ei, &num);
2554 VariantClear(v);
2555 if(FAILED(hres))
2556 return hres;
2558 return stack_push(ctx, &num);
2561 /* ECMA-262 3rd Edition 11.3.1 */
2562 static HRESULT interp_postinc(exec_ctx_t *ctx)
2564 const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2565 IDispatch *obj;
2566 DISPID id;
2567 VARIANT v;
2568 HRESULT hres;
2570 TRACE("%d\n", arg);
2572 obj = stack_pop_objid(ctx, &id);
2573 if(!obj)
2574 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2576 hres = disp_propget(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/);
2577 if(SUCCEEDED(hres)) {
2578 VARIANT n, inc;
2580 hres = to_number(ctx->parser->script, &v, &ctx->ei, &n);
2581 if(SUCCEEDED(hres)) {
2582 num_set_val(&inc, num_val(&n)+(double)arg);
2583 hres = disp_propput(ctx->parser->script, obj, id, &inc, &ctx->ei, NULL/*FIXME*/);
2585 if(FAILED(hres))
2586 VariantClear(&v);
2588 IDispatch_Release(obj);
2589 if(FAILED(hres))
2590 return hres;
2592 return stack_push(ctx, &v);
2595 /* ECMA-262 3rd Edition 11.4.4, 11.4.5 */
2596 static HRESULT interp_preinc(exec_ctx_t *ctx)
2598 const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2599 IDispatch *obj;
2600 DISPID id;
2601 VARIANT v;
2602 HRESULT hres;
2604 TRACE("%d\n", arg);
2606 obj = stack_pop_objid(ctx, &id);
2607 if(!obj)
2608 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2610 hres = disp_propget(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/);
2611 if(SUCCEEDED(hres)) {
2612 VARIANT n;
2614 hres = to_number(ctx->parser->script, &v, &ctx->ei, &n);
2615 VariantClear(&v);
2616 if(SUCCEEDED(hres)) {
2617 num_set_val(&v, num_val(&n)+(double)arg);
2618 hres = disp_propput(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/);
2621 IDispatch_Release(obj);
2622 if(FAILED(hres))
2623 return hres;
2625 return stack_push(ctx, &v);
2628 /* ECMA-262 3rd Edition 11.9.3 */
2629 static HRESULT equal_values(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, BOOL *ret)
2631 if(V_VT(lval) == V_VT(rval) || (is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval))))
2632 return equal2_values(lval, rval, ret);
2634 /* FIXME: NULL disps should be handled in more general way */
2635 if(V_VT(lval) == VT_DISPATCH && !V_DISPATCH(lval)) {
2636 VARIANT v;
2637 V_VT(&v) = VT_NULL;
2638 return equal_values(ctx, &v, rval, ei, ret);
2641 if(V_VT(rval) == VT_DISPATCH && !V_DISPATCH(rval)) {
2642 VARIANT v;
2643 V_VT(&v) = VT_NULL;
2644 return equal_values(ctx, lval, &v, ei, ret);
2647 if((V_VT(lval) == VT_NULL && V_VT(rval) == VT_EMPTY) ||
2648 (V_VT(lval) == VT_EMPTY && V_VT(rval) == VT_NULL)) {
2649 *ret = TRUE;
2650 return S_OK;
2653 if(V_VT(lval) == VT_BSTR && is_num_vt(V_VT(rval))) {
2654 VARIANT v;
2655 HRESULT hres;
2657 hres = to_number(ctx, lval, ei, &v);
2658 if(FAILED(hres))
2659 return hres;
2661 return equal_values(ctx, &v, rval, ei, ret);
2664 if(V_VT(rval) == VT_BSTR && is_num_vt(V_VT(lval))) {
2665 VARIANT v;
2666 HRESULT hres;
2668 hres = to_number(ctx, rval, ei, &v);
2669 if(FAILED(hres))
2670 return hres;
2672 return equal_values(ctx, lval, &v, ei, ret);
2675 if(V_VT(rval) == VT_BOOL) {
2676 VARIANT v;
2678 V_VT(&v) = VT_I4;
2679 V_I4(&v) = V_BOOL(rval) ? 1 : 0;
2680 return equal_values(ctx, lval, &v, ei, ret);
2683 if(V_VT(lval) == VT_BOOL) {
2684 VARIANT v;
2686 V_VT(&v) = VT_I4;
2687 V_I4(&v) = V_BOOL(lval) ? 1 : 0;
2688 return equal_values(ctx, &v, rval, ei, ret);
2692 if(V_VT(rval) == VT_DISPATCH && (V_VT(lval) == VT_BSTR || is_num_vt(V_VT(lval)))) {
2693 VARIANT v;
2694 HRESULT hres;
2696 hres = to_primitive(ctx, rval, ei, &v, NO_HINT);
2697 if(FAILED(hres))
2698 return hres;
2700 hres = equal_values(ctx, lval, &v, ei, ret);
2702 VariantClear(&v);
2703 return hres;
2707 if(V_VT(lval) == VT_DISPATCH && (V_VT(rval) == VT_BSTR || is_num_vt(V_VT(rval)))) {
2708 VARIANT v;
2709 HRESULT hres;
2711 hres = to_primitive(ctx, lval, ei, &v, NO_HINT);
2712 if(FAILED(hres))
2713 return hres;
2715 hres = equal_values(ctx, &v, rval, ei, ret);
2717 VariantClear(&v);
2718 return hres;
2722 *ret = FALSE;
2723 return S_OK;
2726 /* ECMA-262 3rd Edition 11.9.1 */
2727 static HRESULT interp_eq(exec_ctx_t *ctx)
2729 VARIANT *l, *r;
2730 BOOL b;
2731 HRESULT hres;
2733 r = stack_pop(ctx);
2734 l = stack_pop(ctx);
2736 TRACE("%s == %s\n", debugstr_variant(l), debugstr_variant(r));
2738 hres = equal_values(ctx->parser->script, l, r, &ctx->ei, &b);
2739 VariantClear(l);
2740 VariantClear(r);
2741 if(FAILED(hres))
2742 return hres;
2744 return stack_push_bool(ctx, b);
2747 /* ECMA-262 3rd Edition 11.9.2 */
2748 static HRESULT interp_neq(exec_ctx_t *ctx)
2750 VARIANT *l, *r;
2751 BOOL b;
2752 HRESULT hres;
2754 r = stack_pop(ctx);
2755 l = stack_pop(ctx);
2757 TRACE("%s != %s\n", debugstr_variant(l), debugstr_variant(r));
2759 hres = equal_values(ctx->parser->script, l, r, &ctx->ei, &b);
2760 VariantClear(l);
2761 VariantClear(r);
2762 if(FAILED(hres))
2763 return hres;
2765 return stack_push_bool(ctx, !b);
2768 /* ECMA-262 3rd Edition 11.9.4 */
2769 static HRESULT interp_eq2(exec_ctx_t *ctx)
2771 VARIANT *l, *r;
2772 BOOL b;
2773 HRESULT hres;
2775 TRACE("\n");
2777 r = stack_pop(ctx);
2778 l = stack_pop(ctx);
2780 hres = equal2_values(r, l, &b);
2781 VariantClear(l);
2782 VariantClear(r);
2783 if(FAILED(hres))
2784 return hres;
2786 return stack_push_bool(ctx, b);
2789 /* ECMA-262 3rd Edition 11.9.5 */
2790 static HRESULT interp_neq2(exec_ctx_t *ctx)
2792 VARIANT *l, *r;
2793 BOOL b;
2794 HRESULT hres;
2796 TRACE("\n");
2798 r = stack_pop(ctx);
2799 l = stack_pop(ctx);
2801 hres = equal2_values(r, l, &b);
2802 VariantClear(l);
2803 VariantClear(r);
2804 if(FAILED(hres))
2805 return hres;
2807 return stack_push_bool(ctx, !b);
2810 /* ECMA-262 3rd Edition 11.8.5 */
2811 static HRESULT less_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL greater, jsexcept_t *ei, BOOL *ret)
2813 VARIANT l, r, ln, rn;
2814 HRESULT hres;
2816 hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2817 if(FAILED(hres))
2818 return hres;
2820 hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
2821 if(FAILED(hres)) {
2822 VariantClear(&l);
2823 return hres;
2826 if(V_VT(&l) == VT_BSTR && V_VT(&r) == VT_BSTR) {
2827 *ret = (strcmpW(V_BSTR(&l), V_BSTR(&r)) < 0) ^ greater;
2828 SysFreeString(V_BSTR(&l));
2829 SysFreeString(V_BSTR(&r));
2830 return S_OK;
2833 hres = to_number(ctx, &l, ei, &ln);
2834 VariantClear(&l);
2835 if(SUCCEEDED(hres))
2836 hres = to_number(ctx, &r, ei, &rn);
2837 VariantClear(&r);
2838 if(FAILED(hres))
2839 return hres;
2841 if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) {
2842 *ret = (V_I4(&ln) < V_I4(&rn)) ^ greater;
2843 }else {
2844 DOUBLE ld = num_val(&ln);
2845 DOUBLE rd = num_val(&rn);
2847 *ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater);
2850 return S_OK;
2853 /* ECMA-262 3rd Edition 11.8.1 */
2854 static HRESULT interp_lt(exec_ctx_t *ctx)
2856 VARIANT *l, *r;
2857 BOOL b;
2858 HRESULT hres;
2860 r = stack_pop(ctx);
2861 l = stack_pop(ctx);
2863 TRACE("%s < %s\n", debugstr_variant(l), debugstr_variant(r));
2865 hres = less_eval(ctx->parser->script, l, r, FALSE, &ctx->ei, &b);
2866 VariantClear(l);
2867 VariantClear(r);
2868 if(FAILED(hres))
2869 return hres;
2871 return stack_push_bool(ctx, b);
2874 /* ECMA-262 3rd Edition 11.8.1 */
2875 static HRESULT interp_lteq(exec_ctx_t *ctx)
2877 VARIANT *l, *r;
2878 BOOL b;
2879 HRESULT hres;
2881 r = stack_pop(ctx);
2882 l = stack_pop(ctx);
2884 TRACE("%s <= %s\n", debugstr_variant(l), debugstr_variant(r));
2886 hres = less_eval(ctx->parser->script, r, l, TRUE, &ctx->ei, &b);
2887 VariantClear(l);
2888 VariantClear(r);
2889 if(FAILED(hres))
2890 return hres;
2892 return stack_push_bool(ctx, b);
2895 /* ECMA-262 3rd Edition 11.8.2 */
2896 static HRESULT interp_gt(exec_ctx_t *ctx)
2898 VARIANT *l, *r;
2899 BOOL b;
2900 HRESULT hres;
2902 r = stack_pop(ctx);
2903 l = stack_pop(ctx);
2905 TRACE("%s > %s\n", debugstr_variant(l), debugstr_variant(r));
2907 hres = less_eval(ctx->parser->script, r, l, FALSE, &ctx->ei, &b);
2908 VariantClear(l);
2909 VariantClear(r);
2910 if(FAILED(hres))
2911 return hres;
2913 return stack_push_bool(ctx, b);
2916 /* ECMA-262 3rd Edition 11.8.4 */
2917 static HRESULT interp_gteq(exec_ctx_t *ctx)
2919 VARIANT *l, *r;
2920 BOOL b;
2921 HRESULT hres;
2923 r = stack_pop(ctx);
2924 l = stack_pop(ctx);
2926 TRACE("%s >= %s\n", debugstr_variant(l), debugstr_variant(r));
2928 hres = less_eval(ctx->parser->script, l, r, TRUE, &ctx->ei, &b);
2929 VariantClear(l);
2930 VariantClear(r);
2931 if(FAILED(hres))
2932 return hres;
2934 return stack_push_bool(ctx, b);
2937 /* ECMA-262 3rd Edition 11.4.8 */
2938 static HRESULT interp_bneg(exec_ctx_t *ctx)
2940 VARIANT *v, r;
2941 INT i;
2942 HRESULT hres;
2944 TRACE("\n");
2946 v = stack_pop(ctx);
2947 hres = to_int32(ctx->parser->script, v, &ctx->ei, &i);
2948 VariantClear(v);
2949 if(FAILED(hres))
2950 return hres;
2952 V_VT(&r) = VT_I4;
2953 V_I4(&r) = ~i;
2954 return stack_push(ctx, &r);
2957 /* ECMA-262 3rd Edition 11.4.9 */
2958 static HRESULT interp_neg(exec_ctx_t *ctx)
2960 VARIANT *v;
2961 VARIANT_BOOL b;
2962 HRESULT hres;
2964 TRACE("\n");
2966 v = stack_pop(ctx);
2967 hres = to_boolean(v, &b);
2968 VariantClear(v);
2969 if(FAILED(hres))
2970 return hres;
2972 return stack_push_bool(ctx, !b);
2975 /* ECMA-262 3rd Edition 11.7.1 */
2976 static HRESULT interp_lshift(exec_ctx_t *ctx)
2978 DWORD r;
2979 INT l;
2980 HRESULT hres;
2982 hres = stack_pop_uint(ctx, &r);
2983 if(FAILED(hres))
2984 return hres;
2986 hres = stack_pop_int(ctx, &l);
2987 if(FAILED(hres))
2988 return hres;
2990 return stack_push_int(ctx, l << (r&0x1f));
2993 /* ECMA-262 3rd Edition 11.7.2 */
2994 static HRESULT interp_rshift(exec_ctx_t *ctx)
2996 DWORD r;
2997 INT l;
2998 HRESULT hres;
3000 hres = stack_pop_uint(ctx, &r);
3001 if(FAILED(hres))
3002 return hres;
3004 hres = stack_pop_int(ctx, &l);
3005 if(FAILED(hres))
3006 return hres;
3008 return stack_push_int(ctx, l >> (r&0x1f));
3011 /* ECMA-262 3rd Edition 11.7.3 */
3012 static HRESULT interp_rshift2(exec_ctx_t *ctx)
3014 DWORD r, l;
3015 HRESULT hres;
3017 hres = stack_pop_uint(ctx, &r);
3018 if(FAILED(hres))
3019 return hres;
3021 hres = stack_pop_uint(ctx, &l);
3022 if(FAILED(hres))
3023 return hres;
3025 return stack_push_int(ctx, l >> (r&0x1f));
3028 /* ECMA-262 3rd Edition 11.13.1 */
3029 static HRESULT interp_assign(exec_ctx_t *ctx)
3031 IDispatch *disp;
3032 DISPID id;
3033 VARIANT *v;
3034 HRESULT hres;
3036 TRACE("\n");
3038 v = stack_pop(ctx);
3039 disp = stack_pop_objid(ctx, &id);
3041 if(!disp)
3042 return throw_reference_error(ctx->parser->script, &ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
3044 hres = disp_propput(ctx->parser->script, disp, id, v, &ctx->ei, NULL/*FIXME*/);
3045 IDispatch_Release(disp);
3046 if(FAILED(hres)) {
3047 VariantClear(v);
3048 return hres;
3051 return stack_push(ctx, v);
3054 static HRESULT interp_undefined(exec_ctx_t *ctx)
3056 VARIANT v;
3058 TRACE("\n");
3060 V_VT(&v) = VT_EMPTY;
3061 return stack_push(ctx, &v);
3064 static HRESULT interp_jmp(exec_ctx_t *ctx)
3066 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
3068 TRACE("\n");
3070 ctx->ip = arg;
3071 return S_OK;
3074 static HRESULT interp_pop(exec_ctx_t *ctx)
3076 TRACE("\n");
3078 stack_popn(ctx, 1);
3079 return S_OK;
3082 static HRESULT interp_ret(exec_ctx_t *ctx)
3084 TRACE("\n");
3086 ctx->ip = -1;
3087 return S_OK;
3090 static HRESULT interp_tree(exec_ctx_t *ctx)
3092 instr_t *instr = ctx->parser->code->instrs+ctx->ip;
3093 exprval_t val;
3094 VARIANT v;
3095 HRESULT hres;
3097 TRACE("\n");
3099 hres = expr_eval(ctx->parser->script, instr->arg1.expr, 0, &ctx->ei, &val);
3100 if(FAILED(hres))
3101 return hres;
3103 hres = exprval_to_value(ctx->parser->script, &val, &ctx->ei, &v);
3104 exprval_release(&val);
3105 if(FAILED(hres))
3106 return hres;
3108 return stack_push(ctx, &v);
3111 typedef HRESULT (*op_func_t)(exec_ctx_t*);
3113 static const op_func_t op_funcs[] = {
3114 #define X(x,a,b,c) interp_##x,
3115 OP_LIST
3116 #undef X
3119 static const unsigned op_move[] = {
3120 #define X(a,x,b,c) x,
3121 OP_LIST
3122 #undef X
3125 static HRESULT interp_expression_eval(script_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3127 exec_ctx_t *exec_ctx = ctx->exec_ctx;
3128 unsigned prev_ip, prev_top;
3129 jsop_t op;
3130 HRESULT hres = S_OK;
3132 TRACE("\n");
3134 prev_top = exec_ctx->top;
3135 prev_ip = exec_ctx->ip;
3136 exec_ctx->ip = expr->instr_off;
3138 while(exec_ctx->ip != -1) {
3139 op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
3140 hres = op_funcs[op](exec_ctx);
3141 if(FAILED(hres))
3142 break;
3143 exec_ctx->ip += op_move[op];
3146 exec_ctx->ip = prev_ip;
3148 if(FAILED(hres)) {
3149 stack_popn(exec_ctx, exec_ctx->top-prev_top);
3150 *ei = exec_ctx->ei;
3151 memset(&exec_ctx->ei, 0, sizeof(exec_ctx->ei));
3152 return hres;
3155 assert(exec_ctx->top == prev_top+1 || ((flags&EXPR_NOVAL) && exec_ctx->top == prev_top));
3157 ret->type = EXPRVAL_VARIANT;
3158 if(exec_ctx->top == prev_top)
3159 V_VT(&ret->u.var) = VT_EMPTY;
3160 else
3161 ret->u.var = *stack_pop(exec_ctx);
3162 return S_OK;
3165 HRESULT compiled_expression_eval(script_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3167 HRESULT hres;
3169 TRACE("\n");
3171 if(expr->instr_off == -1) {
3172 hres = compile_subscript(ctx->exec_ctx->parser, expr, !(flags & EXPR_NOVAL), &expr->instr_off);
3173 if(FAILED(hres))
3174 return hres;
3177 return interp_expression_eval(ctx, expr, flags, ei, ret);