diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-06-20 13:14:55 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-06-26 10:03:53 +0000 |
commit | c9fa5b8071f4a32afd05cc9fa5cd8ab28e60dc55 (patch) | |
tree | ebad47a92af84cb51a9049c805919f007697bdfc /src/qml/jsruntime/qv4proxy.cpp | |
parent | d95b4826bdf94ad90ba90812cc07d18f3f37b9e9 (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.cpp | 54 |
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); |