diff options
author | Robin Burchell <robin.burchell@crimson.no> | 2018-05-24 22:45:04 +0200 |
---|---|---|
committer | Robin Burchell <robin.burchell@crimson.no> | 2018-05-30 18:13:09 +0000 |
commit | e7dab999f7f662b7045e61ee080df3d00da18a92 (patch) | |
tree | 020eb29bab252b14ada811e22ac6c67e353e9275 /src/qml/jsruntime/qv4arrayobject.cpp | |
parent | 704961111410f1d53b5aebc25ee188ced5a294d9 (diff) |
qv4arrayobject: Implement Array.prototype.copyWithin as per ES7
The remaining two failures are due to Proxy being missing.
Change-Id: I6cc5177cd958d98600cc2ba3b1e1a18bc420530c
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4arrayobject.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4arrayobject.cpp | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index ad1558785d..4a78bbcd9a 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -102,6 +102,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("copyWithin"), method_copyWithin, 2); defineDefaultProperty(QStringLiteral("entries"), method_entries, 0); defineDefaultProperty(QStringLiteral("find"), method_find, 1); defineDefaultProperty(QStringLiteral("findIndex"), method_findIndex, 1); @@ -242,6 +243,76 @@ ReturnedValue ArrayPrototype::method_concat(const FunctionObject *b, const Value return result.asReturnedValue(); } +ReturnedValue ArrayPrototype::method_copyWithin(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) +{ + Scope scope(b); + ScopedObject instance(scope, thisObject->toObject(scope.engine)); + if (!instance) + RETURN_UNDEFINED(); + + double len = instance->getLength(); + double target = argv[0].toInteger(); + double start = argv[1].toInteger(); + double end = len; + + if (argc > 2 && !argv[2].isUndefined()) { + end = argv[2].toInteger(); + } + + double relativeTarget = target; + double relativeStart = start; + double relativeEnd = end; + double from = 0; + double to = 0; + + if (relativeTarget < 0) { + to = std::max(len+relativeTarget, 0.0); + } else { + to = std::min(relativeTarget, len); + } + if (relativeStart < 0) { + from = std::max(len+relativeStart, 0.0); + } else { + from = std::min(relativeStart, len); + } + + double fin = 0; + if (relativeEnd < 0) { + fin = std::max(len+relativeEnd, 0.0); + } else { + fin = std::min(relativeEnd, len); + } + double count = std::min(fin-from, len-to); + double direction = 1; + if (from < to && to < from+count) { + direction = -1; + from = from + count - 1; + to = to + count - 1; + } + + while (count > 0) { + bool fromPresent = false; + ScopedValue fromVal(scope, instance->getIndexed(from, &fromPresent)); + + if (fromPresent) { + instance->setIndexed(to, fromVal, QV4::Object::DoThrowOnRejection); + CHECK_EXCEPTION(); + } else { + bool didDelete = instance->deleteIndexedProperty(to); + CHECK_EXCEPTION(); + if (!didDelete) { + return scope.engine->throwTypeError(); + } + } + + from = from + direction; + to = to + direction; + count = count - 1; + } + + return instance.asReturnedValue(); +} + ReturnedValue ArrayPrototype::method_entries(const FunctionObject *b, const Value *thisObject, const Value *, int) { Scope scope(b); |