jscript: Use bytecode for delete on array expression implementation.

This commit is contained in:
Jacek Caban 2011-11-30 10:14:22 +01:00 committed by Alexandre Julliard
parent 6c47177cb1
commit facc2189d2
5 changed files with 90 additions and 2 deletions

View File

@ -301,6 +301,34 @@ static HRESULT compile_interp_fallback(compiler_ctx_t *ctx, expression_t *expr)
return S_OK;
}
static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
{
HRESULT hres;
switch(expr->expression->type) {
case EXPR_ARRAY: {
array_expression_t *array_expr = (array_expression_t*)expr->expression;
hres = compile_expression(ctx, array_expr->member_expr);
if(FAILED(hres))
return hres;
hres = compile_expression(ctx, array_expr->expression);
if(FAILED(hres))
return hres;
if(push_instr(ctx, OP_delete) == -1)
return E_OUTOFMEMORY;
break;
}
default:
expr->expr.eval = delete_expression_eval;
return compile_interp_fallback(ctx, &expr->expr);
}
return S_OK;
}
static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
{
switch(literal->type) {
@ -352,6 +380,8 @@ static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr)
return compile_comma_expression(ctx, (binary_expression_t*)expr);
case EXPR_COND:
return compile_conditional_expression(ctx, (conditional_expression_t*)expr);
case EXPR_DELETE:
return compile_delete_expression(ctx, (unary_expression_t*)expr);
case EXPR_DIV:
return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
case EXPR_EQ:

View File

@ -2497,6 +2497,53 @@ HRESULT delete_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD fla
return return_bool(ret, b);
}
/* ECMA-262 3rd Edition 11.4.2 */
static HRESULT interp_delete(exec_ctx_t *ctx)
{
VARIANT *obj_var, *name_var;
IDispatchEx *dispex;
IDispatch *obj;
BSTR name;
BOOL ret;
HRESULT hres;
TRACE("\n");
name_var = stack_pop(ctx);
obj_var = stack_pop(ctx);
hres = to_object(ctx->parser->script, obj_var, &obj);
VariantClear(obj_var);
if(FAILED(hres)) {
VariantClear(name_var);
return hres;
}
hres = to_string(ctx->parser->script, name_var, &ctx->ei, &name);
VariantClear(name_var);
if(FAILED(hres)) {
IDispatch_Release(obj);
return hres;
}
hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
if(SUCCEEDED(hres)) {
hres = IDispatchEx_DeleteMemberByName(dispex, name, make_grfdex(ctx->parser->script, fdexNameCaseSensitive));
ret = TRUE;
IDispatchEx_Release(dispex);
}else {
hres = S_OK;
ret = FALSE;
}
IDispatch_Release(obj);
SysFreeString(name);
if(FAILED(hres))
return hres;
return stack_push_bool(ctx, ret);
}
/* ECMA-262 3rd Edition 11.4.2 */
static HRESULT interp_void(exec_ctx_t *ctx)
{
@ -3469,5 +3516,8 @@ HRESULT compiled_expression_eval(script_ctx_t *ctx, expression_t *expr, DWORD fl
if(FAILED(hres))
return hres;
return (expr->eval = interp_expression_eval)(ctx, expr, flags, ei, ret);
if(expr->eval == compiled_expression_eval)
expr->eval = interp_expression_eval;
return expr->eval(ctx, expr, flags, ei, ret);
}

View File

@ -45,6 +45,7 @@ typedef struct _func_stack {
X(add, 1, 0,0) \
X(bool, 1, ARG_INT, 0) \
X(bneg, 1, 0,0) \
X(delete, 1, 0,0) \
X(div, 1, 0,0) \
X(double, 1, ARG_SBL, 0) \
X(eq, 1, 0,0) \

View File

@ -1318,7 +1318,7 @@ static const expression_eval_t expression_eval_table[] = {
compiled_expression_eval,
compiled_expression_eval,
compiled_expression_eval,
delete_expression_eval,
compiled_expression_eval,
compiled_expression_eval,
typeof_expression_eval,
compiled_expression_eval,

View File

@ -830,9 +830,16 @@ tmp = new Object();
tmp.test = false;
ok((delete tmp.test) === true, "delete returned false");
ok(typeof(tmp.test) === "undefined", "tmp.test type = " + typeof(tmp.test));
ok(!("test" in tmp), "test is still in tmp after delete?");
for(iter in tmp)
ok(false, "tmp has prop " + iter);
tmp = new Object();
tmp.test = false;
ok((delete tmp["test"]) === true, "delete returned false");
ok(typeof(tmp.test) === "undefined", "tmp.test type = " + typeof(tmp.test));
ok(!("test" in tmp), "test is still in tmp after delete?");
tmp.testWith = true;
with(tmp)
ok(testWith === true, "testWith !== true");