diff options
author | Lars Knoll <lars.knoll@digia.com> | 2013-01-03 22:56:52 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2013-01-04 09:16:06 +0100 |
commit | 9d1e3e301d88a3dad6115043396fdd8d0ee31ca4 (patch) | |
tree | 65b2f130a4f24bc5e17b6140485ab1a5ff07cf51 | |
parent | 22480fc638afdc0bc860602381e81654e4cbfa3c (diff) |
Set data properties using __defineOwnProperties__
Properties in object literals are defined using
defineOwnProperty, so that they get set even if
the object prototype contains a non writable
property with the same name.
This fixes all remaining test cases for 11.1.5
Change-Id: I3928a144d09c51c5bf20a25bcb1c6c3c243975ee
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r-- | qmljs_runtime.cpp | 25 | ||||
-rw-r--r-- | qmljs_runtime.h | 1 | ||||
-rw-r--r-- | qv4codegen.cpp | 33 | ||||
-rw-r--r-- | qv4ir.cpp | 2 | ||||
-rw-r--r-- | qv4ir_p.h | 1 | ||||
-rw-r--r-- | qv4isel_masm.cpp | 17 |
6 files changed, 65 insertions, 14 deletions
diff --git a/qmljs_runtime.cpp b/qmljs_runtime.cpp index 73555c4c92..80e4a9ddc1 100644 --- a/qmljs_runtime.cpp +++ b/qmljs_runtime.cpp @@ -890,14 +890,33 @@ void __qmljs_builtin_declare_var(ExecutionContext *ctx, bool deletable, String * ctx->createMutableBinding(name, deletable); } +void __qmljs_builtin_define_property(Value object, String *name, Value val, ExecutionContext *ctx) +{ + Object *o = object.asObject(); + assert(o); + + PropertyDescriptor pd; + pd.value = val; + pd.type = PropertyDescriptor::Data; + pd.writable = PropertyDescriptor::Enabled; + pd.enumberable = PropertyDescriptor::Enabled; + pd.configurable = PropertyDescriptor::Enabled; + o->__defineOwnProperty__(ctx, name, &pd); +} + void __qmljs_builtin_define_getter_setter(Value object, String *name, Value getter, Value setter, ExecutionContext *ctx) { Object *o = object.asObject(); assert(o); - PropertyDescriptor desc; - desc.fromAccessor(getter.asFunctionObject(), setter.asFunctionObject()); - o->__defineOwnProperty__(ctx, name, &desc); + PropertyDescriptor pd; + pd.get = getter.asFunctionObject(); + pd.set = setter.asFunctionObject(); + pd.type = PropertyDescriptor::Accessor; + pd.writable = PropertyDescriptor::Undefined; + pd.enumberable = PropertyDescriptor::Enabled; + pd.configurable = PropertyDescriptor::Enabled; + o->__defineOwnProperty__(ctx, name, &pd); } Value __qmljs_increment(Value value, ExecutionContext *ctx) diff --git a/qmljs_runtime.h b/qmljs_runtime.h index 085125a9c4..66d9c780cc 100644 --- a/qmljs_runtime.h +++ b/qmljs_runtime.h @@ -104,6 +104,7 @@ void __qmljs_builtin_rethrow(ExecutionContext *context); void __qmljs_builtin_push_with(Value o, ExecutionContext *ctx); void __qmljs_builtin_pop_with(ExecutionContext *ctx); void __qmljs_builtin_declare_var(ExecutionContext *ctx, bool deletable, String *name); +void __qmljs_builtin_define_property(Value object, String *name, Value val, ExecutionContext *ctx); void __qmljs_builtin_define_getter_setter(Value object, String *name, Value getter, Value setter, ExecutionContext *ctx); // constructors diff --git a/qv4codegen.cpp b/qv4codegen.cpp index 9e4c0c90cd..6446a81111 100644 --- a/qv4codegen.cpp +++ b/qv4codegen.cpp @@ -1402,25 +1402,36 @@ bool Codegen::visit(ObjectLiteral *ast) } } if (!valueMap.isEmpty()) { - const unsigned getter = _block->newTemp(); - const unsigned setter = _block->newTemp(); + unsigned value = 0; + unsigned getter = 0; + unsigned setter = 0; for (QMap<QString, ObjectPropertyValue>::const_iterator it = valueMap.constBegin(); it != valueMap.constEnd(); ++it) { + IR::ExprList *args = _function->New<IR::ExprList>(); + IR::ExprList *current = args; + current->expr = _block->TEMP(t); + current->next = _function->New<IR::ExprList>(); + current = current->next; + current->expr = _block->NAME(it.key(), 0, 0); + current->next = _function->New<IR::ExprList>(); + current = current->next; + if (it->value) { - move(member(_block->TEMP(t), _function->newString(it.key())), it->value); + if (!value) + value = _block->newTemp(); + move(_block->TEMP(value), it->value); + // __qmljs_builtin_define_property(Value object, String *name, Value val, ExecutionContext *ctx) + current->expr = _block->TEMP(value); + _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_define_property, 0, 0), args)); } else { + if (!getter) { + getter = _block->newTemp(); + setter = _block->newTemp(); + } move(_block->TEMP(getter), it->getter ? _block->CLOSURE(it->getter) : _block->CONST(IR::UndefinedType, 0)); move(_block->TEMP(setter), it->setter ? _block->CLOSURE(it->setter) : _block->CONST(IR::UndefinedType, 0)); // __qmljs_builtin_define_getter_setter(Value object, String *name, Value getter, Value setter, ExecutionContext *ctx); - IR::ExprList *args = _function->New<IR::ExprList>(); - IR::ExprList *current = args; - current->expr = _block->TEMP(t); - current->next = _function->New<IR::ExprList>(); - current = current->next; - current->expr = _block->NAME(it.key(), 0, 0); - current->next = _function->New<IR::ExprList>(); - current = current->next; current->expr = _block->TEMP(getter); current->next = _function->New<IR::ExprList>(); current = current->next; @@ -244,6 +244,8 @@ static const char *builtin_to_string(Name::Builtin b) return "builtin_pop_with"; case IR::Name::builtin_declare_vars: return "builtin_declare_vars"; + case IR::Name::builtin_define_property: + return "builtin_define_property"; case IR::Name::builtin_define_getter_setter: return "builtin_define_getter_setter"; } @@ -285,6 +285,7 @@ struct Name: Expr { builtin_push_with, builtin_pop_with, builtin_declare_vars, + builtin_define_property, builtin_define_getter_setter }; diff --git a/qv4isel_masm.cpp b/qv4isel_masm.cpp index de6a67e3f3..3f44f260da 100644 --- a/qv4isel_masm.cpp +++ b/qv4isel_masm.cpp @@ -554,6 +554,23 @@ void InstructionSelection::callActivationProperty(IR::Call *call, IR::Temp *resu object, identifier(*name->id), getter, setter, Assembler::ContextRegister); break; } + case IR::Name::builtin_define_property: { + if (!call->args) + return; + IR::ExprList *args = call->args; + IR::Temp *object = args->expr->asTemp(); + assert(object); + args = args->next; + assert(args); + IR::Name *name = args->expr->asName(); + args = args->next; + assert(args); + IR::Temp *value = args->expr->asTemp(); + + generateFunctionCall(Assembler::Void, __qmljs_builtin_define_property, + object, identifier(*name->id), value, Assembler::ContextRegister); + break; + } } } |