aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChris Adams <christopher.adams@nokia.com>2011-11-21 10:02:35 +1000
committerQt by Nokia <qt-info@nokia.com>2011-11-29 04:34:11 +0100
commitc648598a8ba8bf72b5d556211df877578d5f5b64 (patch)
tree47cfe3fe9ac48fdd609ac51e5351de925da7dec2 /src
parent5587885a71b962eb9443c1f83e3e477490bd691d (diff)
Add indexed deleter to sequence wrapper, implement length setter
Previously, elements could not be deleted from sequences directly without reassignment. This commit adds an indexed deleter which allows elements to be deleted by specifying an index. A deleted element will be replaced with a default-constructed element in the sequence (slight departure from ECMA262r3 which specifies that it should be replaced with Undefined). This commit also implements the length property setter according to the requirements on Array [[Put]] by ECMA262r3 which allows removal of elements from a sequence (required for proper behaviour of Array.prototype methods such as splice() and pop()). Task-number: QTBUG-22808 Change-Id: I62511b3edc2ec35f92d2a2bd719278e129c98547 Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/declarative/qml/v8/qv8sequencewrapper.cpp21
-rw-r--r--src/declarative/qml/v8/qv8sequencewrapper_p.h2
-rw-r--r--src/declarative/qml/v8/qv8sequencewrapper_p_p.h67
3 files changed, 87 insertions, 3 deletions
diff --git a/src/declarative/qml/v8/qv8sequencewrapper.cpp b/src/declarative/qml/v8/qv8sequencewrapper.cpp
index f63b5da4ea..267e8ec4e6 100644
--- a/src/declarative/qml/v8/qv8sequencewrapper.cpp
+++ b/src/declarative/qml/v8/qv8sequencewrapper.cpp
@@ -66,10 +66,10 @@ void QV8SequenceWrapper::init(QV8Engine *engine)
m_valueOf = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(ValueOf)->GetFunction());
v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter);
- ft->InstanceTemplate()->SetIndexedPropertyHandler(IndexedGetter, IndexedSetter, 0, 0, IndexedEnumerator);
- ft->InstanceTemplate()->SetAccessor(v8::String::New("length"), LengthGetter, 0,
+ ft->InstanceTemplate()->SetIndexedPropertyHandler(IndexedGetter, IndexedSetter, 0, IndexedDeleter, IndexedEnumerator);
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("length"), LengthGetter, LengthSetter,
v8::Handle<v8::Value>(), v8::DEFAULT,
- v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete | v8::DontEnum));
+ v8::PropertyAttribute(v8::DontDelete | v8::DontEnum));
ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0,
m_toString, v8::DEFAULT,
v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete | v8::DontEnum));
@@ -184,6 +184,13 @@ v8::Handle<v8::Value> QV8SequenceWrapper::IndexedGetter(quint32 index, const v8:
return sr->indexedGetter(index);
}
+v8::Handle<v8::Boolean> QV8SequenceWrapper::IndexedDeleter(quint32 index, const v8::AccessorInfo &info)
+{
+ QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This());
+ Q_ASSERT(sr);
+ return sr->indexedDeleter(index);
+}
+
v8::Handle<v8::Array> QV8SequenceWrapper::IndexedEnumerator(const v8::AccessorInfo &info)
{
QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This());
@@ -199,6 +206,14 @@ v8::Handle<v8::Value> QV8SequenceWrapper::LengthGetter(v8::Local<v8::String> pro
return v8::Integer::NewFromUnsigned(sr->lengthGetter());
}
+void QV8SequenceWrapper::LengthSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ Q_UNUSED(property);
+ QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This());
+ Q_ASSERT(sr);
+ sr->lengthSetter(value);
+}
+
v8::Handle<v8::Value> QV8SequenceWrapper::ToStringGetter(v8::Local<v8::String> property, const v8::AccessorInfo &info)
{
Q_UNUSED(property);
diff --git a/src/declarative/qml/v8/qv8sequencewrapper_p.h b/src/declarative/qml/v8/qv8sequencewrapper_p.h
index da0f7eacca..0ddeed9eda 100644
--- a/src/declarative/qml/v8/qv8sequencewrapper_p.h
+++ b/src/declarative/qml/v8/qv8sequencewrapper_p.h
@@ -88,8 +88,10 @@ private:
static v8::Handle<v8::Value> IndexedGetter(quint32 index, const v8::AccessorInfo &info);
static v8::Handle<v8::Value> IndexedSetter(quint32 index, v8::Local<v8::Value> value, const v8::AccessorInfo &info);
+ static v8::Handle<v8::Boolean> IndexedDeleter(quint32 index, const v8::AccessorInfo &info);
static v8::Handle<v8::Array> IndexedEnumerator(const v8::AccessorInfo &info);
static v8::Handle<v8::Value> LengthGetter(v8::Local<v8::String> property, const v8::AccessorInfo &info);
+ static void LengthSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo &info);
static v8::Handle<v8::Value> ToStringGetter(v8::Local<v8::String> property, const v8::AccessorInfo &info);
static v8::Handle<v8::Value> ToString(const v8::Arguments &args);
static v8::Handle<v8::Value> ValueOfGetter(v8::Local<v8::String> property, const v8::AccessorInfo &info);
diff --git a/src/declarative/qml/v8/qv8sequencewrapper_p_p.h b/src/declarative/qml/v8/qv8sequencewrapper_p_p.h
index eea595ed6b..a947d52013 100644
--- a/src/declarative/qml/v8/qv8sequencewrapper_p_p.h
+++ b/src/declarative/qml/v8/qv8sequencewrapper_p_p.h
@@ -82,8 +82,10 @@ public:
virtual bool isEqual(const QV8SequenceResource *v) = 0;
virtual quint32 lengthGetter() = 0;
+ virtual void lengthSetter(v8::Handle<v8::Value> value) = 0;
virtual v8::Handle<v8::Value> indexedSetter(quint32 index, v8::Handle<v8::Value> value) = 0;
virtual v8::Handle<v8::Value> indexedGetter(quint32 index) = 0;
+ virtual v8::Handle<v8::Boolean> indexedDeleter(quint32 index) = 0;
virtual v8::Handle<v8::Array> indexedEnumerator() = 0;
virtual v8::Handle<v8::Value> toString() = 0;
@@ -286,6 +288,48 @@ static QString convertUrlToString(QV8Engine *, const QUrl &v)
} \
return c.count(); \
} \
+ void lengthSetter(v8::Handle<v8::Value> value) \
+ { \
+ /* Get the new required length */ \
+ if (value.IsEmpty() || !value->IsUint32()) \
+ return; \
+ quint32 newLength = value->Uint32Value(); \
+ /* Read the sequence from the QObject property if we're a reference */ \
+ if (objectType == QV8SequenceResource::Reference) { \
+ if (!object) \
+ return; \
+ void *a[] = { &c, 0 }; \
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, propertyIndex, a); \
+ } \
+ /* Determine whether we need to modify the sequence */ \
+ quint32 count = c.count(); \
+ if (newLength == count) { \
+ return; \
+ } else if (newLength > count) { \
+ /* according to ECMA262r3 we need to insert */ \
+ /* undefined values increasing length to newLength. */ \
+ /* We cannot, so we insert default-values instead. */ \
+ while (newLength > count++) { \
+ c.append(DefaultValue); \
+ } \
+ } else { \
+ /* according to ECMA262r3 we need to remove */ \
+ /* elements until the sequence is the required length. */ \
+ while (newLength < count) { \
+ count--; \
+ c.removeAt(count); \
+ } \
+ } \
+ /* write back if required. */ \
+ if (objectType == QV8SequenceResource::Reference) { \
+ /* write back. already checked that object is non-null, so skip that check here. */ \
+ int status = -1; \
+ QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::DontRemoveBinding; \
+ void *a[] = { &c, 0, &status, &flags }; \
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, propertyIndex, a); \
+ } \
+ return; \
+ } \
v8::Handle<v8::Value> indexedSetter(quint32 index, v8::Handle<v8::Value> value) \
{ \
if (objectType == QV8SequenceResource::Reference) { \
@@ -331,6 +375,29 @@ static QString convertUrlToString(QV8Engine *, const QUrl &v)
return ConversionToV8fn(engine, c.at(index)); \
return v8::Undefined(); \
} \
+ v8::Handle<v8::Boolean> indexedDeleter(quint32 index) \
+ { \
+ if (objectType == QV8SequenceResource::Reference) { \
+ if (!object) \
+ return v8::Boolean::New(false); \
+ void *a[] = { &c, 0 }; \
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, propertyIndex, a); \
+ } \
+ if (index < c.count()) { \
+ /* according to ECMA262r3 it should be Undefined, */ \
+ /* but we cannot, so we insert a default-value instead. */ \
+ c.replace(index, DefaultValue); \
+ if (objectType == QV8SequenceResource::Reference) { \
+ /* write back. already checked that object is non-null, so skip that check here. */ \
+ int status = -1; \
+ QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::DontRemoveBinding; \
+ void *a[] = { &c, 0, &status, &flags }; \
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, propertyIndex, a); \
+ } \
+ return v8::Boolean::New(true); \
+ } \
+ return v8::Boolean::New(false); \
+ } \
v8::Handle<v8::Array> indexedEnumerator() \
{ \
if (objectType == QV8SequenceResource::Reference) { \