115ReturnedValue QQmlContextWrapper::getPropertyAndBase(
const QQmlContextWrapper *resource, PropertyKey id,
const Value *receiver,
bool *hasProperty, Value *base, Lookup *lookup)
118 return Object::virtualGet(resource, id, receiver, hasProperty);
120 QV4::ExecutionEngine *v4 = resource->engine();
121 QV4::Scope scope(v4);
123 if (v4->callingQmlContext().data() != resource->d()->context) {
124 if (resource->d()->module) {
125 Scoped<Module> module(scope, resource->d()->module);
126 bool hasProp =
false;
127 ScopedValue value(scope, module->get(id, receiver, &hasProp));
130 *hasProperty = hasProp;
131 return value->asReturnedValue();
135 return Object::virtualGet(resource, id, receiver, hasProperty);
138 ScopedValue result(scope);
142 QQmlRefPointer<QQmlContextData> context = resource->getContext();
143 QQmlRefPointer<QQmlContextData> expressionContext = context;
148 return result->asReturnedValue();
159 QObject *scopeObject = resource->getScopeObject();
161 ScopedString name(scope, id.asStringOrSymbol());
163 const auto globalLookup = [v4, &name](
bool *hasProp) {
164 return v4->globalObject->get(name, hasProp);
167 const auto jsLookup = [resource, &id, receiver](
bool *hasProp) {
168 return Object::virtualGet(resource, id, receiver, hasProp);
171 const bool isJSContext = context->isJSContext();
174 if (isJSContext && performLookup(&result, hasProperty, jsLookup))
175 return result->asReturnedValue();
191 const QMetaObjectPrivate *metaObjectPrivate = scopeObject
192 ?
reinterpret_cast<
const QMetaObjectPrivate *>(scopeObject->metaObject()->d.data)
194 if (metaObjectPrivate && metaObjectPrivate->flags & DynamicMetaObject) {
197 if (performLookup(&result, hasProperty, globalLookup))
198 return result->asReturnedValue();
201 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(v4->qmlEngine());
202 if (context->imports() && (name->startsWithUpper() || context->valueTypesAreAddressable())) {
204 QQmlTypeNameCache::Result r = context->imports()->query<QQmlImport::AllowRecursion>(
205 name, v4->typeLoader());
210 if (r.scriptIndex != -1) {
212 lookup->qmlContextScriptLookup.scriptIndex = r.scriptIndex;
213 lookup->call = Lookup::Call::ContextGetterScript;
214 return lookup->contextGetter(v4, base);
216 QV4::ScopedObject scripts(scope, context->importedScripts());
218 return scripts->get(r.scriptIndex);
219 return QV4::Encode::null();
220 }
else if (r.type.isValid()) {
222 bool isValueSingleton =
false;
223 if (r.type.isSingleton()) {
224 QQmlEnginePrivate *e = QQmlEnginePrivate::get(v4->qmlEngine());
225 if (r.type.isQObjectSingleton() || r.type.isCompositeSingleton()) {
226 e->singletonInstance<QObject*>(r.type);
227 lookup->qmlContextSingletonLookup.singletonObject.set(v4,
228 Value::fromReturnedValue(
229 QQmlTypeWrapper::create(v4,
nullptr, r.type)
232 QJSValue singleton = e->singletonInstance<QJSValue>(r.type);
237 Q_ASSERT(!QJSValuePrivate::asQString(&singleton));
239 if (QV4::Value *val = QJSValuePrivate::takeManagedValue(&singleton)) {
240 lookup->qmlContextSingletonLookup.singletonObject.set(v4, val->heapObject());
242 lookup->qmlContextSingletonLookup.singletonValue = QJSValuePrivate::asReturnedValue(&singleton);
243 isValueSingleton =
true;
246 lookup->call = isValueSingleton
247 ? Lookup::Call::ContextGetterValueSingleton
248 : Lookup::Call::ContextGetterSingleton;
249 return lookup->contextGetter(v4, base);
252 result = QQmlTypeWrapper::create(v4, scopeObject, r.type);
253 }
else if (r.importNamespace) {
254 result = QQmlTypeWrapper::create(v4, scopeObject, context->imports(), r.importNamespace);
257 lookup->qmlTypeLookup.qmlTypeWrapper.set(v4, result->heapObject());
258 lookup->call = Lookup::Call::ContextGetterType;
260 return result->asReturnedValue();
266 Lookup *
const originalLookup = lookup;
268 Lookup::Call contextGetterCall = Lookup::Call::ContextGetterContextObjectProperty;
271 if (scopeObject == context->contextObject()) {
272 scopeObject =
nullptr;
273 contextGetterCall = Lookup::Call::ContextGetterScopeObjectProperty;
276 QQmlRefPointer<QQmlContextData> outer = context;
278 if (outer == context) {
279 if (
auto property = searchContextProperties(
280 v4, context, name, hasProperty, base, lookup, originalLookup, ep)) {
284 outer = outer->parent();
286 if (
const auto cu = context->typeCompilationUnit(); cu && cu->componentsAreBound()) {
293 outer && outer->typeCompilationUnit() == cu;
294 outer = outer->parent()) {
295 if (
auto property = searchContextProperties(
296 v4, outer, name, hasProperty, base,
297 nullptr, originalLookup, ep)) {
306 bool hasProp =
false;
308 const QQmlPropertyData *propertyData =
nullptr;
310 QV4::ScopedObject wrapper(scope, QV4::QObjectWrapper::wrap(v4, scopeObject));
311 QV4::ScopedValue result(scope, QV4::QObjectWrapper::getQmlProperty(
312 v4, context, wrapper->d(), scopeObject, name,
313 getQmlPropertyFlags(lookup), &hasProp, &propertyData));
321 QQmlData *ddata = QQmlData::get(scopeObject,
false);
322 if (ddata && ddata->propertyCache) {
325 base ? *base : Value::fromReturnedValue(
326 QV4::QObjectWrapper::wrap(v4, scopeObject)));
327 if (QObjectMethod *method = result->as<QObjectMethod>()) {
328 QV4::setupQObjectMethodLookup(
329 lookup, ddata, propertyData, val->objectValue(),
331 lookup->call = Lookup::Call::ContextGetterScopeObjectMethod;
333 QV4::setupQObjectLookup(
334 lookup, ddata, propertyData, val->objectValue());
335 lookup->call = Lookup::Call::ContextGetterScopeObjectProperty;
340 return result->asReturnedValue();
343 scopeObject =
nullptr;
347 if (QObject *contextObject = context->contextObject()) {
348 bool hasProp =
false;
349 const QQmlPropertyData *propertyData =
nullptr;
350 QV4::ScopedObject wrapper(scope, QV4::QObjectWrapper::wrap(v4, contextObject));
351 result = QV4::QObjectWrapper::getQmlProperty(
352 v4, context, wrapper->d(), contextObject, name, getQmlPropertyFlags(lookup),
353 &hasProp, &propertyData);
361 QQmlData *ddata = QQmlData::get(contextObject,
false);
362 if (ddata && ddata->propertyCache && lookup->call != contextGetterCall) {
365 base ? *base : Value::fromReturnedValue(
366 QV4::QObjectWrapper::wrap(v4, contextObject)));
367 if (QObjectMethod *method = result->as<QObjectMethod>()) {
368 setupQObjectMethodLookup(
369 lookup, ddata, propertyData, val->objectValue(),
371 if (contextGetterCall == Lookup::Call::ContextGetterScopeObjectProperty)
372 lookup->call = Lookup::Call::ContextGetterScopeObjectMethod;
374 lookup->call = Lookup::Call::ContextGetterContextObjectMethod;
377 lookup, ddata, propertyData, val->objectValue());
378 lookup->call = contextGetterCall;
381 }
else if (originalLookup) {
382 originalLookup->call = Lookup::Call::ContextGetterInParentContextHierarchy;
385 return result->asReturnedValue();
389 context = context->parent();
398 if (!isJSContext && performLookup(&result, hasProperty, jsLookup))
399 return result->asReturnedValue();
403 if (originalLookup) {
407 lookup = originalLookup;
408 result = lookup->resolveGlobalGetter(v4);
409 if (lookup->call != Lookup::Call::GlobalGetterGeneric) {
412 lookup->qmlContextGlobalLookup.getterTrampoline = lookup->call;
413 lookup->call = Lookup::Call::ContextGetterInGlobalObject;
414 return result->asReturnedValue();
416 lookup->call = Lookup::Call::ContextGetterGeneric;
418 if (performLookup(&result, hasProperty, globalLookup))
419 return result->asReturnedValue();
422 expressionContext->setUnresolvedNames(
true);
424 return Encode::undefined();
434bool QQmlContextWrapper::virtualPut(Managed *m, PropertyKey id,
const Value &value, Value *receiver)
436 Q_ASSERT(m->as<QQmlContextWrapper>());
438 if (id.isSymbol() || id.isArrayIndex())
439 return Object::virtualPut(m, id, value, receiver);
441 QQmlContextWrapper *resource =
static_cast<QQmlContextWrapper *>(m);
442 ExecutionEngine *v4 = resource->engine();
443 QV4::Scope scope(v4);
444 if (scope.hasException())
446 QV4::Scoped<QQmlContextWrapper> wrapper(scope, resource);
448 auto member = wrapper->internalClass()->findValueOrSetter(id);
449 if (member.index < UINT_MAX)
450 return wrapper->putValue(member.index, member.attrs, value);
454 QQmlRefPointer<QQmlContextData> context = wrapper->getContext();
455 QQmlRefPointer<QQmlContextData> expressionContext = context;
462 QObject *scopeObject = wrapper->getScopeObject();
463 ScopedString name(scope, id.asStringOrSymbol());
467 if (
const int propertyIndex = context->propertyIndex(name); propertyIndex != -1) {
468 if (propertyIndex < context->numIdValues()) {
469 v4->throwError(QLatin1String(
"left-hand side of assignment operator is not an lvalue"));
477 QV4::QObjectWrapper::setQmlProperty(v4, context, scopeObject, name, QV4::QObjectWrapper::CheckRevision, value))
479 scopeObject =
nullptr;
482 if (context->contextObject() &&
483 QV4::QObjectWrapper::setQmlProperty(v4, context, context->contextObject(), name,
484 QV4::QObjectWrapper::CheckRevision, value))
487 context = context->parent();
490 expressionContext->setUnresolvedNames(
true);
492 QString error = QLatin1String(
"Invalid write to global property \"") + name->toQString() +
494 v4->throwError(error);
498ReturnedValue QQmlContextWrapper::resolveQmlContextPropertyLookupGetter(Lookup *l, ExecutionEngine *engine, Value *base)
501 auto *func = engine->currentStackFrame->v4Function;
502 ScopedPropertyKey name(scope, engine->identifierTable->asPropertyKey(
503 func->compilationUnit->runtimeStrings[l->nameIndex]));
509 for (Heap::ExecutionContext *ctx = engine->currentContext()->d(); ctx; ctx = ctx->outer) {
510 if (ctx->type == Heap::ExecutionContext::Type_CallContext) {
511 const uint index = ctx->internalClass->indexOfValueOrGetter(name);
512 if (index < std::numeric_limits<uint>::max()) {
513 if (!func->detectedInjectedParameters) {
514 const auto location = func->sourceLocation();
515 qCWarning(lcQmlContext).nospace().noquote()
516 << location.sourceFile <<
":" << location.line <<
":" << location.column
517 <<
" Parameter \"" << name->toQString() <<
"\" is not declared."
518 <<
" Injection of parameters into signal handlers is deprecated."
519 <<
" Use JavaScript functions with formal parameters instead.";
522 func->detectedInjectedParameters =
true;
525 return static_cast<Heap::CallContext *>(ctx)->locals[index].asReturnedValue();
531 if (ctx->type != Heap::ExecutionContext::Type_BlockContext && ctx->type != Heap::ExecutionContext::Type_CallContext)
535 bool hasProperty =
false;
536 ScopedValue result(scope);
538 Scoped<QmlContext> callingQmlContext(scope, engine->qmlContext());
539 if (callingQmlContext) {
540 Scoped<QQmlContextWrapper> qmlContextWrapper(scope, callingQmlContext->d()->qml());
541 result = QQmlContextWrapper::getPropertyAndBase(
542 qmlContextWrapper, name,
nullptr, &hasProperty, base, l);
545 result = l->resolveGlobalGetter(engine);
546 if (l->call != Lookup::Call::GlobalGetterGeneric) {
548 l->qmlContextGlobalLookup.getterTrampoline = l->call;
549 l->call = Lookup::Call::ContextGetterInGlobalObject;
553 return engine->throwReferenceError(name->toQString());
554 return result->asReturnedValue();
753ReturnedValue QQmlContextWrapper::lookupInParentContextHierarchy(Lookup *l, ExecutionEngine *engine, Value *base)
756 Scoped<QmlContext> qmlContext(scope, engine->qmlContext());
758 return QV4::Encode::undefined();
760 QQmlRefPointer<QQmlContextData> context = qmlContext->qmlContext();
762 return QV4::Encode::undefined();
764 QQmlRefPointer<QQmlContextData> expressionContext = context;
766 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine->qmlEngine());
768 PropertyKey id =engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->
769 runtimeStrings[l->nameIndex]);
770 ScopedString name(scope, id.asStringOrSymbol());
772 ScopedValue result(scope);
774 for (context = context->parent(); context; context = context->parent()) {
775 if (
auto property = searchContextProperties(engine, context, name,
nullptr, base,
nullptr,
nullptr, ep))
779 if (QObject *contextObject = context->contextObject()) {
780 bool hasProp =
false;
781 QV4::ScopedObject wrapper(scope, QV4::QObjectWrapper::wrap(engine, contextObject));
782 result = QV4::QObjectWrapper::getQmlProperty(
783 engine, context, wrapper->d(), contextObject, name, getQmlPropertyFlags(l),
789 return result->asReturnedValue();
794 bool hasProp =
false;
795 result = engine->globalObject->get(name, &hasProp);
797 return result->asReturnedValue();
799 expressionContext->setUnresolvedNames(
true);
801 return Encode::undefined();