aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4proxy.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-06-20 13:14:55 +0200
committerLars Knoll <lars.knoll@qt.io>2018-06-26 10:03:53 +0000
commitc9fa5b8071f4a32afd05cc9fa5cd8ab28e60dc55 (patch)
treeebad47a92af84cb51a9049c805919f007697bdfc /src/qml/jsruntime/qv4proxy.cpp
parentd95b4826bdf94ad90ba90812cc07d18f3f37b9e9 (diff)
Implement defineProperty for proxy objects
Change-Id: I3de298060010d459f58fa4242b0a5ef17f60ffe4 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4proxy.cpp')
-rw-r--r--src/qml/jsruntime/qv4proxy.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp
index 06ed889c60..5b5149a2f4 100644
--- a/src/qml/jsruntime/qv4proxy.cpp
+++ b/src/qml/jsruntime/qv4proxy.cpp
@@ -292,6 +292,60 @@ PropertyAttributes ProxyObject::getOwnProperty(Managed *m, Identifier id, Proper
return resultAttributes;
}
+bool ProxyObject::defineOwnProperty(Managed *m, Identifier id, const Property *p, PropertyAttributes attrs)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedString prop(scope, scope.engine->newString(QStringLiteral("defineProperty")));
+ ScopedValue trap(scope, handler->get(prop));
+ if (scope.hasException())
+ return false;
+ if (trap->isNullOrUndefined())
+ return target->defineOwnProperty(id, p, attrs);
+ if (!trap->isFunctionObject()) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+
+ JSCallData cdata(scope, 3, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = id.isArrayIndex() ? Primitive::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asHeapObject();
+ cdata.args[2] = ObjectPrototype::fromPropertyDescriptor(scope.engine, p, attrs);
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ bool result = trapResult->toBoolean();
+ if (!result)
+ return false;
+
+ ScopedProperty targetDesc(scope);
+ PropertyAttributes targetAttributes = target->getOwnProperty(id, targetDesc);
+ bool extensibleTarget = target->isExtensible();
+ bool settingConfigFalse = attrs.hasConfigurable() && !attrs.isConfigurable();
+ if (targetAttributes == Attr_Invalid) {
+ if (!extensibleTarget || settingConfigFalse) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+ } else {
+ // ###
+ // if IsCompatiblePropertyDescriptor(extensibleTarget, Desc, targetDesc) is false throw a type error.
+ if (settingConfigFalse && targetAttributes.isConfigurable()) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool ProxyObject::isExtensible(const Managed *m)
{
Scope scope(m);