summaryrefslogtreecommitdiffstats
path: root/src/script/bridge
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@trolltech.com>2009-07-29 07:51:07 (GMT)
committerOlivier Goffart <ogoffart@trolltech.com>2009-07-29 09:16:18 (GMT)
commit538153994cacc4613aef1eb8ef77e501be7f5a88 (patch)
tree5b1ae7732aa02e50d85a9f10280d3335f98e673b /src/script/bridge
parent9e4aa947217d92c51d09a6adaddaf88829d42f89 (diff)
downloadQt-538153994cacc4613aef1eb8ef77e501be7f5a88.zip
Qt-538153994cacc4613aef1eb8ef77e501be7f5a88.tar.gz
Qt-538153994cacc4613aef1eb8ef77e501be7f5a88.tar.bz2
Enter a scope when enterning a native function.
so native function that would call engine->evaluate("var b = 'foo'); would not change the global object. The change in qscriptengine.cpp makes sure that the correct scope is used for the execution of QScriptEngine::evaluate. The changes in qscriptfunction.cpp push a new scope for native function calls. We might want to move that into QScriptContext later Reviewed-by: Kent Hansen
Diffstat (limited to 'src/script/bridge')
-rw-r--r--src/script/bridge/qscriptfunction.cpp69
1 files changed, 68 insertions, 1 deletions
diff --git a/src/script/bridge/qscriptfunction.cpp b/src/script/bridge/qscriptfunction.cpp
index ee5c9c3..af70523 100644
--- a/src/script/bridge/qscriptfunction.cpp
+++ b/src/script/bridge/qscriptfunction.cpp
@@ -19,8 +19,8 @@
#include "JSGlobalObject.h"
-QT_BEGIN_NAMESPACE
+QT_BEGIN_NAMESPACE
namespace JSC
{
ASSERT_CLASS_FITS_IN_CELL(QScript::FunctionWrapper);
@@ -30,6 +30,37 @@ ASSERT_CLASS_FITS_IN_CELL(QScript::FunctionWithArgWrapper);
namespace QScript
{
+
+class QScriptActivation : public JSC::JSVariableObject {
+public:
+ QScriptActivation(JSC::ExecState *callFrame)
+ : JSC::JSVariableObject(callFrame->globalData().activationStructure, new QScriptActivationData(callFrame->registers()))
+ {}
+ virtual ~QScriptActivation() { delete d; }
+ virtual bool isDynamicScope() const {return true; }
+// virtual bool isActivationObject() const { return true; }
+
+ virtual void putWithAttributes(JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes)
+ {
+ if (symbolTablePutWithAttributes(propertyName, value, attributes))
+ return;
+
+ JSC::PutPropertySlot slot;
+ JSObject::putWithAttributes(exec, propertyName, value, attributes, true, slot);
+ }
+
+
+private:
+ struct QScriptActivationData : public JSVariableObjectData {
+ QScriptActivationData(JSC::Register* registers)
+ : JSVariableObjectData(&symbolTable, registers)
+ { }
+ JSC::SymbolTable symbolTable;
+ };
+};
+
+
+
FunctionWrapper::FunctionWrapper(QScriptEngine *engine, int length, const JSC::Identifier &name,
QScriptEngine::FunctionSignature function)
: JSC::PrototypeFunction(QScriptEnginePrivate::get(engine)->globalExec(),
@@ -58,9 +89,18 @@ JSC::JSValue FunctionWrapper::proxyCall(JSC::ExecState *exec, JSC::JSObject *cal
JSC::ExecState *previousFrame = eng_p->currentFrame;
eng_p->currentFrame = exec;
QScriptContext *ctx = eng_p->contextForFrame(exec);
+
+ //We might have nested eval inside our function so we should create another scope
+ JSC::JSObject* scope = new (exec) QScriptActivation(exec);
+ exec->setScopeChain(exec->scopeChain()->copy()->push(scope));
+
QScriptValue result = self->data->function(ctx, self->data->engine);
if (!result.isValid())
result = QScriptValue(QScriptValue::UndefinedValue);
+
+ exec->setScopeChain(exec->scopeChain()->pop());
+ exec->scopeChain()->deref();
+
eng_p->currentFrame = previousFrame;
eng_p->releaseContextForFrame(exec);
return eng_p->scriptValueToJSCValue(result);
@@ -74,10 +114,19 @@ JSC::JSObject* FunctionWrapper::proxyConstruct(JSC::ExecState *exec, JSC::JSObje
JSC::ExecState *previousFrame = eng_p->currentFrame;
QScriptContext *ctx = eng_p->contextForFrame(exec);
eng_p->currentFrame = exec;
+
+ //We might have nested eval inside our function so we should create another scope
+ JSC::JSObject* scope = new (exec) QScriptActivation(exec);
+ exec->setScopeChain(exec->scopeChain()->copy()->push(scope));
+
QScriptValue defaultObject = ctx->thisObject();
QScriptValue result = self->data->function(ctx, self->data->engine);
if (!result.isObject())
result = defaultObject;
+
+ exec->setScopeChain(exec->scopeChain()->pop());
+ exec->scopeChain()->deref();
+
eng_p->currentFrame = previousFrame;
eng_p->releaseContextForFrame(exec);
return JSC::asObject(eng_p->scriptValueToJSCValue(result));
@@ -112,7 +161,16 @@ JSC::JSValue FunctionWithArgWrapper::proxyCall(JSC::ExecState *exec, JSC::JSObje
JSC::ExecState *previousFrame = eng_p->currentFrame;
QScriptContext *ctx = eng_p->contextForFrame(exec);
eng_p->currentFrame = exec;
+
+ //We might have nested eval inside our function so we should create another scope
+ JSC::JSObject* scope = new (exec) QScriptActivation(exec);
+ exec->setScopeChain(exec->scopeChain()->copy()->push(scope));
+
QScriptValue result = self->data->function(ctx, self->data->engine, self->data->arg);
+
+ exec->setScopeChain(exec->scopeChain()->pop());
+ exec->scopeChain()->deref();
+
eng_p->currentFrame = previousFrame;
eng_p->releaseContextForFrame(exec);
return eng_p->scriptValueToJSCValue(result);
@@ -126,10 +184,19 @@ JSC::JSObject* FunctionWithArgWrapper::proxyConstruct(JSC::ExecState *exec, JSC:
JSC::ExecState *previousFrame = eng_p->currentFrame;
QScriptContext *ctx = eng_p->contextForFrame(exec);
eng_p->currentFrame = exec;
+
+ //We might have nested eval inside our function so we should create another scope
+ JSC::JSObject* scope = new (exec) QScriptActivation(exec);
+ exec->setScopeChain(exec->scopeChain()->copy()->push(scope));
+
QScriptValue defaultObject = ctx->thisObject();
QScriptValue result = self->data->function(ctx, self->data->engine, self->data->arg);
if (!result.isObject())
result = defaultObject;
+
+ exec->setScopeChain(exec->scopeChain()->pop());
+ exec->scopeChain()->deref();
+
eng_p->currentFrame = previousFrame;
eng_p->releaseContextForFrame(exec);
return JSC::asObject(eng_p->scriptValueToJSCValue(result));