aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-06-19 12:07:40 +0200
committerLars Knoll <lars.knoll@qt.io>2018-06-25 07:36:44 +0000
commit3823e9b94f849f8344b81250fac708ac2eaccd16 (patch)
treeffe4ce6f2df01889501b4c4e45b8241d02d973f5
parent4094ce77af45427613e823a2a4d3c6087230d35a (diff)
Support preventExtensions in Proxy handlers
Change-Id: I03aaacc260bdb46eb09c597598a45fbb25d6d7b6 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/jsruntime/qv4object.cpp8
-rw-r--r--src/qml/jsruntime/qv4object_p.h4
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp2
-rw-r--r--src/qml/jsruntime/qv4proxy.cpp31
-rw-r--r--src/qml/jsruntime/qv4proxy_p.h1
-rw-r--r--src/qml/jsruntime/qv4reflect.cpp3
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations7
7 files changed, 47 insertions, 9 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)
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index a1019b2fdc..320396dfcc 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -867,12 +867,7 @@ built-ins/Proxy/ownKeys/return-type-throws-undefined.js fails
built-ins/Proxy/ownKeys/trap-is-not-callable-realm.js fails
built-ins/Proxy/ownKeys/trap-is-not-callable.js fails
built-ins/Proxy/ownKeys/trap-is-undefined.js fails
-built-ins/Proxy/preventExtensions/call-parameters.js fails
-built-ins/Proxy/preventExtensions/null-handler.js fails
-built-ins/Proxy/preventExtensions/return-false.js fails
-built-ins/Proxy/preventExtensions/return-true-target-is-extensible.js fails
built-ins/Proxy/preventExtensions/trap-is-not-callable-realm.js fails
-built-ins/Proxy/preventExtensions/trap-is-not-callable.js fails
built-ins/Proxy/proxy-no-prototype.js fails
built-ins/Proxy/revocable/revocation-function-name.js fails
built-ins/Proxy/revocable/revocation-function-nonconstructor.js fails
@@ -882,6 +877,7 @@ built-ins/Proxy/setPrototypeOf/call-parameters.js fails
built-ins/Proxy/setPrototypeOf/internals-call-order.js fails
built-ins/Proxy/setPrototypeOf/not-extensible-target-not-same-target-prototype.js fails
built-ins/Proxy/setPrototypeOf/not-extensible-target-same-target-prototype.js fails
+built-ins/Proxy/setPrototypeOf/return-abrupt-from-target-getprototypeof.js fails
built-ins/Proxy/setPrototypeOf/toboolean-trap-result-false.js fails
built-ins/Proxy/setPrototypeOf/toboolean-trap-result-true-target-is-extensible.js fails
built-ins/Proxy/setPrototypeOf/trap-is-not-callable-realm.js fails
@@ -891,7 +887,6 @@ built-ins/Reflect/construct/newtarget-is-not-constructor-throws.js fails
built-ins/Reflect/construct/return-with-newtarget-argument.js fails
built-ins/Reflect/get/return-value-from-receiver.js fails
built-ins/Reflect/ownKeys/return-on-corresponding-order.js fails
-built-ins/Reflect/preventExtensions/return-boolean-from-proxy-object.js fails
built-ins/Reflect/set/creates-a-data-descriptor.js fails
built-ins/Reflect/set/different-property-descriptors.js fails
built-ins/Reflect/set/receiver-is-not-object.js fails