77QQmlBoundSignalExpression::QQmlBoundSignalExpression(
const QObject *target,
int index,
const QQmlRefPointer<QQmlContextData> &ctxt,
79 : QQmlJavaScriptExpression(),
84 init(ctxt, scopeObject);
86 QV4::ExecutionEngine *engine = ctxt->engine()->handle();
88 if (!function->isClosureWrapper()) {
89 QList<QByteArray> signalParameters = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).parameterNames();
90 if (!signalParameters.isEmpty()) {
92 QQmlPropertyCache::signalParameterStringForJS(signalParameters, &error);
93 if (!error.isEmpty()) {
94 qmlWarning(scopeObject) << error;
97 function->updateInternalClass(engine, signalParameters);
101 QV4::Scope valueScope(engine);
102 QV4::Scoped<QV4::QmlContext> qmlContext(valueScope, scope);
104 qmlContext = QV4::QmlContext::create(engine->rootContext(), ctxt, scopeObject);
105 if (
auto closure = function->nestedFunction()) {
109 setupFunction(qmlContext, closure);
111 setupFunction(qmlContext, function);
115 if (function->isClosureWrapper()) {
116 bool isUndefined =
false;
117 QV4::Scoped<QV4::JavaScriptFunctionObject> result(
118 valueScope, QQmlJavaScriptExpression::evaluate(&isUndefined));
120 Q_ASSERT(!isUndefined);
121 Q_ASSERT(result->function());
122 Q_ASSERT(result->function()->compilationUnit == function->compilationUnit);
124 QV4::Scoped<QV4::ExecutionContext> callContext(valueScope, result->scope());
125 setupFunction(callContext, result->function());
130void QQmlBoundSignalExpression::init(
const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope)
132 setNotifyOnValueChanged(
false);
134 setScopeObject(scope);
136 Q_ASSERT(m_target && m_index > -1);
137 m_index = QQmlPropertyCache::originalClone(m_target, m_index);
140QQmlBoundSignalExpression::~QQmlBoundSignalExpression()
144QString QQmlBoundSignalExpression::expressionIdentifier()
const
146 QQmlSourceLocation loc = sourceLocation();
147 return loc.sourceFile + QLatin1Char(
':') + QString::number(loc.line);
150void QQmlBoundSignalExpression::expressionChanged()
155QString QQmlBoundSignalExpression::expression()
const
157 if (expressionFunctionValid())
158 return QStringLiteral(
"function() { [native code] }");
164void QQmlBoundSignalExpression::evaluate(
void **a)
166 if (!expressionFunctionValid())
169 QQmlEngine *qmlengine = engine();
176 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(qmlengine);
177 QV4::ExecutionEngine *v4 = qmlengine->handle();
178 QV4::Scope scope(v4);
180 ep->referenceScarceResources();
184 const QMetaObject *targetMeta = m_target->metaObject();
185 const QMetaMethod metaMethod = targetMeta->method(
186 QMetaObjectPrivate::signal(targetMeta, m_index).methodIndex());
188 int argCount = metaMethod.parameterCount();
189 QQmlMetaObject::ArgTypeStorage<9> storage;
190 storage.reserve(argCount + 1);
191 storage.append(QMetaType());
192 for (
int i = 0; i < argCount; ++i) {
193 const QMetaType type = metaMethod.parameterMetaType(i);
196 else if (type.flags().testFlag(QMetaType::IsEnumeration))
197 storage.append(type.underlyingType());
199 storage.append(type);
202 QQmlJavaScriptExpression::evaluate(a, storage.constData(), argCount);
204 void *ignoredResult =
nullptr;
205 QMetaType invalidType;
206 QQmlJavaScriptExpression::evaluate(&ignoredResult, &invalidType, 0);
209 ep->dereferenceScarceResources();
216
217
218
219QQmlBoundSignal::QQmlBoundSignal(QObject *target,
int signal, QObject *owner,
221 : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlBoundSignal),
222 m_prevSignal(
nullptr), m_nextSignal(
nullptr),
228
229
230
231
232
233 signal = QQmlPropertyCache::originalClone(target, signal);
234 QQmlNotifierEndpoint::connect(target, signal, engine);
237QQmlBoundSignal::~QQmlBoundSignal()
242void QQmlBoundSignal::addToObject(QObject *obj)
244 Q_ASSERT(!m_prevSignal);
247 QQmlData *data = QQmlData::get(obj,
true);
249 m_nextSignal = data->signalHandlers;
250 if (m_nextSignal) m_nextSignal->m_prevSignal = &m_nextSignal;
251 m_prevSignal = &data->signalHandlers;
252 data->signalHandlers =
this;
255void QQmlBoundSignal::removeFromObject()
258 *m_prevSignal = m_nextSignal;
259 if (m_nextSignal) m_nextSignal->m_prevSignal = m_prevSignal;
260 m_prevSignal =
nullptr;
261 m_nextSignal =
nullptr;
266
267
268QQmlBoundSignalExpression *QQmlBoundSignal::expression()
const
270 return m_expression.data();
274
275
276
277
278void QQmlBoundSignal::takeExpression(QQmlBoundSignalExpression *e)
280 m_expression.adopt(e);
282 m_expression->setNotifyOnValueChanged(
false);
286
287
288
289
290
291
292void QQmlBoundSignal::setEnabled(
bool enabled)
294 if (m_enabled == enabled)
302 QQmlBoundSignal *s =
static_cast<QQmlBoundSignal*>(e);
304 if (!s->m_expression || !s->m_enabled)
307 QV4DebugService *service = QQmlDebugConnector::service<QV4DebugService>();
309 service->signalEmitted(QString::fromUtf8(QMetaObjectPrivate::signal(
310 s->m_expression->target()->metaObject(),
311 s->signalIndex()).methodSignature()));
314 if (s->m_expression && (engine = s->m_expression->engine())) {
315 Q_TRACE_SCOPE(QQmlHandlingSignal, engine,
316 s->m_expression->function() ? s->m_expression->function()->name()->toQString() : QString(),
317 s->m_expression->sourceLocation().sourceFile, s->m_expression->sourceLocation().line,
318 s->m_expression->sourceLocation().column);
319 QQmlHandlingSignalProfiler prof(QQmlEnginePrivate::get(engine)->profiler,
320 s->m_expression.data());
321 s->m_expression->evaluate(a);
322 if (s->m_expression && s->m_expression->hasError()) {
323 QQmlEnginePrivate::warning(engine, s->m_expression->error(engine));