Fix some issues with the delete operator

Properly implement delete operator for identifiers
and local variables.

Change-Id: I8ac55edc80c31a94d11444c9f5c78caf4b131c95
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This commit is contained in:
Lars Knoll 2012-11-25 00:26:28 +01:00 committed by Simon Hausmann
parent 87b3179817
commit 15326415d1
8 changed files with 38 additions and 26 deletions

View File

@ -500,14 +500,9 @@ void __qmljs_llvm_delete_member(ExecutionContext *ctx, Value *result, Value *bas
*result = __qmljs_delete_member(ctx, *base, name);
}
void __qmljs_llvm_delete_property(ExecutionContext *ctx, Value *result, String *name)
void __qmljs_llvm_delete_name(ExecutionContext *ctx, Value *result, String *name)
{
*result = __qmljs_delete_property(ctx, name);
}
void __qmljs_llvm_delete_value(ExecutionContext *ctx, Value *result, Value *value)
{
*result = __qmljs_delete_value(ctx, *value);
*result = __qmljs_delete_name(ctx, name);
}
} // extern "C"

View File

@ -262,11 +262,11 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
MOTH_END_INSTR(CallBuiltinDeleteSubscript)
MOTH_BEGIN_INSTR(CallBuiltinDeleteName)
TEMP(instr.targetTempIndex) = __qmljs_delete_property(context, instr.name);
TEMP(instr.targetTempIndex) = __qmljs_delete_name(context, instr.name);
MOTH_END_INSTR(CallBuiltinDeleteName)
MOTH_BEGIN_INSTR(CallBuiltinDeleteValue)
TEMP(instr.targetTempIndex) = __qmljs_delete_value(context, TEMP(instr.tempIndex));
TEMP(instr.targetTempIndex) = VM::Value::fromBoolean(false);
MOTH_END_INSTR(CallBuiltinDeleteValue)
MOTH_BEGIN_INSTR(CreateValue)

View File

@ -221,6 +221,26 @@ PropertyDescriptor *ExecutionContext::lookupPropertyDescriptor(String *name, Pro
return 0;
}
bool ExecutionContext::deleteProperty(String *name)
{
for (DeclarativeEnvironment *ctx = lexicalEnvironment; ctx; ctx = ctx->outer) {
if (ctx->withObject) {
DeclarativeEnvironment::With *w = ctx->withObject;
while (w) {
if (w->object->__hasProperty__(this, name))
w->object->__delete__(this, name);
w = w->next;
}
}
if (ctx->activation) {
if (ctx->activation->__hasProperty__(this, name))
ctx->activation->__delete__(this, name);
}
}
// ### throw syntax error in strict mode
return true;
}
void ExecutionContext::inplaceBitOp(Value value, String *name, BinOp op)
{
for (DeclarativeEnvironment *ctx = lexicalEnvironment; ctx; ctx = ctx->outer) {

View File

@ -118,6 +118,7 @@ struct ExecutionContext
PropertyDescriptor *lookupPropertyDescriptor(String *name, PropertyDescriptor *tmp);
void inplaceBitOp(Value value, String *name, BinOp op);
bool deleteProperty(String *name);
inline uint argumentCount() const { return variableEnvironment->argumentCount; }
inline Value argument(unsigned int index = 0)

View File

@ -411,7 +411,7 @@ struct Object {
virtual void __put__(ExecutionContext *ctx, String *name, const Value &value, bool throwException = false);
virtual bool __canPut__(ExecutionContext *ctx, String *name);
virtual bool __hasProperty__(ExecutionContext *ctx, String *name) const;
virtual bool __delete__(ExecutionContext *ctx, String *name, bool throwException);
virtual bool __delete__(ExecutionContext *ctx, String *name, bool throwException = false);
virtual bool __defineOwnProperty__(ExecutionContext *ctx, String *name, PropertyDescriptor *desc, bool throwException = false);
//

View File

@ -195,18 +195,9 @@ Value __qmljs_delete_member(ExecutionContext *ctx, Value base, String *name)
return Value::fromBoolean(obj.objectValue()->__delete__(ctx, name, true));
}
Value __qmljs_delete_property(ExecutionContext *ctx, String *name)
Value __qmljs_delete_name(ExecutionContext *ctx, String *name)
{
Object *obj = ctx->lexicalEnvironment->activation;
if (!obj)
obj = ctx->engine->globalObject.objectValue();
return Value::fromBoolean(obj->__delete__(ctx, name, true));
}
Value __qmljs_delete_value(ExecutionContext *ctx, Value value)
{
Q_UNUSED(value);
return __qmljs_throw_type_error(ctx); // ### throw syntax error
return Value::fromBoolean(ctx->deleteProperty(name));
}
Value __qmljs_add_helper(Value left, Value right, ExecutionContext *ctx)

View File

@ -177,8 +177,7 @@ Value __qmljs_not(Value value, ExecutionContext *ctx);
Value __qmljs_delete_subscript(ExecutionContext *ctx, Value base, Value index);
Value __qmljs_delete_member(ExecutionContext *ctx, Value base, String *name);
Value __qmljs_delete_property(ExecutionContext *ctx, String *name);
Value __qmljs_delete_value(ExecutionContext *ctx, Value value);
Value __qmljs_delete_name(ExecutionContext *ctx, String *name);
Value __qmljs_typeof(Value value, ExecutionContext *ctx);
void __qmljs_throw(Value value, ExecutionContext *context);

View File

@ -230,9 +230,15 @@ void InstructionSelection::callActivationProperty(IR::Call *call, IR::Temp *resu
} else if (IR::Subscript *ss = call->args->expr->asSubscript()) {
generateFunctionCall(result, __qmljs_delete_subscript, ContextRegister, ss->base->asTemp(), ss->index->asTemp());
return;
} else {
assert(!"builtin_delete: unimplemented");
Q_UNIMPLEMENTED();
} else if (IR::Name *n = call->args->expr->asName()) {
generateFunctionCall(result, __qmljs_delete_name, ContextRegister, n);
return;
} else if (call->args->expr->asTemp()){
// ### should throw in strict mode
Address dest = loadTempAddress(ScratchRegister, result);
Value v = Value::fromBoolean(false);
storeValue(v, dest);
return;
}
break;
}