diff options
author | Kent Hansen <khansen@trolltech.com> | 2009-07-10 12:27:16 (GMT) |
---|---|---|
committer | Kent Hansen <khansen@trolltech.com> | 2009-07-10 12:27:16 (GMT) |
commit | 75bc0215080fcafea9ba1bafedd980d9ac71bf9d (patch) | |
tree | 61156a5b2eaf3377b304beb6df59343750d21804 /src/script/bridge/qscriptvariant.cpp | |
parent | 0579f4be2e79bb95c963a7e2368b6ee797c25e90 (diff) | |
download | Qt-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.cpp | 45 |
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); |