1 /****************************************************************************
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtScript module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL-ONLY$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
43 #include "qscriptqobject_p.h"
45 #include <QtCore/qmetaobject.h>
46 #include <QtCore/qvarlengtharray.h>
47 #include <QtCore/qdebug.h>
48 #include <QtScript/qscriptable.h>
49 #include "../api/qscriptengine_p.h"
50 #include "../api/qscriptable_p.h"
51 #include "../api/qscriptcontext_p.h"
52 #include "qscriptfunction_p.h"
55 #include "PrototypeFunction.h"
56 #include "PropertyNameArray.h"
57 #include "JSFunction.h"
61 #include "RegExpObject.h"
62 #include "RegExpConstructor.h"
67 ASSERT_CLASS_FITS_IN_CELL(QScript::QObjectPrototype
);
68 ASSERT_CLASS_FITS_IN_CELL(QScript::QMetaObjectWrapperObject
);
69 ASSERT_CLASS_FITS_IN_CELL(QScript::QMetaObjectPrototype
);
70 ASSERT_CLASS_FITS_IN_CELL(QScript::QtFunction
);
71 ASSERT_CLASS_FITS_IN_CELL(QScript::QtPropertyFunction
);
79 struct QObjectConnection
82 JSC::JSValue receiver
;
84 JSC::JSValue senderWrapper
;
86 QObjectConnection(int i
, JSC::JSValue r
, JSC::JSValue s
,
88 : slotIndex(i
), receiver(r
), slot(s
), senderWrapper(sw
) {}
89 QObjectConnection() : slotIndex(-1) {}
91 bool hasTarget(JSC::JSValue r
, JSC::JSValue s
) const
93 if ((r
&& r
.isObject()) != (receiver
&& receiver
.isObject()))
95 if (((r
&& r
.isObject()) && (receiver
&& receiver
.isObject()))
102 void mark(JSC::MarkStack
& markStack
)
104 // ### need to find out if senderWrapper is marked
106 // see if the sender should be marked or not
107 Q_ASSERT(senderWrapper
.inherits(&QScriptObject::info
));
108 QScriptObject
*scriptObject
= static_cast<QScriptObject
*>(JSC::asObject(senderWrapper
));
109 QScriptObjectDelegate
*delegate
= scriptObject
->delegate();
110 Q_ASSERT(delegate
&& (delegate
->type() == QScriptObjectDelegate::QtObject
));
111 QObjectDelegate
*inst
= static_cast<QObjectDelegate
*>(delegate
);
112 if ((inst
->ownership() == QScriptEngine::ScriptOwnership
)
113 || ((inst
->ownership() == QScriptEngine::AutoOwnership
)
114 && inst
->value() && !inst
->value()->parent())) {
115 // #### don't mark if not marked otherwise
116 //senderWrapper = JSC::JSValue();
117 markStack
.append(senderWrapper
);
119 markStack
.append(senderWrapper
);
123 markStack
.append(receiver
);
125 markStack
.append(slot
);
129 class QObjectNotifyCaller
: public QObject
132 void callConnectNotify(const char *signal
)
133 { connectNotify(signal
); }
134 void callDisconnectNotify(const char *signal
)
135 { disconnectNotify(signal
); }
138 class QObjectConnectionManager
: public QObject
141 QObjectConnectionManager(QScriptEnginePrivate
*engine
);
142 ~QObjectConnectionManager();
144 bool addSignalHandler(QObject
*sender
, int signalIndex
,
145 JSC::JSValue receiver
,
147 JSC::JSValue senderWrapper
,
148 Qt::ConnectionType type
);
149 bool removeSignalHandler(QObject
*sender
, int signalIndex
,
150 JSC::JSValue receiver
,
153 static const QMetaObject staticMetaObject
;
154 virtual const QMetaObject
*metaObject() const;
155 virtual void *qt_metacast(const char *);
156 virtual int qt_metacall(QMetaObject::Call
, int, void **argv
);
158 void execute(int slotIndex
, void **argv
);
160 void mark(JSC::MarkStack
&);
163 QScriptEnginePrivate
*engine
;
165 QVector
<QVector
<QObjectConnection
> > connections
;
168 static bool hasMethodAccess(const QMetaMethod
&method
, int index
, const QScriptEngine::QObjectWrapOptions
&opt
)
170 return (method
.access() != QMetaMethod::Private
)
171 && ((index
!= 2) || !(opt
& QScriptEngine::ExcludeDeleteLater
));
174 static bool isEnumerableMetaProperty(const QMetaProperty
&prop
,
175 const QMetaObject
*mo
, int index
)
177 return prop
.isScriptable() && prop
.isValid()
178 // the following lookup is to ensure that we have the
179 // "most derived" occurrence of the property with this name
180 && (mo
->indexOfProperty(prop
.name()) == index
);
183 static inline QByteArray
methodName(const QMetaMethod
&method
)
185 QByteArray signature
= method
.signature();
186 return signature
.left(signature
.indexOf('('));
189 static QVariant
variantFromValue(QScriptEnginePrivate
*eng
,
190 int targetType
, const QScriptValue
&value
)
192 QVariant
v(targetType
, (void *)0);
194 if (QScriptEnginePrivate::convert(value
, targetType
, v
.data(), eng
))
196 if (uint(targetType
) == QVariant::LastType
)
197 return value
.toVariant();
198 if (value
.isVariant()) {
199 v
= value
.toVariant();
200 if (v
.canConvert(QVariant::Type(targetType
))) {
201 v
.convert(QVariant::Type(targetType
));
204 QByteArray typeName
= v
.typeName();
205 if (typeName
.endsWith('*')
206 && (QMetaType::type(typeName
.left(typeName
.size()-1)) == targetType
)) {
207 return QVariant(targetType
, *reinterpret_cast<void* *>(v
.data()));
214 static const bool GeneratePropertyFunctions
= true;
216 static unsigned flagsForMetaProperty(const QMetaProperty
&prop
)
218 return (JSC::DontDelete
219 | (!prop
.isWritable() ? unsigned(JSC::ReadOnly
) : unsigned(0))
220 | (GeneratePropertyFunctions
221 ? unsigned(JSC::Getter
| JSC::Setter
)
223 | QObjectMemberAttribute
);
226 static int indexOfMetaEnum(const QMetaObject
*meta
, const QByteArray
&str
)
230 int scopeIdx
= str
.lastIndexOf("::");
231 if (scopeIdx
!= -1) {
232 scope
= str
.left(scopeIdx
);
233 name
= str
.mid(scopeIdx
+ 2);
237 for (int i
= meta
->enumeratorCount() - 1; i
>= 0; --i
) {
238 QMetaEnum m
= meta
->enumerator(i
);
239 if ((m
.name() == name
) && (scope
.isEmpty() || (m
.scope() == scope
)))
245 static inline QScriptable
*scriptableFromQObject(QObject
*qobj
)
247 void *ptr
= qobj
->qt_metacast("QScriptable");
248 return reinterpret_cast<QScriptable
*>(ptr
);
251 QtFunction::QtFunction(JSC::JSValue object
, int initialIndex
, bool maybeOverloaded
,
252 JSC::JSGlobalData
*data
, WTF::PassRefPtr
<JSC::Structure
> sid
,
253 const JSC::Identifier
&ident
)
254 : JSC::InternalFunction(data
, sid
, ident
),
255 data(new Data(object
, initialIndex
, maybeOverloaded
))
259 QtFunction::~QtFunction()
264 JSC::CallType
QtFunction::getCallData(JSC::CallData
&callData
)
266 callData
.native
.function
= call
;
267 return JSC::CallTypeHost
;
270 void QtFunction::markChildren(JSC::MarkStack
& markStack
)
273 markStack
.append(data
->object
);
274 JSC::InternalFunction::markChildren(markStack
);
277 QScriptObject
*QtFunction::wrapperObject() const
279 Q_ASSERT(JSC::asObject(data
->object
)->inherits(&QScriptObject::info
));
280 return static_cast<QScriptObject
*>(JSC::asObject(data
->object
));
283 QObject
*QtFunction::qobject() const
285 QScriptObject
*scriptObject
= wrapperObject();
286 QScriptObjectDelegate
*delegate
= scriptObject
->delegate();
287 Q_ASSERT(delegate
&& (delegate
->type() == QScriptObjectDelegate::QtObject
));
288 return static_cast<QScript::QObjectDelegate
*>(delegate
)->value();
291 const QMetaObject
*QtFunction::metaObject() const
293 QObject
*qobj
= qobject();
296 return qobj
->metaObject();
299 int QtFunction::initialIndex() const
301 return data
->initialIndex
;
304 bool QtFunction::maybeOverloaded() const
306 return data
->maybeOverloaded
;
309 int QtFunction::mostGeneralMethod(QMetaMethod
*out
) const
311 const QMetaObject
*meta
= metaObject();
314 int index
= initialIndex();
315 QMetaMethod method
= meta
->method(index
);
316 if (maybeOverloaded() && (method
.attributes() & QMetaMethod::Cloned
)) {
317 // find the most general method
319 method
= meta
->method(--index
);
320 } while (method
.attributes() & QMetaMethod::Cloned
);
327 QList
<int> QScript::QtFunction::overloadedIndexes() const
329 if (!maybeOverloaded())
332 QString name
= functionName();
333 const QMetaObject
*meta
= metaObject();
334 for (int index
= mostGeneralMethod() - 1; index
>= 0; --index
) {
335 QString otherName
= QString::fromLatin1(methodName(meta
->method(index
)));
336 if (otherName
== name
)
337 result
.append(index
);
342 QString
QtFunction::functionName() const
344 const QMetaObject
*meta
= metaObject();
347 QMetaMethod method
= meta
->method(initialIndex());
348 return QLatin1String(methodName(method
));
351 class QScriptMetaType
362 inline QScriptMetaType()
363 : m_kind(Invalid
) { }
365 inline Kind
kind() const
370 inline bool isValid() const
371 { return (m_kind
!= Invalid
); }
373 inline bool isVariant() const
374 { return (m_kind
== Variant
); }
376 inline bool isMetaType() const
377 { return (m_kind
== MetaType
); }
379 inline bool isUnresolved() const
380 { return (m_kind
== Unresolved
); }
382 inline bool isMetaEnum() const
383 { return (m_kind
== MetaEnum
); }
385 QByteArray
name() const;
387 inline int enumeratorIndex() const
388 { Q_ASSERT(isMetaEnum()); return m_typeId
; }
390 inline bool operator==(const QScriptMetaType
&other
) const
392 return (m_kind
== other
.m_kind
) && (m_typeId
== other
.m_typeId
);
395 static inline QScriptMetaType
variant()
396 { return QScriptMetaType(Variant
); }
398 static inline QScriptMetaType
metaType(int typeId
, const QByteArray
&name
)
399 { return QScriptMetaType(MetaType
, typeId
, name
); }
401 static inline QScriptMetaType
metaEnum(int enumIndex
, const QByteArray
&name
)
402 { return QScriptMetaType(MetaEnum
, enumIndex
, name
); }
404 static inline QScriptMetaType
unresolved(const QByteArray
&name
)
405 { return QScriptMetaType(Unresolved
, /*typeId=*/0, name
); }
408 inline QScriptMetaType(Kind kind
, int typeId
= 0, const QByteArray
&name
= QByteArray())
409 : m_kind(kind
), m_typeId(typeId
), m_name(name
) { }
416 int QScriptMetaType::typeId() const
419 return QMetaType::type("QVariant");
420 return isMetaEnum() ? 2/*int*/ : m_typeId
;
423 QByteArray
QScriptMetaType::name() const
425 if (!m_name
.isEmpty())
427 else if (m_kind
== Variant
)
429 return QMetaType::typeName(typeId());
432 class QScriptMetaMethod
435 inline QScriptMetaMethod()
437 inline QScriptMetaMethod(const QByteArray
&name
, const QVector
<QScriptMetaType
> &types
)
438 : m_name(name
), m_types(types
), m_firstUnresolvedIndex(-1)
440 QVector
<QScriptMetaType
>::const_iterator it
;
441 for (it
= m_types
.constBegin(); it
!= m_types
.constEnd(); ++it
) {
442 if ((*it
).kind() == QScriptMetaType::Unresolved
) {
443 m_firstUnresolvedIndex
= it
- m_types
.constBegin();
448 inline bool isValid() const
449 { return !m_types
.isEmpty(); }
451 QByteArray
name() const
454 inline QScriptMetaType
returnType() const
455 { return m_types
.at(0); }
457 inline int argumentCount() const
458 { return m_types
.count() - 1; }
460 inline QScriptMetaType
argumentType(int arg
) const
461 { return m_types
.at(arg
+ 1); }
463 inline bool fullyResolved() const
464 { return m_firstUnresolvedIndex
== -1; }
466 inline bool hasUnresolvedReturnType() const
467 { return (m_firstUnresolvedIndex
== 0); }
469 inline int firstUnresolvedIndex() const
470 { return m_firstUnresolvedIndex
; }
472 inline int count() const
473 { return m_types
.count(); }
475 inline QScriptMetaType
type(int index
) const
476 { return m_types
.at(index
); }
478 inline QVector
<QScriptMetaType
> types() const
483 QVector
<QScriptMetaType
> m_types
;
484 int m_firstUnresolvedIndex
;
487 struct QScriptMetaArguments
491 QScriptMetaMethod method
;
492 QVarLengthArray
<QVariant
, 9> args
;
494 inline QScriptMetaArguments(int dist
, int idx
, const QScriptMetaMethod
&mtd
,
495 const QVarLengthArray
<QVariant
, 9> &as
)
496 : matchDistance(dist
), index(idx
), method(mtd
), args(as
) { }
497 inline QScriptMetaArguments()
500 inline bool isValid() const
501 { return (index
!= -1); }
504 static QMetaMethod
metaMethod(const QMetaObject
*meta
,
505 QMetaMethod::MethodType type
,
508 if (type
!= QMetaMethod::Constructor
)
509 return meta
->method(index
);
511 return meta
->constructor(index
);
514 static JSC::JSValue
callQtMethod(JSC::ExecState
*exec
, QMetaMethod::MethodType callType
,
515 QObject
*thisQObject
, const JSC::ArgList
&scriptArgs
,
516 const QMetaObject
*meta
, int initialIndex
,
517 bool maybeOverloaded
)
520 QScriptMetaMethod chosenMethod
;
521 int chosenIndex
= -1;
522 QVarLengthArray
<QVariant
, 9> args
;
523 QVector
<QScriptMetaArguments
> candidates
;
524 QVector
<QScriptMetaArguments
> unresolved
;
525 QVector
<int> tooFewArgs
;
526 QVector
<int> conversionFailed
;
528 exec
->clearException();
529 QScriptEnginePrivate
*engine
= QScript::scriptEngineFromExec(exec
);
530 for (index
= initialIndex
; index
>= 0; --index
) {
531 QMetaMethod method
= metaMethod(meta
, callType
, index
);
533 if (index
== initialIndex
)
534 funName
= methodName(method
);
536 if (methodName(method
) != funName
)
540 QVector
<QScriptMetaType
> types
;
541 // resolve return type
542 QByteArray returnTypeName
= method
.typeName();
543 int rtype
= QMetaType::type(returnTypeName
);
544 if ((rtype
== 0) && !returnTypeName
.isEmpty()) {
545 if (returnTypeName
== "QVariant") {
546 types
.append(QScriptMetaType::variant());
548 int enumIndex
= indexOfMetaEnum(meta
, returnTypeName
);
550 types
.append(QScriptMetaType::metaEnum(enumIndex
, returnTypeName
));
552 types
.append(QScriptMetaType::unresolved(returnTypeName
));
555 if (callType
== QMetaMethod::Constructor
)
556 types
.append(QScriptMetaType::metaType(QMetaType::QObjectStar
, "QObject*"));
557 else if (returnTypeName
== "QVariant")
558 types
.append(QScriptMetaType::variant());
560 types
.append(QScriptMetaType::metaType(rtype
, returnTypeName
));
563 // resolve argument types
564 QList
<QByteArray
> parameterTypeNames
= method
.parameterTypes();
565 for (int i
= 0; i
< parameterTypeNames
.count(); ++i
) {
566 QByteArray argTypeName
= parameterTypeNames
.at(i
);
567 int atype
= QMetaType::type(argTypeName
);
569 if (argTypeName
== "QVariant") {
570 types
.append(QScriptMetaType::variant());
572 int enumIndex
= indexOfMetaEnum(meta
, argTypeName
);
574 types
.append(QScriptMetaType::metaEnum(enumIndex
, argTypeName
));
576 types
.append(QScriptMetaType::unresolved(argTypeName
));
579 if (argTypeName
== "QVariant")
580 types
.append(QScriptMetaType::variant());
582 types
.append(QScriptMetaType::metaType(atype
, argTypeName
));
586 QScriptMetaMethod mtd
= QScriptMetaMethod(methodName(method
), types
);
588 if (int(scriptArgs
.size()) < mtd
.argumentCount()) {
589 tooFewArgs
.append(index
);
593 if (!mtd
.fullyResolved()) {
594 // remember it so we can give an error message later, if necessary
595 unresolved
.append(QScriptMetaArguments(/*matchDistance=*/INT_MAX
, index
,
596 mtd
, QVarLengthArray
<QVariant
, 9>()));
597 if (mtd
.hasUnresolvedReturnType())
601 if (args
.count() != mtd
.count())
602 args
.resize(mtd
.count());
604 QScriptMetaType retType
= mtd
.returnType();
605 args
[0] = QVariant(retType
.typeId(), (void *)0); // the result
607 // try to convert arguments
608 bool converted
= true;
609 int matchDistance
= 0;
610 for (int i
= 0; converted
&& i
< mtd
.argumentCount(); ++i
) {
612 if (i
< (int)scriptArgs
.size())
613 actual
= engine
->scriptValueFromJSCValue(scriptArgs
.at(i
));
615 actual
= QScriptValue(QScriptValue::UndefinedValue
);
616 QScriptMetaType argType
= mtd
.argumentType(i
);
619 if (argType
.isUnresolved()) {
620 v
= QVariant(QMetaType::QObjectStar
, (void *)0);
621 converted
= engine
->convertToNativeQObject(
622 actual
, argType
.name(), reinterpret_cast<void* *>(v
.data()));
623 } else if (argType
.isVariant()) {
624 if (actual
.isVariant()) {
625 v
= actual
.toVariant();
627 v
= actual
.toVariant();
628 converted
= v
.isValid() || actual
.isUndefined() || actual
.isNull();
631 tid
= argType
.typeId();
632 v
= QVariant(tid
, (void *)0);
633 converted
= QScriptEnginePrivate::convert(actual
, tid
, v
.data(), engine
);
634 if (exec
->hadException())
635 return exec
->exception();
639 if (actual
.isVariant()) {
641 tid
= argType
.typeId();
642 QVariant vv
= actual
.toVariant();
643 if (vv
.canConvert(QVariant::Type(tid
))) {
645 converted
= v
.convert(QVariant::Type(tid
));
646 if (converted
&& (vv
.userType() != tid
))
649 QByteArray vvTypeName
= vv
.typeName();
650 if (vvTypeName
.endsWith('*')
651 && (vvTypeName
.left(vvTypeName
.size()-1) == argType
.name())) {
652 v
= QVariant(tid
, *reinterpret_cast<void* *>(vv
.data()));
657 } else if (actual
.isNumber() || actual
.isString()) {
658 // see if it's an enum value
660 if (argType
.isMetaEnum()) {
661 m
= meta
->enumerator(argType
.enumeratorIndex());
663 int mi
= indexOfMetaEnum(meta
, argType
.name());
665 m
= meta
->enumerator(mi
);
668 if (actual
.isNumber()) {
669 int ival
= actual
.toInt32();
670 if (m
.valueToKey(ival
) != 0) {
671 qVariantSetValue(v
, ival
);
676 QString sval
= actual
.toString();
677 int ival
= m
.keyToValue(sval
.toLatin1());
679 qVariantSetValue(v
, ival
);
687 // determine how well the conversion matched
688 if (actual
.isNumber()) {
690 case QMetaType::Double
:
693 case QMetaType::Float
:
696 case QMetaType::LongLong
:
697 case QMetaType::ULongLong
:
700 case QMetaType::Long
:
701 case QMetaType::ULong
:
705 case QMetaType::UInt
:
708 case QMetaType::Short
:
709 case QMetaType::UShort
:
712 case QMetaType::Char
:
713 case QMetaType::UChar
:
720 } else if (actual
.isString()) {
722 case QMetaType::QString
:
729 } else if (actual
.isBoolean()) {
731 case QMetaType::Bool
:
738 } else if (actual
.isDate()) {
740 case QMetaType::QDateTime
:
743 case QMetaType::QDate
:
746 case QMetaType::QTime
:
753 } else if (actual
.isRegExp()) {
755 case QMetaType::QRegExp
:
762 } else if (actual
.isVariant()) {
763 if (argType
.isVariant()
764 || (actual
.toVariant().userType() == tid
)) {
769 } else if (actual
.isArray()) {
771 case QMetaType::QStringList
:
772 case QMetaType::QVariantList
:
779 } else if (actual
.isQObject()) {
781 case QMetaType::QObjectStar
:
782 case QMetaType::QWidgetStar
:
789 } else if (actual
.isNull()) {
791 case QMetaType::VoidStar
:
792 case QMetaType::QObjectStar
:
793 case QMetaType::QWidgetStar
:
797 if (!argType
.name().endsWith('*'))
811 if ((scriptArgs
.size() == (size_t)mtd
.argumentCount())
812 && (matchDistance
== 0)) {
813 // perfect match, use this one
818 bool redundant
= false;
819 if ((callType
!= QMetaMethod::Constructor
)
820 && (index
< meta
->methodOffset())) {
821 // it is possible that a virtual method is redeclared in a subclass,
822 // in which case we want to ignore the superclass declaration
823 for (int i
= 0; i
< candidates
.size(); ++i
) {
824 const QScriptMetaArguments
&other
= candidates
.at(i
);
825 if (mtd
.types() == other
.method
.types()) {
832 QScriptMetaArguments
metaArgs(matchDistance
, index
, mtd
, args
);
833 if (candidates
.isEmpty()) {
834 candidates
.append(metaArgs
);
836 const QScriptMetaArguments
&otherArgs
= candidates
.at(0);
837 if ((args
.count() > otherArgs
.args
.count())
838 || ((args
.count() == otherArgs
.args
.count())
839 && (matchDistance
<= otherArgs
.matchDistance
))) {
840 candidates
.prepend(metaArgs
);
842 candidates
.append(metaArgs
);
847 } else if (mtd
.fullyResolved()) {
848 conversionFailed
.append(index
);
851 if (!maybeOverloaded
)
856 if ((chosenIndex
== -1) && candidates
.isEmpty()) {
857 // context->calleeMetaIndex = initialIndex;
858 //#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
859 // engine->notifyFunctionEntry(context);
861 if (!conversionFailed
.isEmpty()) {
862 QString message
= QString::fromLatin1("incompatible type of argument(s) in call to %0(); candidates were\n")
863 .arg(QLatin1String(funName
));
864 for (int i
= 0; i
< conversionFailed
.size(); ++i
) {
866 message
+= QLatin1String("\n");
867 QMetaMethod mtd
= metaMethod(meta
, callType
, conversionFailed
.at(i
));
868 message
+= QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd
.signature()));
870 result
= JSC::throwError(exec
, JSC::TypeError
, message
);
871 } else if (!unresolved
.isEmpty()) {
872 QScriptMetaArguments argsInstance
= unresolved
.first();
873 int unresolvedIndex
= argsInstance
.method
.firstUnresolvedIndex();
874 Q_ASSERT(unresolvedIndex
!= -1);
875 QScriptMetaType unresolvedType
= argsInstance
.method
.type(unresolvedIndex
);
876 QString unresolvedTypeName
= QString::fromLatin1(unresolvedType
.name());
877 QString message
= QString::fromLatin1("cannot call %0(): ")
878 .arg(QString::fromLatin1(funName
));
879 if (unresolvedIndex
> 0) {
880 message
.append(QString::fromLatin1("argument %0 has unknown type `%1'").
881 arg(unresolvedIndex
).arg(unresolvedTypeName
));
883 message
.append(QString::fromLatin1("unknown return type `%0'")
884 .arg(unresolvedTypeName
));
886 message
.append(QString::fromLatin1(" (register the type with qScriptRegisterMetaType())"));
887 result
= JSC::throwError(exec
, JSC::TypeError
, message
);
889 QString message
= QString::fromLatin1("too few arguments in call to %0(); candidates are\n")
890 .arg(QLatin1String(funName
));
891 for (int i
= 0; i
< tooFewArgs
.size(); ++i
) {
893 message
+= QLatin1String("\n");
894 QMetaMethod mtd
= metaMethod(meta
, callType
, tooFewArgs
.at(i
));
895 message
+= QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd
.signature()));
897 result
= JSC::throwError(exec
, JSC::SyntaxError
, message
);
900 if (chosenIndex
== -1) {
901 QScriptMetaArguments metaArgs
= candidates
.at(0);
902 if ((candidates
.size() > 1)
903 && (metaArgs
.args
.count() == candidates
.at(1).args
.count())
904 && (metaArgs
.matchDistance
== candidates
.at(1).matchDistance
)) {
906 QString message
= QString::fromLatin1("ambiguous call of overloaded function %0(); candidates were\n")
907 .arg(QLatin1String(funName
));
908 for (int i
= 0; i
< candidates
.size(); ++i
) {
910 message
+= QLatin1String("\n");
911 QMetaMethod mtd
= metaMethod(meta
, callType
, candidates
.at(i
).index
);
912 message
+= QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd
.signature()));
914 result
= JSC::throwError(exec
, JSC::TypeError
, message
);
916 chosenMethod
= metaArgs
.method
;
917 chosenIndex
= metaArgs
.index
;
918 args
= metaArgs
.args
;
922 if (chosenIndex
!= -1) {
924 // context->calleeMetaIndex = chosenIndex;
926 QVarLengthArray
<void*, 9> array(args
.count());
927 void **params
= array
.data();
928 for (int i
= 0; i
< args
.count(); ++i
) {
929 const QVariant
&v
= args
[i
];
930 switch (chosenMethod
.type(i
).kind()) {
931 case QScriptMetaType::Variant
:
932 params
[i
] = const_cast<QVariant
*>(&v
);
934 case QScriptMetaType::MetaType
:
935 case QScriptMetaType::MetaEnum
:
936 case QScriptMetaType::Unresolved
:
937 params
[i
] = const_cast<void*>(v
.constData());
944 QScriptable
*scriptable
= 0;
946 scriptable
= scriptableFromQObject(thisQObject
);
947 QScriptEngine
*oldEngine
= 0;
949 oldEngine
= QScriptablePrivate::get(scriptable
)->engine
;
950 QScriptablePrivate::get(scriptable
)->engine
= QScriptEnginePrivate::get(engine
);
954 //#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
955 // engine->notifyFunctionEntry(context);
958 if (callType
== QMetaMethod::Constructor
) {
960 meta
->static_metacall(QMetaObject::CreateInstance
, chosenIndex
, params
);
962 QMetaObject::metacall(thisQObject
, QMetaObject::InvokeMetaMethod
, chosenIndex
, params
);
966 QScriptablePrivate::get(scriptable
)->engine
= oldEngine
;
968 if (exec
->hadException()) {
969 result
= exec
->exception() ; // propagate
971 QScriptMetaType retType
= chosenMethod
.returnType();
972 if (retType
.isVariant()) {
973 result
= engine
->jscValueFromVariant(*(QVariant
*)params
[0]);
974 } else if (retType
.typeId() != 0) {
975 result
= engine
->scriptValueToJSCValue(engine
->create(retType
.typeId(), params
[0]));
977 QScriptValue sv
= QScriptEnginePrivate::get(engine
)->newVariant(QVariant(retType
.typeId(), params
[0]));
978 result
= engine
->scriptValueToJSCValue(sv
);
981 result
= JSC::jsUndefined();
990 JSC::JSValue
QtFunction::execute(JSC::ExecState
*exec
, JSC::JSValue thisValue
,
991 const JSC::ArgList
&scriptArgs
)
993 Q_ASSERT(data
->object
.inherits(&QScriptObject::info
));
994 QScriptObject
*scriptObject
= static_cast<QScriptObject
*>(JSC::asObject(data
->object
));
995 QScriptObjectDelegate
*delegate
= scriptObject
->delegate();
996 Q_ASSERT(delegate
&& (delegate
->type() == QScriptObjectDelegate::QtObject
));
997 QObject
*qobj
= static_cast<QScript::QObjectDelegate
*>(delegate
)->value();
998 Q_ASSERT_X(qobj
!= 0, "QtFunction::call", "handle the case when QObject has been deleted");
999 QScriptEnginePrivate
*engine
= scriptEngineFromExec(exec
);
1001 const QMetaObject
*meta
= qobj
->metaObject();
1002 QObject
*thisQObject
= 0;
1003 thisValue
= engine
->toUsableValue(thisValue
);
1004 if (thisValue
.inherits(&QScriptObject::info
)) {
1005 delegate
= static_cast<QScriptObject
*>(JSC::asObject(thisValue
))->delegate();
1006 if (delegate
&& (delegate
->type() == QScriptObjectDelegate::QtObject
))
1007 thisQObject
= static_cast<QScript::QObjectDelegate
*>(delegate
)->value();
1010 thisQObject
= qobj
; // ### TypeError
1012 if (!meta
->cast(thisQObject
)) {
1013 // invoking a function in the prototype
1017 return callQtMethod(exec
, QMetaMethod::Method
, thisQObject
, scriptArgs
,
1018 meta
, data
->initialIndex
, data
->maybeOverloaded
);
1021 const JSC::ClassInfo
QtFunction::info
= { "QtFunction", &InternalFunction::info
, 0, 0 };
1023 JSC::JSValue JSC_HOST_CALL
QtFunction::call(JSC::ExecState
*exec
, JSC::JSObject
*callee
,
1024 JSC::JSValue thisValue
, const JSC::ArgList
&args
)
1026 if (!callee
->inherits(&QtFunction::info
))
1027 return throwError(exec
, JSC::TypeError
, "callee is not a QtFunction object");
1028 QtFunction
*qfun
= static_cast<QtFunction
*>(callee
);
1029 QScriptEnginePrivate
*eng_p
= scriptEngineFromExec(exec
);
1030 JSC::ExecState
*previousFrame
= eng_p
->currentFrame
;
1031 eng_p
->currentFrame
= exec
;
1032 eng_p
->pushContext(exec
, thisValue
, args
, callee
);
1033 JSC::JSValue result
= qfun
->execute(eng_p
->currentFrame
, thisValue
, args
);
1034 eng_p
->popContext();
1035 eng_p
->currentFrame
= previousFrame
;
1039 const JSC::ClassInfo
QtPropertyFunction::info
= { "QtPropertyFunction", &InternalFunction::info
, 0, 0 };
1041 QtPropertyFunction::QtPropertyFunction(const QMetaObject
*meta
, int index
,
1042 JSC::JSGlobalData
*data
,
1043 WTF::PassRefPtr
<JSC::Structure
> sid
,
1044 const JSC::Identifier
&ident
)
1045 : JSC::InternalFunction(data
, sid
, ident
),
1046 data(new Data(meta
, index
))
1050 QtPropertyFunction::~QtPropertyFunction()
1055 JSC::CallType
QtPropertyFunction::getCallData(JSC::CallData
&callData
)
1057 callData
.native
.function
= call
;
1058 return JSC::CallTypeHost
;
1061 JSC::JSValue JSC_HOST_CALL
QtPropertyFunction::call(
1062 JSC::ExecState
*exec
, JSC::JSObject
*callee
,
1063 JSC::JSValue thisValue
, const JSC::ArgList
&args
)
1065 if (!callee
->inherits(&QtPropertyFunction::info
))
1066 return throwError(exec
, JSC::TypeError
, "callee is not a QtPropertyFunction object");
1067 QtPropertyFunction
*qfun
= static_cast<QtPropertyFunction
*>(callee
);
1068 QScriptEnginePrivate
*eng_p
= scriptEngineFromExec(exec
);
1069 JSC::ExecState
*previousFrame
= eng_p
->currentFrame
;
1070 eng_p
->currentFrame
= exec
;
1071 eng_p
->pushContext(exec
, thisValue
, args
, callee
);
1072 JSC::JSValue result
= qfun
->execute(eng_p
->currentFrame
, thisValue
, args
);
1073 eng_p
->popContext();
1074 eng_p
->currentFrame
= previousFrame
;
1078 JSC::JSValue
QtPropertyFunction::execute(JSC::ExecState
*exec
,
1079 JSC::JSValue thisValue
,
1080 const JSC::ArgList
&args
)
1082 JSC::JSValue result
= JSC::jsUndefined();
1084 // ### don't go via QScriptValue
1085 QScriptEnginePrivate
*engine
= scriptEngineFromExec(exec
);
1086 thisValue
= engine
->toUsableValue(thisValue
);
1087 QScriptValue object
= engine
->scriptValueFromJSCValue(thisValue
);
1088 QObject
*qobject
= object
.toQObject();
1089 while ((!qobject
|| (qobject
->metaObject() != data
->meta
))
1090 && object
.prototype().isObject()) {
1091 object
= object
.prototype();
1092 qobject
= object
.toQObject();
1094 Q_ASSERT_X(qobject
, Q_FUNC_INFO
, "this-object must be a QObject");
1096 QMetaProperty prop
= data
->meta
->property(data
->index
);
1097 Q_ASSERT(prop
.isScriptable());
1098 if (args
.size() == 0) {
1100 if (prop
.isValid()) {
1101 QScriptable
*scriptable
= scriptableFromQObject(qobject
);
1102 QScriptEngine
*oldEngine
= 0;
1104 oldEngine
= QScriptablePrivate::get(scriptable
)->engine
;
1105 QScriptablePrivate::get(scriptable
)->engine
= QScriptEnginePrivate::get(engine
);
1108 QVariant v
= prop
.read(qobject
);
1111 QScriptablePrivate::get(scriptable
)->engine
= oldEngine
;
1113 result
= engine
->jscValueFromVariant(v
);
1117 JSC::JSValue arg
= args
.at(0);
1119 if (prop
.isEnumType() && arg
.isString()
1120 && !engine
->hasDemarshalFunction(prop
.userType())) {
1121 // give QMetaProperty::write() a chance to convert from
1122 // string to enum value
1123 v
= (QString
)arg
.toString(exec
);
1125 // ### don't go via QScriptValue
1126 QScriptValue tmp
= engine
->scriptValueFromJSCValue(arg
);
1127 v
= variantFromValue(engine
, prop
.userType(), tmp
);
1130 QScriptable
*scriptable
= scriptableFromQObject(qobject
);
1131 QScriptEngine
*oldEngine
= 0;
1133 oldEngine
= QScriptablePrivate::get(scriptable
)->engine
;
1134 QScriptablePrivate::get(scriptable
)->engine
= QScriptEnginePrivate::get(engine
);
1137 prop
.write(qobject
, v
);
1140 QScriptablePrivate::get(scriptable
)->engine
= oldEngine
;
1147 const QMetaObject
*QtPropertyFunction::metaObject() const
1152 int QtPropertyFunction::propertyIndex() const
1158 QObjectDelegate::QObjectDelegate(
1159 QObject
*object
, QScriptEngine::ValueOwnership ownership
,
1160 const QScriptEngine::QObjectWrapOptions
&options
)
1161 : data(new Data(object
, ownership
, options
))
1165 QObjectDelegate::~QObjectDelegate()
1167 switch (data
->ownership
) {
1168 case QScriptEngine::QtOwnership
:
1170 case QScriptEngine::ScriptOwnership
:
1172 delete data
->value
; // ### fixme
1173 // eng->disposeQObject(value);
1175 case QScriptEngine::AutoOwnership
:
1176 if (data
->value
&& !data
->value
->parent())
1177 delete data
->value
; // ### fixme
1178 // eng->disposeQObject(value);
1184 QScriptObjectDelegate::Type
QObjectDelegate::type() const
1189 bool QObjectDelegate::getOwnPropertySlot(QScriptObject
*object
, JSC::ExecState
*exec
,
1190 const JSC::Identifier
&propertyName
,
1191 JSC::PropertySlot
&slot
)
1193 #ifndef QT_NO_PROPERTIES
1194 QByteArray name
= QString(propertyName
.ustring()).toLatin1();
1195 QObject
*qobject
= data
->value
;
1197 QString message
= QString::fromLatin1("cannot access member `%0' of deleted QObject")
1198 .arg(QString::fromLatin1(name
));
1199 slot
.setValue(JSC::throwError(exec
, JSC::GeneralError
, message
));
1203 const QMetaObject
*meta
= qobject
->metaObject();
1205 QHash
<QByteArray
, JSC::JSValue
>::const_iterator it
= data
->cachedMembers
.constFind(name
);
1206 if (it
!= data
->cachedMembers
.constEnd()) {
1207 if (GeneratePropertyFunctions
&& (meta
->indexOfProperty(name
) != -1))
1208 slot
.setGetterSlot(JSC::asObject(it
.value()));
1210 slot
.setValue(it
.value());
1215 const QScriptEngine::QObjectWrapOptions
&opt
= data
->options
;
1216 QScriptEnginePrivate
*eng
= scriptEngineFromExec(exec
);
1218 if (name
.contains('(')) {
1219 QByteArray normalized
= QMetaObject::normalizedSignature(name
);
1220 if (-1 != (index
= meta
->indexOfMethod(normalized
))) {
1221 QMetaMethod method
= meta
->method(index
);
1222 if (hasMethodAccess(method
, index
, opt
)) {
1223 if (!(opt
& QScriptEngine::ExcludeSuperClassMethods
)
1224 || (index
>= meta
->methodOffset())) {
1225 QtFunction
*fun
= new (exec
)QtFunction(
1226 object
, index
, /*maybeOverloaded=*/false,
1227 &exec
->globalData(), eng
->originalGlobalObject()->functionStructure(),
1230 data
->cachedMembers
.insert(name
, fun
);
1237 index
= meta
->indexOfProperty(name
);
1239 QMetaProperty prop
= meta
->property(index
);
1240 if (prop
.isScriptable()) {
1241 if (!(opt
& QScriptEngine::ExcludeSuperClassProperties
)
1242 || (index
>= meta
->propertyOffset())) {
1243 if (GeneratePropertyFunctions
) {
1244 QtPropertyFunction
*fun
= new (exec
)QtPropertyFunction(
1245 meta
, index
, &exec
->globalData(),
1246 eng
->originalGlobalObject()->functionStructure(),
1248 data
->cachedMembers
.insert(name
, fun
);
1249 slot
.setGetterSlot(fun
);
1252 if (!prop
.isValid())
1253 val
= JSC::jsUndefined();
1255 val
= eng
->jscValueFromVariant(prop
.read(qobject
));
1263 index
= qobject
->dynamicPropertyNames().indexOf(name
);
1265 JSC::JSValue val
= eng
->jscValueFromVariant(qobject
->property(name
));
1270 const int offset
= (opt
& QScriptEngine::ExcludeSuperClassMethods
)
1271 ? meta
->methodOffset() : 0;
1272 for (index
= meta
->methodCount() - 1; index
>= offset
; --index
) {
1273 QMetaMethod method
= meta
->method(index
);
1274 if (hasMethodAccess(method
, index
, opt
)
1275 && (methodName(method
) == name
)) {
1276 QtFunction
*fun
= new (exec
)QtFunction(
1277 object
, index
, /*maybeOverloaded=*/true,
1278 &exec
->globalData(), eng
->originalGlobalObject()->functionStructure(),
1281 data
->cachedMembers
.insert(name
, fun
);
1286 if (!(opt
& QScriptEngine::ExcludeChildObjects
)) {
1287 QList
<QObject
*> children
= qobject
->children();
1288 for (index
= 0; index
< children
.count(); ++index
) {
1289 QObject
*child
= children
.at(index
);
1290 if (child
->objectName() == QString(propertyName
.ustring())) {
1291 QScriptEngine::QObjectWrapOptions opt
= QScriptEngine::PreferExistingWrapperObject
;
1292 QScriptValue tmp
= QScriptEnginePrivate::get(eng
)->newQObject(child
, QScriptEngine::QtOwnership
, opt
);
1293 slot
.setValue(eng
->scriptValueToJSCValue(tmp
));
1299 return QScriptObjectDelegate::getOwnPropertySlot(object
, exec
, propertyName
, slot
);
1300 #else //QT_NO_PROPERTIES
1302 #endif //QT_NO_PROPERTIES
1305 void QObjectDelegate::put(QScriptObject
*object
, JSC::ExecState
* exec
,
1306 const JSC::Identifier
& propertyName
,
1307 JSC::JSValue value
, JSC::PutPropertySlot
&slot
)
1309 #ifndef QT_NO_PROPERTIES
1310 QByteArray name
= ((QString
)propertyName
.ustring()).toLatin1();
1311 QObject
*qobject
= data
->value
;
1313 QString message
= QString::fromLatin1("cannot access member `%0' of deleted QObject")
1314 .arg(QString::fromLatin1(name
));
1315 JSC::throwError(exec
, JSC::GeneralError
, message
);
1319 const QScriptEngine::QObjectWrapOptions
&opt
= data
->options
;
1320 const QMetaObject
*meta
= qobject
->metaObject();
1321 QScriptEnginePrivate
*eng
= scriptEngineFromExec(exec
);
1323 if (name
.contains('(')) {
1324 QByteArray normalized
= QMetaObject::normalizedSignature(name
);
1325 if (-1 != (index
= meta
->indexOfMethod(normalized
))) {
1326 QMetaMethod method
= meta
->method(index
);
1327 if (hasMethodAccess(method
, index
, opt
)) {
1328 if (!(opt
& QScriptEngine::ExcludeSuperClassMethods
)
1329 || (index
>= meta
->methodOffset())) {
1330 data
->cachedMembers
.insert(name
, value
);
1337 index
= meta
->indexOfProperty(name
);
1339 QMetaProperty prop
= meta
->property(index
);
1340 if (prop
.isScriptable()) {
1341 if (!(opt
& QScriptEngine::ExcludeSuperClassProperties
)
1342 || (index
>= meta
->propertyOffset())) {
1343 if (GeneratePropertyFunctions
) {
1344 // ### ideally JSC would do this for us already, i.e. find out
1345 // that the property is a setter and call the setter.
1346 // Maybe QtPropertyFunction needs to inherit JSC::GetterSetter.
1348 QHash
<QByteArray
, JSC::JSValue
>::const_iterator it
;
1349 it
= data
->cachedMembers
.constFind(name
);
1350 if (it
!= data
->cachedMembers
.constEnd()) {
1353 fun
= new (exec
)QtPropertyFunction(
1354 meta
, index
, &exec
->globalData(),
1355 eng
->originalGlobalObject()->functionStructure(),
1357 data
->cachedMembers
.insert(name
, fun
);
1359 JSC::CallData callData
;
1360 JSC::CallType callType
= fun
.getCallData(callData
);
1361 JSC::JSValue argv
[1] = { value
};
1362 JSC::ArgList
args(argv
, 1);
1363 (void)JSC::call(exec
, fun
, callType
, callData
, object
, args
);
1366 if (prop
.isEnumType() && value
.isString()
1367 && !eng
->hasDemarshalFunction(prop
.userType())) {
1368 // give QMetaProperty::write() a chance to convert from
1369 // string to enum value
1370 v
= (QString
)value
.toString(exec
);
1372 v
= eng
->jscValueToVariant(value
, prop
.userType());
1374 (void)prop
.write(qobject
, v
);
1381 const int offset
= (opt
& QScriptEngine::ExcludeSuperClassMethods
)
1382 ? meta
->methodOffset() : 0;
1383 for (index
= meta
->methodCount() - 1; index
>= offset
; --index
) {
1384 QMetaMethod method
= meta
->method(index
);
1385 if (hasMethodAccess(method
, index
, opt
)
1386 && (methodName(method
) == name
)) {
1387 data
->cachedMembers
.insert(name
, value
);
1392 index
= qobject
->dynamicPropertyNames().indexOf(name
);
1393 if ((index
!= -1) || (opt
& QScriptEngine::AutoCreateDynamicProperties
)) {
1394 QVariant v
= eng
->scriptValueFromJSCValue(value
).toVariant();
1395 (void)qobject
->setProperty(name
, v
);
1399 QScriptObjectDelegate::put(object
, exec
, propertyName
, value
, slot
);
1400 #endif //QT_NO_PROPERTIES
1403 bool QObjectDelegate::deleteProperty(QScriptObject
*object
, JSC::ExecState
*exec
,
1404 const JSC::Identifier
& propertyName
,
1405 bool checkDontDelete
)
1407 #ifndef QT_NO_PROPERTIES
1408 QByteArray name
= ((QString
)propertyName
.ustring()).toLatin1();
1409 QObject
*qobject
= data
->value
;
1411 QString message
= QString::fromLatin1("cannot access member `%0' of deleted QObject")
1412 .arg(QString::fromLatin1(name
));
1413 JSC::throwError(exec
, JSC::GeneralError
, message
);
1417 const QMetaObject
*meta
= qobject
->metaObject();
1419 QHash
<QByteArray
, JSC::JSValue
>::iterator it
= data
->cachedMembers
.find(name
);
1420 if (it
!= data
->cachedMembers
.end()) {
1421 if (GeneratePropertyFunctions
&& (meta
->indexOfProperty(name
) != -1))
1423 data
->cachedMembers
.erase(it
);
1428 const QScriptEngine::QObjectWrapOptions
&opt
= data
->options
;
1429 int index
= meta
->indexOfProperty(name
);
1431 QMetaProperty prop
= meta
->property(index
);
1432 if (prop
.isScriptable() &&
1433 (!(opt
& QScriptEngine::ExcludeSuperClassProperties
)
1434 || (index
>= meta
->propertyOffset()))) {
1439 index
= qobject
->dynamicPropertyNames().indexOf(name
);
1441 (void)qobject
->setProperty(name
, QVariant());
1445 return QScriptObjectDelegate::deleteProperty(object
, exec
, propertyName
, checkDontDelete
);
1446 #else //QT_NO_PROPERTIES
1448 #endif //QT_NO_PROPERTIES
1451 bool QObjectDelegate::getPropertyAttributes(const QScriptObject
*object
,
1452 JSC::ExecState
*exec
,
1453 const JSC::Identifier
&propertyName
,
1454 unsigned &attributes
) const
1456 #ifndef QT_NO_PROPERTIES
1457 // ### try to avoid duplicating logic from getOwnPropertySlot()
1458 QByteArray name
= ((QString
)propertyName
.ustring()).toLatin1();
1459 QObject
*qobject
= data
->value
;
1463 const QScriptEngine::QObjectWrapOptions
&opt
= data
->options
;
1464 const QMetaObject
*meta
= qobject
->metaObject();
1466 if (name
.contains('(')) {
1467 QByteArray normalized
= QMetaObject::normalizedSignature(name
);
1468 if (-1 != (index
= meta
->indexOfMethod(normalized
))) {
1469 QMetaMethod method
= meta
->method(index
);
1470 if (hasMethodAccess(method
, index
, opt
)) {
1471 if (!(opt
& QScriptEngine::ExcludeSuperClassMethods
)
1472 || (index
>= meta
->methodOffset())) {
1473 attributes
= QObjectMemberAttribute
;
1474 if (opt
& QScriptEngine::SkipMethodsInEnumeration
)
1475 attributes
|= JSC::DontEnum
;
1482 index
= meta
->indexOfProperty(name
);
1484 QMetaProperty prop
= meta
->property(index
);
1485 if (prop
.isScriptable()) {
1486 if (!(opt
& QScriptEngine::ExcludeSuperClassProperties
)
1487 || (index
>= meta
->propertyOffset())) {
1488 attributes
= flagsForMetaProperty(prop
);
1494 index
= qobject
->dynamicPropertyNames().indexOf(name
);
1496 attributes
= QObjectMemberAttribute
;
1500 const int offset
= (opt
& QScriptEngine::ExcludeSuperClassMethods
)
1501 ? meta
->methodOffset() : 0;
1502 for (index
= meta
->methodCount() - 1; index
>= offset
; --index
) {
1503 QMetaMethod method
= meta
->method(index
);
1504 if (hasMethodAccess(method
, index
, opt
)
1505 && (methodName(method
) == name
)) {
1506 attributes
= QObjectMemberAttribute
;
1507 if (opt
& QScriptEngine::SkipMethodsInEnumeration
)
1508 attributes
|= JSC::DontEnum
;
1513 if (!(opt
& QScriptEngine::ExcludeChildObjects
)) {
1514 QList
<QObject
*> children
= qobject
->children();
1515 for (index
= 0; index
< children
.count(); ++index
) {
1516 QObject
*child
= children
.at(index
);
1517 if (child
->objectName() == (QString
)(propertyName
.ustring())) {
1518 attributes
= JSC::ReadOnly
| JSC::DontDelete
| JSC::DontEnum
;
1524 return QScriptObjectDelegate::getPropertyAttributes(object
, exec
, propertyName
, attributes
);
1525 #else //QT_NO_PROPERTIES
1527 #endif //QT_NO_PROPERTIES
1530 void QObjectDelegate::getOwnPropertyNames(QScriptObject
*object
, JSC::ExecState
*exec
,
1531 JSC::PropertyNameArray
&propertyNames
,
1532 bool includeNonEnumerable
)
1534 #ifndef QT_NO_PROPERTIES
1535 QObject
*qobject
= data
->value
;
1537 QString message
= QString::fromLatin1("cannot get property names of deleted QObject");
1538 JSC::throwError(exec
, JSC::GeneralError
, message
);
1542 const QScriptEngine::QObjectWrapOptions
&opt
= data
->options
;
1543 const QMetaObject
*meta
= qobject
->metaObject();
1545 int i
= (opt
& QScriptEngine::ExcludeSuperClassProperties
)
1546 ? meta
->propertyOffset() : 0;
1547 for ( ; i
< meta
->propertyCount(); ++i
) {
1548 QMetaProperty prop
= meta
->property(i
);
1549 if (isEnumerableMetaProperty(prop
, meta
, i
)) {
1550 QString name
= QString::fromLatin1(prop
.name());
1551 propertyNames
.add(JSC::Identifier(exec
, name
));
1557 QList
<QByteArray
> dpNames
= qobject
->dynamicPropertyNames();
1558 for (int i
= 0; i
< dpNames
.size(); ++i
) {
1559 QString name
= QString::fromLatin1(dpNames
.at(i
));
1560 propertyNames
.add(JSC::Identifier(exec
, name
));
1564 if (!(opt
& QScriptEngine::SkipMethodsInEnumeration
)) {
1565 int i
= (opt
& QScriptEngine::ExcludeSuperClassMethods
)
1566 ? meta
->methodOffset() : 0;
1567 for ( ; i
< meta
->methodCount(); ++i
) {
1568 QMetaMethod method
= meta
->method(i
);
1569 if (hasMethodAccess(method
, i
, opt
)) {
1570 QMetaMethod method
= meta
->method(i
);
1571 QString sig
= QString::fromLatin1(method
.signature());
1572 propertyNames
.add(JSC::Identifier(exec
, sig
));
1577 QScriptObjectDelegate::getOwnPropertyNames(object
, exec
, propertyNames
, includeNonEnumerable
);
1578 #endif //QT_NO_PROPERTIES
1581 void QObjectDelegate::markChildren(QScriptObject
*object
, JSC::MarkStack
& markStack
)
1583 QHash
<QByteArray
, JSC::JSValue
>::const_iterator it
;
1584 for (it
= data
->cachedMembers
.constBegin(); it
!= data
->cachedMembers
.constEnd(); ++it
) {
1585 JSC::JSValue val
= it
.value();
1587 markStack
.append(val
);
1590 QScriptObjectDelegate::markChildren(object
, markStack
);
1593 bool QObjectDelegate::compareToObject(QScriptObject
*, JSC::ExecState
*exec
, JSC::JSObject
*o2
)
1595 if (!o2
->inherits(&QScriptObject::info
))
1597 QScriptObject
*object
= static_cast<QScriptObject
*>(o2
);
1598 QScriptObjectDelegate
*delegate
= object
->delegate();
1599 if (!delegate
|| (delegate
->type() != QScriptObjectDelegate::QtObject
))
1601 return value() == static_cast<QObjectDelegate
*>(delegate
)->value();
1604 static JSC::JSValue JSC_HOST_CALL
qobjectProtoFuncFindChild(JSC::ExecState
*exec
, JSC::JSObject
*,
1605 JSC::JSValue thisValue
, const JSC::ArgList
&args
)
1607 QScriptEnginePrivate
*engine
= scriptEngineFromExec(exec
);
1608 thisValue
= engine
->toUsableValue(thisValue
);
1609 if (!thisValue
.inherits(&QScriptObject::info
))
1610 return throwError(exec
, JSC::TypeError
, "this object is not a QObject");
1611 QScriptObject
*scriptObject
= static_cast<QScriptObject
*>(JSC::asObject(thisValue
));
1612 QScriptObjectDelegate
*delegate
= scriptObject
->delegate();
1613 if (!delegate
|| (delegate
->type() != QScriptObjectDelegate::QtObject
))
1614 return throwError(exec
, JSC::TypeError
, "this object is not a QObject");
1615 QObject
*obj
= static_cast<QObjectDelegate
*>(delegate
)->value();
1617 if (args
.size() != 0)
1618 name
= args
.at(0).toString(exec
);
1619 QObject
*child
= qFindChild
<QObject
*>(obj
, name
);
1620 QScriptEngine::QObjectWrapOptions opt
= QScriptEngine::PreferExistingWrapperObject
;
1621 return engine
->newQObject(child
, QScriptEngine::QtOwnership
, opt
);
1624 static JSC::JSValue JSC_HOST_CALL
qobjectProtoFuncFindChildren(JSC::ExecState
*exec
, JSC::JSObject
*,
1625 JSC::JSValue thisValue
, const JSC::ArgList
&args
)
1627 QScriptEnginePrivate
*engine
= scriptEngineFromExec(exec
);
1628 thisValue
= engine
->toUsableValue(thisValue
);
1629 // extract the QObject
1630 if (!thisValue
.inherits(&QScriptObject::info
))
1631 return throwError(exec
, JSC::TypeError
, "this object is not a QObject");
1632 QScriptObject
*scriptObject
= static_cast<QScriptObject
*>(JSC::asObject(thisValue
));
1633 QScriptObjectDelegate
*delegate
= scriptObject
->delegate();
1634 if (!delegate
|| (delegate
->type() != QScriptObjectDelegate::QtObject
))
1635 return throwError(exec
, JSC::TypeError
, "this object is not a QObject");
1636 const QObject
*const obj
= static_cast<QObjectDelegate
*>(delegate
)->value();
1638 // find the children
1639 QList
<QObject
*> children
;
1640 if (args
.size() != 0) {
1641 const JSC::JSValue arg
= args
.at(0);
1642 if (arg
.inherits(&JSC::RegExpObject::info
)) {
1643 const QObjectList allChildren
= obj
->children();
1645 JSC::RegExpObject
*const regexp
= JSC::asRegExpObject(arg
);
1647 const int allChildrenCount
= allChildren
.size();
1648 for (int i
= 0; i
< allChildrenCount
; ++i
) {
1649 QObject
*const child
= allChildren
.at(i
);
1650 const JSC::UString childName
= child
->objectName();
1651 JSC::RegExpConstructor
* regExpConstructor
= engine
->originalGlobalObject()->regExpConstructor();
1654 regExpConstructor
->performMatch(regexp
->regExp(), childName
, 0, position
, length
);
1656 children
.append(child
);
1659 const QString
name(args
.at(0).toString(exec
));
1660 children
= qFindChildren
<QObject
*>(obj
, name
);
1663 children
= qFindChildren
<QObject
*>(obj
, QString());
1665 // create the result array with the children
1666 const int length
= children
.size();
1667 JSC::JSArray
*const result
= JSC::constructEmptyArray(exec
, length
);
1669 QScriptEngine::QObjectWrapOptions opt
= QScriptEngine::PreferExistingWrapperObject
;
1670 for (int i
= 0; i
< length
; ++i
) {
1671 QObject
*const child
= children
.at(i
);
1672 result
->put(exec
, i
, engine
->newQObject(child
, QScriptEngine::QtOwnership
, opt
));
1674 return JSC::JSValue(result
);
1677 static JSC::JSValue JSC_HOST_CALL
qobjectProtoFuncToString(JSC::ExecState
*exec
, JSC::JSObject
*,
1678 JSC::JSValue thisValue
, const JSC::ArgList
&)
1680 QScriptEnginePrivate
*engine
= scriptEngineFromExec(exec
);
1681 thisValue
= engine
->toUsableValue(thisValue
);
1682 if (!thisValue
.inherits(&QScriptObject::info
))
1683 return JSC::jsUndefined();
1684 QScriptObject
*scriptObject
= static_cast<QScriptObject
*>(JSC::asObject(thisValue
));
1685 QScriptObjectDelegate
*delegate
= scriptObject
->delegate();
1686 if (!delegate
|| (delegate
->type() != QScriptObjectDelegate::QtObject
))
1687 return JSC::jsUndefined();
1688 QObject
*obj
= static_cast<QObjectDelegate
*>(delegate
)->value();
1689 const QMetaObject
*meta
= obj
? obj
->metaObject() : &QObject::staticMetaObject
;
1690 QString name
= obj
? obj
->objectName() : QString::fromUtf8("unnamed");
1691 QString str
= QString::fromUtf8("%0(name = \"%1\")")
1692 .arg(QLatin1String(meta
->className())).arg(name
);
1693 return JSC::jsString(exec
, str
);
1696 QObjectPrototype::QObjectPrototype(JSC::ExecState
* exec
, WTF::PassRefPtr
<JSC::Structure
> structure
,
1697 JSC::Structure
* prototypeFunctionStructure
)
1698 : QScriptObject(structure
)
1700 setDelegate(new QObjectDelegate(new QObjectPrototypeObject(), QScriptEngine::AutoOwnership
,
1701 QScriptEngine::ExcludeSuperClassMethods
1702 | QScriptEngine::ExcludeSuperClassProperties
1703 | QScriptEngine::ExcludeChildObjects
));
1705 putDirectFunction(exec
, new (exec
) JSC::PrototypeFunction(exec
, prototypeFunctionStructure
, /*length=*/0, exec
->propertyNames().toString
, qobjectProtoFuncToString
), JSC::DontEnum
);
1706 putDirectFunction(exec
, new (exec
) JSC::PrototypeFunction(exec
, prototypeFunctionStructure
, /*length=*/1, JSC::Identifier(exec
, "findChild"), qobjectProtoFuncFindChild
), JSC::DontEnum
);
1707 putDirectFunction(exec
, new (exec
) JSC::PrototypeFunction(exec
, prototypeFunctionStructure
, /*length=*/1, JSC::Identifier(exec
, "findChildren"), qobjectProtoFuncFindChildren
), JSC::DontEnum
);
1710 const JSC::ClassInfo
QMetaObjectWrapperObject::info
= { "QMetaObject", 0, 0, 0 };
1712 QMetaObjectWrapperObject::QMetaObjectWrapperObject(
1713 JSC::ExecState
*exec
, const QMetaObject
*metaObject
, JSC::JSValue ctor
,
1714 WTF::PassRefPtr
<JSC::Structure
> sid
)
1715 : JSC::JSObject(sid
),
1716 data(new Data(metaObject
, ctor
))
1719 data
->prototype
= new (exec
)JSC::JSObject(exec
->lexicalGlobalObject()->emptyObjectStructure());
1722 QMetaObjectWrapperObject::~QMetaObjectWrapperObject()
1727 bool QMetaObjectWrapperObject::getOwnPropertySlot(
1728 JSC::ExecState
*exec
, const JSC::Identifier
& propertyName
,
1729 JSC::PropertySlot
&slot
)
1731 const QMetaObject
*meta
= data
->value
;
1735 if (propertyName
== exec
->propertyNames().prototype
) {
1737 slot
.setValue(data
->ctor
.get(exec
, propertyName
));
1739 slot
.setValue(data
->prototype
);
1743 QByteArray name
= QString(propertyName
.ustring()).toLatin1();
1745 for (int i
= 0; i
< meta
->enumeratorCount(); ++i
) {
1746 QMetaEnum e
= meta
->enumerator(i
);
1747 for (int j
= 0; j
< e
.keyCount(); ++j
) {
1748 const char *key
= e
.key(j
);
1749 if (!qstrcmp(key
, name
.constData())) {
1750 slot
.setValue(JSC::JSValue(exec
, e
.value(j
)));
1756 return JSC::JSObject::getOwnPropertySlot(exec
, propertyName
, slot
);
1759 void QMetaObjectWrapperObject::put(JSC::ExecState
* exec
, const JSC::Identifier
& propertyName
,
1760 JSC::JSValue value
, JSC::PutPropertySlot
&slot
)
1762 if (propertyName
== exec
->propertyNames().prototype
) {
1764 data
->ctor
.put(exec
, propertyName
, value
, slot
);
1766 data
->prototype
= value
;
1769 const QMetaObject
*meta
= data
->value
;
1771 QByteArray name
= QString(propertyName
.ustring()).toLatin1();
1772 for (int i
= 0; i
< meta
->enumeratorCount(); ++i
) {
1773 QMetaEnum e
= meta
->enumerator(i
);
1774 for (int j
= 0; j
< e
.keyCount(); ++j
) {
1775 if (!qstrcmp(e
.key(j
), name
.constData()))
1780 JSC::JSObject::put(exec
, propertyName
, value
, slot
);
1783 bool QMetaObjectWrapperObject::deleteProperty(
1784 JSC::ExecState
*exec
, const JSC::Identifier
& propertyName
,
1785 bool checkDontDelete
)
1787 if (propertyName
== exec
->propertyNames().prototype
)
1789 const QMetaObject
*meta
= data
->value
;
1791 QByteArray name
= QString(propertyName
.ustring()).toLatin1();
1792 for (int i
= 0; i
< meta
->enumeratorCount(); ++i
) {
1793 QMetaEnum e
= meta
->enumerator(i
);
1794 for (int j
= 0; j
< e
.keyCount(); ++j
) {
1795 if (!qstrcmp(e
.key(j
), name
.constData()))
1800 return JSC::JSObject::deleteProperty(exec
, propertyName
, checkDontDelete
);
1803 bool QMetaObjectWrapperObject::getPropertyAttributes(JSC::ExecState
*exec
,
1804 const JSC::Identifier
&propertyName
,
1805 unsigned &attributes
) const
1807 if (propertyName
== exec
->propertyNames().prototype
) {
1808 attributes
= JSC::DontDelete
;
1811 const QMetaObject
*meta
= data
->value
;
1813 QByteArray name
= QString(propertyName
.ustring()).toLatin1();
1814 for (int i
= 0; i
< meta
->enumeratorCount(); ++i
) {
1815 QMetaEnum e
= meta
->enumerator(i
);
1816 for (int j
= 0; j
< e
.keyCount(); ++j
) {
1817 if (!qstrcmp(e
.key(j
), name
.constData())) {
1818 attributes
= JSC::ReadOnly
| JSC::DontDelete
;
1824 return JSC::JSObject::getPropertyAttributes(exec
, propertyName
, attributes
);
1827 void QMetaObjectWrapperObject::getOwnPropertyNames(JSC::ExecState
*exec
,
1828 JSC::PropertyNameArray
&propertyNames
,
1829 bool includeNonEnumerable
)
1831 const QMetaObject
*meta
= data
->value
;
1834 for (int i
= 0; i
< meta
->enumeratorCount(); ++i
) {
1835 QMetaEnum e
= meta
->enumerator(i
);
1836 for (int j
= 0; j
< e
.keyCount(); ++j
)
1837 propertyNames
.add(JSC::Identifier(exec
, e
.key(j
)));
1839 JSC::JSObject::getOwnPropertyNames(exec
, propertyNames
, includeNonEnumerable
);
1842 void QMetaObjectWrapperObject::markChildren(JSC::MarkStack
& markStack
)
1845 markStack
.append(data
->ctor
);
1846 if (data
->prototype
)
1847 markStack
.append(data
->prototype
);
1848 JSC::JSObject::markChildren(markStack
);
1851 JSC::CallType
QMetaObjectWrapperObject::getCallData(JSC::CallData
& callData
)
1853 callData
.native
.function
= call
;
1854 return JSC::CallTypeHost
;
1857 JSC::ConstructType
QMetaObjectWrapperObject::getConstructData(JSC::ConstructData
& constructData
)
1859 constructData
.native
.function
= construct
;
1860 return JSC::ConstructTypeHost
;
1863 JSC::JSValue JSC_HOST_CALL
QMetaObjectWrapperObject::call(
1864 JSC::ExecState
*exec
, JSC::JSObject
*callee
,
1865 JSC::JSValue thisValue
, const JSC::ArgList
&args
)
1867 QScriptEnginePrivate
*eng_p
= scriptEngineFromExec(exec
);
1868 thisValue
= eng_p
->toUsableValue(thisValue
);
1869 if (!callee
->inherits(&QMetaObjectWrapperObject::info
))
1870 return throwError(exec
, JSC::TypeError
, "callee is not a QMetaObject");
1871 QMetaObjectWrapperObject
*self
= static_cast<QMetaObjectWrapperObject
*>(callee
);
1872 JSC::ExecState
*previousFrame
= eng_p
->currentFrame
;
1873 eng_p
->pushContext(exec
, thisValue
, args
, callee
);
1874 JSC::JSValue result
= self
->execute(eng_p
->currentFrame
, args
);
1875 eng_p
->popContext();
1876 eng_p
->currentFrame
= previousFrame
;
1880 JSC::JSObject
* QMetaObjectWrapperObject::construct(JSC::ExecState
*exec
, JSC::JSObject
*callee
, const JSC::ArgList
&args
)
1882 QMetaObjectWrapperObject
*self
= static_cast<QMetaObjectWrapperObject
*>(callee
);
1883 QScriptEnginePrivate
*eng_p
= scriptEngineFromExec(exec
);
1884 JSC::ExecState
*previousFrame
= eng_p
->currentFrame
;
1885 eng_p
->pushContext(exec
, JSC::JSValue(), args
, callee
, true);
1886 JSC::JSValue result
= self
->execute(eng_p
->currentFrame
, args
);
1887 eng_p
->popContext();
1888 eng_p
->currentFrame
= previousFrame
;
1889 if (!result
|| !result
.isObject())
1891 return JSC::asObject(result
);
1894 JSC::JSValue
QMetaObjectWrapperObject::execute(JSC::ExecState
*exec
,
1895 const JSC::ArgList
&args
)
1898 QScriptEnginePrivate
*eng_p
= QScript::scriptEngineFromExec(exec
);
1899 QScriptContext
*ctx
= eng_p
->contextForFrame(exec
);
1900 JSC::CallData callData
;
1901 JSC::CallType callType
= data
->ctor
.getCallData(callData
);
1903 Q_ASSERT_X(callType
== JSC::CallTypeHost
, Q_FUNC_INFO
, "script constructors not supported");
1904 if (data
->ctor
.inherits(&FunctionWithArgWrapper::info
)) {
1905 FunctionWithArgWrapper
*wrapper
= static_cast<FunctionWithArgWrapper
*>(JSC::asObject(data
->ctor
));
1906 QScriptValue result
= wrapper
->function()(ctx
, QScriptEnginePrivate::get(eng_p
), wrapper
->arg());
1907 return eng_p
->scriptValueToJSCValue(result
);
1909 Q_ASSERT(data
->ctor
.inherits(&FunctionWrapper::info
));
1910 FunctionWrapper
*wrapper
= static_cast<FunctionWrapper
*>(JSC::asObject(data
->ctor
));
1911 QScriptValue result
= wrapper
->function()(ctx
, QScriptEnginePrivate::get(eng_p
));
1912 return eng_p
->scriptValueToJSCValue(result
);
1915 const QMetaObject
*meta
= data
->value
;
1916 if (meta
->constructorCount() > 0) {
1917 JSC::JSValue result
= callQtMethod(exec
, QMetaMethod::Constructor
, /*thisQObject=*/0,
1918 args
, meta
, meta
->constructorCount()-1, /*maybeOverloaded=*/true);
1919 if (!exec
->hadException()) {
1920 Q_ASSERT(result
&& result
.inherits(&QScriptObject::info
));
1921 QScriptObject
*object
= static_cast<QScriptObject
*>(JSC::asObject(result
));
1922 QScript::QObjectDelegate
*delegate
= static_cast<QScript::QObjectDelegate
*>(object
->delegate());
1923 delegate
->setOwnership(QScriptEngine::AutoOwnership
);
1924 if (data
->prototype
)
1925 object
->setPrototype(data
->prototype
);
1929 QString message
= QString::fromLatin1("no constructor for %0")
1930 .arg(QLatin1String(meta
->className()));
1931 return JSC::throwError(exec
, JSC::TypeError
, message
);
1936 struct StaticQtMetaObject
: public QObject
1938 static const QMetaObject
*get()
1939 { return &static_cast<StaticQtMetaObject
*> (0)->staticQtMetaObject
; }
1942 static JSC::JSValue JSC_HOST_CALL
qmetaobjectProtoFuncClassName(
1943 JSC::ExecState
*exec
, JSC::JSObject
*, JSC::JSValue thisValue
, const JSC::ArgList
&)
1945 QScriptEnginePrivate
*engine
= scriptEngineFromExec(exec
);
1946 thisValue
= engine
->toUsableValue(thisValue
);
1947 if (!thisValue
.inherits(&QMetaObjectWrapperObject::info
))
1948 return throwError(exec
, JSC::TypeError
, "this object is not a QMetaObject");
1949 const QMetaObject
*meta
= static_cast<QMetaObjectWrapperObject
*>(JSC::asObject(thisValue
))->value();
1950 return JSC::jsString(exec
, meta
->className());
1953 QMetaObjectPrototype::QMetaObjectPrototype(
1954 JSC::ExecState
*exec
, WTF::PassRefPtr
<JSC::Structure
> structure
,
1955 JSC::Structure
* prototypeFunctionStructure
)
1956 : QMetaObjectWrapperObject(exec
, StaticQtMetaObject::get(), /*ctor=*/JSC::JSValue(), structure
)
1958 putDirectFunction(exec
, new (exec
) JSC::PrototypeFunction(exec
, prototypeFunctionStructure
, /*length=*/0, JSC::Identifier(exec
, "className"), qmetaobjectProtoFuncClassName
), JSC::DontEnum
);
1961 static const uint qt_meta_data_QObjectConnectionManager
[] = {
1971 // slots: signature, parameters, type, tag, flags
1972 35, 34, 34, 34, 0x0a,
1977 static const char qt_meta_stringdata_QObjectConnectionManager
[] = {
1978 "QScript::QObjectConnectionManager\0\0execute()\0"
1981 const QMetaObject
QObjectConnectionManager::staticMetaObject
= {
1982 { &QObject::staticMetaObject
, qt_meta_stringdata_QObjectConnectionManager
,
1983 qt_meta_data_QObjectConnectionManager
, 0 }
1986 const QMetaObject
*QObjectConnectionManager::metaObject() const
1988 return &staticMetaObject
;
1991 void *QObjectConnectionManager::qt_metacast(const char *_clname
)
1993 if (!_clname
) return 0;
1994 if (!strcmp(_clname
, qt_meta_stringdata_QObjectConnectionManager
))
1995 return static_cast<void*>(const_cast<QObjectConnectionManager
*>(this));
1996 return QObject::qt_metacast(_clname
);
1999 int QObjectConnectionManager::qt_metacall(QMetaObject::Call _c
, int _id
, void **_a
)
2001 _id
= QObject::qt_metacall(_c
, _id
, _a
);
2004 if (_c
== QMetaObject::InvokeMetaMethod
) {
2011 void QObjectConnectionManager::execute(int slotIndex
, void **argv
)
2013 JSC::JSValue receiver
;
2015 JSC::JSValue senderWrapper
;
2016 int signalIndex
= -1;
2017 for (int i
= 0; i
< connections
.size(); ++i
) {
2018 const QVector
<QObjectConnection
> &cs
= connections
.at(i
);
2019 for (int j
= 0; j
< cs
.size(); ++j
) {
2020 const QObjectConnection
&c
= cs
.at(j
);
2021 if (c
.slotIndex
== slotIndex
) {
2022 receiver
= c
.receiver
;
2024 senderWrapper
= c
.senderWrapper
;
2030 Q_ASSERT(slot
&& slot
.isObject());
2032 if (engine
->isCollecting()) {
2033 qWarning("QtScript: can't execute signal handler during GC");
2034 // we can't do a script function call during GC,
2035 // so we're forced to ignore this signal
2040 QScriptFunction
*fun
= engine
->convertToNativeFunction(slot
);
2042 // the signal handler has been GC'ed. This can only happen when
2043 // a QObject is owned by the engine, the engine is destroyed, and
2044 // there is a script function connected to the destroyed() signal
2045 Q_ASSERT(signalIndex
<= 1); // destroyed(QObject*)
2050 const QMetaObject
*meta
= sender()->metaObject();
2051 const QMetaMethod method
= meta
->method(signalIndex
);
2053 QList
<QByteArray
> parameterTypes
= method
.parameterTypes();
2054 int argc
= parameterTypes
.count();
2056 JSC::ExecState
*exec
= engine
->currentFrame
;
2057 QVarLengthArray
<JSC::JSValue
, 8> argsVector(argc
);
2058 for (int i
= 0; i
< argc
; ++i
) {
2059 // ### optimize -- no need to convert via QScriptValue
2060 QScriptValue actual
;
2061 void *arg
= argv
[i
+ 1];
2062 QByteArray typeName
= parameterTypes
.at(i
);
2063 int argType
= QMetaType::type(parameterTypes
.at(i
));
2065 if (typeName
== "QVariant") {
2066 actual
= engine
->scriptValueFromVariant(*reinterpret_cast<QVariant
*>(arg
));
2068 qWarning("QScriptEngine: Unable to handle unregistered datatype '%s' "
2069 "when invoking handler of signal %s::%s",
2070 typeName
.constData(), meta
->className(), method
.signature());
2071 actual
= QScriptValue(QScriptValue::UndefinedValue
);
2074 actual
= engine
->create(argType
, arg
);
2076 argsVector
[i
] = engine
->scriptValueToJSCValue(actual
);
2078 JSC::ArgList
jscArgs(argsVector
.data(), argsVector
.size());
2080 JSC::JSValue senderObject
;
2081 if (senderWrapper
&& senderWrapper
.inherits(&QScriptObject::info
)) // ### check if it's actually a QObject wrapper
2082 senderObject
= senderWrapper
;
2084 QScriptEngine::QObjectWrapOptions opt
= QScriptEngine::PreferExistingWrapperObject
;
2085 senderObject
= engine
->newQObject(sender(), QScriptEngine::QtOwnership
, opt
);
2088 JSC::JSValue thisObject
;
2089 if (receiver
&& receiver
.isObject())
2090 thisObject
= receiver
;
2092 thisObject
= engine
->globalObject();
2094 JSC::CallData callData
;
2095 JSC::CallType callType
= slot
.getCallData(callData
);
2096 if (exec
->hadException())
2097 exec
->clearException(); // ### otherwise JSC asserts
2098 JSC::call(exec
, slot
, callType
, callData
, thisObject
, jscArgs
);
2100 if (exec
->hadException()) {
2101 engine
->emitSignalHandlerException();
2105 QObjectConnectionManager::QObjectConnectionManager(QScriptEnginePrivate
*eng
)
2106 : engine(eng
), slotCounter(0)
2110 QObjectConnectionManager::~QObjectConnectionManager()
2114 void QObjectConnectionManager::mark(JSC::MarkStack
& markStack
)
2116 for (int i
= 0; i
< connections
.size(); ++i
) {
2117 QVector
<QObjectConnection
> &cs
= connections
[i
];
2118 for (int j
= 0; j
< cs
.size(); ++j
)
2119 cs
[j
].mark(markStack
);
2123 bool QObjectConnectionManager::addSignalHandler(
2124 QObject
*sender
, int signalIndex
, JSC::JSValue receiver
,
2125 JSC::JSValue function
, JSC::JSValue senderWrapper
,
2126 Qt::ConnectionType type
)
2128 if (connections
.size() <= signalIndex
)
2129 connections
.resize(signalIndex
+1);
2130 QVector
<QObjectConnection
> &cs
= connections
[signalIndex
];
2131 int absSlotIndex
= slotCounter
+ metaObject()->methodOffset();
2132 bool ok
= QMetaObject::connect(sender
, signalIndex
, this, absSlotIndex
, type
);
2134 cs
.append(QObjectConnection(slotCounter
++, receiver
, function
, senderWrapper
));
2135 QMetaMethod signal
= sender
->metaObject()->method(signalIndex
);
2136 QByteArray signalString
;
2137 signalString
.append('2'); // signal code
2138 signalString
.append(signal
.signature());
2139 static_cast<QObjectNotifyCaller
*>(sender
)->callConnectNotify(signalString
);
2144 bool QObjectConnectionManager::removeSignalHandler(
2145 QObject
*sender
, int signalIndex
,
2146 JSC::JSValue receiver
, JSC::JSValue slot
)
2148 if (connections
.size() <= signalIndex
)
2150 QVector
<QObjectConnection
> &cs
= connections
[signalIndex
];
2151 for (int i
= 0; i
< cs
.size(); ++i
) {
2152 const QObjectConnection
&c
= cs
.at(i
);
2153 if (c
.hasTarget(receiver
, slot
)) {
2154 int absSlotIndex
= c
.slotIndex
+ metaObject()->methodOffset();
2155 bool ok
= QMetaObject::disconnect(sender
, signalIndex
, this, absSlotIndex
);
2158 QMetaMethod signal
= sender
->metaObject()->method(signalIndex
);
2159 QByteArray signalString
;
2160 signalString
.append('2'); // signal code
2161 signalString
.append(signal
.signature());
2162 static_cast<QScript::QObjectNotifyCaller
*>(sender
)->callDisconnectNotify(signalString
);
2170 QObjectData::QObjectData(QScriptEnginePrivate
*eng
)
2171 : engine(eng
), connectionManager(0)
2175 QObjectData::~QObjectData()
2177 if (connectionManager
) {
2178 delete connectionManager
;
2179 connectionManager
= 0;
2183 void QObjectData::mark(JSC::MarkStack
& markStack
)
2185 if (connectionManager
)
2186 connectionManager
->mark(markStack
);
2188 QList
<QScript::QObjectWrapperInfo
>::iterator it
;
2189 for (it
= wrappers
.begin(); it
!= wrappers
.end(); ) {
2190 const QScript::QObjectWrapperInfo
&info
= *it
;
2191 // ### don't mark if there are no other references.
2192 // we need something like isMarked()
2193 markStack
.append(info
.object
);
2199 bool QObjectData::addSignalHandler(QObject
*sender
,
2201 JSC::JSValue receiver
,
2203 JSC::JSValue senderWrapper
,
2204 Qt::ConnectionType type
)
2206 if (!connectionManager
)
2207 connectionManager
= new QObjectConnectionManager(engine
);
2208 return connectionManager
->addSignalHandler(
2209 sender
, signalIndex
, receiver
, slot
, senderWrapper
, type
);
2212 bool QObjectData::removeSignalHandler(QObject
*sender
,
2214 JSC::JSValue receiver
,
2217 if (!connectionManager
)
2219 return connectionManager
->removeSignalHandler(
2220 sender
, signalIndex
, receiver
, slot
);
2223 QScriptObject
*QObjectData::findWrapper(QScriptEngine::ValueOwnership ownership
,
2224 const QScriptEngine::QObjectWrapOptions
&options
) const
2226 for (int i
= 0; i
< wrappers
.size(); ++i
) {
2227 const QObjectWrapperInfo
&info
= wrappers
.at(i
);
2228 if ((info
.ownership
== ownership
) && (info
.options
== options
))
2234 void QObjectData::registerWrapper(QScriptObject
*wrapper
,
2235 QScriptEngine::ValueOwnership ownership
,
2236 const QScriptEngine::QObjectWrapOptions
&options
)
2238 wrappers
.append(QObjectWrapperInfo(wrapper
, ownership
, options
));
2241 } // namespace QScript
2247 ASSERT_CLASS_FITS_IN_CELL(QScript::QtFunction
);
2250 #include "moc_qscriptqobject_p.cpp"