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 static const WCHAR booleanW[] = {'b','o','o','l','e','a','n',0};
33 static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0};
34 static const WCHAR numberW[] = {'n','u','m','b','e','r',0};
35 static const WCHAR objectW[] = {'o','b','j','e','c','t',0};
36 static const WCHAR stringW[] = {'s','t','r','i','n','g',0};
37 static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
38 static const WCHAR unknownW[] = {'u','n','k','n','o','w','n',0};
40 struct _return_type_t {
44 struct _except_frame_t {
53 static HRESULT stack_push(exec_ctx_t *ctx, VARIANT *v)
55 if(!ctx->stack_size) {
56 ctx->stack = heap_alloc(16*sizeof(VARIANT));
60 }else if(ctx->stack_size == ctx->top) {
63 new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(VARIANT));
69 ctx->stack = new_stack;
73 ctx->stack[ctx->top++] = *v;
77 static HRESULT stack_push_bool(exec_ctx_t *ctx, BOOL b)
82 V_BOOL(&v) = b ? VARIANT_TRUE : VARIANT_FALSE;
83 return stack_push(ctx, &v);
86 static inline HRESULT stack_push_number(exec_ctx_t *ctx, double number)
90 num_set_val(&v, number);
91 return stack_push(ctx, &v);
94 static inline HRESULT stack_push_int(exec_ctx_t *ctx, INT n)
100 return stack_push(ctx, &v);
103 static inline HRESULT stack_push_string(exec_ctx_t *ctx, const WCHAR *str)
108 V_BSTR(&v) = SysAllocString(str);
109 return V_BSTR(&v) ? stack_push(ctx, &v) : E_OUTOFMEMORY;
112 static HRESULT stack_push_objid(exec_ctx_t *ctx, IDispatch *disp, DISPID id)
117 V_VT(&v) = VT_DISPATCH;
118 V_DISPATCH(&v) = disp;
119 hres = stack_push(ctx, &v);
125 return stack_push(ctx, &v);
128 static inline VARIANT *stack_top(exec_ctx_t *ctx)
131 return ctx->stack + ctx->top-1;
134 static inline VARIANT *stack_topn(exec_ctx_t *ctx, unsigned n)
136 assert(ctx->top > n);
137 return ctx->stack + ctx->top-1-n;
140 static inline VARIANT *stack_pop(exec_ctx_t *ctx)
143 return ctx->stack + --ctx->top;
146 static void stack_popn(exec_ctx_t *ctx, unsigned n)
149 VariantClear(stack_pop(ctx));
152 static HRESULT stack_pop_number(exec_ctx_t *ctx, VARIANT *r)
158 hres = to_number(ctx->parser->script, v, ctx->ei, r);
163 static HRESULT stack_pop_object(exec_ctx_t *ctx, IDispatch **r)
169 if(V_VT(v) == VT_DISPATCH) {
171 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_REQUIRED, NULL);
176 hres = to_object(ctx->parser->script, v, r);
181 static inline HRESULT stack_pop_int(exec_ctx_t *ctx, INT *r)
183 return to_int32(ctx->parser->script, stack_pop(ctx), ctx->ei, r);
186 static inline HRESULT stack_pop_uint(exec_ctx_t *ctx, DWORD *r)
188 return to_uint32(ctx->parser->script, stack_pop(ctx), ctx->ei, r);
191 static inline IDispatch *stack_pop_objid(exec_ctx_t *ctx, DISPID *id)
193 assert(V_VT(stack_top(ctx)) == VT_INT && V_VT(stack_topn(ctx, 1)) == VT_DISPATCH);
195 *id = V_INT(stack_pop(ctx));
196 return V_DISPATCH(stack_pop(ctx));
199 static inline IDispatch *stack_topn_objid(exec_ctx_t *ctx, unsigned n, DISPID *id)
201 assert(V_VT(stack_topn(ctx, n)) == VT_INT && V_VT(stack_topn(ctx, n+1)) == VT_DISPATCH);
203 *id = V_INT(stack_topn(ctx, n));
204 return V_DISPATCH(stack_topn(ctx, n+1));
207 static void exprval_release(exprval_t *val)
210 case EXPRVAL_VARIANT:
211 if(V_VT(&val->u.var) != VT_EMPTY)
212 VariantClear(&val->u.var);
215 if(val->u.idref.disp)
216 IDispatch_Release(val->u.idref.disp);
218 case EXPRVAL_INVALID:
223 /* ECMA-262 3rd Edition 8.7.1 */
224 static HRESULT exprval_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
226 V_VT(ret) = VT_EMPTY;
229 case EXPRVAL_VARIANT:
230 return VariantCopy(ret, &val->u.var);
232 if(!val->u.idref.disp) {
233 FIXME("throw ReferenceError\n");
237 return disp_propget(ctx, val->u.idref.disp, val->u.idref.id, ret, ei, NULL/*FIXME*/);
238 case EXPRVAL_INVALID:
242 ERR("type %d\n", val->type);
246 static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
248 if(val->type == EXPRVAL_VARIANT) {
250 V_VT(&val->u.var) = VT_EMPTY;
254 return exprval_value(ctx, val, ei, ret);
257 static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id)
259 val->type = EXPRVAL_IDREF;
260 val->u.idref.disp = disp;
261 val->u.idref.id = id;
264 IDispatch_AddRef(disp);
267 HRESULT scope_push(scope_chain_t *scope, jsdisp_t *obj, scope_chain_t **ret)
269 scope_chain_t *new_scope;
271 new_scope = heap_alloc(sizeof(scope_chain_t));
273 return E_OUTOFMEMORY;
278 new_scope->obj = obj;
282 new_scope->next = scope;
284 new_scope->next = NULL;
291 static void scope_pop(scope_chain_t **scope)
300 void scope_release(scope_chain_t *scope)
306 scope_release(scope->next);
308 jsdisp_release(scope->obj);
312 HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, jsdisp_t *var_disp,
313 scope_chain_t *scope, BOOL is_global, exec_ctx_t **ret)
317 ctx = heap_alloc_zero(sizeof(exec_ctx_t));
319 return E_OUTOFMEMORY;
322 ctx->is_global = is_global;
325 ctx->this_obj = this_obj;
326 else if(script_ctx->host_global)
327 ctx->this_obj = script_ctx->host_global;
329 ctx->this_obj = to_disp(script_ctx->global);
330 IDispatch_AddRef(ctx->this_obj);
332 jsdisp_addref(var_disp);
333 ctx->var_disp = var_disp;
337 ctx->scope_chain = scope;
344 void exec_release(exec_ctx_t *ctx)
350 scope_release(ctx->scope_chain);
352 jsdisp_release(ctx->var_disp);
354 IDispatch_Release(ctx->this_obj);
355 heap_free(ctx->stack);
359 static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
364 hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
366 TRACE("unsing IDispatch\n");
369 return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
373 hres = IDispatchEx_GetDispID(dispex, name, make_grfdex(ctx, flags|fdexNameCaseSensitive), id);
374 IDispatchEx_Release(dispex);
378 static inline BOOL is_null(const VARIANT *v)
380 return V_VT(v) == VT_NULL || (V_VT(v) == VT_DISPATCH && !V_DISPATCH(v));
383 static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret)
385 IObjectIdentity *identity;
386 IUnknown *unk1, *unk2;
394 if(!disp1 || !disp2) {
399 hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1);
403 hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2);
405 IUnknown_Release(unk1);
412 hres = IUnknown_QueryInterface(unk1, &IID_IObjectIdentity, (void**)&identity);
413 if(SUCCEEDED(hres)) {
414 hres = IObjectIdentity_IsEqualObject(identity, unk2);
415 IObjectIdentity_Release(identity);
422 IUnknown_Release(unk1);
423 IUnknown_Release(unk2);
427 /* ECMA-262 3rd Edition 11.9.6 */
428 static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
432 if(V_VT(lval) != V_VT(rval)) {
433 if(is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval)))
434 *ret = num_val(lval) == num_val(rval);
435 else if(is_null(lval))
436 *ret = is_null(rval);
448 *ret = V_I4(lval) == V_I4(rval);
451 *ret = V_R8(lval) == V_R8(rval);
455 *ret = SysStringLen(V_BSTR(rval))?FALSE:TRUE;
456 else if(!V_BSTR(rval))
457 *ret = SysStringLen(V_BSTR(lval))?FALSE:TRUE;
459 *ret = !strcmpW(V_BSTR(lval), V_BSTR(rval));
462 return disp_cmp(V_DISPATCH(lval), V_DISPATCH(rval), ret);
464 *ret = !V_BOOL(lval) == !V_BOOL(rval);
467 FIXME("unimplemented vt %d\n", V_VT(lval));
474 static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
480 for(item = ctx->named_items; item; item = item->next) {
481 if(item->flags & SCRIPTITEM_GLOBALMEMBERS) {
482 hres = disp_get_id(ctx, item->disp, identifier, 0, &id);
483 if(SUCCEEDED(hres)) {
485 exprval_set_idref(ret, item->disp, id);
494 /* ECMA-262 3rd Edition 10.1.4 */
495 static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, DWORD flags, jsexcept_t *ei, exprval_t *ret)
497 scope_chain_t *scope;
502 TRACE("%s\n", debugstr_w(identifier));
504 for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) {
505 hres = jsdisp_get_id(scope->obj, identifier, 0, &id);
506 if(SUCCEEDED(hres)) {
507 exprval_set_idref(ret, to_disp(scope->obj), id);
512 hres = jsdisp_get_id(ctx->global, identifier, 0, &id);
513 if(SUCCEEDED(hres)) {
514 exprval_set_idref(ret, to_disp(ctx->global), id);
518 for(item = ctx->named_items; item; item = item->next) {
519 if((item->flags & SCRIPTITEM_ISVISIBLE) && !strcmpW(item->name, identifier)) {
526 hres = IActiveScriptSite_GetItemInfo(ctx->site, identifier,
527 SCRIPTINFO_IUNKNOWN, &unk, NULL);
529 WARN("GetItemInfo failed: %08x\n", hres);
533 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
534 IUnknown_Release(unk);
536 WARN("object does not implement IDispatch\n");
541 ret->type = EXPRVAL_VARIANT;
542 V_VT(&ret->u.var) = VT_DISPATCH;
543 V_DISPATCH(&ret->u.var) = item->disp;
544 IDispatch_AddRef(item->disp);
549 if(lookup_global_members(ctx, identifier, ret))
552 if(flags & fdexNameEnsure) {
553 hres = jsdisp_get_id(ctx->global, identifier, fdexNameEnsure, &id);
557 exprval_set_idref(ret, to_disp(ctx->global), id);
561 ret->type = EXPRVAL_INVALID;
565 /* ECMA-262 3rd Edition 12.2 */
566 static HRESULT interp_var_set(exec_ctx_t *ctx)
568 const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
572 TRACE("%s\n", debugstr_w(name));
575 hres = jsdisp_propput_name(ctx->var_disp, name, v, ctx->ei, NULL/*FIXME*/);
580 /* ECMA-262 3rd Edition 12.6.4 */
581 static HRESULT interp_forin(exec_ctx_t *ctx)
583 const HRESULT arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
584 IDispatch *var_obj, *obj = NULL;
593 val = stack_pop(ctx);
595 assert(V_VT(stack_top(ctx)) == VT_I4);
596 id = V_I4(stack_top(ctx));
598 var_obj = stack_topn_objid(ctx, 1, &var_id);
600 FIXME("invalid ref\n");
605 if(V_VT(stack_topn(ctx, 3)) == VT_DISPATCH)
606 obj = V_DISPATCH(stack_topn(ctx, 3));
609 hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
610 if(SUCCEEDED(hres)) {
611 hres = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, id, &id);
613 hres = IDispatchEx_GetMemberName(dispex, id, &name);
614 IDispatchEx_Release(dispex);
620 TRACE("No IDispatchEx\n");
629 V_I4(stack_top(ctx)) = id;
633 hres = disp_propput(ctx->parser->script, var_obj, var_id, &v, ctx->ei, NULL/*FIXME*/);
642 return stack_push(ctx, val);
647 /* ECMA-262 3rd Edition 12.7 */
648 HRESULT continue_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
650 branch_statement_t *stat = (branch_statement_t*)_stat;
652 assert(stat->identifier != NULL);
653 FIXME("identifier not implemented\n");
657 /* ECMA-262 3rd Edition 12.8 */
658 HRESULT break_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
660 branch_statement_t *stat = (branch_statement_t*)_stat;
662 assert(stat->identifier != NULL);
663 FIXME("identifier not implemented\n");
667 /* ECMA-262 3rd Edition 12.10 */
668 HRESULT interp_push_scope(exec_ctx_t *ctx)
678 hres = to_object(ctx->parser->script, v, &disp);
683 obj = to_jsdisp(disp);
685 IDispatch_Release(disp);
686 FIXME("disp is not jsdisp\n");
690 hres = scope_push(ctx->scope_chain, obj, &ctx->scope_chain);
695 /* ECMA-262 3rd Edition 12.10 */
696 HRESULT interp_pop_scope(exec_ctx_t *ctx)
700 scope_pop(&ctx->scope_chain);
704 /* ECMA-262 3rd Edition 12.12 */
705 HRESULT interp_label(exec_ctx_t *ctx)
711 /* ECMA-262 3rd Edition 12.13 */
712 static HRESULT interp_case(exec_ctx_t *ctx)
714 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
722 hres = equal2_values(stack_top(ctx), v, &b);
736 /* ECMA-262 3rd Edition 12.13 */
737 static HRESULT interp_throw(exec_ctx_t *ctx)
741 ctx->rt->ei.var = *stack_pop(ctx);
742 return DISP_E_EXCEPTION;
745 static HRESULT interp_throw_ref(exec_ctx_t *ctx)
747 const HRESULT arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
749 TRACE("%08x\n", arg);
751 return throw_reference_error(ctx->parser->script, ctx->ei, arg, NULL);
754 static HRESULT interp_throw_type(exec_ctx_t *ctx)
756 const HRESULT hres = ctx->parser->code->instrs[ctx->ip].arg1.uint;
757 const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg2.str;
759 TRACE("%08x %s\n", hres, debugstr_w(str));
761 return throw_type_error(ctx->parser->script, ctx->ei, hres, str);
764 /* ECMA-262 3rd Edition 12.14 */
765 static HRESULT interp_push_except(exec_ctx_t *ctx)
767 const unsigned arg1 = ctx->parser->code->instrs[ctx->ip].arg1.uint;
768 const BSTR arg2 = ctx->parser->code->instrs[ctx->ip].arg2.bstr;
769 except_frame_t *except;
774 stack_top = ctx->top;
779 hres = stack_push_bool(ctx, TRUE);
782 hres = stack_push_bool(ctx, TRUE);
787 except = heap_alloc(sizeof(*except));
789 return E_OUTOFMEMORY;
791 except->stack_top = stack_top;
792 except->scope = ctx->scope_chain;
793 except->catch_off = arg1;
794 except->ident = arg2;
795 except->next = ctx->except_frame;
796 ctx->except_frame = except;
800 /* ECMA-262 3rd Edition 12.14 */
801 static HRESULT interp_pop_except(exec_ctx_t *ctx)
803 except_frame_t *except;
807 except = ctx->except_frame;
808 assert(except != NULL);
810 ctx->except_frame = except->next;
815 /* ECMA-262 3rd Edition 12.14 */
816 static HRESULT interp_end_finally(exec_ctx_t *ctx)
824 assert(V_VT(stack_top(ctx)) == VT_BOOL);
825 if(!V_BOOL(stack_top(ctx))) {
826 TRACE("passing exception\n");
830 ctx->rt->ei.var = *stack_pop(ctx);
831 return DISP_E_EXCEPTION;
835 return stack_push(ctx, v);
838 /* ECMA-262 3rd Edition 13 */
839 static HRESULT interp_func(exec_ctx_t *ctx)
841 function_expression_t *expr = ctx->parser->code->instrs[ctx->ip].arg1.func;
848 hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain,
849 expr->src_str, expr->src_len, &dispex);
853 var_set_jsdisp(&v, dispex);
854 return stack_push(ctx, &v);
857 /* ECMA-262 3rd Edition 11.2.1 */
858 static HRESULT interp_array(exec_ctx_t *ctx)
868 namev = stack_pop(ctx);
870 hres = stack_pop_object(ctx, &obj);
876 hres = to_string(ctx->parser->script, namev, ctx->ei, &name);
879 IDispatch_Release(obj);
883 hres = disp_get_id(ctx->parser->script, obj, name, 0, &id);
885 if(SUCCEEDED(hres)) {
886 hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
887 }else if(hres == DISP_E_UNKNOWNNAME) {
891 IDispatch_Release(obj);
895 return stack_push(ctx, &v);
898 /* ECMA-262 3rd Edition 11.2.1 */
899 static HRESULT interp_member(exec_ctx_t *ctx)
901 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
909 hres = stack_pop_object(ctx, &obj);
913 hres = disp_get_id(ctx->parser->script, obj, arg, 0, &id);
914 if(SUCCEEDED(hres)) {
916 hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
917 }else if(hres == DISP_E_UNKNOWNNAME) {
921 IDispatch_Release(obj);
925 return stack_push(ctx, &v);
928 /* ECMA-262 3rd Edition 11.2.1 */
929 static HRESULT interp_memberid(exec_ctx_t *ctx)
931 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
932 VARIANT *objv, *namev;
940 namev = stack_pop(ctx);
941 objv = stack_pop(ctx);
943 hres = to_object(ctx->parser->script, objv, &obj);
945 if(SUCCEEDED(hres)) {
946 hres = to_string(ctx->parser->script, namev, ctx->ei, &name);
948 IDispatch_Release(obj);
954 hres = disp_get_id(ctx->parser->script, obj, name, arg, &id);
957 IDispatch_Release(obj);
958 if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
960 id = JS_E_INVALID_PROPERTY;
966 return stack_push_objid(ctx, obj, id);
969 /* ECMA-262 3rd Edition 11.2.1 */
970 static HRESULT interp_refval(exec_ctx_t *ctx)
979 disp = stack_topn_objid(ctx, 0, &id);
981 return throw_reference_error(ctx->parser->script, ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
983 hres = disp_propget(ctx->parser->script, disp, id, &v, ctx->ei, NULL/*FIXME*/);
987 return stack_push(ctx, &v);
990 static void jsstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, DISPPARAMS *dp)
996 dp->rgdispidNamedArgs = NULL;
999 assert(ctx->top >= arg_cnt);
1001 for(i=1; i*2 <= arg_cnt; i++) {
1002 tmp = ctx->stack[ctx->top-i];
1003 ctx->stack[ctx->top-i] = ctx->stack[ctx->top-arg_cnt+i-1];
1004 ctx->stack[ctx->top-arg_cnt+i-1] = tmp;
1007 dp->rgvarg = ctx->stack + ctx->top-arg_cnt;
1010 /* ECMA-262 3rd Edition 11.2.2 */
1011 static HRESULT interp_new(exec_ctx_t *ctx)
1013 const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1020 constr = stack_topn(ctx, arg);
1022 /* NOTE: Should use to_object here */
1024 if(V_VT(constr) == VT_NULL)
1025 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1026 else if(V_VT(constr) != VT_DISPATCH)
1027 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_ACTION, NULL);
1028 else if(!V_DISPATCH(constr))
1029 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1031 jsstack_to_dp(ctx, arg, &dp);
1032 hres = disp_call(ctx->parser->script, V_DISPATCH(constr), DISPID_VALUE,
1033 DISPATCH_CONSTRUCT, &dp, &v, ctx->ei, NULL/*FIXME*/);
1037 stack_popn(ctx, arg+1);
1038 return stack_push(ctx, &v);
1041 /* ECMA-262 3rd Edition 11.2.3 */
1042 static HRESULT interp_call(exec_ctx_t *ctx)
1044 const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1045 const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1050 TRACE("%d %d\n", argn, do_ret);
1052 objv = stack_topn(ctx, argn);
1053 if(V_VT(objv) != VT_DISPATCH)
1054 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1056 jsstack_to_dp(ctx, argn, &dp);
1057 hres = disp_call(ctx->parser->script, V_DISPATCH(objv), DISPID_VALUE, DISPATCH_METHOD, &dp,
1058 do_ret ? &v : NULL, ctx->ei, NULL/*FIXME*/);
1062 stack_popn(ctx, argn+1);
1063 return do_ret ? stack_push(ctx, &v) : S_OK;
1067 /* ECMA-262 3rd Edition 11.2.3 */
1068 static HRESULT interp_call_member(exec_ctx_t *ctx)
1070 const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1071 const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1078 TRACE("%d %d\n", argn, do_ret);
1080 obj = stack_topn_objid(ctx, argn, &id);
1082 return throw_type_error(ctx->parser->script, ctx->ei, id, NULL);
1084 jsstack_to_dp(ctx, argn, &dp);
1085 hres = disp_call(ctx->parser->script, obj, id, DISPATCH_METHOD, &dp, do_ret ? &v : NULL, ctx->ei, NULL/*FIXME*/);
1089 stack_popn(ctx, argn+2);
1090 return do_ret ? stack_push(ctx, &v) : S_OK;
1094 /* ECMA-262 3rd Edition 11.1.1 */
1095 static HRESULT interp_this(exec_ctx_t *ctx)
1101 V_VT(&v) = VT_DISPATCH;
1102 V_DISPATCH(&v) = ctx->this_obj;
1103 IDispatch_AddRef(ctx->this_obj);
1104 return stack_push(ctx, &v);
1107 /* ECMA-262 3rd Edition 10.1.4 */
1108 static HRESULT interp_ident(exec_ctx_t *ctx)
1110 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1115 TRACE("%s\n", debugstr_w(arg));
1117 hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
1121 if(exprval.type == EXPRVAL_INVALID)
1122 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_UNDEFINED_VARIABLE, arg);
1124 hres = exprval_to_value(ctx->parser->script, &exprval, ctx->ei, &v);
1125 exprval_release(&exprval);
1129 return stack_push(ctx, &v);
1132 /* ECMA-262 3rd Edition 10.1.4 */
1133 static HRESULT interp_identid(exec_ctx_t *ctx)
1135 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1136 const unsigned flags = ctx->parser->code->instrs[ctx->ip].arg2.uint;
1140 TRACE("%s %x\n", debugstr_w(arg), flags);
1142 hres = identifier_eval(ctx->parser->script, arg, flags, ctx->ei, &exprval);
1146 if(exprval.type != EXPRVAL_IDREF) {
1147 WARN("invalid ref\n");
1148 exprval_release(&exprval);
1149 return stack_push_objid(ctx, NULL, JS_E_OBJECT_EXPECTED);
1152 return stack_push_objid(ctx, exprval.u.idref.disp, exprval.u.idref.id);
1155 /* ECMA-262 3rd Edition 7.8.1 */
1156 static HRESULT interp_null(exec_ctx_t *ctx)
1163 return stack_push(ctx, &v);
1166 /* ECMA-262 3rd Edition 7.8.2 */
1167 static HRESULT interp_bool(exec_ctx_t *ctx)
1169 const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1171 TRACE("%s\n", arg ? "true" : "false");
1173 return stack_push_bool(ctx, arg);
1176 /* ECMA-262 3rd Edition 7.8.3 */
1177 static HRESULT interp_int(exec_ctx_t *ctx)
1179 const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1186 return stack_push(ctx, &v);
1189 /* ECMA-262 3rd Edition 7.8.3 */
1190 static HRESULT interp_double(exec_ctx_t *ctx)
1192 const double arg = *ctx->parser->code->instrs[ctx->ip].arg1.dbl;
1195 TRACE("%lf\n", arg);
1199 return stack_push(ctx, &v);
1202 /* ECMA-262 3rd Edition 7.8.4 */
1203 static HRESULT interp_str(exec_ctx_t *ctx)
1205 const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg1.str;
1208 TRACE("%s\n", debugstr_w(str));
1211 V_BSTR(&v) = SysAllocString(str);
1213 return E_OUTOFMEMORY;
1215 return stack_push(ctx, &v);
1218 /* ECMA-262 3rd Edition 7.8 */
1219 static HRESULT interp_regexp(exec_ctx_t *ctx)
1221 const WCHAR *source = ctx->parser->code->instrs[ctx->ip].arg1.str;
1222 const LONG flags = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1227 TRACE("%s %x\n", debugstr_w(source), flags);
1229 hres = create_regexp(ctx->parser->script, source, strlenW(source), flags, ®exp);
1233 var_set_jsdisp(&v, regexp);
1234 return stack_push(ctx, &v);
1237 /* ECMA-262 3rd Edition 11.1.4 */
1238 static HRESULT interp_carray(exec_ctx_t *ctx)
1240 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1248 hres = create_array(ctx->parser->script, arg, &array);
1255 hres = jsdisp_propput_idx(array, i, v, ctx->ei, NULL/*FIXME*/);
1258 jsdisp_release(array);
1263 var_set_jsdisp(&r, array);
1264 return stack_push(ctx, &r);
1267 /* ECMA-262 3rd Edition 11.1.5 */
1268 HRESULT interp_new_obj(exec_ctx_t *ctx)
1276 hres = create_object(ctx->parser->script, NULL, &obj);
1280 var_set_jsdisp(&v, obj);
1281 return stack_push(ctx, &v);
1284 /* ECMA-262 3rd Edition 11.1.5 */
1285 HRESULT interp_obj_prop(exec_ctx_t *ctx)
1287 const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1292 TRACE("%s\n", debugstr_w(name));
1296 assert(V_VT(stack_top(ctx)) == VT_DISPATCH);
1297 obj = as_jsdisp(V_DISPATCH(stack_top(ctx)));
1299 hres = jsdisp_propput_name(obj, name, v, ctx->ei, NULL/*FIXME*/);
1304 /* ECMA-262 3rd Edition 11.11 */
1305 static HRESULT interp_cnd_nz(exec_ctx_t *ctx)
1307 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1313 hres = to_boolean(stack_top(ctx), &b);
1326 /* ECMA-262 3rd Edition 11.11 */
1327 static HRESULT interp_cnd_z(exec_ctx_t *ctx)
1329 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1335 hres = to_boolean(stack_top(ctx), &b);
1348 /* ECMA-262 3rd Edition 11.10 */
1349 static HRESULT interp_or(exec_ctx_t *ctx)
1356 hres = stack_pop_int(ctx, &r);
1360 hres = stack_pop_int(ctx, &l);
1364 return stack_push_int(ctx, l|r);
1367 /* ECMA-262 3rd Edition 11.10 */
1368 static HRESULT interp_xor(exec_ctx_t *ctx)
1375 hres = stack_pop_int(ctx, &r);
1379 hres = stack_pop_int(ctx, &l);
1383 return stack_push_int(ctx, l^r);
1386 /* ECMA-262 3rd Edition 11.10 */
1387 static HRESULT interp_and(exec_ctx_t *ctx)
1394 hres = stack_pop_int(ctx, &r);
1398 hres = stack_pop_int(ctx, &l);
1402 return stack_push_int(ctx, l&r);
1405 /* ECMA-262 3rd Edition 11.8.6 */
1406 static HRESULT interp_instanceof(exec_ctx_t *ctx)
1408 jsdisp_t *obj, *iter, *tmp = NULL;
1413 static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
1416 if(V_VT(v) != VT_DISPATCH || !V_DISPATCH(v)) {
1418 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
1421 obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
1422 IDispatch_Release(V_DISPATCH(v));
1424 FIXME("non-jsdisp objects not supported\n");
1428 if(is_class(obj, JSCLASS_FUNCTION)) {
1429 hres = jsdisp_propget_name(obj, prototypeW, &prot, ctx->ei, NULL/*FIXME*/);
1431 hres = throw_type_error(ctx->parser->script, ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
1433 jsdisp_release(obj);
1439 if(V_VT(&prot) == VT_DISPATCH) {
1440 if(V_VT(v) == VT_DISPATCH)
1441 tmp = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
1442 for(iter = tmp; !ret && iter; iter = iter->prototype) {
1443 hres = disp_cmp(V_DISPATCH(&prot), to_disp(iter), &ret);
1449 jsdisp_release(tmp);
1451 FIXME("prototype is not an object\n");
1455 VariantClear(&prot);
1460 return stack_push_bool(ctx, ret);
1463 /* ECMA-262 3rd Edition 11.8.7 */
1464 static HRESULT interp_in(exec_ctx_t *ctx)
1474 obj = stack_pop(ctx);
1477 if(V_VT(obj) != VT_DISPATCH || !V_DISPATCH(obj)) {
1480 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1483 hres = to_string(ctx->parser->script, v, ctx->ei, &str);
1486 IDispatch_Release(V_DISPATCH(obj));
1490 hres = disp_get_id(ctx->parser->script, V_DISPATCH(obj), str, 0, &id);
1491 IDispatch_Release(V_DISPATCH(obj));
1495 else if(hres == DISP_E_UNKNOWNNAME)
1500 return stack_push_bool(ctx, ret);
1503 /* ECMA-262 3rd Edition 11.6.1 */
1504 static HRESULT add_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
1509 hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
1513 hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
1519 if(V_VT(&l) == VT_BSTR || V_VT(&r) == VT_BSTR) {
1520 BSTR lstr = NULL, rstr = NULL;
1522 if(V_VT(&l) == VT_BSTR)
1525 hres = to_string(ctx, &l, ei, &lstr);
1527 if(SUCCEEDED(hres)) {
1528 if(V_VT(&r) == VT_BSTR)
1531 hres = to_string(ctx, &r, ei, &rstr);
1534 if(SUCCEEDED(hres)) {
1537 len1 = SysStringLen(lstr);
1538 len2 = SysStringLen(rstr);
1540 V_VT(retv) = VT_BSTR;
1541 V_BSTR(retv) = SysAllocStringLen(NULL, len1+len2);
1542 memcpy(V_BSTR(retv), lstr, len1*sizeof(WCHAR));
1543 memcpy(V_BSTR(retv)+len1, rstr, (len2+1)*sizeof(WCHAR));
1546 if(V_VT(&l) != VT_BSTR)
1547 SysFreeString(lstr);
1548 if(V_VT(&r) != VT_BSTR)
1549 SysFreeString(rstr);
1553 hres = to_number(ctx, &l, ei, &nl);
1554 if(SUCCEEDED(hres)) {
1555 hres = to_number(ctx, &r, ei, &nr);
1557 num_set_val(retv, num_val(&nl) + num_val(&nr));
1566 /* ECMA-262 3rd Edition 11.6.1 */
1567 static HRESULT interp_add(exec_ctx_t *ctx)
1569 VARIANT *l, *r, ret;
1575 TRACE("%s + %s\n", debugstr_variant(l), debugstr_variant(r));
1577 hres = add_eval(ctx->parser->script, l, r, ctx->ei, &ret);
1583 return stack_push(ctx, &ret);
1586 /* ECMA-262 3rd Edition 11.6.2 */
1587 static HRESULT interp_sub(exec_ctx_t *ctx)
1594 hres = stack_pop_number(ctx, &r);
1598 hres = stack_pop_number(ctx, &l);
1602 return stack_push_number(ctx, num_val(&l)-num_val(&r));
1605 /* ECMA-262 3rd Edition 11.5.1 */
1606 static HRESULT interp_mul(exec_ctx_t *ctx)
1613 hres = stack_pop_number(ctx, &r);
1617 hres = stack_pop_number(ctx, &l);
1621 return stack_push_number(ctx, num_val(&l)*num_val(&r));
1624 /* ECMA-262 3rd Edition 11.5.2 */
1625 static HRESULT interp_div(exec_ctx_t *ctx)
1632 hres = stack_pop_number(ctx, &r);
1636 hres = stack_pop_number(ctx, &l);
1640 return stack_push_number(ctx, num_val(&l)/num_val(&r));
1643 /* ECMA-262 3rd Edition 11.5.3 */
1644 static HRESULT interp_mod(exec_ctx_t *ctx)
1651 hres = stack_pop_number(ctx, &r);
1655 hres = stack_pop_number(ctx, &l);
1659 return stack_push_number(ctx, fmod(num_val(&l), num_val(&r)));
1662 /* ECMA-262 3rd Edition 11.4.2 */
1663 static HRESULT interp_delete(exec_ctx_t *ctx)
1665 VARIANT *obj_var, *name_var;
1666 IDispatchEx *dispex;
1674 name_var = stack_pop(ctx);
1675 obj_var = stack_pop(ctx);
1677 hres = to_object(ctx->parser->script, obj_var, &obj);
1678 VariantClear(obj_var);
1680 VariantClear(name_var);
1684 hres = to_string(ctx->parser->script, name_var, ctx->ei, &name);
1685 VariantClear(name_var);
1687 IDispatch_Release(obj);
1691 hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
1692 if(SUCCEEDED(hres)) {
1693 hres = IDispatchEx_DeleteMemberByName(dispex, name, make_grfdex(ctx->parser->script, fdexNameCaseSensitive));
1695 IDispatchEx_Release(dispex);
1701 IDispatch_Release(obj);
1702 SysFreeString(name);
1706 return stack_push_bool(ctx, ret);
1709 /* ECMA-262 3rd Edition 11.4.2 */
1710 static HRESULT interp_delete_ident(exec_ctx_t *ctx)
1712 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1713 IDispatchEx *dispex;
1718 TRACE("%s\n", debugstr_w(arg));
1720 hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
1724 if(exprval.type != EXPRVAL_IDREF) {
1725 FIXME("Unsupported exprval\n");
1726 exprval_release(&exprval);
1730 hres = IDispatch_QueryInterface(exprval.u.idref.disp, &IID_IDispatchEx, (void**)&dispex);
1731 IDispatch_Release(exprval.u.idref.disp);
1732 if(SUCCEEDED(hres)) {
1733 hres = IDispatchEx_DeleteMemberByDispID(dispex, exprval.u.idref.id);
1734 IDispatchEx_Release(dispex);
1741 return stack_push_bool(ctx, ret);
1744 /* ECMA-262 3rd Edition 11.4.2 */
1745 static HRESULT interp_void(exec_ctx_t *ctx)
1753 V_VT(&v) = VT_EMPTY;
1754 return stack_push(ctx, &v);
1757 /* ECMA-262 3rd Edition 11.4.3 */
1758 static HRESULT typeof_string(VARIANT *v, const WCHAR **ret)
1780 if(V_DISPATCH(v) && (dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(v)))) {
1781 *ret = is_class(dispex, JSCLASS_FUNCTION) ? functionW : objectW;
1782 jsdisp_release(dispex);
1789 FIXME("unhandled vt %d\n", V_VT(v));
1796 /* ECMA-262 3rd Edition 11.4.3 */
1797 static HRESULT interp_typeofid(exec_ctx_t *ctx)
1805 static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
1809 obj = stack_pop_objid(ctx, &id);
1811 return stack_push_string(ctx, undefinedW);
1813 V_VT(&v) = VT_EMPTY;
1814 hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1815 IDispatch_Release(obj);
1817 return stack_push_string(ctx, unknownW);
1819 hres = typeof_string(&v, &ret);
1824 return stack_push_string(ctx, ret);
1827 /* ECMA-262 3rd Edition 11.4.3 */
1828 static HRESULT interp_typeofident(exec_ctx_t *ctx)
1830 const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1836 TRACE("%s\n", debugstr_w(arg));
1838 hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
1842 if(exprval.type == EXPRVAL_INVALID) {
1843 hres = stack_push_string(ctx, undefinedW);
1844 exprval_release(&exprval);
1848 hres = exprval_to_value(ctx->parser->script, &exprval, ctx->ei, &v);
1849 exprval_release(&exprval);
1853 hres = typeof_string(&v, &ret);
1858 return stack_push_string(ctx, ret);
1861 /* ECMA-262 3rd Edition 11.4.3 */
1862 static HRESULT interp_typeof(exec_ctx_t *ctx)
1871 hres = typeof_string(v, &ret);
1876 return stack_push_string(ctx, ret);
1879 /* ECMA-262 3rd Edition 11.4.7 */
1880 static HRESULT interp_minus(exec_ctx_t *ctx)
1887 hres = stack_pop_number(ctx, &n);
1891 return stack_push_number(ctx, -num_val(&n));
1894 /* ECMA-262 3rd Edition 11.4.6 */
1895 static HRESULT interp_tonum(exec_ctx_t *ctx)
1903 hres = to_number(ctx->parser->script, v, ctx->ei, &num);
1908 return stack_push(ctx, &num);
1911 /* ECMA-262 3rd Edition 11.3.1 */
1912 static HRESULT interp_postinc(exec_ctx_t *ctx)
1914 const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1922 obj = stack_pop_objid(ctx, &id);
1924 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1926 hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1927 if(SUCCEEDED(hres)) {
1930 hres = to_number(ctx->parser->script, &v, ctx->ei, &n);
1931 if(SUCCEEDED(hres)) {
1932 num_set_val(&inc, num_val(&n)+(double)arg);
1933 hres = disp_propput(ctx->parser->script, obj, id, &inc, ctx->ei, NULL/*FIXME*/);
1938 IDispatch_Release(obj);
1942 return stack_push(ctx, &v);
1945 /* ECMA-262 3rd Edition 11.4.4, 11.4.5 */
1946 static HRESULT interp_preinc(exec_ctx_t *ctx)
1948 const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1956 obj = stack_pop_objid(ctx, &id);
1958 return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1960 hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1961 if(SUCCEEDED(hres)) {
1964 hres = to_number(ctx->parser->script, &v, ctx->ei, &n);
1966 if(SUCCEEDED(hres)) {
1967 num_set_val(&v, num_val(&n)+(double)arg);
1968 hres = disp_propput(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1971 IDispatch_Release(obj);
1975 return stack_push(ctx, &v);
1978 /* ECMA-262 3rd Edition 11.9.3 */
1979 static HRESULT equal_values(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, BOOL *ret)
1981 if(V_VT(lval) == V_VT(rval) || (is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval))))
1982 return equal2_values(lval, rval, ret);
1984 /* FIXME: NULL disps should be handled in more general way */
1985 if(V_VT(lval) == VT_DISPATCH && !V_DISPATCH(lval)) {
1988 return equal_values(ctx, &v, rval, ei, ret);
1991 if(V_VT(rval) == VT_DISPATCH && !V_DISPATCH(rval)) {
1994 return equal_values(ctx, lval, &v, ei, ret);
1997 if((V_VT(lval) == VT_NULL && V_VT(rval) == VT_EMPTY) ||
1998 (V_VT(lval) == VT_EMPTY && V_VT(rval) == VT_NULL)) {
2003 if(V_VT(lval) == VT_BSTR && is_num_vt(V_VT(rval))) {
2007 hres = to_number(ctx, lval, ei, &v);
2011 return equal_values(ctx, &v, rval, ei, ret);
2014 if(V_VT(rval) == VT_BSTR && is_num_vt(V_VT(lval))) {
2018 hres = to_number(ctx, rval, ei, &v);
2022 return equal_values(ctx, lval, &v, ei, ret);
2025 if(V_VT(rval) == VT_BOOL) {
2029 V_I4(&v) = V_BOOL(rval) ? 1 : 0;
2030 return equal_values(ctx, lval, &v, ei, ret);
2033 if(V_VT(lval) == VT_BOOL) {
2037 V_I4(&v) = V_BOOL(lval) ? 1 : 0;
2038 return equal_values(ctx, &v, rval, ei, ret);
2042 if(V_VT(rval) == VT_DISPATCH && (V_VT(lval) == VT_BSTR || is_num_vt(V_VT(lval)))) {
2046 hres = to_primitive(ctx, rval, ei, &v, NO_HINT);
2050 hres = equal_values(ctx, lval, &v, ei, ret);
2057 if(V_VT(lval) == VT_DISPATCH && (V_VT(rval) == VT_BSTR || is_num_vt(V_VT(rval)))) {
2061 hres = to_primitive(ctx, lval, ei, &v, NO_HINT);
2065 hres = equal_values(ctx, &v, rval, ei, ret);
2076 /* ECMA-262 3rd Edition 11.9.1 */
2077 static HRESULT interp_eq(exec_ctx_t *ctx)
2086 TRACE("%s == %s\n", debugstr_variant(l), debugstr_variant(r));
2088 hres = equal_values(ctx->parser->script, l, r, ctx->ei, &b);
2094 return stack_push_bool(ctx, b);
2097 /* ECMA-262 3rd Edition 11.9.2 */
2098 static HRESULT interp_neq(exec_ctx_t *ctx)
2107 TRACE("%s != %s\n", debugstr_variant(l), debugstr_variant(r));
2109 hres = equal_values(ctx->parser->script, l, r, ctx->ei, &b);
2115 return stack_push_bool(ctx, !b);
2118 /* ECMA-262 3rd Edition 11.9.4 */
2119 static HRESULT interp_eq2(exec_ctx_t *ctx)
2130 hres = equal2_values(r, l, &b);
2136 return stack_push_bool(ctx, b);
2139 /* ECMA-262 3rd Edition 11.9.5 */
2140 static HRESULT interp_neq2(exec_ctx_t *ctx)
2151 hres = equal2_values(r, l, &b);
2157 return stack_push_bool(ctx, !b);
2160 /* ECMA-262 3rd Edition 11.8.5 */
2161 static HRESULT less_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL greater, jsexcept_t *ei, BOOL *ret)
2163 VARIANT l, r, ln, rn;
2166 hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2170 hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
2176 if(V_VT(&l) == VT_BSTR && V_VT(&r) == VT_BSTR) {
2177 *ret = (strcmpW(V_BSTR(&l), V_BSTR(&r)) < 0) ^ greater;
2178 SysFreeString(V_BSTR(&l));
2179 SysFreeString(V_BSTR(&r));
2183 hres = to_number(ctx, &l, ei, &ln);
2186 hres = to_number(ctx, &r, ei, &rn);
2191 if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) {
2192 *ret = (V_I4(&ln) < V_I4(&rn)) ^ greater;
2194 DOUBLE ld = num_val(&ln);
2195 DOUBLE rd = num_val(&rn);
2197 *ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater);
2203 /* ECMA-262 3rd Edition 11.8.1 */
2204 static HRESULT interp_lt(exec_ctx_t *ctx)
2213 TRACE("%s < %s\n", debugstr_variant(l), debugstr_variant(r));
2215 hres = less_eval(ctx->parser->script, l, r, FALSE, ctx->ei, &b);
2221 return stack_push_bool(ctx, b);
2224 /* ECMA-262 3rd Edition 11.8.1 */
2225 static HRESULT interp_lteq(exec_ctx_t *ctx)
2234 TRACE("%s <= %s\n", debugstr_variant(l), debugstr_variant(r));
2236 hres = less_eval(ctx->parser->script, r, l, TRUE, ctx->ei, &b);
2242 return stack_push_bool(ctx, b);
2245 /* ECMA-262 3rd Edition 11.8.2 */
2246 static HRESULT interp_gt(exec_ctx_t *ctx)
2255 TRACE("%s > %s\n", debugstr_variant(l), debugstr_variant(r));
2257 hres = less_eval(ctx->parser->script, r, l, FALSE, ctx->ei, &b);
2263 return stack_push_bool(ctx, b);
2266 /* ECMA-262 3rd Edition 11.8.4 */
2267 static HRESULT interp_gteq(exec_ctx_t *ctx)
2276 TRACE("%s >= %s\n", debugstr_variant(l), debugstr_variant(r));
2278 hres = less_eval(ctx->parser->script, l, r, TRUE, ctx->ei, &b);
2284 return stack_push_bool(ctx, b);
2287 /* ECMA-262 3rd Edition 11.4.8 */
2288 static HRESULT interp_bneg(exec_ctx_t *ctx)
2297 hres = to_int32(ctx->parser->script, v, ctx->ei, &i);
2304 return stack_push(ctx, &r);
2307 /* ECMA-262 3rd Edition 11.4.9 */
2308 static HRESULT interp_neg(exec_ctx_t *ctx)
2317 hres = to_boolean(v, &b);
2322 return stack_push_bool(ctx, !b);
2325 /* ECMA-262 3rd Edition 11.7.1 */
2326 static HRESULT interp_lshift(exec_ctx_t *ctx)
2332 hres = stack_pop_uint(ctx, &r);
2336 hres = stack_pop_int(ctx, &l);
2340 return stack_push_int(ctx, l << (r&0x1f));
2343 /* ECMA-262 3rd Edition 11.7.2 */
2344 static HRESULT interp_rshift(exec_ctx_t *ctx)
2350 hres = stack_pop_uint(ctx, &r);
2354 hres = stack_pop_int(ctx, &l);
2358 return stack_push_int(ctx, l >> (r&0x1f));
2361 /* ECMA-262 3rd Edition 11.7.3 */
2362 static HRESULT interp_rshift2(exec_ctx_t *ctx)
2367 hres = stack_pop_uint(ctx, &r);
2371 hres = stack_pop_uint(ctx, &l);
2375 return stack_push_int(ctx, l >> (r&0x1f));
2378 /* ECMA-262 3rd Edition 11.13.1 */
2379 static HRESULT interp_assign(exec_ctx_t *ctx)
2389 disp = stack_pop_objid(ctx, &id);
2392 return throw_reference_error(ctx->parser->script, ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
2394 hres = disp_propput(ctx->parser->script, disp, id, v, ctx->ei, NULL/*FIXME*/);
2395 IDispatch_Release(disp);
2401 return stack_push(ctx, v);
2404 static HRESULT interp_undefined(exec_ctx_t *ctx)
2410 V_VT(&v) = VT_EMPTY;
2411 return stack_push(ctx, &v);
2414 static HRESULT interp_jmp(exec_ctx_t *ctx)
2416 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
2424 static HRESULT interp_jmp_z(exec_ctx_t *ctx)
2426 const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
2434 hres = to_boolean(v, &b);
2446 static HRESULT interp_pop(exec_ctx_t *ctx)
2454 static HRESULT interp_ret(exec_ctx_t *ctx)
2462 static HRESULT interp_tree(exec_ctx_t *ctx)
2464 instr_t *instr = ctx->parser->code->instrs+ctx->ip;
2470 hres = instr->arg1.stat->eval(ctx->parser->script, instr->arg1.stat, ctx->rt, &v);
2474 return stack_push(ctx, &v);
2477 typedef HRESULT (*op_func_t)(exec_ctx_t*);
2479 static const op_func_t op_funcs[] = {
2480 #define X(x,a,b,c) interp_##x,
2485 static const unsigned op_move[] = {
2486 #define X(a,x,b,c) x,
2491 static HRESULT unwind_exception(exec_ctx_t *ctx)
2493 except_frame_t *except_frame;
2498 except_frame = ctx->except_frame;
2499 ctx->except_frame = except_frame->next;
2501 assert(except_frame->stack_top <= ctx->top);
2502 stack_popn(ctx, ctx->top - except_frame->stack_top);
2504 while(except_frame->scope != ctx->scope_chain)
2505 scope_pop(&ctx->scope_chain);
2507 ctx->ip = except_frame->catch_off;
2509 except_val = ctx->rt->ei.var;
2510 memset(&ctx->rt->ei, 0, sizeof(ctx->rt->ei));
2512 ident = except_frame->ident;
2513 heap_free(except_frame);
2516 jsdisp_t *scope_obj;
2518 hres = create_dispex(ctx->parser->script, NULL, NULL, &scope_obj);
2519 if(SUCCEEDED(hres)) {
2520 hres = jsdisp_propput_name(scope_obj, ident, &except_val, &ctx->rt->ei, NULL/*FIXME*/);
2522 jsdisp_release(scope_obj);
2524 VariantClear(&except_val);
2528 hres = scope_push(ctx->scope_chain, scope_obj, &ctx->scope_chain);
2529 jsdisp_release(scope_obj);
2533 hres = stack_push(ctx, &except_val);
2537 hres = stack_push_bool(ctx, FALSE);
2541 V_VT(&v) = VT_EMPTY;
2542 hres = stack_push(ctx, &v);
2548 static HRESULT enter_bytecode(script_ctx_t *ctx, unsigned ip, return_type_t *rt, VARIANT *ret)
2550 exec_ctx_t *exec_ctx = ctx->exec_ctx;
2551 except_frame_t *prev_except_frame;
2552 unsigned prev_ip, prev_top;
2553 scope_chain_t *prev_scope;
2554 return_type_t *prev_rt;
2555 jsexcept_t *prev_ei;
2557 HRESULT hres = S_OK;
2561 prev_rt = exec_ctx->rt;
2562 prev_top = exec_ctx->top;
2563 prev_scope = exec_ctx->scope_chain;
2564 prev_except_frame = exec_ctx->except_frame;
2565 prev_ip = exec_ctx->ip;
2566 prev_ei = exec_ctx->ei;
2569 exec_ctx->ei = &rt->ei;
2570 exec_ctx->except_frame = NULL;
2572 while(exec_ctx->ip != -1) {
2573 op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
2574 hres = op_funcs[op](exec_ctx);
2576 TRACE("EXCEPTION\n");
2578 if(!exec_ctx->except_frame)
2581 hres = unwind_exception(exec_ctx);
2585 exec_ctx->ip += op_move[op];
2589 exec_ctx->rt = prev_rt;
2590 exec_ctx->ip = prev_ip;
2591 exec_ctx->ei = prev_ei;
2592 exec_ctx->except_frame = prev_except_frame;
2595 while(exec_ctx->scope_chain != prev_scope)
2596 scope_pop(&exec_ctx->scope_chain);
2597 stack_popn(exec_ctx, exec_ctx->top-prev_top);
2601 assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top);
2602 assert(exec_ctx->scope_chain == prev_scope);
2604 if(exec_ctx->top == prev_top)
2605 V_VT(ret) = VT_EMPTY;
2607 *ret = *stack_pop(exec_ctx);
2611 HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, BOOL from_eval,
2612 jsexcept_t *ei, VARIANT *retv)
2614 script_ctx_t *script = parser->script;
2615 function_declaration_t *func;
2616 parser_ctx_t *prev_parser;
2619 exec_ctx_t *prev_ctx;
2621 HRESULT hres = S_OK;
2623 for(func = source->functions; func; func = func->next) {
2627 hres = create_source_function(parser, func->expr->parameter_list, func->expr->source_elements,
2628 ctx->scope_chain, func->expr->src_str, func->expr->src_len, &func_obj);
2632 var_set_jsdisp(&var, func_obj);
2633 hres = jsdisp_propput_name(ctx->var_disp, func->expr->identifier, &var, ei, NULL);
2634 jsdisp_release(func_obj);
2639 for(var = source->variables; var; var = var->next) {
2643 name = SysAllocString(var->identifier);
2645 return E_OUTOFMEMORY;
2647 if(!ctx->is_global || !lookup_global_members(parser->script, name, NULL))
2648 hres = jsdisp_get_id(ctx->var_disp, var->identifier, fdexNameEnsure, &id);
2649 SysFreeString(name);
2654 prev_ctx = script->exec_ctx;
2655 script->exec_ctx = ctx;
2657 prev_parser = ctx->parser;
2658 ctx->parser = parser;
2660 V_VT(&val) = VT_EMPTY;
2661 memset(&rt, 0, sizeof(rt));
2663 if(source->statement) {
2664 if(source->instr_off == -1) {
2665 hres = compile_subscript_stat(ctx->parser, source->statement, from_eval, &source->instr_off);
2666 if(FAILED(hres) && is_jscript_error(hres))
2667 hres = throw_syntax_error(script, &rt.ei, hres, NULL);
2670 hres = enter_bytecode(script, source->instr_off, &rt, &val);
2673 script->exec_ctx = prev_ctx;
2674 ctx->parser = prev_parser;