aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4proxy.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-06-18 09:35:48 +0200
committerLars Knoll <lars.knoll@qt.io>2018-06-25 07:36:34 +0000
commit12319279538be50f83db3c2a1e68ccde8fd99814 (patch)
treedfc8c327ff68b1e94ae790216434505e9a88c37c /src/qml/jsruntime/qv4proxy.cpp
parent53bbda2dfeac39f6f28e507ea9a92965076b65e6 (diff)
Implement support for getOwnPropertyDescript and has in Proxy objects
Change-Id: Ie7a15afebdfbad31738d2d944d4128065b8a611f Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4proxy.cpp')
-rw-r--r--src/qml/jsruntime/qv4proxy.cpp107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp
index 11000123f6..7bde34f880 100644
--- a/src/qml/jsruntime/qv4proxy.cpp
+++ b/src/qml/jsruntime/qv4proxy.cpp
@@ -41,6 +41,7 @@
#include "qv4proxy_p.h"
#include "qv4symbol_p.h"
#include "qv4jscall_p.h"
+#include "qv4objectproto_p.h"
using namespace QV4;
@@ -192,6 +193,112 @@ bool ProxyObject::deleteIndexedProperty(Managed *m, uint index)
return deleteProperty(m, name);
}
+bool ProxyObject::hasProperty(const Managed *m, Identifier id)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler)
+ return scope.engine->throwTypeError();
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedString hasProp(scope, scope.engine->newString(QStringLiteral("has")));
+ ScopedValue trap(scope, handler->get(hasProp));
+ if (scope.hasException())
+ return Encode::undefined();
+ if (trap->isUndefined())
+ return target->hasProperty(m, id);
+ if (!trap->isFunctionObject())
+ return scope.engine->throwTypeError();
+
+ JSCallData cdata(scope, 2, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = id.isArrayIndex() ? Primitive::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asHeapObject();
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ bool result = trapResult->toBoolean();
+ if (!result) {
+ ScopedProperty targetDesc(scope);
+ PropertyAttributes attributes = target->getOwnProperty(id, targetDesc);
+ if (attributes != Attr_Invalid) {
+ if (!attributes.isConfigurable() || !target->isExtensible())
+ return scope.engine->throwTypeError();
+ }
+ }
+ return result;
+}
+
+PropertyAttributes ProxyObject::getOwnProperty(Managed *m, Identifier id, Property *p)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler) {
+ scope.engine->throwTypeError();
+ return Attr_Invalid;
+ }
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedString deleteProp(scope, scope.engine->newString(QStringLiteral("getOwnPropertyDescriptor")));
+ ScopedValue trap(scope, handler->get(deleteProp));
+ if (scope.hasException())
+ return Attr_Invalid;
+ if (trap->isUndefined())
+ return target->getOwnProperty(id, p);
+ if (!trap->isFunctionObject()) {
+ scope.engine->throwTypeError();
+ return Attr_Invalid;
+ }
+
+ JSCallData cdata(scope, 2, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = id.isArrayIndex() ? Primitive::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asHeapObject();
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ if (!trapResult->isObject() && !trapResult->isUndefined()) {
+ scope.engine->throwTypeError();
+ return Attr_Invalid;
+ }
+
+ ScopedProperty targetDesc(scope);
+ PropertyAttributes targetAttributes = target->getOwnProperty(id, targetDesc);
+ if (trapResult->isUndefined()) {
+ p->value = Encode::undefined();
+ if (targetAttributes == Attr_Invalid) {
+ p->value = Encode::undefined();
+ return Attr_Invalid;
+ }
+ if (!targetAttributes.isConfigurable() || !target->isExtensible()) {
+ scope.engine->throwTypeError();
+ return Attr_Invalid;
+ }
+ return Attr_Invalid;
+ }
+
+ //bool extensibleTarget = target->isExtensible();
+ ScopedProperty resultDesc(scope);
+ PropertyAttributes resultAttributes;
+ 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 (!resultAttributes.isConfigurable()) {
+ if (targetAttributes == Attr_Invalid || !targetAttributes.isConfigurable()) {
+ scope.engine->throwTypeError();
+ return Attr_Invalid;
+ }
+ }
+
+ p->value = resultDesc->value;
+ p->set = resultDesc->set;
+ return resultAttributes;
+}
+
//ReturnedValue ProxyObject::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
//{