diff options
author | Lars Knoll <[email protected]> | 2018-04-26 13:12:38 +0200 |
---|---|---|
committer | Lars Knoll <[email protected]> | 2018-05-02 14:20:29 +0000 |
commit | 8761cbd4f7aada5a976831ff404b004f537a660b (patch) | |
tree | 5b5b258178c99e0d77cc84a2e8c31df41f98415b | |
parent | 7d46d7251032ea31f7e7dcef4855a0e5d669fed5 (diff) |
Implement StringIterator
Add support for String.prototype[Symbol.iterator] and the
StringIterator object.
Change-Id: I72c4f988e4f363be1af51f9cc5f8e83af43cd151
Reviewed-by: Simon Hausmann <[email protected]>
-rw-r--r-- | src/qml/jsruntime/jsruntime.pri | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 2 | ||||
-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/qv4stringiterator.cpp | 95 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4stringiterator_p.h | 103 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4stringobject.cpp | 15 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4stringobject_p.h | 1 | ||||
-rw-r--r-- | tests/auto/qml/ecmascripttests/TestExpectations | 11 |
10 files changed, 226 insertions, 11 deletions
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri index aa33565851..d06e505c81 100644 --- a/src/qml/jsruntime/jsruntime.pri +++ b/src/qml/jsruntime/jsruntime.pri @@ -31,6 +31,7 @@ SOURCES += \ $$PWD/qv4objectproto.cpp \ $$PWD/qv4qmlcontext.cpp \ $$PWD/qv4regexpobject.cpp \ + $$PWD/qv4stringiterator.cpp \ $$PWD/qv4stringobject.cpp \ $$PWD/qv4variantobject.cpp \ $$PWD/qv4objectiterator.cpp \ @@ -84,6 +85,7 @@ HEADERS += \ $$PWD/qv4qmlcontext_p.h \ $$PWD/qv4regexpobject_p.h \ $$PWD/qv4runtimecodegen_p.h \ + $$PWD/qv4stringiterator_p.h \ $$PWD/qv4stringobject_p.h \ $$PWD/qv4variantobject_p.h \ $$PWD/qv4property_p.h \ diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index c8fb568ad1..1c3c3e7ff8 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -66,6 +66,7 @@ #include "qv4profiling_p.h" #include "qv4executableallocator_p.h" #include "qv4iterator_p.h" +#include "qv4stringiterator_p.h" #if QT_CONFIG(qml_sequence_object) #include "qv4sequenceobject_p.h" @@ -407,6 +408,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) jsObjects[URIError_Ctor] = memoryManager->allocate<URIErrorCtor>(global); jsObjects[IteratorProto] = memoryManager->allocate<IteratorPrototype>(); jsObjects[ArrayIteratorProto] = memoryManager->allocObject<ArrayIteratorPrototype>(newInternalClass(ArrayIteratorPrototype::staticVTable(), iteratorPrototype())); + jsObjects[StringIteratorProto] = memoryManager->allocObject<StringIteratorPrototype>(newInternalClass(StringIteratorPrototype::staticVTable(), iteratorPrototype())); static_cast<ObjectPrototype *>(objectPrototype())->init(this, objectCtor()); static_cast<StringPrototype *>(stringPrototype())->init(this, stringCtor()); @@ -428,6 +430,8 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) static_cast<IteratorPrototype *>(iteratorPrototype())->init(this); static_cast<ArrayIteratorPrototype *>(arrayIteratorPrototype())->init(this); + static_cast<StringIteratorPrototype *>(stringIteratorPrototype())->init(this); + static_cast<VariantPrototype *>(variantPrototype())->init(); #if QT_CONFIG(qml_sequence_object) diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index f6ffd775ea..819481ed91 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -188,6 +188,7 @@ public: SignalHandlerProto, IteratorProto, ArrayIteratorProto, + StringIteratorProto, Object_Ctor, String_Ctor, @@ -268,6 +269,7 @@ public: 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); } + Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); } EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); } FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); } diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp index d5ed0c0c32..bce504a4c6 100644 --- a/src/qml/jsruntime/qv4managed.cpp +++ b/src/qml/jsruntime/qv4managed.cpp @@ -125,6 +125,9 @@ QString Managed::className() const case Type_ArrayIteratorObject: s = "Array Iterator"; break; + case Type_StringIteratorObject: + s = "String 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 454f4912c0..d404b66419 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -199,6 +199,7 @@ public: Type_ExecutionContext, Type_InternalClass, Type_ArrayIteratorObject, + Type_StringIteratorObject, Type_ForeachIteratorObject, Type_RegExp, diff --git a/src/qml/jsruntime/qv4stringiterator.cpp b/src/qml/jsruntime/qv4stringiterator.cpp new file mode 100644 index 0000000000..abdd0ee051 --- /dev/null +++ b/src/qml/jsruntime/qv4stringiterator.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Crimson AS <[email protected]> +** 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/qv4stringiterator_p.h> +#include <private/qv4symbol_p.h> + +using namespace QV4; + +DEFINE_OBJECT_VTABLE(StringIteratorObject); + +void StringIteratorPrototype::init(ExecutionEngine *e) +{ + defineDefaultProperty(QStringLiteral("next"), method_next, 0); + + Scope scope(e); + ScopedString val(scope, e->newString(QLatin1String("String Iterator"))); + defineReadonlyConfigurableProperty(e->symbol_toStringTag(), val); +} + +ReturnedValue StringIteratorPrototype::method_next(const FunctionObject *b, const Value *that, const Value *, int) +{ + Scope scope(b); + const StringIteratorObject *thisObject = that->as<StringIteratorObject>(); + if (!thisObject) + return scope.engine->throwTypeError(QLatin1String("Not an String Iterator instance")); + + ScopedString s(scope, thisObject->d()->iteratedString); + if (!s) { + QV4::Value undefined = Primitive::undefinedValue(); + return IteratorPrototype::createIterResultObject(scope.engine, undefined, ScopedValue(scope, true); + } + + quint32 index = thisObject->d()->nextIndex; + + QString str = s->toQString(); + quint32 len = str.length(); + + if (index >= len) { + thisObject->d()->iteratedString.set(scope.engine, nullptr); + QV4::Value undefined = Primitive::undefinedValue(); + return IteratorPrototype::createIterResultObject(scope.engine, undefined, ScopedValue(scope, true); + } + + QChar ch = str.at(index); + int num = 1; + if (ch.unicode() >= 0xd800 && ch.unicode() <= 0xdbff && index + 1 != len) { + ch = str.at(index + 1); + if (ch.unicode() >= 0xdc00 && ch.unicode() <= 0xdfff) + num = 2; + } + + thisObject->d()->nextIndex += num; + + ScopedString resultString(scope, scope.engine->newString(s->toQString().mid(index, num))); + return IteratorPrototype::createIterResultObject(scope.engine, resultString, ScopedValue(scope, false); +} + diff --git a/src/qml/jsruntime/qv4stringiterator_p.h b/src/qml/jsruntime/qv4stringiterator_p.h new file mode 100644 index 0000000000..672ccc9963 --- /dev/null +++ b/src/qml/jsruntime/qv4stringiterator_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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 QV4STRINGITERATOR_P_H +#define QV4STRINGITERATOR_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 "qv4string_p.h" + +QT_BEGIN_NAMESPACE + + +namespace QV4 { + +namespace Heap { + +#define StringIteratorObjectMembers(class, Member) \ + Member(class, Pointer, String *, iteratedString) \ + Member(class, NoMark, quint32, nextIndex) + +DECLARE_HEAP_OBJECT(StringIteratorObject, Object) { + DECLARE_MARKOBJECTS(StringIteratorObject); + void init(String *str, QV4::ExecutionEngine *engine) + { + Object::init(); + this->iteratedString.set(engine, str); + this->nextIndex = 0; + } +}; + +} + +struct StringIteratorPrototype : Object +{ + V4_PROTOTYPE(iteratorPrototype) + void init(ExecutionEngine *engine); + + static ReturnedValue method_next(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc); +}; + +struct StringIteratorObject : Object +{ + V4_OBJECT2(StringIteratorObject, Object) + Q_MANAGED_TYPE(StringIteratorObject) + V4_PROTOTYPE(stringIteratorPrototype) + + void init(ExecutionEngine *engine); +}; + + +} + +QT_END_NAMESPACE + +#endif // QV4ARRAYITERATOR_P_H + diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index bfc7a82046..2c0d1fdbad 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -47,6 +47,7 @@ #include "qv4symbol_p.h" #include "qv4alloca_p.h" #include "qv4jscall_p.h" +#include "qv4stringiterator_p.h" #include <QtCore/QDateTime> #include <QtCore/QDebug> #include <QtCore/QStringList> @@ -206,6 +207,7 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("toUpperCase"), method_toUpperCase); defineDefaultProperty(QStringLiteral("toLocaleUpperCase"), method_toLocaleUpperCase); defineDefaultProperty(QStringLiteral("trim"), method_trim); + defineDefaultProperty(engine->symbol_iterator(), method_iterator); } static Heap::String *thisAsString(ExecutionEngine *v4, const QV4::Value *thisObject) @@ -928,3 +930,16 @@ ReturnedValue StringPrototype::method_trim(const FunctionObject *b, const Value return Encode(v4->newString(QString(chars + start, end - start + 1))); } + + + +ReturnedValue StringPrototype::method_iterator(const FunctionObject *b, const Value *thisObject, const Value *, int) +{ + Scope scope(b); + ScopedString s(scope, thisObject->toString(scope.engine)); + if (!s || thisObject->isNullOrUndefined()) + return scope.engine->throwTypeError(); + + Scoped<StringIteratorObject> si(scope, scope.engine->memoryManager->allocate<StringIteratorObject>(s->d(), scope.engine)); + return si->asReturnedValue(); +} diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h index 7d25678b61..207e9f2781 100644 --- a/src/qml/jsruntime/qv4stringobject_p.h +++ b/src/qml/jsruntime/qv4stringobject_p.h @@ -139,6 +139,7 @@ struct StringPrototype: StringObject static ReturnedValue method_toLocaleUpperCase(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_fromCharCode(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_trim(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); + static ReturnedValue method_iterator(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 f692d1e74f..00b9b7f513 100644 --- a/tests/auto/qml/ecmascripttests/TestExpectations +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -2164,10 +2164,6 @@ built-ins/String/fromCodePoint/number-is-out-of-range.js fails built-ins/String/fromCodePoint/return-string-value.js fails built-ins/String/fromCodePoint/to-number-conversions.js fails built-ins/String/proto-from-ctor-realm.js fails -built-ins/String/prototype/Symbol.iterator/length.js fails -built-ins/String/prototype/Symbol.iterator/name.js fails -built-ins/String/prototype/Symbol.iterator/prop-desc.js fails -built-ins/String/prototype/Symbol.iterator/this-val-to-str-err.js fails built-ins/String/prototype/codePointAt/codePointAt.js fails built-ins/String/prototype/codePointAt/length.js fails built-ins/String/prototype/codePointAt/name.js fails @@ -2254,13 +2250,6 @@ built-ins/String/raw/template-length-throws.js fails built-ins/String/raw/template-raw-throws.js fails built-ins/String/raw/template-substitutions-are-appended-on-same-index.js fails built-ins/String/raw/zero-literal-segments.js fails -built-ins/StringIteratorPrototype/Symbol.toStringTag.js fails -built-ins/StringIteratorPrototype/ancestry.js fails -built-ins/StringIteratorPrototype/next/length.js fails -built-ins/StringIteratorPrototype/next/name.js fails -built-ins/StringIteratorPrototype/next/next-iteration-surrogate-pairs.js fails -built-ins/StringIteratorPrototype/next/next-iteration.js fails -built-ins/StringIteratorPrototype/next/next-missing-internal-slots.js fails built-ins/Symbol/for/cross-realm.js fails built-ins/Symbol/hasInstance/cross-realm.js fails built-ins/Symbol/isConcatSpreadable/cross-realm.js fails |