From 2b8a9fc66309038dac21624293cf3b91d87165c3 Mon Sep 17 00:00:00 2001 From: Kai Uwe Broulik Date: Tue, 8 Nov 2016 11:09:13 +0100 Subject: Add ECMAScript 6 Array find and findIndex methods Change-Id: I318fa243ab68b8a714923ab816d62e8c544fca8c Reviewed-by: Lars Knoll --- src/qml/doc/src/javascript/functionlist.qdoc | 2 + src/qml/jsruntime/qv4arrayobject.cpp | 76 ++++++++++++++++++++++++++++ src/qml/jsruntime/qv4arrayobject_p.h | 2 + tests/auto/qml/qjsengine/tst_qjsengine.cpp | 2 + tests/manual/v4/fun.4.js | 3 +- 5 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/qml/doc/src/javascript/functionlist.qdoc b/src/qml/doc/src/javascript/functionlist.qdoc index b9a25a2440..f5b1ed3cf1 100644 --- a/src/qml/doc/src/javascript/functionlist.qdoc +++ b/src/qml/doc/src/javascript/functionlist.qdoc @@ -143,6 +143,8 @@ \li toLocaleString() \li concat([item1 [, item2 [, ...]]]) \li join(separator) + \li find(callbackfn [, thisArg]) // ECMAScript 6: Added in Qt 5.9 + \li findIndex(callbackfn [, thisArg]) // ECMAScript 6: Added in Qt 5.9 \li pop() \li push([item1 [, item2 [, ...]]]) \li reverse() diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 659ede7552..20ba11fd75 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -96,6 +96,8 @@ 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("find"), method_find, 1); + defineDefaultProperty(QStringLiteral("findIndex"), method_findIndex, 1); defineDefaultProperty(QStringLiteral("join"), method_join, 1); defineDefaultProperty(QStringLiteral("pop"), method_pop, 0); defineDefaultProperty(QStringLiteral("push"), method_push, 1); @@ -182,6 +184,80 @@ ReturnedValue ArrayPrototype::method_concat(CallContext *ctx) return result.asReturnedValue(); } +ReturnedValue ArrayPrototype::method_find(CallContext *ctx) +{ + Scope scope(ctx); + ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + if (!instance) + return Encode::undefined(); + + uint len = instance->getLength(); + + ScopedFunctionObject callback(scope, ctx->argument(0)); + if (!callback) + return ctx->engine()->throwTypeError(); + + ScopedCallData callData(scope, 3); + callData->thisObject = ctx->argument(1); + callData->args[2] = instance; + + ScopedValue v(scope); + + for (uint k = 0; k < len; ++k) { + v = instance->getIndexed(k); + if (scope.hasException()) + return Encode::undefined(); + + callData->args[0] = v; + callData->args[1] = Primitive::fromDouble(k); + callback->call(scope, callData); + + if (scope.hasException()) + return Encode::undefined(); + else if (scope.result.toBoolean()) + return v->asReturnedValue(); + } + + return Encode::undefined(); +} + +ReturnedValue ArrayPrototype::method_findIndex(CallContext *ctx) +{ + Scope scope(ctx); + ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + if (!instance) + return Encode::undefined(); + + uint len = instance->getLength(); + + ScopedFunctionObject callback(scope, ctx->argument(0)); + if (!callback) + return ctx->engine()->throwTypeError(); + + ScopedCallData callData(scope, 3); + callData->thisObject = ctx->argument(1); + callData->args[2] = instance; + + ScopedValue v(scope); + + for (uint k = 0; k < len; ++k) { + v = instance->getIndexed(k); + if (scope.hasException()) + return Encode::undefined(); + + callData->args[0] = v; + callData->args[1] = Primitive::fromDouble(k); + callback->call(scope, callData); + + if (scope.hasException()) + return Encode::undefined(); + else if (scope.result.toBoolean()) + return Encode(k); + } + + return Encode(-1); +} + ReturnedValue ArrayPrototype::method_join(CallContext *ctx) { Scope scope(ctx); diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h index 9a05bb8681..f00c0c0249 100644 --- a/src/qml/jsruntime/qv4arrayobject_p.h +++ b/src/qml/jsruntime/qv4arrayobject_p.h @@ -82,6 +82,8 @@ struct ArrayPrototype: ArrayObject static ReturnedValue method_toString(CallContext *ctx); static ReturnedValue method_toLocaleString(CallContext *ctx); static ReturnedValue method_concat(CallContext *ctx); + static ReturnedValue method_find(CallContext *ctx); + static ReturnedValue method_findIndex(CallContext *ctx); static ReturnedValue method_join(CallContext *ctx); static ReturnedValue method_pop(CallContext *ctx); static ReturnedValue method_push(CallContext *ctx); diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 2c7dde1b8d..f6fbb8c37e 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -1038,6 +1038,8 @@ void tst_QJSEngine::builtinFunctionNames_data() QTest::newRow("Array.prototype.toString") << QString("Array.prototype.toString") << QString("toString"); QTest::newRow("Array.prototype.toLocaleString") << QString("Array.prototype.toLocaleString") << QString("toLocaleString"); QTest::newRow("Array.prototype.concat") << QString("Array.prototype.concat") << QString("concat"); + QTest::newRow("Array.prototype.find") << QString("Array.prototype.find") << QString("find"); + QTest::newRow("Array.prototype.findIndex") << QString("Array.prototype.findIndex") << QString("findIndex"); QTest::newRow("Array.prototype.join") << QString("Array.prototype.join") << QString("join"); QTest::newRow("Array.prototype.pop") << QString("Array.prototype.pop") << QString("pop"); QTest::newRow("Array.prototype.push") << QString("Array.prototype.push") << QString("push"); diff --git a/tests/manual/v4/fun.4.js b/tests/manual/v4/fun.4.js index b130acccd3..277761ad09 100644 --- a/tests/manual/v4/fun.4.js +++ b/tests/manual/v4/fun.4.js @@ -15,4 +15,5 @@ print([10, 20, 30].filter(function (v,k,o) { return v >= 20 })); print([10,20,30].reduce(function(a,v,k,o) { return a + v })); print([10,20,30].reduceRight(function(a,v,k,o) { return a + v })); - +print([10, 20, 30].find(function (v,k,o) { return v >= 20 })); +print([10, 20, 30].findIndex(function (v,k,o) { return v >= 20 })); -- cgit v1.2.3