Begin implement C++ style wrappers in QQmlLocale
authorSimon Hausmann <simon.hausmann@digia.com>
Wed, 8 May 2013 14:48:09 +0000 (16:48 +0200)
committerLars Knoll <lars.knoll@digia.com>
Thu, 9 May 2013 06:29:06 +0000 (08:29 +0200)
The locale.currencySymbol function is converted into a member function
of the wrapper. For the time of the transition the prototype chain is
modified to be obj -> v8 proto template -> v4classgen generated proto

Change-Id: I72913e9d284a2a3678b23c7d7ce27fbb3447f1fb
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/qml/qml.pri
src/qml/qml/qqmllocale.cpp
src/qml/qml/v4/v4.pri
src/qml/qml/v4/v4classgen

index 29cd437..24e7f5b 100644 (file)
@@ -126,6 +126,8 @@ HEADERS += \
     $$PWD/qqmlapplicationengine_p.h \
     $$PWD/qqmlapplicationengine.h
 
+JS_CLASS_SOURCES += \
+    $$PWD/qqmllocale.cpp
 
 include(parser/parser.pri)
 include(rewriter/rewriter.pri)
index 8963a4d..0bd1508 100644 (file)
@@ -54,8 +54,9 @@
 
 QT_BEGIN_NAMESPACE
 
-class QQmlLocaleData : public QV4::Object
+class QV4_JS_CLASS(QQmlLocaleData) : public QV4::Object
 {
+    QV4_ANNOTATE(managedTypeName QmlLocale staticInitClass true)
 public:
     QQmlLocaleData(QV4::ExecutionEngine *engine)
         : QV4::Object(engine)
@@ -68,6 +69,10 @@ public:
     QLocale locale;
     QV8Engine *engine; // ### compat, remove once unused
 
+    static void initClass(QV4::ExecutionEngine *engine, const QV4::Value &obj);
+
+    QV4::Value method_currencySymbol(QV4::SimpleCallContext *ctx);
+
 private:
     static void destroy(Managed *that)
     {
@@ -522,10 +527,8 @@ static v8::Handle<v8::Value> locale_get_uiLanguages(v8::Handle<v8::String>, cons
     return result;
 }
 
-static QV4::Value locale_currencySymbol(QV4::SimpleCallContext *ctx)
+QV4::Value QQmlLocaleData::method_currencySymbol(QV4::SimpleCallContext *ctx)
 {
-    GET_LOCALE_DATA_RESOURCE(ctx->thisObject);
-
     if (ctx->argumentCount > 1)
         V4THROW_ERROR("Locale: currencySymbol(): Invalid arguments");
 
@@ -535,7 +538,7 @@ static QV4::Value locale_currencySymbol(QV4::SimpleCallContext *ctx)
         format = QLocale::CurrencySymbolFormat(intFormat);
     }
 
-    return QV4::Value::fromString(ctx, r->locale.currencySymbol(format));
+    return QV4::Value::fromString(ctx, locale.currencySymbol(format));
 }
 
 #define LOCALE_FORMAT(FUNC) \
@@ -645,6 +648,7 @@ public:
     ~QV8LocaleDataDeletable();
 
     QV4::PersistentValue prototype;
+    QV4::PersistentValue v4Prototype;
 };
 
 QV8LocaleDataDeletable::QV8LocaleDataDeletable(QV8Engine *engine)
@@ -665,8 +669,6 @@ QV8LocaleDataDeletable::QV8LocaleDataDeletable(QV8Engine *engine)
     LOCALE_REGISTER_STRING_ACCESSOR(ft, amText);
     LOCALE_REGISTER_STRING_ACCESSOR(ft, pmText);
 
-    ft->PrototypeTemplate()->Set(v8::String::New("currencySymbol"), V8FUNCTION(locale_currencySymbol, engine));
-
     ft->PrototypeTemplate()->Set(v8::String::New("dateTimeFormat"), V8FUNCTION(locale_dateTimeFormat, engine));
     ft->PrototypeTemplate()->Set(v8::String::New("dateFormat"), V8FUNCTION(locale_dateFormat, engine));
     ft->PrototypeTemplate()->Set(v8::String::New("timeFormat"), V8FUNCTION(locale_timeFormat, engine));
@@ -683,6 +685,11 @@ QV8LocaleDataDeletable::QV8LocaleDataDeletable(QV8Engine *engine)
     ft->PrototypeTemplate()->SetAccessor(v8::String::New("uiLanguages"), locale_get_uiLanguages);
 
     prototype = QV4::Value::fromObject(ft->GetFunction()->NewInstance()->v4Value().asObject()->prototype);
+
+    QV4::ExecutionEngine *eng = QV8Engine::getV4(engine);
+    v4Prototype = QV4::Value::fromObject(eng->newObject());
+    QQmlLocaleData::initClass(eng, v4Prototype.value());
+    prototype.value().asObject()->prototype->prototype = v4Prototype.value().asObject();
 }
 
 QV8LocaleDataDeletable::~QV8LocaleDataDeletable()
@@ -1058,4 +1065,6 @@ QV4::Value QQmlLocale::localeCompare(QV4::SimpleCallContext *ctx)
     \endlist
 */
 
+#include "qqmllocale_jsclass.cpp"
+
 QT_END_NAMESPACE
index 06389fd..74b3e37 100644 (file)
@@ -96,10 +96,10 @@ HEADERS += \
     $$PWD/qv4util_p.h \
     $$PWD/qv4executableallocator_p.h
 
-JS_CLASS_SOURCES = $$PWD/qv4dateobject_p.h \
-                   $$PWD/qv4stringobject_p.h \
-                   $$PWD/qv4booleanobject_p.h \
-                   $$PWD/qv4regexpobject_p.h
+JS_CLASS_SOURCES += $$PWD/qv4dateobject_p.h \
+                    $$PWD/qv4stringobject_p.h \
+                    $$PWD/qv4booleanobject_p.h \
+                    $$PWD/qv4regexpobject_p.h
 
 js_class_bindings.output = ${QMAKE_FILE_BASE}_jsclass.cpp
 js_class_bindings.input = JS_CLASS_SOURCES
index f182045..019435b 100755 (executable)
@@ -4,18 +4,37 @@ import re, sys, os
 import argparse
 
 class ParsedMethod():
-    def __init__(self, name, methodPrefix):
+    def __init__(self, name, methodPrefix, static):
         self.name = name
         self.methodPrefix = methodPrefix
         self.options = {}
+        self.static = static
+
+    def isClassMethod(self):
+        return self.static
 
     def generateBinding(self, out, objectPrefix = ""):
         length = 0
+
+        methodName = self.methodPrefix + "_" + self.name
+        if not self.isClassMethod():
+            methodName = "wrap_" + methodName
+
         if "argc" in self.options:
             length = self.options["argc"]
-        out.write("    %sdefineDefaultProperty(engine, QStringLiteral(\"%s\"), %s_%s, %s);\n" % (objectPrefix, self.name, self.methodPrefix, self.name, length))
+        out.write("    %sdefineDefaultProperty(engine, QStringLiteral(\"%s\"), %s, %s);\n" % (objectPrefix, self.name, methodName, length))
         if "alias" in self.options:
-            out.write("    %sdefineDefaultProperty(engine, QStringLiteral(\"%s\"), %s_%s, %s);\n" % (objectPrefix, self.options["alias"], self.methodPrefix, self.name, length))
+            out.write("    %sdefineDefaultProperty(engine, QStringLiteral(\"%s\"), %s, %s);\n" % (objectPrefix, self.options["alias"], methodName, length))
+
+    def generateMemberFunctionWrapper(self, out, parsedClass):
+        out.write("static QV4::Value wrap_%s_%s(QV4::SimpleCallContext *ctx)\n" % (self.methodPrefix, self.name))
+        out.write("{\n")
+        out.write("    QV4::Object *thatObject = ctx->thisObject.asObject();\n")
+        out.write("    if (!thatObject)\n")
+        out.write("        ctx->throwTypeError();\n")
+        out.write("    return thatObject->as%s()->%s_%s(ctx);\n" % (parsedClass.managedTypeName(), self.methodPrefix, self.name))
+        out.write("}\n")
+        out.write("\n")
 
 class ParsedClass():
     def __init__(self, name):
@@ -27,6 +46,16 @@ class ParsedClass():
     def needsConstructor(self):
         return len(self.ctor_methods) > 0
 
+    def managedTypeName(self):
+        if "managedTypeName" in self.options:
+            return self.options["managedTypeName"]
+        return self.name
+
+    def option(self, name):
+        if name in self.options:
+            return self.options[name]
+        return None
+
 def parseOptions(options):
     options = options.split(" ")
     result = {}
@@ -38,7 +67,7 @@ def parseMethod(line, match, methodPrefix):
     annotatePattern = re.compile(r".*QV4_ANNOTATE\((?P<Options>.+)\).*")
     argcPattern = re.compile(r".*QV4_ARGC\((?P<count>\d+)\).*")
 
-    method = ParsedMethod(match.group("MethodName"), methodPrefix)
+    method = ParsedMethod(match.group("MethodName"), methodPrefix, line.find("static") == 0)
 
     annotateMatch = annotatePattern.match(line)
     if annotateMatch:
@@ -124,11 +153,25 @@ def generateBinding(out, parsedClass, vtableEntries):
         out.write("    return new (scope->engine->memoryManager) %s(scope);\n" % ctorClass)
         out.write("}\n\n")
 
+    for method in parsedClass.methods:
+        if not method.isClassMethod():
+            method.generateMemberFunctionWrapper(out, parsedClass)
+
+    for method in parsedClass.ctor_methods:
+        if not method.isClassMethod():
+            method.generateMemberFunctionWrapper(out, parsedClass)
+
     ctorSignature = ""
     if parsedClass.needsConstructor():
-        ctorSignature = ", const Value &ctor"
+        ctorSignature = ", const QV4::Value &ctor"
+
+    obj = ""
+    objSignature = ""
+    if parsedClass.option("staticInitClass") == "true":
+        objSignature = ", const QV4::Value &obj"
+        obj = "obj.objectValue()->"
 
-    out.write("void %s::initClass(QV4::ExecutionEngine *engine%s)\n" % (parsedClass.name, ctorSignature))
+    out.write("void %s::initClass(QV4::ExecutionEngine *engine%s%s)\n" % (parsedClass.name, objSignature, ctorSignature))
     out.write("{\n")
 
     if parsedClass.needsConstructor():
@@ -152,7 +195,7 @@ def generateBinding(out, parsedClass, vtableEntries):
         out.write("\n")
 
     for method in parsedClass.methods:
-        method.generateBinding(out)
+        method.generateBinding(out, obj)
 
     out.write("}\n")
 
@@ -200,7 +243,7 @@ parser.add_argument("input")
 parser.add_argument("--output")
 options = parser.parse_args()
 
-vtableEntries = extractManagedVTableLayout(os.path.dirname(os.path.abspath(options.input)))
+vtableEntries = extractManagedVTableLayout(os.path.dirname(__file__))
 if len(vtableEntries) ==  0:
     print("Could not parse vtable layout from qv4managed_p.h")
     sys.exit(1)
@@ -216,7 +259,6 @@ classes = parse(lines)
 f.close()
 
 out.write("/* Generated file, do not edit */\n")
-out.write("#include \"%s\"\n" % options.input)
 
 for parsedClass in classes:
     out.write("\n")