diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/qml/jsruntime/qv4proxy.cpp | 54 | ||||
| -rw-r--r-- | src/qml/jsruntime/qv4proxy_p.h | 1 |
2 files changed, 55 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); diff --git a/src/qml/jsruntime/qv4proxy_p.h b/src/qml/jsruntime/qv4proxy_p.h index c249b9671c..306f3f00cb 100644 --- a/src/qml/jsruntime/qv4proxy_p.h +++ b/src/qml/jsruntime/qv4proxy_p.h @@ -92,6 +92,7 @@ struct ProxyObject: Object { static bool deleteProperty(Managed *m, Identifier id); static bool hasProperty(const Managed *m, Identifier id); static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p); + static bool defineOwnProperty(Managed *m, Identifier id, const Property *p, PropertyAttributes attrs); static bool isExtensible(const Managed *m); static bool preventExtensions(Managed *); static Heap::Object *getPrototypeOf(const Managed *); |
