71QQmlBoundSignalExpression::QQmlBoundSignalExpression(
const QObject *target,
int index,
const QQmlRefPointer<QQmlContextData> &ctxt,
80 QV4::ExecutionEngine *engine = ctxt->engine()->handle();
82 if (!function->isClosureWrapper()) {
83 QList<QByteArray> signalParameters = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).parameterNames();
84 if (!signalParameters.isEmpty()) {
86 QQmlPropertyCache::signalParameterStringForJS(signalParameters, &error);
87 if (!error.isEmpty()) {
88 qmlWarning(scopeObject) << error;
91 function->updateInternalClass(engine, signalParameters);
95 QV4::Scope valueScope(engine);
96 QV4::Scoped<QV4::QmlContext> qmlContext(valueScope, scope);
98 qmlContext = QV4::QmlContext::create(engine->rootContext(), ctxt, scopeObject);
99 if (
auto closure = function->nestedFunction()) {
103 setupFunction(qmlContext, closure);
105 setupFunction(qmlContext, function);
109 if (function->isClosureWrapper()) {
110 bool isUndefined =
false;
111 QV4::Scoped<QV4::JavaScriptFunctionObject> result(
112 valueScope, QQmlJavaScriptExpression::evaluate(&isUndefined));
114 Q_ASSERT(!isUndefined);
115 Q_ASSERT(result->function());
116 Q_ASSERT(result->function()->compilationUnit == function->compilationUnit);
118 QV4::Scoped<QV4::ExecutionContext> callContext(valueScope, result->scope());
119 setupFunction(callContext, result->function());
124void QQmlBoundSignalExpression::init(
const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope)
126 setNotifyOnValueChanged(
false);
128 setScopeObject(scope);
130 Q_ASSERT(m_target && m_index > -1);
131 m_index = QQmlPropertyCache::originalClone(m_target, m_index);
134QQmlBoundSignalExpression::~QQmlBoundSignalExpression()
138QString QQmlBoundSignalExpression::expressionIdentifier()
const
140 QQmlSourceLocation loc = sourceLocation();
141 return loc.sourceFile + QLatin1Char(
':') + QString::number(loc.line);
144void QQmlBoundSignalExpression::expressionChanged()
149QString QQmlBoundSignalExpression::expression()
const
151 if (expressionFunctionValid())
152 return QStringLiteral(
"function() { [native code] }");
158void QQmlBoundSignalExpression::evaluate(
void **a)
160 if (!expressionFunctionValid())
163 QQmlEngine *qmlengine = engine();
170 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(qmlengine);
171 QV4::ExecutionEngine *v4 = qmlengine->handle();
172 QV4::Scope scope(v4);
174 ep->referenceScarceResources();
178 const QMetaObject *targetMeta = m_target->metaObject();
179 const QMetaMethod metaMethod = targetMeta->method(
180 QMetaObjectPrivate::signal(targetMeta, m_index).methodIndex());
182 int argCount = metaMethod.parameterCount();
183 QQmlMetaObject::ArgTypeStorage<9> storage;
184 storage.reserve(argCount + 1);
185 storage.append(QMetaType());
186 for (
int i = 0; i < argCount; ++i) {
187 const QMetaType type = metaMethod.parameterMetaType(i);
190 else if (type.flags().testFlag(QMetaType::IsEnumeration))
191 storage.append(type.underlyingType());
193 storage.append(type);
196 QQmlJavaScriptExpression::evaluate(a, storage.constData(), argCount);
198 void *ignoredResult =
nullptr;
199 QMetaType invalidType;
200 QQmlJavaScriptExpression::evaluate(&ignoredResult, &invalidType, 0);
203 ep->dereferenceScarceResources();
210
211
212
213QQmlBoundSignal::QQmlBoundSignal(QObject *target,
int signal, QObject *owner,
215 : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlBoundSignal),
216 m_prevSignal(
nullptr), m_nextSignal(
nullptr),
222
223
224
225
226
227 signal = QQmlPropertyCache::originalClone(target, signal);
228 QQmlNotifierEndpoint::connect(target, signal, engine);
231QQmlBoundSignal::~QQmlBoundSignal()
236void QQmlBoundSignal::addToObject(QObject *obj)
238 Q_ASSERT(!m_prevSignal);
241 QQmlData *data = QQmlData::get(obj,
true);
243 m_nextSignal = data->signalHandlers;
244 if (m_nextSignal) m_nextSignal->m_prevSignal = &m_nextSignal;
245 m_prevSignal = &data->signalHandlers;
246 data->signalHandlers =
this;
249void QQmlBoundSignal::removeFromObject()
252 *m_prevSignal = m_nextSignal;
253 if (m_nextSignal) m_nextSignal->m_prevSignal = m_prevSignal;
254 m_prevSignal =
nullptr;
255 m_nextSignal =
nullptr;
260
261
262QQmlBoundSignalExpression *QQmlBoundSignal::expression()
const
264 return m_expression.data();
268
269
270
271
272void QQmlBoundSignal::takeExpression(QQmlBoundSignalExpression *e)
274 m_expression.adopt(e);
276 m_expression->setNotifyOnValueChanged(
false);
280
281
282
283
284
285
286void QQmlBoundSignal::setEnabled(
bool enabled)
288 if (m_enabled == enabled)
296 QQmlBoundSignal *s =
static_cast<QQmlBoundSignal*>(e);
298 if (!s->m_expression || !s->m_enabled)
301 QV4DebugService *service = QQmlDebugConnector::service<QV4DebugService>();
303 service->signalEmitted(QString::fromUtf8(QMetaObjectPrivate::signal(
304 s->m_expression->target()->metaObject(),
305 s->signalIndex()).methodSignature()));
308 if (s->m_expression && (engine = s->m_expression->engine())) {
309 Q_TRACE_SCOPE(QQmlHandlingSignal, engine,
310 s->m_expression->function() ? s->m_expression->function()->name()->toQString() : QString(),
311 s->m_expression->sourceLocation().sourceFile, s->m_expression->sourceLocation().line,
312 s->m_expression->sourceLocation().column);
313 QQmlHandlingSignalProfiler prof(QQmlEnginePrivate::get(engine)->profiler,
314 s->m_expression.data());
315 s->m_expression->evaluate(a);
316 if (s->m_expression && s->m_expression->hasError()) {
317 QQmlEnginePrivate::warning(engine, s->m_expression->error(engine));