aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-09-08 09:59:24 +0200
committerLars Knoll <lars.knoll@qt.io>2018-09-08 16:50:51 +0000
commit26dc00747e1e2632435d01b7562443dff4f2e7d3 (patch)
tree2eb62cf4fa67992b1f17001420e60a5fb200f973 /src/qml
parent321d1d3f9d6338d2f536d58492bb3e4a5dfb808e (diff)
Implement IsCompatiblePropertyDescriptor and use it in Proxy
Change-Id: I40bc5ce2858ebfe1afb04a7957a53114b37ef50f Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/jsruntime/qv4property_p.h34
-rw-r--r--src/qml/jsruntime/qv4proxy.cpp13
2 files changed, 42 insertions, 5 deletions
diff --git a/src/qml/jsruntime/qv4property_p.h b/src/qml/jsruntime/qv4property_p.h
index 26dc7a83c3..bad8eeb078 100644
--- a/src/qml/jsruntime/qv4property_p.h
+++ b/src/qml/jsruntime/qv4property_p.h
@@ -92,6 +92,40 @@ struct Property {
set = other->set;
}
+ // ES8, section 9.1.6.2/9,.1.6.3
+ bool isCompatible(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const {
+ if (otherAttrs.isEmpty())
+ return true;
+ if (!attrs.isConfigurable()) {
+ if (otherAttrs.hasConfigurable() && otherAttrs.isConfigurable())
+ return false;
+ if (otherAttrs.hasEnumerable() && otherAttrs.isEnumerable() != attrs.isEnumerable())
+ return false;
+ }
+ if (otherAttrs.isGeneric())
+ return true;
+ if (attrs.isData() != otherAttrs.isData()) {
+ if (!attrs.isConfigurable())
+ return false;
+ } else if (attrs.isData() && otherAttrs.isData()) {
+ if (!attrs.isConfigurable() && !attrs.isWritable()) {
+ if (otherAttrs.hasWritable() && otherAttrs.isWritable())
+ return false;
+ if (!other->value.isEmpty() && !value.sameValue(other->value))
+ return false;
+ }
+ } else if (attrs.isAccessor() && otherAttrs.isAccessor()) {
+ if (!attrs.isConfigurable()) {
+ if (!other->value.isEmpty() && !value.sameValue(other->value))
+ return false;
+ if (!other->set.isEmpty() && !set.sameValue(other->set))
+ return false;
+ }
+ }
+ return true;
+ }
+
+
explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(nullptr); }
Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter) {
value.setM(reinterpret_cast<Heap::Base *>(getter));
diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp
index d4f342c50e..19e46304af 100644
--- a/src/qml/jsruntime/qv4proxy.cpp
+++ b/src/qml/jsruntime/qv4proxy.cpp
@@ -277,9 +277,10 @@ PropertyAttributes ProxyObject::virtualGetOwnProperty(Managed *m, PropertyKey id
ObjectPrototype::toPropertyDescriptor(scope.engine, trapResult, resultDesc, &resultAttributes);
resultDesc->fullyPopulated(&resultAttributes);
- // ###
- //Let valid be IsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc).
- //If valid is false, throw a TypeError exception.
+ if (!targetDesc->isCompatible(targetAttributes, resultDesc, resultAttributes)) {
+ scope.engine->throwTypeError();
+ return Attr_Invalid;
+ }
if (!resultAttributes.isConfigurable()) {
if (targetAttributes == Attr_Invalid || !targetAttributes.isConfigurable()) {
@@ -336,8 +337,10 @@ bool ProxyObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Pro
return false;
}
} else {
- // ###
- // if IsCompatiblePropertyDescriptor(extensibleTarget, Desc, targetDesc) is false throw a type error.
+ if (!targetDesc->isCompatible(targetAttributes, p, attrs)) {
+ scope.engine->throwTypeError();
+ return false;
+ }
if (settingConfigFalse && targetAttributes.isConfigurable()) {
scope.engine->throwTypeError();
return false;