aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4arrayobject.cpp
diff options
context:
space:
mode:
authorRobin Burchell <robin.burchell@crimson.no>2018-05-26 19:19:57 +0200
committerRobin Burchell <robin.burchell@crimson.no>2018-05-27 14:32:50 +0000
commit1f85383957abbc6863a8c75e9be7acbf08c6c2ad (patch)
tree14136a55a5c208fae43ad95b58cd80b907763fea /src/qml/jsruntime/qv4arrayobject.cpp
parent4bbd8859624da1cf396c09d5a0dd778c985118c0 (diff)
qv4arrayobject: Implement Array.of from ES7
One small difficulty: We can't accurately tell whether a thisObject is a constructor or not, so right now we're just swallowing all exceptions and creating an array if they occur. This isn't correct, but it isn't trivial to fix, either: I think we would have to somehow mark our builtins that are constructors, and allow those, but use the array fallback for other builtins, calling user functions and bubbling up if they throw. This is probably good enough for the time being though, as writing something like: function Test() { throw "Foo"; } Array.of.call(Test) ... is probably not very likely, compared to more "usual" use. Change-Id: Ied341a7fa9c3a7fd907e2815c019bc431171ce62 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4arrayobject.cpp')
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 2c4be85014..ad1558785d 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -95,6 +95,7 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineDefaultProperty(QStringLiteral("isArray"), method_isArray, 1);
+ ctor->defineDefaultProperty(QStringLiteral("of"), method_of, 0);
ctor->addSymbolSpecies();
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
@@ -138,6 +139,50 @@ ReturnedValue ArrayPrototype::method_isArray(const FunctionObject *, const Value
return Encode(isArray);
}
+ReturnedValue ArrayPrototype::method_of(const FunctionObject *builtin, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(builtin);
+ ScopedObject object(scope, Primitive::undefinedValue());
+ ScopedFunctionObject that(scope, thisObject);
+
+ if (that) {
+ // ### the spec says that we should only call constructors if
+ // IsConstructor(that), but we have no way of knowing if a builtin is a
+ // constructor. so for the time being, just try call it, and silence any
+ // exceptions-- this is not ideal, as the spec also says that we should
+ // return on exception.
+ ScopedValue argument(scope, QV4::Encode(argc));
+ object = ScopedObject(scope, that->callAsConstructor(argument, 1));
+ if (scope.engine->hasException) {
+ scope.engine->catchException(); // probably not a constructor, then.
+ }
+ }
+
+ if (!object) {
+ object = ScopedObject(scope, scope.engine->newArrayObject());
+ CHECK_EXCEPTION();
+ }
+
+ int k = 0;
+ while (k < argc) {
+ if (object->hasOwnProperty(k)) {
+ return scope.engine->throwTypeError(QString::fromLatin1("Cannot redefine property: %1").arg(k));
+ }
+ object->arraySet(k, argv[k]);
+ CHECK_EXCEPTION();
+
+ k++;
+ }
+
+ // ArrayObject updates its own length, and will throw if we try touch it.
+ if (!object->as<ArrayObject>()) {
+ object->set(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(argc)), QV4::Object::DoThrowOnRejection);
+ CHECK_EXCEPTION();
+ }
+
+ return object.asReturnedValue();
+}
+
ReturnedValue ArrayPrototype::method_toString(const FunctionObject *builtin, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(builtin);