summaryrefslogtreecommitdiffstats
path: root/src/script
diff options
context:
space:
mode:
authorKent Hansen <khansen@trolltech.com>2009-08-11 12:03:28 (GMT)
committerKent Hansen <khansen@trolltech.com>2009-08-11 12:03:28 (GMT)
commit73a86eaf8136959cbac60af540ee8faadf454015 (patch)
tree28d107e106c4b00033bba2eadd325a7fef1569b4 /src/script
parentf2f338a922d20ad36c9849f5ea3208a8c4f1674a (diff)
downloadQt-73a86eaf8136959cbac60af540ee8faadf454015.zip
Qt-73a86eaf8136959cbac60af540ee8faadf454015.tar.gz
Qt-73a86eaf8136959cbac60af540ee8faadf454015.tar.bz2
make it possible to pop all items in a scope chain and then push to it
A lot of the JSC::ExecState functions rely on scopeChain() not being 0. This means we shouldn't pop the scope chain if doing so would make it empty; otherwise when you call e.g. pushScope() or evaluate(), you will crash. So instead of popping the chain completely, we now set the sole scope chain item's object pointer to 0 and add appropriate checks elsewhere. A second issue, not solved in this commit, is that JSC expects the Global Object to always be the last item in every scope chain. If it's not, you will crash.
Diffstat (limited to 'src/script')
-rw-r--r--src/script/api/qscriptcontext.cpp32
1 files changed, 24 insertions, 8 deletions
diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp
index f4b8af6..25763f9 100644
--- a/src/script/api/qscriptcontext.cpp
+++ b/src/script/api/qscriptcontext.cpp
@@ -333,7 +333,7 @@ bool QScriptContext::isCalledAsConstructor() const
JSC::ScopeChainNode *node = frame->scopeChain();
JSC::ScopeChainIterator it(node);
for (it = node->begin(); it != node->end(); ++it) {
- if ((*it)->isVariableObject()) {
+ if ((*it) && (*it)->isVariableObject()) {
if ((*it)->inherits(&QScript::QScriptActivationObject::info)) {
return static_cast<QScript::QScriptActivationObject *>(*it)->d_ptr()->calledAsConstructor;
}
@@ -436,7 +436,7 @@ QScriptValue QScriptContext::activationObject() const
JSC::ScopeChainNode *node = frame->scopeChain();
JSC::ScopeChainIterator it(node);
for (it = node->begin(); it != node->end(); ++it) {
- if ((*it)->isVariableObject()) {
+ if ((*it) && (*it)->isVariableObject()) {
result = *it;
break;
}
@@ -484,7 +484,7 @@ void QScriptContext::setActivationObject(const QScriptValue &activation)
// replace the first activation object in the scope chain
JSC::ScopeChainNode *node = frame->scopeChain();
while (node != 0) {
- if (node->object->isVariableObject()) {
+ if (node->object && node->object->isVariableObject()) {
node->object = object;
break;
}
@@ -631,11 +631,14 @@ QString QScriptContext::toString() const
QScriptValueList QScriptContext::scopeChain() const
{
const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
QScriptValueList result;
JSC::ScopeChainNode *node = frame->scopeChain();
JSC::ScopeChainIterator it(node);
- for (it = node->begin(); it != node->end(); ++it)
- result.append(QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(*it));
+ for (it = node->begin(); it != node->end(); ++it) {
+ if (*it)
+ result.append(engine->scriptValueFromJSCValue(*it));
+ }
return result;
}
@@ -659,7 +662,12 @@ void QScriptContext::pushScope(const QScriptValue &object)
}
JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
JSC::JSValue jscObject = QScript::scriptEngineFromExec(frame)->scriptValueToJSCValue(object);
- frame->setScopeChain(frame->scopeChain()->push(JSC::asObject(jscObject)));
+ JSC::ScopeChainNode *scope = frame->scopeChain();
+ Q_ASSERT(scope != 0);
+ if (!scope->object) // pushing to an "empty" chain
+ scope->object = JSC::asObject(jscObject);
+ else
+ frame->setScopeChain(scope->push(JSC::asObject(jscObject)));
}
/*!
@@ -675,8 +683,16 @@ void QScriptContext::pushScope(const QScriptValue &object)
QScriptValue QScriptContext::popScope()
{
JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
- QScriptValue result = QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(frame->scopeChain()->object);
- frame->setScopeChain(frame->scopeChain()->pop());
+ JSC::ScopeChainNode *scope = frame->scopeChain();
+ Q_ASSERT(scope != 0);
+ QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
+ QScriptValue result = engine->scriptValueFromJSCValue(scope->object);
+ if (!scope->next) {
+ // We cannot have a null scope chain, so just zap the object pointer.
+ scope->object = 0;
+ } else {
+ frame->setScopeChain(scope->pop());
+ }
return result;
}