From ee565b3db656b5b9bfd57d98d53b898c1a62e1f0 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 30 Aug 2018 12:58:55 +0200 Subject: 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 --- src/qml/jsruntime/qv4runtime.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'src/qml/jsruntime/qv4runtime.cpp') 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(args[2]); + if (arg != ObjectLiteralArgument::Value) { + Q_ASSERT(args[2].isInteger()); + int functionId = args[2].integerValue(); + QV4::Function *clos = static_cast(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(&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(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) -- cgit v1.2.3