summaryrefslogtreecommitdiffstats
path: root/src/script/bridge/qscriptvariant.cpp
diff options
context:
space:
mode:
authorKent Hansen <khansen@trolltech.com>2009-07-10 12:27:16 (GMT)
committerKent Hansen <khansen@trolltech.com>2009-07-10 12:27:16 (GMT)
commit75bc0215080fcafea9ba1bafedd980d9ac71bf9d (patch)
tree61156a5b2eaf3377b304beb6df59343750d21804 /src/script/bridge/qscriptvariant.cpp
parent0579f4be2e79bb95c963a7e2368b6ee797c25e90 (diff)
downloadQt-75bc0215080fcafea9ba1bafedd980d9ac71bf9d.zip
Qt-75bc0215080fcafea9ba1bafedd980d9ac71bf9d.tar.gz
Qt-75bc0215080fcafea9ba1bafedd980d9ac71bf9d.tar.bz2
implement ability to dynamically change class of script objects
With an object created by QScriptEngine::newObject(), it should be possible to call QScriptValue::setClass() to dynamically change the behavior of that object. Similarly, it should be possible to promote plain script objects to QObject (QVariant) wrappers by calling the overload of QScriptEngine::newQObject() (newVariant()) that takes a script object as the first argument. This commit implements this capability. The premise is the (internal) QScriptObject class, which inherits JSC::JSObject. It reimplements all the methods for getting/setting properties etc. Then there's a level of indirection to facilitate dynamic change of the class: Each QScriptObject can have a delegate associated with it that will handle operations on the object. By default there is no delegate, so the object behaves as a normal JS object, as you expect. However, once a delegate is set (e.g., when QScriptValue::setScriptClass() is called), QScriptObject will give the delegate the chance to handle the object operation. In addition to a delegate implementation for QScriptClass-based objects, there are also delegates for QObject and QVariant wrappers. These replace the QObjectWrapperObject and QVariantWrapperObject classes.
Diffstat (limited to 'src/script/bridge/qscriptvariant.cpp')
-rw-r--r--src/script/bridge/qscriptvariant.cpp45
1 files changed, 31 insertions, 14 deletions
diff --git a/src/script/bridge/qscriptvariant.cpp b/src/script/bridge/qscriptvariant.cpp
index 0255961..46da70a 100644
--- a/src/script/bridge/qscriptvariant.cpp
+++ b/src/script/bridge/qscriptvariant.cpp
@@ -21,7 +21,6 @@ QT_BEGIN_NAMESPACE
namespace JSC
{
-ASSERT_CLASS_FITS_IN_CELL(QScript::QVariantWrapperObject);
ASSERT_CLASS_FITS_IN_CELL(QScript::QVariantPrototype);
}
@@ -30,34 +29,52 @@ namespace QScript
JSC::UString qtStringToJSCUString(const QString &str);
-const JSC::ClassInfo QVariantWrapperObject::info = { "QVariant", 0, 0, 0 };
+QVariantDelegate::QVariantDelegate(const QVariant &value)
+ : m_value(value)
+{
+}
+
+QVariantDelegate::~QVariantDelegate()
+{
+}
-QVariantWrapperObject::QVariantWrapperObject(WTF::PassRefPtr<JSC::Structure> sid)
- : JSC::JSObject(sid), data(new Data())
+QVariant &QVariantDelegate::value()
{
+ return m_value;
}
-QVariantWrapperObject::~QVariantWrapperObject()
+void QVariantDelegate::setValue(const QVariant &value)
{
- delete data;
+ m_value = value;
+}
+
+QScriptObjectDelegate::Type QVariantDelegate::type() const
+{
+ return Variant;
}
static JSC::JSValue JSC_HOST_CALL variantProtoFuncToString(JSC::ExecState *exec, JSC::JSObject*,
JSC::JSValue thisValue, const JSC::ArgList&)
{
- if (!thisValue.isObject(&QVariantWrapperObject::info))
- return throwError(exec, JSC::TypeError);
- const QVariant &v = static_cast<QVariantWrapperObject*>(JSC::asObject(thisValue))->value();
- // ### check the type
+ if (!thisValue.isObject(&QScriptObject::info))
+ return throwError(exec, JSC::TypeError, "This object is not a QVariant");
+ QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(thisValue))->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::Variant))
+ return throwError(exec, JSC::TypeError, "This object is not a QVariant");
+ const QVariant &v = static_cast<QVariantDelegate*>(delegate)->value();
+ // ### call valueOf()
return JSC::jsString(exec, QScript::qtStringToJSCUString(v.toString()));
}
static JSC::JSValue JSC_HOST_CALL variantProtoFuncValueOf(JSC::ExecState *exec, JSC::JSObject*,
JSC::JSValue thisValue, const JSC::ArgList&)
{
- if (!thisValue.isObject(&QVariantWrapperObject::info))
+ if (!thisValue.isObject(&QScriptObject::info))
+ return throwError(exec, JSC::TypeError);
+ QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(thisValue))->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::Variant))
return throwError(exec, JSC::TypeError);
- const QVariant &v = static_cast<QVariantWrapperObject*>(JSC::asObject(thisValue))->value();
+ const QVariant &v = static_cast<QVariantDelegate*>(delegate)->value();
switch (v.type()) {
case QVariant::Invalid:
return JSC::jsUndefined();
@@ -87,9 +104,9 @@ static JSC::JSValue JSC_HOST_CALL variantProtoFuncValueOf(JSC::ExecState *exec,
QVariantPrototype::QVariantPrototype(JSC::ExecState* exec, WTF::PassRefPtr<JSC::Structure> structure,
JSC::Structure* prototypeFunctionStructure)
- : QVariantWrapperObject(structure)
+ : QScriptObject(structure)
{
- setValue(QVariant());
+ setDelegate(new QVariantDelegate(QVariant()));
putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, variantProtoFuncToString), JSC::DontEnum);
putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, variantProtoFuncValueOf), JSC::DontEnum);