From 70f320f661a0241fcb5fc85f5b9df8e565f5f7e0 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Mon, 10 Aug 2009 14:38:22 +0200 Subject: finish implementation of QScriptEngine::importExtension() Added the properties to the activation object: __extension__, __setupPackage__ and __postInit__. --- src/script/api/qscriptengine.cpp | 49 +++++++++++++------------- tests/auto/qscriptengine/tst_qscriptengine.cpp | 4 +-- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index fa6e8dd..f84e36e 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -777,6 +777,25 @@ JSC::JSValue stringProtoFuncArg(JSC::ExecState *exec, JSC::JSObject*, JSC::JSVal } +#if !defined(QT_NO_QOBJECT) && !defined(QT_NO_LIBRARY) +static QScriptValue __setupPackage__(QScriptContext *ctx, QScriptEngine *eng) +{ + QString path = ctx->argument(0).toString(); + QStringList components = path.split(QLatin1Char('.')); + QScriptValue o = eng->globalObject(); + for (int i = 0; i < components.count(); ++i) { + QString name = components.at(i); + QScriptValue oo = o.property(name); + if (!oo.isValid()) { + oo = eng->newObject(); + o.setProperty(name, oo); + } + o = oo; + } + return o; +} +#endif + QScriptPushScopeHelper::QScriptPushScopeHelper(JSC::CallFrame *exec, bool calledAsConstructor) { engine = scriptEngineFromExec(exec); @@ -1024,7 +1043,6 @@ QScriptContext *QScriptEnginePrivate::contextForFrame(JSC::ExecState *frame) return reinterpret_cast(frame); } - JSC::JSGlobalObject *QScriptEnginePrivate::originalGlobalObject() const { return globalData->head; @@ -2937,27 +2955,11 @@ QScriptValue QScriptEngine::importExtension(const QString &extension) // initialize the extension in a new context QScriptContext *ctx = pushContext(); ctx->setThisObject(globalObject()); -#if 0 // ### implement me - ctx->setActivationObject(newActivationObject()); - QScriptObject *activation_data = ctx_p->m_activation.m_object_value; - activation_data->m_scope = globalObject(); - - activation_data->m_members.resize(4); - activation_data->m_values.resize(4); - activation_data->m_members[0].object( - nameId(QLatin1String("__extension__")), 0, - QScriptValue::ReadOnly | QScriptValue::Undeletable); - activation_data->m_values[0] = QScriptValueImpl(this, ext); - activation_data->m_members[1].object( - nameId(QLatin1String("__setupPackage__")), 1, 0); - activation_data->m_values[1] = createFunction(__setupPackage__, 0, 0); - activation_data->m_members[2].object( - nameId(QLatin1String("__all__")), 2, 0); - activation_data->m_values[2] = undefinedValue(); - activation_data->m_members[3].object( - nameId(QLatin1String("__postInit__")), 3, 0); - activation_data->m_values[3] = undefinedValue(); -#endif + ctx->activationObject().setProperty(QLatin1String("__extension__"), ext, + QScriptValue::ReadOnly | QScriptValue::Undeletable); + ctx->activationObject().setProperty(QLatin1String("__setupPackage__"), + newFunction(QScript::__setupPackage__)); + ctx->activationObject().setProperty(QLatin1String("__postInit__"), QScriptValue(QScriptValue::UndefinedValue)); // the script is evaluated first if (!initjsContents.isEmpty()) { @@ -2981,8 +2983,7 @@ QScriptValue QScriptEngine::importExtension(const QString &extension) } // if the __postInit__ function has been set, we call it - // ### enable once activationObject() works - QScriptValue postInit; // = ctx->activationObject().property(QLatin1String("__postInit__")); + QScriptValue postInit = ctx->activationObject().property(QLatin1String("__postInit__")); if (postInit.isFunction()) { postInit.call(globalObject()); if (hasUncaughtException()) { diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index 538834b..e0dd173 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -1783,7 +1783,6 @@ void tst_QScriptEngine::importExtension() for (int x = 0; x < 2; ++x) { QCOMPARE(eng.globalObject().property("com").isValid(), x == 1); QScriptValue ret = eng.importExtension("com.trolltech"); - QEXPECT_FAIL("", "", Abort); QCOMPARE(eng.hasUncaughtException(), false); QCOMPARE(ret.isUndefined(), true); @@ -1840,9 +1839,10 @@ void tst_QScriptEngine::importExtension() QVERIFY(eng.importedExtensions().isEmpty()); QScriptValue ret = eng.importExtension("com.trolltech.syntaxerror"); QVERIFY(eng.hasUncaughtException()); + QEXPECT_FAIL("", "JSC throws syntax error eagerly", Continue); QCOMPARE(eng.uncaughtExceptionLineNumber(), 4); QVERIFY(ret.isError()); - QCOMPARE(ret.property("message").toString(), QLatin1String("invalid assignment lvalue")); + QCOMPARE(ret.property("message").toString(), QLatin1String("Parse error")); } QStringList imp = eng.importedExtensions(); QCOMPARE(imp.size(), 2); -- cgit v0.12 From 400d4cf8aac6d22bf8992bea8e20db91a14469ae Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Mon, 10 Aug 2009 15:00:16 +0200 Subject: cleanup (hide the use of reinterpret_cast) Introduce a frameForContext() function so we don't have to cast all over the place. --- src/script/api/qscriptcontext.cpp | 40 +++++++++++++++++------------------ src/script/api/qscriptcontextinfo.cpp | 4 +++- src/script/api/qscriptengine.cpp | 11 +++++++++- src/script/api/qscriptengine_p.h | 5 +++-- 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp index 66d4c3e..0d2f20c 100644 --- a/src/script/api/qscriptcontext.cpp +++ b/src/script/api/qscriptcontext.cpp @@ -177,7 +177,7 @@ QScriptContext::QScriptContext() */ QScriptValue QScriptContext::throwValue(const QScriptValue &value) { - JSC::CallFrame *frame = reinterpret_cast(this); + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); JSC::JSValue jscValue = QScript::scriptEngineFromExec(frame)->scriptValueToJSCValue(value); frame->setException(jscValue); return value; @@ -199,7 +199,7 @@ QScriptValue QScriptContext::throwValue(const QScriptValue &value) */ QScriptValue QScriptContext::throwError(Error error, const QString &text) { - JSC::CallFrame *frame = reinterpret_cast(this); + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); JSC::ErrorType jscError = JSC::GeneralError; switch (error) { case UnknownError: @@ -234,7 +234,7 @@ QScriptValue QScriptContext::throwError(Error error, const QString &text) */ QScriptValue QScriptContext::throwError(const QString &text) { - JSC::CallFrame *frame = reinterpret_cast(this); + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); JSC::JSObject *result = JSC::throwError(frame, JSC::GeneralError, QScript::qtStringToJSCUString(text)); return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result); } @@ -253,7 +253,7 @@ QScriptContext::~QScriptContext() */ QScriptEngine *QScriptContext::engine() const { - const JSC::CallFrame *frame = reinterpret_cast(this); + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); return QScriptEnginePrivate::get(QScript::scriptEngineFromExec(frame)); } @@ -267,7 +267,7 @@ QScriptEngine *QScriptContext::engine() const */ QScriptValue QScriptContext::argument(int index) const { - JSC::CallFrame *frame = const_cast(reinterpret_cast(this)); + JSC::CallFrame *frame = const_cast(QScriptEnginePrivate::frameForContext(this)); if (index < 0) return QScriptValue(); if (index >= argumentCount()) @@ -284,7 +284,7 @@ QScriptValue QScriptContext::argument(int index) const */ QScriptValue QScriptContext::callee() const { - const JSC::CallFrame *frame = reinterpret_cast(this); + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(frame->callee()); } @@ -305,7 +305,7 @@ QScriptValue QScriptContext::callee() const */ QScriptValue QScriptContext::argumentsObject() const { - JSC::CallFrame *frame = const_cast(reinterpret_cast(this)); + JSC::CallFrame *frame = const_cast(QScriptEnginePrivate::frameForContext(this)); if (frame == frame->lexicalGlobalObject()->globalExec()) { //global context doesn't have any argument, return an empty object return QScriptEnginePrivate::get(QScript::scriptEngineFromExec(frame))->newObject(); @@ -328,7 +328,7 @@ QScriptValue QScriptContext::argumentsObject() const */ bool QScriptContext::isCalledAsConstructor() const { - JSC::CallFrame *frame = reinterpret_cast(const_cast(this)); + JSC::CallFrame *frame = const_cast(QScriptEnginePrivate::frameForContext(this)); //For native functions, look up for the QScriptActivationObject and its calledAsConstructor flag. JSC::ScopeChainNode *node = frame->scopeChain(); @@ -349,7 +349,7 @@ bool QScriptContext::isCalledAsConstructor() const if (!returnPC) return false; - JSC::CallFrame *callerFrame = reinterpret_cast(parentContext()); + JSC::CallFrame *callerFrame = QScriptEnginePrivate::frameForContext(parentContext()); if (!callerFrame) return false; @@ -369,7 +369,7 @@ bool QScriptContext::isCalledAsConstructor() const */ QScriptContext *QScriptContext::parentContext() const { - const JSC::CallFrame *frame = reinterpret_cast(this); + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); JSC::CallFrame *callerFrame = frame->callerFrame(); if (callerFrame == (JSC::CallFrame*)(1)) // ### CallFrame::noCaller() is private return 0; @@ -388,7 +388,7 @@ QScriptContext *QScriptContext::parentContext() const */ int QScriptContext::argumentCount() const { - const JSC::CallFrame *frame = reinterpret_cast(this); + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); int argc = frame->argumentCount(); if (argc != 0) --argc; // -1 due to "this" @@ -409,7 +409,7 @@ QScriptValue QScriptContext::returnValue() const */ void QScriptContext::setReturnValue(const QScriptValue &result) { - JSC::CallFrame *frame = reinterpret_cast(this); + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); JSC::CallFrame *callerFrame = frame->callerFrame(); if (!callerFrame->codeBlock()) return; @@ -427,7 +427,7 @@ void QScriptContext::setReturnValue(const QScriptValue &result) */ QScriptValue QScriptContext::activationObject() const { - JSC::CallFrame *frame = const_cast(reinterpret_cast(this)); + JSC::CallFrame *frame = const_cast(QScriptEnginePrivate::frameForContext(this)); // ### this is still a bit shaky // if properties of the activation are accessed after this context is // popped, we CRASH. @@ -468,7 +468,7 @@ void QScriptContext::setActivationObject(const QScriptValue &activation) { if (!activation.isObject()) return; - JSC::CallFrame *frame = reinterpret_cast(this); + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); JSC::JSObject *object = JSC::asObject(engine->scriptValueToJSCValue(activation)); if (!object->isVariableObject()) { @@ -484,7 +484,7 @@ void QScriptContext::setActivationObject(const QScriptValue &activation) */ QScriptValue QScriptContext::thisObject() const { - JSC::CallFrame *frame = const_cast(reinterpret_cast(this)); + JSC::CallFrame *frame = const_cast(QScriptEnginePrivate::frameForContext(this)); QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); JSC::JSValue result = engine->thisForContext(frame); if (!result || result.isNull()) @@ -500,7 +500,7 @@ QScriptValue QScriptContext::thisObject() const */ void QScriptContext::setThisObject(const QScriptValue &thisObject) { - JSC::CallFrame *frame = reinterpret_cast(this); + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); if (!thisObject.isObject()) return; if (thisObject.engine() != engine()) { @@ -528,7 +528,7 @@ void QScriptContext::setThisObject(const QScriptValue &thisObject) */ QScriptContext::ExecutionState QScriptContext::state() const { - const JSC::CallFrame *frame = reinterpret_cast(this); + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); if (frame->hadException()) return QScriptContext::ExceptionState; return QScriptContext::NormalState; @@ -617,7 +617,7 @@ QString QScriptContext::toString() const */ QScriptValueList QScriptContext::scopeChain() const { - const JSC::CallFrame *frame = reinterpret_cast(this); + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); QScriptValueList result; JSC::ScopeChainNode *node = frame->scopeChain(); JSC::ScopeChainIterator it(node); @@ -638,7 +638,7 @@ void QScriptContext::pushScope(const QScriptValue &object) { if (!object.isObject()) return; - JSC::CallFrame *frame = reinterpret_cast(this); + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); JSC::JSValue jscObject = QScript::scriptEngineFromExec(frame)->scriptValueToJSCValue(object); frame->setScopeChain(frame->scopeChain()->push(JSC::asObject(jscObject))); } @@ -655,7 +655,7 @@ void QScriptContext::pushScope(const QScriptValue &object) */ QScriptValue QScriptContext::popScope() { - JSC::CallFrame *frame = reinterpret_cast(this); + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); QScriptValue result = QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(frame->scopeChain()->object); frame->setScopeChain(frame->scopeChain()->pop()); return result; diff --git a/src/script/api/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp index 98d0d52..52776e2 100644 --- a/src/script/api/qscriptcontextinfo.cpp +++ b/src/script/api/qscriptcontextinfo.cpp @@ -42,6 +42,8 @@ #include "qscriptcontextinfo.h" #include "qscriptcontext_p.h" +#include "qscriptengine.h" +#include "qscriptengine_p.h" #include "../bridge/qscriptqobject_p.h" #include #include @@ -156,7 +158,7 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte lineNumber = -1; columnNumber = -1; - const JSC::ExecState *frame = reinterpret_cast(context); + const JSC::ExecState *frame = QScriptEnginePrivate::frameForContext(context); JSC::JSObject *callee = frame->callee(); if (callee && callee->isObject(&JSC::InternalFunction::info)) functionName = QScript::qtStringFromJSCUString(JSC::asInternalFunction(callee)->name(&frame->globalData())); diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index f84e36e..3ae1502 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -863,7 +863,6 @@ QScriptEnginePrivate::~QScriptEnginePrivate() detachAllRegisteredScriptValues(); qDeleteAll(m_qobjectData); qDeleteAll(m_typeInfos); - qDeleteAll(contextForFrameHash); JSC::JSLock lock(false); globalData->heap.destroy(); globalData->deref(); @@ -1043,6 +1042,16 @@ QScriptContext *QScriptEnginePrivate::contextForFrame(JSC::ExecState *frame) return reinterpret_cast(frame); } +JSC::ExecState *QScriptEnginePrivate::frameForContext(QScriptContext *context) +{ + return reinterpret_cast(context); +} + +const JSC::ExecState *QScriptEnginePrivate::frameForContext(const QScriptContext *context) +{ + return reinterpret_cast(context); +} + JSC::JSGlobalObject *QScriptEnginePrivate::originalGlobalObject() const { return globalData->head; diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index 20b2616..472b0da 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -143,7 +143,9 @@ public: JSC::JSValue defaultPrototype(int metaTypeId) const; void setDefaultPrototype(int metaTypeId, JSC::JSValue prototype); - QScriptContext *contextForFrame(JSC::ExecState *frame); + static QScriptContext *contextForFrame(JSC::ExecState *frame); + static JSC::ExecState *frameForContext(QScriptContext *context); + static const JSC::ExecState *frameForContext(const QScriptContext *context); JSC::JSGlobalObject *originalGlobalObject() const; JSC::JSObject *getOriginalGlobalObjectProxy(); @@ -207,7 +209,6 @@ public: JSC::JSGlobalData *globalData; JSC::JSObject *originalGlobalObjectProxy; JSC::ExecState *currentFrame; - QHash contextForFrameHash; WTF::RefPtr scriptObjectStructure; -- cgit v0.12