aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/jsapi/qjsvalue.cpp12
-rw-r--r--src/qml/jsruntime/jsruntime.pri2
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp14
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4context.cpp6
-rw-r--r--src/qml/jsruntime/qv4engine.cpp11
-rw-r--r--src/qml/jsruntime/qv4engine_p.h2
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h1
-rw-r--r--src/qml/jsruntime/qv4generatorobject.cpp8
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4identifier.cpp10
-rw-r--r--src/qml/jsruntime/qv4identifier_p.h3
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp6
-rw-r--r--src/qml/jsruntime/qv4managed.cpp3
-rw-r--r--src/qml/jsruntime/qv4managed_p.h1
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4object.cpp250
-rw-r--r--src/qml/jsruntime/qv4object_p.h51
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp8
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp75
-rw-r--r--src/qml/jsruntime/qv4proxy.cpp520
-rw-r--r--src/qml/jsruntime/qv4proxy_p.h122
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp40
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h2
-rw-r--r--src/qml/jsruntime/qv4reflect.cpp18
-rw-r--r--src/qml/jsruntime/qv4reflect_p.h2
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp2
-rw-r--r--src/qml/jsruntime/qv4string.cpp8
-rw-r--r--src/qml/jsruntime/qv4string_p.h2
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp5
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp4
-rw-r--r--src/qml/qml/qqmlcomponent.cpp2
-rw-r--r--src/qml/qml/qqmllocale.cpp2
-rw-r--r--src/qml/qml/qqmlmetatype.cpp2
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp19
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp18
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h2
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp24
-rw-r--r--src/qml/qml/v8/qv8engine.cpp4
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp4
-rw-r--r--src/qml/util/qqmladaptormodel.cpp4
44 files changed, 957 insertions, 328 deletions
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 348ddb25d9..01ec44e250 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -852,7 +852,7 @@ QJSValue QJSValue::prototype() const
ScopedObject o(scope, QJSValuePrivate::getValue(this)->as<QV4::Object>());
if (!o)
return QJSValue();
- ScopedObject p(scope, o->prototype());
+ ScopedObject p(scope, o->getPrototypeOf());
if (!p)
return QJSValue(NullValue);
return QJSValue(o->internalClass()->engine, p.asReturnedValue());
@@ -884,7 +884,7 @@ void QJSValue::setPrototype(const QJSValue& prototype)
if (!val)
return;
if (val->isNull()) {
- o->setPrototype(nullptr);
+ o->setPrototypeOf(nullptr);
return;
}
@@ -895,7 +895,7 @@ void QJSValue::setPrototype(const QJSValue& prototype)
qWarning("QJSValue::setPrototype() failed: cannot set a prototype created in a different engine");
return;
}
- if (!o->setPrototype(p))
+ if (!o->setPrototypeOf(p))
qWarning("QJSValue::setPrototype() failed: cyclic prototype value");
}
@@ -1269,8 +1269,8 @@ bool QJSValue::hasProperty(const QString &name) const
if (!o)
return false;
- ScopedString s(scope, engine->newIdentifier(name));
- return o->hasProperty(s);
+ ScopedString s(scope, engine->newString(name));
+ return o->hasProperty(s->toPropertyKey());
}
/*!
@@ -1291,7 +1291,7 @@ bool QJSValue::hasOwnProperty(const QString &name) const
return false;
ScopedString s(scope, engine->newIdentifier(name));
- return o->hasOwnProperty(s);
+ return o->getOwnProperty(s->identifier()) != Attr_Invalid;
}
/*!
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index a2408d7d2a..34eea36f0a 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -30,6 +30,7 @@ SOURCES += \
$$PWD/qv4numberobject.cpp \
$$PWD/qv4object.cpp \
$$PWD/qv4objectproto.cpp \
+ $$PWD/qv4proxy.cpp \
$$PWD/qv4qmlcontext.cpp \
$$PWD/qv4reflect.cpp \
$$PWD/qv4regexpobject.cpp \
@@ -89,6 +90,7 @@ HEADERS += \
$$PWD/qv4numberobject_p.h \
$$PWD/qv4object_p.h \
$$PWD/qv4objectproto_p.h \
+ $$PWD/qv4proxy_p.h \
$$PWD/qv4qmlcontext_p.h \
$$PWD/qv4reflect_p.h \
$$PWD/qv4regexpobject_p.h \
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 58951d043c..3fa680bfef 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -202,19 +202,19 @@ bool ArgumentsObject::deleteIndexedProperty(Managed *m, uint index)
return Object::deleteIndexedProperty(m, index);
}
-PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index)
+PropertyAttributes ArgumentsObject::getOwnProperty(Managed *m, Identifier id, Property *p)
{
const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
- if (args->fullyCreated())
- return Object::queryIndexed(m, index);
+ if (!id.isArrayIndex() || args->fullyCreated())
+ return Object::getOwnProperty(m, id, p);
- uint numAccessors = qMin(args->d()->nFormals, args->context()->argc());
+ uint index = id.asArrayIndex();
uint argCount = args->context()->argc();
if (index >= argCount)
return PropertyAttributes();
- if (index >= numAccessors)
- return Attr_Data;
- return Attr_Accessor;
+ if (p)
+ p->value = args->context()->args()[index];
+ return Attr_Data;
}
DEFINE_OBJECT_VTABLE(ArgumentsGetterFunction);
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index f246f66019..2518b4642a 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -150,7 +150,7 @@ struct ArgumentsObject: Object {
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static bool putIndexed(Managed *m, uint index, const Value &value);
static bool deleteIndexedProperty(Managed *m, uint index);
- static PropertyAttributes queryIndexed(const Managed *m, uint index);
+ static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p);
static qint64 getLength(const Managed *m);
void fullyCreate();
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 434f6781a8..a82628e249 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -247,7 +247,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
mappedValue = *nextValue;
}
- if (!a->hasOwnProperty(k)) {
+ if (a->getOwnProperty(Identifier::fromArrayIndex(k)) == Attr_Invalid) {
a->arraySet(k, mappedValue);
} else {
// Don't return: we need to close the iterator.
@@ -289,7 +289,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
mappedValue = kValue;
}
- if (a->hasOwnProperty(k))
+ if (a->getOwnProperty(Identifier::fromArrayIndex(k)) != Attr_Invalid)
return scope.engine->throwTypeError(QString::fromLatin1("Cannot redefine property: %1").arg(k));
a->arraySet(k, mappedValue);
@@ -318,7 +318,7 @@ ReturnedValue ArrayPrototype::method_of(const FunctionObject *builtin, const Val
int k = 0;
while (k < argc) {
- if (a->hasOwnProperty(k)) {
+ if (a->getOwnProperty(Identifier::fromArrayIndex(k)) != Attr_Invalid) {
return scope.engine->throwTypeError(QString::fromLatin1("Cannot redefine property: %1").arg(k));
}
a->arraySet(k, argv[k]);
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index eb83f902db..80b95a71d4 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -66,7 +66,7 @@ void BooleanPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(engine->id_toString(), method_toString);
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 78cca8d525..03a56cb173 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -178,7 +178,7 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
ctx = ctx->d()->outer;
}
- if (activation->hasOwnProperty(name))
+ if (activation->getOwnProperty(name->toPropertyKey()) != Attr_Invalid)
return;
ScopedProperty desc(scope);
PropertyAttributes attrs(Attr_Data);
@@ -209,7 +209,7 @@ bool ExecutionContext::deleteProperty(String *name)
if (ctx->activation) {
Scope scope(this);
ScopedObject object(scope, ctx->activation);
- if (object && object->hasProperty(name))
+ if (object && object->hasProperty(name->toPropertyKey()))
return object->deleteProperty(name);
}
break;
@@ -236,7 +236,7 @@ ExecutionContext::Error ExecutionContext::setProperty(String *name, const Value
case Heap::ExecutionContext::Type_WithContext: {
Scope scope(v4);
ScopedObject w(scope, ctx->activation);
- if (w->hasProperty(name)) {
+ if (w->hasProperty(name->toPropertyKey())) {
if (!w->put(name, value))
return TypeError;
return NoError;
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 1073a2abab..7f26d1d16b 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -73,6 +73,7 @@
#include "qv4stringiterator_p.h"
#include "qv4generatorobject_p.h"
#include "qv4reflect_p.h"
+#include "qv4proxy_p.h"
#if QT_CONFIG(qml_sequence_object)
#include "qv4sequenceobject_p.h"
@@ -290,6 +291,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
jsSymbols[Symbol_toPrimitive] = Symbol::create(this, QStringLiteral("@Symbol.toPrimitive"));
jsSymbols[Symbol_toStringTag] = Symbol::create(this, QStringLiteral("@Symbol.toStringTag"));
jsSymbols[Symbol_unscopables] = Symbol::create(this, QStringLiteral("@Symbol.unscopables"));
+ jsSymbols[Symbol_revokableProxy] = Symbol::create(this, QStringLiteral("@Proxy.revokableProxy"));
ic = newInternalClass(ArrayPrototype::staticVTable(), objectPrototype());
Q_ASSERT(ic->d()->prototype);
@@ -386,6 +388,8 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
classes[Class_ErrorProto] = ic->addMember(id_name()->identifier(), Attr_Data|Attr_NotEnumerable, &index);
Q_ASSERT(index == ErrorPrototype::Index_Name);
+ classes[Class_ProxyObject] = classes[Class_Empty]->changeVTable(ProxyObject::staticVTable());
+
jsObjects[GetStack_Function] = FunctionObject::createBuiltinFunction(this, str = newIdentifier(QStringLiteral("stack")), ErrorObject::method_get_stack, 0);
jsObjects[ErrorProto] = memoryManager->allocObject<ErrorPrototype>(classes[Class_ErrorProto]);
@@ -398,7 +402,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
jsObjects[URIErrorProto] = memoryManager->allocObject<URIErrorPrototype>(ic->d());
jsObjects[VariantProto] = memoryManager->allocate<VariantPrototype>();
- Q_ASSERT(variantPrototype()->prototype() == objectPrototype()->d());
+ Q_ASSERT(variantPrototype()->getPrototypeOf() == objectPrototype()->d());
#if QT_CONFIG(qml_sequence_object)
ic = newInternalClass(SequencePrototype::staticVTable(), SequencePrototype::defaultPrototype(this));
@@ -532,6 +536,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->allocate<MathObject>()));
globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->allocate<JsonObject>()));
globalObject->defineDefaultProperty(QStringLiteral("Reflect"), (o = memoryManager->allocate<Reflect>()));
+ globalObject->defineDefaultProperty(QStringLiteral("Proxy"), (o = memoryManager->allocate<Proxy>(rootContext())));
globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue());
globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN()));
@@ -1838,7 +1843,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
} else if (Object *o = value->objectValue()) {
// Look in the prototype chain.
QV4::Scope scope(this);
- QV4::ScopedObject proto(scope, o->prototype());
+ QV4::ScopedObject proto(scope, o->getPrototypeOf());
while (proto) {
bool canCast = false;
if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
@@ -1859,7 +1864,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
*reinterpret_cast<void* *>(data) = var.data();
return true;
}
- proto = proto->prototype();
+ proto = proto->getPrototypeOf();
}
}
} else if (value->isNull() && name.endsWith('*')) {
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index b007e65c4b..abd363adcb 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -368,6 +368,7 @@ public:
Symbol_toPrimitive,
Symbol_toStringTag,
Symbol_unscopables,
+ Symbol_revokableProxy,
NJSSymbols
};
Value *jsSymbols;
@@ -425,6 +426,7 @@ public:
Symbol *symbol_toPrimitive() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toPrimitive); }
Symbol *symbol_toStringTag() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toStringTag); }
Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
+ Symbol *symbol_revokableProxy() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_revokableProxy); }
#ifndef V4_BOOTSTRAP
QIntrusiveList<CompiledData::CompilationUnit, &CompiledData::CompilationUnit::nextCompilationUnit> compilationUnits;
diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h
index 03ff25d5b5..7701cf37bc 100644
--- a/src/qml/jsruntime/qv4enginebase_p.h
+++ b/src/qml/jsruntime/qv4enginebase_p.h
@@ -115,6 +115,7 @@ struct Q_QML_EXPORT EngineBase {
Class_ErrorObjectWithMessage,
Class_ErrorProto,
Class_QmlContextWrapper,
+ Class_ProxyObject,
Class_Symbol,
NClasses
};
diff --git a/src/qml/jsruntime/qv4generatorobject.cpp b/src/qml/jsruntime/qv4generatorobject.cpp
index a29eef513c..1c4c970c2e 100644
--- a/src/qml/jsruntime/qv4generatorobject.cpp
+++ b/src/qml/jsruntime/qv4generatorobject.cpp
@@ -78,9 +78,9 @@ Heap::FunctionObject *GeneratorFunction::create(ExecutionContext *context, Funct
Scope scope(context);
Scoped<GeneratorFunction> g(scope, context->engine()->memoryManager->allocate<GeneratorFunction>(context, function));
ScopedObject proto(scope, scope.engine->newObject());
- proto->setPrototype(scope.engine->generatorPrototype());
+ proto->setPrototypeOf(scope.engine->generatorPrototype());
g->defineDefaultProperty(scope.engine->id_prototype(), proto, Attr_NotConfigurable|Attr_NotEnumerable);
- g->setPrototype(ScopedObject(scope, scope.engine->generatorFunctionCtor()->get(scope.engine->id_prototype())));
+ g->setPrototypeOf(ScopedObject(scope, scope.engine->generatorFunctionCtor()->get(scope.engine->id_prototype())));
return g->d();
}
@@ -104,7 +104,7 @@ ReturnedValue GeneratorFunction::call(const FunctionObject *f, const Value *this
Scope scope(gf);
Scoped<GeneratorObject> g(scope, scope.engine->memoryManager->allocManaged<GeneratorObject>(requiredMemory, scope.engine->classes[EngineBase::Class_GeneratorObject]));
- g->setPrototype(ScopedObject(scope, gf->get(scope.engine->id_prototype())));
+ g->setPrototypeOf(ScopedObject(scope, gf->get(scope.engine->id_prototype())));
Heap::GeneratorObject *gp = g->d();
gp->stack.size = stackSize;
@@ -160,7 +160,7 @@ void GeneratorPrototype::init(ExecutionEngine *engine, Object *ctor)
ctorProto->defineDefaultProperty(engine->symbol_toStringTag(), (v = engine->newIdentifier(QStringLiteral("GeneratorFunction"))), Attr_ReadOnly_ButConfigurable);
ctorProto->defineDefaultProperty(engine->id_prototype(), (v = this), Attr_ReadOnly_ButConfigurable);
- setPrototype(engine->iteratorPrototype());
+ setPrototypeOf(engine->iteratorPrototype());
defineDefaultProperty(QStringLiteral("constructor"), ctorProto, Attr_ReadOnly_ButConfigurable);
defineDefaultProperty(QStringLiteral("next"), method_next, 1);
defineDefaultProperty(QStringLiteral("return"), method_return, 1);
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 47a6734eda..95f65c47c0 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -335,7 +335,7 @@ void Heap::EvalFunction::init(QV4::ExecutionContext *scope)
Scope s(scope);
Heap::FunctionObject::init(scope, s.engine->id_eval());
ScopedFunctionObject f(s, this);
- f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(1));
+ f->defineReadonlyConfigurableProperty(s.engine->id_length(), Primitive::fromInt32(1));
}
ReturnedValue EvalFunction::evalCall(const Value *, const Value *argv, int argc, bool directCall) const
diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp
index 4bfae14aec..08e480e8c2 100644
--- a/src/qml/jsruntime/qv4identifier.cpp
+++ b/src/qml/jsruntime/qv4identifier.cpp
@@ -44,6 +44,16 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+bool Identifier::isString() const
+{
+ return isValid() && asHeapObject()->internalClass->vtable->isString;
+}
+
+bool Identifier::isSymbol() const
+{
+ return isValid() && !asHeapObject()->internalClass->vtable->isString && asHeapObject()->internalClass->vtable->isStringOrSymbol;
+}
+
QString Identifier::toQString() const
{
if (isArrayIndex())
diff --git a/src/qml/jsruntime/qv4identifier_p.h b/src/qml/jsruntime/qv4identifier_p.h
index b167a149a2..fd4ff75974 100644
--- a/src/qml/jsruntime/qv4identifier_p.h
+++ b/src/qml/jsruntime/qv4identifier_p.h
@@ -73,6 +73,9 @@ struct Identifier
static Identifier fromHeapObject(Heap::Base *b) { return Identifier{ reinterpret_cast<quintptr>(b) }; }
Heap::Base *asHeapObject() const { return (id & 1) ? nullptr : reinterpret_cast<Heap::Base *>(id); }
+ bool isString() const;
+ bool isSymbol() const;
+
Q_QML_EXPORT QString toQString() const;
bool operator ==(const Identifier &other) const { return id == other.id; }
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index c045ac3008..ee741e4abb 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -146,6 +146,12 @@ Heap::String *IdentifierTable::insertString(const QString &s)
{
uint subtype;
uint hash = String::createHashValue(s.constData(), s.length(), &subtype);
+ if (subtype == Heap::String::StringType_ArrayIndex) {
+ Heap::String *str = engine->newString(s);
+ str->stringHash = hash;
+ str->subtype = subtype;
+ return str;
+ }
uint idx = hash % alloc;
while (Heap::StringOrSymbol *e = entriesByHash[idx]) {
if (e->stringHash == hash && e->toQString() == s)
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index 58f5b0051f..9321b9dd64 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -118,6 +118,9 @@ QString Managed::className() const
case Type_JsonObject:
s = "JSON";
break;
+ case Type_ProxyObject:
+ s = "ProxyObject";
+ break;
case Type_MathObject:
s = "Math";
break;
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index f16bf3dc58..6983b52c83 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -196,6 +196,7 @@ public:
Type_ArgumentsObject,
Type_JsonObject,
Type_MathObject,
+ Type_ProxyObject,
Type_ExecutionContext,
Type_InternalClass,
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index f58ff45801..de24ec8181 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -95,7 +95,7 @@ void NumberPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(qt_qnan()));
ctor->defineReadonlyProperty(QStringLiteral("NEGATIVE_INFINITY"), Primitive::fromDouble(-qInf()));
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 79a63d1ee6..dff7555061 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -93,19 +93,6 @@ void Heap::Object::setUsedAsProto()
internalClass.set(internalClass->engine, internalClass->asProtoClass());
}
-bool Object::setPrototype(Object *proto)
-{
- Heap::Object *p = proto ? proto->d() : nullptr;
- Heap::Object *pp = p;
- while (pp) {
- if (pp == d())
- return false;
- pp = pp->prototype();
- }
- setInternalClass(internalClass()->changePrototype(p));
- return true;
-}
-
ReturnedValue Object::getValue(const Value &thisObject, const Value &v, PropertyAttributes attrs)
{
if (!attrs.isAccessor())
@@ -275,48 +262,9 @@ void Object::insertMember(StringOrSymbol *s, const Property *p, PropertyAttribut
}
}
-// Section 8.12.1
-void Object::getOwnProperty(StringOrSymbol *name, PropertyAttributes *attrs, Property *p)
-{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return getOwnProperty(idx, attrs, p);
-
- name->makeIdentifier();
- Identifier id = name->identifier();
-
- uint member = internalClass()->find(id);
- if (member < UINT_MAX) {
- *attrs = internalClass()->propertyData[member];
- if (p) {
- p->value = *propertyData(member);
- if (attrs->isAccessor())
- p->set = *propertyData(member + SetterOffset);
- }
- return;
- }
-
- if (attrs)
- *attrs = Attr_Invalid;
- return;
-}
-
-void Object::getOwnProperty(uint index, PropertyAttributes *attrs, Property *p)
+void Object::setPrototypeUnchecked(const Object *p)
{
- if (arrayData()) {
- if (arrayData()->getProperty(index, p, attrs))
- return;
- }
- if (isStringObject()) {
- *attrs = Attr_NotConfigurable|Attr_NotWritable;
- if (p)
- p->value = static_cast<StringObject *>(this)->getIndex(index);
- return;
- }
-
- if (attrs)
- *attrs = Attr_Invalid;
- return;
+ setInternalClass(internalClass()->changePrototype(p ? p->d() : nullptr));
}
// Section 8.12.2
@@ -366,68 +314,6 @@ PropertyIndex Object::getValueOrSetter(uint index, PropertyAttributes *attrs)
return { nullptr, 0 };
}
-bool Object::hasProperty(StringOrSymbol *name) const
-{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return hasProperty(idx);
-
- Scope scope(engine());
- ScopedObject o(scope, d());
- while (o) {
- if (o->hasOwnProperty(name))
- return true;
-
- o = o->prototype();
- }
-
- return false;
-}
-
-bool Object::hasProperty(uint index) const
-{
- Scope scope(engine());
- ScopedObject o(scope, d());
- while (o) {
- if (o->hasOwnProperty(index))
- return true;
-
- o = o->prototype();
- }
-
- return false;
-}
-
-bool Object::hasOwnProperty(StringOrSymbol *name) const
-{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return hasOwnProperty(idx);
-
- name->makeIdentifier();
- Identifier id = name->identifier();
-
- if (internalClass()->find(id) < UINT_MAX)
- return true;
- if (!query(name).isEmpty())
- return true;
- return false;
-}
-
-bool Object::hasOwnProperty(uint index) const
-{
- if (arrayData() && !arrayData()->isEmpty(index))
- return true;
-
- if (isStringObject()) {
- if (index < static_cast<const StringObject *>(this)->length())
- return true;
- }
- if (!queryIndexed(index).isEmpty())
- return true;
- return false;
-}
-
ReturnedValue Object::callAsConstructor(const FunctionObject *f, const Value *, int)
{
return f->engine()->throwTypeError();
@@ -458,36 +344,6 @@ bool Object::putIndexed(Managed *m, uint index, const Value &value)
return static_cast<Object *>(m)->internalPutIndexed(index, value);
}
-PropertyAttributes Object::query(const Managed *m, StringOrSymbol *name)
-{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return queryIndexed(m, idx);
-
- name->makeIdentifier();
- Identifier id = name->identifier();
-
- const Object *o = static_cast<const Object *>(m);
- idx = o->internalClass()->find(id);
- if (idx < UINT_MAX)
- return o->internalClass()->propertyData[idx];
-
- return Attr_Invalid;
-}
-
-PropertyAttributes Object::queryIndexed(const Managed *m, uint index)
-{
- const Object *o = static_cast<const Object *>(m);
- if (o->arrayData() && !o->arrayData()->isEmpty(index))
- return o->arrayData()->attributes(index);
-
- if (o->isStringObject()) {
- if (index < static_cast<const StringObject *>(o)->length())
- return (Attr_NotWritable|Attr_NotConfigurable);
- }
- return Attr_Invalid;
-}
-
bool Object::deleteProperty(Managed *m, StringOrSymbol *name)
{
return static_cast<Object *>(m)->internalDeleteProperty(name);
@@ -617,7 +473,7 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
return str.asReturnedValue();
}
}
- o = o->prototype();
+ o = o->getPrototypeOf();
}
if (exists) {
@@ -676,13 +532,13 @@ bool Object::internalPut(StringOrSymbol *name, const Value &value)
memberIndex.set(engine, value);
}
return true;
- } else if (!prototype()) {
+ } else if (!getPrototypeOf()) {
if (!isExtensible())
return false;
} else {
// clause 4
Scope scope(engine);
- memberIndex = ScopedObject(scope, prototype())->getValueOrSetter(name, &attrs);
+ memberIndex = ScopedObject(scope, getPrototypeOf())->getValueOrSetter(name, &attrs);
if (!memberIndex.isNull()) {
if (attrs.isAccessor()) {
if (!memberIndex->as<FunctionObject>())
@@ -741,13 +597,13 @@ bool Object::internalPutIndexed(uint index, const Value &value)
arrayIndex.set(engine, value);
return true;
- } else if (!prototype()) {
+ } else if (!getPrototypeOf()) {
if (!isExtensible())
return false;
} else {
// clause 4
Scope scope(engine);
- arrayIndex = ScopedObject(scope, prototype())->getValueOrSetter(index, &attrs);
+ arrayIndex = ScopedObject(scope, getPrototypeOf())->getValueOrSetter(index, &attrs);
if (!arrayIndex.isNull()) {
if (attrs.isAccessor()) {
if (!arrayIndex->as<FunctionObject>())
@@ -1102,6 +958,98 @@ ReturnedValue Object::instanceOf(const Object *typeObject, const Value &var)
return Encode(false);
}
+bool Object::hasProperty(const Managed *m, Identifier id)
+{
+ Scope scope(m->engine());
+ ScopedObject o(scope, m);
+ ScopedProperty p(scope);
+ while (o) {
+ if (o->getOwnProperty(id, p) != Attr_Invalid)
+ return true;
+
+ o = o->getPrototypeOf();
+ }
+
+ return false;
+}
+
+PropertyAttributes Object::getOwnProperty(Managed *m, Identifier id, Property *p)
+{
+ PropertyAttributes attrs;
+ Object *o = static_cast<Object *>(m);
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ if (o->arrayData()) {
+ if (o->arrayData()->getProperty(index, p, &attrs))
+ return attrs;
+ }
+ if (o->isStringObject()) {
+ if (index >= static_cast<const StringObject *>(m)->length())
+ return Attr_Invalid;
+ attrs = Attr_NotConfigurable|Attr_NotWritable;
+ if (p)
+ p->value = static_cast<StringObject *>(o)->getIndex(index);
+ return attrs;
+ }
+ } else {
+ Q_ASSERT(id.asHeapObject());
+
+ uint member = o->internalClass()->find(id);
+ if (member < UINT_MAX) {
+ attrs = o->internalClass()->propertyData[member];
+ if (p) {
+ p->value = *o->propertyData(member);
+ if (attrs.isAccessor())
+ p->set = *o->propertyData(member + SetterOffset);
+ }
+ return attrs;
+ }
+ }
+
+ return Attr_Invalid;
+}
+
+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;
+}
+
+Heap::Object *Object::getPrototypeOf(const Managed *m)
+{
+ return m->internalClass()->prototype;
+}
+
+bool Object::setPrototypeOf(Managed *m, const Object *proto)
+{
+ Q_ASSERT(m->isObject());
+ Object *o = static_cast<Object *>(m);
+ Heap::Object *current = o->internalClass()->prototype;
+ Heap::Object *protod = proto ? proto->d() : nullptr;
+ if (current == protod)
+ return true;
+ if (!o->internalClass()->extensible)
+ return false;
+ Heap::Object *p = protod;
+ while (p) {
+ if (p == o->d())
+ return false;
+ if (reinterpret_cast<const ObjectVTable *>(p->vtable())->getPrototypeOf !=
+ reinterpret_cast<const ObjectVTable *>(Object::staticVTable())->getPrototypeOf)
+ break;
+ p = p->prototype();
+ }
+ o->setInternalClass(o->internalClass()->changePrototype(protod));
+ 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 5ad67635db..6ec7452ca6 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -173,10 +173,14 @@ struct ObjectVTable
ReturnedValue (*getIndexed)(const Managed *, uint index, bool *hasProperty);
bool (*put)(Managed *, StringOrSymbol *name, const Value &value);
bool (*putIndexed)(Managed *, uint index, const Value &value);
- PropertyAttributes (*query)(const Managed *, StringOrSymbol *name);
- PropertyAttributes (*queryIndexed)(const Managed *, uint index);
bool (*deleteProperty)(Managed *m, StringOrSymbol *name);
bool (*deleteIndexedProperty)(Managed *m, uint index);
+ bool (*hasProperty)(const Managed *m, Identifier id);
+ PropertyAttributes (*getOwnProperty)(Managed *m, Identifier id, Property *p);
+ bool (*isExtensible)(const Managed *);
+ bool (*preventExtensions)(Managed *);
+ Heap::Object *(*getPrototypeOf)(const Managed *);
+ bool (*setPrototypeOf)(Managed *, const Object *);
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);
@@ -192,10 +196,14 @@ const QV4::ObjectVTable classname::static_vtbl = \
getIndexed, \
put, \
putIndexed, \
- query, \
- queryIndexed, \
deleteProperty, \
deleteIndexedProperty, \
+ hasProperty, \
+ getOwnProperty, \
+ isExtensible, \
+ preventExtensions, \
+ getPrototypeOf, \
+ setPrototypeOf, \
getLength, \
advanceIterator, \
instanceOf \
@@ -240,20 +248,17 @@ struct Q_QML_EXPORT Object: Managed {
void setProperty(ExecutionEngine *engine, uint index, Heap::Base *b) const { d()->setProperty(engine, index, b); }
const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(d()->vtable()); }
- Heap::Object *prototype() const { return d()->prototype(); }
- bool setPrototype(Object *proto);
- void getOwnProperty(StringOrSymbol *name, PropertyAttributes *attrs, Property *p = nullptr);
- void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = nullptr);
+ PropertyAttributes getOwnProperty(Identifier id, Property *p = nullptr) {
+ return vtable()->getOwnProperty(this, id, p);
+ }
PropertyIndex getValueOrSetter(StringOrSymbol *name, PropertyAttributes *attrs);
PropertyIndex getValueOrSetter(uint index, PropertyAttributes *attrs);
- bool hasProperty(StringOrSymbol *name) const;
- bool hasProperty(uint index) const;
-
- bool hasOwnProperty(StringOrSymbol *name) const;
- bool hasOwnProperty(uint index) const;
+ bool hasProperty(Identifier id) const {
+ return vtable()->hasProperty(this, id);
+ }
bool __defineOwnProperty__(ExecutionEngine *engine, uint index, StringOrSymbol *member, const Property *p, PropertyAttributes attrs);
bool __defineOwnProperty__(ExecutionEngine *engine, StringOrSymbol *name, const Property *p, PropertyAttributes attrs);
@@ -302,7 +307,11 @@ struct Q_QML_EXPORT Object: Managed {
}
void insertMember(StringOrSymbol *s, const Property *p, PropertyAttributes attributes);
- bool isExtensible() const { return d()->internalClass->extensible; }
+ bool isExtensible() const { return vtable()->isExtensible(this); }
+ bool preventExtensions() { return vtable()->preventExtensions(this); }
+ Heap::Object *getPrototypeOf() const { return vtable()->getPrototypeOf(this); }
+ bool setPrototypeOf(const Object *p) { return vtable()->setPrototypeOf(this, p); }
+ void setPrototypeUnchecked(const Object *p);
// Array handling
@@ -362,7 +371,7 @@ public:
Scope scope(engine());
ScopedObject p(scope, this);
- while ((p = p->prototype()))
+ while ((p = p->getPrototypeOf()))
if (p->arrayData())
return true;
@@ -418,10 +427,6 @@ public:
return ret;
}
- PropertyAttributes query(StringOrSymbol *name) const
- { return vtable()->query(this, name); }
- PropertyAttributes queryIndexed(uint index) const
- { return vtable()->queryIndexed(this, index); }
bool deleteProperty(StringOrSymbol *name)
{ return vtable()->deleteProperty(this, name); }
bool deleteIndexedProperty(uint index)
@@ -439,10 +444,14 @@ protected:
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static bool put(Managed *m, StringOrSymbol *name, const Value &value);
static bool putIndexed(Managed *m, uint index, const Value &value);
- static PropertyAttributes query(const Managed *m, StringOrSymbol *name);
- static PropertyAttributes queryIndexed(const Managed *m, uint index);
static bool deleteProperty(Managed *m, StringOrSymbol *name);
static bool deleteIndexedProperty(Managed *m, uint index);
+ 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 Heap::Object *getPrototypeOf(const Managed *);
+ static bool setPrototypeOf(Managed *, const Object *);
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/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 1290a2c1b2..fc4a06747f 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -104,12 +104,12 @@ void ObjectIterator::next(Value *name, uint *index, Property *pd, PropertyAttrib
n = *name;
bool shadowed = false;
while (o->d() != current->heapObject()) {
- if ((!!n && o->hasOwnProperty(n)) ||
- (*index != UINT_MAX && o->hasOwnProperty(*index))) {
+ Identifier id = n ? (n->makeIdentifier(), n->identifier()) : Identifier::fromArrayIndex(*index);
+ if ((id.isValid() ||id.isArrayIndex()) && o->getOwnProperty(id) != Attr_Invalid) {
shadowed = true;
break;
}
- o = o->prototype();
+ o = o->getPrototypeOf();
}
if (shadowed)
continue;
@@ -118,7 +118,7 @@ void ObjectIterator::next(Value *name, uint *index, Property *pd, PropertyAttrib
}
if (flags & WithProtoChain)
- current->setM(co->prototype());
+ current->setM(co->getPrototypeOf());
else
current->setM(nullptr);
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index a61b5d5136..9d52ab1980 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -71,7 +71,7 @@ ReturnedValue ObjectCtor::callAsConstructor(const FunctionObject *f, const Value
ScopedObject obj(scope, scope.engine->newObject());
ScopedObject proto(scope, ctor->get(scope.engine->id_prototype()));
if (!!proto)
- obj->setPrototype(proto);
+ obj->setPrototypeOf(proto);
return obj.asReturnedValue();
} else {
return argv[0].toObject(v4)->asReturnedValue();
@@ -136,7 +136,7 @@ ReturnedValue ObjectPrototype::method_getPrototypeOf(const FunctionObject *b, co
if (scope.engine->hasException)
return QV4::Encode::undefined();
- ScopedObject p(scope, o->prototype());
+ ScopedObject p(scope, o->getPrototypeOf());
return (!!p ? p->asReturnedValue() : Encode::null());
}
@@ -167,9 +167,8 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(const FunctionObj
if (scope.engine->hasException)
return QV4::Encode::undefined();
- PropertyAttributes attrs;
ScopedProperty desc(scope);
- O->getOwnProperty(name, &attrs, desc);
+ PropertyAttributes attrs = O->getOwnProperty(name->toPropertyKey(), desc);
return fromPropertyDescriptor(scope.engine, desc, attrs);
}
@@ -237,9 +236,8 @@ ReturnedValue ObjectPrototype::method_assign(const FunctionObject *b, const Valu
for (quint32 i = 0; i < length; ++i) {
nextKey = Value::fromReturnedValue(keys->getIndexed(i)).toString(scope.engine);
- PropertyAttributes attrs;
ScopedProperty prop(scope);
- from->getOwnProperty(nextKey, &attrs, prop);
+ PropertyAttributes attrs = from->getOwnProperty(nextKey->toPropertyKey(), prop);
if (attrs == PropertyFlag::Attr_Invalid)
continue;
@@ -266,7 +264,7 @@ ReturnedValue ObjectPrototype::method_create(const FunctionObject *builtin, cons
ScopedObject O(scope, argv[0]);
ScopedObject newObject(scope, scope.engine->newObject());
- newObject->setPrototype(O);
+ newObject->setPrototypeOf(O);
if (argc > 1 && !argv[1].isUndefined()) {
@@ -403,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();
}
@@ -518,17 +516,10 @@ ReturnedValue ObjectPrototype::method_setPrototypeOf(const FunctionObject *f, co
return argv[0].asReturnedValue();
ScopedObject o(scope, argv[0]);
- ScopedObject p(scope, argv[1]);
- Q_ASSERT(!!o);
-
- if (o->prototype() != p->d()) {
- bool ok = false;
- if (o->isExtensible()) {
- ok = o->setPrototype(p);
- }
- if (!ok)
- return scope.engine->throwTypeError(QStringLiteral("Object.setPrototypeOf: Could not change prototype"));
- }
+ const Object *p = argv[1].isNull() ? nullptr : static_cast<const Object *>(argv + 1);
+ bool ok = o->setPrototypeOf(p);
+ if (!ok)
+ return scope.engine->throwTypeError(QStringLiteral("Could not change prototype."));
return o->asReturnedValue();
}
@@ -592,9 +583,7 @@ ReturnedValue ObjectPrototype::method_hasOwnProperty(const FunctionObject *b, co
ScopedObject O(scope, thisObject->toObject(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
- bool r = O->hasOwnProperty(P);
- if (!r)
- r = !O->query(P).isEmpty();
+ bool r = O->getOwnProperty(P->toPropertyKey()) != Attr_Invalid;
return Encode(r);
}
@@ -608,11 +597,11 @@ ReturnedValue ObjectPrototype::method_isPrototypeOf(const FunctionObject *b, con
ScopedObject O(scope, thisObject->toObject(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
- ScopedObject proto(scope, V->prototype());
+ ScopedObject proto(scope, V->getPrototypeOf());
while (proto) {
if (O->d() == proto->d())
return Encode(true);
- proto = proto->prototype();
+ proto = proto->getPrototypeOf();
}
return Encode(false);
}
@@ -627,8 +616,7 @@ ReturnedValue ObjectPrototype::method_propertyIsEnumerable(const FunctionObject
ScopedObject o(scope, thisObject->toObject(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
- PropertyAttributes attrs;
- o->getOwnProperty(p, &attrs);
+ PropertyAttributes attrs = o->getOwnProperty(p->toPropertyKey());
return Encode(attrs.isEnumerable());
}
@@ -699,32 +687,21 @@ ReturnedValue ObjectPrototype::method_get_proto(const FunctionObject *b, const V
if (!o)
THROW_TYPE_ERROR();
- return Encode(o->prototype());
+ return Encode(o->getPrototypeOf());
}
ReturnedValue ObjectPrototype::method_set_proto(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
ScopedObject o(scope, thisObject);
- if (!o || !argc)
+ if (!o || !argc || (!argv[0].isObject() && !argv[0].isNull()))
THROW_TYPE_ERROR();
- if (argv[0].isNull()) {
- o->setPrototype(nullptr);
- RETURN_UNDEFINED();
- }
-
- ScopedObject p(scope, argv[0]);
- bool ok = false;
- if (!!p) {
- if (o->prototype() == p->d()) {
- ok = true;
- } else if (o->isExtensible()) {
- ok = o->setPrototype(p);
- }
- }
+ const Object *p = argv[0].isNull() ? nullptr : static_cast<const Object *>(argv);
+ bool ok = o->setPrototypeOf(p);
if (!ok)
- return scope.engine->throwTypeError(QStringLiteral("Cyclic __proto__ value"));
+ return scope.engine->throwTypeError(QStringLiteral("Could not change prototype."));
+ return Encode::undefined();
RETURN_UNDEFINED();
}
@@ -742,13 +719,13 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
desc->set = Primitive::emptyValue();
ScopedValue tmp(scope);
- if (o->hasProperty(engine->id_enumerable()))
+ if (o->hasProperty(engine->id_enumerable()->toPropertyKey()))
attrs->setEnumerable((tmp = o->get(engine->id_enumerable()))->toBoolean());
- if (o->hasProperty(engine->id_configurable()))
+ if (o->hasProperty(engine->id_configurable()->toPropertyKey()))
attrs->setConfigurable((tmp = o->get(engine->id_configurable()))->toBoolean());
- if (o->hasProperty(engine->id_get())) {
+ if (o->hasProperty(engine->id_get()->toPropertyKey())) {
ScopedValue get(scope, o->get(engine->id_get()));
FunctionObject *f = get->as<FunctionObject>();
if (f || get->isUndefined()) {
@@ -760,7 +737,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(engine->id_set())) {
+ if (o->hasProperty(engine->id_set()->toPropertyKey())) {
ScopedValue set(scope, o->get(engine->id_set()));
FunctionObject *f = set->as<FunctionObject>();
if (f || set->isUndefined()) {
@@ -772,7 +749,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(engine->id_writable())) {
+ if (o->hasProperty(engine->id_writable()->toPropertyKey())) {
if (attrs->isAccessor()) {
engine->throwTypeError();
return;
@@ -782,7 +759,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
desc->value = Primitive::undefinedValue();
}
- if (o->hasProperty(engine->id_value())) {
+ if (o->hasProperty(engine->id_value()->toPropertyKey())) {
if (attrs->isAccessor()) {
engine->throwTypeError();
return;
diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp
new file mode 100644
index 0000000000..1e0c452430
--- /dev/null
+++ b/src/qml/jsruntime/qv4proxy.cpp
@@ -0,0 +1,520 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qv4proxy_p.h"
+#include "qv4symbol_p.h"
+#include "qv4jscall_p.h"
+#include "qv4objectproto_p.h"
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(ProxyObject);
+
+void Heap::ProxyObject::init(const QV4::Object *target, const QV4::Object *handler)
+{
+ Object::init();
+ ExecutionEngine *e = internalClass->engine;
+ this->target.set(e, target->d());
+ this->handler.set(e, handler->d());
+}
+
+ReturnedValue ProxyObject::get(const Managed *m, StringOrSymbol *name, bool *hasProperty)
+{
+ 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);
+ ScopedValue trap(scope, handler->get(scope.engine->id_get()));
+ if (scope.hasException())
+ return Encode::undefined();
+ if (trap->isNullOrUndefined())
+ return target->get(name, hasProperty);
+ if (!trap->isFunctionObject())
+ return scope.engine->throwTypeError();
+ if (hasProperty)
+ *hasProperty = true;
+
+ JSCallData cdata(scope, 3, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = name;
+ cdata.args[2] = o->d(); // ### fix receiver handling
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ ScopedProperty targetDesc(scope);
+ PropertyAttributes attributes = target->getOwnProperty(name->toPropertyKey(), targetDesc);
+ if (attributes != Attr_Invalid && !attributes.isConfigurable()) {
+ if (attributes.isData() && !attributes.isWritable()) {
+ if (!trapResult->sameValue(targetDesc->value))
+ return scope.engine->throwTypeError();
+ }
+ if (attributes.isAccessor() && targetDesc->value.isUndefined()) {
+ if (!trapResult->isUndefined())
+ return scope.engine->throwTypeError();
+ }
+ }
+ return trapResult->asReturnedValue();
+}
+
+ReturnedValue ProxyObject::getIndexed(const Managed *m, uint index, bool *hasProperty)
+{
+ Scope scope(m);
+ ScopedString name(scope, Primitive::fromUInt32(index).toString(scope.engine));
+ return get(m, name, hasProperty);
+}
+
+bool ProxyObject::put(Managed *m, StringOrSymbol *name, const Value &value)
+{
+ 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);
+ ScopedValue trap(scope, handler->get(scope.engine->id_set()));
+ if (scope.hasException())
+ return Encode::undefined();
+ if (trap->isNullOrUndefined())
+ return target->put(name, value);
+ if (!trap->isFunctionObject())
+ return scope.engine->throwTypeError();
+
+ JSCallData cdata(scope, 4, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = name;
+ cdata.args[2] = value;
+ cdata.args[3] = o->d(); // ### fix receiver handling
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ if (!trapResult->toBoolean())
+ return false;
+ ScopedProperty targetDesc(scope);
+ PropertyAttributes attributes = target->getOwnProperty(name->toPropertyKey(), targetDesc);
+ if (attributes != Attr_Invalid && !attributes.isConfigurable()) {
+ if (attributes.isData() && !attributes.isWritable()) {
+ if (!value.sameValue(targetDesc->value))
+ return scope.engine->throwTypeError();
+ }
+ if (attributes.isAccessor() && targetDesc->set.isUndefined())
+ return scope.engine->throwTypeError();
+ }
+ return true;
+}
+
+bool ProxyObject::putIndexed(Managed *m, uint index, const Value &value)
+{
+ Scope scope(m);
+ ScopedString name(scope, Primitive::fromUInt32(index).toString(scope.engine));
+ return put(m, name, value);
+}
+
+bool ProxyObject::deleteProperty(Managed *m, StringOrSymbol *name)
+{
+ 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 deleteProp(scope, scope.engine->newString(QStringLiteral("deleteProperty")));
+ ScopedValue trap(scope, handler->get(deleteProp));
+ if (scope.hasException())
+ return Encode::undefined();
+ if (trap->isNullOrUndefined())
+ return target->deleteProperty(name);
+ if (!trap->isFunctionObject())
+ return scope.engine->throwTypeError();
+
+ JSCallData cdata(scope, 3, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = name;
+ cdata.args[2] = o->d(); // ### fix receiver handling
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ if (!trapResult->toBoolean())
+ return false;
+ ScopedProperty targetDesc(scope);
+ PropertyAttributes attributes = target->getOwnProperty(name->toPropertyKey(), targetDesc);
+ if (attributes == Attr_Invalid)
+ return true;
+ if (!attributes.isConfigurable())
+ return scope.engine->throwTypeError();
+ return true;
+}
+
+bool ProxyObject::deleteIndexedProperty(Managed *m, uint index)
+{
+ Scope scope(m);
+ ScopedString name(scope, Primitive::fromUInt32(index).toString(scope.engine));
+ 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->isNullOrUndefined())
+ 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->isNullOrUndefined())
+ 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;
+}
+
+bool ProxyObject::isExtensible(const 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("isExtensible")));
+ ScopedValue trap(scope, handler->get(hasProp));
+ if (scope.hasException())
+ return Encode::undefined();
+ if (trap->isNullOrUndefined())
+ return target->isExtensible();
+ 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;
+}
+
+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->isNullOrUndefined())
+ 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;
+}
+
+Heap::Object *ProxyObject::getPrototypeOf(const Managed *m)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler) {
+ scope.engine->throwTypeError();
+ return nullptr;
+ }
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedString name(scope, scope.engine->newString(QStringLiteral("getPrototypeOf")));
+ ScopedValue trap(scope, handler->get(name));
+ if (scope.hasException())
+ return nullptr;
+ if (trap->isNullOrUndefined())
+ return target->getPrototypeOf();
+ if (!trap->isFunctionObject()) {
+ scope.engine->throwTypeError();
+ return nullptr;
+ }
+
+ JSCallData cdata(scope, 1, nullptr, handler);
+ cdata.args[0] = target;
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ if (!trapResult->isNull() && !trapResult->isObject()) {
+ scope.engine->throwTypeError();
+ return nullptr;
+ }
+ Heap::Object *proto = trapResult->isNull() ? nullptr : static_cast<Heap::Object *>(trapResult->heapObject());
+ if (!target->isExtensible()) {
+ Heap::Object *targetProto = target->getPrototypeOf();
+ if (proto != targetProto) {
+ scope.engine->throwTypeError();
+ return nullptr;
+ }
+ }
+ return proto;
+}
+
+bool ProxyObject::setPrototypeOf(Managed *m, const Object *p)
+{
+ 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 name(scope, scope.engine->newString(QStringLiteral("setPrototypeOf")));
+ ScopedValue trap(scope, handler->get(name));
+ if (scope.hasException())
+ return false;
+ if (trap->isNullOrUndefined())
+ return target->setPrototypeOf(p);
+ if (!trap->isFunctionObject()) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+
+ JSCallData cdata(scope, 2, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = p ? p->asReturnedValue() : Encode::null();
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ bool result = trapResult->toBoolean();
+ if (!result)
+ return false;
+ if (!target->isExtensible()) {
+ Heap::Object *targetProto = target->getPrototypeOf();
+ if (p->d() != targetProto) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+ }
+ return true;
+}
+
+//ReturnedValue ProxyObject::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+//{
+
+//}
+
+//ReturnedValue ProxyObject::call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+//{
+
+//}
+
+DEFINE_OBJECT_VTABLE(Proxy);
+
+void Heap::Proxy::init(QV4::ExecutionContext *ctx)
+{
+ Heap::FunctionObject::init(ctx, QStringLiteral("Proxy"));
+
+ Scope scope(ctx);
+ Scoped<QV4::Proxy> ctor(scope, this);
+ ctor->defineDefaultProperty(QStringLiteral("revocable"), QV4::Proxy::method_revocable, 2);
+ ctor->defineReadonlyConfigurableProperty(scope.engine->id_length(), Primitive::fromInt32(2));
+}
+
+ReturnedValue Proxy::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+{
+ Scope scope(f);
+ if (argc < 2 || !argv[0].isObject() || !argv[1].isObject())
+ return scope.engine->throwTypeError();
+
+ const Object *target = static_cast<const Object *>(argv);
+ const Object *handler = static_cast<const Object *>(argv + 1);
+ if (const ProxyObject *ptarget = target->as<ProxyObject>())
+ if (!ptarget->d()->handler)
+ return scope.engine->throwTypeError();
+ if (const ProxyObject *phandler = handler->as<ProxyObject>())
+ if (!phandler->d()->handler)
+ return scope.engine->throwTypeError();
+
+ ScopedObject o(scope, scope.engine->memoryManager->allocate<ProxyObject>(target, handler));
+ return o->asReturnedValue();
+}
+
+ReturnedValue Proxy::call(const FunctionObject *f, const Value *, const Value *, int)
+{
+ return f->engine()->throwTypeError();
+}
+
+ReturnedValue Proxy::method_revocable(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ Scope scope(f);
+ ScopedObject proxy(scope, Proxy::callAsConstructor(f, argv, argc));
+ if (scope.hasException())
+ return Encode::undefined();
+
+ ScopedString revoke(scope, scope.engine->newString(QStringLiteral("revoke")));
+ ScopedFunctionObject revoker(scope, createBuiltinFunction(scope.engine, revoke, method_revoke, 0));
+ revoker->defineDefaultProperty(scope.engine->symbol_revokableProxy(), proxy);
+
+ ScopedObject o(scope, scope.engine->newObject());
+ ScopedString p(scope, scope.engine->newString(QStringLiteral("proxy")));
+ o->defineDefaultProperty(p, proxy);
+ o->defineDefaultProperty(revoke, revoker);
+ return o->asReturnedValue();
+}
+
+ReturnedValue Proxy::method_revoke(const FunctionObject *f, const Value *, const Value *, int)
+{
+ Scope scope(f);
+ Scoped<ProxyObject> proxy(scope, f->get(scope.engine->symbol_revokableProxy()));
+ Q_ASSERT(proxy);
+
+ proxy->d()->target.set(scope.engine, nullptr);
+ proxy->d()->handler.set(scope.engine, nullptr);
+ return Encode::undefined();
+}
diff --git a/src/qml/jsruntime/qv4proxy_p.h b/src/qml/jsruntime/qv4proxy_p.h
new file mode 100644
index 0000000000..cbabc7e5d9
--- /dev/null
+++ b/src/qml/jsruntime/qv4proxy_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4PROXY_P_H
+#define QV4PROXY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qv4object_p.h"
+#include "qv4functionobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+namespace Heap {
+
+#define ProxyObjectMembers(class, Member) \
+ Member(class, Pointer, Object *, target) \
+ Member(class, Pointer, Object *, handler)
+
+DECLARE_HEAP_OBJECT(ProxyObject, Object) {
+ DECLARE_MARKOBJECTS(ProxyObject)
+
+ void init(const QV4::Object *target, const QV4::Object *handler);
+};
+
+#define ProxyMembers(class, Member) \
+ Member(class, Pointer, Symbol *, revokableProxySymbol) \
+
+DECLARE_HEAP_OBJECT(Proxy, FunctionObject) {
+ DECLARE_MARKOBJECTS(Proxy)
+
+ void init(QV4::ExecutionContext *ctx);
+};
+
+}
+
+struct ProxyObject: Object {
+ V4_OBJECT2(ProxyObject, Object)
+ Q_MANAGED_TYPE(ProxyObject)
+ V4_INTERNALCLASS(ProxyObject)
+
+ static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
+ static bool put(Managed *m, StringOrSymbol *name, const Value &value);
+ static bool putIndexed(Managed *m, uint index, const Value &value);
+ static bool deleteProperty(Managed *m, StringOrSymbol *name);
+ static bool deleteIndexedProperty(Managed *m, uint index);
+ 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 Heap::Object *getPrototypeOf(const Managed *);
+ static bool setPrototypeOf(Managed *, const Object *);
+
+ // those might require a second proxy object that derives from FunctionObject...
+// static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
+// static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+};
+
+struct Proxy : FunctionObject
+{
+ V4_OBJECT2(Proxy, FunctionObject)
+
+ static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
+ static ReturnedValue call(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+
+ static ReturnedValue method_revocable(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+
+ static ReturnedValue method_revoke(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QV4ECMAOBJECTS_P_H
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index e17ce55f7b..94d645ac2b 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -733,25 +733,29 @@ bool QObjectWrapper::put(Managed *m, StringOrSymbol *n, const Value &value)
return true;
}
-PropertyAttributes QObjectWrapper::query(const Managed *m, StringOrSymbol *name)
+PropertyAttributes QObjectWrapper::getOwnProperty(Managed *m, Identifier id, Property *p)
{
- if (name->isSymbol())
- return QV4::Object::query(m, name);
- String *n = static_cast<String *>(name);
-
- const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
- const QObject *thatObject = that->d()->object();
- if (QQmlData::wasDeleted(thatObject))
- return QV4::Object::query(m, name);
+ if (id.isString()) {
+ QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
+ const QObject *thatObject = that->d()->object();
+ if (!QQmlData::wasDeleted(thatObject)) {
+ Scope scope(m);
+ ScopedString n(scope, id.asHeapObject());
+ QQmlContextData *qmlContext = scope.engine->callingQmlContext();
+ QQmlPropertyData local;
+ if (that->findProperty(scope.engine, qmlContext, n, IgnoreRevision, &local)
+ || n->equals(scope.engine->id_destroy()) || n->equals(scope.engine->id_toString())) {
+ if (p) {
+ // ### probably not the fastest implementation
+ bool hasProperty;
+ p->value = that->getQmlProperty(qmlContext, n, IgnoreRevision, &hasProperty, /*includeImports*/ true);
+ }
+ return QV4::Attr_Data;
+ }
+ }
+ }
- ExecutionEngine *engine = that->engine();
- QQmlContextData *qmlContext = engine->callingQmlContext();
- QQmlPropertyData local;
- if (that->findProperty(engine, qmlContext, n, IgnoreRevision, &local)
- || n->equals(engine->id_destroy()) || n->equals(engine->id_toString()))
- return QV4::Attr_Data;
- else
- return QV4::Object::query(m, name);
+ return QV4::Object::getOwnProperty(m, id, p);
}
void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
@@ -2089,7 +2093,7 @@ ReturnedValue QMetaObjectWrapper::constructInternal(const Value *argv, int argc)
}
Scoped<QMetaObjectWrapper> metaObject(scope, this);
object->defineDefaultProperty(v4->id_constructor(), metaObject);
- object->setPrototype(const_cast<QMetaObjectWrapper*>(this));
+ object->setPrototypeOf(const_cast<QMetaObjectWrapper*>(this));
return object.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 56e20adbfa..12272c2925 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -195,7 +195,7 @@ protected:
static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
static bool put(Managed *m, StringOrSymbol *name, const Value &value);
- static PropertyAttributes query(const Managed *, StringOrSymbol *name);
+ static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static ReturnedValue method_connect(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
diff --git a/src/qml/jsruntime/qv4reflect.cpp b/src/qml/jsruntime/qv4reflect.cpp
index 69baecd337..9b4a5a2375 100644
--- a/src/qml/jsruntime/qv4reflect.cpp
+++ b/src/qml/jsruntime/qv4reflect.cpp
@@ -175,12 +175,14 @@ ReturnedValue Reflect::method_getOwnPropertyDescriptor(const FunctionObject *f,
return ObjectPrototype::method_getOwnPropertyDescriptor(f, thisObject, argv, argc);
}
-ReturnedValue Reflect::method_getPrototypeOf(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+ReturnedValue Reflect::method_getPrototypeOf(const FunctionObject *f, const Value *, const Value *argv, int argc)
{
if (!argc || !argv[0].isObject())
return f->engine()->throwTypeError();
- return ObjectPrototype::method_getPrototypeOf(f, thisObject, argv, argc);
+ const Object *o = static_cast<const Object *>(argv);
+ Heap::Object *p = o->getPrototypeOf();
+ return (p ? p->asReturnedValue() : Encode::null());
}
ReturnedValue Reflect::method_has(const FunctionObject *f, const Value *, const Value *argv, int argc)
@@ -232,8 +234,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)
@@ -261,10 +262,13 @@ ReturnedValue Reflect::method_set(const FunctionObject *f, const Value *, const
return Encode(result);
}
-ReturnedValue Reflect::method_setPrototypeOf(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+ReturnedValue Reflect::method_setPrototypeOf(const FunctionObject *f, const Value *, const Value *argv, int argc)
{
- if (argc < 2 || !argv[0].isObject())
+ if (argc < 2 || !argv[0].isObject() || (!argv[1].isNull() && !argv[1].isObject()))
return f->engine()->throwTypeError();
- return ObjectPrototype::method_setPrototypeOf(f, thisObject, argv, argc);
+ Scope scope(f);
+ ScopedObject o(scope, static_cast<const Object *>(argv));
+ const Object *proto = argv[1].isNull() ? nullptr : static_cast<const Object *>(argv + 1);
+ return Encode(o->setPrototypeOf(proto));
}
diff --git a/src/qml/jsruntime/qv4reflect_p.h b/src/qml/jsruntime/qv4reflect_p.h
index 73d257e006..d480e1d914 100644
--- a/src/qml/jsruntime/qv4reflect_p.h
+++ b/src/qml/jsruntime/qv4reflect_p.h
@@ -73,7 +73,7 @@ struct Reflect : Object {
static ReturnedValue method_deleteProperty(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_get(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_getOwnPropertyDescriptor(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_getPrototypeOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_getPrototypeOf(const FunctionObject *, const Value *, const Value *argv, int argc);
static ReturnedValue method_has(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_isExtensible(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_ownKeys(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 8759a72074..a5249fcc7e 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -374,7 +374,7 @@ QV4::ReturnedValue Runtime::method_in(ExecutionEngine *engine, const Value &left
ScopedStringOrSymbol s(scope, left.toPropertyKey(engine));
if (scope.hasException())
return Encode::undefined();
- bool r = ro->hasProperty(s);
+ bool r = ro->hasProperty(s->toPropertyKey());
return Encode(r);
}
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 27c73a2b77..cfd2d0a5b2 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -250,6 +250,14 @@ void Heap::StringOrSymbol::createHashValue() const
stringHash = QV4::String::calculateHashValue(ch, end, &subtype);
}
+Identifier StringOrSymbol::toPropertyKey() const {
+ uint index = asArrayIndex();
+ if (index < UINT_MAX)
+ return Identifier::fromArrayIndex(index);
+ makeIdentifier();
+ return identifier();
+}
+
uint String::getLength(const Managed *m)
{
return static_cast<const String *>(m)->d()->length();
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 0deb542ea2..2e3ca977bf 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -178,6 +178,8 @@ struct Q_QML_PRIVATE_EXPORT StringOrSymbol : public Managed {
uint asArrayIndex() const;
+ Identifier toPropertyKey() const;
+
inline QString toQString() const {
return d()->toQString();
}
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 3639edac17..b1ae5a1ce5 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -118,9 +118,8 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name,
while (it->arrayIndex < slen) {
*index = it->arrayIndex;
++it->arrayIndex;
- PropertyAttributes a;
Property pd;
- s->getOwnProperty(*index, &a, &pd);
+ PropertyAttributes a = s->getOwnProperty(Identifier::fromArrayIndex(*index), &pd);
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
*attrs = a;
p->copy(&pd, a);
@@ -220,7 +219,7 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor)
setProperty(scope.engine, Heap::StringObject::LengthPropertyIndex, Primitive::fromInt32(0));
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineDefaultProperty(QStringLiteral("fromCharCode"), StringCtor::method_fromCharCode, 1);
ctor->defineDefaultProperty(QStringLiteral("fromCodePoint"), StringCtor::method_fromCodePoint, 1);
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 3eadfe04a6..86aa18c3a4 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -410,9 +410,9 @@ void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(3));
ctor->defineReadonlyProperty(engine->id_prototype(), *this);
ctor->defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement));
- ctor->setPrototype(engine->intrinsicTypedArrayCtor());
+ ctor->setPrototypeOf(engine->intrinsicTypedArrayCtor());
- setPrototype(engine->intrinsicTypedArrayPrototype());
+ setPrototypeOf(engine->intrinsicTypedArrayPrototype());
defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement));
}
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 96f6c6aed6..9b43ea0531 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1409,7 +1409,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->allocate<QV4::QmlIncubatorObject>(mode));
QV4::ScopedObject p(scope, e->incubationProto.value());
- r->setPrototype(p);
+ r->setPrototypeOf(p);
if (!valuemap->isUndefined())
r->d()->valuemap.set(scope.engine, valuemap);
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index c5a85dd4d3..42c72e0447 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -828,7 +828,7 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale)
QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocate<QQmlLocaleData>());
*wrapper->d()->locale = locale;
QV4::ScopedObject p(scope, d->prototype.value());
- wrapper->setPrototype(p);
+ wrapper->setPrototypeOf(p);
return wrapper.asReturnedValue();
}
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index dd027818cd..69a8ff034a 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -1873,7 +1873,7 @@ int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *q
if (!module)
return -1;
- QQmlType type = module->type(QHashedStringRef(qmlName), versionMinor);
+ QQmlType type = module->type(QHashedStringRef(QString::fromUtf8(qmlName)), versionMinor);
if (!type.isValid())
return -1;
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 7270cffb00..144d077c44 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -350,15 +350,18 @@ bool QQmlTypeWrapper::put(Managed *m, StringOrSymbol *n, const Value &value)
return false;
}
-PropertyAttributes QQmlTypeWrapper::query(const Managed *m, StringOrSymbol *name)
+PropertyAttributes QQmlTypeWrapper::getOwnProperty(Managed *m, Identifier id, Property *p)
{
- if (name->isSymbol())
- return Object::query(m, name);
- String *n = static_cast<String *>(name);
- // ### Implement more efficiently.
- bool hasProperty = false;
- static_cast<Object *>(const_cast<Managed*>(m))->get(n, &hasProperty);
- return hasProperty ? Attr_Data : Attr_Invalid;
+ if (id.isString()) {
+ Scope scope(m);
+ ScopedString n(scope, id.asHeapObject());
+ // ### Implement more efficiently.
+ bool hasProperty = false;
+ static_cast<Object *>(m)->get(n, &hasProperty);
+ return hasProperty ? Attr_Data : Attr_Invalid;
+ }
+
+ return QV4::Object::getOwnProperty(m, id, p);
}
bool QQmlTypeWrapper::isEqualTo(Managed *a, Managed *b)
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 30bbc8d179..b17d0e0868 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -114,7 +114,7 @@ struct Q_QML_EXPORT QQmlTypeWrapper : Object
static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
static bool put(Managed *m, StringOrSymbol *name, const Value &value);
- static PropertyAttributes query(const Managed *, StringOrSymbol *name);
+ static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p);
static bool isEqualTo(Managed *that, Managed *o);
static ReturnedValue instanceOf(const Object *typeObject, const Value &var);
};
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 7e0cf64bed..aa716b8a73 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -241,17 +241,17 @@ bool QQmlValueTypeWrapper::isEqualTo(Managed *m, Managed *other)
return false;
}
-PropertyAttributes QQmlValueTypeWrapper::query(const Managed *m, StringOrSymbol *name)
+PropertyAttributes QQmlValueTypeWrapper::getOwnProperty(Managed *m, Identifier id, Property *p)
{
- if (name->isSymbol())
- return Object::query(m, name);
-
- String *n = static_cast<String *>(name);
- Q_ASSERT(m->as<const QQmlValueTypeWrapper>());
- const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
+ if (id.isString()) {
+ Scope scope(m);
+ ScopedString n(scope, id.asHeapObject());
+ const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
+ QQmlPropertyData *result = r->d()->propertyCache()->property(n.getPointer(), nullptr, nullptr);
+ return result ? Attr_Data : Attr_Invalid;
+ }
- QQmlPropertyData *result = r->d()->propertyCache()->property(n, nullptr, nullptr);
- return result ? Attr_Data : Attr_Invalid;
+ return QV4::Object::getOwnProperty(m, id, p);
}
void QQmlValueTypeWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index 5a684bfb4d..12d7114d2f 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -109,7 +109,7 @@ public:
static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
static bool put(Managed *m, StringOrSymbol *name, const Value &value);
static bool isEqualTo(Managed *m, Managed *other);
- static PropertyAttributes query(const Managed *, StringOrSymbol *name);
+ static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static ReturnedValue method_toString(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 41531c1df3..a8faac4b0d 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -611,7 +611,7 @@ ReturnedValue Node::create(ExecutionEngine *v4, NodeImpl *data)
switch (data->type) {
case NodeImpl::Attr:
- instance->setPrototype((p = Attr::prototype(v4)));
+ instance->setPrototypeUnchecked((p = Attr::prototype(v4)));
break;
case NodeImpl::Comment:
case NodeImpl::Document:
@@ -623,13 +623,13 @@ ReturnedValue Node::create(ExecutionEngine *v4, NodeImpl *data)
case NodeImpl::ProcessingInstruction:
return Encode::undefined();
case NodeImpl::CDATA:
- instance->setPrototype((p = CDATA::prototype(v4)));
+ instance->setPrototypeUnchecked((p = CDATA::prototype(v4)));
break;
case NodeImpl::Text:
- instance->setPrototype((p = Text::prototype(v4)));
+ instance->setPrototypeUnchecked((p = Text::prototype(v4)));
break;
case NodeImpl::Element:
- instance->setPrototype((p = Element::prototype(v4)));
+ instance->setPrototypeUnchecked((p = Element::prototype(v4)));
break;
}
@@ -643,7 +643,7 @@ ReturnedValue Element::prototype(ExecutionEngine *engine)
Scope scope(engine);
ScopedObject p(scope, engine->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = NodePrototype::getProto(engine)));
+ p->setPrototypeUnchecked((pp = NodePrototype::getProto(engine)));
p->defineAccessorProperty(QStringLiteral("tagName"), NodePrototype::method_get_nodeName, nullptr);
d->elementPrototype.set(engine, p);
engine->v8Engine->freezeObject(p);
@@ -658,7 +658,7 @@ ReturnedValue Attr::prototype(ExecutionEngine *engine)
Scope scope(engine);
ScopedObject p(scope, engine->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = NodePrototype::getProto(engine)));
+ p->setPrototypeUnchecked((pp = NodePrototype::getProto(engine)));
p->defineAccessorProperty(QStringLiteral("name"), method_name, nullptr);
p->defineAccessorProperty(QStringLiteral("value"), method_value, nullptr);
p->defineAccessorProperty(QStringLiteral("ownerElement"), method_ownerElement, nullptr);
@@ -715,7 +715,7 @@ ReturnedValue CharacterData::prototype(ExecutionEngine *v4)
Scope scope(v4);
ScopedObject p(scope, v4->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = NodePrototype::getProto(v4)));
+ p->setPrototypeUnchecked((pp = NodePrototype::getProto(v4)));
p->defineAccessorProperty(QStringLiteral("data"), NodePrototype::method_get_nodeValue, nullptr);
p->defineAccessorProperty(QStringLiteral("length"), method_length, nullptr);
d->characterDataPrototype.set(v4, p);
@@ -751,7 +751,7 @@ ReturnedValue Text::prototype(ExecutionEngine *v4)
Scope scope(v4);
ScopedObject p(scope, v4->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = CharacterData::prototype(v4)));
+ p->setPrototypeUnchecked((pp = CharacterData::prototype(v4)));
p->defineAccessorProperty(QStringLiteral("isElementContentWhitespace"), method_isElementContentWhitespace, nullptr);
p->defineAccessorProperty(QStringLiteral("wholeText"), method_wholeText, nullptr);
d->textPrototype.set(v4, p);
@@ -768,7 +768,7 @@ ReturnedValue CDATA::prototype(ExecutionEngine *v4)
Scope scope(v4);
ScopedObject p(scope, v4->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = Text::prototype(v4)));
+ p->setPrototypeUnchecked((pp = Text::prototype(v4)));
d->cdataPrototype.set(v4, p);
v4->v8Engine->freezeObject(p);
}
@@ -782,7 +782,7 @@ ReturnedValue Document::prototype(ExecutionEngine *v4)
Scope scope(v4);
ScopedObject p(scope, v4->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = NodePrototype::getProto(v4)));
+ p->setPrototypeUnchecked((pp = NodePrototype::getProto(v4)));
p->defineAccessorProperty(QStringLiteral("xmlVersion"), method_xmlVersion, nullptr);
p->defineAccessorProperty(QStringLiteral("xmlEncoding"), method_xmlEncoding, nullptr);
p->defineAccessorProperty(QStringLiteral("xmlStandalone"), method_xmlStandalone, nullptr);
@@ -879,7 +879,7 @@ ReturnedValue Document::load(ExecutionEngine *v4, const QByteArray &data)
ScopedObject instance(scope, v4->memoryManager->allocate<Node>(document));
document->release(); // the GC should own the NodeImpl via Node now
ScopedObject p(scope);
- instance->setPrototype((p = Document::prototype(v4)));
+ instance->setPrototypeUnchecked((p = Document::prototype(v4)));
return instance.asReturnedValue();
}
@@ -1650,7 +1650,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->v8Engine->networkAccessManager(), scope.engine);
Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocate<QQmlXMLHttpRequestWrapper>(r));
ScopedObject proto(scope, ctor->d()->proto);
- w->setPrototype(proto);
+ w->setPrototypeUnchecked(proto);
return w.asReturnedValue();
}
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index b5e25fb6d4..f99c4def45 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -223,13 +223,13 @@ static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object)
QV4::Scope scope(v4);
bool instanceOfObject = false;
- QV4::ScopedObject p(scope, object->prototype());
+ QV4::ScopedObject p(scope, object->getPrototypeOf());
while (p) {
if (p->d() == v4->objectPrototype()->d()) {
instanceOfObject = true;
break;
}
- p = p->prototype();
+ p = p->getPrototypeOf();
}
if (!instanceOfObject)
return;
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 62ccf0d66c..f98f57a8ed 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -2563,7 +2563,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index)
QV4::Scope scope(v4);
QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(cacheItem));
QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value());
- o->setPrototype(p);
+ o->setPrototypeOf(p);
++cacheItem->scriptRef;
return QQmlV4Handle(o);
@@ -3395,7 +3395,7 @@ public:
QV4::ScopedObject changeProto(scope, engineData(v4)->changeProto.value());
QV4::Scoped<QQmlDelegateModelGroupChange> object(scope, QQmlDelegateModelGroupChange::create(v4));
- object->setPrototype(changeProto);
+ object->setPrototypeOf(changeProto);
object->d()->change = change;
if (hasProperty)
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index 3016316e57..4130eff33a 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -439,7 +439,7 @@ public:
QV4::Scope scope(v4);
QV4::ScopedObject proto(scope, type->prototype.value());
QV4::ScopedObject o(scope, proto->engine()->memoryManager->allocate<QQmlDelegateModelItemObject>(this));
- o->setPrototype(proto);
+ o->setPrototypeOf(proto);
++scriptRef;
return o.asReturnedValue();
}
@@ -620,7 +620,7 @@ public:
QV4::Scope scope(v4);
QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(this));
QV4::ScopedObject p(scope, data->listItemProto.value());
- o->setPrototype(p);
+ o->setPrototypeOf(p);
++scriptRef;
return o.asReturnedValue();
}