diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-06-18 09:35:48 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-06-25 07:36:34 +0000 |
commit | 12319279538be50f83db3c2a1e68ccde8fd99814 (patch) | |
tree | dfc8c327ff68b1e94ae790216434505e9a88c37c /src/qml/jsruntime/qv4proxy.cpp | |
parent | 53bbda2dfeac39f6f28e507ea9a92965076b65e6 (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.cpp | 107 |
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) //{ |