Commit 162f2e6b authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

jscript: Moved eval return value logic to specific statement handlers.

parent 86787db2
......@@ -1016,21 +1016,12 @@ static HRESULT compile_block_statement(compiler_ctx_t *ctx, statement_t *iter)
{
HRESULT hres;
/* FIXME: do it only if needed */
if(!iter)
return push_instr(ctx, OP_undefined) ? S_OK : E_OUTOFMEMORY;
while(1) {
while(iter) {
hres = compile_statement(ctx, NULL, iter);
if(FAILED(hres))
return hres;
iter = iter->next;
if(!iter)
break;
if(!push_instr(ctx, OP_pop))
return E_OUTOFMEMORY;
}
return S_OK;
......@@ -1073,28 +1064,31 @@ static HRESULT compile_variable_list(compiler_ctx_t *ctx, variable_declaration_t
/* ECMA-262 3rd Edition 12.2 */
static HRESULT compile_var_statement(compiler_ctx_t *ctx, var_statement_t *stat)
{
HRESULT hres;
hres = compile_variable_list(ctx, stat->variable_list);
if(FAILED(hres))
return hres;
return push_instr(ctx, OP_undefined) ? S_OK : E_OUTOFMEMORY;
return compile_variable_list(ctx, stat->variable_list);
}
/* ECMA-262 3rd Edition 12.4 */
static HRESULT compile_expression_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
{
BOOL no_ret = FALSE;
HRESULT hres;
hres = compile_expression_noret(ctx, stat->expr, &no_ret);
if(FAILED(hres))
return hres;
if(!ctx->from_eval) {
BOOL no_ret = FALSE;
/* FIXME: that's a big potential optimization */
if(no_ret && !push_instr(ctx, OP_undefined))
return E_OUTOFMEMORY;
hres = compile_expression_noret(ctx, stat->expr, &no_ret);
if(FAILED(hres))
return hres;
if(!no_ret && !push_instr(ctx, OP_pop))
return E_OUTOFMEMORY;
}else {
hres = compile_expression(ctx, stat->expr);
if(FAILED(hres))
return hres;
if(!push_instr(ctx, OP_setret))
return E_OUTOFMEMORY;
}
return S_OK;
}
......@@ -1102,7 +1096,7 @@ static HRESULT compile_expression_statement(compiler_ctx_t *ctx, expression_stat
/* ECMA-262 3rd Edition 12.5 */
static HRESULT compile_if_statement(compiler_ctx_t *ctx, if_statement_t *stat)
{
unsigned jmp_else, jmp_end;
unsigned jmp_else;
HRESULT hres;
hres = compile_expression(ctx, stat->expr);
......@@ -1117,23 +1111,24 @@ static HRESULT compile_if_statement(compiler_ctx_t *ctx, if_statement_t *stat)
if(FAILED(hres))
return hres;
jmp_end = push_instr(ctx, OP_jmp);
if(!jmp_end)
return E_OUTOFMEMORY;
if(stat->else_stat) {
unsigned jmp_end;
set_arg_uint(ctx, jmp_else, ctx->code_off);
jmp_end = push_instr(ctx, OP_jmp);
if(!jmp_end)
return E_OUTOFMEMORY;
set_arg_uint(ctx, jmp_else, ctx->code_off);
if(stat->else_stat) {
hres = compile_statement(ctx, NULL, stat->else_stat);
if(FAILED(hres))
return hres;
set_arg_uint(ctx, jmp_end, ctx->code_off);
}else {
/* FIXME: We could sometimes avoid it */
if(!push_instr(ctx, OP_undefined))
return E_OUTOFMEMORY;
set_arg_uint(ctx, jmp_else, ctx->code_off);
}
set_arg_uint(ctx, jmp_end, ctx->code_off);
return S_OK;
}
......@@ -1152,12 +1147,9 @@ static HRESULT compile_while_statement(compiler_ctx_t *ctx, while_statement_t *s
if(!stat_ctx.continue_label)
return E_OUTOFMEMORY;
if(!stat->do_while) {
/* FIXME: avoid */
if(!push_instr(ctx, OP_undefined))
return E_OUTOFMEMORY;
jmp_off = ctx->code_off;
jmp_off = ctx->code_off;
if(!stat->do_while) {
label_set_addr(ctx, stat_ctx.continue_label);
hres = compile_expression(ctx, stat->expr);
if(FAILED(hres))
......@@ -1166,11 +1158,6 @@ static HRESULT compile_while_statement(compiler_ctx_t *ctx, while_statement_t *s
hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
if(FAILED(hres))
return hres;
if(!push_instr(ctx, OP_pop))
return E_OUTOFMEMORY;
}else {
jmp_off = ctx->code_off;
}
hres = compile_statement(ctx, &stat_ctx, stat->statement);
......@@ -1186,9 +1173,6 @@ static HRESULT compile_while_statement(compiler_ctx_t *ctx, while_statement_t *s
hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
if(FAILED(hres))
return hres;
if(!push_instr(ctx, OP_pop))
return E_OUTOFMEMORY;
}
hres = push_instr_uint(ctx, OP_jmp, jmp_off);
......@@ -1228,10 +1212,6 @@ static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat)
if(!stat_ctx.continue_label)
return E_OUTOFMEMORY;
/* FIXME: avoid */
if(!push_instr(ctx, OP_undefined))
return E_OUTOFMEMORY;
expr_off = ctx->code_off;
if(stat->expr) {
......@@ -1244,9 +1224,6 @@ static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat)
return hres;
}
if(!push_instr(ctx, OP_pop))
return E_OUTOFMEMORY;
hres = compile_statement(ctx, &stat_ctx, stat->statement);
if(FAILED(hres))
return hres;
......@@ -1317,10 +1294,6 @@ static HRESULT compile_forin_statement(compiler_ctx_t *ctx, forin_statement_t *s
if(FAILED(hres))
return hres;
/* FIXME: avoid */
if(!push_instr(ctx, OP_undefined))
return E_OUTOFMEMORY;
label_set_addr(ctx, stat_ctx.continue_label);
hres = push_instr_uint(ctx, OP_forin, stat_ctx.break_label);
if(FAILED(hres))
......@@ -1361,7 +1334,6 @@ static HRESULT pop_to_stat(compiler_ctx_t *ctx, BOOL var_stack, BOOL scope_stack
}
}
return S_OK;
}
......@@ -1415,9 +1387,6 @@ static HRESULT compile_continue_statement(compiler_ctx_t *ctx, branch_statement_
if(FAILED(hres))
return hres;
if(!push_instr(ctx, OP_undefined))
return E_OUTOFMEMORY;
return push_instr_uint(ctx, OP_jmp, pop_ctx->continue_label);
}
......@@ -1455,9 +1424,6 @@ static HRESULT compile_break_statement(compiler_ctx_t *ctx, branch_statement_t *
if(FAILED(hres))
return hres;
if(!push_instr(ctx, OP_undefined))
return E_OUTOFMEMORY;
return push_instr_uint(ctx, OP_jmp, pop_ctx->break_label);
}
......@@ -1475,11 +1441,14 @@ static HRESULT compile_return_statement(compiler_ctx_t *ctx, expression_statemen
if(FAILED(hres))
return hres;
if(stat->expr) {
if(stat->expr)
hres = compile_expression(ctx, stat->expr);
if(FAILED(hres))
return hres;
}
else
hres = push_instr(ctx, OP_undefined) ? S_OK : E_OUTOFMEMORY;
if(FAILED(hres))
return hres;
if(!push_instr(ctx, OP_setret))
return E_OUTOFMEMORY;
hres = pop_to_stat(ctx, FALSE, TRUE, NULL);
if(FAILED(hres))
......@@ -1607,26 +1576,14 @@ static HRESULT compile_switch_statement(compiler_ctx_t *ctx, switch_statement_t
set_arg_uint(ctx, iter->expr ? case_jmps[i++] : default_jmp, ctx->code_off);
if(iter->stat) {
for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter);
stat_iter = stat_iter->next) {
hres = compile_statement(ctx, &stat_ctx, stat_iter);
if(FAILED(hres))
break;
if(stat_iter->next && !push_instr(ctx, OP_pop)) {
hres = E_OUTOFMEMORY;
break;
}
}
for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter);
stat_iter = stat_iter->next) {
hres = compile_statement(ctx, &stat_ctx, stat_iter);
if(FAILED(hres))
break;
}else {
if(!push_instr(ctx, OP_undefined)) {
hres = E_OUTOFMEMORY;
break;
}
}
if(FAILED(hres))
break;
}
heap_free(case_jmps);
......@@ -1639,8 +1596,6 @@ static HRESULT compile_switch_statement(compiler_ctx_t *ctx, switch_statement_t
if(FAILED(hres))
return hres;
set_arg_uint(ctx, default_jmp, ctx->code_off);
if(!push_instr(ctx, OP_undefined))
return E_OUTOFMEMORY;
}
label_set_addr(ctx, stat_ctx.break_label);
......@@ -1714,10 +1669,6 @@ static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat)
}
if(stat->finally_statement) {
/* FIXME: avoid */
if(!push_instr(ctx, OP_pop))
return E_OUTOFMEMORY;
hres = compile_statement(ctx, stat->catch_block ? NULL : &finally_ctx, stat->finally_statement);
if(FAILED(hres))
return hres;
......@@ -1749,7 +1700,8 @@ static HRESULT compile_statement(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx,
hres = compile_continue_statement(ctx, (branch_statement_t*)stat);
break;
case STAT_EMPTY:
hres = push_instr(ctx, OP_undefined) ? S_OK : E_OUTOFMEMORY; /* FIXME */
/* nothing to do */
hres = S_OK;
break;
case STAT_EXPR:
hres = compile_expression_statement(ctx, (expression_statement_t*)stat);
......@@ -1883,8 +1835,6 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source,
resolve_labels(ctx, off);
if(!from_eval && !push_instr(ctx, OP_pop))
return E_OUTOFMEMORY;
if(!push_instr(ctx, OP_ret))
return E_OUTOFMEMORY;
......
......@@ -291,6 +291,7 @@ HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, jsdisp_t
ctx->ref = 1;
ctx->is_global = is_global;
ctx->ret = jsval_undefined();
/* ECMA-262 3rd Edition 11.2.3.7 */
if(this_obj) {
......@@ -340,6 +341,7 @@ void exec_release(exec_ctx_t *ctx)
IDispatch_Release(ctx->this_obj);
if(ctx->script)
script_release(ctx->script);
jsval_release(ctx->ret);
heap_free(ctx->stack);
heap_free(ctx);
}
......@@ -592,20 +594,16 @@ static HRESULT interp_forin(exec_ctx_t *ctx)
IDispatchEx *dispex;
DISPID id, var_id;
BSTR name = NULL;
jsval_t val;
HRESULT hres;
TRACE("\n");
val = stack_pop(ctx);
assert(is_number(stack_top(ctx)));
id = get_number(stack_top(ctx));
var_obj = stack_topn_objid(ctx, 1, &var_id);
if(!var_obj) {
FIXME("invalid ref\n");
jsval_release(val);
return E_FAIL;
}
......@@ -619,10 +617,8 @@ static HRESULT interp_forin(exec_ctx_t *ctx)
if(hres == S_OK)
hres = IDispatchEx_GetMemberName(dispex, id, &name);
IDispatchEx_Release(dispex);
if(FAILED(hres)) {
jsval_release(val);
if(FAILED(hres))
return hres;
}
}else {
TRACE("No IDispatchEx\n");
}
......@@ -636,7 +632,6 @@ static HRESULT interp_forin(exec_ctx_t *ctx)
if(!str)
return E_OUTOFMEMORY;
jsval_release(val);
stack_pop(ctx);
stack_push(ctx, jsval_number(id)); /* safe, just after pop() */
......@@ -649,7 +644,6 @@ static HRESULT interp_forin(exec_ctx_t *ctx)
}else {
stack_popn(ctx, 4);
ctx->ip = arg;
return stack_push(ctx, val);
}
return S_OK;
}
......@@ -795,8 +789,6 @@ static HRESULT interp_end_finally(exec_ctx_t *ctx)
TRACE("\n");
v = stack_pop(ctx);
assert(is_bool(stack_top(ctx)));
if(!get_bool(stack_top(ctx))) {
TRACE("passing exception\n");
......@@ -809,7 +801,7 @@ static HRESULT interp_end_finally(exec_ctx_t *ctx)
}
stack_popn(ctx, 2);
return stack_push(ctx, v);
return S_OK;
}
/* ECMA-262 3rd Edition 13 */
......@@ -2361,6 +2353,15 @@ static HRESULT interp_ret(exec_ctx_t *ctx)
return S_OK;
}
static HRESULT interp_setret(exec_ctx_t *ctx)
{
TRACE("\n");
jsval_release(ctx->ret);
ctx->ret = stack_pop(ctx);
return S_OK;
}
typedef HRESULT (*op_func_t)(exec_ctx_t*);
static const op_func_t op_funcs[] = {
......@@ -2421,10 +2422,6 @@ static HRESULT unwind_exception(exec_ctx_t *ctx)
return hres;
hres = stack_push(ctx, jsval_bool(FALSE));
if(FAILED(hres))
return hres;
hres = stack_push(ctx, jsval_undefined());
}
return hres;
......@@ -2485,11 +2482,10 @@ static HRESULT enter_bytecode(script_ctx_t *ctx, bytecode_t *code, function_code
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);
if(exec_ctx->top == prev_top)
*ret = jsval_undefined();
else
*ret = stack_pop(exec_ctx);
*ret = exec_ctx->ret;
exec_ctx->ret = jsval_undefined();
return S_OK;
}
......
......@@ -105,6 +105,7 @@ typedef struct {
X(typeofident,1, 0,0) \
X(refval, 1, 0,0) \
X(ret, 0, 0,0) \
X(setret, 1, 0,0) \
X(sub, 1, 0,0) \
X(undefined, 1, 0,0) \
X(var_set, 1, ARG_BSTR, 0) \
......@@ -238,6 +239,7 @@ struct _exec_ctx_t {
unsigned stack_size;
unsigned top;
except_frame_t *except_frame;
jsval_t ret;
unsigned ip;
};
......
......@@ -191,6 +191,12 @@ tmp = eval("1,2;");
ok(tmp === 2, "tmp = " + tmp);
tmp = eval("if(true) {3}");
ok(tmp === 3, "tmp = " + tmp);
testNoRes();
eval("testRes(); testRes()");
tmp = eval("3; if(false) {4;} else {};;;")
ok(tmp === 3, "tmp = " + tmp);
tmp = (function(){ return testRes();})();
var obj1 = new Object();
ok(typeof(obj1) === "object", "typeof(obj1) is not object");
......
......@@ -126,6 +126,8 @@ DEFINE_EXPECT(DeleteMemberByDispID);
#define DISPID_GLOBAL_TESTARGTYPES 0x1015
#define DISPID_GLOBAL_INTPROP 0x1016
#define DISPID_GLOBAL_DISPUNK 0x1017
#define DISPID_GLOBAL_TESTRES 0x1018
#define DISPID_GLOBAL_TESTNORES 0x1019
#define DISPID_GLOBAL_TESTPROPDELETE 0x2000
......@@ -598,6 +600,16 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD
return S_OK;
}
if(!strcmp_wa(bstrName, "testRes")) {
*pid = DISPID_GLOBAL_TESTRES;
return S_OK;
}
if(!strcmp_wa(bstrName, "testNoRes")) {
*pid = DISPID_GLOBAL_TESTNORES;
return S_OK;
}
if(strict_dispid_check && strcmp_wa(bstrName, "t"))
ok(0, "unexpected call %s\n", wine_dbgstr_w(bstrName));
return DISP_E_UNKNOWNNAME;
......@@ -735,6 +747,18 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid,
return S_OK;
case DISPID_GLOBAL_TESTRES:
ok(pvarRes != NULL, "pvarRes = NULL\n");
if(pvarRes)
V_VT(pvarRes) = VT_NULL;
return S_OK;
case DISPID_GLOBAL_TESTNORES:
ok(!pvarRes, "pvarRes != NULL\n");
if(pvarRes)
V_VT(pvarRes) = VT_NULL;
return S_OK;
case DISPID_GLOBAL_TESTOBJ:
ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags);
ok(pdp != NULL, "pdp == NULL\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment