diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-05-31 14:22:35 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-06-04 13:02:32 +0000 |
commit | bdb8cf49daf4a1c7dfb9bd9caf14e19e3aa66293 (patch) | |
tree | c9f2c88f41bc4f5dd7011325438436694f5449fb /src/qml/jsruntime/qv4runtime.cpp | |
parent | 502678a183e68a837a5b2ddee2978a3be5e9e008 (diff) |
Fix creation of object literals
Our method to create object literals wasn't compliant with the
ES7 spec, as we would in some cases re-order the properties.
This violated the spec which required properties to be created
in order, so that for-of would also iterate over them in creation
order.
As a nice side effect, this simplifies the code and gets a couple
of test cases using computed property names to pass.
Task-number: QTBUG-62512
Change-Id: I6dfe004357c5d46a0890027f4fd9e2d1e1a2a17a
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4runtime.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 54 |
1 files changed, 27 insertions, 27 deletions
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index b712b40897..5eec51c1e4 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1382,45 +1382,45 @@ ReturnedValue Runtime::method_arrayLiteral(ExecutionEngine *engine, Value *value return engine->newArrayObject(values, length)->asReturnedValue(); } -ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags) +ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, int classId, int argc, const QV4::Value *args) { Scope scope(engine); Scoped<InternalClass> klass(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeClasses[classId]); ScopedObject o(scope, engine->newObject(klass->d())); - { - bool needSparseArray = arrayGetterSetterCountAndFlags >> 30; - if (needSparseArray) - o->initSparseArray(); - } + Q_ASSERT(uint(argc) >= klass->d()->size); for (uint i = 0; i < klass->d()->size; ++i) o->setProperty(i, *args++); - if (arrayValueCount > 0) { - ScopedValue entry(scope); - for (int i = 0; i < arrayValueCount; ++i) { - uint idx = args->toUInt32(); - ++args; - entry = *args++; - o->arraySet(idx, entry); - } - } + Q_ASSERT((argc - klass->d()->size) % 3 == 0); + int additionalArgs = (argc - int(klass->d()->size))/3; - uint arrayGetterSetterCount = arrayGetterSetterCountAndFlags & ((1 << 30) - 1); - if (arrayGetterSetterCount > 0) { - ScopedProperty pd(scope); - for (uint i = 0; i < arrayGetterSetterCount; ++i) { - uint idx = args->toUInt32(); - ++args; - pd->value = *args; - ++args; - pd->set = *args; - ++args; - o->arraySet(idx, pd, Attr_Accessor); + if (!additionalArgs) + return o->asReturnedValue(); + + Scoped<StringOrSymbol> name(scope); + ScopedProperty pd(scope); + for (int i = 0; i < additionalArgs; ++i) { + Q_ASSERT(args->isInteger()); + ObjectLiteralArgument arg = ObjectLiteralArgument(args->integerValue()); + name = args[1].toPropertyKey(engine); + if (engine->hasException) + return Encode::undefined(); + Q_ASSERT(arg == ObjectLiteralArgument::Value || args[2].isFunctionObject()); + if (arg == ObjectLiteralArgument::Value || arg == ObjectLiteralArgument::Getter) { + pd->value = args[2]; + pd->set = Primitive::emptyValue(); + } else { + pd->value = Primitive::emptyValue(); + pd->set = args[2]; } - } + bool ok = o->__defineOwnProperty__(scope.engine, name, pd, (arg == ObjectLiteralArgument::Value ? Attr_Data : Attr_Accessor)); + if (!ok) + return engine->throwTypeError(); + args += 3; + } return o.asReturnedValue(); } |