diff options
author | Kent Hansen <khansen@trolltech.com> | 2009-07-27 17:42:26 (GMT) |
---|---|---|
committer | Kent Hansen <khansen@trolltech.com> | 2009-07-27 18:01:19 (GMT) |
commit | 8923339fa086cbf6adc404fb18dcda6c1206985d (patch) | |
tree | 13ad42fc95c63e9f49a971a42fab7ddb1c6af61c /src/script/bridge | |
parent | 117802b5ca71478d01bb79f88aa3596729b0a590 (diff) | |
download | Qt-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/script/bridge')
-rw-r--r-- | src/script/bridge/qscriptqobject.cpp | 25 | ||||
-rw-r--r-- | src/script/bridge/qscriptvariant.cpp | 8 |
2 files changed, 25 insertions, 8 deletions
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(); |