Title: [125032] trunk/Source
Revision
125032
Author
[email protected]
Date
2012-08-08 06:19:22 -0700 (Wed, 08 Aug 2012)

Log Message

[Qt] Port internal findMethodIndex method matcher to use JSC C API
https://bugs.webkit.org/show_bug.cgi?id=93463

Patch by Simon Hausmann <[email protected]> on 2012-08-08
Reviewed by Kenneth Rohde Christiansen.

Source/WebCore:

Based on patch by No'am Rosenthal.

* bridge/qt/qt_runtime.cpp:
(JSC::Bindings::setException):
(Bindings):
(JSC::Bindings::findMethodIndex): Fixed also coding style while at it.
(JSC::Bindings::QtRuntimeMetaMethod::call): Use new findMethodIndex. The
created JSValueRefs should not need GC protection because we only support
up to 10 method arguments and thus they will live on the stack storage
of the vector.
* bridge/qt/qt_runtime.h:
(Bindings):

Source/WebKit/qt:

Adjust the expectations of the unit test for some of the exceptions the
method throws when signals/slots cannot be found/matched. The C API doesn't allow
us to create syntax (type) errors, only generic error exceptions.

* tests/qobjectbridge/tst_qobjectbridge.cpp:
(tst_QObjectBridge::callQtInvokable):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (125031 => 125032)


--- trunk/Source/WebCore/ChangeLog	2012-08-08 13:18:18 UTC (rev 125031)
+++ trunk/Source/WebCore/ChangeLog	2012-08-08 13:19:22 UTC (rev 125032)
@@ -1,3 +1,23 @@
+2012-08-08  Simon Hausmann  <[email protected]>
+
+        [Qt] Port internal findMethodIndex method matcher to use JSC C API
+        https://bugs.webkit.org/show_bug.cgi?id=93463
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        Based on patch by No'am Rosenthal.
+
+        * bridge/qt/qt_runtime.cpp:
+        (JSC::Bindings::setException):
+        (Bindings):
+        (JSC::Bindings::findMethodIndex): Fixed also coding style while at it.
+        (JSC::Bindings::QtRuntimeMetaMethod::call): Use new findMethodIndex. The
+        created JSValueRefs should not need GC protection because we only support
+        up to 10 method arguments and thus they will live on the stack storage
+        of the vector.
+        * bridge/qt/qt_runtime.h:
+        (Bindings):
+
 2012-08-08  Alexander Pavlov  <[email protected]>
 
         Web Inspector: move setTouchEventEmulationEnabled from DOMAgent to PageAgent

Modified: trunk/Source/WebCore/bridge/qt/qt_runtime.cpp (125031 => 125032)


--- trunk/Source/WebCore/bridge/qt/qt_runtime.cpp	2012-08-08 13:18:18 UTC (rev 125031)
+++ trunk/Source/WebCore/bridge/qt/qt_runtime.cpp	2012-08-08 13:19:22 UTC (rev 125032)
@@ -122,6 +122,17 @@
 }
 #endif
 
+void setException(JSContextRef context, JSValueRef* exception, const QString& text)
+{
+    if (!exception)
+        return;
+
+    JSStringRef errorStr = JSStringCreateWithUTF8CString(text.toUtf8());
+    JSValueRef errorVal[] = { JSValueMakeString(context, errorStr) };
+    *exception = JSObjectMakeError(context, 1, errorVal, 0);
+    JSStringRelease(errorStr);
+}
+
 struct RuntimeConversion {
     ConvertToJSValueFunction toJSValueFunc;
     ConvertToVariantFunction toVariantFunc;
@@ -1141,13 +1152,15 @@
 
 // Helper function for resolving methods
 // Largely based on code in QtScript for compatibility reasons
-static int findMethodIndex(ExecState* exec,
+static int findMethodIndex(JSContextRef context,
                            const QMetaObject* meta,
                            const QByteArray& signature,
+                           int argumentCount,
+                           const JSValueRef arguments[],
                            bool allowPrivate,
                            QVarLengthArray<QVariant, 10> &vars,
                            void** vvars,
-                           JSObject **pError)
+                           JSValueRef* exception)
 {
     QList<int> matchingIndices;
 
@@ -1169,7 +1182,6 @@
     }
 
     int chosenIndex = -1;
-    *pError = 0;
     QVector<QtMethodMatchType> chosenTypes;
 
     QVarLengthArray<QVariant, 10> args;
@@ -1228,7 +1240,7 @@
         }
 
         // If the native method requires more arguments than what was passed from _javascript_
-        if (exec->argumentCount() + 1 < static_cast<unsigned>(types.count())) {
+        if (argumentCount + 1 < static_cast<unsigned>(types.count())) {
             qMatchDebug() << "Match:too few args for" << method.methodSignature();
             tooFewArgs.append(index);
             continue;
@@ -1253,10 +1265,10 @@
         bool converted = true;
         int matchDistance = 0;
         for (unsigned i = 0; converted && i + 1 < static_cast<unsigned>(types.count()); ++i) {
-            JSValue arg = i < exec->argumentCount() ? exec->argument(i) : jsUndefined();
+            JSValueRef arg = i < argumentCount ? arguments[i] : JSValueMakeUndefined(context);
 
             int argdistance = -1;
-            QVariant v = convertValueToQVariant(exec, arg, types.at(i+1).typeId(), &argdistance);
+            QVariant v = convertValueToQVariant(toJS(context), toJS(toJS(context), arg), types.at(i+1).typeId(), &argdistance);
             if (argdistance >= 0) {
                 matchDistance += argdistance;
                 args[i+1] = v;
@@ -1269,25 +1281,23 @@
         qMatchDebug() << "Match: " << method.methodSignature() << (converted ? "converted":"failed to convert") << "distance " << matchDistance;
 
         if (converted) {
-            if ((exec->argumentCount() + 1 == static_cast<unsigned>(types.count()))
+            if ((argumentCount + 1 == static_cast<unsigned>(types.count()))
                 && (matchDistance == 0)) {
                 // perfect match, use this one
                 chosenIndex = index;
                 break;
-            } else {
-                QtMethodMatchData currentMatch(matchDistance, index, types, args);
-                if (candidates.isEmpty()) {
+            }
+            QtMethodMatchData currentMatch(matchDistance, index, types, args);
+            if (candidates.isEmpty())
+                candidates.append(currentMatch);
+            else {
+                QtMethodMatchData bestMatchSoFar = candidates.at(0);
+                if ((args.count() > bestMatchSoFar.args.count())
+                    || ((args.count() == bestMatchSoFar.args.count())
+                    && (matchDistance <= bestMatchSoFar.matchDistance)))
+                    candidates.prepend(currentMatch);
+                else
                     candidates.append(currentMatch);
-                } else {
-                    QtMethodMatchData bestMatchSoFar = candidates.at(0);
-                    if ((args.count() > bestMatchSoFar.args.count())
-                        || ((args.count() == bestMatchSoFar.args.count())
-                            && (matchDistance <= bestMatchSoFar.matchDistance))) {
-                        candidates.prepend(currentMatch);
-                    } else {
-                        candidates.append(currentMatch);
-                    }
-                }
             }
         } else {
             conversionFailed.append(index);
@@ -1308,7 +1318,7 @@
                 QMetaMethod mtd = meta->method(conversionFailed.at(i));
                 message += QString::fromLatin1("    %0").arg(QString::fromLatin1(mtd.methodSignature()));
             }
-            *pError = throwError(exec, createTypeError(exec, message.toLatin1().constData()));
+            setException(context, exception, message);
         } else if (!unresolved.isEmpty()) {
             QtMethodMatchData argsInstance = unresolved.first();
             int unresolvedIndex = argsInstance.firstUnresolvedIndex();
@@ -1317,7 +1327,7 @@
             QString message = QString::fromLatin1("cannot call %0(): unknown type `%1'")
                 .arg(QString::fromLatin1(signature))
                 .arg(QLatin1String(unresolvedType.name()));
-            *pError = throwError(exec, createTypeError(exec, message.toLatin1().constData()));
+            setException(context, exception, message);
         } else {
             QString message = QString::fromLatin1("too few arguments in call to %0(); candidates are\n")
                               .arg(QString::fromLatin1(signature));
@@ -1327,7 +1337,7 @@
                 QMetaMethod mtd = meta->method(tooFewArgs.at(i));
                 message += QString::fromLatin1("    %0").arg(QString::fromLatin1(mtd.methodSignature()));
             }
-            *pError = throwError(exec, createSyntaxError(exec, message.toLatin1().constData()));
+            setException(context, exception, message);
         }
     }
 
@@ -1349,7 +1359,7 @@
                     message += QString::fromLatin1("    %0").arg(QString::fromLatin1(mtd.methodSignature()));
                 }
             }
-            *pError = throwError(exec, createTypeError(exec, message.toLatin1().constData()));
+            setException(context, exception, message);
         } else {
             chosenIndex = bestMatch.index;
             args = bestMatch.args;
@@ -1424,12 +1434,17 @@
 
     QObject *obj = d->m_instance->getObject();
     if (obj) {
+        const int argumentCount = static_cast<int>(exec->argumentCount());
+        Vector<JSValueRef, 10> args(argumentCount);
+        for (int i = 0; i < argumentCount; ++i)
+            args[i] = toRef(exec, exec->argument(i));
+
         QVarLengthArray<QVariant, 10> vargs;
         void *qargs[11];
 
         int methodIndex;
-        JSObject* errorObj = 0;
-        if ((methodIndex = findMethodIndex(exec, obj->metaObject(), d->m_signature, d->m_allowPrivate, vargs, (void **)qargs, &errorObj)) != -1) {
+        JSValueRef exception = 0;
+        if ((methodIndex = findMethodIndex(toRef(exec), obj->metaObject(), d->m_signature, argumentCount, args.data(), d->m_allowPrivate, vargs, (void **)qargs, &exception)) != -1) {
             if (QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, methodIndex, qargs) >= 0)
                 return JSValue::encode(jsUndefined());
 
@@ -1437,8 +1452,8 @@
                 return JSValue::encode(convertQVariantToValue(exec, d->m_instance->rootObject(), vargs[0]));
         }
 
-        if (errorObj)
-            return JSValue::encode(errorObj);
+        if (exception)
+            return throwVMError(exec, toJS(exec, exception));
     } else {
         return throwVMError(exec, createError(exec, "cannot call function of deleted QObject"));
     }

Modified: trunk/Source/WebCore/bridge/qt/qt_runtime.h (125031 => 125032)


--- trunk/Source/WebCore/bridge/qt/qt_runtime.h	2012-08-08 13:18:18 UTC (rev 125031)
+++ trunk/Source/WebCore/bridge/qt/qt_runtime.h	2012-08-08 13:19:22 UTC (rev 125032)
@@ -271,6 +271,8 @@
 QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type hint, int *distance);
 JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant);
 
+void setException(JSContextRef, JSValueRef* exception, const QString& text);
+
 } // namespace Bindings
 } // namespace JSC
 

Modified: trunk/Source/WebKit/qt/ChangeLog (125031 => 125032)


--- trunk/Source/WebKit/qt/ChangeLog	2012-08-08 13:18:18 UTC (rev 125031)
+++ trunk/Source/WebKit/qt/ChangeLog	2012-08-08 13:19:22 UTC (rev 125032)
@@ -1,5 +1,19 @@
 2012-08-08  Simon Hausmann  <[email protected]>
 
+        [Qt] Port internal findMethodIndex method matcher to use JSC C API
+        https://bugs.webkit.org/show_bug.cgi?id=93463
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        Adjust the expectations of the unit test for some of the exceptions the
+        method throws when signals/slots cannot be found/matched. The C API doesn't allow
+        us to create syntax (type) errors, only generic error exceptions.
+
+        * tests/qobjectbridge/tst_qobjectbridge.cpp:
+        (tst_QObjectBridge::callQtInvokable):
+
+2012-08-08  Simon Hausmann  <[email protected]>
+
         [Qt] Add unit test for QObject bindings for scriptable plugins
         https://bugs.webkit.org/show_bug.cgi?id=93462
 

Modified: trunk/Source/WebKit/qt/tests/qobjectbridge/tst_qobjectbridge.cpp (125031 => 125032)


--- trunk/Source/WebKit/qt/tests/qobjectbridge/tst_qobjectbridge.cpp	2012-08-08 13:18:18 UTC (rev 125031)
+++ trunk/Source/WebKit/qt/tests/qobjectbridge/tst_qobjectbridge.cpp	2012-08-08 13:19:22 UTC (rev 125032)
@@ -1142,7 +1142,7 @@
         QString type;
         QString ret = evalJS("myObject.myInvokableWithVoidStarArg(123)", type);
         QCOMPARE(type, sError);
-        QCOMPARE(ret, QLatin1String("TypeError: incompatible type of argument(s) in call to myInvokableWithVoidStarArg(); candidates were\n    myInvokableWithVoidStarArg(void*)"));
+        QCOMPARE(ret, QLatin1String("Error: incompatible type of argument(s) in call to myInvokableWithVoidStarArg(); candidates were\n    myInvokableWithVoidStarArg(void*)"));
         QCOMPARE(m_myObject->qtFunctionInvoked(), -1);
     }
 
@@ -1151,7 +1151,7 @@
         QString type;
         QString ret = evalJS("myObject.myInvokableWithAmbiguousArg(123)", type);
         QCOMPARE(type, sError);
-        QCOMPARE(ret, QLatin1String("TypeError: ambiguous call of overloaded function myInvokableWithAmbiguousArg(); candidates were\n    myInvokableWithAmbiguousArg(int)\n    myInvokableWithAmbiguousArg(uint)"));
+        QCOMPARE(ret, QLatin1String("Error: ambiguous call of overloaded function myInvokableWithAmbiguousArg(); candidates were\n    myInvokableWithAmbiguousArg(int)\n    myInvokableWithAmbiguousArg(uint)"));
     }
 
     m_myObject->resetQtFunctionInvoked();
@@ -1380,7 +1380,7 @@
         QString type;
         QString ret = evalJS("myObject.myInvokableWithIntArg()", type);
         QCOMPARE(type, sError);
-        QCOMPARE(ret, QLatin1String("SyntaxError: too few arguments in call to myInvokableWithIntArg(); candidates are\n    myInvokableWithIntArg(int,int)\n    myInvokableWithIntArg(int)"));
+        QCOMPARE(ret, QLatin1String("Error: too few arguments in call to myInvokableWithIntArg(); candidates are\n    myInvokableWithIntArg(int,int)\n    myInvokableWithIntArg(int)"));
     }
 
     // call function where not all types have been registered
@@ -1389,7 +1389,7 @@
         QString type;
         QString ret = evalJS("myObject.myInvokableWithBrushStyleArg(0)", type);
         QCOMPARE(type, sError);
-        QCOMPARE(ret, QLatin1String("TypeError: cannot call myInvokableWithBrushStyleArg(): unknown type `Qt::BrushStyle'"));
+        QCOMPARE(ret, QLatin1String("Error: cannot call myInvokableWithBrushStyleArg(): unknown type `Qt::BrushStyle'"));
         QCOMPARE(m_myObject->qtFunctionInvoked(), -1);
     }
 
@@ -1399,7 +1399,7 @@
         QString type;
         QString ret = evalJS("myObject.myInvokableWithQBrushArg(null)", type);
         QCOMPARE(type, sError);
-        QCOMPARE(ret, QLatin1String("TypeError: incompatible type of argument(s) in call to myInvokableWithQBrushArg(); candidates were\n    myInvokableWithQBrushArg(QBrush)"));
+        QCOMPARE(ret, QLatin1String("Error: incompatible type of argument(s) in call to myInvokableWithQBrushArg(); candidates were\n    myInvokableWithQBrushArg(QBrush)"));
         QCOMPARE(m_myObject->qtFunctionInvoked(), -1);
     }
 }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to