diff options
author | Robin Burchell <[email protected]> | 2018-05-24 21:19:22 +0200 |
---|---|---|
committer | Robin Burchell <[email protected]> | 2018-05-25 20:41:46 +0000 |
commit | a1ea2b8ec057bca58fdb5e9498e2f302ef0e61b4 (patch) | |
tree | 44a46d21a149897ca2a9c352fc2a61b48a5a7aaa | |
parent | 120e5c8dd99a51c0b5010f1eb7101366ae3ea638 (diff) |
qv4arrayobject: Implement Array.prototype.fill according to ES7
Task-number: QTBUG-56824
Change-Id: Ib12b9fe5ebdd5375f17cf4927eb9b4e292731932
Reviewed-by: Lars Knoll <[email protected]>
-rw-r--r-- | src/qml/jsruntime/qv4arrayobject.cpp | 37 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arrayobject_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 17 | ||||
-rw-r--r-- | tests/auto/qml/ecmascripttests/TestExpectations | 13 |
4 files changed, 55 insertions, 13 deletions
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index c04edbe872..f8398d206d 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -116,6 +116,7 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("keys"), method_keys, 0); defineDefaultProperty(QStringLiteral("lastIndexOf"), method_lastIndexOf, 1); defineDefaultProperty(QStringLiteral("every"), method_every, 1); + defineDefaultProperty(QStringLiteral("fill"), method_fill, 1); defineDefaultProperty(QStringLiteral("some"), method_some, 1); defineDefaultProperty(QStringLiteral("forEach"), method_forEach, 1); defineDefaultProperty(QStringLiteral("map"), method_map, 1); @@ -854,6 +855,42 @@ ReturnedValue ArrayPrototype::method_every(const FunctionObject *b, const Value return Encode(ok); } +ReturnedValue ArrayPrototype::method_fill(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(); + + uint len = instance->getLength(); + int relativeStart = argc > 1 ? argv[1].toInteger() : 0; + int relativeEnd = len; + if (argc > 2 && !argv[2].isUndefined()) { + relativeEnd = argv[2].toInteger(); + } + uint k = 0; + uint fin = 0; + + if (relativeStart < 0) { + k = std::max(len+relativeStart, uint(0)); + } else { + k = std::min(uint(relativeStart), len); + } + + if (relativeEnd < 0) { + fin = std::max(len + relativeEnd, uint(0)); + } else { + fin = std::min(uint(relativeEnd), len); + } + + while (k < fin) { + instance->setIndexed(k, argv[0], QV4::Object::DoThrowOnRejection); + k++; + } + + return instance.asReturnedValue(); +} + ReturnedValue ArrayPrototype::method_some(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) { Scope scope(b); diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h index 31067b0c39..a8feb65e80 100644 --- a/src/qml/jsruntime/qv4arrayobject_p.h +++ b/src/qml/jsruntime/qv4arrayobject_p.h @@ -98,6 +98,7 @@ struct ArrayPrototype: ArrayObject 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_fill(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_some(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_forEach(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_map(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 7cc99376be..5ad67635db 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -385,6 +385,23 @@ public: DoNotThrow }; + // This is the same as set(), but it doesn't require creating a string key, + // which is much more efficient for the array case. + inline bool setIndexed(uint idx, const Value &v, ThrowOnFailure shouldThrow) + { + bool ret = vtable()->putIndexed(this, idx, v); + // ES6: 7.3.3, 6: If success is false and Throw is true, throw a TypeError exception. + if (!ret && shouldThrow == ThrowOnFailure::DoThrowOnRejection) { + ExecutionEngine *e = engine(); + if (!e->hasException) { // allow a custom set impl to throw itself + QString message = QLatin1String("Cannot assign to read-only property \"") + + QString::number(idx) + QLatin1Char('\"'); + e->throwTypeError(message); + } + } + return ret; + } + // ES6: 7.3.3 Set (O, P, V, Throw) inline bool set(StringOrSymbol *name, const Value &v, ThrowOnFailure shouldThrow) { diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations index 626b1a39a4..3b6170716f 100644 --- a/tests/auto/qml/ecmascripttests/TestExpectations +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -143,19 +143,6 @@ 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/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 -built-ins/Array/prototype/fill/fill-values-relative-end.js fails -built-ins/Array/prototype/fill/fill-values-relative-start.js fails -built-ins/Array/prototype/fill/fill-values.js fails -built-ins/Array/prototype/fill/length.js fails -built-ins/Array/prototype/fill/name.js fails -built-ins/Array/prototype/fill/prop-desc.js fails -built-ins/Array/prototype/fill/return-abrupt-from-end.js fails -built-ins/Array/prototype/fill/return-abrupt-from-setting-property-value.js fails -built-ins/Array/prototype/fill/return-abrupt-from-start.js fails -built-ins/Array/prototype/fill/return-abrupt-from-this-length.js fails -built-ins/Array/prototype/fill/return-this.js fails built-ins/Array/prototype/filter/create-ctor-non-object.js fails built-ins/Array/prototype/filter/create-proto-from-ctor-realm-array.js fails built-ins/Array/prototype/filter/create-proto-from-ctor-realm-non-array.js fails |