diff options
author | Robin Burchell <robin.burchell@crimson.no> | 2017-02-09 19:58:50 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-05-02 14:20:13 +0000 |
commit | a4207b2f958e12b01653d8285d9433a77bce9c52 (patch) | |
tree | bd56186a0a0112586379f92429c99be659d7e711 | |
parent | f665c9b25dde5d34f14a47f2aa52f8141bc03fd1 (diff) |
Add Array Iterator objects from ES6 (22.1.5)
And implement / expose them via:
22.1.3.4 - Array.prototype.entries()
22.1.3.13 - Array.prototype.keys()
22.1.3.29 - Array.prototype.values()
22.1.3.31 - Array.prototype[Symbol.iterator]
Most tests for Array iterators now pass.
At the same time, expose them on TypedArray's prototype:
- 22.2.3.15 %TypedArray%.prototype.keys
- 22.2.3.29 %TypedArray%.prototype.values
- 22.2.3.6 %TypedArray%.prototype.entries
- 22.2.3.31 %TypedArray%.prototype[Symbol.iterator]
For TypedArray, test coverage improves a tiny bit (3 passing tests), but the
vast majority fail as it seems like the object structure for TypedArray is
currently incomplete as far as ES6 expects.
It seems that ES6 expects the object structure to be:
* %TypedArray% (inherits FunctionObject)
(this is the TypedArray intrinsic object, and responsible for initializing
the TypedArray instances)
* All the TypedArray ctors (e.g. UInt8Array)
These inherit %TypedArray%, and make a super call to it to do their work
* %TypedArrayPrototype% (inherits Object)
(this is the initial prototype for %TypedArray%)
* All the ctors have their own separate instance of this
* The instances also make use it
So, for instance, a lot of the tests attempt to access the prototype like:
var proto = Object.getPrototypeOf(Int8Array)
var keys = proto.prototype.keys
As ES6 expects Int8Array.prototype to be %TypedArray% (22.2.5), this expands to:
Object.getPrototypeOf(%TypedArray%)
which it expects to be %TypedArrayPrototype%.
But since we have no intrinsic object, and the ctors inherit
FunctionObject, we instead return the wrong prototype into 'var proto'.
Change-Id: I5e1a95a0420ecb70a0e35a5df3f65557510c5925
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r-- | src/qml/jsruntime/jsruntime.pri | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arrayiterator.cpp | 106 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arrayiterator_p.h | 114 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arrayobject.cpp | 42 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arrayobject_p.h | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 12 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4iterator.cpp | 63 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4iterator_p.h | 76 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4managed.cpp | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4managed_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4typedarray.cpp | 43 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4typedarray_p.h | 3 | ||||
-rw-r--r-- | tests/auto/qml/ecmascripttests/TestExpectations | 53 |
14 files changed, 479 insertions, 49 deletions
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri index c7d80d5a82..aa33565851 100644 --- a/src/qml/jsruntime/jsruntime.pri +++ b/src/qml/jsruntime/jsruntime.pri @@ -14,6 +14,7 @@ SOURCES += \ $$PWD/qv4sparsearray.cpp \ $$PWD/qv4arraydata.cpp \ $$PWD/qv4arrayobject.cpp \ + $$PWD/qv4arrayiterator.cpp \ $$PWD/qv4argumentsobject.cpp \ $$PWD/qv4booleanobject.cpp \ $$PWD/qv4dateobject.cpp \ @@ -21,6 +22,7 @@ SOURCES += \ $$PWD/qv4function.cpp \ $$PWD/qv4functionobject.cpp \ $$PWD/qv4globalobject.cpp \ + $$PWD/qv4iterator.cpp \ $$PWD/qv4jsonobject.cpp \ $$PWD/qv4mathobject.cpp \ $$PWD/qv4memberdata.cpp \ @@ -64,6 +66,7 @@ HEADERS += \ $$PWD/qv4sparsearray_p.h \ $$PWD/qv4arraydata_p.h \ $$PWD/qv4arrayobject_p.h \ + $$PWD/qv4arrayiterator_p.h \ $$PWD/qv4argumentsobject_p.h \ $$PWD/qv4booleanobject_p.h \ $$PWD/qv4dateobject_p.h \ @@ -71,6 +74,7 @@ HEADERS += \ $$PWD/qv4function_p.h \ $$PWD/qv4functionobject_p.h \ $$PWD/qv4globalobject_p.h \ + $$PWD/qv4iterator_p.h \ $$PWD/qv4jsonobject_p.h \ $$PWD/qv4mathobject_p.h \ $$PWD/qv4memberdata_p.h \ diff --git a/src/qml/jsruntime/qv4arrayiterator.cpp b/src/qml/jsruntime/qv4arrayiterator.cpp new file mode 100644 index 0000000000..13c036f9a9 --- /dev/null +++ b/src/qml/jsruntime/qv4arrayiterator.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Crimson AS <info@crimson.no> +** 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 <private/qv4iterator_p.h> +#include <private/qv4arrayiterator_p.h> +#include <private/qv4typedarray_p.h> +#include <private/qv4symbol_p.h> + +using namespace QV4; + +DEFINE_OBJECT_VTABLE(ArrayIteratorObject); + +void ArrayIteratorPrototype::init(ExecutionEngine *e) +{ + defineDefaultProperty(QStringLiteral("next"), method_next, 0); + + Scope scope(e); + ScopedString val(scope, e->newString(QLatin1String("Array Iterator"))); + defineReadonlyConfigurableProperty(e->symbol_toStringTag(), val); +} + +ReturnedValue ArrayIteratorPrototype::method_next(const FunctionObject *b, const Value *that, const Value *, int) +{ + Scope scope(b); + const ArrayIteratorObject *thisObject = that->as<ArrayIteratorObject>(); + if (!thisObject) + return scope.engine->throwTypeError(QLatin1String("Not an Array Iterator instance")); + + ScopedObject a(scope, thisObject->d()->iteratedObject); + if (!a) { + QV4::Value undefined = Primitive::undefinedValue(); + return IteratorPrototype::createIterResultObject(scope.engine, undefined, ScopedValue(scope, Primitive::fromBoolean(true)))->asReturnedValue(); + } + + quint32 index = thisObject->d()->nextIndex; + ArrayIteratorKind itemKind = thisObject->d()->iterationKind; + + Scoped<TypedArray> ta(scope, a->as<TypedArray>()); + quint32 len = a->getLength(); + + if (index >= len) { + thisObject->d()->iteratedObject.set(scope.engine, nullptr); + QV4::Value undefined = Primitive::undefinedValue(); + return IteratorPrototype::createIterResultObject(scope.engine, undefined, ScopedValue(scope, Primitive::fromBoolean(true)))->asReturnedValue(); + } + + thisObject->d()->nextIndex = index + 1; + if (itemKind == KeyIteratorKind) { + return IteratorPrototype::createIterResultObject(scope.engine, Primitive::fromInt32(index), ScopedValue(scope, Primitive::fromBoolean(false)))->asReturnedValue(); + } + + ReturnedValue elementValue = a->getIndexed(index); + CHECK_EXCEPTION(); + + if (itemKind == ValueIteratorKind) { + return IteratorPrototype::createIterResultObject(scope.engine, Value::fromReturnedValue(elementValue), ScopedValue(scope, Primitive::fromBoolean(false)))->asReturnedValue(); + } else { + Q_ASSERT(itemKind == KeyValueIteratorKind); + + ScopedArrayObject resultArray(scope, scope.engine->newArrayObject()); + resultArray->arrayReserve(2); + resultArray->arrayPut(0, Primitive::fromInt32(index)); + resultArray->arrayPut(1, Value::fromReturnedValue(elementValue)); + resultArray->setArrayLengthUnchecked(2); + + return IteratorPrototype::createIterResultObject(scope.engine, resultArray, ScopedValue(scope, Primitive::fromBoolean(false)))->asReturnedValue(); + } +} + diff --git a/src/qml/jsruntime/qv4arrayiterator_p.h b/src/qml/jsruntime/qv4arrayiterator_p.h new file mode 100644 index 0000000000..2951c9a763 --- /dev/null +++ b/src/qml/jsruntime/qv4arrayiterator_p.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Crimson AS <info@crimson.no> +** 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 QV4ARRAYITERATOR_P_H +#define QV4ARRAYITERATOR_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 "qv4arraydata_p.h" + +QT_BEGIN_NAMESPACE + + +namespace QV4 { + +// ### spec says that this is a string, but I don't see it exposed anywhere, so +// does that matter? +// ### maybe we should share this with other iterator types in the future. +enum ArrayIteratorKind { + KeyIteratorKind, + ValueIteratorKind, + KeyValueIteratorKind +}; + +namespace Heap { + +#define ArrayIteratorObjectMembers(class, Member) \ + Member(class, Pointer, Object *, iteratedObject) \ + Member(class, NoMark, ArrayIteratorKind, iterationKind) \ + Member(class, NoMark, quint32, nextIndex) + +DECLARE_HEAP_OBJECT(ArrayIteratorObject, Object) { + DECLARE_MARKOBJECTS(ArrayIteratorObject); + void init(Object *obj, QV4::ExecutionEngine *engine) + { + Object::init(); + this->iteratedObject.set(engine, obj); + this->nextIndex = 0; + } +}; + +} + +struct ArrayIteratorPrototype : Object +{ + V4_PROTOTYPE(iteratorPrototype) + void init(ExecutionEngine *engine); + + static ReturnedValue method_next(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc); +}; + +struct ArrayIteratorObject : Object +{ + V4_OBJECT2(ArrayIteratorObject, Object) + Q_MANAGED_TYPE(ArrayIteratorObject) + V4_PROTOTYPE(arrayIteratorPrototype) + + void init(ExecutionEngine *engine); +}; + + +} + +QT_END_NAMESPACE + +#endif // QV4ARRAYITERATOR_P_H + diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 2bc5ec1de1..4dfe177c12 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -38,12 +38,14 @@ ****************************************************************************/ #include "qv4arrayobject_p.h" +#include "qv4arrayiterator_p.h" #include "qv4sparsearray_p.h" #include "qv4objectproto_p.h" #include "qv4jscall_p.h" #include "qv4argumentsobject_p.h" #include "qv4runtime_p.h" #include "qv4string_p.h" +#include "qv4symbol_p.h" #include <QtCore/qscopedvaluerollback.h> using namespace QV4; @@ -96,6 +98,7 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(engine->id_toString(), method_toString, 0); defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0); defineDefaultProperty(QStringLiteral("concat"), method_concat, 1); + defineDefaultProperty(QStringLiteral("entries"), method_entries, 0); defineDefaultProperty(QStringLiteral("find"), method_find, 1); defineDefaultProperty(QStringLiteral("findIndex"), method_findIndex, 1); defineDefaultProperty(QStringLiteral("join"), method_join, 1); @@ -108,6 +111,7 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("splice"), method_splice, 2); defineDefaultProperty(QStringLiteral("unshift"), method_unshift, 1); defineDefaultProperty(QStringLiteral("indexOf"), method_indexOf, 1); + defineDefaultProperty(QStringLiteral("keys"), method_keys, 0); defineDefaultProperty(QStringLiteral("lastIndexOf"), method_lastIndexOf, 1); defineDefaultProperty(QStringLiteral("every"), method_every, 1); defineDefaultProperty(QStringLiteral("some"), method_some, 1); @@ -116,6 +120,8 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("filter"), method_filter, 1); defineDefaultProperty(QStringLiteral("reduce"), method_reduce, 1); defineDefaultProperty(QStringLiteral("reduceRight"), method_reduceRight, 1); + defineDefaultProperty(QStringLiteral("values"), method_values, 0); + defineDefaultProperty(engine->symbol_iterator(), method_values, 0); } ReturnedValue ArrayPrototype::method_isArray(const FunctionObject *, const Value *, const Value *argv, int argc) @@ -183,6 +189,18 @@ ReturnedValue ArrayPrototype::method_concat(const FunctionObject *b, const Value return result.asReturnedValue(); } +ReturnedValue ArrayPrototype::method_entries(const FunctionObject *b, const Value *thisObject, const Value *, int) +{ + Scope scope(b); + ScopedObject O(scope, thisObject->toObject(scope.engine)); + if (!O) + RETURN_UNDEFINED(); + + Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O)); + ao->d()->iterationKind = ArrayIteratorKind::KeyValueIteratorKind; + return ao->asReturnedValue(); +} + ReturnedValue ArrayPrototype::method_find(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) { Scope scope(b); @@ -743,6 +761,18 @@ ReturnedValue ArrayPrototype::method_indexOf(const FunctionObject *b, const Valu return Encode(-1); } +ReturnedValue ArrayPrototype::method_keys(const FunctionObject *f, const Value *thisObject, const Value *, int) +{ + Scope scope(f); + ScopedObject O(scope, thisObject->toObject(scope.engine)); + if (!O) + RETURN_UNDEFINED(); + + Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O)); + ao->d()->iterationKind = ArrayIteratorKind::KeyIteratorKind; + return ao->asReturnedValue(); +} + ReturnedValue ArrayPrototype::method_lastIndexOf(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) { Scope scope(b); @@ -1058,3 +1088,15 @@ ReturnedValue ArrayPrototype::method_reduceRight(const FunctionObject *b, const return acc->asReturnedValue(); } +ReturnedValue ArrayPrototype::method_values(const FunctionObject *b, const Value *thisObject, const Value *, int) +{ + Scope scope(b); + ScopedObject O(scope, thisObject->toObject(scope.engine)); + if (!O) + RETURN_UNDEFINED(); + + Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O)); + ao->d()->iterationKind = ArrayIteratorKind::ValueIteratorKind; + return ao->asReturnedValue(); +} + diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h index 3825a600a2..9416176863 100644 --- a/src/qml/jsruntime/qv4arrayobject_p.h +++ b/src/qml/jsruntime/qv4arrayobject_p.h @@ -82,6 +82,7 @@ struct ArrayPrototype: ArrayObject static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_toLocaleString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_concat(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); + static ReturnedValue method_entries(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_find(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_findIndex(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_join(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); @@ -94,6 +95,7 @@ struct ArrayPrototype: ArrayObject static ReturnedValue method_splice(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_unshift(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_indexOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); + static ReturnedValue method_keys(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_lastIndexOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_every(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_some(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); @@ -102,6 +104,7 @@ struct ArrayPrototype: ArrayObject static ReturnedValue method_filter(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_reduce(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_reduceRight(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); + static ReturnedValue method_values(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); }; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 22dc984b4a..0bd2894fe3 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -42,6 +42,7 @@ #include <qv4object_p.h> #include <qv4objectproto_p.h> #include <qv4objectiterator_p.h> +#include <qv4arrayiterator_p.h> #include <qv4arrayobject_p.h> #include <qv4booleanobject_p.h> #include <qv4globalobject_p.h> @@ -64,6 +65,7 @@ #include "qv4debugging_p.h" #include "qv4profiling_p.h" #include "qv4executableallocator_p.h" +#include "qv4iterator_p.h" #if QT_CONFIG(qml_sequence_object) #include "qv4sequenceobject_p.h" @@ -402,6 +404,8 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) jsObjects[SyntaxError_Ctor] = memoryManager->allocate<SyntaxErrorCtor>(global); jsObjects[TypeError_Ctor] = memoryManager->allocate<TypeErrorCtor>(global); jsObjects[URIError_Ctor] = memoryManager->allocate<URIErrorCtor>(global); + jsObjects[IteratorProto] = memoryManager->allocate<IteratorPrototype>(); + jsObjects[ArrayIteratorProto] = memoryManager->allocObject<ArrayIteratorPrototype>(newInternalClass(ArrayIteratorPrototype::staticVTable(), iteratorPrototype())); static_cast<ObjectPrototype *>(objectPrototype())->init(this, objectCtor()); static_cast<StringPrototype *>(stringPrototype())->init(this, stringCtor()); @@ -420,6 +424,9 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype())->init(this, syntaxErrorCtor()); static_cast<TypeErrorPrototype *>(typeErrorPrototype())->init(this, typeErrorCtor()); static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor()); + + static_cast<IteratorPrototype *>(iteratorPrototype())->init(this); + static_cast<ArrayIteratorPrototype *>(arrayIteratorPrototype())->init(this); static_cast<VariantPrototype *>(variantPrototype())->init(); #if QT_CONFIG(qml_sequence_object) @@ -779,6 +786,11 @@ Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o) return obj->d(); } +Heap::Object *ExecutionEngine::newArrayIteratorObject(Object *o) +{ + return memoryManager->allocate<ArrayIteratorObject>(o->d(), this); +} + Heap::QmlContext *ExecutionEngine::qmlContext() const { if (!currentStackFrame) diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index eaf1fae1af..517d9f88a8 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -185,6 +185,8 @@ public: DataViewProto, ValueTypeProto, SignalHandlerProto, + IteratorProto, + ArrayIteratorProto, Object_Ctor, String_Ctor, @@ -262,6 +264,8 @@ public: Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); } Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); } + Object *iteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + IteratorProto); } + Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); } EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); } FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); } @@ -476,6 +480,7 @@ public: Heap::Object *newVariantObject(const QVariant &v); Heap::Object *newForEachIteratorObject(Object *o); + Heap::Object *newArrayIteratorObject(Object *o); Heap::QmlContext *qmlContext() const; QObject *qmlScopeObject() const; diff --git a/src/qml/jsruntime/qv4iterator.cpp b/src/qml/jsruntime/qv4iterator.cpp new file mode 100644 index 0000000000..a97d2c60f2 --- /dev/null +++ b/src/qml/jsruntime/qv4iterator.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** 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 <qv4iterator_p.h> +#include <qv4symbol_p.h> +#include <qv4engine_p.h> + +using namespace QV4; + +void IteratorPrototype::init(ExecutionEngine *engine) +{ + defineDefaultProperty(engine->symbol_iterator(), method_iterator, 0); +} + +ReturnedValue IteratorPrototype::method_iterator(const FunctionObject *, const Value *thisObject, const Value *, int) +{ + return thisObject->asReturnedValue(); +} + + +Heap::Object *IteratorPrototype::createIterResultObject(ExecutionEngine *engine, const Value &value, const Value &done) +{ + Scope scope(engine); + ScopedObject obj(scope, engine->newObject()); + obj->set(ScopedString(scope, engine->newString(QStringLiteral("value"))), value, Object::DoNotThrow); + obj->set(ScopedString(scope, engine->newString(QStringLiteral("done"))), done, Object::DoNotThrow); + return obj->d(); +} diff --git a/src/qml/jsruntime/qv4iterator_p.h b/src/qml/jsruntime/qv4iterator_p.h new file mode 100644 index 0000000000..16027e64a0 --- /dev/null +++ b/src/qml/jsruntime/qv4iterator_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 QV4ITERATOR_P_H +#define QV4ITERATOR_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 "qv4arraydata_p.h" + +QT_BEGIN_NAMESPACE + + +namespace QV4 { + +struct IteratorPrototype : Object +{ + void init(ExecutionEngine *engine); + + static ReturnedValue method_iterator(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc); + + static Heap::Object *createIterResultObject(ExecutionEngine *engine, const Value &value, const Value &done); +}; + +} + +QT_END_NAMESPACE + +#endif // QV4ARRAYITERATOR_P_H + diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp index a2e9deb854..d5ed0c0c32 100644 --- a/src/qml/jsruntime/qv4managed.cpp +++ b/src/qml/jsruntime/qv4managed.cpp @@ -122,6 +122,9 @@ QString Managed::className() const case Type_ExecutionContext: s = "__ExecutionContext"; break; + case Type_ArrayIteratorObject: + s = "Array Iterator"; + break; case Type_ForeachIteratorObject: s = "__ForeachIterator"; break; diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 5a032ba401..454f4912c0 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -198,6 +198,7 @@ public: Type_ExecutionContext, Type_InternalClass, + Type_ArrayIteratorObject, Type_ForeachIteratorObject, Type_RegExp, diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index ea931abd1c..81e4deb463 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -36,10 +36,13 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #include "qv4typedarray_p.h" +#include "qv4arrayiterator_p.h" #include "qv4arraybuffer_p.h" #include "qv4string_p.h" #include "qv4jscall_p.h" +#include "qv4symbol_p.h" #include <cmath> @@ -405,8 +408,12 @@ void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor) defineAccessorProperty(QStringLiteral("length"), method_get_length, nullptr); defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement)); + defineDefaultProperty(QStringLiteral("entries"), method_entries, 0); + defineDefaultProperty(QStringLiteral("keys"), method_keys, 0); + defineDefaultProperty(QStringLiteral("values"), method_values, 0); defineDefaultProperty(QStringLiteral("set"), method_set, 1); defineDefaultProperty(QStringLiteral("subarray"), method_subarray, 0); + defineDefaultProperty(engine->symbol_iterator(), method_values, 0); } ReturnedValue TypedArrayPrototype::method_get_buffer(const FunctionObject *b, const Value *thisObject, const Value *, int) @@ -449,6 +456,42 @@ ReturnedValue TypedArrayPrototype::method_get_length(const FunctionObject *b, co return Encode(v->d()->byteLength/v->d()->type->bytesPerElement); } +ReturnedValue TypedArrayPrototype::method_entries(const FunctionObject *b, const Value *thisObject, const Value *, int) +{ + Scope scope(b); + Scoped<TypedArray> O(scope, thisObject); + if (!O) + THROW_TYPE_ERROR(); + + Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O)); + ao->d()->iterationKind = ArrayIteratorKind::KeyValueIteratorKind; + return ao->asReturnedValue(); +} + +ReturnedValue TypedArrayPrototype::method_keys(const FunctionObject *b, const Value *thisObject, const Value *, int) +{ + Scope scope(b); + Scoped<TypedArray> O(scope, thisObject); + if (!O) + THROW_TYPE_ERROR(); + + Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O)); + ao->d()->iterationKind = ArrayIteratorKind::KeyIteratorKind; + return ao->asReturnedValue(); +} + +ReturnedValue TypedArrayPrototype::method_values(const FunctionObject *b, const Value *thisObject, const Value *, int) +{ + Scope scope(b); + Scoped<TypedArray> O(scope, thisObject); + if (!O) + THROW_TYPE_ERROR(); + + Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O)); + ao->d()->iterationKind = ArrayIteratorKind::ValueIteratorKind; + return ao->asReturnedValue(); +} + ReturnedValue TypedArrayPrototype::method_set(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) { Scope scope(b); diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h index 129c662c97..74561f9c35 100644 --- a/src/qml/jsruntime/qv4typedarray_p.h +++ b/src/qml/jsruntime/qv4typedarray_p.h @@ -158,6 +158,9 @@ struct TypedArrayPrototype : Object static ReturnedValue method_get_byteOffset(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_get_length(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); + static ReturnedValue method_entries(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); + static ReturnedValue method_keys(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); + static ReturnedValue method_values(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_set(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_subarray(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); }; diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations index 97194ede51..a5f6eafaa7 100644 --- a/tests/auto/qml/ecmascripttests/TestExpectations +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -126,13 +126,6 @@ built-ins/Array/prototype/copyWithin/return-abrupt-from-target.js fails built-ins/Array/prototype/copyWithin/return-abrupt-from-this-length.js fails built-ins/Array/prototype/copyWithin/return-this.js fails built-ins/Array/prototype/copyWithin/undefined-end.js fails -built-ins/Array/prototype/entries/iteration-mutable.js fails -built-ins/Array/prototype/entries/iteration.js fails -built-ins/Array/prototype/entries/length.js fails -built-ins/Array/prototype/entries/name.js fails -built-ins/Array/prototype/entries/prop-desc.js fails -built-ins/Array/prototype/entries/returns-iterator-from-object.js fails -built-ins/Array/prototype/entries/returns-iterator.js fails built-ins/Array/prototype/every/15.4.4.16-3-29.js fails built-ins/Array/prototype/fill/coerced-indexes.js fails built-ins/Array/prototype/fill/fill-values-custom-start-and-end.js fails @@ -179,13 +172,6 @@ built-ins/Array/prototype/includes/values-are-not-cached.js fails built-ins/Array/prototype/indexOf/15.4.4.14-3-28.js fails built-ins/Array/prototype/indexOf/15.4.4.14-3-29.js fails built-ins/Array/prototype/join/S15.4.4.5_A4_T3.js fails -built-ins/Array/prototype/keys/iteration-mutable.js fails -built-ins/Array/prototype/keys/iteration.js fails -built-ins/Array/prototype/keys/length.js fails -built-ins/Array/prototype/keys/name.js fails -built-ins/Array/prototype/keys/prop-desc.js fails -built-ins/Array/prototype/keys/returns-iterator-from-object.js fails -built-ins/Array/prototype/keys/returns-iterator.js fails built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-28.js fails built-ins/Array/prototype/map/create-ctor-non-object.js fails built-ins/Array/prototype/map/create-proto-from-ctor-realm-array.js fails @@ -244,13 +230,6 @@ built-ins/Array/prototype/toLocaleString/primitive_this_value_getter.js strictFa built-ins/Array/prototype/unshift/clamps-to-integer-limit.js fails built-ins/Array/prototype/unshift/length-near-integer-limit.js fails built-ins/Array/prototype/unshift/throws-if-integer-limit-exceeded.js fails -built-ins/Array/prototype/values/iteration-mutable.js fails -built-ins/Array/prototype/values/iteration.js fails -built-ins/Array/prototype/values/length.js fails -built-ins/Array/prototype/values/name.js fails -built-ins/Array/prototype/values/prop-desc.js fails -built-ins/Array/prototype/values/returns-iterator-from-object.js fails -built-ins/Array/prototype/values/returns-iterator.js fails built-ins/ArrayBuffer/Symbol.species/length.js fails built-ins/ArrayBuffer/Symbol.species/return-value.js fails built-ins/ArrayBuffer/Symbol.species/symbol-species-name.js fails @@ -285,18 +264,6 @@ built-ins/ArrayBuffer/prototype/slice/start-exceeds-length.js fails built-ins/ArrayBuffer/prototype/slice/tointeger-conversion-end.js fails built-ins/ArrayBuffer/prototype/slice/tointeger-conversion-start.js fails built-ins/ArrayBuffer/undefined-newtarget-throws.js fails -built-ins/ArrayIteratorPrototype/Symbol.toStringTag/property-descriptor.js fails -built-ins/ArrayIteratorPrototype/Symbol.toStringTag/value-direct.js fails -built-ins/ArrayIteratorPrototype/Symbol.toStringTag/value-from-to-string.js fails -built-ins/ArrayIteratorPrototype/next/Float32Array.js fails -built-ins/ArrayIteratorPrototype/next/Float64Array.js fails -built-ins/ArrayIteratorPrototype/next/Int16Array.js fails -built-ins/ArrayIteratorPrototype/next/Int32Array.js fails -built-ins/ArrayIteratorPrototype/next/Int8Array.js fails -built-ins/ArrayIteratorPrototype/next/Uint16Array.js fails -built-ins/ArrayIteratorPrototype/next/Uint32Array.js fails -built-ins/ArrayIteratorPrototype/next/Uint8Array.js fails -built-ins/ArrayIteratorPrototype/next/Uint8ClampedArray.js fails built-ins/ArrayIteratorPrototype/next/args-mapped-expansion-after-exhaustion.js sloppyFails built-ins/ArrayIteratorPrototype/next/args-mapped-expansion-before-exhaustion.js sloppyFails built-ins/ArrayIteratorPrototype/next/args-mapped-iteration.js sloppyFails @@ -306,12 +273,6 @@ built-ins/ArrayIteratorPrototype/next/args-unmapped-expansion-before-exhaustion. built-ins/ArrayIteratorPrototype/next/args-unmapped-iteration.js sloppyFails built-ins/ArrayIteratorPrototype/next/args-unmapped-truncation-before-exhaustion.js sloppyFails built-ins/ArrayIteratorPrototype/next/detach-typedarray-in-progress.js fails -built-ins/ArrayIteratorPrototype/next/iteration-mutable.js fails -built-ins/ArrayIteratorPrototype/next/iteration.js fails -built-ins/ArrayIteratorPrototype/next/length.js fails -built-ins/ArrayIteratorPrototype/next/name.js fails -built-ins/ArrayIteratorPrototype/next/non-own-slots.js fails -built-ins/ArrayIteratorPrototype/next/property-descriptor.js fails built-ins/AsyncFunction/AsyncFunction-construct.js fails built-ins/AsyncFunction/AsyncFunction-is-extensible.js fails built-ins/AsyncFunction/AsyncFunction-is-subclass.js fails @@ -768,10 +729,6 @@ built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-outer-try built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-outer-try-before-nested.js fails built-ins/GeneratorPrototype/throw/try-finally-within-finally.js fails built-ins/GeneratorPrototype/throw/try-finally-within-try.js fails -built-ins/IteratorPrototype/Symbol.iterator/length.js fails -built-ins/IteratorPrototype/Symbol.iterator/name.js fails -built-ins/IteratorPrototype/Symbol.iterator/prop-desc.js fails -built-ins/IteratorPrototype/Symbol.iterator/return-val.js fails built-ins/JSON/Symbol.toStringTag.js fails built-ins/JSON/parse/revived-proxy-revoked.js fails built-ins/JSON/parse/revived-proxy.js fails @@ -2425,11 +2382,9 @@ built-ins/TypedArray/prototype/copyWithin/undefined-end.js fails built-ins/TypedArray/prototype/entries/detached-buffer.js fails built-ins/TypedArray/prototype/entries/invoked-as-func.js fails built-ins/TypedArray/prototype/entries/invoked-as-method.js fails -built-ins/TypedArray/prototype/entries/iter-prototype.js fails built-ins/TypedArray/prototype/entries/length.js fails built-ins/TypedArray/prototype/entries/name.js fails built-ins/TypedArray/prototype/entries/prop-desc.js fails -built-ins/TypedArray/prototype/entries/return-itor.js fails built-ins/TypedArray/prototype/entries/this-is-not-object.js fails built-ins/TypedArray/prototype/entries/this-is-not-typedarray-instance.js fails built-ins/TypedArray/prototype/every/callbackfn-arguments-with-thisarg.js fails @@ -2620,11 +2575,9 @@ built-ins/TypedArray/prototype/join/this-is-not-typedarray-instance.js fails built-ins/TypedArray/prototype/keys/detached-buffer.js fails built-ins/TypedArray/prototype/keys/invoked-as-func.js fails built-ins/TypedArray/prototype/keys/invoked-as-method.js fails -built-ins/TypedArray/prototype/keys/iter-prototype.js fails built-ins/TypedArray/prototype/keys/length.js fails built-ins/TypedArray/prototype/keys/name.js fails built-ins/TypedArray/prototype/keys/prop-desc.js fails -built-ins/TypedArray/prototype/keys/return-itor.js fails built-ins/TypedArray/prototype/keys/this-is-not-object.js fails built-ins/TypedArray/prototype/keys/this-is-not-typedarray-instance.js fails built-ins/TypedArray/prototype/lastIndexOf/detached-buffer.js fails @@ -2863,11 +2816,9 @@ built-ins/TypedArray/prototype/toString/detached-buffer.js fails built-ins/TypedArray/prototype/values/detached-buffer.js fails built-ins/TypedArray/prototype/values/invoked-as-func.js fails built-ins/TypedArray/prototype/values/invoked-as-method.js fails -built-ins/TypedArray/prototype/values/iter-prototype.js fails built-ins/TypedArray/prototype/values/length.js fails built-ins/TypedArray/prototype/values/name.js fails built-ins/TypedArray/prototype/values/prop-desc.js fails -built-ins/TypedArray/prototype/values/return-itor.js fails built-ins/TypedArray/prototype/values/this-is-not-object.js fails built-ins/TypedArray/prototype/values/this-is-not-typedarray-instance.js fails built-ins/TypedArrays/Float32Array/prototype/proto.js fails @@ -3036,12 +2987,16 @@ built-ins/TypedArrays/of/new-instance-empty.js fails built-ins/TypedArrays/of/new-instance-from-zero.js fails built-ins/TypedArrays/of/new-instance-using-custom-ctor.js fails built-ins/TypedArrays/of/new-instance.js fails +built-ins/TypedArrays/prototype/Symbol.iterator.js fails built-ins/TypedArrays/prototype/buffer/inherited.js fails built-ins/TypedArrays/prototype/byteLength/inherited.js fails built-ins/TypedArrays/prototype/byteOffset/inherited.js fails +built-ins/TypedArrays/prototype/entries/inherited.js fails +built-ins/TypedArrays/prototype/keys/inherited.js fails built-ins/TypedArrays/prototype/length/inherited.js fails built-ins/TypedArrays/prototype/set/inherited.js fails built-ins/TypedArrays/prototype/subarray/inherited.js fails +built-ins/TypedArrays/prototype/values/inherited.js fails built-ins/WeakMap/constructor.js fails built-ins/WeakMap/empty-iterable.js fails built-ins/WeakMap/get-set-method-failure.js fails |