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
20 #include "wine/port.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 {
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 expr->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));
69 }else if(ctx->stack_size == ctx->top) {
72 new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(VARIANT));
78 ctx->stack = new_stack;
82 ctx->stack[ctx->top++] = *v;
86 static HRESULT stack_push_bool(exec_ctx_t *ctx, BOOL b)
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)
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)
109 return stack_push(ctx, &v);
112 static inline HRESULT stack_push_string(exec_ctx_t *ctx, const WCHAR *str)
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)
126 V_VT(&v) = VT_DISPATCH;
127 V_DISPATCH(&v) = disp;
128 hres = stack_push(ctx, &v);
134 return stack_push(ctx, &v);
137 static inline VARIANT *stack_top(exec_ctx_t *ctx)
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)
152 return ctx->stack + --ctx->top;
155 static void stack_popn(exec_ctx_t *ctx, unsigned n)
158 VariantClear(stack_pop(ctx));
161 static HRESULT stack_pop_number(exec_ctx_t *ctx, VARIANT *r)
167 hres = to_number(ctx->parser->script, v, &ctx->ei, r);
172 static HRESULT stack_pop_object(exec_ctx_t *ctx, IDispatch **r)
178 if(V_VT(v) == VT_DISPATCH) {
180 return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_OBJECT_REQUIRED, NULL);
185 hres = to_object(ctx->parser->script, v, r);
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)
219 case EXPRVAL_VARIANT:
220 if(V_VT(&val->u.var) != VT_EMPTY)
221 VariantClear(&val->u.var);
224 if(val->u.idref.disp)
225 IDispatch_Release(val->u.idref.disp);
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;
238 case EXPRVAL_VARIANT:
239 return VariantCopy(ret, &val->u.var);
241 if(!val->u.idref.disp) {
242 FIXME("throw ReferenceError\n");
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);
255 static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
257 if(val->type == EXPRVAL_VARIANT) {
259 V_VT(&val->u.var) = VT_EMPTY;
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) {
272 hres = exprval_to_value(ctx, exprval, ei, &val);
276 hres = to_boolean(&val, b);
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;
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));
300 return E_OUTOFMEMORY;
305 new_scope->obj = obj;
309 new_scope->next = scope;
311 new_scope->next = NULL;
318 static void scope_pop(scope_chain_t **scope)
327 void scope_release(scope_chain_t *scope)
333 scope_release(scope->next);
335 jsdisp_release(scope->obj);
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)
344 ctx = heap_alloc_zero(sizeof(exec_ctx_t));
346 return E_OUTOFMEMORY;
349 ctx->is_global = is_global;
352 ctx->this_obj = this_obj;
353 else if(script_ctx->host_global)
354 ctx->this_obj = script_ctx->host_global;
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;
364 ctx->scope_chain = scope;
371 void exec_release(exec_ctx_t *ctx)
377 scope_release(ctx->scope_chain);
379 jsdisp_release(ctx->var_disp);
381 IDispatch_Release(ctx->this_obj);
382 heap_free(ctx->stack);
386 static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
391 hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
393 TRACE("unsing IDispatch\n");
396 return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
400 hres = IDispatchEx_GetDispID(dispex, name, make_grfdex(ctx, flags|fdexNameCaseSensitive), id);
401 IDispatchEx_Release(dispex);
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;
430 if(!disp1 || !disp2) {
435 hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1);
439 hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2);
441 IUnknown_Release(unk1);
448 hres = IUnknown_QueryInterface(unk1, &IID_IObjectIdentity, (void**)&identity);
449 if(SUCCEEDED(hres)) {
450 hres = IObjectIdentity_IsEqualObject(identity, unk2);
451 IObjectIdentity_Release(identity);
458 IUnknown_Release(unk1);
459 IUnknown_Release(unk2);
463 /* ECMA-262 3rd Edition 11.9.6 */
464 static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
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);
484 *ret = V_I4(lval) == V_I4(rval);
487 *ret = V_R8(lval) == V_R8(rval);
491 *ret = SysStringLen(V_BSTR(rval))?FALSE:TRUE;
492 else if(!V_BSTR(rval))
493 *ret = SysStringLen(V_BSTR(lval))?FALSE:TRUE;
495 *ret = !strcmpW(V_BSTR(lval), V_BSTR(rval));
498 return disp_cmp(V_DISPATCH(lval), V_DISPATCH(rval), ret);
500 *ret = !V_BOOL(lval) == !V_BOOL(rval);
503 FIXME("unimplemented vt %d\n", V_VT(lval));
510 static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
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)) {
521 exprval_set_idref(ret, item->disp, id);
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;
539 exec_ctx_t *prev_ctx;
543 for(func = source->functions; func; func = func->next) {
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);
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);
559 for(var = source->variables; var; var = var->next) {
563 name = SysAllocString(var->identifier);
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);
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));
584 for(stat = source->statement; stat; stat = stat->next) {
585 hres = stat_eval(script, stat, &rt, &tmp);
591 if(rt.type != RT_NORMAL)
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);
609 if(!retv || (!from_eval && rt.type != RT_RETURN))
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;
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);
634 hres = jsdisp_get_id(ctx->global, identifier, 0, &id);
635 if(SUCCEEDED(hres)) {
636 exprval_set_idref(ret, to_disp(ctx->global), id);
640 for(item = ctx->named_items; item; item = item->next) {
641 if((item->flags & SCRIPTITEM_ISVISIBLE) && !strcmpW(item->name, identifier)) {
648 hres = IActiveScriptSite_GetItemInfo(ctx->site, identifier,
649 SCRIPTINFO_IUNKNOWN, &unk, NULL);
651 WARN("GetItemInfo failed: %08x\n", hres);
655 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
656 IUnknown_Release(unk);
658 WARN("object does not implement IDispatch\n");
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);
671 if(lookup_global_members(ctx, identifier, ret))
674 if(flags & fdexNameEnsure) {
675 hres = jsdisp_get_id(ctx->global, identifier, fdexNameEnsure, &id);
679 exprval_set_idref(ret, to_disp(ctx->global), id);
683 ret->type = EXPRVAL_INVALID;
684 ret->u.identifier = SysAllocString(identifier);
685 if(!ret->u.identifier)
686 return E_OUTOFMEMORY;
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;
701 V_VT(&val) = VT_EMPTY;
702 for(iter = stat->stat_list; iter; iter = iter->next) {
703 hres = stat_eval(ctx, iter, rt, &tmp);
709 if(rt->type != RT_NORMAL)
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;
728 for(iter = var_list; iter; iter = iter->next) {
735 hres = expr_eval(ctx, iter->expr, 0, ei, &exprval);
739 hres = exprval_to_value(ctx, &exprval, ei, &val);
740 exprval_release(&exprval);
744 hres = jsdisp_propput_name(ctx->exec_ctx->var_disp, iter->identifier, &val, ei, NULL/*FIXME*/);
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;
761 hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
765 V_VT(ret) = VT_EMPTY;
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)
774 V_VT(ret) = VT_EMPTY;
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;
788 hres = expr_eval(ctx, stat->expr, EXPR_NOVAL, &rt->ei, &exprval);
792 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
793 exprval_release(&exprval);
798 TRACE("= %s\n", debugstr_variant(ret));
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;
812 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
816 hres = exprval_to_boolean(ctx, &exprval, &rt->ei, &b);
817 exprval_release(&exprval);
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);
826 V_VT(ret) = VT_EMPTY;
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;
843 V_VT(&val) = VT_EMPTY;
844 test_expr = !stat->do_while;
848 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
852 hres = exprval_to_boolean(ctx, &exprval, &rt->ei, &b);
853 exprval_release(&exprval);
854 if(FAILED(hres) || !b)
860 hres = stat_eval(ctx, stat->statement, rt, &tmp);
867 if(rt->type == RT_CONTINUE)
868 rt->type = RT_NORMAL;
869 if(rt->type != RT_NORMAL)
878 if(rt->type == RT_BREAK)
879 rt->type = RT_NORMAL;
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;
896 if(stat->variable_list) {
897 hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
900 }else if(stat->begin_expr) {
901 hres = expr_eval(ctx, stat->begin_expr, 0, &rt->ei, &exprval);
905 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
906 exprval_release(&exprval);
913 V_VT(&retv) = VT_EMPTY;
917 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
921 hres = exprval_to_boolean(ctx, &exprval, &rt->ei, &b);
922 exprval_release(&exprval);
923 if(FAILED(hres) || !b)
927 hres = stat_eval(ctx, stat->statement, rt, &tmp);
934 if(rt->type == RT_CONTINUE)
935 rt->type = RT_NORMAL;
936 else if(rt->type != RT_NORMAL)
940 hres = expr_eval(ctx, stat->end_expr, 0, &rt->ei, &exprval);
944 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
945 exprval_release(&exprval);
958 if(rt->type == RT_BREAK)
959 rt->type = RT_NORMAL;
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;
983 hres = variable_list_eval(ctx, stat->variable, &rt->ei);
988 hres = expr_eval(ctx, stat->in_expr, 0, &rt->ei, &exprval);
992 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
993 exprval_release(&exprval);
997 if(V_VT(&val) != VT_DISPATCH) {
998 TRACE("in vt %d\n", V_VT(&val));
1000 V_VT(ret) = VT_EMPTY;
1004 hres = IDispatch_QueryInterface(V_DISPATCH(&val), &IID_IDispatchEx, (void**)&in_obj);
1005 IDispatch_Release(V_DISPATCH(&val));
1007 TRACE("Object doesn't support IDispatchEx\n");
1008 V_VT(ret) = VT_EMPTY;
1012 V_VT(&retv) = VT_EMPTY;
1015 identifier = SysAllocString(stat->variable->identifier);
1018 hres = IDispatchEx_GetNextDispID(in_obj, fdexEnumDefault, id, &id);
1019 if(FAILED(hres) || hres == S_FALSE)
1022 hres = IDispatchEx_GetMemberName(in_obj, id, &str);
1026 TRACE("iter %s\n", debugstr_w(str));
1028 if(stat->variable) {
1029 hres = identifier_eval(ctx, identifier, 0, NULL, &exprval);
1031 switch(stat->expr->type) {
1033 hres = array_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
1036 hres = identifier_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
1039 hres = member_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
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);
1055 hres = stat_eval(ctx, stat->statement, rt, &tmp);
1059 VariantClear(&retv);
1062 if(rt->type == RT_CONTINUE)
1063 rt->type = RT_NORMAL;
1064 else if(rt->type != RT_NORMAL)
1068 SysFreeString(identifier);
1069 IDispatchEx_Release(in_obj);
1071 VariantClear(&retv);
1075 if(rt->type == RT_BREAK)
1076 rt->type = RT_NORMAL;
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;
1089 if(stat->identifier) {
1090 FIXME("indentifier not implemented\n");
1094 rt->type = RT_CONTINUE;
1095 V_VT(ret) = VT_EMPTY;
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;
1106 if(stat->identifier) {
1107 FIXME("indentifier not implemented\n");
1111 rt->type = RT_BREAK;
1112 V_VT(ret) = VT_EMPTY;
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;
1127 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
1131 hres = exprval_to_value(ctx, &exprval, &rt->ei, ret);
1132 exprval_release(&exprval);
1136 V_VT(ret) = VT_EMPTY;
1139 TRACE("= %s\n", debugstr_variant(ret));
1140 rt->type = RT_RETURN;
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;
1156 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
1160 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
1161 exprval_release(&exprval);
1165 hres = to_object(ctx, &val, &disp);
1170 obj = iface_to_jsdisp((IUnknown*)disp);
1171 IDispatch_Release(disp);
1173 FIXME("disp id not jsdisp\n");
1177 hres = scope_push(ctx->exec_ctx->scope_chain, obj, &ctx->exec_ctx->scope_chain);
1178 jsdisp_release(obj);
1182 hres = stat_eval(ctx, stat->statement, rt, ret);
1184 scope_pop(&ctx->exec_ctx->scope_chain);
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)
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;
1208 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
1212 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
1213 exprval_release(&exprval);
1217 for(iter = stat->case_list; iter; iter = iter->next) {
1219 default_clausule = iter;
1223 hres = expr_eval(ctx, iter->expr, 0, &rt->ei, &exprval);
1227 hres = exprval_to_value(ctx, &exprval, &rt->ei, &cval);
1228 exprval_release(&exprval);
1232 hres = equal2_values(&val, &cval, &b);
1233 VariantClear(&cval);
1234 if(FAILED(hres) || b)
1243 iter = default_clausule;
1245 V_VT(&val) = VT_EMPTY;
1249 for(stat_iter = iter->stat; stat_iter; stat_iter = stat_iter->next) {
1250 hres = stat_eval(ctx, stat_iter, rt, &tmp);
1257 if(rt->type != RT_NORMAL)
1267 if(rt->type == RT_BREAK)
1268 rt->type = RT_NORMAL;
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;
1284 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
1288 hres = exprval_to_value(ctx, &exprval, &rt->ei, &val);
1289 exprval_release(&exprval);
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)
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);
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;
1357 hres = stat_eval(ctx, stat->try_statement, rt, &val);
1359 TRACE("EXCEPTION\n");
1360 if(!stat->catch_block)
1363 hres = catch_eval(ctx, stat->catch_block, rt, &val);
1368 if(stat->finally_statement) {
1370 hres = stat_eval(ctx, stat->finally_statement, rt, &val);
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;
1389 hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain,
1390 expr->src_str, expr->src_len, &dispex);
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;
1403 VARIANT member, val;
1406 IDispatch *obj = NULL;
1411 hres = expr_eval(ctx, expr->expression1, 0, ei, &exprval);
1415 hres = exprval_to_value(ctx, &exprval, ei, &member);
1416 exprval_release(&exprval);
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);
1431 VariantClear(&member);
1432 if(SUCCEEDED(hres)) {
1433 hres = to_string(ctx, &val, ei, &str);
1435 if(SUCCEEDED(hres)) {
1436 hres = disp_get_id(ctx, obj, str, fdexNameEnsure, &id);
1441 exprval_set_idref(ret, obj, id);
1443 IDispatch_Release(obj);
1449 /* ECMA-262 3rd Edition 11.2.1 */
1450 static HRESULT interp_array(exec_ctx_t *ctx)
1460 namev = stack_pop(ctx);
1462 hres = stack_pop_object(ctx, &obj);
1464 VariantClear(namev);
1468 hres = to_string(ctx->parser->script, namev, &ctx->ei, &name);
1469 VariantClear(namev);
1471 IDispatch_Release(obj);
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;
1483 IDispatch_Release(obj);
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;
1503 hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
1507 hres = exprval_to_value(ctx, &exprval, ei, &member);
1508 exprval_release(&exprval);
1512 hres = to_object(ctx, &member, &obj);
1513 VariantClear(&member);
1517 str = SysAllocString(expr->identifier);
1519 IDispatch_Release(obj);
1520 return E_OUTOFMEMORY;
1523 hres = disp_get_id(ctx, obj, str, fdexNameEnsure, &id);
1526 exprval_set_idref(ret, obj, id);
1528 IDispatch_Release(obj);
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;
1543 hres = stack_pop_object(ctx, &obj);
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;
1555 IDispatch_Release(obj);
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;
1574 namev = stack_pop(ctx);
1575 objv = stack_pop(ctx);
1577 hres = to_object(ctx->parser->script, objv, &obj);
1579 if(SUCCEEDED(hres)) {
1580 hres = to_string(ctx->parser->script, namev, &ctx->ei, &name);
1582 IDispatch_Release(obj);
1584 VariantClear(namev);
1588 hres = disp_get_id(ctx->parser->script, obj, name, arg, &id);
1589 SysFreeString(name);
1591 IDispatch_Release(obj);
1592 if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
1594 id = JS_E_INVALID_PROPERTY;
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)
1613 disp = stack_topn_objid(ctx, 0, &id);
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*/);
1621 return stack_push(ctx, &v);
1624 static void jsstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, DISPPARAMS *dp)
1629 dp->cArgs = arg_cnt;
1630 dp->rgdispidNamedArgs = NULL;
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;
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*/);
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;
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*/);
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;
1712 TRACE("%d %d\n", argn, do_ret);
1714 obj = stack_topn_objid(ctx, argn, &id);
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*/);
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)
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;
1750 identifier = SysAllocString(expr->identifier);
1752 return E_OUTOFMEMORY;
1754 hres = identifier_eval(ctx, identifier, fdexNameEnsure, ei, ret);
1756 SysFreeString(identifier);
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;
1768 TRACE("%s\n", debugstr_w(arg));
1770 hres = identifier_eval(ctx->parser->script, arg, 0, &ctx->ei, &exprval);
1774 hres = exprval_to_value(ctx->parser->script, &exprval, &ctx->ei, &v);
1775 exprval_release(&exprval);
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;
1790 TRACE("%s %x\n", debugstr_w(arg), flags);
1792 hres = identifier_eval(ctx->parser->script, arg, flags, &ctx->ei, &exprval);
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)
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;
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;
1845 TRACE("%lf\n", 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;
1858 TRACE("%s\n", debugstr_w(str));
1861 V_BSTR(&v) = SysAllocString(str);
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;
1877 TRACE("%s %x\n", debugstr_w(source), flags);
1879 hres = create_regexp(ctx->parser->script, source, strlenW(source), flags, ®exp);
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;
1898 hres = create_array(ctx->parser->script, arg, &array);
1905 hres = jsdisp_propput_idx(array, i, v, &ctx->ei, NULL/*FIXME*/);
1908 jsdisp_release(array);
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)
1926 hres = create_object(ctx->parser->script, NULL, &obj);
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;
1942 TRACE("%s\n", debugstr_w(name));
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*/);
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;
1963 hres = to_boolean(stack_top(ctx), &b);
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;
1985 hres = to_boolean(stack_top(ctx), &b);
1998 /* ECMA-262 3rd Edition 11.10 */
1999 static HRESULT interp_or(exec_ctx_t *ctx)
2006 hres = stack_pop_int(ctx, &r);
2010 hres = stack_pop_int(ctx, &l);
2014 return stack_push_int(ctx, l|r);
2017 /* ECMA-262 3rd Edition 11.10 */
2018 static HRESULT interp_xor(exec_ctx_t *ctx)
2025 hres = stack_pop_int(ctx, &r);
2029 hres = stack_pop_int(ctx, &l);
2033 return stack_push_int(ctx, l^r);
2036 /* ECMA-262 3rd Edition 11.10 */
2037 static HRESULT interp_and(exec_ctx_t *ctx)
2044 hres = stack_pop_int(ctx, &r);
2048 hres = stack_pop_int(ctx, &l);
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;
2063 static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
2066 if(V_VT(v) != VT_DISPATCH || !V_DISPATCH(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));
2074 FIXME("non-jsdisp objects not supported\n");
2078 if(is_class(obj, JSCLASS_FUNCTION)) {
2079 hres = jsdisp_propget_name(obj, prototypeW, &prot, &ctx->ei, NULL/*FIXME*/);
2081 hres = throw_type_error(ctx->parser->script, &ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
2083 jsdisp_release(obj);
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);
2099 jsdisp_release(tmp);
2101 FIXME("prototype is not an object\n");
2105 VariantClear(&prot);
2110 return stack_push_bool(ctx, ret);
2113 /* ECMA-262 3rd Edition 11.8.7 */
2114 static HRESULT interp_in(exec_ctx_t *ctx)
2124 obj = stack_pop(ctx);
2127 if(V_VT(obj) != VT_DISPATCH || !V_DISPATCH(obj)) {
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);
2136 IDispatch_Release(V_DISPATCH(obj));
2140 hres = disp_get_id(ctx->parser->script, V_DISPATCH(obj), str, 0, &id);
2141 IDispatch_Release(V_DISPATCH(obj));
2145 else if(hres == DISP_E_UNKNOWNNAME)
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)
2159 hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2163 hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
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)
2175 hres = to_string(ctx, &l, ei, &lstr);
2177 if(SUCCEEDED(hres)) {
2178 if(V_VT(&r) == VT_BSTR)
2181 hres = to_string(ctx, &r, ei, &rstr);
2184 if(SUCCEEDED(hres)) {
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);
2203 hres = to_number(ctx, &l, ei, &nl);
2204 if(SUCCEEDED(hres)) {
2205 hres = to_number(ctx, &r, ei, &nr);
2207 num_set_val(retv, num_val(&nl) + num_val(&nr));
2216 /* ECMA-262 3rd Edition 11.6.1 */
2217 static HRESULT interp_add(exec_ctx_t *ctx)
2219 VARIANT *l, *r, ret;
2225 TRACE("%s + %s\n", debugstr_variant(l), debugstr_variant(r));
2227 hres = add_eval(ctx->parser->script, l, r, &ctx->ei, &ret);
2233 return stack_push(ctx, &ret);
2236 /* ECMA-262 3rd Edition 11.6.2 */
2237 static HRESULT interp_sub(exec_ctx_t *ctx)
2244 hres = stack_pop_number(ctx, &r);
2248 hres = stack_pop_number(ctx, &l);
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)
2263 hres = stack_pop_number(ctx, &r);
2267 hres = stack_pop_number(ctx, &l);
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)
2282 hres = stack_pop_number(ctx, &r);
2286 hres = stack_pop_number(ctx, &l);
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)
2301 hres = stack_pop_number(ctx, &r);
2305 hres = stack_pop_number(ctx, &l);
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;
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);
2330 VariantClear(name_var);
2334 hres = to_string(ctx->parser->script, name_var, &ctx->ei, &name);
2335 VariantClear(name_var);
2337 IDispatch_Release(obj);
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));
2345 IDispatchEx_Release(dispex);
2351 IDispatch_Release(obj);
2352 SysFreeString(name);
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;
2368 TRACE("%s\n", debugstr_w(arg));
2370 hres = identifier_eval(ctx->parser->script, arg, 0, &ctx->ei, &exprval);
2374 if(exprval.type != EXPRVAL_IDREF) {
2375 FIXME("Unsupported exprval\n");
2376 exprval_release(&exprval);
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);
2391 return stack_push_bool(ctx, ret);
2394 /* ECMA-262 3rd Edition 11.4.2 */
2395 static HRESULT interp_void(exec_ctx_t *ctx)
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)
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);
2439 FIXME("unhandled vt %d\n", V_VT(v));
2446 /* ECMA-262 3rd Edition 11.4.3 */
2447 static HRESULT interp_typeofid(exec_ctx_t *ctx)
2455 static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
2459 obj = stack_pop_objid(ctx, &id);
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);
2467 return stack_push_string(ctx, unknownW);
2469 hres = typeof_string(&v, &ret);
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;
2486 TRACE("%s\n", debugstr_w(arg));
2488 hres = identifier_eval(ctx->parser->script, arg, 0, &ctx->ei, &exprval);
2492 if(exprval.type == EXPRVAL_INVALID) {
2493 hres = stack_push_string(ctx, undefinedW);
2494 exprval_release(&exprval);
2498 hres = exprval_to_value(ctx->parser->script, &exprval, &ctx->ei, &v);
2499 exprval_release(&exprval);
2503 hres = typeof_string(&v, &ret);
2508 return stack_push_string(ctx, ret);
2511 /* ECMA-262 3rd Edition 11.4.3 */
2512 static HRESULT interp_typeof(exec_ctx_t *ctx)
2521 hres = typeof_string(v, &ret);
2526 return stack_push_string(ctx, ret);
2529 /* ECMA-262 3rd Edition 11.4.7 */
2530 static HRESULT interp_minus(exec_ctx_t *ctx)
2537 hres = stack_pop_number(ctx, &n);
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)
2553 hres = to_number(ctx->parser->script, v, &ctx->ei, &num);
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;
2572 obj = stack_pop_objid(ctx, &id);
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)) {
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*/);
2588 IDispatch_Release(obj);
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;
2606 obj = stack_pop_objid(ctx, &id);
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)) {
2614 hres = to_number(ctx->parser->script, &v, &ctx->ei, &n);
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);
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)) {
2638 return equal_values(ctx, &v, rval, ei, ret);
2641 if(V_VT(rval) == VT_DISPATCH && !V_DISPATCH(rval)) {
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)) {
2653 if(V_VT(lval) == VT_BSTR && is_num_vt(V_VT(rval))) {
2657 hres = to_number(ctx, lval, ei, &v);
2661 return equal_values(ctx, &v, rval, ei, ret);
2664 if(V_VT(rval) == VT_BSTR && is_num_vt(V_VT(lval))) {
2668 hres = to_number(ctx, rval, ei, &v);
2672 return equal_values(ctx, lval, &v, ei, ret);
2675 if(V_VT(rval) == VT_BOOL) {
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) {
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)))) {
2696 hres = to_primitive(ctx, rval, ei, &v, NO_HINT);
2700 hres = equal_values(ctx, lval, &v, ei, ret);
2707 if(V_VT(lval) == VT_DISPATCH && (V_VT(rval) == VT_BSTR || is_num_vt(V_VT(rval)))) {
2711 hres = to_primitive(ctx, lval, ei, &v, NO_HINT);
2715 hres = equal_values(ctx, &v, rval, ei, ret);
2726 /* ECMA-262 3rd Edition 11.9.1 */
2727 static HRESULT interp_eq(exec_ctx_t *ctx)
2736 TRACE("%s == %s\n", debugstr_variant(l), debugstr_variant(r));
2738 hres = equal_values(ctx->parser->script, l, r, &ctx->ei, &b);
2744 return stack_push_bool(ctx, b);
2747 /* ECMA-262 3rd Edition 11.9.2 */
2748 static HRESULT interp_neq(exec_ctx_t *ctx)
2757 TRACE("%s != %s\n", debugstr_variant(l), debugstr_variant(r));
2759 hres = equal_values(ctx->parser->script, l, r, &ctx->ei, &b);
2765 return stack_push_bool(ctx, !b);
2768 /* ECMA-262 3rd Edition 11.9.4 */
2769 static HRESULT interp_eq2(exec_ctx_t *ctx)
2780 hres = equal2_values(r, l, &b);
2786 return stack_push_bool(ctx, b);
2789 /* ECMA-262 3rd Edition 11.9.5 */
2790 static HRESULT interp_neq2(exec_ctx_t *ctx)
2801 hres = equal2_values(r, l, &b);
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;
2816 hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2820 hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
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));
2833 hres = to_number(ctx, &l, ei, &ln);
2836 hres = to_number(ctx, &r, ei, &rn);
2841 if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) {
2842 *ret = (V_I4(&ln) < V_I4(&rn)) ^ greater;
2844 DOUBLE ld = num_val(&ln);
2845 DOUBLE rd = num_val(&rn);
2847 *ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater);
2853 /* ECMA-262 3rd Edition 11.8.1 */
2854 static HRESULT interp_lt(exec_ctx_t *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);
2871 return stack_push_bool(ctx, b);
2874 /* ECMA-262 3rd Edition 11.8.1 */
2875 static HRESULT interp_lteq(exec_ctx_t *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);
2892 return stack_push_bool(ctx, b);
2895 /* ECMA-262 3rd Edition 11.8.2 */
2896 static HRESULT interp_gt(exec_ctx_t *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);
2913 return stack_push_bool(ctx, b);
2916 /* ECMA-262 3rd Edition 11.8.4 */
2917 static HRESULT interp_gteq(exec_ctx_t *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);
2934 return stack_push_bool(ctx, b);
2937 /* ECMA-262 3rd Edition 11.4.8 */
2938 static HRESULT interp_bneg(exec_ctx_t *ctx)
2947 hres = to_int32(ctx->parser->script, v, &ctx->ei, &i);
2954 return stack_push(ctx, &r);
2957 /* ECMA-262 3rd Edition 11.4.9 */
2958 static HRESULT interp_neg(exec_ctx_t *ctx)
2967 hres = to_boolean(v, &b);
2972 return stack_push_bool(ctx, !b);
2975 /* ECMA-262 3rd Edition 11.7.1 */
2976 static HRESULT interp_lshift(exec_ctx_t *ctx)
2982 hres = stack_pop_uint(ctx, &r);
2986 hres = stack_pop_int(ctx, &l);
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)
3000 hres = stack_pop_uint(ctx, &r);
3004 hres = stack_pop_int(ctx, &l);
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)
3017 hres = stack_pop_uint(ctx, &r);
3021 hres = stack_pop_uint(ctx, &l);
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)
3039 disp = stack_pop_objid(ctx, &id);
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);
3051 return stack_push(ctx, v);
3054 static HRESULT interp_undefined(exec_ctx_t *ctx)
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;
3074 static HRESULT interp_pop(exec_ctx_t *ctx)
3082 static HRESULT interp_ret(exec_ctx_t *ctx)
3090 static HRESULT interp_tree(exec_ctx_t *ctx)
3092 instr_t *instr = ctx->parser->code->instrs+ctx->ip;
3099 hres = expr_eval(ctx->parser->script, instr->arg1.expr, 0, &ctx->ei, &val);
3103 hres = exprval_to_value(ctx->parser->script, &val, &ctx->ei, &v);
3104 exprval_release(&val);
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,
3119 static const unsigned op_move[] = {
3120 #define X(a,x,b,c) 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;
3130 HRESULT hres = S_OK;
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);
3143 exec_ctx->ip += op_move[op];
3146 exec_ctx->ip = prev_ip;
3149 stack_popn(exec_ctx, exec_ctx->top-prev_top);
3151 memset(&exec_ctx->ei, 0, sizeof(exec_ctx->ei));
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;
3161 ret->u.var = *stack_pop(exec_ctx);
3165 HRESULT compiled_expression_eval(script_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
3171 hres = compile_subscript(ctx->exec_ctx->parser, expr, !(flags & EXPR_NOVAL), &expr->instr_off);
3175 if(expr->eval == compiled_expression_eval)
3176 expr->eval = interp_expression_eval;
3178 return expr->eval(ctx, expr, flags, ei, ret);