78QQmlBoundSignalExpression::QQmlBoundSignalExpression(
const QObject *target,
int index,
const QQmlRefPointer<QQmlContextData> &ctxt,
80 : QQmlJavaScriptExpression(),
85 init(ctxt, scopeObject);
87 QV4::ExecutionEngine *engine = ctxt->engine()->handle();
89 if (!function->isClosureWrapper()) {
90 QList<QByteArray> signalParameters = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).parameterNames();
91 if (!signalParameters.isEmpty()) {
93 QQmlPropertyCache::signalParameterStringForJS(signalParameters, &error);
94 if (!error.isEmpty()) {
95 qmlWarning(scopeObject) << error;
98 function->updateInternalClass(engine, signalParameters);
102 QV4::Scope valueScope(engine);
103 QV4::Scoped<QV4::QmlContext> qmlContext(valueScope, scope);
105 qmlContext = QV4::QmlContext::create(engine->rootContext(), ctxt, scopeObject);
106 if (
auto closure = function->nestedFunction()) {
110 setupFunction(qmlContext, closure);
112 setupFunction(qmlContext, function);
116 if (function->isClosureWrapper()) {
117 bool isUndefined =
false;
118 QV4::Scoped<QV4::JavaScriptFunctionObject> result(
119 valueScope, QQmlJavaScriptExpression::evaluate(&isUndefined));
121 Q_ASSERT(!isUndefined);
122 Q_ASSERT(result->function());
123 Q_ASSERT(result->function()->compilationUnit == function->compilationUnit);
125 QV4::Scoped<QV4::ExecutionContext> callContext(valueScope, result->scope());
126 setupFunction(callContext, result->function());
131void QQmlBoundSignalExpression::init(
const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope)
133 setNotifyOnValueChanged(
false);
135 setScopeObject(scope);
137 Q_ASSERT(m_target && m_index > -1);
138 m_index = QQmlPropertyCache::originalClone(m_target, m_index);
141QQmlBoundSignalExpression::~QQmlBoundSignalExpression()
145QString QQmlBoundSignalExpression::expressionIdentifier()
const
147 QQmlSourceLocation loc = sourceLocation();
148 return loc.sourceFile + QLatin1Char(
':') + QString::number(loc.line);
151void QQmlBoundSignalExpression::expressionChanged()
156QString QQmlBoundSignalExpression::expression()
const
158 if (expressionFunctionValid())
159 return QStringLiteral(
"function() { [native code] }");
165void QQmlBoundSignalExpression::evaluate(
void **a)
167 if (!expressionFunctionValid())
170 QQmlEngine *qmlengine = engine();
177 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(qmlengine);
178 QV4::ExecutionEngine *v4 = qmlengine->handle();
179 QV4::Scope scope(v4);
181 ep->referenceScarceResources();
185 const QMetaObject *targetMeta = m_target->metaObject();
186 const QMetaMethod metaMethod = targetMeta->method(
187 QMetaObjectPrivate::signal(targetMeta, m_index).methodIndex());
189 int argCount = metaMethod.parameterCount();
190 QQmlMetaObject::ArgTypeStorage<9> storage;
191 storage.reserve(argCount + 1);
192 storage.append(QMetaType());
193 for (
int i = 0; i < argCount; ++i) {
194 const QMetaType type = metaMethod.parameterMetaType(i);
197 else if (type.flags().testFlag(QMetaType::IsEnumeration))
198 storage.append(type.underlyingType());
200 storage.append(type);
203 QQmlJavaScriptExpression::evaluate(a, storage.constData(), argCount);
205 void *ignoredResult =
nullptr;
206 QMetaType invalidType;
207 QQmlJavaScriptExpression::evaluate(&ignoredResult, &invalidType, 0);
210 ep->dereferenceScarceResources();
217
218
219
220QQmlBoundSignal::QQmlBoundSignal(QObject *target,
int signal, QObject *owner,
222 : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlBoundSignal),
223 m_prevSignal(
nullptr), m_nextSignal(
nullptr),
229
230
231
232
233
234 signal = QQmlPropertyCache::originalClone(target, signal);
235 QQmlNotifierEndpoint::connect(target, signal, engine);
238QQmlBoundSignal::~QQmlBoundSignal()
243void QQmlBoundSignal::addToObject(QObject *obj)
245 Q_ASSERT(!m_prevSignal);
248 QQmlData *data = QQmlData::get(obj,
true);
250 m_nextSignal = data->signalHandlers;
251 if (m_nextSignal) m_nextSignal->m_prevSignal = &m_nextSignal;
252 m_prevSignal = &data->signalHandlers;
253 data->signalHandlers =
this;
256void QQmlBoundSignal::removeFromObject()
259 *m_prevSignal = m_nextSignal;
260 if (m_nextSignal) m_nextSignal->m_prevSignal = m_prevSignal;
261 m_prevSignal =
nullptr;
262 m_nextSignal =
nullptr;
267
268
269QQmlBoundSignalExpression *QQmlBoundSignal::expression()
const
271 return m_expression.data();
275
276
277
278
279void QQmlBoundSignal::takeExpression(QQmlBoundSignalExpression *e)
281 m_expression.adopt(e);
283 m_expression->setNotifyOnValueChanged(
false);
287
288
289
290
291
292
293void QQmlBoundSignal::setEnabled(
bool enabled)
295 if (m_enabled == enabled)
303 QQmlBoundSignal *s =
static_cast<QQmlBoundSignal*>(e);
305 if (!s->m_expression || !s->m_enabled)
308 QV4DebugService *service = QQmlDebugConnector::service<QV4DebugService>();
310 service->signalEmitted(QString::fromUtf8(QMetaObjectPrivate::signal(
311 s->m_expression->target()->metaObject(),
312 s->signalIndex()).methodSignature()));
315 if (s->m_expression && (engine = s->m_expression->engine())) {
316 Q_TRACE_SCOPE(QQmlHandlingSignal, engine,
317 s->m_expression->function() ? s->m_expression->function()->name()->toQString() : QString(),
318 s->m_expression->sourceLocation().sourceFile, s->m_expression->sourceLocation().line,
319 s->m_expression->sourceLocation().column);
320 QQmlHandlingSignalProfiler prof(QQmlEnginePrivate::get(engine)->profiler,
321 s->m_expression.data());
322 s->m_expression->evaluate(a);
323 if (s->m_expression && s->m_expression->hasError()) {
324 QQmlEnginePrivate::warning(engine, s->m_expression->error(engine));