aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp21
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp20
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4object.cpp197
-rw-r--r--src/qml/jsruntime/qv4object_p.h29
-rw-r--r--src/qml/jsruntime/qv4proxy.cpp17
-rw-r--r--src/qml/jsruntime/qv4proxy_p.h3
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp17
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h2
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp20
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h2
-rw-r--r--src/qml/jsruntime/qv4reflect.cpp11
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp2
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp8
-rw-r--r--src/qml/jsruntime/qv4serialize.cpp2
-rw-r--r--src/qml/jsruntime/qv4symbol_p.h4
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp6
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h2
19 files changed, 148 insertions, 219 deletions
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index ba9bf9652d..c2a50a49ec 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -185,17 +185,20 @@ ReturnedValue ArgumentsObject::getIndexed(const Managed *m, uint index, bool *ha
return Encode::undefined();
}
-bool ArgumentsObject::putIndexed(Managed *m, uint index, const Value &value)
+bool ArgumentsObject::put(Managed *m, Identifier id, const Value &value, Value *receiver)
{
ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
- if (!args->fullyCreated() && index >= static_cast<uint>(args->context()->argc()))
- args->fullyCreate();
-
- if (args->fullyCreated())
- return Object::putIndexed(m, index, value);
-
- args->context()->setArg(index, value);
- return true;
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ if (!args->fullyCreated() && index >= static_cast<uint>(args->context()->argc()))
+ args->fullyCreate();
+
+ if (!args->fullyCreated()) {
+ args->context()->setArg(index, value);
+ return true;
+ }
+ }
+ return Object::put(m, id, value, receiver);
}
bool ArgumentsObject::deleteProperty(Managed *m, Identifier id)
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index 46110e465f..69d136674b 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -148,7 +148,7 @@ struct ArgumentsObject: Object {
static bool defineOwnProperty(Managed *m, Identifier id, const Property *desc, PropertyAttributes attrs);
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
- static bool putIndexed(Managed *m, uint index, const Value &value);
+ static bool put(Managed *m, Identifier id, const Value &value, Value *receiver);
static bool deleteProperty(Managed *m, Identifier id);
static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p);
static qint64 getLength(const Managed *m);
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 481dfd22c6..9efb315b50 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -385,7 +385,7 @@ ReturnedValue ArrayPrototype::method_concat(const FunctionObject *b, const Value
for (int i = 0, len = eltAsObj->getLength(); i < len; ++i) {
entry = eltAsObj->getIndexed(i);
// spec says not to throw if this fails
- result->putIndexed(startIndex + i, entry);
+ result->put(startIndex + i, entry);
}
} else {
result->arraySet(result->getLength(), argv[i]);
@@ -675,7 +675,7 @@ ReturnedValue ArrayPrototype::method_push(const FunctionObject *b, const Value *
len = instance->arrayData()->length();
} else {
for (int i = 0, ei = argc; i < ei; ++i) {
- if (!instance->putIndexed(len + i, argv[i]))
+ if (!instance->put(len + i, argv[i]))
return scope.engine->throwTypeError();
}
len += argc;
@@ -713,12 +713,12 @@ ReturnedValue ArrayPrototype::method_reverse(const FunctionObject *b, const Valu
CHECK_EXCEPTION();
bool ok;
if (hiExists)
- ok = instance->putIndexed(lo, hval);
+ ok = instance->put(lo, hval);
else
ok = instance->deleteProperty(Identifier::fromArrayIndex(lo));
if (ok) {
if (loExists)
- ok = instance->putIndexed(hi, lval);
+ ok = instance->put(hi, lval);
else
ok = instance->deleteProperty(Identifier::fromArrayIndex(hi));
}
@@ -761,7 +761,7 @@ ReturnedValue ArrayPrototype::method_shift(const FunctionObject *b, const Value
CHECK_EXCEPTION();
bool ok;
if (exists)
- ok = instance->putIndexed(k - 1, v);
+ ok = instance->put(k - 1, v);
else
ok = instance->deleteProperty(Identifier::fromArrayIndex(k - 1));
if (!ok)
@@ -889,7 +889,7 @@ ReturnedValue ArrayPrototype::method_splice(const FunctionObject *b, const Value
CHECK_EXCEPTION();
bool ok;
if (exists)
- ok = instance->putIndexed(k + itemCount, v);
+ ok = instance->put(k + itemCount, v);
else
ok = instance->deleteProperty(Identifier::fromArrayIndex(k + itemCount));
if (!ok)
@@ -907,7 +907,7 @@ ReturnedValue ArrayPrototype::method_splice(const FunctionObject *b, const Value
CHECK_EXCEPTION();
bool ok;
if (exists)
- ok = instance->putIndexed(k + itemCount - 1, v);
+ ok = instance->put(k + itemCount - 1, v);
else
ok = instance->deleteProperty(Identifier::fromArrayIndex(k + itemCount - 1));
if (!ok)
@@ -917,7 +917,7 @@ ReturnedValue ArrayPrototype::method_splice(const FunctionObject *b, const Value
}
for (uint i = 0; i < itemCount; ++i)
- instance->putIndexed(start + i, argv[i + 2]);
+ instance->put(start + i, argv[i + 2]);
if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount))))
return scope.engine->throwTypeError();
@@ -947,14 +947,14 @@ ReturnedValue ArrayPrototype::method_unshift(const FunctionObject *b, const Valu
v = instance->getIndexed(k - 1, &exists);
bool ok;
if (exists)
- ok = instance->putIndexed(k + argc - 1, v);
+ ok = instance->put(k + argc - 1, v);
else
ok = instance->deleteProperty(Identifier::fromArrayIndex(k + argc - 1));
if (!ok)
return scope.engine->throwTypeError();
}
for (int i = 0, ei = argc; i < ei; ++i) {
- bool ok = instance->putIndexed(i, argv[i]);
+ bool ok = instance->put(i, argv[i]);
if (!ok)
return scope.engine->throwTypeError();
}
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 75a9bf4111..ed7d8611ee 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -264,7 +264,7 @@ bool JsonParser::parseMember(Object *o)
ScopedString s(scope, engine->newIdentifier(key));
uint idx = s->asArrayIndex();
if (idx < UINT_MAX) {
- o->putIndexed(idx, val);
+ o->put(idx, val);
} else {
o->insertMember(s, val);
}
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 1597c35319..7c375db1e1 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -268,50 +268,43 @@ void Object::setPrototypeUnchecked(const Object *p)
}
// Section 8.12.2
-PropertyIndex Object::getValueOrSetter(StringOrSymbol *name, PropertyAttributes *attrs)
+PropertyIndex Object::getValueOrSetter(Identifier id, PropertyAttributes *attrs)
{
- Q_ASSERT(name->asArrayIndex() == UINT_MAX);
-
- name->makeIdentifier();
- Identifier id = name->identifier();
-
- Heap::Object *o = d();
- while (o) {
- uint idx = o->internalClass->find(id);
- if (idx < UINT_MAX) {
- *attrs = o->internalClass->propertyData[idx];
- return o->writablePropertyData(attrs->isAccessor() ? idx + SetterOffset : idx );
- }
-
- o = o->prototype();
- }
- *attrs = Attr_Invalid;
- return { nullptr, nullptr };
-}
-
-PropertyIndex Object::getValueOrSetter(uint index, PropertyAttributes *attrs)
-{
- Heap::Object *o = d();
- while (o) {
- if (o->arrayData) {
- uint idx = o->arrayData->mappedIndex(index);
- if (idx != UINT_MAX) {
- *attrs = o->arrayData->attributes(index);
- return { o->arrayData , o->arrayData->values.values + (attrs->isAccessor() ? idx + SetterOffset : idx) };
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ Heap::Object *o = d();
+ while (o) {
+ if (o->arrayData) {
+ uint idx = o->arrayData->mappedIndex(index);
+ if (idx != UINT_MAX) {
+ *attrs = o->arrayData->attributes(index);
+ return { o->arrayData , o->arrayData->values.values + (attrs->isAccessor() ? idx + SetterOffset : idx) };
+ }
+ }
+ if (o->vtable()->type == Type_StringObject) {
+ if (index < static_cast<const Heap::StringObject *>(o)->length()) {
+ // this is an evil hack, but it works, as the method is only ever called from put,
+ // where we don't use the returned pointer there for non writable attributes
+ *attrs = (Attr_NotWritable|Attr_NotConfigurable);
+ return { reinterpret_cast<Heap::ArrayData *>(0x1), nullptr };
+ }
}
+ o = o->prototype();
}
- if (o->vtable()->type == Type_StringObject) {
- if (index < static_cast<const Heap::StringObject *>(o)->length()) {
- // this is an evil hack, but it works, as the method is only ever called from putIndexed,
- // where we don't use the returned pointer there for non writable attributes
- *attrs = (Attr_NotWritable|Attr_NotConfigurable);
- return { reinterpret_cast<Heap::ArrayData *>(0x1), 0 };
+ } else {
+ Heap::Object *o = d();
+ while (o) {
+ uint idx = o->internalClass->find(id);
+ if (idx < UINT_MAX) {
+ *attrs = o->internalClass->propertyData[idx];
+ return o->writablePropertyData(attrs->isAccessor() ? idx + SetterOffset : idx );
}
+
+ o = o->prototype();
}
- o = o->prototype();
}
*attrs = Attr_Invalid;
- return { nullptr, 0 };
+ return { nullptr, nullptr };
}
ReturnedValue Object::callAsConstructor(const FunctionObject *f, const Value *, int)
@@ -334,14 +327,9 @@ ReturnedValue Object::getIndexed(const Managed *m, uint index, bool *hasProperty
return static_cast<const Object *>(m)->internalGetIndexed(index, hasProperty);
}
-bool Object::put(Managed *m, StringOrSymbol *name, const Value &value)
-{
- return static_cast<Object *>(m)->internalPut(name, value);
-}
-
-bool Object::putIndexed(Managed *m, uint index, const Value &value)
+bool Object::put(Managed *m, Identifier id, const Value &value, Value *receiver)
{
- return static_cast<Object *>(m)->internalPutIndexed(index, value);
+ return static_cast<Object *>(m)->internalPut(id, value, receiver);
}
bool Object::deleteProperty(Managed *m, Identifier id)
@@ -484,31 +472,39 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
// Section 8.12.5
-bool Object::internalPut(StringOrSymbol *name, const Value &value)
+bool Object::internalPut(Identifier id, const Value &value, Value *receiver)
{
ExecutionEngine *engine = this->engine();
if (engine->hasException)
return false;
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return putIndexed(idx, value);
-
- name->makeIdentifier();
- Identifier id = name->identifier();
+ uint index = id.asArrayIndex();
+ Scope scope(engine);
- PropertyIndex memberIndex{nullptr, nullptr};
- uint member = internalClass()->find(id);
PropertyAttributes attrs;
- if (member < UINT_MAX) {
- attrs = internalClass()->propertyData[member];
- memberIndex = d()->writablePropertyData(attrs.isAccessor() ? member + SetterOffset : member);
+ PropertyIndex propertyIndex{nullptr, nullptr};
+
+ if (index != UINT_MAX) {
+ if (arrayData())
+ propertyIndex = arrayData()->getValueOrSetter(index, &attrs);
+
+ if (propertyIndex.isNull() && isStringObject()) {
+ if (index < static_cast<StringObject *>(this)->length())
+ // not writable
+ return false;
+ }
+ } else {
+ uint member = internalClass()->find(id);
+ if (member < UINT_MAX) {
+ attrs = internalClass()->propertyData[member];
+ propertyIndex = d()->writablePropertyData(attrs.isAccessor() ? member + SetterOffset : member);
+ }
}
// clause 1
- if (!memberIndex.isNull()) {
+ if (!propertyIndex.isNull()) {
if (attrs.isAccessor()) {
- if (memberIndex->as<FunctionObject>())
+ if (propertyIndex->as<FunctionObject>())
goto cont;
return false;
} else if (!attrs.isWritable())
@@ -524,7 +520,7 @@ bool Object::internalPut(StringOrSymbol *name, const Value &value)
if (!ok)
return false;
} else {
- memberIndex.set(engine, value);
+ propertyIndex.set(engine, value);
}
return true;
} else if (!getPrototypeOf()) {
@@ -532,11 +528,10 @@ bool Object::internalPut(StringOrSymbol *name, const Value &value)
return false;
} else {
// clause 4
- Scope scope(engine);
- memberIndex = ScopedObject(scope, getPrototypeOf())->getValueOrSetter(name, &attrs);
- if (!memberIndex.isNull()) {
+ propertyIndex = ScopedObject(scope, getPrototypeOf())->getValueOrSetter(id, &attrs);
+ if (!propertyIndex.isNull()) {
if (attrs.isAccessor()) {
- if (!memberIndex->as<FunctionObject>())
+ if (!propertyIndex->as<FunctionObject>())
return false;
} else if (!isExtensible() || !attrs.isWritable()) {
return false;
@@ -549,84 +544,24 @@ bool Object::internalPut(StringOrSymbol *name, const Value &value)
cont:
// Clause 5
- if (!memberIndex.isNull() && attrs.isAccessor()) {
- Q_ASSERT(memberIndex->as<FunctionObject>());
+ if (!propertyIndex.isNull() && attrs.isAccessor()) {
+ Q_ASSERT(propertyIndex->as<FunctionObject>());
Scope scope(engine);
- ScopedFunctionObject setter(scope, *memberIndex);
+ ScopedFunctionObject setter(scope, *propertyIndex);
JSCallData jsCallData(scope, 1);
jsCallData->args[0] = value;
- *jsCallData->thisObject = this;
+ *jsCallData->thisObject = *receiver;
setter->call(jsCallData);
return !engine->hasException;
}
- insertMember(name, value);
- return true;
-}
-
-bool Object::internalPutIndexed(uint index, const Value &value)
-{
- ExecutionEngine *engine = this->engine();
- if (engine->hasException)
- return false;
-
- PropertyAttributes attrs;
-
- PropertyIndex arrayIndex = arrayData() ? arrayData()->getValueOrSetter(index, &attrs) : PropertyIndex{ nullptr, 0 };
-
- if (arrayIndex.isNull() && isStringObject()) {
- if (index < static_cast<StringObject *>(this)->length())
- // not writable
- return false;
- }
-
- // clause 1
- if (!arrayIndex.isNull()) {
- if (attrs.isAccessor()) {
- if (arrayIndex->as<FunctionObject>())
- goto cont;
- return false;
- } else if (!attrs.isWritable())
- return false;
-
- arrayIndex.set(engine, value);
- return true;
- } else if (!getPrototypeOf()) {
- if (!isExtensible())
- return false;
+ if (index != UINT_MAX) {
+ arraySet(index, value);
} else {
- // clause 4
- Scope scope(engine);
- arrayIndex = ScopedObject(scope, getPrototypeOf())->getValueOrSetter(index, &attrs);
- if (!arrayIndex.isNull()) {
- if (attrs.isAccessor()) {
- if (!arrayIndex->as<FunctionObject>())
- return false;
- } else if (!isExtensible() || !attrs.isWritable()) {
- return false;
- }
- } else if (!isExtensible()) {
- return false;
- }
+ Scoped<StringOrSymbol> name(scope, id.asHeapObject());
+ insertMember(name, value);
}
-
- cont:
-
- // Clause 5
- if (!arrayIndex.isNull() && attrs.isAccessor()) {
- Q_ASSERT(arrayIndex->as<FunctionObject>());
-
- Scope scope(engine);
- ScopedFunctionObject setter(scope, *arrayIndex);
- JSCallData jsCallData(scope, 1);
- jsCallData->args[0] = value;
- *jsCallData->thisObject = this;
- setter->call(jsCallData);
- return !engine->hasException;
- }
-
- arraySet(index, value);
return true;
}
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index e57708d8e4..88d07ef3f1 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -171,8 +171,7 @@ struct ObjectVTable
ReturnedValue (*callAsConstructor)(const FunctionObject *, const Value *argv, int argc);
ReturnedValue (*get)(const Managed *, StringOrSymbol *name, bool *hasProperty);
ReturnedValue (*getIndexed)(const Managed *, uint index, bool *hasProperty);
- bool (*put)(Managed *, StringOrSymbol *name, const Value &value);
- bool (*putIndexed)(Managed *, uint index, const Value &value);
+ bool (*put)(Managed *, Identifier id, const Value &value, Value *receiver);
bool (*deleteProperty)(Managed *m, Identifier id);
bool (*hasProperty)(const Managed *m, Identifier id);
PropertyAttributes (*getOwnProperty)(Managed *m, Identifier id, Property *p);
@@ -195,7 +194,6 @@ const QV4::ObjectVTable classname::static_vtbl = \
get, \
getIndexed, \
put, \
- putIndexed, \
deleteProperty, \
hasProperty, \
getOwnProperty, \
@@ -253,8 +251,7 @@ struct Q_QML_EXPORT Object: Managed {
return vtable()->getOwnProperty(this, id, p);
}
- PropertyIndex getValueOrSetter(StringOrSymbol *name, PropertyAttributes *attrs);
- PropertyIndex getValueOrSetter(uint index, PropertyAttributes *attrs);
+ PropertyIndex getValueOrSetter(Identifier id, PropertyAttributes *attrs);
bool hasProperty(Identifier id) const {
return vtable()->hasProperty(this, id);
@@ -382,10 +379,14 @@ public:
{ return vtable()->getIndexed(this, idx, hasProperty); }
// use the set variants instead, to customize throw behavior
- inline bool put(StringOrSymbol *name, const Value &v)
- { return vtable()->put(this, name, v); }
- inline bool putIndexed(uint idx, const Value &v)
- { return vtable()->putIndexed(this, idx, v); }
+ inline bool put(StringOrSymbol *name, const Value &v, Value *receiver = nullptr)
+ { if (!receiver) receiver = this; return vtable()->put(this, name->toPropertyKey(), v, receiver); }
+ inline bool put(uint idx, const Value &v, Value *receiver = nullptr)
+ { if (!receiver) receiver = this; return vtable()->put(this, Identifier::fromArrayIndex(idx), v, receiver); }
+ QT_DEPRECATED inline bool putIndexed(uint idx, const Value &v)
+ { return put(idx, v); }
+ inline bool put(Identifier id, const Value &v, Value *receiver = nullptr)
+ { if (!receiver) receiver = this; return vtable()->put(this, id, v, receiver); }
enum ThrowOnFailure {
DoThrowOnRejection,
@@ -396,7 +397,7 @@ public:
// which is much more efficient for the array case.
inline bool setIndexed(uint idx, const Value &v, ThrowOnFailure shouldThrow)
{
- bool ret = vtable()->putIndexed(this, idx, v);
+ bool ret = vtable()->put(this, Identifier::fromArrayIndex(idx), v, this);
// ES6: 7.3.3, 6: If success is false and Throw is true, throw a TypeError exception.
if (!ret && shouldThrow == ThrowOnFailure::DoThrowOnRejection) {
ExecutionEngine *e = engine();
@@ -412,7 +413,7 @@ public:
// ES6: 7.3.3 Set (O, P, V, Throw)
inline bool set(StringOrSymbol *name, const Value &v, ThrowOnFailure shouldThrow)
{
- bool ret = vtable()->put(this, name, v);
+ bool ret = vtable()->put(this, name->toPropertyKey(), v, this);
// ES6: 7.3.3, 6: If success is false and Throw is true, throw a TypeError exception.
if (!ret && shouldThrow == ThrowOnFailure::DoThrowOnRejection) {
ExecutionEngine *e = engine();
@@ -438,8 +439,7 @@ protected:
static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
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 put(Managed *m, Identifier id, const Value &value, Value *receiver);
static bool deleteProperty(Managed *m, Identifier id);
static bool hasProperty(const Managed *m, Identifier id);
static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p);
@@ -456,8 +456,7 @@ private:
bool internalDefineOwnProperty(ExecutionEngine *engine, uint index, StringOrSymbol *member, const Property *p, PropertyAttributes attrs);
ReturnedValue internalGet(StringOrSymbol *name, bool *hasProperty) const;
ReturnedValue internalGetIndexed(uint index, bool *hasProperty) const;
- bool internalPut(StringOrSymbol *name, const Value &value);
- bool internalPutIndexed(uint index, const Value &value);
+ bool internalPut(Identifier id, const Value &value, Value *receiver);
bool internalDeleteProperty(Identifier id);
friend struct ObjectIterator;
diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp
index 5b5149a2f4..11914e4feb 100644
--- a/src/qml/jsruntime/qv4proxy.cpp
+++ b/src/qml/jsruntime/qv4proxy.cpp
@@ -103,7 +103,7 @@ ReturnedValue ProxyObject::getIndexed(const Managed *m, uint index, bool *hasPro
return get(m, name, hasProperty);
}
-bool ProxyObject::put(Managed *m, StringOrSymbol *name, const Value &value)
+bool ProxyObject::put(Managed *m, Identifier id, const Value &value, Value *receiver)
{
Scope scope(m);
const ProxyObject *o = static_cast<const ProxyObject *>(m);
@@ -117,21 +117,21 @@ bool ProxyObject::put(Managed *m, StringOrSymbol *name, const Value &value)
if (scope.hasException())
return Encode::undefined();
if (trap->isNullOrUndefined())
- return target->put(name, value);
+ return target->put(id, value, receiver);
if (!trap->isFunctionObject())
return scope.engine->throwTypeError();
JSCallData cdata(scope, 4, nullptr, handler);
cdata.args[0] = target;
- cdata.args[1] = name;
+ cdata.args[1] = id.toStringOrSymbol(scope.engine);
cdata.args[2] = value;
- cdata.args[3] = o->d(); // ### fix receiver handling
+ cdata.args[3] = *receiver;
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);
+ PropertyAttributes attributes = target->getOwnProperty(id, targetDesc);
if (attributes != Attr_Invalid && !attributes.isConfigurable()) {
if (attributes.isData() && !attributes.isWritable()) {
if (!value.sameValue(targetDesc->value))
@@ -143,13 +143,6 @@ bool ProxyObject::put(Managed *m, StringOrSymbol *name, const Value &value)
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, Identifier id)
{
Scope scope(m);
diff --git a/src/qml/jsruntime/qv4proxy_p.h b/src/qml/jsruntime/qv4proxy_p.h
index 306f3f00cb..f605621210 100644
--- a/src/qml/jsruntime/qv4proxy_p.h
+++ b/src/qml/jsruntime/qv4proxy_p.h
@@ -87,8 +87,7 @@ struct ProxyObject: Object {
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 put(Managed *m, Identifier id, const Value &value, Value *receiver);
static bool deleteProperty(Managed *m, Identifier id);
static bool hasProperty(const Managed *m, Identifier id);
static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p);
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 4226bf7972..a3e761050c 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -229,13 +229,12 @@ ReturnedValue QQmlContextWrapper::get(const Managed *m, StringOrSymbol *n, bool
return Encode::undefined();
}
-bool QQmlContextWrapper::put(Managed *m, StringOrSymbol *n, const Value &value)
+bool QQmlContextWrapper::put(Managed *m, Identifier id, const Value &value, Value *receiver)
{
Q_ASSERT(m->as<QQmlContextWrapper>());
- if (n->isSymbol())
- return Object::put(m, n, value);
- String *name = static_cast<String *>(n);
+ if (id.isSymbol() || id.isArrayIndex())
+ return Object::put(m, id, value, receiver);
QQmlContextWrapper *resource = static_cast<QQmlContextWrapper *>(m);
ExecutionEngine *v4 = resource->engine();
@@ -244,21 +243,20 @@ bool QQmlContextWrapper::put(Managed *m, StringOrSymbol *n, const Value &value)
return false;
QV4::Scoped<QQmlContextWrapper> wrapper(scope, resource);
- name->makeIdentifier();
- uint member = wrapper->internalClass()->find(name->identifier());
+ uint member = wrapper->internalClass()->find(id);
if (member < UINT_MAX)
return wrapper->putValue(member, value);
if (wrapper->d()->isNullWrapper) {
if (wrapper && wrapper->d()->readOnly) {
- QString error = QLatin1String("Invalid write to global property \"") + name->toQString() +
+ QString error = QLatin1String("Invalid write to global property \"") + id.toQString() +
QLatin1Char('"');
ScopedString e(scope, v4->newString(error));
v4->throwError(e);
return false;
}
- return Object::put(m, name, value);
+ return Object::put(m, id, value, receiver);
}
// It's possible we could delay the calculation of the "actual" context (in the case
@@ -272,6 +270,7 @@ bool QQmlContextWrapper::put(Managed *m, StringOrSymbol *n, const Value &value)
// See QV8ContextWrapper::Getter for resolution order
QObject *scopeObject = wrapper->getScopeObject();
+ ScopedString name(scope, id.asHeapObject());
while (context) {
const QV4::IdentifierHash &properties = context->propertyNames();
@@ -302,7 +301,7 @@ bool QQmlContextWrapper::put(Managed *m, StringOrSymbol *n, const Value &value)
return false;
}
- return Object::put(m, name, value);
+ return Object::put(m, id, value, receiver);
}
void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QQmlContextWrapper *qml)
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index 86c5b62da2..2dc0e57008 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -99,7 +99,7 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
void setReadOnly(bool b) { d()->readOnly = b; }
static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
- static bool put(Managed *m, StringOrSymbol *name, const Value &value);
+ static bool put(Managed *m, Identifier id, const Value &value, Value *receiver);
};
struct Q_QML_EXPORT QmlContext : public ExecutionContext
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 94d645ac2b..8476d01f67 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -703,30 +703,30 @@ QV4::ReturnedValue QObjectWrapper::get(const Managed *m, StringOrSymbol *name, b
return that->getQmlProperty(qmlContext, n, IgnoreRevision, hasProperty, /*includeImports*/ true);
}
-bool QObjectWrapper::put(Managed *m, StringOrSymbol *n, const Value &value)
+bool QObjectWrapper::put(Managed *m, Identifier id, const Value &value, Value *receiver)
{
- if (n->isSymbol())
- return Object::put(m, n, value);
- String *name = static_cast<String *>(n);
+ if (!id.isString())
+ return Object::put(m, id, value, receiver);
+ Scope scope(m);
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
- ExecutionEngine *v4 = that->engine();
+ ScopedString name(scope, id.asHeapObject());
- if (v4->hasException || QQmlData::wasDeleted(that->d()->object()))
+ if (scope.engine->hasException || QQmlData::wasDeleted(that->d()->object()))
return false;
- QQmlContextData *qmlContext = v4->callingQmlContext();
- if (!setQmlProperty(v4, qmlContext, that->d()->object(), name, QV4::QObjectWrapper::IgnoreRevision, value)) {
+ QQmlContextData *qmlContext = scope.engine->callingQmlContext();
+ if (!setQmlProperty(scope.engine, qmlContext, that->d()->object(), name, QV4::QObjectWrapper::IgnoreRevision, value)) {
QQmlData *ddata = QQmlData::get(that->d()->object());
// Types created by QML are not extensible at run-time, but for other QObjects we can store them
// as regular JavaScript properties, like on JavaScript objects.
if (ddata && ddata->context) {
QString error = QLatin1String("Cannot assign to non-existent property \"") +
name->toQString() + QLatin1Char('\"');
- v4->throwError(error);
+ scope.engine->throwError(error);
return false;
} else {
- return QV4::Object::put(m, name, value);
+ return QV4::Object::put(m, id, value, receiver);
}
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 12272c2925..5d1f79fd39 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -194,7 +194,7 @@ protected:
QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const;
static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
- static bool put(Managed *m, StringOrSymbol *name, const Value &value);
+ static bool put(Managed *m, Identifier id, const Value &value, Value *receiver);
static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
diff --git a/src/qml/jsruntime/qv4reflect.cpp b/src/qml/jsruntime/qv4reflect.cpp
index 2594f53b14..48920fd63c 100644
--- a/src/qml/jsruntime/qv4reflect.cpp
+++ b/src/qml/jsruntime/qv4reflect.cpp
@@ -248,17 +248,12 @@ ReturnedValue Reflect::method_set(const FunctionObject *f, const Value *, const
Value undef = Primitive::undefinedValue();
const Value *index = argc > 1 ? &argv[1] : &undef;
const Value &val = argc > 2 ? argv[2] : undef;
+ ScopedValue receiver(scope, argc >3 ? argv[3] : argv[0]);
- uint n = index->asArrayIndex();
- if (n < UINT_MAX) {
- bool result = o->putIndexed(n, val);
- return Encode(result);
- }
-
- ScopedStringOrSymbol name(scope, index->toPropertyKey(scope.engine));
+ Scoped<StringOrSymbol> propertyKey(scope, index->toPropertyKey(scope.engine));
if (scope.engine->hasException)
return false;
- bool result = o->put(name, val);
+ bool result = o->put(propertyKey->toPropertyKey(), val, receiver);
return Encode(result);
}
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 7f2738321c..948a002e46 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -689,7 +689,7 @@ static Q_NEVER_INLINE bool setElementFallback(ExecutionEngine *engine, const Val
return true;
}
}
- return o->putIndexed(idx, value);
+ return o->put(idx, value);
}
ScopedStringOrSymbol name(scope, index.toPropertyKey(engine));
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index f6f8e51e19..74964916ee 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -565,8 +565,12 @@ public:
static QV4::ReturnedValue getIndexed(const QV4::Managed *that, uint index, bool *hasProperty)
{ return static_cast<const QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); }
- static bool putIndexed(Managed *that, uint index, const QV4::Value &value)
- { return static_cast<QQmlSequence<Container> *>(that)->containerPutIndexed(index, value); }
+ static bool put(Managed *that, Identifier id, const QV4::Value &value, Value *receiver)
+ {
+ if (id.isArrayIndex())
+ return static_cast<QQmlSequence<Container> *>(that)->containerPutIndexed(id.asArrayIndex(), value);
+ return Object::put(that, id, value, receiver);
+ }
static QV4::PropertyAttributes queryIndexed(const QV4::Managed *that, uint index)
{ return static_cast<const QQmlSequence<Container> *>(that)->containerQueryIndexed(index); }
static bool deleteProperty(QV4::Managed *that, Identifier id)
diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp
index 31b51cbfe3..0fb6044e7d 100644
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ b/src/qml/jsruntime/qv4serialize.cpp
@@ -332,7 +332,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine)
ScopedValue v(scope);
for (quint32 ii = 0; ii < size; ++ii) {
v = deserialize(data, engine);
- a->putIndexed(ii, v);
+ a->put(ii, v);
}
return a.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4symbol_p.h b/src/qml/jsruntime/qv4symbol_p.h
index 3cf6bc5dde..ed04b436ef 100644
--- a/src/qml/jsruntime/qv4symbol_p.h
+++ b/src/qml/jsruntime/qv4symbol_p.h
@@ -117,9 +117,7 @@ struct SymbolObject : Object
V4_INTERNALCLASS(SymbolObject)
V4_PROTOTYPE(symbolPrototype)
- static bool put(Managed *, StringOrSymbol *, const Value &) { return false; }
- static bool putIndexed(Managed *, uint, const Value &) { return false; }
-
+ static bool put(Managed *, Identifier, const Value &, Value *) { return false; }
};
}
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 86aa18c3a4..bb679f7ea0 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -384,8 +384,12 @@ ReturnedValue TypedArray::getIndexed(const Managed *m, uint index, bool *hasProp
return a->d()->type->read(a->d()->buffer->data->data(), byteOffset);
}
-bool TypedArray::putIndexed(Managed *m, uint index, const Value &value)
+bool TypedArray::put(Managed *m, Identifier id, const Value &value, Value *receiver)
{
+ if (!id.isArrayIndex())
+ return Object::put(m, id, value, receiver);
+
+ uint index = id.asArrayIndex();
ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
if (v4->hasException)
return false;
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index 43ff1ec5b7..cbc449471b 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -140,7 +140,7 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object
}
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
- static bool putIndexed(Managed *m, uint index, const Value &value);
+ static bool put(Managed *m, Identifier id, const Value &value, Value *receiver);
};
struct IntrinsicTypedArrayCtor: FunctionObject