diff options
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 8 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4objectproto.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4proxy.cpp | 31 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4proxy_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4reflect.cpp | 3 |
6 files changed, 46 insertions, 3 deletions
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 751010fa4e..02acc1a5e0 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -1025,6 +1025,14 @@ bool Object::isExtensible(const Managed *m) return m->d()->internalClass->extensible; } +bool Object::preventExtensions(Managed *m) +{ + Q_ASSERT(m->isObject()); + Object *o = static_cast<Object *>(m); + o->setInternalClass(o->internalClass()->nonExtensible()); + return true; +} + bool Object::setArrayLength(uint newLen) { Q_ASSERT(isArrayObject()); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index a9851984e1..b55e8f25e2 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -178,6 +178,7 @@ struct ObjectVTable bool (*hasProperty)(const Managed *m, Identifier id); PropertyAttributes (*getOwnProperty)(Managed *m, Identifier id, Property *p); bool (*isExtensible)(const Managed *); + bool (*preventExtensions)(Managed *); qint64 (*getLength)(const Managed *m); void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); ReturnedValue (*instanceOf)(const Object *typeObject, const Value &var); @@ -198,6 +199,7 @@ const QV4::ObjectVTable classname::static_vtbl = \ hasProperty, \ getOwnProperty, \ isExtensible, \ + preventExtensions, \ getLength, \ advanceIterator, \ instanceOf \ @@ -304,6 +306,7 @@ struct Q_QML_EXPORT Object: Managed { void insertMember(StringOrSymbol *s, const Property *p, PropertyAttributes attributes); bool isExtensible() const { return vtable()->isExtensible(this); } + bool preventExtensions() { return vtable()->preventExtensions(this); } // Array handling @@ -441,6 +444,7 @@ protected: static bool hasProperty(const Managed *m, Identifier id); static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p); static bool isExtensible(const Managed *m); + static bool preventExtensions(Managed *); static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); static qint64 getLength(const Managed *m); static ReturnedValue instanceOf(const Object *typeObject, const Value &var); diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 72b2816dd9..84238477fd 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -401,7 +401,7 @@ ReturnedValue ObjectPrototype::method_preventExtensions(const FunctionObject *b, if (!o) return argv[0].asReturnedValue(); - o->setInternalClass(o->internalClass()->nonExtensible()); + o->preventExtensions(); return o.asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp index 637a3c16df..e499dfbcf1 100644 --- a/src/qml/jsruntime/qv4proxy.cpp +++ b/src/qml/jsruntime/qv4proxy.cpp @@ -330,6 +330,37 @@ bool ProxyObject::isExtensible(const Managed *m) return result; } +bool ProxyObject::preventExtensions(Managed *m) +{ + 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("preventExtensions"))); + ScopedValue trap(scope, handler->get(hasProp)); + if (scope.hasException()) + return Encode::undefined(); + if (trap->isUndefined()) + return target->preventExtensions(); + if (!trap->isFunctionObject()) + return scope.engine->throwTypeError(); + + JSCallData cdata(scope, 1, nullptr, handler); + cdata.args[0] = target; + + ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + bool result = trapResult->toBoolean(); + if (result && target->isExtensible()) { + scope.engine->throwTypeError(); + return false; + } + return result; +} + //ReturnedValue ProxyObject::callAsConstructor(const FunctionObject *f, const Value *argv, int argc) //{ diff --git a/src/qml/jsruntime/qv4proxy_p.h b/src/qml/jsruntime/qv4proxy_p.h index 36cf00aa47..a8b5b63a6c 100644 --- a/src/qml/jsruntime/qv4proxy_p.h +++ b/src/qml/jsruntime/qv4proxy_p.h @@ -94,6 +94,7 @@ struct ProxyObject: Object { static bool hasProperty(const Managed *m, Identifier id); static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p); static bool isExtensible(const Managed *m); + static bool preventExtensions(Managed *); // those might require a second proxy object that derives from FunctionObject... // static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc); diff --git a/src/qml/jsruntime/qv4reflect.cpp b/src/qml/jsruntime/qv4reflect.cpp index 69baecd337..219e28b6e7 100644 --- a/src/qml/jsruntime/qv4reflect.cpp +++ b/src/qml/jsruntime/qv4reflect.cpp @@ -232,8 +232,7 @@ ReturnedValue Reflect::method_preventExtensions(const FunctionObject *f, const V return scope.engine->throwTypeError(); ScopedObject o(scope, static_cast<const Object *>(argv)); - o->setInternalClass(o->internalClass()->nonExtensible()); - return Encode(true); + return Encode(o->preventExtensions()); } ReturnedValue Reflect::method_set(const FunctionObject *f, const Value *, const Value *argv, int argc) |