Convert some code in qqmlcomponent over to use v4
authorLars Knoll <lars.knoll@digia.com>
Sat, 27 Apr 2013 14:01:41 +0000 (07:01 -0700)
committerSimon Hausmann <simon.hausmann@digia.com>
Mon, 29 Apr 2013 11:08:52 +0000 (13:08 +0200)
Add an evaluateScript() method to qv8engine, that replaces the
v8::Script class

Change-Id: I00e0e18d4e3dbcba26632ca3492749a6b0f1a7f0
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/qml/qqmlcomponent.cpp
src/qml/qml/v8/qv8engine.cpp
src/qml/qml/v8/qv8engine_p.h

index 5c123a6..70e4ec2 100644 (file)
@@ -61,6 +61,8 @@
 #include <private/qv8engine_p.h>
 #include <private/qv8include_p.h>
 
+#include <private/qv4functionobject_p.h>
+
 #include <QStack>
 #include <QStringList>
 #include <QThreadStorage>
 #include <qqmlinfo.h>
 #include "qqmlmemoryprofiler_p.h"
 
+#define INITIALPROPERTIES_SOURCE \
+        "(function(object, values) {"\
+            "try {"\
+                "for (var property in values) {" \
+                    "try {"\
+                        "var properties = property.split(\".\");"\
+                        "var o = object;"\
+                        "for (var ii = 0; ii < properties.length - 1; ++ii) {"\
+                            "o = o[properties[ii]];"\
+                        "}"\
+                        "o[properties[properties.length - 1]] = values[property];"\
+                    "} catch(e) {}"\
+                "}"\
+            "} catch(e) {}"\
+        "})"
+
+
 namespace {
     QThreadStorage<int> creationDepth;
 }
@@ -81,7 +100,6 @@ public:
     virtual ~QQmlComponentExtension();
 
     v8::Persistent<v8::Function> incubationConstructor;
-    v8::Persistent<v8::Script> initialProperties;
     v8::Persistent<v8::Function> forceCompletion;
 };
 V8_DEFINE_EXTENSION(QQmlComponentExtension, componentExtension);
@@ -1182,6 +1200,7 @@ void QQmlComponent::createObject(QQmlV8Function *args)
     }
 
     QV8Engine *v8engine = args->engine();
+    QV4::ExecutionEngine *v4engine = QV8Engine::getV4(v8engine);
 
     QQmlContext *ctxt = creationContext();
     if (!ctxt) ctxt = d->engine->rootContext();
@@ -1201,10 +1220,9 @@ void QQmlComponent::createObject(QQmlV8Function *args)
 
     if (!valuemap.IsEmpty()) {
         QQmlComponentExtension *e = componentExtension(v8engine);
-        // Try catch isn't needed as the function itself is loaded with try/catch
-        v8::Handle<v8::Value> function = e->initialProperties->Run(args->qmlGlobal());
-        v8::Handle<v8::Value> args[] = { object, valuemap };
-        v8::Handle<v8::Function>::Cast(function)->Call(v8engine->global(), 2, args);
+        QV4::Value f = v8engine->evaluateScript(QString::fromLatin1(INITIALPROPERTIES_SOURCE), args->qmlGlobal()->v4Value().asObject());
+        QV4::Value args[] = { object->v4Value(), valuemap->v4Value() };
+        f.asFunctionObject()->call(v4engine->current, QV4::Value::fromObject(v4engine->globalObject), args, 2);
     }
 
     d->completeCreate();
@@ -1340,6 +1358,7 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(v8::Handle<v8::
 {
     QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
     QV8Engine *v8engine = ep->v8engine();
+    QV4::ExecutionEngine *v4engine = QV8Engine::getV4(v8engine);
 
     v8::HandleScope handle_scope;
     v8::Context::Scope scope(v8engine->context());
@@ -1349,10 +1368,9 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(v8::Handle<v8::
 
     if (!valuemap.IsEmpty()) {
         QQmlComponentExtension *e = componentExtension(v8engine);
-        // Try catch isn't needed as the function itself is loaded with try/catch
-        v8::Handle<v8::Value> function = e->initialProperties->Run(qmlGlobal);
-        v8::Handle<v8::Value> args[] = { object, valuemap };
-        v8::Handle<v8::Function>::Cast(function)->Call(v8engine->global(), 2, args);
+        QV4::Value f = v8engine->evaluateScript(QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobal->v4Value().asObject());
+        QV4::Value args[] = { object->v4Value(), valuemap->v4Value() };
+        f.asFunctionObject()->call(v4engine->current, QV4::Value::fromObject(v4engine->globalObject), args, 2);
     }
 }
 
@@ -1379,26 +1397,6 @@ QQmlComponentExtension::QQmlComponentExtension(QV8Engine *engine)
                                         QV8IncubatorResource::ForceCompletionGetter); 
     incubationConstructor = qPersistentNew(ft->GetFunction());
     }
-
-    {
-#define INITIALPROPERTIES_SOURCE \
-        "(function(object, values) {"\
-            "try {"\
-                "for(var property in values) {" \
-                    "try {"\
-                        "var properties = property.split(\".\");"\
-                        "var o = object;"\
-                        "for (var ii = 0; ii < properties.length - 1; ++ii) {"\
-                            "o = o[properties[ii]];"\
-                        "}"\
-                        "o[properties[properties.length - 1]] = values[property];"\
-                    "} catch(e) {}"\
-                "}"\
-            "} catch(e) {}"\
-        "})"
-    initialProperties = qPersistentNew(engine->qmlModeCompile(QLatin1String(INITIALPROPERTIES_SOURCE)));
-#undef INITIALPROPERTIES_SOURCE
-    }
 }
 
 v8::Handle<v8::Value> QV8IncubatorResource::ObjectGetter(v8::Local<v8::String>, 
@@ -1448,7 +1446,6 @@ void QV8IncubatorResource::StatusChangedSetter(v8::Local<v8::String>, v8::Local<
 QQmlComponentExtension::~QQmlComponentExtension()
 {
     qPersistentDispose(incubationConstructor);
-    qPersistentDispose(initialProperties);
     qPersistentDispose(forceCompletion);
 }
 
@@ -1464,15 +1461,11 @@ void QV8IncubatorResource::setInitialState(QObject *o)
     if (!valuemap.IsEmpty()) {
         QQmlComponentExtension *e = componentExtension(engine);
 
-        v8::HandleScope handle_scope;
-        v8::Context::Scope scope(engine->context());
-
-        v8::Handle<v8::Value> function = e->initialProperties->Run(qmlGlobal);
-        v8::Handle<v8::Value> args[] = { engine->newQObject(o), valuemap };
-        v8::Handle<v8::Function>::Cast(function)->Call(engine->global(), 2, args);
+        QV4::ExecutionEngine *v4engine = QV8Engine::getV4(engine);
 
-        qPersistentDispose(valuemap);
-        qPersistentDispose(qmlGlobal);
+        QV4::Value f = engine->evaluateScript(QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobal->v4Value().asObject());
+        QV4::Value args[] = { engine->newQObject(o)->v4Value(), valuemap->v4Value() };
+        f.asFunctionObject()->call(v4engine->current, QV4::Value::fromObject(v4engine->globalObject), args, 2);
     }
 }
     
@@ -1517,4 +1510,6 @@ void QV8IncubatorResource::statusChanged(Status s)
         dispose();
 }
 
+#undef INITIALPROPERTIES_SOURCE
+
 QT_END_NAMESPACE
index 67582e1..e470eaa 100644 (file)
@@ -70,6 +70,7 @@
 #include <private/qv4objectiterator_p.h>
 #include <private/qv4mm_p.h>
 #include <private/qv4objectproto_p.h>
+#include <private/qv4globalobject_p.h>
 
 Q_DECLARE_METATYPE(QList<int>)
 
@@ -1620,6 +1621,22 @@ QJSValue QV8Engine::evaluate(const QString& program, const QString& fileName, qu
     return evaluate(script, tryCatch);
 }
 
+QV4::Value QV8Engine::evaluateScript(const QString &script, QV4::Object *scopeObject)
+{
+    QV4::ExecutionContext *ctx = m_v4Engine->current;
+
+    QV4::Value result = QV4::Value::undefinedValue();
+
+    try {
+        QV4::EvalFunction *eval = new (m_v4Engine->memoryManager) QV4::EvalFunction(m_v4Engine->rootContext, scopeObject);
+        QV4::Value arg = QV4::Value::fromString(m_v4Engine->current, script);
+        result = eval->evalCall(m_v4Engine->current, QV4::Value::undefinedValue(), &arg, 1, /*directCall*/ false);
+    } catch (QV4::Exception &e) {
+        e.accept(ctx);
+    }
+    return result;
+}
+
 
 QT_END_NAMESPACE
 
index 187eea4..d5854d3 100644 (file)
@@ -101,6 +101,7 @@ namespace QV4 {
     struct Value;
 }
 
+#define V4FUNCTION(function, engine) new QV4::BuiltinFunctionOld(engine->rootContext, engine->id_undefined, function)
 
 // Uncomment the following line to enable global handle debugging.  When enabled, all the persistent
 // handles allocated using qPersistentNew() (or registered with qPersistentRegsiter()) and disposed
@@ -383,6 +384,7 @@ public:
 
     QJSValue evaluate(const QString &program, const QString &fileName = QString(), quint16 lineNumber = 1);
     QJSValue evaluate(v8::Handle<v8::Script> script, v8::TryCatch& tryCatch);
+    QV4::Value evaluateScript(const QString &script, QV4::Object *scopeObject = 0);
 
     QJSValue newArray(uint length);
     v8::Local<v8::Object> newVariant(const QVariant &variant);