summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKent Hansen <khansen@trolltech.com>2009-07-27 17:42:26 (GMT)
committerKent Hansen <khansen@trolltech.com>2009-07-27 18:01:19 (GMT)
commit8923339fa086cbf6adc404fb18dcda6c1206985d (patch)
tree13ad42fc95c63e9f49a971a42fab7ddb1c6af61c /src
parent117802b5ca71478d01bb79f88aa3596729b0a590 (diff)
downloadQt-8923339fa086cbf6adc404fb18dcda6c1206985d.zip
Qt-8923339fa086cbf6adc404fb18dcda6c1206985d.tar.gz
Qt-8923339fa086cbf6adc404fb18dcda6c1206985d.tar.bz2
make QScriptEngine::setGlobalObject() work to some extent
JSC requires that the global object is actually a JSGlobalObject instance, whereas QScriptEngine::setGlobalObject() allows any object to be set as the global object. The way we solve this is by proxying from an internal global object to the custom (user-set) object. We need to take care that the internal global object is never actually exposed through our API; a brilliantly named helper function, toUsableValue(), makes that happen. Evaluating "var a = 10" with a custom global object doesn't work yet; the variable always ends up in the internal Global Object. For variable assignments, JSC appears to bypass the normal JSObject::put() and instead use JSGlobalObject::copyGlobals{From,To}(), which means I can't intercept and proxy the assignments. This commit enough to get the Context2D example working. There's another bug with iteration of the built-in Global Object's properties (non-enumerable properties are always skipped by the JSC C++ API, whereas with QScriptValueIterator they should not be), but that's a totally separate issue.
Diffstat (limited to 'src')
-rw-r--r--src/script/api/qscriptengine.cpp148
-rw-r--r--src/script/api/qscriptengine_p.h9
-rw-r--r--src/script/api/qscriptvalue.cpp9
-rw-r--r--src/script/bridge/qscriptqobject.cpp25
-rw-r--r--src/script/bridge/qscriptvariant.cpp8
5 files changed, 165 insertions, 34 deletions
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index 2f7e976..1b7d0e4 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -321,7 +321,7 @@ struct GlobalClientData : public JSC::JSGlobalData::ClientData
class GlobalObject : public JSC::JSGlobalObject
{
public:
- GlobalObject(QScriptEnginePrivate*);
+ GlobalObject();
virtual ~GlobalObject();
virtual JSC::UString className() const { return "global"; }
virtual void mark();
@@ -337,7 +337,44 @@ public:
virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
public:
- QScriptEnginePrivate *engine;
+ JSC::JSObject *customGlobalObject;
+};
+
+class OriginalGlobalObjectProxy : public JSC::JSObject
+{
+public:
+ explicit OriginalGlobalObjectProxy(WTF::PassRefPtr<JSC::Structure> sid,
+ JSC::JSGlobalObject *object)
+ : JSC::JSObject(sid), originalGlobalObject(object)
+ {}
+ virtual ~OriginalGlobalObjectProxy()
+ {}
+ virtual JSC::UString className() const
+ { return originalGlobalObject->className(); }
+ virtual void mark()
+ {
+ Q_ASSERT(!marked());
+ if (!originalGlobalObject->marked())
+ originalGlobalObject->JSC::JSGlobalObject::mark();
+ JSC::JSObject::mark();
+ }
+ virtual bool getOwnPropertySlot(JSC::ExecState* exec,
+ const JSC::Identifier& propertyName,
+ JSC::PropertySlot& slot)
+ { return originalGlobalObject->JSC::JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot); }
+ virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName,
+ JSC::JSValue value, JSC::PutPropertySlot& slot)
+ { originalGlobalObject->JSC::JSGlobalObject::put(exec, propertyName, value, slot); }
+ virtual bool deleteProperty(JSC::ExecState* exec,
+ const JSC::Identifier& propertyName)
+ { return originalGlobalObject->JSC::JSGlobalObject::deleteProperty(exec, propertyName); }
+ virtual bool getPropertyAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName,
+ unsigned& attributes) const
+ { return originalGlobalObject->JSC::JSGlobalObject::getPropertyAttributes(exec, propertyName, attributes); }
+ virtual void getPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames)
+ { originalGlobalObject->JSC::JSGlobalObject::getPropertyNames(exec, propertyNames); }
+private:
+ JSC::JSGlobalObject *originalGlobalObject;
};
static int toDigit(char c)
@@ -585,8 +622,8 @@ JSC::JSValue functionConnect(JSC::ExecState *exec, JSC::JSObject */*callee*/, JS
#endif // QT_NO_QOBJECT
}
-GlobalObject::GlobalObject(QScriptEnginePrivate *eng)
- : JSC::JSGlobalObject(), engine(eng)
+GlobalObject::GlobalObject()
+ : JSC::JSGlobalObject(), customGlobalObject(0)
{
}
@@ -596,37 +633,52 @@ GlobalObject::~GlobalObject()
void GlobalObject::mark()
{
+ Q_ASSERT(!marked());
JSC::JSGlobalObject::mark();
+ if (customGlobalObject && !customGlobalObject->marked())
+ customGlobalObject->mark();
}
bool GlobalObject::getOwnPropertySlot(JSC::ExecState* exec,
const JSC::Identifier& propertyName,
JSC::PropertySlot& slot)
{
+ if (customGlobalObject)
+ return customGlobalObject->getOwnPropertySlot(exec, propertyName, slot);
return JSC::JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot);
}
void GlobalObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName,
JSC::JSValue value, JSC::PutPropertySlot& slot)
{
- JSC::JSGlobalObject::put(exec, propertyName, value, slot);
+ if (customGlobalObject)
+ customGlobalObject->put(exec, propertyName, value, slot);
+ else
+ JSC::JSGlobalObject::put(exec, propertyName, value, slot);
}
bool GlobalObject::deleteProperty(JSC::ExecState* exec,
const JSC::Identifier& propertyName)
{
+ if (customGlobalObject)
+ return customGlobalObject->deleteProperty(exec, propertyName);
return JSC::JSGlobalObject::deleteProperty(exec, propertyName);
}
bool GlobalObject::getPropertyAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName,
unsigned& attributes) const
{
+ if (customGlobalObject)
+ return customGlobalObject->getPropertyAttributes(exec, propertyName, attributes);
return JSC::JSGlobalObject::getPropertyAttributes(exec, propertyName, attributes);
}
void GlobalObject::getPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames)
{
- JSC::JSGlobalObject::getPropertyNames(exec, propertyNames);
+ if (customGlobalObject)
+ customGlobalObject->getPropertyNames(exec, propertyNames);
+ else
+ JSC::JSGlobalObject::getPropertyNames(exec, propertyNames);
}
static JSC::JSValue JSC_HOST_CALL functionPrint(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
@@ -785,6 +837,7 @@ JSC::JSValue stringProtoFuncArg(JSC::ExecState *exec, JSC::JSObject*, JSC::JSVal
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(QScript::GlobalObject);
+ASSERT_CLASS_FITS_IN_CELL(QScript::OriginalGlobalObjectProxy);
} // namespace JSC
@@ -796,7 +849,7 @@ QScriptEnginePrivate::QScriptEnginePrivate() : idGenerator(1)
globalData = JSC::JSGlobalData::create().releaseRef();
globalData->clientData = new QScript::GlobalClientData(this);
- JSC::JSGlobalObject *globalObject = new (globalData)QScript::GlobalObject(this);
+ JSC::JSGlobalObject *globalObject = new (globalData)QScript::GlobalObject();
JSC::ExecState* exec = globalObject->globalExec();
@@ -821,7 +874,7 @@ QScriptEnginePrivate::QScriptEnginePrivate() : idGenerator(1)
currentFrame = exec;
- customGlobalObject = 0;
+ originalGlobalObjectProxy = 0;
agent = 0;
processEventsInterval = -1;
}
@@ -1029,20 +1082,79 @@ void QScriptEnginePrivate::releaseContextForFrame(JSC::ExecState *frame)
delete ctx;
}
-JSC::JSGlobalObject *QScriptEnginePrivate::globalObject() const
+JSC::JSGlobalObject *QScriptEnginePrivate::originalGlobalObject() const
{
return globalData->head;
}
+JSC::JSObject *QScriptEnginePrivate::customGlobalObject() const
+{
+ QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
+ return glob->customGlobalObject;
+}
+
+JSC::JSObject *QScriptEnginePrivate::getOriginalGlobalObjectProxy()
+{
+ if (!originalGlobalObjectProxy) {
+ JSC::ExecState* exec = currentFrame;
+ originalGlobalObjectProxy = new (exec)QScript::OriginalGlobalObjectProxy(scriptObjectStructure, originalGlobalObject());
+ }
+ return originalGlobalObjectProxy;
+}
+
+JSC::JSObject *QScriptEnginePrivate::globalObject() const
+{
+ QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
+ if (glob->customGlobalObject)
+ return glob->customGlobalObject;
+ return glob;
+}
+
+void QScriptEnginePrivate::setGlobalObject(JSC::JSObject *object)
+{
+ if (object == globalObject())
+ return;
+ QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
+ if (object == originalGlobalObjectProxy)
+ glob->customGlobalObject = 0;
+ else {
+ Q_ASSERT(object != originalGlobalObject());
+ glob->customGlobalObject = object;
+ }
+}
+
JSC::ExecState *QScriptEnginePrivate::globalExec() const
{
- return globalObject()->globalExec();
+ return originalGlobalObject()->globalExec();
+}
+
+/*!
+ \internal
+
+ If the given \a value is the original global object, returns the custom
+ global object or a proxy to the original global object; otherwise returns \a
+ value.
+*/
+JSC::JSValue QScriptEnginePrivate::toUsableValue(JSC::JSValue value)
+{
+ if (!value || !value.isObject() || !JSC::asObject(value)->isGlobalObject())
+ return value;
+ Q_ASSERT(JSC::asObject(value) == originalGlobalObject());
+ if (customGlobalObject())
+ return customGlobalObject();
+ if (!originalGlobalObjectProxy)
+ originalGlobalObjectProxy = new (currentFrame)QScript::OriginalGlobalObjectProxy(scriptObjectStructure, originalGlobalObject());
+ return originalGlobalObjectProxy;
}
void QScriptEnginePrivate::mark()
{
- if (customGlobalObject && !customGlobalObject->marked())
- customGlobalObject->mark();
+ if (!originalGlobalObject()->marked())
+ originalGlobalObject()->mark();
+ if (!globalObject()->marked())
+ globalObject()->mark();
+ if (originalGlobalObjectProxy && !originalGlobalObjectProxy->marked())
+ originalGlobalObjectProxy->mark();
if (qobjectPrototype && !qobjectPrototype->marked())
qobjectPrototype->mark();
@@ -1086,9 +1198,6 @@ bool QScriptEnginePrivate::isCollecting() const
void QScriptEnginePrivate::collectGarbage()
{
- // ### why isn't the global object always marked by the Collector?
- if (!globalObject()->marked())
- globalObject()->mark();
JSC::JSLock lock(false);
globalData->heap.collect();
}
@@ -1385,11 +1494,10 @@ QScriptValue QScriptEngine::globalObject() const
void QScriptEngine::setGlobalObject(const QScriptValue &object)
{
Q_D(QScriptEngine);
- if (!object.isObject() || globalObject().strictlyEquals(object))
+ if (!object.isObject())
return;
JSC::JSObject *jscObject = JSC::asObject(d->scriptValueToJSCValue(object));
- qWarning("QScriptEngine::setGlobalObject() is not implemented");
-// d->customGlobalObject = jscObject;
+ d->setGlobalObject(jscObject);
}
/*!
@@ -2410,7 +2518,7 @@ QScriptValue QScriptEnginePrivate::create(int type, const void *ptr)
}
}
if (result.isObject() && info && info->prototype
- && JSC::JSValue::strictEqual(scriptValueToJSCValue(result.prototype()), globalObject()->objectPrototype())) {
+ && JSC::JSValue::strictEqual(scriptValueToJSCValue(result.prototype()), originalGlobalObject()->objectPrototype())) {
result.setPrototype(scriptValueFromJSCValue(info->prototype));
}
return result;
@@ -2671,7 +2779,7 @@ void QScriptEngine::installTranslatorFunctions(const QScriptValue &object)
Q_D(QScriptEngine);
JSC::ExecState* exec = d->currentFrame;
JSC::JSValue jscObject = d->scriptValueToJSCValue(object);
- JSC::JSGlobalObject *glob = d->globalObject();
+ JSC::JSGlobalObject *glob = d->originalGlobalObject();
if (!jscObject || !jscObject.isObject())
jscObject = glob;
// unsigned attribs = JSC::DontEnum;
diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h
index 4db77c0..c0f5e13 100644
--- a/src/script/api/qscriptengine_p.h
+++ b/src/script/api/qscriptengine_p.h
@@ -110,8 +110,13 @@ public:
QScriptContext *contextForFrame(JSC::ExecState *frame);
void releaseContextForFrame(JSC::ExecState *frame);
- JSC::JSGlobalObject *globalObject() const;
+ JSC::JSGlobalObject *originalGlobalObject() const;
+ JSC::JSObject *getOriginalGlobalObjectProxy();
+ JSC::JSObject *customGlobalObject() const;
+ JSC::JSObject *globalObject() const;
+ void setGlobalObject(JSC::JSObject *object);
JSC::ExecState *globalExec() const;
+ JSC::JSValue toUsableValue(JSC::JSValue value);
void mark();
bool isCollecting() const;
@@ -162,7 +167,7 @@ public:
#endif
JSC::JSGlobalData *globalData;
- JSC::JSObject *customGlobalObject;
+ JSC::JSObject *originalGlobalObjectProxy;
JSC::ExecState *currentFrame;
QHash<JSC::ExecState*, QScriptContext*> contextForFrameHash;
diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp
index 5ace14d..59e6729 100644
--- a/src/script/api/qscriptvalue.cpp
+++ b/src/script/api/qscriptvalue.cpp
@@ -276,19 +276,20 @@ QScriptValuePrivate::QScriptValueAutoRegister& QScriptValuePrivate::QScriptValue
return *this;
};
-
void QScriptValuePrivate::initFromJSCValue(JSC::JSValue value)
{
- type = JSC;
- jscValue = value;
if (value.isCell()) {
- JSC::JSCell *cell = value.asCell();
Q_ASSERT(engine != 0);
QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine);
+ value = eng_p->toUsableValue(value);
+ JSC::JSCell *cell = JSC::asCell(value);
+ Q_ASSERT(cell != eng_p->originalGlobalObject());
if (!eng_p->keepAliveValues.contains(cell))
eng_p->keepAliveValues[cell] = 0;
eng_p->keepAliveValues[cell].ref();
}
+ type = JSC;
+ jscValue = value;
}
void QScriptValuePrivate::initFromNumber(double value)
diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp
index b065f5c..94bd8f9 100644
--- a/src/script/bridge/qscriptqobject.cpp
+++ b/src/script/bridge/qscriptqobject.cpp
@@ -487,6 +487,7 @@ JSC::JSValue QtFunction::execute(JSC::ExecState *exec, JSC::JSValue thisValue,
const QMetaObject *meta = qobj->metaObject();
QObject *thisQObject = 0;
+ thisValue = engine->toUsableValue(thisValue);
if (thisValue.isObject(&QScriptObject::info)) {
delegate = static_cast<QScriptObject*>(JSC::asObject(thisValue))->delegate();
if (delegate && (delegate->type() == QScriptObjectDelegate::QtObject))
@@ -1029,6 +1030,7 @@ JSC::JSValue QtPropertyFunction::execute(JSC::ExecState *exec,
// ### don't go via QScriptValue
QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ thisValue = engine->toUsableValue(thisValue);
QScriptValue object = engine->scriptValueFromJSCValue(thisValue);
QObject *qobject = object.toQObject();
while ((!qobject || (qobject->metaObject() != data->meta))
@@ -1168,7 +1170,7 @@ bool QObjectDelegate::getOwnPropertySlot(QScriptObject *object, JSC::ExecState *
|| (index >= meta->methodOffset())) {
QtFunction *fun = new (exec)QtFunction(
object, index, /*maybeOverloaded=*/false,
- &exec->globalData(), eng->globalObject()->functionStructure(),
+ &exec->globalData(), eng->originalGlobalObject()->functionStructure(),
propertyName);
slot.setValue(fun);
data->cachedMembers.insert(name, fun);
@@ -1187,7 +1189,7 @@ bool QObjectDelegate::getOwnPropertySlot(QScriptObject *object, JSC::ExecState *
if (GeneratePropertyFunctions) {
QtPropertyFunction *fun = new (exec)QtPropertyFunction(
meta, index, &exec->globalData(),
- eng->globalObject()->functionStructure(),
+ eng->originalGlobalObject()->functionStructure(),
propertyName);
data->cachedMembers.insert(name, fun);
slot.setGetterSlot(fun);
@@ -1219,7 +1221,7 @@ bool QObjectDelegate::getOwnPropertySlot(QScriptObject *object, JSC::ExecState *
&& (methodName(method) == name)) {
QtFunction *fun = new (exec)QtFunction(
object, index, /*maybeOverloaded=*/true,
- &exec->globalData(), eng->globalObject()->functionStructure(),
+ &exec->globalData(), eng->originalGlobalObject()->functionStructure(),
propertyName);
slot.setValue(fun);
data->cachedMembers.insert(name, fun);
@@ -1292,7 +1294,7 @@ void QObjectDelegate::put(QScriptObject *object, JSC::ExecState* exec,
} else {
fun = new (exec)QtPropertyFunction(
meta, index, &exec->globalData(),
- eng->globalObject()->functionStructure(),
+ eng->originalGlobalObject()->functionStructure(),
propertyName);
data->cachedMembers.insert(name, fun);
}
@@ -1520,6 +1522,8 @@ void QObjectDelegate::mark(QScriptObject *object)
static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChild(JSC::ExecState *exec, JSC::JSObject*,
JSC::JSValue thisValue, const JSC::ArgList &args)
{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ thisValue = engine->toUsableValue(thisValue);
if (!thisValue.isObject(&QScriptObject::info))
return throwError(exec, JSC::TypeError, "this object is not a QObject");
QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(thisValue));
@@ -1532,13 +1536,14 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChild(JSC::ExecState *exec
name = QScript::qtStringFromJSCUString(args.at(0).toString(exec));
QObject *child = qFindChild<QObject*>(obj, name);
QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject;
- QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
return engine->newQObject(child, QScriptEngine::QtOwnership, opt);
}
static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChildren(JSC::ExecState *exec, JSC::JSObject*,
JSC::JSValue thisValue, const JSC::ArgList &args)
{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ thisValue = engine->toUsableValue(thisValue);
// extract the QObject
if (!thisValue.isObject(&QScriptObject::info))
return throwError(exec, JSC::TypeError, "this object is not a QObject");
@@ -1547,7 +1552,6 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChildren(JSC::ExecState *e
if (!delegate || (delegate->type() != QScriptObjectDelegate::QtObject))
return throwError(exec, JSC::TypeError, "this object is not a QObject");
const QObject *const obj = static_cast<QObjectDelegate*>(delegate)->value();
- QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
// find the children
QList<QObject *> children;
@@ -1562,7 +1566,7 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChildren(JSC::ExecState *e
for (int i = 0; i < allChildrenCount; ++i) {
QObject *const child = allChildren.at(i);
const JSC::UString childName = qtStringToJSCUString(child->objectName());
- JSC::RegExpConstructor* regExpConstructor = engine->globalObject()->regExpConstructor();
+ JSC::RegExpConstructor* regExpConstructor = engine->originalGlobalObject()->regExpConstructor();
int position;
int length;
regExpConstructor->performMatch(regexp->regExp(), childName, 0, position, length);
@@ -1591,6 +1595,8 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChildren(JSC::ExecState *e
static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncToString(JSC::ExecState *exec, JSC::JSObject*,
JSC::JSValue thisValue, const JSC::ArgList&)
{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ thisValue = engine->toUsableValue(thisValue);
if (!thisValue.isObject(&QScriptObject::info))
return JSC::jsUndefined();
QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(thisValue));
@@ -1771,10 +1777,11 @@ JSC::JSValue JSC_HOST_CALL QMetaObjectWrapperObject::call(
JSC::ExecState *exec, JSC::JSObject *callee,
JSC::JSValue thisValue, const JSC::ArgList &args)
{
+ QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
+ thisValue = eng_p->toUsableValue(thisValue);
if (!callee->isObject(&QMetaObjectWrapperObject::info))
return throwError(exec, JSC::TypeError, "callee is not a QMetaObject");
QMetaObjectWrapperObject *self = static_cast<QMetaObjectWrapperObject*>(callee);
- QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
JSC::ExecState *previousFrame = eng_p->currentFrame;
eng_p->currentFrame = exec;
JSC::JSValue result = self->execute(exec, args);
@@ -1832,6 +1839,8 @@ struct StaticQtMetaObject : public QObject
static JSC::JSValue JSC_HOST_CALL qmetaobjectProtoFuncClassName(
JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue thisValue, const JSC::ArgList&)
{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ thisValue = engine->toUsableValue(thisValue);
if (!thisValue.isObject(&QMetaObjectWrapperObject::info))
return throwError(exec, JSC::TypeError, "this object is not a QMetaObject");
const QMetaObject *meta = static_cast<QMetaObjectWrapperObject*>(JSC::asObject(thisValue))->value();
diff --git a/src/script/bridge/qscriptvariant.cpp b/src/script/bridge/qscriptvariant.cpp
index 46da70a..752dd09 100644
--- a/src/script/bridge/qscriptvariant.cpp
+++ b/src/script/bridge/qscriptvariant.cpp
@@ -13,6 +13,9 @@
#ifndef QT_NO_SCRIPT
+#include "../api/qscriptengine.h"
+#include "../api/qscriptengine_p.h"
+
#include "Error.h"
#include "PrototypeFunction.h"
#include "JSString.h"
@@ -28,6 +31,7 @@ namespace QScript
{
JSC::UString qtStringToJSCUString(const QString &str);
+QScriptEnginePrivate *scriptEngineFromExec(JSC::ExecState*);
QVariantDelegate::QVariantDelegate(const QVariant &value)
: m_value(value)
@@ -56,6 +60,8 @@ QScriptObjectDelegate::Type QVariantDelegate::type() const
static JSC::JSValue JSC_HOST_CALL variantProtoFuncToString(JSC::ExecState *exec, JSC::JSObject*,
JSC::JSValue thisValue, const JSC::ArgList&)
{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ thisValue = engine->toUsableValue(thisValue);
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();
@@ -69,6 +75,8 @@ static JSC::JSValue JSC_HOST_CALL variantProtoFuncToString(JSC::ExecState *exec,
static JSC::JSValue JSC_HOST_CALL variantProtoFuncValueOf(JSC::ExecState *exec, JSC::JSObject*,
JSC::JSValue thisValue, const JSC::ArgList&)
{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ thisValue = engine->toUsableValue(thisValue);
if (!thisValue.isObject(&QScriptObject::info))
return throwError(exec, JSC::TypeError);
QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(thisValue))->delegate();