2 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "qt_runtime.h"
24 #include "BooleanObject.h"
25 #include "DateInstance.h"
26 #include "DatePrototype.h"
27 #include "FunctionPrototype.h"
28 #include "Interpreter.h"
30 #include "JSContextRefPrivate.h"
31 #include "JSDocument.h"
32 #include "JSDOMBinding.h"
33 #include "JSDOMWindow.h"
34 #include <JSFunction.h>
35 #include "JSGlobalObject.h"
36 #include "JSHTMLElement.h"
39 #include "JSRetainPtr.h"
40 #include "JSUint8ClampedArray.h"
41 #include "ObjectPrototype.h"
42 #include "PropertyNameArray.h"
43 #include "qdatetime.h"
45 #include "qmetaobject.h"
46 #include "qmetatype.h"
48 #include "qstringlist.h"
49 #include "qt_instance.h"
50 #include "qt_pixmapruntime.h"
51 #include "qvarlengtharray.h"
53 #include <wtf/DateMath.h>
56 #include <runtime/Error.h>
57 #include <runtime_array.h>
58 #include <runtime_object.h>
61 Q_DECLARE_METATYPE(QObjectList);
62 Q_DECLARE_METATYPE(QList<int>);
63 Q_DECLARE_METATYPE(QVariant);
65 using namespace WebCore;
71 //#define QTWK_RUNTIME_CONVERSION_DEBUG
72 //#define QTWK_RUNTIME_MATCH_DEBUG
78 inline ~QWKNoDebug(){}
81 inline QWKNoDebug &operator<<(const T &) { return *this; }
84 #ifdef QTWK_RUNTIME_CONVERSION_DEBUG
85 #define qConvDebug() qDebug()
87 #define qConvDebug() QWKNoDebug()
90 #ifdef QTWK_RUNTIME_MATCH_DEBUG
91 #define qMatchDebug() qDebug()
93 #define qMatchDebug() QWKNoDebug()
110 #if defined(QTWK_RUNTIME_CONVERSION_DEBUG) || defined(QTWK_RUNTIME_MATCH_DEBUG)
111 QDebug operator<<(QDebug dbg, const JSRealType &c)
113 const char *map[] = { "Variant", "Number", "Boolean", "String", "Date",
114 "Array", "RTObject", "Object", "Null", "RTArray"};
116 dbg.nospace() << "JSType(" << ((int)c) << ", " << map[c] << ")";
122 void setException(JSContextRef context, JSValueRef* exception, const QString& text)
127 JSStringRef errorStr = JSStringCreateWithUTF8CString(text.toUtf8());
128 JSValueRef errorVal[] = { JSValueMakeString(context, errorStr) };
129 *exception = JSObjectMakeError(context, 1, errorVal, 0);
130 JSStringRelease(errorStr);
133 struct RuntimeConversion {
134 ConvertToJSValueFunction toJSValueFunc;
135 ConvertToVariantFunction toVariantFunc;
138 typedef QHash<int, RuntimeConversion> RuntimeConversionTable;
139 Q_GLOBAL_STATIC(RuntimeConversionTable, customRuntimeConversions)
141 void registerCustomType(int qtMetaTypeId, ConvertToVariantFunction toVariantFunc, ConvertToJSValueFunction toJSValueFunc)
143 RuntimeConversion conversion;
144 conversion.toJSValueFunc = toJSValueFunc;
145 conversion.toVariantFunc = toVariantFunc;
146 customRuntimeConversions()->insert(qtMetaTypeId, conversion);
149 static bool isJSUint8ClampedArray(JSValue val)
151 return val.isCell() && val.inherits(&JSUint8ClampedArray::s_info);
154 static JSRealType valueRealType(ExecState* exec, JSValue val)
158 else if (val.isString())
160 else if (val.isBoolean())
162 else if (val.isNull())
164 else if (isJSUint8ClampedArray(val))
165 return JSUint8ClampedArray;
166 else if (val.isObject()) {
167 JSObject *object = val.toObject(exec);
168 if (object->inherits(&RuntimeArray::s_info)) // RuntimeArray 'inherits' from Array, but not in C++
170 else if (object->inherits(&JSArray::s_info))
172 else if (object->inherits(&DateInstance::s_info))
174 else if (object->inherits(&RuntimeObject::s_info))
179 return String; // I don't know.
182 QVariant convertValueToQVariant(ExecState*, JSValue, QMetaType::Type, int*, HashSet<JSObject*>*, int);
184 static QVariantMap convertValueToQVariantMap(ExecState* exec, JSObject* object, HashSet<JSObject*>* visitedObjects, int recursionLimit)
186 Q_ASSERT(!exec->hadException());
188 PropertyNameArray properties(exec);
189 object->methodTable()->getPropertyNames(object, exec, properties, ExcludeDontEnumProperties);
190 PropertyNameArray::const_iterator it = properties.begin();
194 while (it != properties.end()) {
195 if (object->propertyIsEnumerable(exec, *it)) {
196 JSValue val = object->get(exec, *it);
197 if (exec->hadException())
198 exec->clearException();
200 QVariant v = convertValueToQVariant(exec, val, QMetaType::Void, &objdist, visitedObjects, recursionLimit);
202 UString ustring = (*it).ustring();
203 QString id = QString((const QChar*)ustring.impl()->characters(), ustring.length());
204 result.insert(id, v);
213 QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type hint, int *distance, HashSet<JSObject*>* visitedObjects, int recursionLimit)
217 if (!value || !recursionLimit)
220 JSObject* object = 0;
221 if (value.isObject()) {
222 object = value.toObject(exec);
223 if (visitedObjects->contains(object))
226 visitedObjects->add(object);
229 // check magic pointer values before dereferencing value
231 || (value == jsUndefined()
232 && hint != QMetaType::QString
233 && hint != (QMetaType::Type) qMetaTypeId<QVariant>())) {
239 JSLockHolder lock(exec);
240 JSRealType type = valueRealType(exec, value);
241 if (hint == QMetaType::Void) {
244 hint = QMetaType::Double;
247 hint = QMetaType::Bool;
251 hint = QMetaType::QString;
254 hint = QMetaType::QDateTime;
257 if (object->inherits(&NumberObject::s_info))
258 hint = QMetaType::Double;
259 else if (object->inherits(&BooleanObject::s_info))
260 hint = QMetaType::Bool;
262 hint = QMetaType::QVariantMap;
265 hint = QMetaType::QObjectStar;
267 case JSUint8ClampedArray:
268 hint = QMetaType::QByteArray;
272 hint = QMetaType::QVariantList;
277 qConvDebug() << "convertValueToQVariant: jstype is " << type << ", hint is" << hint;
279 if (value == jsNull()
280 && hint != QMetaType::QObjectStar
281 && hint != QMetaType::VoidStar
282 && hint != QMetaType::QString
283 && hint != (QMetaType::Type) qMetaTypeId<QVariant>()) {
292 case QMetaType::Bool:
293 if (type == Object && object->inherits(&BooleanObject::s_info))
294 ret = QVariant(asBooleanObject(value)->internalValue().toBoolean());
296 ret = QVariant(value.toBoolean());
304 case QMetaType::UInt:
305 case QMetaType::Long:
306 case QMetaType::ULong:
307 case QMetaType::LongLong:
308 case QMetaType::ULongLong:
309 case QMetaType::Short:
310 case QMetaType::UShort:
311 case QMetaType::Float:
312 case QMetaType::Double:
313 ret = QVariant(value.toNumber(exec));
314 ret.convert((QVariant::Type)hint);
315 if (type == Number) {
317 case QMetaType::Double:
320 case QMetaType::Float:
323 case QMetaType::LongLong:
324 case QMetaType::ULongLong:
327 case QMetaType::Long:
328 case QMetaType::ULong:
332 case QMetaType::UInt:
335 case QMetaType::Short:
336 case QMetaType::UShort:
349 case QMetaType::QChar:
350 if (type == Number || type == Boolean) {
351 ret = QVariant(QChar((ushort)value.toNumber(exec)));
357 UString str = value.toString(exec)->value(exec);
358 ret = QVariant(QChar(str.length() ? *(const ushort*)str.impl()->characters() : 0));
366 case QMetaType::QString: {
367 if (value.isUndefinedOrNull()) {
372 UString ustring = value.toString(exec)->value(exec);
373 ret = QVariant(QString((const QChar*)ustring.impl()->characters(), ustring.length()));
382 case QMetaType::QVariantMap:
383 if (type == Object || type == Array || type == RTArray) {
384 ret = QVariant(convertValueToQVariantMap(exec, object, visitedObjects, recursionLimit));
385 // Those types can still have perfect matches, e.g. 'bool' if value is a Boolean Object.
390 case QMetaType::QVariantList:
391 if (type == RTArray) {
392 RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
395 int len = rtarray->getLength();
397 qConvDebug() << "converting a " << len << " length Array";
398 for (int i = 0; i < len; ++i) {
399 JSValue val = rtarray->getConcreteArray()->valueAt(exec, i);
400 result.append(convertValueToQVariant(exec, val, QMetaType::Void, &objdist, visitedObjects, recursionLimit));
402 qConvDebug() << "Failed converting element at index " << i;
403 break; // Failed converting a list entry, so fail the array
408 ret = QVariant(result);
410 } else if (type == Array) {
411 JSArray* array = static_cast<JSArray*>(object);
414 int len = array->length();
416 qConvDebug() << "converting a " << len << " length Array";
417 for (int i = 0; i < len; ++i) {
418 JSValue val = array->get(exec, i);
419 result.append(convertValueToQVariant(exec, val, QMetaType::Void, &objdist, visitedObjects, recursionLimit));
421 qConvDebug() << "Failed converting element at index " << i;
422 break; // Failed converting a list entry, so fail the array
427 ret = QVariant(result);
430 // Make a single length array
432 qConvDebug() << "making a single length variantlist";
433 QVariant var = convertValueToQVariant(exec, value, QMetaType::Void, &objdist, visitedObjects, recursionLimit);
437 ret = QVariant(result);
440 qConvDebug() << "failed making single length varlist";
445 case QMetaType::QStringList: {
446 if (type == RTArray) {
447 RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
450 int len = rtarray->getLength();
451 for (int i = 0; i < len; ++i) {
452 JSValue val = rtarray->getConcreteArray()->valueAt(exec, i);
453 UString ustring = val.toString(exec)->value(exec);
454 QString qstring = QString((const QChar*)ustring.impl()->characters(), ustring.length());
456 result.append(qstring);
459 ret = QVariant(result);
460 } else if (type == Array) {
461 JSArray* array = static_cast<JSArray*>(object);
464 int len = array->length();
465 for (int i = 0; i < len; ++i) {
466 JSValue val = array->get(exec, i);
467 UString ustring = val.toString(exec)->value(exec);
468 QString qstring = QString((const QChar*)ustring.impl()->characters(), ustring.length());
470 result.append(qstring);
473 ret = QVariant(result);
475 // Make a single length array
476 UString ustring = value.toString(exec)->value(exec);
477 QString qstring = QString((const QChar*)ustring.impl()->characters(), ustring.length());
479 result.append(qstring);
480 ret = QVariant(result);
486 case QMetaType::QByteArray: {
487 if (type == JSUint8ClampedArray) {
488 WTF::Uint8ClampedArray* arr = toUint8ClampedArray(value);
489 ret = QVariant(QByteArray(reinterpret_cast<const char*>(arr->data()), arr->length()));
492 UString ustring = value.toString(exec)->value(exec);
493 ret = QVariant(QString((const QChar*)ustring.impl()->characters(), ustring.length()).toLatin1());
502 case QMetaType::QDateTime:
503 case QMetaType::QDate:
504 case QMetaType::QTime:
506 DateInstance* date = static_cast<DateInstance*>(object);
507 GregorianDateTime gdt;
508 msToGregorianDateTime(exec, date->internalNumber(), true, gdt);
509 if (hint == QMetaType::QDateTime) {
510 ret = QDateTime(QDate(gdt.year(), gdt.month() + 1, gdt.monthDay()), QTime(gdt.hour(), gdt.minute(), gdt.second()), Qt::UTC);
512 } else if (hint == QMetaType::QDate) {
513 ret = QDate(gdt.year(), gdt.month() + 1, gdt.monthDay());
516 ret = QTime(gdt.hour(), gdt.minute(), gdt.second());
519 } else if (type == Number) {
520 double b = value.toNumber(exec);
521 GregorianDateTime gdt;
522 msToGregorianDateTime(exec, b, true, gdt);
523 if (hint == QMetaType::QDateTime) {
524 ret = QDateTime(QDate(gdt.year(), gdt.month() + 1, gdt.monthDay()), QTime(gdt.hour(), gdt.minute(), gdt.second()), Qt::UTC);
526 } else if (hint == QMetaType::QDate) {
527 ret = QDate(gdt.year(), gdt.month() + 1, gdt.monthDay());
530 ret = QTime(gdt.hour(), gdt.minute(), gdt.second());
533 #ifndef QT_NO_DATESTRING
534 } else if (type == String) {
535 UString ustring = value.toString(exec)->value(exec);
536 QString qstring = QString((const QChar*)ustring.impl()->characters(), ustring.length());
538 if (hint == QMetaType::QDateTime) {
539 QDateTime dt = QDateTime::fromString(qstring, Qt::ISODate);
541 dt = QDateTime::fromString(qstring, Qt::TextDate);
543 dt = QDateTime::fromString(qstring, Qt::SystemLocaleDate);
545 dt = QDateTime::fromString(qstring, Qt::LocaleDate);
550 } else if (hint == QMetaType::QDate) {
551 QDate dt = QDate::fromString(qstring, Qt::ISODate);
553 dt = QDate::fromString(qstring, Qt::TextDate);
555 dt = QDate::fromString(qstring, Qt::SystemLocaleDate);
557 dt = QDate::fromString(qstring, Qt::LocaleDate);
563 QTime dt = QTime::fromString(qstring, Qt::ISODate);
565 dt = QTime::fromString(qstring, Qt::TextDate);
567 dt = QTime::fromString(qstring, Qt::SystemLocaleDate);
569 dt = QTime::fromString(qstring, Qt::LocaleDate);
575 #endif // QT_NO_DATESTRING
579 case QMetaType::QObjectStar:
581 QtInstance* qtinst = QtInstance::getInstance(object);
583 if (qtinst->getObject()) {
584 qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject();
585 ret = QVariant::fromValue(qtinst->getObject());
589 qConvDebug() << "can't convert deleted qobject";
592 qConvDebug() << "wasn't a qtinstance";
594 } else if (type == Null) {
595 QObject* nullobj = 0;
596 ret = QVariant::fromValue(nullobj);
599 qConvDebug() << "previous type was not an object:" << type;
603 case QMetaType::VoidStar:
605 QtInstance* qtinst = QtInstance::getInstance(object);
607 if (qtinst->getObject()) {
608 qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject();
609 ret = QVariant::fromValue((void *)qtinst->getObject());
613 qConvDebug() << "can't convert deleted qobject";
616 qConvDebug() << "wasn't a qtinstance";
618 } else if (type == Null) {
619 ret = QVariant::fromValue((void*)0);
621 } else if (type == Number) {
622 // I don't think that converting a double to a pointer is a wise
623 // move. Except maybe 0.
624 qConvDebug() << "got number for void * - not converting, seems unsafe:" << value.toNumber(exec);
626 qConvDebug() << "void* - unhandled type" << type;
631 // Non const type ids
632 if (hint == (QMetaType::Type) qMetaTypeId<QObjectList>())
634 if (type == RTArray) {
635 RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
638 int len = rtarray->getLength();
639 for (int i = 0; i < len; ++i) {
640 JSValue val = rtarray->getConcreteArray()->valueAt(exec, i);
642 QVariant item = convertValueToQVariant(exec, val, QMetaType::QObjectStar, &itemdist, visitedObjects, recursionLimit);
644 result.append(item.value<QObject*>());
648 // If we didn't fail conversion
649 if (result.count() == len) {
651 ret = QVariant::fromValue(result);
653 } else if (type == Array) {
654 JSObject* object = value.toObject(exec);
655 JSArray* array = static_cast<JSArray *>(object);
657 int len = array->length();
658 for (int i = 0; i < len; ++i) {
659 JSValue val = array->get(exec, i);
661 QVariant item = convertValueToQVariant(exec, val, QMetaType::QObjectStar, &itemdist, visitedObjects, recursionLimit);
663 result.append(item.value<QObject*>());
667 // If we didn't fail conversion
668 if (result.count() == len) {
670 ret = QVariant::fromValue(result);
673 // Make a single length array
676 QVariant item = convertValueToQVariant(exec, value, QMetaType::QObjectStar, &itemdist, visitedObjects, recursionLimit);
678 result.append(item.value<QObject*>());
680 ret = QVariant::fromValue(result);
684 } else if (hint == (QMetaType::Type) qMetaTypeId<QList<int> >()) {
685 if (type == RTArray) {
686 RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
689 int len = rtarray->getLength();
690 for (int i = 0; i < len; ++i) {
691 JSValue val = rtarray->getConcreteArray()->valueAt(exec, i);
693 QVariant item = convertValueToQVariant(exec, val, QMetaType::Int, &itemdist, visitedObjects, recursionLimit);
695 result.append(item.value<int>());
699 // If we didn't fail conversion
700 if (result.count() == len) {
702 ret = QVariant::fromValue(result);
704 } else if (type == Array) {
705 JSArray* array = static_cast<JSArray *>(object);
708 int len = array->length();
709 for (int i = 0; i < len; ++i) {
710 JSValue val = array->get(exec, i);
712 QVariant item = convertValueToQVariant(exec, val, QMetaType::Int, &itemdist, visitedObjects, recursionLimit);
714 result.append(item.value<int>());
718 // If we didn't fail conversion
719 if (result.count() == len) {
721 ret = QVariant::fromValue(result);
724 // Make a single length array
727 QVariant item = convertValueToQVariant(exec, value, QMetaType::Int, &itemdist, visitedObjects, recursionLimit);
729 result.append(item.value<int>());
731 ret = QVariant::fromValue(result);
735 } else if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(hint))) {
736 ret = QtPixmapInstance::variantFromObject(object, static_cast<QMetaType::Type>(hint));
737 } else if (customRuntimeConversions()->contains(hint)) {
738 ret = customRuntimeConversions()->value(hint).toVariantFunc(object, &dist, visitedObjects);
741 } else if (hint == (QMetaType::Type) qMetaTypeId<QVariant>()) {
742 if (value.isUndefinedOrNull()) {
747 if (type == Object) {
748 // Since we haven't really visited this object yet, we remove it
749 visitedObjects->remove(object);
752 // And then recurse with the autodetect flag
753 ret = convertValueToQVariant(exec, value, QMetaType::Void, distance, visitedObjects, recursionLimit);
771 QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type hint, int *distance)
773 const int recursionLimit = 200;
774 HashSet<JSObject*> visitedObjects;
775 return convertValueToQVariant(exec, value, hint, distance, &visitedObjects, recursionLimit);
778 JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant)
780 // Variants with QObject * can be isNull but not a null pointer
781 // An empty QString variant is also null
782 QMetaType::Type type = (QMetaType::Type) variant.userType();
784 qConvDebug() << "convertQVariantToValue: metatype:" << type << ", isnull: " << variant.isNull();
785 if (variant.isNull() &&
786 !QMetaType::typeFlags(type).testFlag(QMetaType::PointerToQObject) &&
787 type != QMetaType::VoidStar &&
788 type != QMetaType::QString) {
792 JSLockHolder lock(exec);
794 if (type == QMetaType::Bool)
795 return jsBoolean(variant.toBool());
797 if (type == QMetaType::Int ||
798 type == QMetaType::UInt ||
799 type == QMetaType::Long ||
800 type == QMetaType::ULong ||
801 type == QMetaType::LongLong ||
802 type == QMetaType::ULongLong ||
803 type == QMetaType::Short ||
804 type == QMetaType::UShort ||
805 type == QMetaType::Float ||
806 type == QMetaType::Double)
807 return jsNumber(variant.toDouble());
809 if (type == QMetaType::QDateTime ||
810 type == QMetaType::QDate ||
811 type == QMetaType::QTime) {
813 QDate date = QDate::currentDate();
814 QTime time(0,0,0); // midnight
816 if (type == QMetaType::QDate)
817 date = variant.value<QDate>();
818 else if (type == QMetaType::QTime)
819 time = variant.value<QTime>();
821 QDateTime dt = variant.value<QDateTime>().toLocalTime();
826 // Dates specified this way are in local time (we convert DateTimes above)
827 GregorianDateTime dt;
828 dt.setYear(date.year());
829 dt.setMonth(date.month() - 1);
830 dt.setMonthDay(date.day());
831 dt.setHour(time.hour());
832 dt.setMinute(time.minute());
833 dt.setSecond(time.second());
835 double ms = gregorianDateTimeToMS(exec, dt, time.msec(), /*inputIsUTC*/ false);
837 return DateInstance::create(exec, exec->lexicalGlobalObject()->dateStructure(), trunc(ms));
840 if (type == QMetaType::QByteArray) {
841 QByteArray qtByteArray = variant.value<QByteArray>();
842 WTF::RefPtr<WTF::Uint8ClampedArray> wtfByteArray = WTF::Uint8ClampedArray::createUninitialized(qtByteArray.length());
843 memcpy(wtfByteArray->data(), qtByteArray.constData(), qtByteArray.length());
844 return toJS(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), wtfByteArray.get());
847 if (QMetaType::typeFlags(type).testFlag(QMetaType::PointerToQObject)) {
848 QObject* obj = variant.value<QObject*>();
851 return QtInstance::getQtInstance(obj, root, QtInstance::QtOwnership)->createRuntimeObject(exec);
854 if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(variant.type())))
855 return QtPixmapInstance::createPixmapRuntimeObject(exec, root, variant);
857 if (customRuntimeConversions()->contains(type)) {
858 if (!root->globalObject()->inherits(&JSDOMWindow::s_info))
859 return jsUndefined();
861 Document* document = (static_cast<JSDOMWindow*>(root->globalObject()))->impl()->document();
863 return jsUndefined();
864 return customRuntimeConversions()->value(type).toJSValueFunc(exec, toJSDOMGlobalObject(document, exec), variant);
867 if (type == QMetaType::QVariantMap) {
868 // create a new object, and stuff properties into it
869 JSObject* ret = constructEmptyObject(exec);
870 QVariantMap map = variant.value<QVariantMap>();
871 QVariantMap::const_iterator i = map.constBegin();
872 while (i != map.constEnd()) {
874 JSValue val = convertQVariantToValue(exec, root.get(), i.value());
876 PutPropertySlot slot;
877 ret->methodTable()->put(ret, exec, Identifier(&exec->globalData(), reinterpret_cast_ptr<const UChar *>(s.constData()), s.length()), val, slot);
887 if (type == QMetaType::QVariantList) {
888 QVariantList vl = variant.toList();
889 qConvDebug() << "got a " << vl.count() << " length list:" << vl;
890 return RuntimeArray::create(exec, new QtArray<QVariant>(vl, QMetaType::Void, root));
891 } else if (type == QMetaType::QStringList) {
892 QStringList sl = variant.value<QStringList>();
893 return RuntimeArray::create(exec, new QtArray<QString>(sl, QMetaType::QString, root));
894 } else if (type == (QMetaType::Type) qMetaTypeId<QObjectList>()) {
895 QObjectList ol= variant.value<QObjectList>();
896 return RuntimeArray::create(exec, new QtArray<QObject*>(ol, QMetaType::QObjectStar, root));
897 } else if (type == (QMetaType::Type)qMetaTypeId<QList<int> >()) {
898 QList<int> il= variant.value<QList<int> >();
899 return RuntimeArray::create(exec, new QtArray<int>(il, QMetaType::Int, root));
902 if (type == (QMetaType::Type)qMetaTypeId<QVariant>()) {
903 QVariant real = variant.value<QVariant>();
904 qConvDebug() << "real variant is:" << real;
905 return convertQVariantToValue(exec, root, real);
908 qConvDebug() << "fallback path for" << variant << variant.userType();
910 QString string = variant.toString();
911 UString ustring((UChar*)string.utf16(), string.length());
912 return jsString(exec, ustring);
915 // Type conversion metadata (from QtScript originally)
916 class QtMethodMatchType
929 : m_kind(Invalid) { }
934 QMetaType::Type typeId() const;
937 { return (m_kind != Invalid); }
939 bool isVariant() const
940 { return (m_kind == Variant); }
942 bool isMetaType() const
943 { return (m_kind == MetaType); }
945 bool isUnresolved() const
946 { return (m_kind == Unresolved); }
948 bool isMetaEnum() const
949 { return (m_kind == MetaEnum); }
951 QByteArray name() const;
953 int enumeratorIndex() const
954 { Q_ASSERT(isMetaEnum()); return m_typeId; }
956 static QtMethodMatchType variant()
957 { return QtMethodMatchType(Variant); }
959 static QtMethodMatchType metaType(int typeId, const QByteArray &name)
960 { return QtMethodMatchType(MetaType, typeId, name); }
962 static QtMethodMatchType metaEnum(int enumIndex, const QByteArray &name)
963 { return QtMethodMatchType(MetaEnum, enumIndex, name); }
965 static QtMethodMatchType unresolved(const QByteArray &name)
966 { return QtMethodMatchType(Unresolved, /*typeId=*/0, name); }
969 QtMethodMatchType(Kind kind, int typeId = 0, const QByteArray &name = QByteArray())
970 : m_kind(kind), m_typeId(typeId), m_name(name) { }
977 QMetaType::Type QtMethodMatchType::typeId() const
980 return (QMetaType::Type) QMetaType::type("QVariant");
981 return (QMetaType::Type) (isMetaEnum() ? QMetaType::Int : m_typeId);
984 QByteArray QtMethodMatchType::name() const
986 if (!m_name.isEmpty())
988 else if (m_kind == Variant)
993 struct QtMethodMatchData
997 QVector<QtMethodMatchType> types;
998 QVarLengthArray<QVariant, 10> args;
1000 QtMethodMatchData(int dist, int idx, QVector<QtMethodMatchType> typs,
1001 const QVarLengthArray<QVariant, 10> &as)
1002 : matchDistance(dist), index(idx), types(typs), args(as) { }
1006 bool isValid() const
1007 { return (index != -1); }
1009 int firstUnresolvedIndex() const
1011 for (int i=0; i < types.count(); i++) {
1012 if (types.at(i).isUnresolved())
1019 static int indexOfMetaEnum(const QMetaObject *meta, const QByteArray &str)
1023 int scopeIdx = str.indexOf("::");
1024 if (scopeIdx != -1) {
1025 scope = str.left(scopeIdx);
1026 name = str.mid(scopeIdx + 2);
1030 for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
1031 QMetaEnum m = meta->enumerator(i);
1032 if ((m.name() == name)/* && (scope.isEmpty() || (m.scope() == scope))*/)
1038 // Helper function for resolving methods
1039 // Largely based on code in QtScript for compatibility reasons
1040 static int findMethodIndex(JSContextRef context,
1041 const QMetaObject* meta,
1042 const QByteArray& signature,
1044 const JSValueRef arguments[],
1046 QVarLengthArray<QVariant, 10> &vars,
1048 JSValueRef* exception)
1050 QList<int> matchingIndices;
1052 bool overloads = !signature.contains('(');
1054 int count = meta->methodCount();
1055 for (int i = count - 1; i >= 0; --i) {
1056 const QMetaMethod m = meta->method(i);
1058 // Don't choose private methods
1059 if (m.access() == QMetaMethod::Private && !allowPrivate)
1062 // try and find all matching named methods
1063 if (!overloads && m.methodSignature() == signature)
1064 matchingIndices.append(i);
1065 else if (overloads && m.name() == signature)
1066 matchingIndices.append(i);
1069 int chosenIndex = -1;
1070 QVector<QtMethodMatchType> chosenTypes;
1072 QVarLengthArray<QVariant, 10> args;
1073 QVector<QtMethodMatchData> candidates;
1074 QVector<QtMethodMatchData> unresolved;
1075 QVector<int> tooFewArgs;
1076 QVector<int> conversionFailed;
1078 foreach(int index, matchingIndices) {
1079 QMetaMethod method = meta->method(index);
1081 QVector<QtMethodMatchType> types;
1082 bool unresolvedTypes = false;
1084 // resolve return type
1085 QByteArray returnTypeName = method.typeName();
1086 int rtype = method.returnType();
1087 if (rtype == QMetaType::UnknownType) {
1088 if (returnTypeName.endsWith('*')) {
1089 types.append(QtMethodMatchType::metaType(QMetaType::VoidStar, returnTypeName));
1091 int enumIndex = indexOfMetaEnum(meta, returnTypeName);
1092 if (enumIndex != -1)
1093 types.append(QtMethodMatchType::metaEnum(enumIndex, returnTypeName));
1095 unresolvedTypes = true;
1096 types.append(QtMethodMatchType::unresolved(returnTypeName));
1100 if (rtype == QMetaType::QVariant)
1101 types.append(QtMethodMatchType::variant());
1103 types.append(QtMethodMatchType::metaType(rtype, returnTypeName));
1106 // resolve argument types
1107 QList<QByteArray> parameterTypeNames = method.parameterTypes();
1108 for (int i = 0; i < parameterTypeNames.count(); ++i) {
1109 QByteArray argTypeName = parameterTypeNames.at(i);
1110 int atype = method.parameterType(i);
1111 if (atype == QMetaType::UnknownType) {
1112 int enumIndex = indexOfMetaEnum(meta, argTypeName);
1113 if (enumIndex != -1)
1114 types.append(QtMethodMatchType::metaEnum(enumIndex, argTypeName));
1116 unresolvedTypes = true;
1117 types.append(QtMethodMatchType::unresolved(argTypeName));
1120 if (atype == QMetaType::QVariant)
1121 types.append(QtMethodMatchType::variant());
1123 types.append(QtMethodMatchType::metaType(atype, argTypeName));
1127 // If the native method requires more arguments than what was passed from JavaScript
1128 if (argumentCount + 1 < static_cast<unsigned>(types.count())) {
1129 qMatchDebug() << "Match:too few args for" << method.methodSignature();
1130 tooFewArgs.append(index);
1134 if (unresolvedTypes) {
1135 qMatchDebug() << "Match:unresolved arg types for" << method.methodSignature();
1136 // remember it so we can give an error message later, if necessary
1137 unresolved.append(QtMethodMatchData(/*matchDistance=*/INT_MAX, index,
1138 types, QVarLengthArray<QVariant, 10>()));
1142 // Now convert arguments
1143 if (args.count() != types.count())
1144 args.resize(types.count());
1146 QtMethodMatchType retType = types[0];
1147 if (retType.typeId() != QMetaType::Void)
1148 args[0] = QVariant(retType.typeId(), (void *)0); // the return value
1150 bool converted = true;
1151 int matchDistance = 0;
1152 for (unsigned i = 0; converted && i + 1 < static_cast<unsigned>(types.count()); ++i) {
1153 JSValueRef arg = i < argumentCount ? arguments[i] : JSValueMakeUndefined(context);
1155 int argdistance = -1;
1156 QVariant v = convertValueToQVariant(toJS(context), toJS(toJS(context), arg), types.at(i+1).typeId(), &argdistance);
1157 if (argdistance >= 0) {
1158 matchDistance += argdistance;
1161 qMatchDebug() << "failed to convert argument " << i << "type" << types.at(i+1).typeId() << QMetaType::typeName(types.at(i+1).typeId());
1166 qMatchDebug() << "Match: " << method.methodSignature() << (converted ? "converted":"failed to convert") << "distance " << matchDistance;
1169 if ((argumentCount + 1 == static_cast<unsigned>(types.count()))
1170 && (matchDistance == 0)) {
1171 // perfect match, use this one
1172 chosenIndex = index;
1175 QtMethodMatchData currentMatch(matchDistance, index, types, args);
1176 if (candidates.isEmpty())
1177 candidates.append(currentMatch);
1179 QtMethodMatchData bestMatchSoFar = candidates.at(0);
1180 if ((args.count() > bestMatchSoFar.args.count())
1181 || ((args.count() == bestMatchSoFar.args.count())
1182 && (matchDistance <= bestMatchSoFar.matchDistance)))
1183 candidates.prepend(currentMatch);
1185 candidates.append(currentMatch);
1188 conversionFailed.append(index);
1195 if (chosenIndex == -1 && candidates.count() == 0) {
1196 // No valid functions at all - format an error message
1197 if (!conversionFailed.isEmpty()) {
1198 QString message = QString::fromLatin1("incompatible type of argument(s) in call to %0(); candidates were\n")
1199 .arg(QString::fromLatin1(signature));
1200 for (int i = 0; i < conversionFailed.size(); ++i) {
1202 message += QLatin1String("\n");
1203 QMetaMethod mtd = meta->method(conversionFailed.at(i));
1204 message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.methodSignature()));
1206 setException(context, exception, message);
1207 } else if (!unresolved.isEmpty()) {
1208 QtMethodMatchData argsInstance = unresolved.first();
1209 int unresolvedIndex = argsInstance.firstUnresolvedIndex();
1210 Q_ASSERT(unresolvedIndex != -1);
1211 QtMethodMatchType unresolvedType = argsInstance.types.at(unresolvedIndex);
1212 QString message = QString::fromLatin1("cannot call %0(): unknown type `%1'")
1213 .arg(QString::fromLatin1(signature))
1214 .arg(QLatin1String(unresolvedType.name()));
1215 setException(context, exception, message);
1217 QString message = QString::fromLatin1("too few arguments in call to %0(); candidates are\n")
1218 .arg(QString::fromLatin1(signature));
1219 for (int i = 0; i < tooFewArgs.size(); ++i) {
1221 message += QLatin1String("\n");
1222 QMetaMethod mtd = meta->method(tooFewArgs.at(i));
1223 message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.methodSignature()));
1225 setException(context, exception, message);
1229 if (chosenIndex == -1 && candidates.count() > 0) {
1230 QtMethodMatchData bestMatch = candidates.at(0);
1231 if ((candidates.size() > 1)
1232 && (bestMatch.args.count() == candidates.at(1).args.count())
1233 && (bestMatch.matchDistance == candidates.at(1).matchDistance)) {
1235 QString message = QString::fromLatin1("ambiguous call of overloaded function %0(); candidates were\n")
1236 .arg(QLatin1String(signature));
1237 for (int i = 0; i < candidates.size(); ++i) {
1238 // Only candidate for overload if argument count and match distance is same as best match
1239 if (candidates.at(i).args.count() == bestMatch.args.count()
1240 || candidates.at(i).matchDistance == bestMatch.matchDistance) {
1242 message += QLatin1String("\n");
1243 QMetaMethod mtd = meta->method(candidates.at(i).index);
1244 message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.methodSignature()));
1247 setException(context, exception, message);
1249 chosenIndex = bestMatch.index;
1250 args = bestMatch.args;
1254 if (chosenIndex != -1) {
1255 /* Copy the stuff over */
1257 vars.resize(args.count());
1258 for (i=0; i < args.count(); i++) {
1260 vvars[i] = vars[i].data();
1267 // Signals are not fuzzy matched as much as methods
1268 static int findSignalIndex(const QMetaObject* meta, int initialIndex, QByteArray signature)
1270 int index = initialIndex;
1271 QMetaMethod method = meta->method(index);
1272 bool overloads = !signature.contains('(');
1273 if (overloads && (method.attributes() & QMetaMethod::Cloned)) {
1274 // find the most general method
1276 method = meta->method(--index);
1277 } while (method.attributes() & QMetaMethod::Cloned);
1282 static JSClassRef prototypeForSignalsAndSlots()
1284 static JSClassDefinition classDef = {
1285 0, kJSClassAttributeNoAutomaticPrototype, 0, 0, 0, 0,
1286 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1288 static JSClassRef cls = JSClassCreate(&classDef);
1292 QtRuntimeMethod::QtRuntimeMethod(JSContextRef ctx, QObject* object, const QByteArray& identifier, int index, int flags, QtInstance* instance)
1294 , m_identifier(identifier)
1297 , m_instance(instance)
1301 QtRuntimeMethod::~QtRuntimeMethod()
1305 JSValueRef QtRuntimeMethod::call(JSContextRef context, JSObjectRef function, JSObjectRef /*thisObject*/, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1307 QtRuntimeMethod* d = toRuntimeMethod(context, function);
1309 setException(context, exception, QStringLiteral("cannot call function of deleted runtime method"));
1310 return JSValueMakeUndefined(context);
1312 QObject* obj = d->m_object;
1315 setException(context, exception, QStringLiteral("cannot call function of deleted QObject"));
1316 return JSValueMakeUndefined(context);
1319 // Allow for maximum of 10 arguments and size stack arrays accordingly.
1320 if (argumentCount > 10)
1321 return JSValueMakeUndefined(context);
1323 QVarLengthArray<QVariant, 10> vargs;
1326 int methodIndex = findMethodIndex(context, obj->metaObject(), d->m_identifier, argumentCount, arguments,
1327 (d->m_flags & AllowPrivate), vargs, (void **)qargs, exception);
1329 if (QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, methodIndex, qargs) >= 0)
1330 return JSValueMakeUndefined(context);
1332 if (vargs.size() > 0 && vargs[0].isValid())
1333 return toRef(toJS(context), convertQVariantToValue(toJS(context), d->m_instance->rootObject(), vargs[0]));
1335 return JSValueMakeUndefined(context);
1338 JSValueRef QtRuntimeMethod::connect(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1340 return connectOrDisconnect(context, function, thisObject, argumentCount, arguments, exception, true);
1343 JSValueRef QtRuntimeMethod::disconnect(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1345 return connectOrDisconnect(context, function, thisObject, argumentCount, arguments, exception, false);
1348 JSObjectRef QtRuntimeMethod::jsObjectRef(JSContextRef context, JSValueRef* exception)
1351 return toRef(m_jsObject.get());
1353 static JSStringRef connectStr = JSStringCreateWithUTF8CString("connect");
1354 static JSStringRef disconnectStr = JSStringCreateWithUTF8CString("disconnect");
1355 JSRetainPtr<JSStringRef> actualNameStr(Adopt, JSStringCreateWithUTF8CString(m_identifier.constData()));
1357 JSObjectRef object = JSObjectMakeFunctionWithCallback(context, actualNameStr.get(), call);
1358 JSValueProtect(context, object);
1360 JSObjectRef generalFunctionProto = JSValueToObject(context, JSObjectGetPrototype(context, object), 0);
1361 JSObjectRef runtimeMethodProto = JSObjectMake(context, prototypeForSignalsAndSlots(), this);
1362 JSObjectSetPrototype(context, runtimeMethodProto, generalFunctionProto);
1364 JSObjectSetPrototype(context, object, runtimeMethodProto);
1366 JSObjectRef connectFunction = JSObjectMakeFunctionWithCallback(context, connectStr, connect);
1367 JSObjectSetPrototype(context, connectFunction, runtimeMethodProto);
1369 JSObjectRef disconnectFunction = JSObjectMakeFunctionWithCallback(context, disconnectStr, disconnect);
1370 JSObjectSetPrototype(context, disconnectFunction, runtimeMethodProto);
1372 const JSPropertyAttributes attributes = kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete;
1373 JSObjectSetProperty(context, object, connectStr, connectFunction, attributes, exception);
1374 JSObjectSetProperty(context, object, disconnectStr, disconnectFunction, attributes, exception);
1376 m_jsObject = PassWeak<JSObject>(toJS(object));
1381 QtRuntimeMethod* QtRuntimeMethod::toRuntimeMethod(JSContextRef context, JSObjectRef object)
1383 JSObjectRef proto = JSValueToObject(context, JSObjectGetPrototype(context, object), 0);
1386 if (!JSValueIsObjectOfClass(context, proto, prototypeForSignalsAndSlots()))
1388 return static_cast<QtRuntimeMethod*>(JSObjectGetPrivate(proto));
1391 JSValueRef QtRuntimeMethod::connectOrDisconnect(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception, bool connect)
1393 QtRuntimeMethod* d = toRuntimeMethod(context, thisObject);
1395 d = toRuntimeMethod(context, function);
1397 QString errorStr = QStringLiteral("QtMetaMethod.%1: Cannot connect to/from deleted QObject").arg(connect ? QStringLiteral("connect") : QStringLiteral("disconnect"));
1398 setException(context, exception, errorStr);
1399 return JSValueMakeUndefined(context);
1402 QString functionName = connect ? QStringLiteral("connect") : QStringLiteral("disconnect");
1404 if (!argumentCount) {
1405 QString errorStr = QStringLiteral("QtMetaMethod.%1: no arguments given").arg(connect ? QStringLiteral("connect") : QStringLiteral("disconnect"));
1406 setException(context, exception, errorStr);
1407 return JSValueMakeUndefined(context);
1410 if ((!(d->m_flags & QtRuntimeMethod::MethodIsSignal))) {
1411 setException(context, exception, QStringLiteral("QtMetaMethod.%3: %1::%2() is not a signal").arg(QString::fromUtf8(d->m_object.data()->metaObject()->className())).arg(QString::fromAscii(d->m_identifier)).arg(functionName));
1412 return JSValueMakeUndefined(context);
1415 QObject* sender = d->m_object.data();
1418 setException(context, exception, QStringLiteral("cannot call function of deleted QObject"));
1419 return JSValueMakeUndefined(context);
1422 int signalIndex = findSignalIndex(sender->metaObject(), d->m_index, d->m_identifier);
1424 JSObjectRef targetObject = 0;
1425 JSObjectRef targetFunction = 0;
1427 if (argumentCount == 1) {
1428 if (!JSValueIsObject(context, arguments[0])) {
1429 setException(context, exception, QStringLiteral("QtMetaMethod.%1: target is not a function").arg(functionName));
1430 return JSValueMakeUndefined(context);
1432 targetFunction = JSValueToObject(context, arguments[0], exception);
1434 // object.signal.connect(someFunction);
1435 if (JSObjectIsFunction(context, targetFunction)) {
1436 // object.signal.connect(otherObject.slot);
1437 if (QtRuntimeMethod* targetMethod = toRuntimeMethod(context, targetFunction))
1438 targetObject = toRef(QtInstance::getQtInstance(targetMethod->m_object.data(), d->m_instance->rootObject(), QtInstance::QtOwnership)->createRuntimeObject(toJS(context)));
1442 // object.signal.connect(object, someFunction);
1443 targetObject = JSValueToObject(context, arguments[0], exception);
1444 if (JSValueIsObject(context, arguments[1])) {
1445 JSObjectRef obj = JSValueToObject(context, arguments[1], exception);
1446 if (JSObjectIsFunction(context, obj))
1447 targetFunction = obj;
1449 if (!targetFunction) {
1450 // Maybe the second argument is a string
1451 JSValueRef conversionException = 0;
1452 JSRetainPtr<JSStringRef> functionName(Adopt, JSValueToStringCopy(context, arguments[1], &conversionException));
1453 if (functionName && !conversionException) {
1454 JSValueRef functionProperty = JSObjectGetProperty(context, targetObject, functionName.get(), &conversionException);
1455 if (!conversionException && functionProperty && JSValueIsObject(context, functionProperty)) {
1456 targetFunction = JSValueToObject(context, functionProperty, 0);
1457 if (!JSObjectIsFunction(context, targetFunction))
1464 // object.signal.connect(someObject);
1465 if (!targetFunction) {
1466 QString message = QStringLiteral("QtMetaMethod.%1: target is not a function");
1468 message = message.arg(QStringLiteral("connect"));
1470 message = message.arg(QStringLiteral("disconnect"));
1471 setException(context, exception, message);
1472 return JSValueMakeUndefined(context);
1476 // to connect, we need:
1477 // target object [from ctor]
1478 // target signal index etc. [from ctor]
1479 // receiver function [from arguments]
1480 // receiver this object [from arguments]
1482 QtConnectionObject* conn = new QtConnectionObject(context, QtInstance::getQtInstance(sender, d->m_instance->rootObject(), QtInstance::QtOwnership), signalIndex, targetObject, targetFunction);
1483 bool ok = QMetaObject::connect(sender, signalIndex, conn, conn->metaObject()->methodOffset());
1486 QString msg = QString(QLatin1String("QtMetaMethod.connect: failed to connect to %1::%2()"))
1487 .arg(QLatin1String(sender->metaObject()->className()))
1488 .arg(QLatin1String(d->m_identifier));
1489 setException(context, exception, msg);
1490 return JSValueMakeUndefined(context);
1494 QtConnectionObject::connections.insert(sender, conn);
1496 return JSValueMakeUndefined(context);
1499 // Now to find our previous connection object.
1500 QList<QtConnectionObject*> conns = QtConnectionObject::connections.values(sender);
1502 foreach (QtConnectionObject* conn, conns) {
1503 // Is this the right connection?
1504 if (!conn->match(context, sender, signalIndex, targetObject, targetFunction))
1507 // Yep, disconnect it
1508 QMetaObject::disconnect(sender, signalIndex, conn, conn->metaObject()->methodOffset());
1509 delete conn; // this will also remove it from the map
1510 return JSValueMakeUndefined(context);
1513 QString msg = QStringLiteral("QtMetaMethod.disconnect: failed to disconnect from %1::%2()")
1514 .arg(QLatin1String(sender->metaObject()->className()))
1515 .arg(QLatin1String(d->m_identifier));
1517 setException(context, exception, msg);
1518 return JSValueMakeUndefined(context);
1523 QMultiMap<QObject*, QtConnectionObject*> QtConnectionObject::connections;
1525 QtConnectionObject::QtConnectionObject(JSContextRef context, PassRefPtr<QtInstance> senderInstance, int signalIndex, JSObjectRef receiver, JSObjectRef receiverFunction)
1526 : QObject(senderInstance->getObject())
1527 , m_context(JSContextGetGlobalContext(context))
1528 , m_rootObject(senderInstance->rootObject())
1529 , m_signalIndex(signalIndex)
1530 , m_receiver(receiver)
1531 , m_receiverFunction(receiverFunction)
1534 JSValueProtect(m_context, m_receiver);
1535 JSValueProtect(m_context, m_receiverFunction);
1538 QtConnectionObject::~QtConnectionObject()
1540 connections.remove(parent(), this);
1543 JSValueUnprotect(m_context, m_receiver);
1544 JSValueUnprotect(m_context, m_receiverFunction);
1547 // Begin moc-generated code -- modify with care! Check "HAND EDIT" parts
1548 struct qt_meta_stringdata_QtConnectionObject_t {
1549 QByteArrayData data[3];
1550 char stringdata[44];
1552 #define QT_MOC_LITERAL(idx, ofs, len) { \
1553 Q_REFCOUNT_INITIALIZE_STATIC, len, 0, 0, \
1554 offsetof(qt_meta_stringdata_QtConnectionObject_t, stringdata) + ofs \
1555 - idx * sizeof(QByteArrayData) \
1557 static const qt_meta_stringdata_QtConnectionObject_t qt_meta_stringdata_QtConnectionObject = {
1559 QT_MOC_LITERAL(0, 0, 33),
1560 QT_MOC_LITERAL(1, 34, 7),
1561 QT_MOC_LITERAL(2, 42, 0)
1563 "JSC::Bindings::QtConnectionObject\0"
1566 #undef QT_MOC_LITERAL
1568 static const uint qt_meta_data_QtConnectionObject[] = {
1577 0, 0, // constructors
1581 // slots: name, argc, parameters, tag, flags
1584 // slots: parameters
1590 void QtConnectionObject::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
1592 if (_c == QMetaObject::InvokeMetaMethod) {
1593 Q_ASSERT(staticMetaObject.cast(_o));
1594 QtConnectionObject *_t = static_cast<QtConnectionObject *>(_o);
1596 case 0: _t->execute(_a); break; // HAND EDIT: add _a parameter
1602 const QMetaObject QtConnectionObject::staticMetaObject = {
1603 { &QObject::staticMetaObject, qt_meta_stringdata_QtConnectionObject.data,
1604 qt_meta_data_QtConnectionObject, qt_static_metacall, 0, 0 }
1607 const QMetaObject *QtConnectionObject::metaObject() const
1609 return &staticMetaObject;
1612 void *QtConnectionObject::qt_metacast(const char *_clname)
1614 if (!_clname) return 0;
1615 if (!strcmp(_clname, qt_meta_stringdata_QtConnectionObject.stringdata))
1616 return static_cast<void*>(const_cast<QtConnectionObject*>(this));
1617 return QObject::qt_metacast(_clname);
1620 int QtConnectionObject::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
1622 _id = QObject::qt_metacall(_c, _id, _a);
1625 if (_c == QMetaObject::InvokeMetaMethod) {
1627 qt_static_metacall(this, _c, _id, _a);
1632 // End of moc-generated code
1634 void QtConnectionObject::execute(void** argv)
1636 QObject* sender = parent();
1637 const QMetaObject* meta = sender->metaObject();
1638 const QMetaMethod method = meta->method(m_signalIndex);
1640 JSValueRef* ignoredException = 0;
1641 JSRetainPtr<JSStringRef> lengthProperty(JSStringCreateWithUTF8CString("length"));
1642 int receiverLength = int(JSValueToNumber(m_context, JSObjectGetProperty(m_context, m_receiverFunction, lengthProperty.get(), ignoredException), ignoredException));
1643 int argc = qMax(method.parameterCount(), receiverLength);
1644 WTF::Vector<JSValueRef> args(argc);
1646 // TODO: remove once conversion functions use JSC API.
1647 ExecState* exec = ::toJS(m_context);
1649 for (int i = 0; i < argc; i++) {
1650 int argType = method.parameterType(i);
1651 args[i] = ::toRef(exec, convertQVariantToValue(exec, m_rootObject, QVariant(argType, argv[i+1])));
1654 JSObjectCallAsFunction(m_context, m_receiverFunction, m_receiver, argc, args.data(), 0);
1657 bool QtConnectionObject::match(JSContextRef context, QObject* sender, int signalIndex, JSObjectRef receiver, JSObjectRef receiverFunction)
1659 if (sender != parent() || signalIndex != m_signalIndex)
1661 JSValueRef* ignoredException = 0;
1662 const bool receiverMatch = (!receiver && !m_receiver) || (receiver && m_receiver && JSValueIsEqual(context, receiver, m_receiver, ignoredException));
1663 return receiverMatch && JSValueIsEqual(context, receiverFunction, m_receiverFunction, ignoredException);
1668 template <typename T> QtArray<T>::QtArray(QList<T> list, QMetaType::Type type, PassRefPtr<RootObject> rootObject)
1673 m_length = m_list.count();
1676 template <typename T> QtArray<T>::~QtArray ()
1680 template <typename T> RootObject* QtArray<T>::rootObject() const
1682 return m_rootObject && m_rootObject->isValid() ? m_rootObject.get() : 0;
1685 template <typename T> void QtArray<T>::setValueAt(ExecState* exec, unsigned index, JSValue aValue) const
1687 // QtScript sets the value, but doesn't forward it to the original source
1688 // (e.g. if you do 'object.intList[5] = 6', the object is not updated, but the
1689 // copy of the list is).
1691 QVariant val = convertValueToQVariant(exec, aValue, m_type, &dist);
1694 m_list[index] = val.value<T>();
1699 template <typename T> JSValue QtArray<T>::valueAt(ExecState *exec, unsigned int index) const
1701 if (index < m_length) {
1702 T val = m_list.at(index);
1703 return convertQVariantToValue(exec, rootObject(), QVariant::fromValue(val));
1706 return jsUndefined();