src/script/bridge/qscriptdeclarativeclass.cpp
changeset 30 5dc02b23752f
parent 18 2f34d5167611
child 33 3e2da88830cd
--- a/src/script/bridge/qscriptdeclarativeclass.cpp	Wed Jun 23 19:07:03 2010 +0300
+++ b/src/script/bridge/qscriptdeclarativeclass.cpp	Tue Jul 06 15:10:48 2010 +0300
@@ -35,19 +35,137 @@
 
 QT_BEGIN_NAMESPACE
 
+/*!
+\class QScriptDeclarativeClass::Value
+\internal
+\brief The QScriptDeclarativeClass::Value class acts as a container for JavaScript data types.
+
+QScriptDeclarativeClass::Value class is similar to QScriptValue, but it is slightly faster.  
+Unlike QScriptValue, however, Value instances cannot be stored as they may not survive garbage 
+collection.  If you need to store a Value, convert it to a QScriptValue and store that.
+*/
+
+QScriptDeclarativeClass::Value::Value()
+{
+    new (this) JSC::JSValue(JSC::jsUndefined());
+}
+
+QScriptDeclarativeClass::Value::Value(const Value &other)
+{
+    new (this) JSC::JSValue((JSC::JSValue &)other);
+}
+
+static QScriptDeclarativeClass::Value jscToValue(const JSC::JSValue &val)
+{
+    return QScriptDeclarativeClass::Value((QScriptDeclarativeClass::Value &)val);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, int value)
+{
+    new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, uint value)
+{
+    new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *, bool value)
+{
+    if (value)
+        new (this) JSC::JSValue(JSC::JSValue::JSTrue);
+    else
+        new (this) JSC::JSValue(JSC::JSValue::JSFalse);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, double value)
+{
+    new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, float value)
+{
+    new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, const QString &value)
+{
+    new (this) JSC::JSValue(JSC::jsString(QScriptEnginePrivate::frameForContext(ctxt), value));
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, const QScriptValue &value)
+{
+    new (this) JSC::JSValue(QScriptEnginePrivate::get(ctxt->engine())->scriptValueToJSCValue(value));
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, int value)
+{
+    new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, uint value)
+{
+    new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, bool value)
+{
+    if (value)
+        new (this) JSC::JSValue(JSC::JSValue::JSTrue);
+    else
+        new (this) JSC::JSValue(JSC::JSValue::JSFalse);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, double value)
+{
+    new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, float value)
+{
+    new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, const QString &value)
+{
+    new (this) JSC::JSValue(JSC::jsString(QScriptEnginePrivate::get(eng)->currentFrame, value));
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, const QScriptValue &value)
+{
+        new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->scriptValueToJSCValue(value));
+}
+
+QScriptDeclarativeClass::Value::~Value()
+{
+    ((JSC::JSValue *)(this))->~JSValue();
+}
+
+QScriptValue QScriptDeclarativeClass::Value::toScriptValue(QScriptEngine *engine) const
+{
+    return QScriptEnginePrivate::get(engine)->scriptValueFromJSCValue((JSC::JSValue &)*this);
+}
+
 QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier()
+    : identifier(0), engine(0)
 {
     new (&d) JSC::Identifier();
 }
 
 QScriptDeclarativeClass::PersistentIdentifier::~PersistentIdentifier()
 {
-    ((JSC::Identifier &)d).JSC::Identifier::~Identifier();
+    if (engine) {
+        QScript::APIShim shim(engine);
+        ((JSC::Identifier &)d).JSC::Identifier::~Identifier();
+    } else {
+        ((JSC::Identifier &)d).JSC::Identifier::~Identifier();
+    }
 }
 
 QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier(const PersistentIdentifier &other)
 {
     identifier = other.identifier;
+    engine = other.engine;
     new (&d) JSC::Identifier((JSC::Identifier &)(other.d));
 }
 
@@ -55,6 +173,7 @@
 QScriptDeclarativeClass::PersistentIdentifier::operator=(const PersistentIdentifier &other)
 {
     identifier = other.identifier;
+    engine = other.engine;
     ((JSC::Identifier &)d) = (JSC::Identifier &)(other.d);
     return *this;
 }
@@ -74,7 +193,8 @@
     Q_ASSERT(engine);
     Q_ASSERT(scriptClass);
 
-    QScriptEnginePrivate *p = static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(engine)); 
+    QScriptEnginePrivate *p = static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(engine));
+    QScript::APIShim shim(p);
 
     JSC::ExecState* exec = p->currentFrame;
     QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure);
@@ -82,28 +202,37 @@
     return p->scriptValueFromJSCValue(result);
 }
 
+QScriptDeclarativeClass::Value 
+QScriptDeclarativeClass::newObjectValue(QScriptEngine *engine, 
+                                        QScriptDeclarativeClass *scriptClass, 
+                                        Object *object)
+{
+    Q_ASSERT(engine);
+    Q_ASSERT(scriptClass);
+
+    QScriptEnginePrivate *p = static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(engine)); 
+    QScript::APIShim shim(p);
+
+    JSC::ExecState* exec = p->currentFrame;
+    QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure);
+    result->setDelegate(new QScript::DeclarativeObjectDelegate(scriptClass, object));
+    return jscToValue(JSC::JSValue(result));
+}
+
 QScriptDeclarativeClass *QScriptDeclarativeClass::scriptClass(const QScriptValue &v)
 {
     QScriptValuePrivate *d = QScriptValuePrivate::get(v);
-    if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info))
+    if (!d || !d->isJSC())
         return 0;
-    QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
-    QScriptObjectDelegate *delegate = scriptObject->delegate();
-    if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject))
-        return 0;
-    return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass();
+    return QScriptEnginePrivate::declarativeClass(d->jscValue);
 }
 
 QScriptDeclarativeClass::Object *QScriptDeclarativeClass::object(const QScriptValue &v)
 {
     QScriptValuePrivate *d = QScriptValuePrivate::get(v);
-    if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info))
+    if (!d || !d->isJSC())
         return 0;
-    QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
-    QScriptObjectDelegate *delegate = scriptObject->delegate();
-    if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject))
-        return 0;
-    return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->object();
+    return QScriptEnginePrivate::declarativeObject(d->jscValue);
 }
 
 QScriptValue QScriptDeclarativeClass::function(const QScriptValue &v, const Identifier &name)
@@ -113,6 +242,7 @@
     if (!d->isObject())
         return QScriptValue();
 
+    QScript::APIShim shim(d->engine);
     JSC::ExecState *exec = d->engine->currentFrame;
     JSC::JSObject *object = d->jscValue.getObject();
     JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
@@ -136,6 +266,7 @@
     if (!d->isObject())
         return QScriptValue();
 
+    QScript::APIShim shim(d->engine);
     JSC::ExecState *exec = d->engine->currentFrame;
     JSC::JSObject *object = d->jscValue.getObject();
     JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
@@ -151,6 +282,55 @@
     return QScriptValue();
 }
 
+QScriptDeclarativeClass::Value
+QScriptDeclarativeClass::functionValue(const QScriptValue &v, const Identifier &name)
+{
+    QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+
+    if (!d->isObject())
+        return Value();
+
+    QScript::APIShim shim(d->engine);
+    JSC::ExecState *exec = d->engine->currentFrame;
+    JSC::JSObject *object = d->jscValue.getObject();
+    JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
+    JSC::JSValue result;
+
+    JSC::Identifier id(exec, (JSC::UString::Rep *)name);
+
+    if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) {
+        result = slot.getValue(exec, id);
+        if (QScript::isFunction(result))
+            return jscToValue(result);
+    }
+
+    return Value();
+}
+
+QScriptDeclarativeClass::Value
+QScriptDeclarativeClass::propertyValue(const QScriptValue &v, const Identifier &name)
+{
+    QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+
+    if (!d->isObject())
+        return Value();
+
+    QScript::APIShim shim(d->engine);
+    JSC::ExecState *exec = d->engine->currentFrame;
+    JSC::JSObject *object = d->jscValue.getObject();
+    JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
+    JSC::JSValue result;
+
+    JSC::Identifier id(exec, (JSC::UString::Rep *)name);
+
+    if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) {
+        result = slot.getValue(exec, id);
+        return jscToValue(result);
+    }
+
+    return Value();
+}
+
 /*
 Returns the scope chain entry at \a index.  If index is less than 0, returns
 entries starting at the end.  For example, scopeChainValue(context, -1) will return
@@ -161,6 +341,7 @@
     context->activationObject(); //ensure the creation of the normal scope for native context
     const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(context);
     QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
+    QScript::APIShim shim(engine);
 
     JSC::ScopeChainNode *node = frame->scopeChain();
     JSC::ScopeChainIterator it(node);
@@ -221,6 +402,7 @@
         return 0;
 
     QScriptEnginePrivate *d = QScriptEnginePrivate::get(engine);
+    QScript::APIShim shim(d);
 
     JSC::CallFrame* newFrame = d->pushContext(d->currentFrame, 
                                               d->currentFrame->globalData().dynamicGlobalObject,
@@ -241,14 +423,25 @@
     return d_ptr->engine;
 }
 
+bool QScriptDeclarativeClass::supportsCall() const
+{
+    return d_ptr->supportsCall;
+}
+
+void QScriptDeclarativeClass::setSupportsCall(bool c)
+{
+    d_ptr->supportsCall = c;
+}
+
 QScriptDeclarativeClass::PersistentIdentifier 
 QScriptDeclarativeClass::createPersistentIdentifier(const QString &str)
 {
     QScriptEnginePrivate *p = 
         static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine)); 
+    QScript::APIShim shim(p);
     JSC::ExecState* exec = p->currentFrame;
 
-    PersistentIdentifier rv(true);
+    PersistentIdentifier rv(p);
     new (&rv.d) JSC::Identifier(exec, (UChar *)str.constData(), str.size());
     rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep();
     return rv;
@@ -259,9 +452,10 @@
 {
     QScriptEnginePrivate *p = 
         static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine)); 
+    QScript::APIShim shim(p);
     JSC::ExecState* exec = p->currentFrame;
 
-    PersistentIdentifier rv(true);
+    PersistentIdentifier rv(p);
     new (&rv.d) JSC::Identifier(exec, (JSC::UString::Rep *)id);
     rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep();
     return rv;
@@ -290,11 +484,12 @@
     return 0;
 }
 
-QScriptValue QScriptDeclarativeClass::property(Object *object, const Identifier &name)
+QScriptDeclarativeClass::Value
+QScriptDeclarativeClass::property(Object *object, const Identifier &name)
 {
     Q_UNUSED(object);
     Q_UNUSED(name);
-    return QScriptValue();
+    return Value();
 }
 
 void QScriptDeclarativeClass::setProperty(Object *object, const Identifier &name, 
@@ -313,6 +508,19 @@
     return 0;
 }
 
+QScriptDeclarativeClass::Value QScriptDeclarativeClass::call(Object *object, 
+                                                             QScriptContext *ctxt)
+{
+    Q_UNUSED(object);
+    Q_UNUSED(ctxt);
+    return Value();
+}
+
+bool QScriptDeclarativeClass::compare(Object *o, Object *o2)
+{
+    return o == o2;
+}
+
 QStringList QScriptDeclarativeClass::propertyNames(Object *object)
 {
     Q_UNUSED(object);