diff options
Diffstat (limited to 'src/qml')
57 files changed, 481 insertions, 390 deletions
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index f2be552cf8..a49bd32d66 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -12,14 +12,14 @@ DEFINE_OBJECT_VTABLE(ArrayBufferCtor); DEFINE_OBJECT_VTABLE(SharedArrayBuffer); DEFINE_OBJECT_VTABLE(ArrayBuffer); -void Heap::SharedArrayBufferCtor::init(QV4::ExecutionContext *scope) +void Heap::SharedArrayBufferCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("SharedArrayBuffer")); + Heap::FunctionObject::init(engine, QStringLiteral("SharedArrayBuffer")); } -void Heap::ArrayBufferCtor::init(QV4::ExecutionContext *scope) +void Heap::ArrayBufferCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("ArrayBuffer")); + Heap::FunctionObject::init(engine, QStringLiteral("ArrayBuffer")); } ReturnedValue SharedArrayBufferCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h index aafa3c6335..af1195a947 100644 --- a/src/qml/jsruntime/qv4arraybuffer_p.h +++ b/src/qml/jsruntime/qv4arraybuffer_p.h @@ -25,11 +25,11 @@ namespace QV4 { namespace Heap { struct SharedArrayBufferCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(QV4::ExecutionEngine *engine); }; struct ArrayBufferCtor : SharedArrayBufferCtor { - void init(QV4::ExecutionContext *scope); + void init(QV4::ExecutionEngine *engine); }; struct Q_QML_EXPORT SharedArrayBuffer : Object { diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index a32017210a..7c9e7034d8 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -14,9 +14,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ArrayCtor); -void Heap::ArrayCtor::init(QV4::ExecutionContext *scope) +void Heap::ArrayCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("Array")); + Heap::FunctionObject::init(engine, QStringLiteral("Array")); } ReturnedValue ArrayCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h index b07e27b24f..a68068937f 100644 --- a/src/qml/jsruntime/qv4arrayobject_p.h +++ b/src/qml/jsruntime/qv4arrayobject_p.h @@ -50,7 +50,7 @@ namespace QV4 { namespace Heap { struct ArrayCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(QV4::ExecutionEngine *engine); }; } diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp index 3110ec7992..5c1d50e753 100644 --- a/src/qml/jsruntime/qv4booleanobject.cpp +++ b/src/qml/jsruntime/qv4booleanobject.cpp @@ -8,9 +8,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(BooleanCtor); DEFINE_OBJECT_VTABLE(BooleanObject); -void Heap::BooleanCtor::init(QV4::ExecutionContext *scope) +void Heap::BooleanCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("Boolean")); + Heap::FunctionObject::init(engine, QStringLiteral("Boolean")); } ReturnedValue BooleanCtor::virtualCallAsConstructor(const FunctionObject *that, const Value *argv, int argc, const Value *newTarget) diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h index e009b0413a..1b2d3914ac 100644 --- a/src/qml/jsruntime/qv4booleanobject_p.h +++ b/src/qml/jsruntime/qv4booleanobject_p.h @@ -25,7 +25,7 @@ namespace QV4 { namespace Heap { struct BooleanCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; } diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 3ae3e5d24c..01f9b4adf3 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -32,7 +32,7 @@ Heap::CallContext *ExecutionContext::newBlockContext(CppStackFrame *frame, int b Heap::ExecutionContext *outer = static_cast<Heap::ExecutionContext *>(frame->context()->m()); c->outer.set(v4, outer); if (frame->isJSTypesFrame()) { - c->function.set(v4, static_cast<Heap::FunctionObject *>( + c->function.set(v4, static_cast<Heap::JavaScriptFunctionObject *>( Value::fromStaticValue( static_cast<JSTypesStackFrame *>(frame)->jsFrame->function).m())); } else { @@ -74,7 +74,7 @@ Heap::CallContext *ExecutionContext::newCallContext(JSTypesStackFrame *frame) c->init(); c->outer.set(v4, outer); - c->function.set(v4, static_cast<Heap::FunctionObject *>( + c->function.set(v4, static_cast<Heap::JavaScriptFunctionObject *>( Value::fromStaticValue(frame->jsFrame->function).m())); const CompiledData::Function *compiledFunction = function->compiledFunction; diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 82a9472223..48b6e04025 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -64,7 +64,7 @@ Q_STATIC_ASSERT(offsetof(ExecutionContextData, outer) == 0); Q_STATIC_ASSERT(offsetof(ExecutionContextData, activation) == offsetof(ExecutionContextData, outer) + QT_POINTER_SIZE); #define CallContextMembers(class, Member) \ - Member(class, Pointer, FunctionObject *, function) \ + Member(class, Pointer, JavaScriptFunctionObject *, function) \ Member(class, ValueArray, ValueArray, locals) DECLARE_HEAP_OBJECT(CallContext, ExecutionContext) { diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp index f4ca09a127..689eb9232b 100644 --- a/src/qml/jsruntime/qv4dataview.cpp +++ b/src/qml/jsruntime/qv4dataview.cpp @@ -13,9 +13,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(DataViewCtor); DEFINE_OBJECT_VTABLE(DataView); -void Heap::DataViewCtor::init(QV4::ExecutionContext *scope) +void Heap::DataViewCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("DataView")); + Heap::FunctionObject::init(engine, QStringLiteral("DataView")); } static uint toIndex(ExecutionEngine *e, const Value &v) diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h index ab2e1e589a..b5fa41d964 100644 --- a/src/qml/jsruntime/qv4dataview_p.h +++ b/src/qml/jsruntime/qv4dataview_p.h @@ -24,7 +24,7 @@ namespace QV4 { namespace Heap { struct DataViewCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; #define DataViewMembers(class, Member) \ diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 6b64be3abb..2cb020e495 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -766,9 +766,9 @@ QDate DateObject::dateTimeToDate(const QDateTime &dateTime) DEFINE_OBJECT_VTABLE(DateCtor); -void Heap::DateCtor::init(QV4::ExecutionContext *scope) +void Heap::DateCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("Date")); + Heap::FunctionObject::init(engine, QStringLiteral("Date")); } ReturnedValue DateCtor::virtualCallAsConstructor(const FunctionObject *that, const Value *argv, int argc, const Value *newTarget) diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h index 7debcff4e9..4c184de897 100644 --- a/src/qml/jsruntime/qv4dateobject_p.h +++ b/src/qml/jsruntime/qv4dateobject_p.h @@ -189,7 +189,7 @@ private: struct DateCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(QV4::ExecutionEngine *engine); }; } diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index a2a2e99a01..8450959de4 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -627,25 +627,23 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) ic = newInternalClass(SequencePrototype::staticVTable(), SequencePrototype::defaultPrototype(this)); jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->allocObject<SequencePrototype>(ic->d())); - ExecutionContext *global = rootContext(); - - jsObjects[Object_Ctor] = memoryManager->allocate<ObjectCtor>(global); - jsObjects[String_Ctor] = memoryManager->allocate<StringCtor>(global); - jsObjects[Symbol_Ctor] = memoryManager->allocate<SymbolCtor>(global); - jsObjects[Number_Ctor] = memoryManager->allocate<NumberCtor>(global); - jsObjects[Boolean_Ctor] = memoryManager->allocate<BooleanCtor>(global); - jsObjects[Array_Ctor] = memoryManager->allocate<ArrayCtor>(global); - jsObjects[Function_Ctor] = memoryManager->allocate<FunctionCtor>(global); - jsObjects[GeneratorFunction_Ctor] = memoryManager->allocate<GeneratorFunctionCtor>(global); - jsObjects[Date_Ctor] = memoryManager->allocate<DateCtor>(global); - jsObjects[RegExp_Ctor] = memoryManager->allocate<RegExpCtor>(global); - jsObjects[Error_Ctor] = memoryManager->allocate<ErrorCtor>(global); - jsObjects[EvalError_Ctor] = memoryManager->allocate<EvalErrorCtor>(global); - jsObjects[RangeError_Ctor] = memoryManager->allocate<RangeErrorCtor>(global); - jsObjects[ReferenceError_Ctor] = memoryManager->allocate<ReferenceErrorCtor>(global); - jsObjects[SyntaxError_Ctor] = memoryManager->allocate<SyntaxErrorCtor>(global); - jsObjects[TypeError_Ctor] = memoryManager->allocate<TypeErrorCtor>(global); - jsObjects[URIError_Ctor] = memoryManager->allocate<URIErrorCtor>(global); + jsObjects[Object_Ctor] = memoryManager->allocate<ObjectCtor>(this); + jsObjects[String_Ctor] = memoryManager->allocate<StringCtor>(this); + jsObjects[Symbol_Ctor] = memoryManager->allocate<SymbolCtor>(this); + jsObjects[Number_Ctor] = memoryManager->allocate<NumberCtor>(this); + jsObjects[Boolean_Ctor] = memoryManager->allocate<BooleanCtor>(this); + jsObjects[Array_Ctor] = memoryManager->allocate<ArrayCtor>(this); + jsObjects[Function_Ctor] = memoryManager->allocate<FunctionCtor>(this); + jsObjects[GeneratorFunction_Ctor] = memoryManager->allocate<GeneratorFunctionCtor>(this); + jsObjects[Date_Ctor] = memoryManager->allocate<DateCtor>(this); + jsObjects[RegExp_Ctor] = memoryManager->allocate<RegExpCtor>(this); + jsObjects[Error_Ctor] = memoryManager->allocate<ErrorCtor>(this); + jsObjects[EvalError_Ctor] = memoryManager->allocate<EvalErrorCtor>(this); + jsObjects[RangeError_Ctor] = memoryManager->allocate<RangeErrorCtor>(this); + jsObjects[ReferenceError_Ctor] = memoryManager->allocate<ReferenceErrorCtor>(this); + jsObjects[SyntaxError_Ctor] = memoryManager->allocate<SyntaxErrorCtor>(this); + jsObjects[TypeError_Ctor] = memoryManager->allocate<TypeErrorCtor>(this); + jsObjects[URIError_Ctor] = memoryManager->allocate<URIErrorCtor>(this); jsObjects[IteratorProto] = memoryManager->allocate<IteratorPrototype>(); ic = newInternalClass(ForInIteratorPrototype::staticVTable(), iteratorPrototype()); @@ -663,9 +661,9 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) // url // - jsObjects[Url_Ctor] = memoryManager->allocate<UrlCtor>(global); + jsObjects[Url_Ctor] = memoryManager->allocate<UrlCtor>(this); jsObjects[UrlProto] = memoryManager->allocate<UrlPrototype>(); - jsObjects[UrlSearchParams_Ctor] = memoryManager->allocate<UrlSearchParamsCtor>(global); + jsObjects[UrlSearchParams_Ctor] = memoryManager->allocate<UrlSearchParamsCtor>(this); jsObjects[UrlSearchParamsProto] = memoryManager->allocate<UrlSearchParamsPrototype>(); str = newString(QStringLiteral("get [Symbol.species]")); @@ -703,19 +701,19 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) sequencePrototype()->cast<SequencePrototype>()->init(); - jsObjects[WeakMap_Ctor] = memoryManager->allocate<WeakMapCtor>(global); + jsObjects[WeakMap_Ctor] = memoryManager->allocate<WeakMapCtor>(this); jsObjects[WeakMapProto] = memoryManager->allocate<WeakMapPrototype>(); static_cast<WeakMapPrototype *>(weakMapPrototype())->init(this, weakMapCtor()); - jsObjects[Map_Ctor] = memoryManager->allocate<MapCtor>(global); + jsObjects[Map_Ctor] = memoryManager->allocate<MapCtor>(this); jsObjects[MapProto] = memoryManager->allocate<MapPrototype>(); static_cast<MapPrototype *>(mapPrototype())->init(this, mapCtor()); - jsObjects[WeakSet_Ctor] = memoryManager->allocate<WeakSetCtor>(global); + jsObjects[WeakSet_Ctor] = memoryManager->allocate<WeakSetCtor>(this); jsObjects[WeakSetProto] = memoryManager->allocate<WeakSetPrototype>(); static_cast<WeakSetPrototype *>(weakSetPrototype())->init(this, weakSetCtor()); - jsObjects[Set_Ctor] = memoryManager->allocate<SetCtor>(global); + jsObjects[Set_Ctor] = memoryManager->allocate<SetCtor>(this); jsObjects[SetProto] = memoryManager->allocate<SetPrototype>(); static_cast<SetPrototype *>(setPrototype())->init(this, setCtor()); @@ -723,33 +721,33 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) // promises // - jsObjects[Promise_Ctor] = memoryManager->allocate<PromiseCtor>(global); + jsObjects[Promise_Ctor] = memoryManager->allocate<PromiseCtor>(this); jsObjects[PromiseProto] = memoryManager->allocate<PromisePrototype>(); static_cast<PromisePrototype *>(promisePrototype())->init(this, promiseCtor()); // typed arrays - jsObjects[SharedArrayBuffer_Ctor] = memoryManager->allocate<SharedArrayBufferCtor>(global); + jsObjects[SharedArrayBuffer_Ctor] = memoryManager->allocate<SharedArrayBufferCtor>(this); jsObjects[SharedArrayBufferProto] = memoryManager->allocate<SharedArrayBufferPrototype>(); static_cast<SharedArrayBufferPrototype *>(sharedArrayBufferPrototype())->init(this, sharedArrayBufferCtor()); - jsObjects[ArrayBuffer_Ctor] = memoryManager->allocate<ArrayBufferCtor>(global); + jsObjects[ArrayBuffer_Ctor] = memoryManager->allocate<ArrayBufferCtor>(this); jsObjects[ArrayBufferProto] = memoryManager->allocate<ArrayBufferPrototype>(); static_cast<ArrayBufferPrototype *>(arrayBufferPrototype())->init(this, arrayBufferCtor()); - jsObjects[DataView_Ctor] = memoryManager->allocate<DataViewCtor>(global); + jsObjects[DataView_Ctor] = memoryManager->allocate<DataViewCtor>(this); jsObjects[DataViewProto] = memoryManager->allocate<DataViewPrototype>(); static_cast<DataViewPrototype *>(dataViewPrototype())->init(this, dataViewCtor()); jsObjects[ValueTypeProto] = (Heap::Base *) nullptr; jsObjects[SignalHandlerProto] = (Heap::Base *) nullptr; - jsObjects[IntrinsicTypedArray_Ctor] = memoryManager->allocate<IntrinsicTypedArrayCtor>(global); + jsObjects[IntrinsicTypedArray_Ctor] = memoryManager->allocate<IntrinsicTypedArrayCtor>(this); jsObjects[IntrinsicTypedArrayProto] = memoryManager->allocate<IntrinsicTypedArrayPrototype>(); static_cast<IntrinsicTypedArrayPrototype *>(intrinsicTypedArrayPrototype()) ->init(this, static_cast<IntrinsicTypedArrayCtor *>(intrinsicTypedArrayCtor())); for (int i = 0; i < NTypedArrayTypes; ++i) { - static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocate<TypedArrayCtor>(global, Heap::TypedArray::Type(i)); + static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocate<TypedArrayCtor>(this, Heap::TypedArray::Type(i)); static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->allocate<TypedArrayPrototype>(Heap::TypedArray::Type(i)); typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>())); } @@ -796,14 +794,14 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->allocate<MathObject>())); globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->allocate<JsonObject>())); globalObject->defineDefaultProperty(QStringLiteral("Reflect"), (o = memoryManager->allocate<Reflect>())); - globalObject->defineDefaultProperty(QStringLiteral("Proxy"), (o = memoryManager->allocate<Proxy>(rootContext()))); + globalObject->defineDefaultProperty(QStringLiteral("Proxy"), (o = memoryManager->allocate<Proxy>(this))); globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Value::undefinedValue()); globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Value::fromDouble(std::numeric_limits<double>::quiet_NaN())); globalObject->defineReadonlyProperty(QStringLiteral("Infinity"), Value::fromDouble(Q_INFINITY)); - jsObjects[Eval_Function] = memoryManager->allocate<EvalFunction>(global); + jsObjects[Eval_Function] = memoryManager->allocate<EvalFunction>(this); globalObject->defineDefaultProperty(QStringLiteral("eval"), *evalFunction()); // ES6: 20.1.2.12 & 20.1.2.13: @@ -832,7 +830,9 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) globalObject->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1); globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1); - ScopedFunctionObject t(scope, memoryManager->allocate<FunctionObject>(rootContext(), nullptr, ::throwTypeError)); + ScopedFunctionObject t( + scope, + memoryManager->allocate<DynamicFunctionObject>(this, nullptr, ::throwTypeError)); t->defineReadonlyProperty(id_length(), Value::fromInt32(0)); t->setInternalClass(t->internalClass()->cryopreserved()); jsObjects[ThrowerObject] = t; diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 35b5952d38..02145a0243 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -182,14 +182,14 @@ DEFINE_OBJECT_VTABLE(SyntaxErrorCtor); DEFINE_OBJECT_VTABLE(TypeErrorCtor); DEFINE_OBJECT_VTABLE(URIErrorCtor); -void Heap::ErrorCtor::init(QV4::ExecutionContext *scope) +void Heap::ErrorCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("Error")); + Heap::FunctionObject::init(engine, QStringLiteral("Error")); } -void Heap::ErrorCtor::init(QV4::ExecutionContext *scope, const QString &name) +void Heap::ErrorCtor::init(QV4::ExecutionEngine *engine, const QString &name) { - Heap::FunctionObject::init(scope, name); + Heap::FunctionObject::init(engine, name); } ReturnedValue ErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) @@ -203,9 +203,9 @@ ReturnedValue ErrorCtor::virtualCall(const FunctionObject *f, const Value *, con return f->callAsConstructor(argv, argc); } -void Heap::EvalErrorCtor::init(QV4::ExecutionContext *scope) +void Heap::EvalErrorCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("EvalError")); + Heap::FunctionObject::init(engine, QStringLiteral("EvalError")); } ReturnedValue EvalErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) @@ -214,9 +214,9 @@ ReturnedValue EvalErrorCtor::virtualCallAsConstructor(const FunctionObject *f, c return ErrorObject::create<EvalErrorObject>(f->engine(), v, newTarget)->asReturnedValue(); } -void Heap::RangeErrorCtor::init(QV4::ExecutionContext *scope) +void Heap::RangeErrorCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("RangeError")); + Heap::FunctionObject::init(engine, QStringLiteral("RangeError")); } ReturnedValue RangeErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) @@ -225,9 +225,9 @@ ReturnedValue RangeErrorCtor::virtualCallAsConstructor(const FunctionObject *f, return ErrorObject::create<RangeErrorObject>(f->engine(), v, newTarget)->asReturnedValue(); } -void Heap::ReferenceErrorCtor::init(QV4::ExecutionContext *scope) +void Heap::ReferenceErrorCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("ReferenceError")); + Heap::FunctionObject::init(engine, QStringLiteral("ReferenceError")); } ReturnedValue ReferenceErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) @@ -236,9 +236,9 @@ ReturnedValue ReferenceErrorCtor::virtualCallAsConstructor(const FunctionObject return ErrorObject::create<ReferenceErrorObject>(f->engine(), v, newTarget)->asReturnedValue(); } -void Heap::SyntaxErrorCtor::init(QV4::ExecutionContext *scope) +void Heap::SyntaxErrorCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("SyntaxError")); + Heap::FunctionObject::init(engine, QStringLiteral("SyntaxError")); } ReturnedValue SyntaxErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) @@ -247,9 +247,9 @@ ReturnedValue SyntaxErrorCtor::virtualCallAsConstructor(const FunctionObject *f, return ErrorObject::create<SyntaxErrorObject>(f->engine(), v, newTarget)->asReturnedValue(); } -void Heap::TypeErrorCtor::init(QV4::ExecutionContext *scope) +void Heap::TypeErrorCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("TypeError")); + Heap::FunctionObject::init(engine, QStringLiteral("TypeError")); } ReturnedValue TypeErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) @@ -258,9 +258,9 @@ ReturnedValue TypeErrorCtor::virtualCallAsConstructor(const FunctionObject *f, c return ErrorObject::create<TypeErrorObject>(f->engine(), v, newTarget)->asReturnedValue(); } -void Heap::URIErrorCtor::init(QV4::ExecutionContext *scope) +void Heap::URIErrorCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("URIError")); + Heap::FunctionObject::init(engine, QStringLiteral("URIError")); } ReturnedValue URIErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index 541f5cae36..f9adbb443b 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -79,32 +79,32 @@ struct URIErrorObject : ErrorObject { }; struct ErrorCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); - void init(QV4::ExecutionContext *scope, const QString &name); + void init(ExecutionEngine *engine); + void init(ExecutionEngine *engine, const QString &name); }; struct EvalErrorCtor : ErrorCtor { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; struct RangeErrorCtor : ErrorCtor { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; struct ReferenceErrorCtor : ErrorCtor { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; struct SyntaxErrorCtor : ErrorCtor { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; struct TypeErrorCtor : ErrorCtor { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; struct URIErrorCtor : ErrorCtor { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; } diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index ab6a34435f..153e8964e8 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -30,84 +30,58 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(FunctionObject); -void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name, - VTable::Call call, VTable::CallWithMetaTypes callWithMetaTypes) +void Heap::FunctionObject::init(QV4::ExecutionEngine *engine, QV4::String *name) { - jsCall = call; - jsCallWithMetaTypes = callWithMetaTypes; - jsConstruct = nullptr; - Object::init(); - this->scope.set(scope->engine(), scope->d()); - Scope s(scope->engine()); + Scope s(engine); ScopedFunctionObject f(s, this); if (name) f->setName(name); -} -void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name) -{ - ExecutionEngine *e = scope->engine(); - - jsCall = vtable()->call; - jsCallWithMetaTypes = vtable()->callWithMetaTypes; - jsConstruct = vtable()->callAsConstructor; - - Object::init(); - this->scope.set(scope->engine(), scope->d()); - Scope s(e); - ScopedFunctionObject f(s, this); - if (name) - f->setName(name); + isConstructor = (vtable()->callAsConstructor != QV4::FunctionObject::virtualCallAsConstructor); } - - -void Heap::FunctionObject::init(QV4::ExecutionContext *scope, Function *function, QV4::String *n) +void Heap::FunctionObject::init(QV4::ExecutionEngine *engine, const QString &name) { - jsCall = vtable()->call; - jsCallWithMetaTypes = vtable()->callWithMetaTypes; - jsConstruct = vtable()->callAsConstructor; - - Object::init(); - setFunction(function); - this->scope.set(scope->engine(), scope->d()); - Scope s(scope->engine()); - ScopedString name(s, n ? n->d() : function->name()); - ScopedFunctionObject f(s, this); - if (name) - f->setName(name); + Scope valueScope(engine); + ScopedString s(valueScope, engine->newString(name)); + init(engine, s); } -void Heap::FunctionObject::init(QV4::ExecutionContext *scope, const QString &name) +void Heap::FunctionObject::init() { - Scope valueScope(scope); - ScopedString s(valueScope, valueScope.engine->newString(name)); - init(scope, s); + init(internalClass->engine, static_cast<QV4::String *>(nullptr)); } -void Heap::FunctionObject::init() +void Heap::JavaScriptFunctionObject::init( + QV4::ExecutionContext *scope, Function *function, QV4::String *n) { - jsCall = vtable()->call; - jsCallWithMetaTypes = vtable()->callWithMetaTypes; - jsConstruct = vtable()->callAsConstructor; - - Object::init(); - this->scope.set(internalClass->engine, internalClass->engine->rootContext()->d()); + Scope s(scope->engine()); + ScopedString name(s, n ? n->d() : function->name()); + FunctionObject::init(s.engine, name); + this->scope.set(s.engine, scope->d()); + setFunction(function); } -void Heap::FunctionObject::setFunction(Function *f) +void Heap::JavaScriptFunctionObject::setFunction(Function *f) { if (f) { function = f; function->executableCompilationUnit()->addref(); } } -void Heap::FunctionObject::destroy() +void Heap::JavaScriptFunctionObject::destroy() { if (function) function->executableCompilationUnit()->release(); - Object::destroy(); + FunctionObject::destroy(); +} + +void Heap::DynamicFunctionObject::init( + QV4::ExecutionEngine *engine, QV4::String *name, VTable::Call call) +{ + FunctionObject::init(engine, name); + jsCall = call; } void FunctionObject::createDefaultPrototypeProperty(uint protoConstructorSlot) @@ -121,32 +95,37 @@ void FunctionObject::createDefaultPrototypeProperty(uint protoConstructorSlot) defineDefaultProperty(s.engine->id_prototype(), proto, Attr_NotEnumerable|Attr_NotConfigurable); } -void FunctionObject::call(QObject *thisObject, void **a, const QMetaType *types, int argc) +ReturnedValue FunctionObject::name() const { - if (const auto callWithMetaTypes = d()->jsCallWithMetaTypes) { - callWithMetaTypes(this, thisObject, a, types, argc); - return; - } + return get(engine()->id_name()); +} - QV4::convertAndCall(engine(), thisObject, a, types, argc, - [this](const Value *thisObject, const Value *argv, int argc) { - return call(thisObject, argv, argc); - }); +ReturnedValue FunctionObject::virtualCall( + const FunctionObject *f, const Value *, const Value *, int) +{ + return f->engine()->throwTypeError(QStringLiteral("Function can only be called with |new|.")); } -ReturnedValue FunctionObject::name() const +void FunctionObject::virtualCallWithMetaTypes( + const FunctionObject *f, QObject *, void **, const QMetaType *, int) { - return get(scope()->internalClass->engine->id_name()); + f->engine()->throwTypeError(QStringLiteral("Function can only be called with |new|.")); } -ReturnedValue FunctionObject::virtualCall(const FunctionObject *, const Value *, const Value *, int) +ReturnedValue FunctionObject::virtualCallAsConstructor( + const FunctionObject *f, const Value *, int, const Value *) { - return Encode::undefined(); + return f->engine()->throwTypeError(QStringLiteral("Function is not a constructor.")); } -void FunctionObject::virtualCallWithMetaTypes( - const FunctionObject *, QObject *, void **, const QMetaType *, int) +void FunctionObject::virtualConvertAndCall( + const FunctionObject *f, QObject *thisObject, + void **argv, const QMetaType *types, int argc) { + QV4::convertAndCall(f->engine(), thisObject, argv, types, argc, + [f](const Value *thisObject, const Value *argv, int argc) { + return f->call(thisObject, argv, argc); + }); } Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function) @@ -156,15 +135,20 @@ Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *sco return scope->engine()->memoryManager->allocate<ScriptFunction>(scope, function); } -Heap::FunctionObject *FunctionObject::createConstructorFunction(ExecutionContext *scope, Function *function, Object *homeObject, bool isDerivedConstructor) +Heap::FunctionObject *FunctionObject::createConstructorFunction( + ExecutionContext *scope, Function *function, Object *homeObject, bool isDerivedConstructor) { + QV4::ExecutionEngine *engine = scope->engine(); if (!function) { - Heap::DefaultClassConstructorFunction *c = scope->engine()->memoryManager->allocate<DefaultClassConstructorFunction>(scope); + Heap::DefaultClassConstructorFunction *c + = engine->memoryManager->allocate<DefaultClassConstructorFunction>(scope); c->isDerivedConstructor = isDerivedConstructor; return c; } - Heap::ConstructorFunction *c = scope->engine()->memoryManager->allocate<ConstructorFunction>(scope, function); - c->homeObject.set(scope->engine(), homeObject->d()); + + Heap::ConstructorFunction *c + = engine->memoryManager->allocate<ConstructorFunction>(scope, function); + c->homeObject.set(engine, homeObject->d()); c->isDerivedConstructor = isDerivedConstructor; return c; } @@ -183,7 +167,8 @@ Heap::FunctionObject *FunctionObject::createBuiltinFunction(ExecutionEngine *eng if (!name) name = engine->newString(QChar::fromLatin1('[') + QStringView{nameOrSymbol->toQString()}.mid(1) + QChar::fromLatin1(']')); - ScopedFunctionObject function(scope, engine->memoryManager->allocate<FunctionObject>(engine->rootContext(), name, code)); + ScopedFunctionObject function( + scope, engine->memoryManager->allocate<DynamicFunctionObject>(engine, name, code)); function->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(argumentCount)); return function->d(); } @@ -199,16 +184,29 @@ ReturnedValue FunctionObject::getHomeObject() const return Encode::undefined(); } -QQmlSourceLocation FunctionObject::sourceLocation() const +DEFINE_OBJECT_VTABLE(JavaScriptFunctionObject); + +QQmlSourceLocation JavaScriptFunctionObject::sourceLocation() const { return d()->function->sourceLocation(); } +DEFINE_OBJECT_VTABLE(DynamicFunctionObject); + +ReturnedValue DynamicFunctionObject::virtualCall( + const FunctionObject *f, const Value *thisObject, const Value *argv, int argc) { + Heap::DynamicFunctionObject *d = static_cast<const DynamicFunctionObject *>(f)->d(); + if (d->jsCall) + return d->jsCall(f, thisObject, argv, argc); + return d->internalClass->engine->throwTypeError( + QStringLiteral("Function can only be called with |new|.")); +} + DEFINE_OBJECT_VTABLE(FunctionCtor); -void Heap::FunctionCtor::init(QV4::ExecutionContext *scope) +void Heap::FunctionCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("Function")); + Heap::FunctionObject::init(engine, QStringLiteral("Function")); } // 15.3.2 @@ -311,6 +309,12 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(engine->symbol_hasInstance(), method_hasInstance, 1, Attr_ReadOnly); } +ReturnedValue FunctionPrototype::virtualCall( + const FunctionObject *, const Value *, const Value *, int) +{ + return Encode::undefined(); +} + ReturnedValue FunctionPrototype::method_toString(const FunctionObject *b, const Value *thisObject, const Value *, int) { ExecutionEngine *v4 = b->engine(); @@ -427,10 +431,7 @@ ReturnedValue FunctionPrototype::method_bind(const FunctionObject *b, const Valu boundArgs->set(scope.engine, i, argv[i + 1]); } - ScopedContext ctx(scope, target->scope()); - Scoped<BoundFunction> bound(scope, BoundFunction::create(ctx, target, boundThis, boundArgs)); - bound->d()->setFunction(target->function()); - return bound->asReturnedValue(); + return BoundFunction::create(target, boundThis, boundArgs)->asReturnedValue(); } ReturnedValue FunctionPrototype::method_hasInstance(const FunctionObject *, const Value *thisObject, const Value *argv, int argc) @@ -490,7 +491,9 @@ DEFINE_OBJECT_VTABLE(ArrowFunction); void ArrowFunction::virtualCallWithMetaTypes(const FunctionObject *fo, QObject *thisObject, void **a, const QMetaType *types, int argc) { - if (fo->function()->kind != Function::AotCompiled) { + const ArrowFunction *self = static_cast<const ArrowFunction *>(fo); + Function *function = self->function(); + if (function->kind != Function::AotCompiled) { QV4::convertAndCall(fo->engine(), thisObject, a, types, argc, [fo](const Value *thisObject, const Value *argv, int argc) { return ArrowFunction::virtualCall(fo, thisObject, argv, argc); @@ -499,16 +502,17 @@ void ArrowFunction::virtualCallWithMetaTypes(const FunctionObject *fo, QObject * } QV4::Scope scope(fo->engine()); - QV4::Scoped<ExecutionContext> context(scope, fo->scope()); + QV4::Scoped<ExecutionContext> context(scope, self->scope()); MetaTypesStackFrame frame; - frame.init(fo->function(), thisObject, context, a, types, argc); + frame.init(function, thisObject, context, a, types, argc); frame.push(scope.engine); Moth::VME::exec(&frame, scope.engine); frame.pop(scope.engine); } -static ReturnedValue qfoDoCall(const QV4::FunctionObject *fo, const QV4::Value *thisObject, - const QV4::Value *argv, int argc) +static ReturnedValue qfoDoCall( + const QV4::JavaScriptFunctionObject *fo, const QV4::Value *thisObject, + const QV4::Value *argv, int argc) { ExecutionEngine *engine = fo->engine(); JSTypesStackFrame frame; @@ -535,7 +539,8 @@ static ReturnedValue qfoDoCall(const QV4::FunctionObject *fo, const QV4::Value * ReturnedValue ArrowFunction::virtualCall(const QV4::FunctionObject *fo, const Value *thisObject, const QV4::Value *argv, int argc) { - Function *function = fo->function(); + const ArrowFunction *self = static_cast<const ArrowFunction *>(fo); + Function *function = self->function(); switch (function->kind) { case Function::AotCompiled: return QV4::convertAndCall( @@ -546,31 +551,22 @@ ReturnedValue ArrowFunction::virtualCall(const QV4::FunctionObject *fo, const Va case Function::JsTyped: return QV4::coerceAndCall( fo->engine(), &function->jsTypedFunction, function->compiledFunction, argv, argc, - [fo, thisObject](const Value *argv, int argc) { - return qfoDoCall(fo, thisObject, argv, argc); + [self, thisObject](const Value *argv, int argc) { + return qfoDoCall(self, thisObject, argv, argc); }); default: break; } - return qfoDoCall(fo, thisObject, argv, argc); + return qfoDoCall(self, thisObject, argv, argc); } void Heap::ArrowFunction::init(QV4::ExecutionContext *scope, Function *function, QV4::String *n) { - FunctionObject::init(); - this->scope.set(scope->engine(), scope->d()); - - setFunction(function); Q_ASSERT(function); + JavaScriptFunctionObject::init(scope, function, n); Scope s(scope); - ScopedFunctionObject f(s, this); - - ScopedString name(s, n ? n->d() : function->name()); - if (name) - f->setName(name); - Q_ASSERT(internalClass && internalClass->verifyIndex(s.engine->id_length()->propertyKey(), Index_Length)); setProperty(s.engine, Index_Length, Value::fromInt32(int(function->compiledFunction->length))); canBeTailCalled = true; @@ -586,6 +582,13 @@ void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_ProtoConstructor); } +void Heap::DefaultClassConstructorFunction::init(QV4::ExecutionContext *scope) +{ + Scope s(scope->engine()); + FunctionObject::init(s.engine, nullptr); + this->scope.set(s.engine, scope->d()); +} + Heap::InternalClass *ScriptFunction::classForConstructor() const { Scope scope(engine()); @@ -613,8 +616,8 @@ ReturnedValue ConstructorFunction::virtualCallAsConstructor(const FunctionObject ExecutionEngine *v4 = f->engine(); JSTypesStackFrame frame; - frame.init(f->function(), argv, argc); - frame.setupJSFrame(v4->jsStackTop, *f, f->scope(), + frame.init(c->function(), argv, argc); + frame.setupJSFrame(v4->jsStackTop, *f, c->scope(), Value::emptyValue(), newTarget ? *newTarget : Value::undefinedValue()); @@ -668,7 +671,7 @@ ReturnedValue DefaultClassConstructorFunction::virtualCallAsConstructor(const Fu JSTypesStackFrame frame; frame.init(nullptr, argv, argc); - frame.setupJSFrame(v4->jsStackTop, *f, f->scope(), + frame.setupJSFrame(v4->jsStackTop, *f, c->scope(), Value::undefinedValue(), newTarget ? *newTarget : Value::undefinedValue(), argc, argc); @@ -705,33 +708,41 @@ DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction); DEFINE_OBJECT_VTABLE(BoundFunction); -void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject *target, - const Value &boundThis, QV4::MemberData *boundArgs) +void Heap::BoundFunction::init( + QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs) { - Scope s(scope); - Heap::FunctionObject::init(scope, QStringLiteral("__bound function__")); + ExecutionEngine *engine = target->engine(); + Scope s(engine); + ScopedString name(s, engine->newString(QStringLiteral("__bound function__"))); + if (auto *js = target->as<QV4::JavaScriptFunctionObject>()) { + ScopedContext ctx(s, js->scope()); + JavaScriptFunctionObject::init(ctx, js->function(), name); + } else { + JavaScriptFunctionObject::init(engine->rootContext(), nullptr, name); + } + this->target.set(s.engine, target->d()); this->boundArgs.set(s.engine, boundArgs ? boundArgs->d() : nullptr); - this->boundThis.set(scope->engine(), boundThis); + this->boundThis.set(s.engine, boundThis); if (!target->isConstructor()) - jsConstruct = nullptr; + isConstructor = false; ScopedObject f(s, this); - ScopedValue l(s, target->get(s.engine->id_length())); + ScopedValue l(s, target->get(engine->id_length())); int len = l->toUInt32(); if (boundArgs) len -= boundArgs->size(); if (len < 0) len = 0; - f->defineReadonlyConfigurableProperty(s.engine->id_length(), Value::fromInt32(len)); + f->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(len)); ScopedProperty pd(s); - pd->value = s.engine->thrower(); - pd->set = s.engine->thrower(); - f->insertMember(s.engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); - f->insertMember(s.engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); + pd->value = engine->thrower(); + pd->set = engine->thrower(); + f->insertMember(engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); + f->insertMember(engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); } ReturnedValue BoundFunction::virtualCall(const FunctionObject *fo, const Value *, const Value *argv, int argc) diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 573848f62a..a6b5d34cba 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -28,36 +28,44 @@ namespace QV4 { struct IndexedBuiltinFunction; struct JSCallData; -namespace Heap { +// A FunctionObject is generally something that can be called, either with a JavaScript +// signature (QV4::Value etc) or with a C++ signature (QMetaType etc). For this, it has +// the Call and CallWithMetaTypes VTable entries. +// Some FunctionObjects need to select the actual implementation of the call at run time. +// This comese in two flavors: +// 1. The implementation is a JavaScript function. For these we have +// JavaScriptFunctionObject that holds a QV4::Function member to defer the call to. +// 2. The implementation is a C++ function. For these we have DynamicFunctionObject that +// holds another Call member in the heap object to defer the call to. +// In addition, a FunctionObject may want to be called as constructor. For this we have +// another VTable entry and a flag in the heap object. +namespace Heap { #define FunctionObjectMembers(class, Member) \ - Member(class, Pointer, ExecutionContext *, scope) \ - Member(class, NoMark, Function *, function) \ - Member(class, NoMark, VTable::Call, jsCall) \ - Member(class, NoMark, VTable::CallAsConstructor, jsConstruct) \ - Member(class, NoMark, VTable::CallWithMetaTypes, jsCallWithMetaTypes) \ + Member(class, NoMark, bool, isConstructor) \ Member(class, NoMark, bool, canBeTailCalled) DECLARE_HEAP_OBJECT(FunctionObject, Object) { - DECLARE_MARKOBJECTS(FunctionObject) enum { Index_ProtoConstructor = 0, Index_Prototype = 0, Index_HasInstance = 1, }; - bool isConstructor() const { - return jsConstruct != nullptr; - } - - Q_QML_EXPORT void init( - QV4::ExecutionContext *scope, QV4::String *name, - VTable::Call call, VTable::CallWithMetaTypes callWithMetaTypes = nullptr); - Q_QML_EXPORT void init(QV4::ExecutionContext *scope, QV4::String *name = nullptr); - Q_QML_EXPORT void init(QV4::ExecutionContext *scope, QV4::Function *function, QV4::String *n = nullptr); - Q_QML_EXPORT void init(QV4::ExecutionContext *scope, const QString &name); + Q_QML_EXPORT void init(QV4::ExecutionEngine *engine, QV4::String *name = nullptr); + Q_QML_EXPORT void init(QV4::ExecutionEngine *engine, const QString &name); Q_QML_EXPORT void init(); +}; + +#define JavaScriptFunctionObjectMembers(class, Member) \ + Member(class, Pointer, ExecutionContext *, scope) \ + Member(class, NoMark, Function *, function) + +DECLARE_HEAP_OBJECT(JavaScriptFunctionObject, FunctionObject) { + DECLARE_MARKOBJECTS(JavaScriptFunctionObject) + + void init(QV4::ExecutionContext *scope, QV4::Function *function, QV4::String *n = nullptr); Q_QML_EXPORT void destroy(); void setFunction(Function *f); @@ -66,8 +74,18 @@ DECLARE_HEAP_OBJECT(FunctionObject, Object) { unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; } }; +#define DynamicFunctionObjectMembers(class, Member) \ + Member(class, NoMark, VTable::Call, jsCall) + +DECLARE_HEAP_OBJECT(DynamicFunctionObject, FunctionObject) { + // NB: We might add a CallWithMetaTypes member to this struct and implement our + // builtins with metatypes, to be called from C++ code. This would make them + // available to qmlcachegen's C++ code generation. + void init(ExecutionEngine *engine, QV4::String *name, VTable::Call call); +}; + struct FunctionCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(QV4::ExecutionEngine *engine); }; struct FunctionPrototype : FunctionObject { @@ -76,12 +94,12 @@ struct FunctionPrototype : FunctionObject { // A function object with an additional index into a list. // Used by Models to refer to property roles. -struct IndexedBuiltinFunction : FunctionObject { - inline void init(QV4::ExecutionContext *scope, qsizetype index, VTable::Call call); +struct IndexedBuiltinFunction : DynamicFunctionObject { + inline void init(QV4::ExecutionEngine *engine, qsizetype index, VTable::Call call); qsizetype index; }; -struct ArrowFunction : FunctionObject { +struct ArrowFunction : JavaScriptFunctionObject { enum { Index_Name = Index_HasInstance + 1, Index_Length @@ -116,9 +134,15 @@ DECLARE_HEAP_OBJECT(ConstructorFunction, ScriptFunction) { bool isDerivedConstructor; }; -struct DefaultClassConstructorFunction : FunctionObject -{ +#define DefaultClassConstructorFunctionMembers(class, Member) \ + Member(class, Pointer, ExecutionContext *, scope) + +DECLARE_HEAP_OBJECT(DefaultClassConstructorFunction, FunctionObject) { + DECLARE_MARKOBJECTS(DefaultClassConstructorFunction) + bool isDerivedConstructor; + + void init(QV4::ExecutionContext *scope); }; #define BoundFunctionMembers(class, Member) \ @@ -126,10 +150,10 @@ struct DefaultClassConstructorFunction : FunctionObject Member(class, HeapValue, HeapValue, boundThis) \ Member(class, Pointer, MemberData *, boundArgs) -DECLARE_HEAP_OBJECT(BoundFunction, FunctionObject) { +DECLARE_HEAP_OBJECT(BoundFunction, JavaScriptFunctionObject) { DECLARE_MARKOBJECTS(BoundFunction) - void init(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs); + void init(QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs); }; } @@ -142,50 +166,55 @@ struct Q_QML_EXPORT FunctionObject: Object { Q_MANAGED_TYPE(FunctionObject) V4_INTERNALCLASS(FunctionObject) V4_PROTOTYPE(functionPrototype) - V4_NEEDS_DESTROY enum { NInlineProperties = 1 }; bool canBeTailCalled() const { return d()->canBeTailCalled; } - Heap::ExecutionContext *scope() const { return d()->scope; } - Function *function() const { return d()->function; } ReturnedValue name() const; - unsigned int formalParameterCount() const { return d()->formalParameterCount(); } - unsigned int varCount() const { return d()->varCount(); } void setName(String *name) { defineReadonlyConfigurableProperty(engine()->id_name(), *name); } void createDefaultPrototypeProperty(uint protoConstructorSlot); - inline ReturnedValue callAsConstructor(const JSCallData &data) const; - ReturnedValue callAsConstructor(const Value *argv, int argc, const Value *newTarget = nullptr) const { - if (!d()->jsConstruct) - return engine()->throwTypeError(QStringLiteral("Function is not a constructor.")); - return d()->jsConstruct(this, argv, argc, newTarget ? newTarget : this); + ReturnedValue callAsConstructor( + const Value *argv, int argc, const Value *newTarget = nullptr) const + { + return vtable()->callAsConstructor(this, argv, argc, newTarget ? newTarget : this); } - inline ReturnedValue call(const JSCallData &data) const; - ReturnedValue call(const Value *thisObject, const Value *argv, int argc) const { - if (!d()->jsCall) - return engine()->throwTypeError(QStringLiteral("Function can only be called with |new|.")); - return d()->jsCall(this, thisObject, argv, argc); + + ReturnedValue call(const Value *thisObject, const Value *argv, int argc) const + { + return vtable()->call(this, thisObject, argv, argc); } - static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); - void call(QObject *thisObject, void **a, const QMetaType *types, int argc); - static void virtualCallWithMetaTypes(const FunctionObject *f, QObject *thisObject, - void **a, const QMetaType *types, int argc); + + void call(QObject *thisObject, void **argv, const QMetaType *types, int argc) const + { + vtable()->callWithMetaTypes(this, thisObject, argv, types, argc); + } + + inline ReturnedValue callAsConstructor(const JSCallData &data) const; + inline ReturnedValue call(const JSCallData &data) const; + + static ReturnedValue virtualCall( + const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); + static void virtualCallWithMetaTypes( + const FunctionObject *f, QObject *thisObject, + void **argv, const QMetaType *types, int argc); + static ReturnedValue virtualCallAsConstructor( + const FunctionObject *f, const Value *argv, int argc, const Value *newTarget); + static void virtualConvertAndCall( + const FunctionObject *f, QObject *thisObject, + void **argv, const QMetaType *types, int argc); static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function); static Heap::FunctionObject *createConstructorFunction(ExecutionContext *scope, Function *function, Object *homeObject, bool isDerivedConstructor); static Heap::FunctionObject *createMemberFunction(ExecutionContext *scope, Function *function, Object *homeObject, String *name); static Heap::FunctionObject *createBuiltinFunction(ExecutionEngine *engine, StringOrSymbol *nameOrSymbol, VTable::Call code, int argumentCount); - bool strictMode() const { return d()->function ? d()->function->isStrict() : false; } bool isBinding() const; bool isBoundFunction() const; - bool isConstructor() const { - return d()->isConstructor(); - } + bool isConstructor() const { return d()->isConstructor; } ReturnedValue getHomeObject() const; @@ -195,8 +224,6 @@ struct Q_QML_EXPORT FunctionObject: Object { bool hasHasInstanceProperty() const { return !internalClass()->propertyData.at(Heap::FunctionObject::Index_HasInstance).isEmpty(); } - - QQmlSourceLocation sourceLocation() const; }; template<> @@ -204,6 +231,27 @@ inline const FunctionObject *Value::as() const { return isManaged() && m()->internalClass->vtable->isFunctionObject ? reinterpret_cast<const FunctionObject *>(this) : nullptr; } +struct Q_QML_EXPORT JavaScriptFunctionObject: FunctionObject +{ + V4_OBJECT2(JavaScriptFunctionObject, FunctionObject) + V4_NEEDS_DESTROY + + Heap::ExecutionContext *scope() const { return d()->scope; } + + Function *function() const { return d()->function; } + unsigned int formalParameterCount() const { return d()->formalParameterCount(); } + unsigned int varCount() const { return d()->varCount(); } + bool strictMode() const { return d()->function ? d()->function->isStrict() : false; } + QQmlSourceLocation sourceLocation() const; +}; + +struct Q_QML_EXPORT DynamicFunctionObject: FunctionObject +{ + V4_OBJECT2(DynamicFunctionObject, FunctionObject) + + static ReturnedValue virtualCall( + const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); +}; struct FunctionCtor: FunctionObject { @@ -225,6 +273,9 @@ struct FunctionPrototype: FunctionObject void init(ExecutionEngine *engine, Object *ctor); + static ReturnedValue virtualCall( + const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); + static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_apply(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_call(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); @@ -232,21 +283,21 @@ struct FunctionPrototype: FunctionObject static ReturnedValue method_hasInstance(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); }; -struct Q_QML_EXPORT IndexedBuiltinFunction : FunctionObject +struct Q_QML_EXPORT IndexedBuiltinFunction : DynamicFunctionObject { - V4_OBJECT2(IndexedBuiltinFunction, FunctionObject) + V4_OBJECT2(IndexedBuiltinFunction, DynamicFunctionObject) }; void Heap::IndexedBuiltinFunction::init( - QV4::ExecutionContext *scope, qsizetype index, VTable::Call call) + QV4::ExecutionEngine *engine, qsizetype index, VTable::Call call) { - Heap::FunctionObject::init(scope); + Heap::FunctionObject::init(engine); this->jsCall = call; this->index = index; } -struct ArrowFunction : FunctionObject { - V4_OBJECT2(ArrowFunction, FunctionObject) +struct ArrowFunction : JavaScriptFunctionObject { + V4_OBJECT2(ArrowFunction, JavaScriptFunctionObject) V4_INTERNALCLASS(ArrowFunction) enum { NInlineProperties = 3 }; @@ -279,16 +330,20 @@ struct ConstructorFunction : ScriptFunction { struct DefaultClassConstructorFunction : FunctionObject { V4_OBJECT2(DefaultClassConstructorFunction, FunctionObject) + + Heap::ExecutionContext *scope() const { return d()->scope; } static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *); static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); }; -struct BoundFunction: FunctionObject { - V4_OBJECT2(BoundFunction, FunctionObject) +struct BoundFunction: JavaScriptFunctionObject { + V4_OBJECT2(BoundFunction, JavaScriptFunctionObject) - static Heap::BoundFunction *create(ExecutionContext *scope, FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs) + static Heap::BoundFunction *create( + FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs) { - return scope->engine()->memoryManager->allocate<BoundFunction>(scope, target, boundThis, boundArgs); + return target->engine()->memoryManager->allocate<BoundFunction>( + target, boundThis, boundArgs); } Heap::FunctionObject *target() const { return d()->target; } diff --git a/src/qml/jsruntime/qv4generatorobject.cpp b/src/qml/jsruntime/qv4generatorobject.cpp index e7a63ba185..f2d7dffde5 100644 --- a/src/qml/jsruntime/qv4generatorobject.cpp +++ b/src/qml/jsruntime/qv4generatorobject.cpp @@ -13,9 +13,9 @@ DEFINE_OBJECT_VTABLE(GeneratorFunctionCtor); DEFINE_OBJECT_VTABLE(GeneratorFunction); DEFINE_OBJECT_VTABLE(GeneratorObject); -void Heap::GeneratorFunctionCtor::init(QV4::ExecutionContext *scope) +void Heap::GeneratorFunctionCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("GeneratorFunction")); + Heap::FunctionObject::init(engine, QStringLiteral("GeneratorFunction")); } ReturnedValue GeneratorFunctionCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) diff --git a/src/qml/jsruntime/qv4generatorobject_p.h b/src/qml/jsruntime/qv4generatorobject_p.h index 55ccc133aa..cb2c1962c5 100644 --- a/src/qml/jsruntime/qv4generatorobject_p.h +++ b/src/qml/jsruntime/qv4generatorobject_p.h @@ -33,7 +33,7 @@ enum class GeneratorState { namespace Heap { struct GeneratorFunctionCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; struct GeneratorFunction : ArrowFunction { diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index d15fb356c4..e3fc0ac1b3 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -80,6 +80,7 @@ namespace Heap { struct ArrayObject; struct DateObject; struct FunctionObject; + struct JavaScriptFunctionObject; struct ErrorObject; struct ArgumentsObject; struct QObjectWrapper; diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index 37548ffc9f..989de0de23 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -290,10 +290,10 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok) DEFINE_OBJECT_VTABLE(EvalFunction); -void Heap::EvalFunction::init(QV4::ExecutionContext *scope) +void Heap::EvalFunction::init(QV4::ExecutionEngine *engine) { - Scope s(scope); - Heap::FunctionObject::init(scope, s.engine->id_eval()); + Scope s(engine); + Heap::FunctionObject::init(engine, s.engine->id_eval()); ScopedFunctionObject f(s, this); f->defineReadonlyConfigurableProperty(s.engine->id_length(), Value::fromInt32(1)); } diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h index 71e06ef417..fd23d71332 100644 --- a/src/qml/jsruntime/qv4globalobject_p.h +++ b/src/qml/jsruntime/qv4globalobject_p.h @@ -24,7 +24,7 @@ namespace QV4 { namespace Heap { struct EvalFunction : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; } diff --git a/src/qml/jsruntime/qv4mapobject.cpp b/src/qml/jsruntime/qv4mapobject.cpp index 4bb9617b93..b927efd685 100644 --- a/src/qml/jsruntime/qv4mapobject.cpp +++ b/src/qml/jsruntime/qv4mapobject.cpp @@ -12,14 +12,14 @@ DEFINE_OBJECT_VTABLE(WeakMapCtor); DEFINE_OBJECT_VTABLE(MapCtor); DEFINE_OBJECT_VTABLE(MapObject); -void Heap::WeakMapCtor::init(QV4::ExecutionContext *scope) +void Heap::WeakMapCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("WeakMap")); + Heap::FunctionObject::init(engine, QStringLiteral("WeakMap")); } -void Heap::MapCtor::init(QV4::ExecutionContext *scope) +void Heap::MapCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("Map")); + Heap::FunctionObject::init(engine, QStringLiteral("Map")); } ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget, bool weakMap) diff --git a/src/qml/jsruntime/qv4mapobject_p.h b/src/qml/jsruntime/qv4mapobject_p.h index 68bc7ceed8..b5eeb68b0c 100644 --- a/src/qml/jsruntime/qv4mapobject_p.h +++ b/src/qml/jsruntime/qv4mapobject_p.h @@ -27,11 +27,11 @@ class ESTable; namespace Heap { struct WeakMapCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; struct MapCtor : WeakMapCtor { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; struct MapObject : Object { diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index d744e569f5..5299a2568a 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -36,9 +36,9 @@ const NumberLocale *NumberLocale::instance() return numberLocaleHolder(); } -void Heap::NumberCtor::init(QV4::ExecutionContext *scope) +void Heap::NumberCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("Number")); + Heap::FunctionObject::init(engine, QStringLiteral("Number")); } ReturnedValue NumberCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h index 8ac2bd1f79..3f0d6d9425 100644 --- a/src/qml/jsruntime/qv4numberobject_p.h +++ b/src/qml/jsruntime/qv4numberobject_p.h @@ -25,7 +25,7 @@ namespace QV4 { namespace Heap { struct NumberCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; } diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index e7f96a12ba..2a78bb4540 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -19,9 +19,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ObjectCtor); -void Heap::ObjectCtor::init(QV4::ExecutionContext *scope) +void Heap::ObjectCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("Object")); + Heap::FunctionObject::init(engine, QStringLiteral("Object")); } ReturnedValue ObjectCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h index d152bfd175..d74cd64926 100644 --- a/src/qml/jsruntime/qv4objectproto_p.h +++ b/src/qml/jsruntime/qv4objectproto_p.h @@ -25,7 +25,7 @@ namespace QV4 { namespace Heap { struct ObjectCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; } diff --git a/src/qml/jsruntime/qv4promiseobject.cpp b/src/qml/jsruntime/qv4promiseobject.cpp index 16cffea124..b8ede3e578 100644 --- a/src/qml/jsruntime/qv4promiseobject.cpp +++ b/src/qml/jsruntime/qv4promiseobject.cpp @@ -314,9 +314,9 @@ void Heap::PromiseReaction::triggerWithValue(ExecutionEngine *e, const Value *va handler->addReaction(e, reaction, value); } -void Heap::PromiseCtor::init(QV4::ExecutionContext *scope) +void Heap::PromiseCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("Promise")); + Heap::FunctionObject::init(engine, QStringLiteral("Promise")); } void Heap::PromiseObject::init(ExecutionEngine *e) diff --git a/src/qml/jsruntime/qv4promiseobject_p.h b/src/qml/jsruntime/qv4promiseobject_p.h index ca31f00881..fbde9f95e0 100644 --- a/src/qml/jsruntime/qv4promiseobject_p.h +++ b/src/qml/jsruntime/qv4promiseobject_p.h @@ -50,7 +50,7 @@ protected: namespace Heap { struct PromiseCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; #define PromiseObjectMembers(class, Member) \ diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp index 109ab61059..892fa1e00c 100644 --- a/src/qml/jsruntime/qv4proxy.cpp +++ b/src/qml/jsruntime/qv4proxy.cpp @@ -25,12 +25,12 @@ void Heap::ProxyObject::init(const QV4::Object *target, const QV4::Object *handl void Heap::ProxyFunctionObject::init(const QV4::FunctionObject *target, const QV4::Object *handler) { ExecutionEngine *e = internalClass->engine; - FunctionObject::init(e->rootContext()); + FunctionObject::init(e); this->target.set(e, target->d()); this->handler.set(e, handler->d()); if (!target->isConstructor()) - jsConstruct = nullptr; + isConstructor = false; } @@ -658,10 +658,8 @@ ReturnedValue ProxyFunctionObject::virtualCallAsConstructor(const FunctionObject if (scope.hasException()) return Encode::undefined(); - if (trap->isNullOrUndefined()) { - Q_ASSERT(target->isConstructor()); + if (trap->isNullOrUndefined()) return target->callAsConstructor(argv, argc, newTarget); - } if (!trap->isFunctionObject()) return scope.engine->throwTypeError(); @@ -708,11 +706,11 @@ ReturnedValue ProxyFunctionObject::virtualCall(const FunctionObject *f, const Va DEFINE_OBJECT_VTABLE(Proxy); -void Heap::Proxy::init(QV4::ExecutionContext *ctx) +void Heap::Proxy::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(ctx, QStringLiteral("Proxy")); + Heap::FunctionObject::init(engine, QStringLiteral("Proxy")); - Scope scope(ctx); + Scope scope(engine); Scoped<QV4::Proxy> ctor(scope, this); ctor->defineDefaultProperty(QStringLiteral("revocable"), QV4::Proxy::method_revocable, 2); ctor->defineReadonlyConfigurableProperty(scope.engine->id_length(), Value::fromInt32(2)); @@ -753,7 +751,10 @@ ReturnedValue Proxy::method_revocable(const FunctionObject *f, const Value *, co Q_ASSERT(proxy); ScopedString revoke(scope, scope.engine->newString(QStringLiteral("revoke"))); - ScopedFunctionObject revoker(scope, scope.engine->memoryManager->allocate<FunctionObject>(scope.engine->rootContext(), nullptr, method_revoke)); + ScopedFunctionObject revoker( + scope, + scope.engine->memoryManager->allocate<DynamicFunctionObject>( + scope.engine, nullptr, method_revoke)); revoker->defineReadonlyConfigurableProperty(scope.engine->id_length(), Value::fromInt32(0)); revoker->defineDefaultProperty(scope.engine->symbol_revokableProxy(), proxy); diff --git a/src/qml/jsruntime/qv4proxy_p.h b/src/qml/jsruntime/qv4proxy_p.h index b3be05a11b..8207838e6d 100644 --- a/src/qml/jsruntime/qv4proxy_p.h +++ b/src/qml/jsruntime/qv4proxy_p.h @@ -43,7 +43,7 @@ struct ProxyFunctionObject : ProxyObject { DECLARE_HEAP_OBJECT(Proxy, FunctionObject) { DECLARE_MARKOBJECTS(Proxy) - void init(QV4::ExecutionContext *ctx); + void init(ExecutionEngine *engine); }; } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 5f85aae89e..2edeb54b11 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -360,20 +360,15 @@ ReturnedValue QObjectWrapper::getProperty( Q_ASSERT(vmemo); return vmemo->vmeMethod(property->coreIndex()); } else if (property->isV4Function()) { - Scope scope(engine); - ScopedContext global(scope, engine->qmlContext()); - if (!global) - global = engine->rootContext(); return QObjectMethod::create( - global, (flags & AttachMethods) ? wrapper : nullptr, property->coreIndex()); + engine, (flags & AttachMethods) ? wrapper : nullptr, property->coreIndex()); } else if (property->isSignalHandler()) { QmlSignalHandler::initProto(engine); return engine->memoryManager->allocate<QmlSignalHandler>( object, property->coreIndex())->asReturnedValue(); } else { - ExecutionContext *global = engine->rootContext(); return QObjectMethod::create( - global, (flags & AttachMethods) ? wrapper : nullptr, property->coreIndex()); + engine, (flags & AttachMethods) ? wrapper : nullptr, property->coreIndex()); } } @@ -405,8 +400,7 @@ static OptionalReturnedValue getDestroyOrToStringMethod( if (hasProperty) *hasProperty = true; - ExecutionContext *global = v4->rootContext(); - return OptionalReturnedValue(QObjectMethod::create(global, qobj, index)); + return OptionalReturnedValue(QObjectMethod::create(v4, qobj, index)); } static OptionalReturnedValue getPropertyFromImports( @@ -641,7 +635,7 @@ void QObjectWrapper::setProperty( QQmlRefPointer<QQmlContextData> callingQmlContext = scope.engine->callingQmlContext(); Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f); - ScopedFunctionObject f(scope, bindingFunction->bindingFunction()); + Scoped<JavaScriptFunctionObject> f(scope, bindingFunction->bindingFunction()); ScopedContext ctx(scope, f->scope()); // binding assignment. @@ -2559,21 +2553,22 @@ ReturnedValue CallArgument::toValue(ExecutionEngine *engine) return Encode::undefined(); } -ReturnedValue QObjectMethod::create(ExecutionContext *scope, Heap::Object *wrapper, int index) +ReturnedValue QObjectMethod::create(ExecutionEngine *engine, Heap::Object *wrapper, int index) { - Scope valueScope(scope); + Scope valueScope(engine); Scoped<QObjectMethod> method( valueScope, - valueScope.engine->memoryManager->allocate<QObjectMethod>(scope, wrapper, index)); + engine->memoryManager->allocate<QObjectMethod>(engine, wrapper, index)); return method.asReturnedValue(); } -ReturnedValue QObjectMethod::create(ExecutionContext *scope, Heap::QQmlValueTypeWrapper *valueType, int index) +ReturnedValue QObjectMethod::create( + ExecutionEngine *engine, Heap::QQmlValueTypeWrapper *valueType, int index) { - Scope valueScope(scope); + Scope valueScope(engine); Scoped<QObjectMethod> method( valueScope, - valueScope.engine->memoryManager->allocate<QObjectMethod>(scope, valueType, index)); + engine->memoryManager->allocate<QObjectMethod>(engine, valueType, index)); return method.asReturnedValue(); } @@ -2596,11 +2591,10 @@ ReturnedValue QObjectMethod::create( } } - Scoped<ExecutionContext> context(valueScope, cloneFrom->scope.get()); Scoped<QObjectMethod> method( valueScope, engine->memoryManager->allocate<QV4::QObjectMethod>( - context, valueTypeWrapper ? valueTypeWrapper->d() : object, cloneFrom->index)); + engine, valueTypeWrapper ? valueTypeWrapper->d() : object, cloneFrom->index)); method->d()->methodCount = cloneFrom->methodCount; @@ -2626,10 +2620,10 @@ ReturnedValue QObjectMethod::create( return method.asReturnedValue(); } -void Heap::QObjectMethod::init(QV4::ExecutionContext *scope, Object *object, int methodIndex) +void Heap::QObjectMethod::init(QV4::ExecutionEngine *engine, Object *object, int methodIndex) { - Heap::FunctionObject::init(scope); - wrapper.set(internalClass->engine, object); + Heap::FunctionObject::init(engine); + wrapper.set(engine, object); index = methodIndex; } @@ -3106,7 +3100,7 @@ ReturnedValue QmlSignalHandler::call(const Value *thisObject, const Value *argv, Scope scope(engine()); Scoped<QObjectMethod> method( scope, QObjectMethod::create( - scope.engine->rootContext(), + scope.engine, static_cast<Heap::QObjectWrapper *>(nullptr), signalIndex())); diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 1af8fc887f..288585f844 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -72,7 +72,7 @@ DECLARE_EXPORTED_HEAP_OBJECT(QObjectMethod, FunctionObject) { int methodCount; int index; - void init(QV4::ExecutionContext *scope, Object *wrapper, int index); + void init(QV4::ExecutionEngine *engine, Object *wrapper, int index); void destroy() { if (methods != reinterpret_cast<const QQmlPropertyData *>(&_singleMethod)) @@ -348,10 +348,11 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject enum { DestroyMethod = -1, ToStringMethod = -2 }; - static ReturnedValue create(QV4::ExecutionContext *scope, Heap::Object *wrapper, int index); + static ReturnedValue create(ExecutionEngine *engine, Heap::Object *wrapper, int index); static ReturnedValue create( - QV4::ExecutionContext *scope, Heap::QQmlValueTypeWrapper *valueType, int index); - static ReturnedValue create(QV4::ExecutionEngine *engine, Heap::QObjectMethod *cloneFrom, + ExecutionEngine *engine, Heap::QQmlValueTypeWrapper *valueType, int index); + static ReturnedValue create( + ExecutionEngine *engine, Heap::QObjectMethod *cloneFrom, Heap::Object *wrapper, Heap::Object *object); int methodIndex() const { return d()->index; } diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index acb9f0acfc..144cd39bcd 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -195,9 +195,9 @@ ReturnedValue RegExpObject::builtinExec(ExecutionEngine *engine, const String *s DEFINE_OBJECT_VTABLE(RegExpCtor); -void Heap::RegExpCtor::init(QV4::ExecutionContext *scope) +void Heap::RegExpCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("RegExp")); + Heap::FunctionObject::init(engine, QStringLiteral("RegExp")); clearLastMatch(); } diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index 8d52300013..179a01fb45 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -50,7 +50,7 @@ DECLARE_HEAP_OBJECT(RegExpObject, Object) { DECLARE_HEAP_OBJECT(RegExpCtor, FunctionObject) { DECLARE_MARKOBJECTS(RegExpCtor) - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); void clearLastMatch(); }; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index c51c94ffe4..2b1fb8f3b6 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1029,7 +1029,7 @@ ReturnedValue Runtime::LoadName::call(ExecutionEngine *engine, int nameIndex) static Object *getSuperBase(Scope &scope) { - ScopedFunctionObject f(scope); + Scoped<JavaScriptFunctionObject> f(scope); ScopedObject homeObject(scope); if (scope.engine->currentStackFrame->isJSTypesFrame()) { JSTypesStackFrame *frame = static_cast<JSTypesStackFrame *>( @@ -1188,7 +1188,7 @@ ReturnedValue Runtime::LoadSuperConstructor::call(ExecutionEngine *engine, const if (!f) return engine->throwTypeError(); Heap::Object *c = static_cast<const Object &>(t).getPrototypeOf(); - if (!c->vtable()->isFunctionObject || !static_cast<Heap::FunctionObject *>(c)->isConstructor()) + if (!c->vtable()->isFunctionObject || !static_cast<Heap::FunctionObject *>(c)->isConstructor) return engine->throwTypeError(); return c->asReturnedValue(); } @@ -1627,20 +1627,23 @@ ReturnedValue Runtime::TailCall::call(JSTypesStackFrame *frame, ExecutionEngine int argc = tos[StackOffsets::tailCall_argc].int_32(); Q_ASSERT(argc >= 0); - if (!function.isFunctionObject()) + const JavaScriptFunctionObject *jsfo = function.as<JavaScriptFunctionObject>(); + if (!jsfo) { + if (const FunctionObject *fo = function.as<FunctionObject>()) + return checkedResult(engine, fo->call(&thisObject, argv, argc)); return engine->throwTypeError(); + } - const FunctionObject &fo = static_cast<const FunctionObject &>(function); - if (!frame->callerCanHandleTailCall() || !fo.canBeTailCalled() || engine->debugger() - || unsigned(argc) > fo.formalParameterCount()) { + if (!frame->callerCanHandleTailCall() || !jsfo->canBeTailCalled() || engine->debugger() + || unsigned(argc) > jsfo->formalParameterCount()) { // Cannot tailcall, do a normal call: - return checkedResult(engine, fo.call(&thisObject, argv, argc)); + return checkedResult(engine, jsfo->call(&thisObject, argv, argc)); } memmove(frame->jsFrame->args, argv, argc * sizeof(Value)); - frame->init(fo.function(), frame->jsFrame->argValues<Value>(), argc, + frame->init(jsfo->function(), frame->jsFrame->argValues<Value>(), argc, frame->callerCanHandleTailCall()); - frame->setupJSFrame(frame->framePointer(), fo, fo.scope(), thisObject, + frame->setupJSFrame(frame->framePointer(), *jsfo, jsfo->scope(), thisObject, Primitive::undefinedValue()); engine->jsStackTop = frame->framePointer() + frame->requiredJSStackFrameSize(); frame->setPendingTailCall(true); diff --git a/src/qml/jsruntime/qv4setobject.cpp b/src/qml/jsruntime/qv4setobject.cpp index a7589a40db..e182015a32 100644 --- a/src/qml/jsruntime/qv4setobject.cpp +++ b/src/qml/jsruntime/qv4setobject.cpp @@ -14,14 +14,14 @@ DEFINE_OBJECT_VTABLE(SetCtor); DEFINE_OBJECT_VTABLE(WeakSetCtor); DEFINE_OBJECT_VTABLE(SetObject); -void Heap::WeakSetCtor::init(QV4::ExecutionContext *scope) +void Heap::WeakSetCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("WeakSet")); + Heap::FunctionObject::init(engine, QStringLiteral("WeakSet")); } -void Heap::SetCtor::init(QV4::ExecutionContext *scope) +void Heap::SetCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("Set")); + Heap::FunctionObject::init(engine, QStringLiteral("Set")); } ReturnedValue WeakSetCtor::construct(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget, bool isWeak) diff --git a/src/qml/jsruntime/qv4setobject_p.h b/src/qml/jsruntime/qv4setobject_p.h index 6ed44b4ed9..5aa10f43c8 100644 --- a/src/qml/jsruntime/qv4setobject_p.h +++ b/src/qml/jsruntime/qv4setobject_p.h @@ -29,12 +29,12 @@ class ESTable; namespace Heap { struct WeakSetCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; struct SetCtor : WeakSetCtor { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; struct SetObject : Object { diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index ad3c39c7b9..5f3d833f33 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -131,9 +131,9 @@ PropertyAttributes StringObject::virtualGetOwnProperty(const Managed *m, Propert DEFINE_OBJECT_VTABLE(StringCtor); -void Heap::StringCtor::init(QV4::ExecutionContext *scope) +void Heap::StringCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("String")); + Heap::FunctionObject::init(engine, QStringLiteral("String")); } ReturnedValue StringCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h index 451a989ef4..73c2bd7b34 100644 --- a/src/qml/jsruntime/qv4stringobject_p.h +++ b/src/qml/jsruntime/qv4stringobject_p.h @@ -44,7 +44,7 @@ DECLARE_HEAP_OBJECT(StringObject, Object) { }; struct StringCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(QV4::ExecutionEngine *engine); }; } diff --git a/src/qml/jsruntime/qv4symbol.cpp b/src/qml/jsruntime/qv4symbol.cpp index 5f7ec89fd2..85ef57f680 100644 --- a/src/qml/jsruntime/qv4symbol.cpp +++ b/src/qml/jsruntime/qv4symbol.cpp @@ -19,9 +19,9 @@ void Heap::Symbol::init(const QString &s) identifier = PropertyKey::fromStringOrSymbol(internalClass->engine, this); } -void Heap::SymbolCtor::init(QV4::ExecutionContext *scope) +void Heap::SymbolCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("Symbol")); + Heap::FunctionObject::init(engine, QStringLiteral("Symbol")); } void Heap::SymbolObject::init(const QV4::Symbol *s) diff --git a/src/qml/jsruntime/qv4symbol_p.h b/src/qml/jsruntime/qv4symbol_p.h index e56510bd69..29a0189b69 100644 --- a/src/qml/jsruntime/qv4symbol_p.h +++ b/src/qml/jsruntime/qv4symbol_p.h @@ -25,7 +25,7 @@ namespace QV4 { namespace Heap { struct SymbolCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; struct Symbol : StringOrSymbol { diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index 6c72eaba5f..ca7d75e0e0 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -236,9 +236,9 @@ const TypedArrayOperations operations[NTypedArrayTypes] = { }; -void Heap::TypedArrayCtor::init(QV4::ExecutionContext *scope, TypedArray::Type t) +void Heap::TypedArrayCtor::init(QV4::ExecutionEngine *engine, TypedArray::Type t) { - Heap::FunctionObject::init(scope, QLatin1String(operations[t].name)); + Heap::FunctionObject::init(engine, QLatin1String(operations[t].name)); type = t; } diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h index 9747eac411..50db9610c7 100644 --- a/src/qml/jsruntime/qv4typedarray_p.h +++ b/src/qml/jsruntime/qv4typedarray_p.h @@ -90,7 +90,7 @@ struct IntrinsicTypedArrayCtor : FunctionObject { }; struct TypedArrayCtor : FunctionObject { - void init(QV4::ExecutionContext *scope, TypedArray::Type t); + void init(ExecutionEngine *engine, TypedArray::Type t); TypedArray::Type type; }; @@ -141,8 +141,6 @@ struct IntrinsicTypedArrayCtor: FunctionObject { V4_OBJECT2(IntrinsicTypedArrayCtor, FunctionObject) - static constexpr VTable::Call virtualCall = nullptr; - static ReturnedValue method_of(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_from(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); }; diff --git a/src/qml/jsruntime/qv4urlobject.cpp b/src/qml/jsruntime/qv4urlobject.cpp index 4ece91a2a2..89c8b9cda2 100644 --- a/src/qml/jsruntime/qv4urlobject.cpp +++ b/src/qml/jsruntime/qv4urlobject.cpp @@ -18,9 +18,9 @@ DEFINE_OBJECT_VTABLE(UrlSearchParamsObject); DEFINE_OBJECT_VTABLE(UrlSearchParamsCtor); -void Heap::UrlCtor::init(QV4::ExecutionContext *scope) +void Heap::UrlCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QLatin1String("URL")); + Heap::FunctionObject::init(engine, QLatin1String("URL")); } void UrlPrototype::init(ExecutionEngine *engine, Object *ctor) @@ -750,9 +750,9 @@ ReturnedValue UrlCtor::virtualCallAsConstructor(const FunctionObject *that, cons } -void Heap::UrlSearchParamsCtor::init(QV4::ExecutionContext *scope) +void Heap::UrlSearchParamsCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QLatin1String("URLSearchParams")); + Heap::FunctionObject::init(engine, QLatin1String("URLSearchParams")); } void UrlSearchParamsPrototype::init(ExecutionEngine *engine, Object *ctor) diff --git a/src/qml/jsruntime/qv4urlobject_p.h b/src/qml/jsruntime/qv4urlobject_p.h index d45b74fcaa..b3b76e1158 100644 --- a/src/qml/jsruntime/qv4urlobject_p.h +++ b/src/qml/jsruntime/qv4urlobject_p.h @@ -47,7 +47,7 @@ DECLARE_HEAP_OBJECT(UrlObject, Object) struct UrlCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; // clang-format off @@ -66,7 +66,7 @@ DECLARE_HEAP_OBJECT(UrlSearchParamsObject, Object) struct UrlSearchParamsCtor : FunctionObject { - void init(QV4::ExecutionContext *scope); + void init(ExecutionEngine *engine); }; } diff --git a/src/qml/jsruntime/qv4vtable_p.h b/src/qml/jsruntime/qv4vtable_p.h index 8ec8c87a31..1f787ce94f 100644 --- a/src/qml/jsruntime/qv4vtable_p.h +++ b/src/qml/jsruntime/qv4vtable_p.h @@ -110,20 +110,38 @@ template<class Class> constexpr VTable::CallWithMetaTypes vtableMetaTypesCallEntry() { // If Class overrides virtualCallWithMetaTypes, return that. - // Otherwise, if it overrides virtualCall, return nullptr so that we convert calls. + // Otherwise, if it overrides virtualCall, return convertAndCall. // Otherwise, just return whatever the base class had. - // A simple != is not considered constexpr, so we have to jump through some hoops. - if constexpr (!std::is_same_v< - VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>, - VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualCallWithMetaTypes>>) { - return Class::virtualCallWithMetaTypes; - } - - if constexpr (!std::is_same_v< - VTableCallWrapper<Class::virtualCall>, - VTableCallWrapper<Class::SuperClass::virtualCall>>) { - return nullptr; + // A simple == on methods is not considered constexpr, so we have to jump through some hoops. + + static_assert( + std::is_same_v< + VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>, + VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualCallWithMetaTypes>> + || !std::is_same_v< + VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>, + VTableCallWithMetaTypesWrapper<nullptr>>, + "You mustn't override virtualCallWithMetaTypes with nullptr"); + + static_assert( + std::is_same_v< + VTableCallWithMetaTypesWrapper<Class::virtualConvertAndCall>, + VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualConvertAndCall>> + || !std::is_same_v< + VTableCallWithMetaTypesWrapper<Class::virtualConvertAndCall>, + VTableCallWithMetaTypesWrapper<nullptr>>, + "You mustn't override virtualConvertAndCall with nullptr"); + + if constexpr ( + std::is_same_v< + VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>, + VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualCallWithMetaTypes>> + && !std::is_same_v< + VTableCallWrapper<Class::virtualCall>, + VTableCallWrapper<Class::SuperClass::virtualCall>>) { + // Converting from metatypes to JS signature is easy. + return Class::virtualConvertAndCall; } return Class::virtualCallWithMetaTypes; @@ -133,21 +151,27 @@ template<class Class> constexpr VTable::Call vtableJsTypesCallEntry() { // If Class overrides virtualCall, return that. - // Otherwise, if it overrides virtualCallWithMetaTypes, return nullptr so that we convert calls. + // Otherwise, if it overrides virtualCallWithMetaTypes, fail. + // (We cannot determine the target types to call virtualCallWithMetaTypes in that case) // Otherwise, just return whatever the base class had. - // A simple != is not considered constexpr, so we have to jump through some hoops. - if constexpr (!std::is_same_v< - VTableCallWrapper<Class::virtualCall>, - VTableCallWrapper<Class::SuperClass::virtualCall>>) { - return Class::virtualCall; - } + // A simple == on methods is not considered constexpr, so we have to jump through some hoops. - if constexpr (!std::is_same_v< - VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>, - VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualCallWithMetaTypes>>) { - return nullptr; - } + static_assert( + !std::is_same_v< + VTableCallWrapper<Class::virtualCall>, + VTableCallWrapper<Class::SuperClass::virtualCall>> + || std::is_same_v< + VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>, + VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualCallWithMetaTypes>>, + "If you override virtualCallWithMetaTypes, override virtualCall, too"); + + static_assert( + std::is_same_v< + VTableCallWrapper<Class::virtualCall>, + VTableCallWrapper<Class::SuperClass::virtualCall>> + || VTableCallWrapper<Class::virtualCall>::c != nullptr, + "You mustn't override virtualCall with nullptr"); return Class::virtualCall; } @@ -174,6 +198,7 @@ protected: static constexpr VTable::Call virtualCall = nullptr; static constexpr VTable::CallAsConstructor virtualCallAsConstructor = nullptr; static constexpr VTable::CallWithMetaTypes virtualCallWithMetaTypes = nullptr; + static constexpr VTable::CallWithMetaTypes virtualConvertAndCall = nullptr; static constexpr VTable::ResolveLookupGetter virtualResolveLookupGetter = nullptr; static constexpr VTable::ResolveLookupSetter virtualResolveLookupSetter = nullptr; diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index 3f9ce26764..0bac2f45a2 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -62,7 +62,8 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(const QObject *target, int function += QLatin1String(") { ") + expression + QLatin1String(" })"); QV4::Scope valueScope(v4); - QV4::ScopedFunctionObject f(valueScope, evalFunction(context(), scopeObject(), function, fileName, line)); + QV4::Scoped<QV4::JavaScriptFunctionObject> f( + valueScope, evalFunction(context(), scopeObject(), function, fileName, line)); QV4::ScopedContext context(valueScope, f->scope()); setupFunction(context, f->function()); } @@ -107,7 +108,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(const QObject *target, int // we need to run the outer function to get the nested one. if (function->isClosureWrapper()) { bool isUndefined = false; - QV4::ScopedFunctionObject result( + QV4::Scoped<QV4::JavaScriptFunctionObject> result( valueScope, QQmlJavaScriptExpression::evaluate(&isUndefined)); Q_ASSERT(!isUndefined); diff --git a/src/qml/qml/qqmlbuiltinfunctions.cpp b/src/qml/qml/qqmlbuiltinfunctions.cpp index de37cc18be..cd31267696 100644 --- a/src/qml/qml/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/qqmlbuiltinfunctions.cpp @@ -1616,11 +1616,11 @@ QLocale QtObject::locale(const QString &name) const } #endif -void Heap::QQmlBindingFunction::init(const QV4::FunctionObject *bindingFunction) +void Heap::QQmlBindingFunction::init(const QV4::JavaScriptFunctionObject *bindingFunction) { Scope scope(bindingFunction->engine()); ScopedContext context(scope, bindingFunction->scope()); - FunctionObject::init(context, bindingFunction->function()); + JavaScriptFunctionObject::init(context, bindingFunction->function()); this->bindingFunction.set(internalClass->engine, bindingFunction->d()); } @@ -1678,7 +1678,8 @@ DEFINE_OBJECT_VTABLE(QQmlBindingFunction); */ QJSValue QtObject::binding(const QJSValue &function) const { - const QV4::FunctionObject *f = QJSValuePrivate::asManagedType<FunctionObject>(&function); + const QV4::JavaScriptFunctionObject *f + = QJSValuePrivate::asManagedType<JavaScriptFunctionObject>(&function); QV4::ExecutionEngine *e = v4Engine(); if (!f) { return QJSValuePrivate::fromReturnedValue( diff --git a/src/qml/qml/qqmlbuiltinfunctions_p.h b/src/qml/qml/qqmlbuiltinfunctions_p.h index 9ceedad28b..60b4d3a91f 100644 --- a/src/qml/qml/qqmlbuiltinfunctions_p.h +++ b/src/qml/qml/qqmlbuiltinfunctions_p.h @@ -199,10 +199,10 @@ struct ConsoleObject : Object { }; #define QQmlBindingFunctionMembers(class, Member) \ - Member(class, Pointer, FunctionObject *, bindingFunction) -DECLARE_HEAP_OBJECT(QQmlBindingFunction, FunctionObject) { + Member(class, Pointer, JavaScriptFunctionObject *, bindingFunction) +DECLARE_HEAP_OBJECT(QQmlBindingFunction, JavaScriptFunctionObject) { DECLARE_MARKOBJECTS(QQmlBindingFunction) - void init(const QV4::FunctionObject *bindingFunction); + void init(const QV4::JavaScriptFunctionObject *bindingFunction); }; } @@ -245,11 +245,11 @@ struct Q_QML_EXPORT GlobalExtensions { }; -struct QQmlBindingFunction : public QV4::FunctionObject +struct QQmlBindingFunction : public QV4::JavaScriptFunctionObject { - V4_OBJECT2(QQmlBindingFunction, FunctionObject) + V4_OBJECT2(QQmlBindingFunction, JavaScriptFunctionObject) - Heap::FunctionObject *bindingFunction() const { return d()->bindingFunction; } + Heap::JavaScriptFunctionObject *bindingFunction() const { return d()->bindingFunction; } QQmlSourceLocation currentLocation() const; // from caller stack trace }; diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp index efd8519a58..ead8a717f5 100644 --- a/src/qml/qml/qqmldelayedcallqueue.cpp +++ b/src/qml/qml/qqmldelayedcallqueue.cpp @@ -126,8 +126,9 @@ QV4::ReturnedValue QQmlDelayedCallQueue::addUniquelyAndExecuteLater(QV4::Executi // if it's a qobject function wrapper, guard against qobject deletion dfc.m_objectGuard = QQmlGuard<QObject>(functionData.first); dfc.m_guarded = true; - } else if (func->scope()->type == QV4::Heap::ExecutionContext::Type_QmlContext) { - QV4::QmlContext::Data *g = static_cast<QV4::QmlContext::Data *>(func->scope()); + } else if (const auto *js = func->as<QV4::JavaScriptFunctionObject>(); + js && js->scope()->type == QV4::Heap::ExecutionContext::Type_QmlContext) { + QV4::QmlContext::Data *g = static_cast<QV4::QmlContext::Data *>(js->scope()); Q_ASSERT(g->qml()->scopeObject); dfc.m_objectGuard = QQmlGuard<QObject>(g->qml()->scopeObject); dfc.m_guarded = true; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index c7812059a1..62b7675e1d 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1945,7 +1945,7 @@ void QQmlEnginePrivate::executeRuntimeFunction(const QV4::ExecutableCompilationU // different version of ExecutionEngine::callInContext() that returns a // QV4::ReturnedValue with no arguments since they are not needed by the // outer function anyhow - QV4::ScopedFunctionObject result(scope, + QV4::Scoped<QV4::JavaScriptFunctionObject> result(scope, v4->callInContext(function, thisObject, callContext, 0, nullptr)); Q_ASSERT(result->function()); Q_ASSERT(result->function()->compilationUnit == function->compilationUnit); diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 7075d0f5f6..5c95ee28aa 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -304,7 +304,7 @@ static ReturnedValue getGadgetProperty(ExecutionEngine *engine, { if (isFunction) { // calling a Q_INVOKABLE function of a value type - return QV4::QObjectMethod::create(engine->rootContext(), valueTypeWrapper, coreIndex); + return QV4::QObjectMethod::create(engine, valueTypeWrapper, coreIndex); } const QMetaObject *metaObject = valueTypeWrapper->metaObject(); @@ -785,7 +785,7 @@ bool QQmlValueTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &v QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f); - QV4::ScopedFunctionObject f(scope, bindingFunction->bindingFunction()); + QV4::Scoped<JavaScriptFunctionObject> f(scope, bindingFunction->bindingFunction()); QV4::ScopedContext ctx(scope, f->scope()); QQmlBinding *newBinding = QQmlBinding::create(&cacheData, f->function(), referenceObject, context, ctx); newBinding->setSourceLocation(bindingFunction->currentLocation()); diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 5f3b6975ca..dffddd2e0d 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -1141,7 +1141,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * QV4::Scope scope(v4); - QV4::ScopedFunctionObject function(scope, method(id)); + QV4::Scoped<QV4::JavaScriptFunctionObject> function(scope, method(id)); if (!function) { // The function was not compiled. There are some exceptional cases which the // expression rewriter does not rewrite properly (e.g., \r-terminated lines diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index c5d18860db..b4800584a3 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1708,7 +1708,7 @@ DEFINE_OBJECT_VTABLE(QQmlXMLHttpRequestWrapper); void Heap::QQmlXMLHttpRequestCtor::init(ExecutionEngine *engine) { - Heap::FunctionObject::init(engine->rootContext(), QStringLiteral("XMLHttpRequest")); + Heap::FunctionObject::init(engine, QStringLiteral("XMLHttpRequest")); Scope scope(engine); Scoped<QV4::QQmlXMLHttpRequestCtor> ctor(scope, this); diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp index 19363f9f76..99541a64dc 100644 --- a/src/qml/types/qqmlconnections.cpp +++ b/src/qml/types/qqmlconnections.cpp @@ -415,13 +415,12 @@ void QQmlConnections::connectSignalsToMethods() auto *signal = new QQmlBoundSignal(target, signalIndex, this, qmlEngine(this)); signal->setEnabled(d->enabled); - QV4::ScopedFunctionObject method( + QV4::Scoped<QV4::JavaScriptFunctionObject> method( scope, vmeMetaObject->vmeMethod(handler->coreIndex())); QQmlBoundSignalExpression *expression = ctxtdata ? new QQmlBoundSignalExpression( - target, signalIndex, ctxtdata, this, - method->as<QV4::FunctionObject>()->function()) + target, signalIndex, ctxtdata, this, method->function()) : nullptr; signal->takeExpression(expression); |