diff --git a/reactos/dll/win32/jscript/compile.c b/reactos/dll/win32/jscript/compile.c index 06c55615f51..39ba79acc51 100644 --- a/reactos/dll/win32/jscript/compile.c +++ b/reactos/dll/win32/jscript/compile.c @@ -550,12 +550,20 @@ static HRESULT compile_new_expression(compiler_ctx_t *ctx, call_expression_t *ex arg_cnt++; } - return push_instr_uint(ctx, OP_new, arg_cnt); + hres = push_instr_uint(ctx, OP_new, arg_cnt); + if(FAILED(hres)) + return hres; + + hres = push_instr_uint(ctx, OP_pop, arg_cnt+1); + if(FAILED(hres)) + return hres; + + return push_instr(ctx, OP_push_ret) ? S_OK : E_OUTOFMEMORY; } static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *expr, BOOL emit_ret) { - unsigned arg_cnt = 0; + unsigned arg_cnt = 0, extra_args; argument_t *arg; unsigned instr; jsop_t op; @@ -563,9 +571,11 @@ static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *e if(is_memberid_expr(expr->expression->type)) { op = OP_call_member; + extra_args = 2; hres = compile_memberid_expression(ctx, expr->expression, 0); }else { op = OP_call; + extra_args = 1; hres = compile_expression(ctx, expr->expression, TRUE); } @@ -585,7 +595,12 @@ static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *e instr_ptr(ctx, instr)->u.arg[0].uint = arg_cnt; instr_ptr(ctx, instr)->u.arg[1].lng = emit_ret; - return S_OK; + + hres = push_instr_uint(ctx, OP_pop, arg_cnt + extra_args); + if(FAILED(hres)) + return hres; + + return !emit_ret || push_instr(ctx, OP_push_ret) ? S_OK : E_OUTOFMEMORY; } static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr) @@ -849,17 +864,11 @@ static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expres return S_OK; } -static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr) +static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr, BOOL emit_ret) { + unsigned func_id = ctx->func->func_cnt++; ctx->func_tail = ctx->func_tail ? (ctx->func_tail->next = expr) : (ctx->func_head = expr); - - /* FIXME: not exactly right */ - if(expr->identifier && !expr->event_target) { - ctx->func->func_cnt++; - return push_instr_bstr(ctx, OP_ident, expr->identifier); - } - - return push_instr_uint(ctx, OP_func, ctx->func->func_cnt++); + return emit_ret ? push_instr_uint(ctx, OP_func, func_id) : S_OK; } static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr, BOOL emit_ret) @@ -944,8 +953,7 @@ static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr, BOOL hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq2); break; case EXPR_FUNC: - hres = compile_function_expression(ctx, (function_expression_t*)expr); - break; + return compile_function_expression(ctx, (function_expression_t*)expr, emit_ret); case EXPR_GREATER: hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt); break; @@ -1471,7 +1479,7 @@ static HRESULT compile_return_statement(compiler_ctx_t *ctx, expression_statemen if(FAILED(hres)) return hres; - return push_instr(ctx, OP_ret) ? S_OK : E_OUTOFMEMORY; + return push_instr_uint(ctx, OP_ret, !stat->expr); } /* ECMA-262 3rd Edition 12.10 */ @@ -1849,8 +1857,9 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, resolve_labels(ctx, off); - if(!push_instr(ctx, OP_ret)) - return E_OUTOFMEMORY; + hres = push_instr_uint(ctx, OP_ret, !from_eval); + if(FAILED(hres)) + return hres; if(TRACE_ON(jscript_disas)) dump_code(ctx, off); diff --git a/reactos/dll/win32/jscript/date.c b/reactos/dll/win32/jscript/date.c index 33b55023d1f..d9a81d90829 100644 --- a/reactos/dll/win32/jscript/date.c +++ b/reactos/dll/win32/jscript/date.c @@ -2163,6 +2163,28 @@ static inline HRESULT date_parse(jsstr_t *input_str, double *ret) { year = tmp; } } + else if(parse[i]=='+' || parse[i]=='-') { + /* Timezone offset */ + BOOL positive = TRUE; + + if(set_offset && set_hour_adjust) break; + set_offset = TRUE; + set_hour_adjust = FALSE; + + if(parse[i] == '-') positive = FALSE; + + i++; + while(isspaceW(parse[i])) i++; + if(parse[i]<'0' || parse[i]>'9') break; + offset = atoiW(&parse[i]); + while(parse[i]>='0' && parse[i]<='9') i++; + + if(offset<24) offset *= 60; + else offset = (offset/100)*60 + offset%100; + + if(positive) offset = -offset; + + } else { if(parse[i]<'A' || parse[i]>'Z') break; else if(parse[i]=='B' && (parse[i+1]=='C' || @@ -2219,27 +2241,11 @@ static inline HRESULT date_parse(jsstr_t *input_str, double *ret) { else if((parse[i]=='U' && parse[i+1]=='T' && parse[i+2]=='C') || (parse[i]=='G' && parse[i+1]=='M' && parse[i+2]=='T')) { /* Timezone */ - BOOL positive = TRUE; - if(set_offset) break; set_offset = TRUE; set_hour_adjust = FALSE; i += 3; - while(isspaceW(parse[i])) i++; - if(parse[i] == '-') positive = FALSE; - else if(parse[i] != '+') continue; - - i++; - while(isspaceW(parse[i])) i++; - if(parse[i]<'0' || parse[i]>'9') break; - offset = atoiW(&parse[i]); - while(parse[i]>='0' && parse[i]<='9') i++; - - if(offset<24) offset *= 60; - else offset = (offset/100)*60 + offset%100; - - if(positive) offset = -offset; } else { /* Month or garbage */ diff --git a/reactos/dll/win32/jscript/decode.c b/reactos/dll/win32/jscript/decode.c index 297070c828b..1799b918646 100644 --- a/reactos/dll/win32/jscript/decode.c +++ b/reactos/dll/win32/jscript/decode.c @@ -87,7 +87,7 @@ static BOOL decode_dword(const WCHAR *p, DWORD *ret) DWORD i; for(i=0; i<6; i++) { - if(p[i] > sizeof(digits)/sizeof(*digits) || digits[p[i]] == 0xff) + if(p[i] >= sizeof(digits)/sizeof(*digits) || digits[p[i]] == 0xff) return FALSE; } if(p[6] != '=' || p[7] != '=') diff --git a/reactos/dll/win32/jscript/dispex.c b/reactos/dll/win32/jscript/dispex.c index 20740e9d9d7..85dc74d9a7a 100644 --- a/reactos/dll/win32/jscript/dispex.c +++ b/reactos/dll/win32/jscript/dispex.c @@ -370,6 +370,8 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t if(prop->name || This->builtin_info->class != JSCLASS_FUNCTION) { vdisp_t vthis; + if(This->builtin_info->class != JSCLASS_FUNCTION && prop->u.p->invoke != JSGlobal_eval) + flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK; if(jsthis) set_disp(&vthis, jsthis); else @@ -1053,7 +1055,7 @@ HRESULT jsdisp_call_value(jsdisp_t *jsfunc, IDispatch *jsthis, WORD flags, unsig { HRESULT hres; - assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT))); + assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT|DISPATCH_JSCRIPT_INTERNAL_MASK))); if(is_class(jsfunc, JSCLASS_FUNCTION)) { hres = Function_invoke(jsfunc, jsthis, flags, argc, argv, r); @@ -1066,6 +1068,7 @@ HRESULT jsdisp_call_value(jsdisp_t *jsfunc, IDispatch *jsthis, WORD flags, unsig } set_disp(&vdisp, jsthis); + flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK; hres = jsfunc->builtin_info->value_prop.invoke(jsfunc->ctx, &vdisp, flags, argc, argv, r); vdisp_release(&vdisp); } @@ -1116,6 +1119,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns return hres; } + flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK; if(ret && argc) flags |= DISPATCH_PROPERTYGET; @@ -1180,6 +1184,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns hres = variant_to_jsval(&retv, ret); VariantClear(&retv); } + return hres; } @@ -1193,7 +1198,7 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W unsigned i; HRESULT hres; - assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT))); + assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT|DISPATCH_JSCRIPT_INTERNAL_MASK))); jsdisp = iface_to_jsdisp((IUnknown*)disp); if(jsdisp) { @@ -1202,6 +1207,7 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W return hres; } + flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK; if(r && argc && flags == DISPATCH_METHOD) flags |= DISPATCH_PROPERTYGET; diff --git a/reactos/dll/win32/jscript/engine.c b/reactos/dll/win32/jscript/engine.c index 351b53527a5..08b7049074f 100644 --- a/reactos/dll/win32/jscript/engine.c +++ b/reactos/dll/win32/jscript/engine.c @@ -50,14 +50,14 @@ typedef struct { } u; } exprval_t; -static HRESULT stack_push(exec_ctx_t *ctx, jsval_t v) +static HRESULT stack_push(script_ctx_t *ctx, jsval_t v) { if(!ctx->stack_size) { ctx->stack = heap_alloc(16*sizeof(*ctx->stack)); if(!ctx->stack) return E_OUTOFMEMORY; ctx->stack_size = 16; - }else if(ctx->stack_size == ctx->top) { + }else if(ctx->stack_size == ctx->stack_top) { jsval_t *new_stack; new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(*new_stack)); @@ -70,11 +70,11 @@ static HRESULT stack_push(exec_ctx_t *ctx, jsval_t v) ctx->stack_size *= 2; } - ctx->stack[ctx->top++] = v; + ctx->stack[ctx->stack_top++] = v; return S_OK; } -static inline HRESULT stack_push_string(exec_ctx_t *ctx, const WCHAR *str) +static inline HRESULT stack_push_string(script_ctx_t *ctx, const WCHAR *str) { jsstr_t *v; @@ -85,7 +85,7 @@ static inline HRESULT stack_push_string(exec_ctx_t *ctx, const WCHAR *str) return stack_push(ctx, jsval_string(v)); } -static HRESULT stack_push_objid(exec_ctx_t *ctx, IDispatch *disp, DISPID id) +static HRESULT stack_push_objid(script_ctx_t *ctx, IDispatch *disp, DISPID id) { HRESULT hres; @@ -96,50 +96,50 @@ static HRESULT stack_push_objid(exec_ctx_t *ctx, IDispatch *disp, DISPID id) return stack_push(ctx, jsval_number(id)); } -static inline jsval_t stack_top(exec_ctx_t *ctx) +static inline jsval_t stack_top(script_ctx_t *ctx) { - assert(ctx->top); - return ctx->stack[ctx->top-1]; + assert(ctx->stack_top > ctx->call_ctx->stack_base); + return ctx->stack[ctx->stack_top-1]; } -static inline jsval_t stack_topn(exec_ctx_t *ctx, unsigned n) +static inline jsval_t stack_topn(script_ctx_t *ctx, unsigned n) { - assert(ctx->top > n); - return ctx->stack[ctx->top-1-n]; + assert(ctx->stack_top > ctx->call_ctx->stack_base+n); + return ctx->stack[ctx->stack_top-1-n]; } -static inline jsval_t *stack_args(exec_ctx_t *ctx, unsigned n) +static inline jsval_t *stack_args(script_ctx_t *ctx, unsigned n) { if(!n) return NULL; - assert(ctx->top > n-1); - return ctx->stack + ctx->top-n; + assert(ctx->stack_top > ctx->call_ctx->stack_base+n-1); + return ctx->stack + ctx->stack_top-n; } -static inline jsval_t stack_pop(exec_ctx_t *ctx) +static inline jsval_t stack_pop(script_ctx_t *ctx) { - assert(ctx->top); - return ctx->stack[--ctx->top]; + assert(ctx->stack_top > ctx->call_ctx->stack_base); + return ctx->stack[--ctx->stack_top]; } -static void stack_popn(exec_ctx_t *ctx, unsigned n) +static void stack_popn(script_ctx_t *ctx, unsigned n) { while(n--) jsval_release(stack_pop(ctx)); } -static HRESULT stack_pop_number(exec_ctx_t *ctx, double *r) +static HRESULT stack_pop_number(script_ctx_t *ctx, double *r) { jsval_t v; HRESULT hres; v = stack_pop(ctx); - hres = to_number(ctx->script, v, r); + hres = to_number(ctx, v, r); jsval_release(v); return hres; } -static HRESULT stack_pop_object(exec_ctx_t *ctx, IDispatch **r) +static HRESULT stack_pop_object(script_ctx_t *ctx, IDispatch **r) { jsval_t v; HRESULT hres; @@ -147,27 +147,27 @@ static HRESULT stack_pop_object(exec_ctx_t *ctx, IDispatch **r) v = stack_pop(ctx); if(is_object_instance(v)) { if(!get_object(v)) - return throw_type_error(ctx->script, JS_E_OBJECT_REQUIRED, NULL); + return throw_type_error(ctx, JS_E_OBJECT_REQUIRED, NULL); *r = get_object(v); return S_OK; } - hres = to_object(ctx->script, v, r); + hres = to_object(ctx, v, r); jsval_release(v); return hres; } -static inline HRESULT stack_pop_int(exec_ctx_t *ctx, INT *r) +static inline HRESULT stack_pop_int(script_ctx_t *ctx, INT *r) { - return to_int32(ctx->script, stack_pop(ctx), r); + return to_int32(ctx, stack_pop(ctx), r); } -static inline HRESULT stack_pop_uint(exec_ctx_t *ctx, DWORD *r) +static inline HRESULT stack_pop_uint(script_ctx_t *ctx, DWORD *r) { - return to_uint32(ctx->script, stack_pop(ctx), r); + return to_uint32(ctx, stack_pop(ctx), r); } -static inline IDispatch *stack_pop_objid(exec_ctx_t *ctx, DISPID *id) +static inline IDispatch *stack_pop_objid(script_ctx_t *ctx, DISPID *id) { assert(is_number(stack_top(ctx)) && is_object_instance(stack_topn(ctx, 1))); @@ -175,7 +175,7 @@ static inline IDispatch *stack_pop_objid(exec_ctx_t *ctx, DISPID *id) return get_object(stack_pop(ctx)); } -static inline IDispatch *stack_topn_objid(exec_ctx_t *ctx, unsigned n, DISPID *id) +static inline IDispatch *stack_topn_objid(script_ctx_t *ctx, unsigned n, DISPID *id) { assert(is_number(stack_topn(ctx, n)) && is_object_instance(stack_topn(ctx, n+1))); @@ -183,6 +183,18 @@ static inline IDispatch *stack_topn_objid(exec_ctx_t *ctx, unsigned n, DISPID *i return get_object(stack_topn(ctx, n+1)); } +static inline jsval_t steal_ret(call_frame_t *frame) +{ + jsval_t r = frame->ret; + frame->ret = jsval_undefined(); + return r; +} + +static inline void clear_ret(call_frame_t *frame) +{ + jsval_release(steal_ret(frame)); +} + static void exprval_release(exprval_t *val) { switch(val->type) { @@ -284,72 +296,6 @@ void scope_release(scope_chain_t *scope) heap_free(scope); } -HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, jsdisp_t *var_disp, - scope_chain_t *scope, BOOL is_global, exec_ctx_t **ret) -{ - exec_ctx_t *ctx; - - ctx = heap_alloc_zero(sizeof(exec_ctx_t)); - if(!ctx) - return E_OUTOFMEMORY; - - ctx->ref = 1; - ctx->is_global = is_global; - ctx->ret = jsval_undefined(); - - /* ECMA-262 3rd Edition 11.2.3.7 */ - if(this_obj) { - jsdisp_t *jsthis; - - jsthis = iface_to_jsdisp((IUnknown*)this_obj); - if(jsthis) { - if(jsthis->builtin_info->class == JSCLASS_GLOBAL || jsthis->builtin_info->class == JSCLASS_NONE) - this_obj = NULL; - jsdisp_release(jsthis); - } - } - - if(this_obj) - ctx->this_obj = this_obj; - else if(script_ctx->host_global) - ctx->this_obj = script_ctx->host_global; - else - ctx->this_obj = to_disp(script_ctx->global); - IDispatch_AddRef(ctx->this_obj); - - jsdisp_addref(var_disp); - ctx->var_disp = var_disp; - - script_addref(script_ctx); - ctx->script = script_ctx; - - if(scope) { - scope_addref(scope); - ctx->scope_chain = scope; - } - - *ret = ctx; - return S_OK; -} - -void exec_release(exec_ctx_t *ctx) -{ - if(--ctx->ref) - return; - - if(ctx->scope_chain) - scope_release(ctx->scope_chain); - if(ctx->var_disp) - jsdisp_release(ctx->var_disp); - if(ctx->this_obj) - IDispatch_Release(ctx->this_obj); - if(ctx->script) - script_release(ctx->script); - jsval_release(ctx->ret); - heap_free(ctx->stack); - heap_free(ctx); -} - static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, const WCHAR *name, BSTR name_bstr, DWORD flags, DISPID *id) { IDispatchEx *dispex; @@ -500,8 +446,8 @@ static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *re TRACE("%s\n", debugstr_w(identifier)); - if(ctx->exec_ctx) { - for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) { + if(ctx->call_ctx) { + for(scope = ctx->call_ctx->scope; scope; scope = scope->next) { if(scope->jsobj) hres = jsdisp_get_id(scope->jsobj, identifier, fdexNameImplicit, &id); else @@ -556,28 +502,48 @@ static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *re return S_OK; } -static inline BSTR get_op_bstr(exec_ctx_t *ctx, int i){ - return ctx->code->instrs[ctx->ip].u.arg[i].bstr; +static inline BSTR get_op_bstr(script_ctx_t *ctx, int i) +{ + call_frame_t *frame = ctx->call_ctx; + return frame->bytecode->instrs[frame->ip].u.arg[i].bstr; } -static inline unsigned get_op_uint(exec_ctx_t *ctx, int i){ - return ctx->code->instrs[ctx->ip].u.arg[i].uint; +static inline unsigned get_op_uint(script_ctx_t *ctx, int i) +{ + call_frame_t *frame = ctx->call_ctx; + return frame->bytecode->instrs[frame->ip].u.arg[i].uint; } -static inline unsigned get_op_int(exec_ctx_t *ctx, int i){ - return ctx->code->instrs[ctx->ip].u.arg[i].lng; +static inline unsigned get_op_int(script_ctx_t *ctx, int i) +{ + call_frame_t *frame = ctx->call_ctx; + return frame->bytecode->instrs[frame->ip].u.arg[i].lng; } -static inline jsstr_t *get_op_str(exec_ctx_t *ctx, int i){ - return ctx->code->instrs[ctx->ip].u.arg[i].str; +static inline jsstr_t *get_op_str(script_ctx_t *ctx, int i) +{ + call_frame_t *frame = ctx->call_ctx; + return frame->bytecode->instrs[frame->ip].u.arg[i].str; } -static inline double get_op_double(exec_ctx_t *ctx){ - return ctx->code->instrs[ctx->ip].u.dbl; +static inline double get_op_double(script_ctx_t *ctx) +{ + call_frame_t *frame = ctx->call_ctx; + return frame->bytecode->instrs[frame->ip].u.dbl; +} + +static inline void jmp_next(script_ctx_t *ctx) +{ + ctx->call_ctx->ip++; +} + +static inline void jmp_abs(script_ctx_t *ctx, unsigned dst) +{ + ctx->call_ctx->ip = dst; } /* ECMA-262 3rd Edition 12.2 */ -static HRESULT interp_var_set(exec_ctx_t *ctx) +static HRESULT interp_var_set(script_ctx_t *ctx) { const BSTR name = get_op_bstr(ctx, 0); jsval_t val; @@ -586,13 +552,13 @@ static HRESULT interp_var_set(exec_ctx_t *ctx) TRACE("%s\n", debugstr_w(name)); val = stack_pop(ctx); - hres = jsdisp_propput_name(ctx->var_disp, name, val); + hres = jsdisp_propput_name(ctx->call_ctx->variable_obj, name, val); jsval_release(val); return hres; } /* ECMA-262 3rd Edition 12.6.4 */ -static HRESULT interp_forin(exec_ctx_t *ctx) +static HRESULT interp_forin(script_ctx_t *ctx) { const HRESULT arg = get_op_uint(ctx, 0); IDispatch *var_obj, *obj = NULL; @@ -640,21 +606,21 @@ static HRESULT interp_forin(exec_ctx_t *ctx) stack_pop(ctx); stack_push(ctx, jsval_number(id)); /* safe, just after pop() */ - hres = disp_propput(ctx->script, var_obj, var_id, jsval_string(str)); + hres = disp_propput(ctx, var_obj, var_id, jsval_string(str)); jsstr_release(str); if(FAILED(hres)) return hres; - ctx->ip++; + jmp_next(ctx); }else { stack_popn(ctx, 4); - ctx->ip = arg; + jmp_abs(ctx, arg); } return S_OK; } /* ECMA-262 3rd Edition 12.10 */ -static HRESULT interp_push_scope(exec_ctx_t *ctx) +static HRESULT interp_push_scope(script_ctx_t *ctx) { IDispatch *disp; jsval_t v; @@ -663,27 +629,27 @@ static HRESULT interp_push_scope(exec_ctx_t *ctx) TRACE("\n"); v = stack_pop(ctx); - hres = to_object(ctx->script, v, &disp); + hres = to_object(ctx, v, &disp); jsval_release(v); if(FAILED(hres)) return hres; - hres = scope_push(ctx->scope_chain, to_jsdisp(disp), disp, &ctx->scope_chain); + hres = scope_push(ctx->call_ctx->scope, to_jsdisp(disp), disp, &ctx->call_ctx->scope); IDispatch_Release(disp); return hres; } /* ECMA-262 3rd Edition 12.10 */ -static HRESULT interp_pop_scope(exec_ctx_t *ctx) +static HRESULT interp_pop_scope(script_ctx_t *ctx) { TRACE("\n"); - scope_pop(&ctx->scope_chain); + scope_pop(&ctx->call_ctx->scope); return S_OK; } /* ECMA-262 3rd Edition 12.13 */ -static HRESULT interp_case(exec_ctx_t *ctx) +static HRESULT interp_case(script_ctx_t *ctx) { const unsigned arg = get_op_uint(ctx, 0); jsval_t v; @@ -700,33 +666,33 @@ static HRESULT interp_case(exec_ctx_t *ctx) if(b) { stack_popn(ctx, 1); - ctx->ip = arg; + jmp_abs(ctx, arg); }else { - ctx->ip++; + jmp_next(ctx); } return S_OK; } /* ECMA-262 3rd Edition 12.13 */ -static HRESULT interp_throw(exec_ctx_t *ctx) +static HRESULT interp_throw(script_ctx_t *ctx) { TRACE("\n"); - jsval_release(ctx->script->ei.val); - ctx->script->ei.val = stack_pop(ctx); + jsval_release(ctx->ei.val); + ctx->ei.val = stack_pop(ctx); return DISP_E_EXCEPTION; } -static HRESULT interp_throw_ref(exec_ctx_t *ctx) +static HRESULT interp_throw_ref(script_ctx_t *ctx) { const HRESULT arg = get_op_uint(ctx, 0); TRACE("%08x\n", arg); - return throw_reference_error(ctx->script, arg, NULL); + return throw_reference_error(ctx, arg, NULL); } -static HRESULT interp_throw_type(exec_ctx_t *ctx) +static HRESULT interp_throw_type(script_ctx_t *ctx) { const HRESULT hres = get_op_uint(ctx, 0); jsstr_t *str = get_op_str(ctx, 1); @@ -735,20 +701,21 @@ static HRESULT interp_throw_type(exec_ctx_t *ctx) TRACE("%08x %s\n", hres, debugstr_jsstr(str)); ptr = jsstr_flatten(str); - return ptr ? throw_type_error(ctx->script, hres, ptr) : E_OUTOFMEMORY; + return ptr ? throw_type_error(ctx, hres, ptr) : E_OUTOFMEMORY; } /* ECMA-262 3rd Edition 12.14 */ -static HRESULT interp_push_except(exec_ctx_t *ctx) +static HRESULT interp_push_except(script_ctx_t *ctx) { const unsigned arg1 = get_op_uint(ctx, 0); const BSTR arg2 = get_op_bstr(ctx, 1); + call_frame_t *frame = ctx->call_ctx; except_frame_t *except; unsigned stack_top; TRACE("\n"); - stack_top = ctx->top; + stack_top = ctx->stack_top; if(!arg2) { HRESULT hres; @@ -766,31 +733,32 @@ static HRESULT interp_push_except(exec_ctx_t *ctx) return E_OUTOFMEMORY; except->stack_top = stack_top; - except->scope = ctx->scope_chain; + except->scope = frame->scope; except->catch_off = arg1; except->ident = arg2; - except->next = ctx->except_frame; - ctx->except_frame = except; + except->next = frame->except_frame; + frame->except_frame = except; return S_OK; } /* ECMA-262 3rd Edition 12.14 */ -static HRESULT interp_pop_except(exec_ctx_t *ctx) +static HRESULT interp_pop_except(script_ctx_t *ctx) { + call_frame_t *frame = ctx->call_ctx; except_frame_t *except; TRACE("\n"); - except = ctx->except_frame; + except = frame->except_frame; assert(except != NULL); - ctx->except_frame = except->next; + frame->except_frame = except->next; heap_free(except); return S_OK; } /* ECMA-262 3rd Edition 12.14 */ -static HRESULT interp_end_finally(exec_ctx_t *ctx) +static HRESULT interp_end_finally(script_ctx_t *ctx) { jsval_t v; @@ -802,7 +770,7 @@ static HRESULT interp_end_finally(exec_ctx_t *ctx) if(!get_bool(v)) { TRACE("passing exception\n"); - ctx->script->ei.val = stack_pop(ctx); + ctx->ei.val = stack_pop(ctx); return DISP_E_EXCEPTION; } @@ -811,16 +779,17 @@ static HRESULT interp_end_finally(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 13 */ -static HRESULT interp_func(exec_ctx_t *ctx) +static HRESULT interp_func(script_ctx_t *ctx) { unsigned func_idx = get_op_uint(ctx, 0); + call_frame_t *frame = ctx->call_ctx; jsdisp_t *dispex; HRESULT hres; TRACE("%d\n", func_idx); - hres = create_source_function(ctx->script, ctx->code, ctx->func_code->funcs+func_idx, - ctx->scope_chain, &dispex); + hres = create_source_function(ctx, frame->bytecode, frame->function->funcs+func_idx, + frame->scope, &dispex); if(FAILED(hres)) return hres; @@ -828,7 +797,7 @@ static HRESULT interp_func(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.2.1 */ -static HRESULT interp_array(exec_ctx_t *ctx) +static HRESULT interp_array(script_ctx_t *ctx) { jsstr_t *name_str; const WCHAR *name; @@ -847,17 +816,17 @@ static HRESULT interp_array(exec_ctx_t *ctx) return hres; } - hres = to_flat_string(ctx->script, namev, &name_str, &name); + hres = to_flat_string(ctx, namev, &name_str, &name); jsval_release(namev); if(FAILED(hres)) { IDispatch_Release(obj); return hres; } - hres = disp_get_id(ctx->script, obj, name, NULL, 0, &id); + hres = disp_get_id(ctx, obj, name, NULL, 0, &id); jsstr_release(name_str); if(SUCCEEDED(hres)) { - hres = disp_propget(ctx->script, obj, id, &v); + hres = disp_propget(ctx, obj, id, &v); }else if(hres == DISP_E_UNKNOWNNAME) { v = jsval_undefined(); hres = S_OK; @@ -870,7 +839,7 @@ static HRESULT interp_array(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.2.1 */ -static HRESULT interp_member(exec_ctx_t *ctx) +static HRESULT interp_member(script_ctx_t *ctx) { const BSTR arg = get_op_bstr(ctx, 0); IDispatch *obj; @@ -884,9 +853,9 @@ static HRESULT interp_member(exec_ctx_t *ctx) if(FAILED(hres)) return hres; - hres = disp_get_id(ctx->script, obj, arg, arg, 0, &id); + hres = disp_get_id(ctx, obj, arg, arg, 0, &id); if(SUCCEEDED(hres)) { - hres = disp_propget(ctx->script, obj, id, &v); + hres = disp_propget(ctx, obj, id, &v); }else if(hres == DISP_E_UNKNOWNNAME) { v = jsval_undefined(); hres = S_OK; @@ -899,7 +868,7 @@ static HRESULT interp_member(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.2.1 */ -static HRESULT interp_memberid(exec_ctx_t *ctx) +static HRESULT interp_memberid(script_ctx_t *ctx) { const unsigned arg = get_op_uint(ctx, 0); jsval_t objv, namev; @@ -914,10 +883,10 @@ static HRESULT interp_memberid(exec_ctx_t *ctx) namev = stack_pop(ctx); objv = stack_pop(ctx); - hres = to_object(ctx->script, objv, &obj); + hres = to_object(ctx, objv, &obj); jsval_release(objv); if(SUCCEEDED(hres)) { - hres = to_flat_string(ctx->script, namev, &name_str, &name); + hres = to_flat_string(ctx, namev, &name_str, &name); if(FAILED(hres)) IDispatch_Release(obj); } @@ -925,7 +894,7 @@ static HRESULT interp_memberid(exec_ctx_t *ctx) if(FAILED(hres)) return hres; - hres = disp_get_id(ctx->script, obj, name, NULL, arg, &id); + hres = disp_get_id(ctx, obj, name, NULL, arg, &id); jsstr_release(name_str); if(FAILED(hres)) { IDispatch_Release(obj); @@ -942,7 +911,7 @@ static HRESULT interp_memberid(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.2.1 */ -static HRESULT interp_refval(exec_ctx_t *ctx) +static HRESULT interp_refval(script_ctx_t *ctx) { IDispatch *disp; jsval_t v; @@ -953,9 +922,9 @@ static HRESULT interp_refval(exec_ctx_t *ctx) disp = stack_topn_objid(ctx, 0, &id); if(!disp) - return throw_reference_error(ctx->script, JS_E_ILLEGAL_ASSIGN, NULL); + return throw_reference_error(ctx, JS_E_ILLEGAL_ASSIGN, NULL); - hres = disp_propget(ctx->script, disp, id, &v); + hres = disp_propget(ctx, disp, id, &v); if(FAILED(hres)) return hres; @@ -963,11 +932,11 @@ static HRESULT interp_refval(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.2.2 */ -static HRESULT interp_new(exec_ctx_t *ctx) +static HRESULT interp_new(script_ctx_t *ctx) { const unsigned argc = get_op_uint(ctx, 0); - jsval_t r, constr; - HRESULT hres; + call_frame_t *frame = ctx->call_ctx; + jsval_t constr; TRACE("%d\n", argc); @@ -976,79 +945,69 @@ static HRESULT interp_new(exec_ctx_t *ctx) /* NOTE: Should use to_object here */ if(is_null(constr)) - return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL); + return throw_type_error(ctx, JS_E_OBJECT_EXPECTED, NULL); else if(!is_object_instance(constr)) - return throw_type_error(ctx->script, JS_E_INVALID_ACTION, NULL); + return throw_type_error(ctx, JS_E_INVALID_ACTION, NULL); else if(!get_object(constr)) - return throw_type_error(ctx->script, JS_E_INVALID_PROPERTY, NULL); + return throw_type_error(ctx, JS_E_INVALID_PROPERTY, NULL); - hres = disp_call_value(ctx->script, get_object(constr), NULL, DISPATCH_CONSTRUCT, argc, stack_args(ctx, argc), &r); - if(FAILED(hres)) - return hres; - - stack_popn(ctx, argc+1); - return stack_push(ctx, r); + clear_ret(frame); + return disp_call_value(ctx, get_object(constr), NULL, DISPATCH_CONSTRUCT | DISPATCH_JSCRIPT_CALLEREXECSSOURCE, + argc, stack_args(ctx, argc), &frame->ret); } /* ECMA-262 3rd Edition 11.2.3 */ -static HRESULT interp_call(exec_ctx_t *ctx) +static HRESULT interp_call(script_ctx_t *ctx) { const unsigned argn = get_op_uint(ctx, 0); const int do_ret = get_op_int(ctx, 1); - jsval_t r, obj; - HRESULT hres; + call_frame_t *frame = ctx->call_ctx; + jsval_t obj; TRACE("%d %d\n", argn, do_ret); obj = stack_topn(ctx, argn); if(!is_object_instance(obj)) - return throw_type_error(ctx->script, JS_E_INVALID_PROPERTY, NULL); + return throw_type_error(ctx, JS_E_INVALID_PROPERTY, NULL); - hres = disp_call_value(ctx->script, get_object(obj), NULL, DISPATCH_METHOD, argn, stack_args(ctx, argn), - do_ret ? &r : NULL); - if(FAILED(hres)) - return hres; - - stack_popn(ctx, argn+1); - return do_ret ? stack_push(ctx, r) : S_OK; + clear_ret(frame); + return disp_call_value(ctx, get_object(obj), NULL, DISPATCH_METHOD | DISPATCH_JSCRIPT_CALLEREXECSSOURCE, + argn, stack_args(ctx, argn), do_ret ? &frame->ret : NULL); } /* ECMA-262 3rd Edition 11.2.3 */ -static HRESULT interp_call_member(exec_ctx_t *ctx) +static HRESULT interp_call_member(script_ctx_t *ctx) { const unsigned argn = get_op_uint(ctx, 0); const int do_ret = get_op_int(ctx, 1); + call_frame_t *frame = ctx->call_ctx; IDispatch *obj; - jsval_t r; DISPID id; - HRESULT hres; TRACE("%d %d\n", argn, do_ret); obj = stack_topn_objid(ctx, argn, &id); if(!obj) - return throw_type_error(ctx->script, id, NULL); - - hres = disp_call(ctx->script, obj, id, DISPATCH_METHOD, argn, stack_args(ctx, argn), do_ret ? &r : NULL); - if(FAILED(hres)) - return hres; - - stack_popn(ctx, argn+2); - return do_ret ? stack_push(ctx, r) : S_OK; + return throw_type_error(ctx, id, NULL); + clear_ret(frame); + return disp_call(ctx, obj, id, DISPATCH_METHOD | DISPATCH_JSCRIPT_CALLEREXECSSOURCE, + argn, stack_args(ctx, argn), do_ret ? &frame->ret : NULL); } /* ECMA-262 3rd Edition 11.1.1 */ -static HRESULT interp_this(exec_ctx_t *ctx) +static HRESULT interp_this(script_ctx_t *ctx) { + call_frame_t *frame = ctx->call_ctx; + TRACE("\n"); - IDispatch_AddRef(ctx->this_obj); - return stack_push(ctx, jsval_disp(ctx->this_obj)); + IDispatch_AddRef(frame->this_obj); + return stack_push(ctx, jsval_disp(frame->this_obj)); } /* ECMA-262 3rd Edition 10.1.4 */ -static HRESULT interp_ident(exec_ctx_t *ctx) +static HRESULT interp_ident(script_ctx_t *ctx) { const BSTR arg = get_op_bstr(ctx, 0); exprval_t exprval; @@ -1057,14 +1016,14 @@ static HRESULT interp_ident(exec_ctx_t *ctx) TRACE("%s\n", debugstr_w(arg)); - hres = identifier_eval(ctx->script, arg, &exprval); + hres = identifier_eval(ctx, arg, &exprval); if(FAILED(hres)) return hres; if(exprval.type == EXPRVAL_INVALID) - return throw_type_error(ctx->script, JS_E_UNDEFINED_VARIABLE, arg); + return throw_type_error(ctx, JS_E_UNDEFINED_VARIABLE, arg); - hres = exprval_to_value(ctx->script, &exprval, &v); + hres = exprval_to_value(ctx, &exprval, &v); exprval_release(&exprval); if(FAILED(hres)) return hres; @@ -1073,7 +1032,7 @@ static HRESULT interp_ident(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 10.1.4 */ -static HRESULT interp_identid(exec_ctx_t *ctx) +static HRESULT interp_identid(script_ctx_t *ctx) { const BSTR arg = get_op_bstr(ctx, 0); const unsigned flags = get_op_uint(ctx, 1); @@ -1082,18 +1041,18 @@ static HRESULT interp_identid(exec_ctx_t *ctx) TRACE("%s %x\n", debugstr_w(arg), flags); - hres = identifier_eval(ctx->script, arg, &exprval); + hres = identifier_eval(ctx, arg, &exprval); if(FAILED(hres)) return hres; if(exprval.type == EXPRVAL_INVALID && (flags & fdexNameEnsure)) { DISPID id; - hres = jsdisp_get_id(ctx->script->global, arg, fdexNameEnsure, &id); + hres = jsdisp_get_id(ctx->global, arg, fdexNameEnsure, &id); if(FAILED(hres)) return hres; - exprval_set_idref(&exprval, to_disp(ctx->script->global), id); + exprval_set_idref(&exprval, to_disp(ctx->global), id); } if(exprval.type != EXPRVAL_IDREF) { @@ -1106,7 +1065,7 @@ static HRESULT interp_identid(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 7.8.1 */ -static HRESULT interp_null(exec_ctx_t *ctx) +static HRESULT interp_null(script_ctx_t *ctx) { TRACE("\n"); @@ -1114,7 +1073,7 @@ static HRESULT interp_null(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 7.8.2 */ -static HRESULT interp_bool(exec_ctx_t *ctx) +static HRESULT interp_bool(script_ctx_t *ctx) { const int arg = get_op_int(ctx, 0); @@ -1124,7 +1083,7 @@ static HRESULT interp_bool(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 7.8.3 */ -static HRESULT interp_int(exec_ctx_t *ctx) +static HRESULT interp_int(script_ctx_t *ctx) { const int arg = get_op_int(ctx, 0); @@ -1134,7 +1093,7 @@ static HRESULT interp_int(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 7.8.3 */ -static HRESULT interp_double(exec_ctx_t *ctx) +static HRESULT interp_double(script_ctx_t *ctx) { const double arg = get_op_double(ctx); @@ -1144,7 +1103,7 @@ static HRESULT interp_double(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 7.8.4 */ -static HRESULT interp_str(exec_ctx_t *ctx) +static HRESULT interp_str(script_ctx_t *ctx) { jsstr_t *str = get_op_str(ctx, 0); @@ -1154,7 +1113,7 @@ static HRESULT interp_str(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 7.8 */ -static HRESULT interp_regexp(exec_ctx_t *ctx) +static HRESULT interp_regexp(script_ctx_t *ctx) { jsstr_t *source = get_op_str(ctx, 0); const unsigned flags = get_op_uint(ctx, 1); @@ -1163,7 +1122,7 @@ static HRESULT interp_regexp(exec_ctx_t *ctx) TRACE("%s %x\n", debugstr_jsstr(source), flags); - hres = create_regexp(ctx->script, source, flags, ®exp); + hres = create_regexp(ctx, source, flags, ®exp); if(FAILED(hres)) return hres; @@ -1171,7 +1130,7 @@ static HRESULT interp_regexp(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.1.4 */ -static HRESULT interp_carray(exec_ctx_t *ctx) +static HRESULT interp_carray(script_ctx_t *ctx) { const unsigned arg = get_op_uint(ctx, 0); jsdisp_t *array; @@ -1181,7 +1140,7 @@ static HRESULT interp_carray(exec_ctx_t *ctx) TRACE("%u\n", arg); - hres = create_array(ctx->script, arg, &array); + hres = create_array(ctx, arg, &array); if(FAILED(hres)) return hres; @@ -1200,14 +1159,14 @@ static HRESULT interp_carray(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.1.5 */ -static HRESULT interp_new_obj(exec_ctx_t *ctx) +static HRESULT interp_new_obj(script_ctx_t *ctx) { jsdisp_t *obj; HRESULT hres; TRACE("\n"); - hres = create_object(ctx->script, NULL, &obj); + hres = create_object(ctx, NULL, &obj); if(FAILED(hres)) return hres; @@ -1215,7 +1174,7 @@ static HRESULT interp_new_obj(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.1.5 */ -static HRESULT interp_obj_prop(exec_ctx_t *ctx) +static HRESULT interp_obj_prop(script_ctx_t *ctx) { const BSTR name = get_op_bstr(ctx, 0); jsdisp_t *obj; @@ -1235,7 +1194,7 @@ static HRESULT interp_obj_prop(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.11 */ -static HRESULT interp_cnd_nz(exec_ctx_t *ctx) +static HRESULT interp_cnd_nz(script_ctx_t *ctx) { const unsigned arg = get_op_uint(ctx, 0); BOOL b; @@ -1248,16 +1207,16 @@ static HRESULT interp_cnd_nz(exec_ctx_t *ctx) return hres; if(b) { - ctx->ip = arg; + jmp_abs(ctx, arg); }else { stack_popn(ctx, 1); - ctx->ip++; + jmp_next(ctx); } return S_OK; } /* ECMA-262 3rd Edition 11.11 */ -static HRESULT interp_cnd_z(exec_ctx_t *ctx) +static HRESULT interp_cnd_z(script_ctx_t *ctx) { const unsigned arg = get_op_uint(ctx, 0); BOOL b; @@ -1271,15 +1230,15 @@ static HRESULT interp_cnd_z(exec_ctx_t *ctx) if(b) { stack_popn(ctx, 1); - ctx->ip++; + jmp_next(ctx); }else { - ctx->ip = arg; + jmp_abs(ctx, arg); } return S_OK; } /* ECMA-262 3rd Edition 11.10 */ -static HRESULT interp_or(exec_ctx_t *ctx) +static HRESULT interp_or(script_ctx_t *ctx) { INT l, r; HRESULT hres; @@ -1298,7 +1257,7 @@ static HRESULT interp_or(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.10 */ -static HRESULT interp_xor(exec_ctx_t *ctx) +static HRESULT interp_xor(script_ctx_t *ctx) { INT l, r; HRESULT hres; @@ -1317,7 +1276,7 @@ static HRESULT interp_xor(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.10 */ -static HRESULT interp_and(exec_ctx_t *ctx) +static HRESULT interp_and(script_ctx_t *ctx) { INT l, r; HRESULT hres; @@ -1336,7 +1295,7 @@ static HRESULT interp_and(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.8.6 */ -static HRESULT interp_instanceof(exec_ctx_t *ctx) +static HRESULT interp_instanceof(script_ctx_t *ctx) { jsdisp_t *obj, *iter, *tmp = NULL; jsval_t prot, v; @@ -1348,7 +1307,7 @@ static HRESULT interp_instanceof(exec_ctx_t *ctx) v = stack_pop(ctx); if(!is_object_instance(v) || !get_object(v)) { jsval_release(v); - return throw_type_error(ctx->script, JS_E_FUNCTION_EXPECTED, NULL); + return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); } obj = iface_to_jsdisp((IUnknown*)get_object(v)); @@ -1361,7 +1320,7 @@ static HRESULT interp_instanceof(exec_ctx_t *ctx) if(is_class(obj, JSCLASS_FUNCTION)) { hres = jsdisp_propget_name(obj, prototypeW, &prot); }else { - hres = throw_type_error(ctx->script, JS_E_FUNCTION_EXPECTED, NULL); + hres = throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); } jsdisp_release(obj); if(FAILED(hres)) @@ -1394,7 +1353,7 @@ static HRESULT interp_instanceof(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.8.7 */ -static HRESULT interp_in(exec_ctx_t *ctx) +static HRESULT interp_in(script_ctx_t *ctx) { const WCHAR *str; jsstr_t *jsstr; @@ -1408,18 +1367,18 @@ static HRESULT interp_in(exec_ctx_t *ctx) obj = stack_pop(ctx); if(!is_object_instance(obj) || !get_object(obj)) { jsval_release(obj); - return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL); + return throw_type_error(ctx, JS_E_OBJECT_EXPECTED, NULL); } v = stack_pop(ctx); - hres = to_flat_string(ctx->script, v, &jsstr, &str); + hres = to_flat_string(ctx, v, &jsstr, &str); jsval_release(v); if(FAILED(hres)) { IDispatch_Release(get_object(obj)); return hres; } - hres = disp_get_id(ctx->script, get_object(obj), str, NULL, 0, &id); + hres = disp_get_id(ctx, get_object(obj), str, NULL, 0, &id); IDispatch_Release(get_object(obj)); jsstr_release(jsstr); if(SUCCEEDED(hres)) @@ -1485,7 +1444,7 @@ static HRESULT add_eval(script_ctx_t *ctx, jsval_t lval, jsval_t rval, jsval_t * } /* ECMA-262 3rd Edition 11.6.1 */ -static HRESULT interp_add(exec_ctx_t *ctx) +static HRESULT interp_add(script_ctx_t *ctx) { jsval_t l, r, ret; HRESULT hres; @@ -1495,7 +1454,7 @@ static HRESULT interp_add(exec_ctx_t *ctx) TRACE("%s + %s\n", debugstr_jsval(l), debugstr_jsval(r)); - hres = add_eval(ctx->script, l, r, &ret); + hres = add_eval(ctx, l, r, &ret); jsval_release(l); jsval_release(r); if(FAILED(hres)) @@ -1505,7 +1464,7 @@ static HRESULT interp_add(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.6.2 */ -static HRESULT interp_sub(exec_ctx_t *ctx) +static HRESULT interp_sub(script_ctx_t *ctx) { double l, r; HRESULT hres; @@ -1524,7 +1483,7 @@ static HRESULT interp_sub(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.5.1 */ -static HRESULT interp_mul(exec_ctx_t *ctx) +static HRESULT interp_mul(script_ctx_t *ctx) { double l, r; HRESULT hres; @@ -1543,7 +1502,7 @@ static HRESULT interp_mul(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.5.2 */ -static HRESULT interp_div(exec_ctx_t *ctx) +static HRESULT interp_div(script_ctx_t *ctx) { double l, r; HRESULT hres; @@ -1562,7 +1521,7 @@ static HRESULT interp_div(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.5.3 */ -static HRESULT interp_mod(exec_ctx_t *ctx) +static HRESULT interp_mod(script_ctx_t *ctx) { double l, r; HRESULT hres; @@ -1581,7 +1540,7 @@ static HRESULT interp_mod(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.4.2 */ -static HRESULT interp_delete(exec_ctx_t *ctx) +static HRESULT interp_delete(script_ctx_t *ctx) { jsval_t objv, namev; IDispatch *obj; @@ -1594,21 +1553,21 @@ static HRESULT interp_delete(exec_ctx_t *ctx) namev = stack_pop(ctx); objv = stack_pop(ctx); - hres = to_object(ctx->script, objv, &obj); + hres = to_object(ctx, objv, &obj); jsval_release(objv); if(FAILED(hres)) { jsval_release(namev); return hres; } - hres = to_string(ctx->script, namev, &name); + hres = to_string(ctx, namev, &name); jsval_release(namev); if(FAILED(hres)) { IDispatch_Release(obj); return hres; } - hres = disp_delete_name(ctx->script, obj, name, &ret); + hres = disp_delete_name(ctx, obj, name, &ret); IDispatch_Release(obj); jsstr_release(name); if(FAILED(hres)) @@ -1618,7 +1577,7 @@ static HRESULT interp_delete(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.4.2 */ -static HRESULT interp_delete_ident(exec_ctx_t *ctx) +static HRESULT interp_delete_ident(script_ctx_t *ctx) { const BSTR arg = get_op_bstr(ctx, 0); exprval_t exprval; @@ -1627,7 +1586,7 @@ static HRESULT interp_delete_ident(exec_ctx_t *ctx) TRACE("%s\n", debugstr_w(arg)); - hres = identifier_eval(ctx->script, arg, &exprval); + hres = identifier_eval(ctx, arg, &exprval); if(FAILED(hres)) return hres; @@ -1652,7 +1611,7 @@ static HRESULT interp_delete_ident(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.4.2 */ -static HRESULT interp_void(exec_ctx_t *ctx) +static HRESULT interp_void(script_ctx_t *ctx) { TRACE("\n"); @@ -1699,7 +1658,7 @@ static HRESULT typeof_string(jsval_t v, const WCHAR **ret) } /* ECMA-262 3rd Edition 11.4.3 */ -static HRESULT interp_typeofid(exec_ctx_t *ctx) +static HRESULT interp_typeofid(script_ctx_t *ctx) { const WCHAR *ret; IDispatch *obj; @@ -1713,7 +1672,7 @@ static HRESULT interp_typeofid(exec_ctx_t *ctx) if(!obj) return stack_push(ctx, jsval_string(jsstr_undefined())); - hres = disp_propget(ctx->script, obj, id, &v); + hres = disp_propget(ctx, obj, id, &v); IDispatch_Release(obj); if(FAILED(hres)) return stack_push_string(ctx, unknownW); @@ -1727,7 +1686,7 @@ static HRESULT interp_typeofid(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.4.3 */ -static HRESULT interp_typeofident(exec_ctx_t *ctx) +static HRESULT interp_typeofident(script_ctx_t *ctx) { const BSTR arg = get_op_bstr(ctx, 0); exprval_t exprval; @@ -1737,7 +1696,7 @@ static HRESULT interp_typeofident(exec_ctx_t *ctx) TRACE("%s\n", debugstr_w(arg)); - hres = identifier_eval(ctx->script, arg, &exprval); + hres = identifier_eval(ctx, arg, &exprval); if(FAILED(hres)) return hres; @@ -1747,7 +1706,7 @@ static HRESULT interp_typeofident(exec_ctx_t *ctx) return hres; } - hres = exprval_to_value(ctx->script, &exprval, &v); + hres = exprval_to_value(ctx, &exprval, &v); exprval_release(&exprval); if(FAILED(hres)) return hres; @@ -1761,7 +1720,7 @@ static HRESULT interp_typeofident(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.4.3 */ -static HRESULT interp_typeof(exec_ctx_t *ctx) +static HRESULT interp_typeof(script_ctx_t *ctx) { const WCHAR *ret; jsval_t v; @@ -1779,7 +1738,7 @@ static HRESULT interp_typeof(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.4.7 */ -static HRESULT interp_minus(exec_ctx_t *ctx) +static HRESULT interp_minus(script_ctx_t *ctx) { double n; HRESULT hres; @@ -1794,7 +1753,7 @@ static HRESULT interp_minus(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.4.6 */ -static HRESULT interp_tonum(exec_ctx_t *ctx) +static HRESULT interp_tonum(script_ctx_t *ctx) { jsval_t v; double n; @@ -1803,7 +1762,7 @@ static HRESULT interp_tonum(exec_ctx_t *ctx) TRACE("\n"); v = stack_pop(ctx); - hres = to_number(ctx->script, v, &n); + hres = to_number(ctx, v, &n); jsval_release(v); if(FAILED(hres)) return hres; @@ -1812,7 +1771,7 @@ static HRESULT interp_tonum(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.3.1 */ -static HRESULT interp_postinc(exec_ctx_t *ctx) +static HRESULT interp_postinc(script_ctx_t *ctx) { const int arg = get_op_int(ctx, 0); IDispatch *obj; @@ -1824,15 +1783,15 @@ static HRESULT interp_postinc(exec_ctx_t *ctx) obj = stack_pop_objid(ctx, &id); if(!obj) - return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL); + return throw_type_error(ctx, JS_E_OBJECT_EXPECTED, NULL); - hres = disp_propget(ctx->script, obj, id, &v); + hres = disp_propget(ctx, obj, id, &v); if(SUCCEEDED(hres)) { double n; - hres = to_number(ctx->script, v, &n); + hres = to_number(ctx, v, &n); if(SUCCEEDED(hres)) - hres = disp_propput(ctx->script, obj, id, jsval_number(n+(double)arg)); + hres = disp_propput(ctx, obj, id, jsval_number(n+(double)arg)); if(FAILED(hres)) jsval_release(v); } @@ -1844,7 +1803,7 @@ static HRESULT interp_postinc(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.4.4, 11.4.5 */ -static HRESULT interp_preinc(exec_ctx_t *ctx) +static HRESULT interp_preinc(script_ctx_t *ctx) { const int arg = get_op_int(ctx, 0); IDispatch *obj; @@ -1857,17 +1816,17 @@ static HRESULT interp_preinc(exec_ctx_t *ctx) obj = stack_pop_objid(ctx, &id); if(!obj) - return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL); + return throw_type_error(ctx, JS_E_OBJECT_EXPECTED, NULL); - hres = disp_propget(ctx->script, obj, id, &v); + hres = disp_propget(ctx, obj, id, &v); if(SUCCEEDED(hres)) { double n; - hres = to_number(ctx->script, v, &n); + hres = to_number(ctx, v, &n); jsval_release(v); if(SUCCEEDED(hres)) { ret = n+(double)arg; - hres = disp_propput(ctx->script, obj, id, jsval_number(ret)); + hres = disp_propput(ctx, obj, id, jsval_number(ret)); } } IDispatch_Release(obj); @@ -1958,7 +1917,7 @@ static HRESULT equal_values(script_ctx_t *ctx, jsval_t lval, jsval_t rval, BOOL } /* ECMA-262 3rd Edition 11.9.1 */ -static HRESULT interp_eq(exec_ctx_t *ctx) +static HRESULT interp_eq(script_ctx_t *ctx) { jsval_t l, r; BOOL b; @@ -1969,7 +1928,7 @@ static HRESULT interp_eq(exec_ctx_t *ctx) TRACE("%s == %s\n", debugstr_jsval(l), debugstr_jsval(r)); - hres = equal_values(ctx->script, l, r, &b); + hres = equal_values(ctx, l, r, &b); jsval_release(l); jsval_release(r); if(FAILED(hres)) @@ -1979,7 +1938,7 @@ static HRESULT interp_eq(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.9.2 */ -static HRESULT interp_neq(exec_ctx_t *ctx) +static HRESULT interp_neq(script_ctx_t *ctx) { jsval_t l, r; BOOL b; @@ -1990,7 +1949,7 @@ static HRESULT interp_neq(exec_ctx_t *ctx) TRACE("%s != %s\n", debugstr_jsval(l), debugstr_jsval(r)); - hres = equal_values(ctx->script, l, r, &b); + hres = equal_values(ctx, l, r, &b); jsval_release(l); jsval_release(r); if(FAILED(hres)) @@ -2000,7 +1959,7 @@ static HRESULT interp_neq(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.9.4 */ -static HRESULT interp_eq2(exec_ctx_t *ctx) +static HRESULT interp_eq2(script_ctx_t *ctx) { jsval_t l, r; BOOL b; @@ -2021,7 +1980,7 @@ static HRESULT interp_eq2(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.9.5 */ -static HRESULT interp_neq2(exec_ctx_t *ctx) +static HRESULT interp_neq2(script_ctx_t *ctx) { jsval_t l, r; BOOL b; @@ -2078,7 +2037,7 @@ static HRESULT less_eval(script_ctx_t *ctx, jsval_t lval, jsval_t rval, BOOL gre } /* ECMA-262 3rd Edition 11.8.1 */ -static HRESULT interp_lt(exec_ctx_t *ctx) +static HRESULT interp_lt(script_ctx_t *ctx) { jsval_t l, r; BOOL b; @@ -2089,7 +2048,7 @@ static HRESULT interp_lt(exec_ctx_t *ctx) TRACE("%s < %s\n", debugstr_jsval(l), debugstr_jsval(r)); - hres = less_eval(ctx->script, l, r, FALSE, &b); + hres = less_eval(ctx, l, r, FALSE, &b); jsval_release(l); jsval_release(r); if(FAILED(hres)) @@ -2099,7 +2058,7 @@ static HRESULT interp_lt(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.8.1 */ -static HRESULT interp_lteq(exec_ctx_t *ctx) +static HRESULT interp_lteq(script_ctx_t *ctx) { jsval_t l, r; BOOL b; @@ -2110,7 +2069,7 @@ static HRESULT interp_lteq(exec_ctx_t *ctx) TRACE("%s <= %s\n", debugstr_jsval(l), debugstr_jsval(r)); - hres = less_eval(ctx->script, r, l, TRUE, &b); + hres = less_eval(ctx, r, l, TRUE, &b); jsval_release(l); jsval_release(r); if(FAILED(hres)) @@ -2120,7 +2079,7 @@ static HRESULT interp_lteq(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.8.2 */ -static HRESULT interp_gt(exec_ctx_t *ctx) +static HRESULT interp_gt(script_ctx_t *ctx) { jsval_t l, r; BOOL b; @@ -2131,7 +2090,7 @@ static HRESULT interp_gt(exec_ctx_t *ctx) TRACE("%s > %s\n", debugstr_jsval(l), debugstr_jsval(r)); - hres = less_eval(ctx->script, r, l, FALSE, &b); + hres = less_eval(ctx, r, l, FALSE, &b); jsval_release(l); jsval_release(r); if(FAILED(hres)) @@ -2141,7 +2100,7 @@ static HRESULT interp_gt(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.8.4 */ -static HRESULT interp_gteq(exec_ctx_t *ctx) +static HRESULT interp_gteq(script_ctx_t *ctx) { jsval_t l, r; BOOL b; @@ -2152,7 +2111,7 @@ static HRESULT interp_gteq(exec_ctx_t *ctx) TRACE("%s >= %s\n", debugstr_jsval(l), debugstr_jsval(r)); - hres = less_eval(ctx->script, l, r, TRUE, &b); + hres = less_eval(ctx, l, r, TRUE, &b); jsval_release(l); jsval_release(r); if(FAILED(hres)) @@ -2162,7 +2121,7 @@ static HRESULT interp_gteq(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.4.8 */ -static HRESULT interp_bneg(exec_ctx_t *ctx) +static HRESULT interp_bneg(script_ctx_t *ctx) { jsval_t v; INT i; @@ -2171,7 +2130,7 @@ static HRESULT interp_bneg(exec_ctx_t *ctx) TRACE("\n"); v = stack_pop(ctx); - hres = to_int32(ctx->script, v, &i); + hres = to_int32(ctx, v, &i); jsval_release(v); if(FAILED(hres)) return hres; @@ -2180,7 +2139,7 @@ static HRESULT interp_bneg(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.4.9 */ -static HRESULT interp_neg(exec_ctx_t *ctx) +static HRESULT interp_neg(script_ctx_t *ctx) { jsval_t v; BOOL b; @@ -2198,7 +2157,7 @@ static HRESULT interp_neg(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.7.1 */ -static HRESULT interp_lshift(exec_ctx_t *ctx) +static HRESULT interp_lshift(script_ctx_t *ctx) { DWORD r; INT l; @@ -2216,7 +2175,7 @@ static HRESULT interp_lshift(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.7.2 */ -static HRESULT interp_rshift(exec_ctx_t *ctx) +static HRESULT interp_rshift(script_ctx_t *ctx) { DWORD r; INT l; @@ -2234,7 +2193,7 @@ static HRESULT interp_rshift(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.7.3 */ -static HRESULT interp_rshift2(exec_ctx_t *ctx) +static HRESULT interp_rshift2(script_ctx_t *ctx) { DWORD r, l; HRESULT hres; @@ -2251,7 +2210,7 @@ static HRESULT interp_rshift2(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.13.1 */ -static HRESULT interp_assign(exec_ctx_t *ctx) +static HRESULT interp_assign(script_ctx_t *ctx) { IDispatch *disp; DISPID id; @@ -2265,10 +2224,10 @@ static HRESULT interp_assign(exec_ctx_t *ctx) disp = stack_pop_objid(ctx, &id); if(!disp) { jsval_release(v); - return throw_reference_error(ctx->script, JS_E_ILLEGAL_ASSIGN, NULL); + return throw_reference_error(ctx, JS_E_ILLEGAL_ASSIGN, NULL); } - hres = disp_propput(ctx->script, disp, id, v); + hres = disp_propput(ctx, disp, id, v); IDispatch_Release(disp); if(FAILED(hres)) { jsval_release(v); @@ -2279,7 +2238,7 @@ static HRESULT interp_assign(exec_ctx_t *ctx) } /* JScript extension */ -static HRESULT interp_assign_call(exec_ctx_t *ctx) +static HRESULT interp_assign_call(script_ctx_t *ctx) { const unsigned argc = get_op_uint(ctx, 0); IDispatch *disp; @@ -2291,9 +2250,9 @@ static HRESULT interp_assign_call(exec_ctx_t *ctx) disp = stack_topn_objid(ctx, argc+1, &id); if(!disp) - return throw_reference_error(ctx->script, JS_E_ILLEGAL_ASSIGN, NULL); + return throw_reference_error(ctx, JS_E_ILLEGAL_ASSIGN, NULL); - hres = disp_call(ctx->script, disp, id, DISPATCH_PROPERTYPUT, argc+1, stack_args(ctx, argc+1), NULL); + hres = disp_call(ctx, disp, id, DISPATCH_PROPERTYPUT, argc+1, stack_args(ctx, argc+1), NULL); if(FAILED(hres)) return hres; @@ -2302,24 +2261,24 @@ static HRESULT interp_assign_call(exec_ctx_t *ctx) return stack_push(ctx, v); } -static HRESULT interp_undefined(exec_ctx_t *ctx) +static HRESULT interp_undefined(script_ctx_t *ctx) { TRACE("\n"); return stack_push(ctx, jsval_undefined()); } -static HRESULT interp_jmp(exec_ctx_t *ctx) +static HRESULT interp_jmp(script_ctx_t *ctx) { const unsigned arg = get_op_uint(ctx, 0); TRACE("%u\n", arg); - ctx->ip = arg; + jmp_abs(ctx, arg); return S_OK; } -static HRESULT interp_jmp_z(exec_ctx_t *ctx) +static HRESULT interp_jmp_z(script_ctx_t *ctx) { const unsigned arg = get_op_uint(ctx, 0); BOOL b; @@ -2335,13 +2294,13 @@ static HRESULT interp_jmp_z(exec_ctx_t *ctx) return hres; if(b) - ctx->ip++; + jmp_next(ctx); else - ctx->ip = arg; + jmp_abs(ctx, arg); return S_OK; } -static HRESULT interp_pop(exec_ctx_t *ctx) +static HRESULT interp_pop(script_ctx_t *ctx) { const unsigned arg = get_op_uint(ctx, 0); @@ -2351,24 +2310,51 @@ static HRESULT interp_pop(exec_ctx_t *ctx) return S_OK; } -static HRESULT interp_ret(exec_ctx_t *ctx) +static HRESULT interp_ret(script_ctx_t *ctx) { + const unsigned clear_ret = get_op_uint(ctx, 0); + call_frame_t *frame = ctx->call_ctx; + TRACE("\n"); - ctx->ip = -1; + if(clear_ret) + jsval_release(steal_ret(frame)); + + if((frame->flags & EXEC_CONSTRUCTOR) && !is_object_instance(frame->ret)) { + jsval_release(frame->ret); + IDispatch_AddRef(frame->this_obj); + frame->ret = jsval_disp(frame->this_obj); + } + + jmp_abs(ctx, -1); return S_OK; } -static HRESULT interp_setret(exec_ctx_t *ctx) +static HRESULT interp_setret(script_ctx_t *ctx) { + call_frame_t *frame = ctx->call_ctx; + TRACE("\n"); - jsval_release(ctx->ret); - ctx->ret = stack_pop(ctx); + jsval_release(frame->ret); + frame->ret = stack_pop(ctx); return S_OK; } -typedef HRESULT (*op_func_t)(exec_ctx_t*); +static HRESULT interp_push_ret(script_ctx_t *ctx) +{ + call_frame_t *frame = ctx->call_ctx; + HRESULT hres; + + TRACE("\n"); + + hres = stack_push(ctx, frame->ret); + if(SUCCEEDED(hres)) + frame->ret = jsval_undefined(); + return hres; +} + +typedef HRESULT (*op_func_t)(script_ctx_t*); static const op_func_t op_funcs[] = { #define X(x,a,b,c) interp_##x, @@ -2382,27 +2368,65 @@ OP_LIST #undef X }; -static HRESULT unwind_exception(exec_ctx_t *ctx) +static void release_call_frame(call_frame_t *frame) +{ + if(frame->arguments_obj) { + /* Reset arguments value to cut the reference cycle. Note that since all activation contexts have + * their own arguments property, it's impossible to use prototype's one during name lookup */ + static const WCHAR argumentsW[] = {'a','r','g','u','m','e','n','t','s',0}; + jsdisp_propput_name(frame->variable_obj, argumentsW, jsval_undefined()); + jsdisp_release(frame->arguments_obj); + } + if(frame->function_instance) + jsdisp_release(frame->function_instance); + if(frame->variable_obj) + jsdisp_release(frame->variable_obj); + if(frame->this_obj) + IDispatch_Release(frame->this_obj); + if(frame->scope) + scope_release(frame->scope); + jsval_release(frame->ret); + release_bytecode(frame->bytecode); + heap_free(frame); +} + +static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres) { except_frame_t *except_frame; + call_frame_t *frame; jsval_t except_val; BSTR ident; HRESULT hres; - except_frame = ctx->except_frame; - ctx->except_frame = except_frame->next; + for(frame = ctx->call_ctx; !frame->except_frame; frame = ctx->call_ctx) { + DWORD flags; - assert(except_frame->stack_top <= ctx->top); - stack_popn(ctx, ctx->top - except_frame->stack_top); + while(frame->scope != frame->base_scope) + scope_pop(&frame->scope); - while(except_frame->scope != ctx->scope_chain) - scope_pop(&ctx->scope_chain); + stack_popn(ctx, ctx->stack_top-frame->stack_base); - ctx->ip = except_frame->catch_off; + ctx->call_ctx = frame->prev_frame; + flags = frame->flags; + release_call_frame(frame); + if(!(flags & EXEC_RETURN_TO_INTERP)) + return exception_hres; + } - except_val = ctx->script->ei.val; - ctx->script->ei.val = jsval_undefined(); - clear_ei(ctx->script); + except_frame = frame->except_frame; + frame->except_frame = except_frame->next; + + assert(except_frame->stack_top <= ctx->stack_top); + stack_popn(ctx, ctx->stack_top - except_frame->stack_top); + + while(except_frame->scope != frame->scope) + scope_pop(&frame->scope); + + frame->ip = except_frame->catch_off; + + except_val = ctx->ei.val; + ctx->ei.val = jsval_undefined(); + clear_ei(ctx); ident = except_frame->ident; heap_free(except_frame); @@ -2410,7 +2434,7 @@ static HRESULT unwind_exception(exec_ctx_t *ctx) if(ident) { jsdisp_t *scope_obj; - hres = create_dispex(ctx->script, NULL, NULL, &scope_obj); + hres = create_dispex(ctx, NULL, NULL, &scope_obj); if(SUCCEEDED(hres)) { hres = jsdisp_propput_name(scope_obj, ident, except_val); if(FAILED(hres)) @@ -2420,7 +2444,7 @@ static HRESULT unwind_exception(exec_ctx_t *ctx) if(FAILED(hres)) return hres; - hres = scope_push(ctx->scope_chain, scope_obj, to_disp(scope_obj), &ctx->scope_chain); + hres = scope_push(frame->scope, scope_obj, to_disp(scope_obj), &frame->scope); jsdisp_release(scope_obj); }else { hres = stack_push(ctx, except_val); @@ -2433,65 +2457,45 @@ static HRESULT unwind_exception(exec_ctx_t *ctx) return hres; } -static HRESULT enter_bytecode(script_ctx_t *ctx, bytecode_t *code, function_code_t *func, jsval_t *ret) +static HRESULT enter_bytecode(script_ctx_t *ctx, jsval_t *r) { - exec_ctx_t *exec_ctx = ctx->exec_ctx; - except_frame_t *prev_except_frame; - function_code_t *prev_func; - unsigned prev_ip, prev_top; - scope_chain_t *prev_scope; - bytecode_t *prev_code; + call_frame_t *frame; jsop_t op; HRESULT hres = S_OK; TRACE("\n"); - prev_top = exec_ctx->top; - prev_scope = exec_ctx->scope_chain; - prev_except_frame = exec_ctx->except_frame; - prev_ip = exec_ctx->ip; - prev_code = exec_ctx->code; - prev_func = exec_ctx->func_code; - exec_ctx->ip = func->instr_off; - exec_ctx->except_frame = NULL; - exec_ctx->code = code; - exec_ctx->func_code = func; - - while(exec_ctx->ip != -1) { - op = code->instrs[exec_ctx->ip].op; - hres = op_funcs[op](exec_ctx); + while(1) { + frame = ctx->call_ctx; + op = frame->bytecode->instrs[frame->ip].op; + hres = op_funcs[op](ctx); if(FAILED(hres)) { TRACE("EXCEPTION %08x\n", hres); - if(!exec_ctx->except_frame) - break; - - hres = unwind_exception(exec_ctx); + hres = unwind_exception(ctx, hres); if(FAILED(hres)) + return hres; + }else if(frame->ip == -1) { + const DWORD return_to_interp = frame->flags & EXEC_RETURN_TO_INTERP; + + assert(ctx->stack_top == frame->stack_base); + assert(frame->scope == frame->base_scope); + + ctx->call_ctx = frame->prev_frame; + if(return_to_interp) { + clear_ret(ctx->call_ctx); + ctx->call_ctx->ret = steal_ret(frame); + }else if(r) { + *r = steal_ret(frame); + } + release_call_frame(frame); + if(!return_to_interp) break; }else { - exec_ctx->ip += op_move[op]; + frame->ip += op_move[op]; } } - exec_ctx->ip = prev_ip; - exec_ctx->except_frame = prev_except_frame; - exec_ctx->code = prev_code; - exec_ctx->func_code = prev_func; - - if(FAILED(hres)) { - while(exec_ctx->scope_chain != prev_scope) - scope_pop(&exec_ctx->scope_chain); - stack_popn(exec_ctx, exec_ctx->top-prev_top); - return hres; - } - - assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top); - assert(exec_ctx->scope_chain == prev_scope); - assert(exec_ctx->top == prev_top); - - *ret = exec_ctx->ret; - exec_ctx->ret = jsval_undefined(); return S_OK; } @@ -2532,54 +2536,94 @@ static HRESULT bind_event_target(script_ctx_t *ctx, function_code_t *func, jsdis return hres; } -HRESULT exec_source(exec_ctx_t *ctx, bytecode_t *code, function_code_t *func, BOOL from_eval, jsval_t *ret) +HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, function_code_t *function, scope_chain_t *scope, + IDispatch *this_obj, jsdisp_t *function_instance, jsdisp_t *variable_obj, jsdisp_t *arguments_obj, jsval_t *r) { - exec_ctx_t *prev_ctx; - jsval_t val; + call_frame_t *frame; unsigned i; - HRESULT hres = S_OK; + HRESULT hres; - for(i = 0; i < func->func_cnt; i++) { + for(i = 0; i < function->func_cnt; i++) { jsdisp_t *func_obj; - if(!func->funcs[i].name) + if(!function->funcs[i].name) continue; - hres = create_source_function(ctx->script, code, func->funcs+i, ctx->scope_chain, &func_obj); + hres = create_source_function(ctx, bytecode, function->funcs+i, scope, &func_obj); if(FAILED(hres)) return hres; - if(func->funcs[i].event_target) - hres = bind_event_target(ctx->script, func->funcs+i, func_obj); + if(function->funcs[i].event_target) + hres = bind_event_target(ctx, function->funcs+i, func_obj); else - hres = jsdisp_propput_name(ctx->var_disp, func->funcs[i].name, jsval_obj(func_obj)); + hres = jsdisp_propput_name(variable_obj, function->funcs[i].name, jsval_obj(func_obj)); jsdisp_release(func_obj); if(FAILED(hres)) return hres; } - for(i=0; i < func->var_cnt; i++) { - if(!ctx->is_global || !lookup_global_members(ctx->script, func->variables[i], NULL)) { + for(i=0; i < function->var_cnt; i++) { + if(!(flags & EXEC_GLOBAL) || !lookup_global_members(ctx, function->variables[i], NULL)) { DISPID id = 0; - hres = jsdisp_get_id(ctx->var_disp, func->variables[i], fdexNameEnsure, &id); + hres = jsdisp_get_id(variable_obj, function->variables[i], fdexNameEnsure, &id); if(FAILED(hres)) return hres; } } - prev_ctx = ctx->script->exec_ctx; - ctx->script->exec_ctx = ctx; + /* ECMA-262 3rd Edition 11.2.3.7 */ + if(this_obj) { + jsdisp_t *jsthis; - hres = enter_bytecode(ctx->script, code, func, &val); - assert(ctx->script->exec_ctx == ctx); - ctx->script->exec_ctx = prev_ctx; - if(FAILED(hres)) - return hres; + jsthis = iface_to_jsdisp((IUnknown*)this_obj); + if(jsthis) { + if(jsthis->builtin_info->class == JSCLASS_GLOBAL || jsthis->builtin_info->class == JSCLASS_NONE) + this_obj = NULL; + jsdisp_release(jsthis); + } + } - if(ret) - *ret = val; + frame = heap_alloc_zero(sizeof(*frame)); + if(!frame) + return E_OUTOFMEMORY; + + frame->bytecode = bytecode_addref(bytecode); + frame->function = function; + frame->ip = function->instr_off; + frame->stack_base = ctx->stack_top; + frame->ret = jsval_undefined(); + if(scope) + frame->base_scope = frame->scope = scope_addref(scope); + + if(this_obj) + frame->this_obj = this_obj; + else if(ctx->host_global) + frame->this_obj = ctx->host_global; else - jsval_release(val); - return S_OK; + frame->this_obj = to_disp(ctx->global); + IDispatch_AddRef(frame->this_obj); + + if(function_instance) + frame->function_instance = jsdisp_addref(function_instance); + if(arguments_obj) + frame->arguments_obj = jsdisp_addref(arguments_obj); + + frame->flags = flags; + frame->variable_obj = jsdisp_addref(variable_obj); + + frame->prev_frame = ctx->call_ctx; + ctx->call_ctx = frame; + + if(flags & EXEC_RETURN_TO_INTERP) { + /* + * We're called directly from interpreter, so we may just setup call frame and return. + * Already running interpreter will take care of execution. + */ + if(r) + *r = jsval_undefined(); + return S_OK; + } + + return enter_bytecode(ctx, r); } diff --git a/reactos/dll/win32/jscript/engine.h b/reactos/dll/win32/jscript/engine.h index 95612315e15..686e995e29f 100644 --- a/reactos/dll/win32/jscript/engine.h +++ b/reactos/dll/win32/jscript/engine.h @@ -72,6 +72,7 @@ X(postinc, 1, ARG_INT, 0) \ X(preinc, 1, ARG_INT, 0) \ X(push_except,1, ARG_ADDR, ARG_BSTR) \ + X(push_ret, 1, 0,0) \ X(push_scope, 1, 0,0) \ X(regexp, 1, ARG_STR, ARG_UINT) \ X(rshift, 1, 0,0) \ @@ -169,9 +170,10 @@ typedef struct _bytecode_t { HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,const WCHAR*,BOOL,BOOL,bytecode_t**) DECLSPEC_HIDDEN; void release_bytecode(bytecode_t*) DECLSPEC_HIDDEN; -static inline void bytecode_addref(bytecode_t *code) +static inline bytecode_t *bytecode_addref(bytecode_t *code) { code->ref++; + return code; } typedef struct _scope_chain_t { @@ -184,41 +186,41 @@ typedef struct _scope_chain_t { HRESULT scope_push(scope_chain_t*,jsdisp_t*,IDispatch*,scope_chain_t**) DECLSPEC_HIDDEN; void scope_release(scope_chain_t*) DECLSPEC_HIDDEN; -static inline void scope_addref(scope_chain_t *scope) +static inline scope_chain_t *scope_addref(scope_chain_t *scope) { scope->ref++; + return scope; } typedef struct _except_frame_t except_frame_t; struct _parser_ctx_t; -struct _exec_ctx_t { - LONG ref; - - struct _parser_ctx_t *parser; - bytecode_t *code; - script_ctx_t *script; - scope_chain_t *scope_chain; - jsdisp_t *var_disp; - IDispatch *this_obj; - function_code_t *func_code; - BOOL is_global; - - jsval_t *stack; - unsigned stack_size; - unsigned top; +typedef struct _call_frame_t { + unsigned ip; except_frame_t *except_frame; + unsigned stack_base; + scope_chain_t *scope; + scope_chain_t *base_scope; + jsval_t ret; - unsigned ip; -}; + IDispatch *this_obj; + jsdisp_t *function_instance; + jsdisp_t *variable_obj; + jsdisp_t *arguments_obj; + DWORD flags; -static inline void exec_addref(exec_ctx_t *ctx) -{ - ctx->ref++; -} + bytecode_t *bytecode; + function_code_t *function; + + struct _call_frame_t *prev_frame; +} call_frame_t; + +#define EXEC_GLOBAL 0x0001 +#define EXEC_CONSTRUCTOR 0x0002 +#define EXEC_RETURN_TO_INTERP 0x0004 + +HRESULT exec_source(script_ctx_t*,DWORD,bytecode_t*,function_code_t*,scope_chain_t*,IDispatch*, + jsdisp_t*,jsdisp_t*,jsdisp_t*,jsval_t*) DECLSPEC_HIDDEN; -void exec_release(exec_ctx_t*) DECLSPEC_HIDDEN; -HRESULT create_exec_ctx(script_ctx_t*,IDispatch*,jsdisp_t*,scope_chain_t*,BOOL,exec_ctx_t**) DECLSPEC_HIDDEN; -HRESULT exec_source(exec_ctx_t*,bytecode_t*,function_code_t*,BOOL,jsval_t*) DECLSPEC_HIDDEN; HRESULT create_source_function(script_ctx_t*,bytecode_t*,function_code_t*,scope_chain_t*,jsdisp_t**) DECLSPEC_HIDDEN; diff --git a/reactos/dll/win32/jscript/function.c b/reactos/dll/win32/jscript/function.c index 91867962852..431972188e9 100644 --- a/reactos/dll/win32/jscript/function.c +++ b/reactos/dll/win32/jscript/function.c @@ -27,7 +27,6 @@ typedef struct { bytecode_t *code; function_code_t *func_code; DWORD length; - jsdisp_t *arguments; } FunctionInstance; typedef struct { @@ -196,10 +195,9 @@ static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, un } static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, unsigned argc, jsval_t *argv, - jsval_t *r) + BOOL is_constructor, BOOL caller_execs_source, jsval_t *r) { jsdisp_t *var_disp, *arg_disp; - exec_ctx_t *exec_ctx; scope_chain_t *scope; HRESULT hres; @@ -232,57 +230,23 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis hres = scope_push(function->scope_chain, var_disp, to_disp(var_disp), &scope); if(SUCCEEDED(hres)) { - hres = create_exec_ctx(ctx, this_obj, var_disp, scope, FALSE, &exec_ctx); + DWORD exec_flags = 0; + + if(caller_execs_source) + exec_flags |= EXEC_RETURN_TO_INTERP; + if(is_constructor) + exec_flags |= EXEC_CONSTRUCTOR; + hres = exec_source(ctx, exec_flags, function->code, function->func_code, scope, this_obj, + &function->dispex, var_disp, arg_disp, r); + scope_release(scope); - - if(SUCCEEDED(hres)) { - jsdisp_t *prev_args; - - prev_args = function->arguments; - function->arguments = arg_disp; - hres = exec_source(exec_ctx, function->code, function->func_code, FALSE, r); - function->arguments = prev_args; - - exec_release(exec_ctx); - } } - /* Reset arguments value to cut the reference cycle. Note that since all activation contexts have - * their own arguments property, it's impossible to use prototype's one during name lookup */ - jsdisp_propput_name(var_disp, argumentsW, jsval_undefined()); - jsdisp_release(arg_disp); jsdisp_release(var_disp); return hres; } -static HRESULT invoke_constructor(script_ctx_t *ctx, FunctionInstance *function, unsigned argc, jsval_t *argv, - jsval_t *r) -{ - jsdisp_t *this_obj; - jsval_t var; - HRESULT hres; - - hres = create_object(ctx, &function->dispex, &this_obj); - if(FAILED(hres)) - return hres; - - hres = invoke_source(ctx, function, to_disp(this_obj), argc, argv, &var); - if(FAILED(hres)) { - jsdisp_release(this_obj); - return hres; - } - - if(is_object_instance(var)) { - jsdisp_release(this_obj); - *r = var; - }else { - jsval_release(var); - *r = jsval_obj(this_obj); - } - return S_OK; -} - static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_disp, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { @@ -303,12 +267,12 @@ static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, } static HRESULT call_function(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, - unsigned argc, jsval_t *argv, jsval_t *r) + unsigned argc, jsval_t *argv, BOOL caller_execs_source, jsval_t *r) { if(function->value_proc) return invoke_value_proc(ctx, function, this_obj, DISPATCH_METHOD, argc, argv, r); - return invoke_source(ctx, function, this_obj, argc, argv, r); + return invoke_source(ctx, function, this_obj, argc, argv, FALSE, caller_execs_source, r); } static HRESULT function_to_string(FunctionInstance *function, jsstr_t **ret) @@ -343,6 +307,7 @@ static HRESULT function_to_string(FunctionInstance *function, jsstr_t **ret) HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { + const BOOL caller_execs_source = (flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE) != 0; FunctionInstance *function; TRACE("func %p this %p\n", func_this, jsthis); @@ -350,14 +315,25 @@ HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsi assert(is_class(func_this, JSCLASS_FUNCTION)); function = (FunctionInstance*)func_this; + flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK; if(function->value_proc) return invoke_value_proc(function->dispex.ctx, function, jsthis, flags, argc, argv, r); - if(flags == DISPATCH_CONSTRUCT) - return invoke_constructor(function->dispex.ctx, function, argc, argv, r); + if(flags == DISPATCH_CONSTRUCT) { + jsdisp_t *this_obj; + HRESULT hres; + + hres = create_object(function->dispex.ctx, &function->dispex, &this_obj); + if(FAILED(hres)) + return hres; + + hres = invoke_source(function->dispex.ctx, function, to_disp(this_obj), argc, argv, TRUE, caller_execs_source, r); + jsdisp_release(this_obj); + return hres; + } assert(flags == DISPATCH_METHOD); - return invoke_source(function->dispex.ctx, function, jsthis, argc, argv, r); + return invoke_source(function->dispex.ctx, function, jsthis, argc, argv, FALSE, caller_execs_source, r); } static HRESULT Function_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) @@ -476,7 +452,7 @@ static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un } if(SUCCEEDED(hres)) - hres = call_function(ctx, function, this_obj, cnt, args, r); + hres = call_function(ctx, function, this_obj, cnt, args, (flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE) != 0, r); if(this_obj) IDispatch_Release(this_obj); @@ -509,7 +485,7 @@ static HRESULT Function_call(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns cnt = argc-1; } - hres = call_function(ctx, function, this_obj, cnt, argv+1, r); + hres = call_function(ctx, function, this_obj, cnt, argv+1, (flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE) != 0, r); if(this_obj) IDispatch_Release(this_obj); @@ -552,10 +528,18 @@ HRESULT Function_get_value(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) static HRESULT Function_get_arguments(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { FunctionInstance *function = function_from_jsdisp(jsthis); + call_frame_t *frame; TRACE("\n"); - *r = function->arguments ? jsval_obj(jsdisp_addref(function->arguments)) : jsval_null(); + for(frame = ctx->call_ctx; frame; frame = frame->prev_frame) { + if(frame->function_instance == &function->dispex) { + *r = jsval_obj(jsdisp_addref(frame->arguments_obj)); + return S_OK; + } + } + + *r = jsval_null(); return S_OK; } diff --git a/reactos/dll/win32/jscript/global.c b/reactos/dll/win32/jscript/global.c index 35aa6941424..6348a7b20c6 100644 --- a/reactos/dll/win32/jscript/global.c +++ b/reactos/dll/win32/jscript/global.c @@ -175,9 +175,11 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u } /* ECMA-262 3rd Edition 15.1.2.1 */ -static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { + call_frame_t *frame; + DWORD exec_flags = 0; bytecode_t *code; const WCHAR *src; HRESULT hres; @@ -196,7 +198,7 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns return S_OK; } - if(!ctx->exec_ctx) { + if(!(frame = ctx->call_ctx)) { FIXME("No active exec_ctx\n"); return E_UNEXPECTED; } @@ -212,7 +214,12 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns return throw_syntax_error(ctx, hres, NULL); } - hres = exec_source(ctx->exec_ctx, code, &code->global_code, TRUE, r); + if(frame->flags & EXEC_GLOBAL) + exec_flags |= EXEC_GLOBAL; + if(flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE) + exec_flags |= EXEC_RETURN_TO_INTERP; + hres = exec_source(ctx, exec_flags, code, &code->global_code, frame->scope, + frame->this_obj, NULL, frame->variable_obj, NULL, r); release_bytecode(code); return hres; } diff --git a/reactos/dll/win32/jscript/jscript.c b/reactos/dll/win32/jscript/jscript.c index 2d7a7fd7475..3755448d425 100644 --- a/reactos/dll/win32/jscript/jscript.c +++ b/reactos/dll/win32/jscript/jscript.c @@ -66,6 +66,8 @@ void script_release(script_ctx_t *ctx) heap_pool_free(&ctx->tmp_heap); if(ctx->last_match) jsstr_release(ctx->last_match); + assert(!ctx->stack_top); + heap_free(ctx->stack); ctx->jscaller->ctx = NULL; IServiceProvider_Release(&ctx->jscaller->IServiceProvider_iface); @@ -92,18 +94,12 @@ static inline BOOL is_started(script_ctx_t *ctx) static HRESULT exec_global_code(JScript *This, bytecode_t *code) { - exec_ctx_t *exec_ctx; HRESULT hres; - hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, TRUE, &exec_ctx); - if(FAILED(hres)) - return hres; - IActiveScriptSite_OnEnterScript(This->site); clear_ei(This->ctx); - hres = exec_source(exec_ctx, code, &code->global_code, FALSE, NULL); - exec_release(exec_ctx); + hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, This->ctx->global, NULL, NULL); IActiveScriptSite_OnLeaveScript(This->site); return hres; @@ -764,26 +760,19 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface, return hres; if(dwFlags & SCRIPTTEXT_ISEXPRESSION) { - exec_ctx_t *exec_ctx; + jsval_t r; - hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, TRUE, &exec_ctx); + IActiveScriptSite_OnEnterScript(This->site); + + clear_ei(This->ctx); + hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, This->ctx->global, NULL, &r); if(SUCCEEDED(hres)) { - jsval_t r; - - IActiveScriptSite_OnEnterScript(This->site); - - clear_ei(This->ctx); - hres = exec_source(exec_ctx, code, &code->global_code, TRUE, &r); - if(SUCCEEDED(hres)) { - if(pvarResult) - hres = jsval_to_variant(r, pvarResult); - jsval_release(r); - } - exec_release(exec_ctx); - - IActiveScriptSite_OnLeaveScript(This->site); + if(pvarResult) + hres = jsval_to_variant(r, pvarResult); + jsval_release(r); } + IActiveScriptSite_OnLeaveScript(This->site); return hres; } diff --git a/reactos/dll/win32/jscript/jscript.h b/reactos/dll/win32/jscript/jscript.h index 02517fa8d13..274238d1c29 100644 --- a/reactos/dll/win32/jscript/jscript.h +++ b/reactos/dll/win32/jscript/jscript.h @@ -50,7 +50,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); typedef struct _jsval_t jsval_t; typedef struct _jsstr_t jsstr_t; typedef struct _script_ctx_t script_ctx_t; -typedef struct _exec_ctx_t exec_ctx_t; typedef struct _dispex_prop_t dispex_prop_t; typedef struct { @@ -116,6 +115,14 @@ extern HINSTANCE jscript_hinstance DECLSPEC_HIDDEN; #define PROPF_CONST 0x0800 #define PROPF_DONTDELETE 0x1000 +/* + * This is our internal dispatch flag informing calee that it's called directly from interpreter. + * If calee is executed as interpreted function, we may let already running interpreter to take + * of execution. + */ +#define DISPATCH_JSCRIPT_CALLEREXECSSOURCE 0x8000 +#define DISPATCH_JSCRIPT_INTERNAL_MASK DISPATCH_JSCRIPT_CALLEREXECSSOURCE + /* NOTE: Keep in sync with names in Object.toString implementation */ typedef enum { JSCLASS_NONE, @@ -399,7 +406,7 @@ struct _script_ctx_t { SCRIPTSTATE state; IActiveScript *active_script; - exec_ctx_t *exec_ctx; + struct _call_frame_t *call_ctx; named_item_t *named_items; IActiveScriptSite *site; IInternetHostSecurityManager *secmgr; @@ -414,6 +421,10 @@ struct _script_ctx_t { IDispatch *host_global; + jsval_t *stack; + unsigned stack_size; + unsigned stack_top; + jsstr_t *last_match; match_result_t match_parens[9]; DWORD last_match_index; @@ -478,6 +489,8 @@ HRESULT regexp_string_match(script_ctx_t*,jsdisp_t*,jsstr_t*,jsval_t*) DECLSPEC_ BOOL bool_obj_value(jsdisp_t*) DECLSPEC_HIDDEN; unsigned array_get_length(jsdisp_t*) DECLSPEC_HIDDEN; +HRESULT JSGlobal_eval(script_ctx_t*,vdisp_t*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; + static inline BOOL is_class(jsdisp_t *jsdisp, jsclass_t class) { return jsdisp->builtin_info->class == class; diff --git a/reactos/dll/win32/jscript/jsregexp.c b/reactos/dll/win32/jscript/jsregexp.c index 8920c11cdc7..3eab0587aad 100644 --- a/reactos/dll/win32/jscript/jsregexp.c +++ b/reactos/dll/win32/jscript/jsregexp.c @@ -257,8 +257,10 @@ static HRESULT RegExp_set_source(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t va static HRESULT RegExp_get_global(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { - FIXME("\n"); - return E_NOTIMPL; + TRACE("\n"); + + *r = jsval_bool(!!(regexp_from_jsdisp(jsthis)->jsregexp->flags & REG_GLOB)); + return S_OK; } static HRESULT RegExp_set_global(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) @@ -269,8 +271,10 @@ static HRESULT RegExp_set_global(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t va static HRESULT RegExp_get_ignoreCase(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { - FIXME("\n"); - return E_NOTIMPL; + TRACE("\n"); + + *r = jsval_bool(!!(regexp_from_jsdisp(jsthis)->jsregexp->flags & REG_FOLD)); + return S_OK; } static HRESULT RegExp_set_ignoreCase(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) @@ -281,8 +285,10 @@ static HRESULT RegExp_set_ignoreCase(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_ static HRESULT RegExp_get_multiline(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { - FIXME("\n"); - return E_NOTIMPL; + TRACE("\n"); + + *r = jsval_bool(!!(regexp_from_jsdisp(jsthis)->jsregexp->flags & REG_MULTILINE)); + return S_OK; } static HRESULT RegExp_set_multiline(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) diff --git a/reactos/dll/win32/jscript/lex.c b/reactos/dll/win32/jscript/lex.c index b4244ab26f5..2471aaa40dd 100644 --- a/reactos/dll/win32/jscript/lex.c +++ b/reactos/dll/win32/jscript/lex.c @@ -589,7 +589,7 @@ static int next_token(parser_ctx_t *ctx, void *lval) return '}'; case '.': - if(++ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { + if(ctx->ptr+1 < ctx->end && isdigitW(ctx->ptr[1])) { double n; HRESULT hres; hres = parse_decimal(&ctx->ptr, ctx->end, &n); @@ -600,6 +600,7 @@ static int next_token(parser_ctx_t *ctx, void *lval) *(literal_t**)lval = new_double_literal(ctx, n); return tNumericLiteral; } + ctx->ptr++; return '.'; case '<': diff --git a/reactos/dll/win32/jscript/string.c b/reactos/dll/win32/jscript/string.c index 35ca5ae13b7..02527dc0ac3 100644 --- a/reactos/dll/win32/jscript/string.c +++ b/reactos/dll/win32/jscript/string.c @@ -18,8 +18,6 @@ #include "jscript.h" -#define UINT32_MAX 0xffffffff - typedef struct { jsdisp_t dispex; jsstr_t *str; diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index c0b2e03c5e8..77585901c08 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -85,7 +85,7 @@ reactos/dll/win32/inseng # Synced to WineStaging-1.9.4 reactos/dll/win32/iphlpapi # Out of sync reactos/dll/win32/itircl # Synced to WineStaging-1.9.4 reactos/dll/win32/itss # Synced to WineStaging-1.9.4 -reactos/dll/win32/jscript # Synced to WineStaging-1.9.4 +reactos/dll/win32/jscript # Synced to WineStaging-1.9.11 reactos/dll/win32/jsproxy # Synced to WineStaging-1.9.4 reactos/dll/win32/loadperf # Synced to WineStaging-1.9.4 reactos/dll/win32/localspl # Synced to WineStaging-1.9.4