diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-08-30 12:58:55 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-08-31 06:08:41 +0000 |
commit | ee565b3db656b5b9bfd57d98d53b898c1a62e1f0 (patch) | |
tree | 857b0f3c09144e68ee0d6cfdf25a227df2f76c8b /src/qml/jsruntime/qv4runtime.cpp | |
parent | ebf9365b5c7ec1e4828be88beeb930b4de52f35b (diff) |
Correctly create methods for functions in object literals
Methods behave slightly different than normal functions as they have
a home object and define how super property access is being done. To
implement this correctly, we need to create these methods during object
initialization time.
Change-Id: Ib3f670c8790b882c6472de786938ca4f0b73f66f
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4runtime.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 3317003ea4..fbddcb6ee1 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1529,30 +1529,48 @@ ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, int classId ScopedProperty pd(scope); ScopedFunctionObject fn(scope); ScopedString fnName(scope); + ScopedValue value(scope); for (int i = 0; i < additionalArgs; ++i) { Q_ASSERT(args->isInteger()); ObjectLiteralArgument arg = ObjectLiteralArgument(args->integerValue()); name = args[1].toPropertyKey(engine); + value = args[2]; if (engine->hasException) return Encode::undefined(); - if (args[2].isFunctionObject()) { - fn = static_cast<const FunctionObject &>(args[2]); + if (arg != ObjectLiteralArgument::Value) { + Q_ASSERT(args[2].isInteger()); + int functionId = args[2].integerValue(); + QV4::Function *clos = static_cast<CompiledData::CompilationUnit*>(engine->currentStackFrame->v4Function->compilationUnit)->runtimeFunctions[functionId]; + Q_ASSERT(clos); + PropertyKey::FunctionNamePrefix prefix = PropertyKey::None; if (arg == ObjectLiteralArgument::Getter) prefix = PropertyKey::Getter; else if (arg == ObjectLiteralArgument::Setter) prefix = PropertyKey::Setter; - + else + arg = ObjectLiteralArgument::Value; fnName = name->asFunctionName(engine, prefix); + + ExecutionContext *current = static_cast<ExecutionContext *>(&engine->currentStackFrame->jsFrame->context); + if (clos->isGenerator()) + value = MemberGeneratorFunction::create(current, clos, fnName)->asReturnedValue(); + else + value = FunctionObject::createMemberFunction(current, clos, fnName)->asReturnedValue(); + } else if (args[2].isFunctionObject()) { + fn = static_cast<const FunctionObject &>(args[2]); + + fnName = name->asFunctionName(engine, PropertyKey::None); fn->setName(fnName); } - Q_ASSERT(arg == ObjectLiteralArgument::Value || args[2].isFunctionObject()); + Q_ASSERT(arg != ObjectLiteralArgument::Method); + Q_ASSERT(arg == ObjectLiteralArgument::Value || value->isFunctionObject()); if (arg == ObjectLiteralArgument::Value || arg == ObjectLiteralArgument::Getter) { - pd->value = args[2]; + pd->value = value; pd->set = Primitive::emptyValue(); } else { pd->value = Primitive::emptyValue(); - pd->set = args[2]; + pd->set = value; } bool ok = o->defineOwnProperty(name, pd, (arg == ObjectLiteralArgument::Value ? Attr_Data : Attr_Accessor)); if (!ok) |