Source/WebCore/ChangeLog

 12012-08-21 Simon Hausmann <simon.hausmann@nokia.com>
 2
 3 [Qt] Port convertQVariantToValue to use the JSC C API
 4 https://bugs.webkit.org/show_bug.cgi?id=93889
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Based on patch by Noam Rosenthal.
 9
 10 * bridge/qt/qt_instance.cpp:
 11 (Bindings):
 12 (JSC::Bindings::QtField::valueFromInstance):
 13 * bridge/qt/qt_runtime.cpp:
 14 (JSC::Bindings::convertQVariantToValue):
 15 (JSC::Bindings::QtRuntimeMethod::call):
 16 (JSC::Bindings::QtConnectionObject::execute):
 17 (JSC::Bindings::::valueAt):
 18 * bridge/qt/qt_runtime.h:
 19 (Bindings):
 20
1212012-08-17 Simon Hausmann <simon.hausmann@nokia.com>
222
323 [Qt] REGRESSION(r125428): fast/profiler/nested-start-and-stop-profiler.html fails

Source/WebCore/bridge/qt/qt_instance.cpp

2020#include "config.h"
2121#include "qt_instance.h"
2222
 23#include "APICast.h"
2324#include "Error.h"
2425#include "JSDOMBinding.h"
2526#include "JSDOMWindowBase.h"

@@JSValue QtInstance::valueOf(ExecState* exec) const
360361}
361362
362363// In qt_runtime.cpp
363 JSValue convertQVariantToValue(ExecState*, PassRefPtr<RootObject> root, const QVariant& variant);
364364QVariant convertValueToQVariant(ExecState*, JSValue, QMetaType::Type hint, int *distance);
365365
366366QByteArray QtField::name() const

@@JSValue QtField::valueFromInstance(ExecState* exec, const Instance* inst) const
394394 else if (m_type == DynamicProperty)
395395 val = obj->property(m_dynamicProperty);
396396#endif
397  return convertQVariantToValue(exec, inst->rootObject(), val);
 397 JSValueRef exception = 0;
 398 JSValueRef jsValue = convertQVariantToValue(toRef(exec), inst->rootObject(), val, &exception);
 399 if (exception)
 400 return throwError(exec, toJS(exec, exception));
 401 return toJS(exec, jsValue);
398402 }
399403 QString msg = QString(QLatin1String("cannot access member `%1' of deleted QObject")).arg(QLatin1String(name()));
400404 return throwError(exec, createError(exec, msg.toLatin1().constData()));

Source/WebCore/bridge/qt/qt_runtime.cpp

@@QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type
775775 return convertValueToQVariant(exec, value, hint, distance, &visitedObjects, recursionLimit);
776776}
777777
778 JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant)
 778JSValueRef convertQVariantToValue(JSContextRef context, PassRefPtr<RootObject> root, const QVariant& variant, JSValueRef *exception)
779779{
780780 // Variants with QObject * can be isNull but not a null pointer
781781 // An empty QString variant is also null

@@JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, con
786786 !QMetaType::typeFlags(type).testFlag(QMetaType::PointerToQObject) &&
787787 type != QMetaType::VoidStar &&
788788 type != QMetaType::QString) {
789  return jsNull();
 789 return JSValueMakeNull(context);
790790 }
791791
792  JSLockHolder lock(exec);
793 
794792 if (type == QMetaType::Bool)
795  return jsBoolean(variant.toBool());
 793 return JSValueMakeBoolean(context, variant.toBool());
796794
797795 if (type == QMetaType::Int ||
798796 type == QMetaType::UInt ||

@@JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, con
804802 type == QMetaType::UShort ||
805803 type == QMetaType::Float ||
806804 type == QMetaType::Double)
807  return jsNumber(variant.toDouble());
 805 return JSValueMakeNumber(context, variant.toDouble());
808806
809807 if (type == QMetaType::QDateTime ||
810808 type == QMetaType::QDate ||

@@JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, con
824822 }
825823
826824 // 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());
834  dt.setIsDST(-1);
835  double ms = gregorianDateTimeToMS(exec, dt, time.msec(), /*inputIsUTC*/ false);
836 
837  return DateInstance::create(exec, exec->lexicalGlobalObject()->dateStructure(), trunc(ms));
 825 const JSValueRef arguments[] = {
 826 JSValueMakeNumber(context, date.year()),
 827 JSValueMakeNumber(context, date.month() - 1),
 828 JSValueMakeNumber(context, date.day()),
 829 JSValueMakeNumber(context, time.hour()),
 830 JSValueMakeNumber(context, time.minute()),
 831 JSValueMakeNumber(context, time.second()),
 832 JSValueMakeNumber(context, time.msec())
 833 };
 834 return JSObjectMakeDate(context, 7, arguments, exception);
838835 }
839836
840837 if (type == QMetaType::QByteArray) {
 838 // ### FIXME: Need private JSC C API.
841839 QByteArray qtByteArray = variant.value<QByteArray>();
842840 WTF::RefPtr<WTF::Uint8ClampedArray> wtfByteArray = WTF::Uint8ClampedArray::createUninitialized(qtByteArray.length());
843841 memcpy(wtfByteArray->data(), qtByteArray.constData(), qtByteArray.length());
844  return toJS(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), wtfByteArray.get());
 842 ExecState* exec = toJS(context);
 843 return toRef(exec, toJS(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), wtfByteArray.get()));
845844 }
846845
847846 if (QMetaType::typeFlags(type).testFlag(QMetaType::PointerToQObject)) {
848847 QObject* obj = variant.value<QObject*>();
849848 if (!obj)
850  return jsNull();
851  return QtInstance::getQtInstance(obj, root, QtInstance::QtOwnership)->createRuntimeObject(exec);
 849 return JSValueMakeNull(context);
 850 ExecState* exec = toJS(context);
 851 return toRef(exec, QtInstance::getQtInstance(obj, root, QtInstance::QtOwnership)->createRuntimeObject(exec));
852852 }
853853
854  if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(variant.type())))
855  return QtPixmapInstance::createPixmapRuntimeObject(exec, root, variant);
 854 if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(variant.type()))) {
 855 ExecState* exec = toJS(context);
 856 return toRef(exec, QtPixmapInstance::createPixmapRuntimeObject(exec, root, variant));
 857 }
856858
857859 if (customRuntimeConversions()->contains(type)) {
858860 if (!root->globalObject()->inherits(&JSDOMWindow::s_info))
859  return jsUndefined();
 861 return JSValueMakeUndefined(context);
860862
861863 Document* document = (static_cast<JSDOMWindow*>(root->globalObject()))->impl()->document();
862864 if (!document)
863  return jsUndefined();
864  return customRuntimeConversions()->value(type).toJSValueFunc(exec, toJSDOMGlobalObject(document, exec), variant);
 865 return JSValueMakeUndefined(context);
 866 ExecState* exec = toJS(context);
 867 return toRef(exec, customRuntimeConversions()->value(type).toJSValueFunc(exec, toJSDOMGlobalObject(document, exec), variant));
865868 }
866869
867870 if (type == QMetaType::QVariantMap) {
868871 // create a new object, and stuff properties into it
869  JSObject* ret = constructEmptyObject(exec);
 872 JSObjectRef ret = JSObjectMake(context, 0, 0);
870873 QVariantMap map = variant.value<QVariantMap>();
871874 QVariantMap::const_iterator i = map.constBegin();
872875 while (i != map.constEnd()) {
873876 QString s = i.key();
874  JSValue val = convertQVariantToValue(exec, root.get(), i.value());
875  if (val) {
876  PutPropertySlot slot;
877  ret->methodTable()->put(ret, exec, Identifier(&exec->globalData(), reinterpret_cast_ptr<const UChar *>(s.constData()), s.length()), val, slot);
878  // ### error case?
879  }
 877 JSStringRef propertyName = JSStringCreateWithCharacters(reinterpret_cast<const JSChar*>(s.constData()), s.length());
 878 JSValueRef propertyValue = convertQVariantToValue(context, root.get(), i.value(), exception);
 879 if (exception && *exception)
 880 break;
 881 if (propertyValue)
 882 JSObjectSetProperty(context, ret, propertyName, propertyValue, kJSPropertyAttributeNone, exception);
 883 if (exception && *exception)
 884 break;
 885 JSStringRelease(propertyName);
880886 ++i;
881887 }
882888

@@JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, con
885891
886892 // List types
887893 if (type == QMetaType::QVariantList) {
 894 // ### Could use special array class that lazily converts.
888895 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));
 896 JSObjectRef array = JSObjectMakeArray(context, 0, 0, exception);
 897 if (exception && *exception)
 898 return array;
 899 for (int i = 0; i < vl.count(); ++i) {
 900 JSValueRef property = convertQVariantToValue(context, root.get(), vl.at(i), exception);
 901 if (exception && *exception)
 902 break;
 903 if (property)
 904 JSObjectSetPropertyAtIndex(context, array, i, property, exception);
 905 if (exception && *exception)
 906 break;
 907 }
 908 return array;
891909 } else if (type == QMetaType::QStringList) {
892910 QStringList sl = variant.value<QStringList>();
893  return RuntimeArray::create(exec, new QtArray<QString>(sl, QMetaType::QString, root));
 911 JSObjectRef array = JSObjectMakeArray(context, 0, 0, exception);
 912 for (int i = 0; i < sl.count(); ++i) {
 913 const QString& s = sl.at(i);
 914 JSStringRef jsString = JSStringCreateWithCharacters(reinterpret_cast<const JSChar*>(s.constData()), s.length());
 915 JSObjectSetPropertyAtIndex(context, array, i, JSValueMakeString(context, jsString), exception);
 916 JSStringRelease(jsString);
 917 }
 918 return array;
894919 } 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));
 920 QObjectList ol = variant.value<QObjectList>();
 921 JSObjectRef array = JSObjectMakeArray(context, 0, 0, exception);
 922 ExecState* exec = toJS(context);
 923 for (int i = 0; i < ol.count(); ++i) {
 924 JSValueRef jsObject = toRef(exec, QtInstance::getQtInstance(ol.at(i), root, QtInstance::QtOwnership)->createRuntimeObject(exec));
 925 JSObjectSetPropertyAtIndex(context, array, i, jsObject, exception);
 926 }
 927 return array;
897928 } 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));
 929 QList<int> il = variant.value<QList<int> >();
 930 JSObjectRef array = JSObjectMakeArray(context, 0, 0, exception);
 931 for (int i = 0; i < il.count(); ++i)
 932 JSObjectSetPropertyAtIndex(context, array, i, JSValueMakeNumber(context, il.at(i)), exception);
 933 return array;
900934 }
901935
902936 if (type == (QMetaType::Type)qMetaTypeId<QVariant>()) {
903937 QVariant real = variant.value<QVariant>();
904938 qConvDebug() << "real variant is:" << real;
905  return convertQVariantToValue(exec, root, real);
 939 return convertQVariantToValue(context, root.get(), real, exception);
906940 }
907941
908942 qConvDebug() << "fallback path for" << variant << variant.userType();
909943
910944 QString string = variant.toString();
911  UString ustring((UChar*)string.utf16(), string.length());
912  return jsString(exec, ustring);
 945 JSStringRef jsstring = JSStringCreateWithCharacters(reinterpret_cast<const JSChar*>(string.constData()), string.length());
 946 JSValueRef value = JSValueMakeString(context, jsstring);
 947 JSStringRelease(jsstring);
 948 return value;
913949}
914950
915951// Type conversion metadata (from QtScript originally)

@@JSValueRef QtRuntimeMethod::call(JSContextRef context, JSObjectRef function, JSO
13331369 return JSValueMakeUndefined(context);
13341370
13351371 if (vargs.size() > 0 && vargs[0].isValid())
1336  return toRef(toJS(context), convertQVariantToValue(toJS(context), d->m_instance->rootObject(), vargs[0]));
 1372 return convertQVariantToValue(context, d->m_instance->rootObject(), vargs[0], exception);
13371373
13381374 return JSValueMakeUndefined(context);
13391375}

@@void QtConnectionObject::execute(void** argv)
16501686
16511687 for (int i = 0; i < argc; i++) {
16521688 int argType = method.parameterType(i);
1653  args[i] = ::toRef(exec, convertQVariantToValue(exec, m_rootObject, QVariant(argType, argv[i+1])));
 1689 args[i] = convertQVariantToValue(toRef(exec), m_rootObject, QVariant(argType, argv[i+1]), ignoredException);
16541690 }
16551691
16561692 JSObjectCallAsFunction(m_context, m_receiverFunction, m_receiver, argc, args.data(), 0);

@@template <typename T> JSValue QtArray<T>::valueAt(ExecState *exec, unsigned int
17021738{
17031739 if (index < m_length) {
17041740 T val = m_list.at(index);
1705  return convertQVariantToValue(exec, rootObject(), QVariant::fromValue(val));
 1741 return convertQVariantToValue(toRef(exec), rootObject(), QVariant::fromValue(val));
17061742 }
17071743
17081744 return jsUndefined();

Source/WebCore/bridge/qt/qt_runtime.h

@@typedef JSValue (*ConvertToJSValueFunction)(ExecState* exec, WebCore::JSDOMGloba
156156void registerCustomType(int qtMetaTypeId, ConvertToVariantFunction, ConvertToJSValueFunction);
157157
158158QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type hint, int *distance);
159 JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant);
 159JSValueRef convertQVariantToValue(JSContextRef, PassRefPtr<RootObject>, const QVariant&, JSValueRef* exception);
160160
161161void setException(JSContextRef, JSValueRef* exception, const QString& text);
162162