aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-01-03 22:56:52 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2013-01-04 09:16:06 +0100
commit9d1e3e301d88a3dad6115043396fdd8d0ee31ca4 (patch)
tree65b2f130a4f24bc5e17b6140485ab1a5ff07cf51
parent22480fc638afdc0bc860602381e81654e4cbfa3c (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.cpp25
-rw-r--r--qmljs_runtime.h1
-rw-r--r--qv4codegen.cpp33
-rw-r--r--qv4ir.cpp2
-rw-r--r--qv4ir_p.h1
-rw-r--r--qv4isel_masm.cpp17
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;
diff --git a/qv4ir.cpp b/qv4ir.cpp
index 67854133dd..68976fb39d 100644
--- a/qv4ir.cpp
+++ b/qv4ir.cpp
@@ -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";
}
diff --git a/qv4ir_p.h b/qv4ir_p.h
index 9cd0a4049b..962aa452dc 100644
--- a/qv4ir_p.h
+++ b/qv4ir_p.h
@@ -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;
+ }
}
}