Title: [126290] trunk/Source/WebCore
Revision
126290
Author
[email protected]
Date
2012-08-22 05:26:18 -0700 (Wed, 22 Aug 2012)

Log Message

[Qt] Port convertQVariantToValue to use the JSC C API
https://bugs.webkit.org/show_bug.cgi?id=93889

Reviewed by Kenneth Rohde Christiansen.

Based on patch by Noam Rosenthal.

This patch is another step towards reducing the use of internal JSC API
in the Qt bridge. Most of the conversion from QVariant to JS values is
straight-forward. The biggest behavioural change is that QVariant lists
are converted on-the-spot instead of lazily. Bug #94691 tracks fixing
that.

* bridge/qt/qt_instance.cpp:
(Bindings):
(JSC::Bindings::QtField::valueFromInstance):
* bridge/qt/qt_runtime.cpp:
(JSC::Bindings::convertQVariantToValue):
(JSC::Bindings::QtRuntimeMethod::call):
(JSC::Bindings::QtConnectionObject::execute):
(JSC::Bindings::::valueAt):
* bridge/qt/qt_runtime.h:
(Bindings):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (126289 => 126290)


--- trunk/Source/WebCore/ChangeLog	2012-08-22 11:21:39 UTC (rev 126289)
+++ trunk/Source/WebCore/ChangeLog	2012-08-22 12:26:18 UTC (rev 126290)
@@ -1,5 +1,31 @@
 2012-08-22  Simon Hausmann  <[email protected]>
 
+        [Qt] Port convertQVariantToValue to use the JSC C API
+        https://bugs.webkit.org/show_bug.cgi?id=93889
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        Based on patch by Noam Rosenthal.
+
+        This patch is another step towards reducing the use of internal JSC API
+        in the Qt bridge. Most of the conversion from QVariant to JS values is
+        straight-forward. The biggest behavioural change is that QVariant lists
+        are converted on-the-spot instead of lazily. Bug #94691 tracks fixing
+        that.
+
+        * bridge/qt/qt_instance.cpp:
+        (Bindings):
+        (JSC::Bindings::QtField::valueFromInstance):
+        * bridge/qt/qt_runtime.cpp:
+        (JSC::Bindings::convertQVariantToValue):
+        (JSC::Bindings::QtRuntimeMethod::call):
+        (JSC::Bindings::QtConnectionObject::execute):
+        (JSC::Bindings::::valueAt):
+        * bridge/qt/qt_runtime.h:
+        (Bindings):
+
+2012-08-22  Simon Hausmann  <[email protected]>
+
         [Qt] REGRESSION(r125428): fast/profiler/nested-start-and-stop-profiler.html fails
         https://bugs.webkit.org/show_bug.cgi?id=93897
 

Modified: trunk/Source/WebCore/bridge/qt/qt_instance.cpp (126289 => 126290)


--- trunk/Source/WebCore/bridge/qt/qt_instance.cpp	2012-08-22 11:21:39 UTC (rev 126289)
+++ trunk/Source/WebCore/bridge/qt/qt_instance.cpp	2012-08-22 12:26:18 UTC (rev 126290)
@@ -20,6 +20,7 @@
 #include "config.h"
 #include "qt_instance.h"
 
+#include "APICast.h"
 #include "Error.h"
 #include "JSDOMBinding.h"
 #include "JSDOMWindowBase.h"
@@ -303,7 +304,6 @@
 }
 
 // In qt_runtime.cpp
-JSValue convertQVariantToValue(ExecState*, PassRefPtr<RootObject> root, const QVariant& variant);
 QVariant convertValueToQVariant(ExecState*, JSValue, QMetaType::Type hint, int *distance);
 
 QByteArray QtField::name() const
@@ -337,7 +337,11 @@
         else if (m_type == DynamicProperty)
             val = obj->property(m_dynamicProperty);
 #endif
-        return convertQVariantToValue(exec, inst->rootObject(), val);
+        JSValueRef exception = 0;
+        JSValueRef jsValue = convertQVariantToValue(toRef(exec), inst->rootObject(), val, &exception);
+        if (exception)
+            return throwError(exec, toJS(exec, exception));
+        return toJS(exec, jsValue);
     }
     QString msg = QString(QLatin1String("cannot access member `%1' of deleted QObject")).arg(QLatin1String(name()));
     return throwError(exec, createError(exec, msg.toLatin1().constData()));

Modified: trunk/Source/WebCore/bridge/qt/qt_runtime.cpp (126289 => 126290)


--- trunk/Source/WebCore/bridge/qt/qt_runtime.cpp	2012-08-22 11:21:39 UTC (rev 126289)
+++ trunk/Source/WebCore/bridge/qt/qt_runtime.cpp	2012-08-22 12:26:18 UTC (rev 126290)
@@ -775,7 +775,7 @@
     return convertValueToQVariant(exec, value, hint, distance, &visitedObjects, recursionLimit);
 }
 
-JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant)
+JSValueRef convertQVariantToValue(JSContextRef context, PassRefPtr<RootObject> root, const QVariant& variant, JSValueRef *exception)
 {
     // Variants with QObject * can be isNull but not a null pointer
     // An empty QString variant is also null
@@ -786,13 +786,11 @@
         !QMetaType::typeFlags(type).testFlag(QMetaType::PointerToQObject) &&
         type != QMetaType::VoidStar &&
         type != QMetaType::QString) {
-        return jsNull();
+        return JSValueMakeNull(context);
     }
 
-    JSLockHolder lock(exec);
-
     if (type == QMetaType::Bool)
-        return jsBoolean(variant.toBool());
+        return JSValueMakeBoolean(context, variant.toBool());
 
     if (type == QMetaType::Int ||
         type == QMetaType::UInt ||
@@ -804,7 +802,7 @@
         type == QMetaType::UShort ||
         type == QMetaType::Float ||
         type == QMetaType::Double)
-        return jsNumber(variant.toDouble());
+        return JSValueMakeNumber(context, variant.toDouble());
 
     if (type == QMetaType::QDateTime ||
         type == QMetaType::QDate ||
@@ -824,59 +822,62 @@
         }
 
         // Dates specified this way are in local time (we convert DateTimes above)
-        GregorianDateTime dt;
-        dt.setYear(date.year());
-        dt.setMonth(date.month() - 1);
-        dt.setMonthDay(date.day());
-        dt.setHour(time.hour());
-        dt.setMinute(time.minute());
-        dt.setSecond(time.second());
-        dt.setIsDST(-1);
-        double ms = gregorianDateTimeToMS(exec, dt, time.msec(), /*inputIsUTC*/ false);
-
-        return DateInstance::create(exec, exec->lexicalGlobalObject()->dateStructure(), trunc(ms));
+        const JSValueRef arguments[] = {
+            JSValueMakeNumber(context, date.year()),
+            JSValueMakeNumber(context, date.month() - 1),
+            JSValueMakeNumber(context, date.day()),
+            JSValueMakeNumber(context, time.hour()),
+            JSValueMakeNumber(context, time.minute()),
+            JSValueMakeNumber(context, time.second()),
+            JSValueMakeNumber(context, time.msec())
+        };
+        return JSObjectMakeDate(context, 7, arguments, exception);
     }
 
     if (type == QMetaType::QByteArray) {
         QByteArray qtByteArray = variant.value<QByteArray>();
         WTF::RefPtr<WTF::Uint8ClampedArray> wtfByteArray = WTF::Uint8ClampedArray::createUninitialized(qtByteArray.length());
         memcpy(wtfByteArray->data(), qtByteArray.constData(), qtByteArray.length());
-        return toJS(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), wtfByteArray.get());
+        ExecState* exec = toJS(context);
+        return toRef(exec, toJS(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), wtfByteArray.get()));
     }
 
     if (QMetaType::typeFlags(type).testFlag(QMetaType::PointerToQObject)) {
         QObject* obj = variant.value<QObject*>();
         if (!obj)
-            return jsNull();
-        return QtInstance::getQtInstance(obj, root, QtInstance::QtOwnership)->createRuntimeObject(exec);
+            return JSValueMakeNull(context);
+        ExecState* exec = toJS(context);
+        return toRef(exec, QtInstance::getQtInstance(obj, root, QtInstance::QtOwnership)->createRuntimeObject(exec));
     }
 
-    if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(variant.type())))
-        return QtPixmapInstance::createPixmapRuntimeObject(exec, root, variant);
+    if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(variant.type()))) {
+        ExecState* exec = toJS(context);
+        return toRef(exec, QtPixmapInstance::createPixmapRuntimeObject(exec, root, variant));
+    }
 
     if (customRuntimeConversions()->contains(type)) {
         if (!root->globalObject()->inherits(&JSDOMWindow::s_info))
-            return jsUndefined();
+            return JSValueMakeUndefined(context);
 
         Document* document = (static_cast<JSDOMWindow*>(root->globalObject()))->impl()->document();
         if (!document)
-            return jsUndefined();
-        return customRuntimeConversions()->value(type).toJSValueFunc(exec, toJSDOMGlobalObject(document, exec), variant);
+            return JSValueMakeUndefined(context);
+        ExecState* exec = toJS(context);
+        return toRef(exec, customRuntimeConversions()->value(type).toJSValueFunc(exec, toJSDOMGlobalObject(document, exec), variant));
     }
 
     if (type == QMetaType::QVariantMap) {
         // create a new object, and stuff properties into it
-        JSObject* ret = constructEmptyObject(exec);
+        JSObjectRef ret = JSObjectMake(context, 0, 0);
         QVariantMap map = variant.value<QVariantMap>();
         QVariantMap::const_iterator i = map.constBegin();
         while (i != map.constEnd()) {
             QString s = i.key();
-            JSValue val = convertQVariantToValue(exec, root.get(), i.value());
-            if (val) {
-                PutPropertySlot slot;
-                ret->methodTable()->put(ret, exec, Identifier(&exec->globalData(), reinterpret_cast_ptr<const UChar *>(s.constData()), s.length()), val, slot);
-                // ### error case?
-            }
+            JSStringRef propertyName = JSStringCreateWithCharacters(reinterpret_cast<const JSChar*>(s.constData()), s.length());
+            JSValueRef propertyValue = convertQVariantToValue(context, root.get(), i.value(), /*ignored exception*/0);
+            if (propertyValue)
+                JSObjectSetProperty(context, ret, propertyName, propertyValue, kJSPropertyAttributeNone, /*ignored exception*/0);
+            JSStringRelease(propertyName);
             ++i;
         }
 
@@ -885,31 +886,58 @@
 
     // List types
     if (type == QMetaType::QVariantList) {
+        // ### TODO: Could use special array class that lazily converts.
+        // See https://bugs.webkit.org/show_bug.cgi?id=94691
         QVariantList vl = variant.toList();
-        qConvDebug() << "got a " << vl.count() << " length list:" << vl;
-        return RuntimeArray::create(exec, new QtArray<QVariant>(vl, QMetaType::Void, root));
+        JSObjectRef array = JSObjectMakeArray(context, 0, 0, exception);
+        if (exception && *exception)
+            return array;
+        for (int i = 0; i < vl.count(); ++i) {
+            JSValueRef property = convertQVariantToValue(context, root.get(), vl.at(i), /*ignored exception*/0);
+            if (property)
+                JSObjectSetPropertyAtIndex(context, array, i, property, /*ignored exception*/0);
+        }
+        return array;
     } else if (type == QMetaType::QStringList) {
         QStringList sl = variant.value<QStringList>();
-        return RuntimeArray::create(exec, new QtArray<QString>(sl, QMetaType::QString, root));
-    } else if (type == (QMetaType::Type) qMetaTypeId<QObjectList>()) {
-        QObjectList ol= variant.value<QObjectList>();
-        return RuntimeArray::create(exec, new QtArray<QObject*>(ol, QMetaType::QObjectStar, root));
-    } else if (type == (QMetaType::Type)qMetaTypeId<QList<int> >()) {
-        QList<int> il= variant.value<QList<int> >();
-        return RuntimeArray::create(exec, new QtArray<int>(il, QMetaType::Int, root));
+        JSObjectRef array = JSObjectMakeArray(context, 0, 0, exception);
+        for (int i = 0; i < sl.count(); ++i) {
+            const QString& s = sl.at(i);
+            JSStringRef jsString = JSStringCreateWithCharacters(reinterpret_cast<const JSChar*>(s.constData()), s.length());
+            JSObjectSetPropertyAtIndex(context, array, i, JSValueMakeString(context, jsString), /*ignored exception*/0);
+            JSStringRelease(jsString);
+        }
+        return array;
+    } else if (type == static_cast<QMetaType::Type>(qMetaTypeId<QObjectList>())) {
+        QObjectList ol = variant.value<QObjectList>();
+        JSObjectRef array = JSObjectMakeArray(context, 0, 0, exception);
+        ExecState* exec = toJS(context);
+        for (int i = 0; i < ol.count(); ++i) {
+            JSValueRef jsObject = toRef(exec, QtInstance::getQtInstance(ol.at(i), root, QtInstance::QtOwnership)->createRuntimeObject(exec));
+            JSObjectSetPropertyAtIndex(context, array, i, jsObject, /*ignored exception*/0);
+        }
+        return array;
+    } else if (type == static_cast<QMetaType::Type>(qMetaTypeId<QList<int> >())) {
+        QList<int> il = variant.value<QList<int> >();
+        JSObjectRef array = JSObjectMakeArray(context, 0, 0, exception);
+        for (int i = 0; i < il.count(); ++i)
+            JSObjectSetPropertyAtIndex(context, array, i, JSValueMakeNumber(context, il.at(i)), /*ignored exception*/0);
+        return array;
     }
 
     if (type == (QMetaType::Type)qMetaTypeId<QVariant>()) {
         QVariant real = variant.value<QVariant>();
         qConvDebug() << "real variant is:" << real;
-        return convertQVariantToValue(exec, root, real);
+        return convertQVariantToValue(context, root.get(), real, exception);
     }
 
     qConvDebug() << "fallback path for" << variant << variant.userType();
 
     QString string = variant.toString();
-    UString ustring((UChar*)string.utf16(), string.length());
-    return jsString(exec, ustring);
+    JSStringRef jsstring = JSStringCreateWithCharacters(reinterpret_cast<const JSChar*>(string.constData()), string.length());
+    JSValueRef value = JSValueMakeString(context, jsstring);
+    JSStringRelease(jsstring);
+    return value;
 }
 
 // Type conversion metadata (from QtScript originally)
@@ -1330,7 +1358,7 @@
         return JSValueMakeUndefined(context);
 
     if (vargs.size() > 0 && vargs[0].isValid())
-        return toRef(toJS(context), convertQVariantToValue(toJS(context), d->m_instance->rootObject(), vargs[0]));
+        return convertQVariantToValue(context, d->m_instance->rootObject(), vargs[0], exception);
 
     return JSValueMakeUndefined(context);
 }
@@ -1648,7 +1676,7 @@
 
     for (int i = 0; i < argc; i++) {
         int argType = method.parameterType(i);
-        args[i] = ::toRef(exec, convertQVariantToValue(exec, m_rootObject, QVariant(argType, argv[i+1])));
+        args[i] = convertQVariantToValue(toRef(exec), m_rootObject, QVariant(argType, argv[i+1]), ignoredException);
     }
 
     JSObjectCallAsFunction(m_context, m_receiverFunction, m_receiver, argc, args.data(), 0);
@@ -1700,7 +1728,7 @@
 {
     if (index < m_length) {
         T val = m_list.at(index);
-        return convertQVariantToValue(exec, rootObject(), QVariant::fromValue(val));
+        return convertQVariantToValue(toRef(exec), rootObject(), QVariant::fromValue(val));
     }
 
     return jsUndefined();

Modified: trunk/Source/WebCore/bridge/qt/qt_runtime.h (126289 => 126290)


--- trunk/Source/WebCore/bridge/qt/qt_runtime.h	2012-08-22 11:21:39 UTC (rev 126289)
+++ trunk/Source/WebCore/bridge/qt/qt_runtime.h	2012-08-22 12:26:18 UTC (rev 126290)
@@ -157,7 +157,7 @@
 void registerCustomType(int qtMetaTypeId, ConvertToVariantFunction, ConvertToJSValueFunction);
 
 QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type hint, int *distance);
-JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant);
+JSValueRef convertQVariantToValue(JSContextRef, PassRefPtr<RootObject>, const QVariant&, JSValueRef* exception);
 
 void setException(JSContextRef, JSValueRef* exception, const QString& text);
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to