summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@trolltech.com>2009-07-30 19:50:17 (GMT)
committerOlivier Goffart <ogoffart@trolltech.com>2009-07-31 14:11:29 (GMT)
commitbb1e71ac344b184d2ab13cd0ed7188eebb34aaf1 (patch)
treee2481d6ab859207c3cef2dd2822f9e0cb65da5cd
parentf6713c0e69d2b2b20da00e9a9a4e23a8f4f85c3d (diff)
downloadQt-bb1e71ac344b184d2ab13cd0ed7188eebb34aaf1.zip
Qt-bb1e71ac344b184d2ab13cd0ed7188eebb34aaf1.tar.gz
Qt-bb1e71ac344b184d2ab13cd0ed7188eebb34aaf1.tar.bz2
Small Refactoring of QScript
- Create a scope (activation object) for the native constructor in QScriptClass - put the isCalledasConstructor in the activation object (so i can clean up the QScriptContext - Remove the code duplication in all native functions. Aknoweldged-by: Kent
-rw-r--r--src/script/api/qscriptcontext.cpp18
-rw-r--r--src/script/api/qscriptcontext_p.h1
-rw-r--r--src/script/api/qscriptengine.cpp20
-rw-r--r--src/script/api/qscriptengine_p.h18
-rw-r--r--src/script/bridge/qscriptactivationobject.cpp3
-rw-r--r--src/script/bridge/qscriptactivationobject_p.h15
-rw-r--r--src/script/bridge/qscriptclassobject.cpp17
-rw-r--r--src/script/bridge/qscriptfunction.cpp43
8 files changed, 78 insertions, 57 deletions
diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp
index 15e4efe..4bdcc6a 100644
--- a/src/script/api/qscriptcontext.cpp
+++ b/src/script/api/qscriptcontext.cpp
@@ -168,7 +168,6 @@ JSC::UString qtStringToJSCUString(const QString &);
}
QScriptContextPrivate::QScriptContextPrivate()
- : calledAsConstructor(false)
{
}
@@ -281,8 +280,6 @@ QScriptValue QScriptContext::throwError(const QString &text)
*/
QScriptContext::~QScriptContext()
{
- delete d_ptr;
- d_ptr = 0;
}
/*!
@@ -366,7 +363,20 @@ QScriptValue QScriptContext::argumentsObject() const
bool QScriptContext::isCalledAsConstructor() const
{
Q_D(const QScriptContext);
- return d->calledAsConstructor;
+ //look up for the QScriptActivationObject and its calledAsConstructor flag.
+ JSC::ScopeChainNode *node = d->frame->scopeChain();
+ JSC::ScopeChainIterator it(node);
+ for (it = node->begin(); it != node->end(); ++it) {
+ if (!(*it)->isVariableObject()) {
+ if ((*it)->inherits(&QScript::QScriptActivationObject::info)) {
+ return static_cast<QScript::QScriptActivationObject *>(*it)->d_ptr()->calledAsConstructor;
+ }
+ //not a native function
+ //### we have no way to know if is is or not a constructor
+ return false;
+ }
+ }
+ return false;
}
/*!
diff --git a/src/script/api/qscriptcontext_p.h b/src/script/api/qscriptcontext_p.h
index 43efd06..25104a1 100644
--- a/src/script/api/qscriptcontext_p.h
+++ b/src/script/api/qscriptcontext_p.h
@@ -84,7 +84,6 @@ public:
static QScriptContextPrivate *get(QScriptContext *q);
JSC::ExecState *frame;
- bool calledAsConstructor;
QScriptEnginePrivate *engine;
};
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index 6bf7354..4fe8f76 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -871,6 +871,26 @@ JSC::JSValue stringProtoFuncArg(JSC::ExecState *exec, JSC::JSObject*, JSC::JSVal
return JSC::jsString(exec, qtStringToJSCUString(result));
}
+
+QScriptPushScopeHelper::QScriptPushScopeHelper(JSC::CallFrame *exec, bool calledAsConstructor)
+{
+ engine = scriptEngineFromExec(exec);
+ previousFrame = engine->currentFrame;
+ engine->currentFrame = exec;
+ QScriptActivationObject *scope = new (exec) QScriptActivationObject(exec);
+ scope->d_ptr()->calledAsConstructor = calledAsConstructor;
+ exec->setScopeChain(exec->scopeChain()->copy()->push(scope));
+}
+
+QScriptPushScopeHelper::~QScriptPushScopeHelper()
+{
+ JSC::CallFrame *exec = engine->currentFrame;
+ exec->setScopeChain(exec->scopeChain()->pop());
+ exec->scopeChain()->deref();
+ engine->currentFrame = previousFrame;
+ engine->releaseContextForFrame(exec);
+}
+
} // namespace QScript
namespace JSC {
diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h
index bc6acfa..ced49bb 100644
--- a/src/script/api/qscriptengine_p.h
+++ b/src/script/api/qscriptengine_p.h
@@ -234,6 +234,24 @@ public:
#endif
};
+namespace QScript
+{
+/*! \internal
+ Helper class to create QScriptActivationObject.
+ To be used on the stack
+*/
+class QScriptPushScopeHelper
+{
+ public:
+ QScriptPushScopeHelper(JSC::CallFrame *newFrame, bool calledAsConstructor = false);
+ ~QScriptPushScopeHelper();
+ private:
+ QScriptEnginePrivate *engine;
+ JSC::CallFrame *previousFrame;
+};
+} // namespace QScript
+
+
QT_END_NAMESPACE
#endif // QT_NO_SCRIPT
diff --git a/src/script/bridge/qscriptactivationobject.cpp b/src/script/bridge/qscriptactivationobject.cpp
index 68cbe8f..0e3b37a 100644
--- a/src/script/bridge/qscriptactivationobject.cpp
+++ b/src/script/bridge/qscriptactivationobject.cpp
@@ -61,6 +61,9 @@ QT_BEGIN_NAMESPACE
namespace QScript
{
+
+const JSC::ClassInfo QScriptActivationObject::info = { "QScriptActivationObject", 0, 0, 0 };
+
QScriptActivationObject::QScriptActivationObject(JSC::ExecState *callFrame)
: JSC::JSVariableObject(callFrame->globalData().activationStructure, new QScriptActivationObjectData(callFrame->registers()))
{
diff --git a/src/script/bridge/qscriptactivationobject_p.h b/src/script/bridge/qscriptactivationobject_p.h
index 633cbf6..4e277dc 100644
--- a/src/script/bridge/qscriptactivationobject_p.h
+++ b/src/script/bridge/qscriptactivationobject_p.h
@@ -61,8 +61,6 @@
QT_BEGIN_NAMESPACE
-class QScriptClass;
-
namespace QScript
{
@@ -72,15 +70,22 @@ public:
virtual ~QScriptActivationObject();
virtual bool isDynamicScope() const { return true; }
virtual void putWithAttributes(JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes);
-private:
+
+ virtual const JSC::ClassInfo* classInfo() const { return &info; }
+ static const JSC::ClassInfo info;
+
struct QScriptActivationObjectData : public JSVariableObjectData {
QScriptActivationObjectData(JSC::Register* registers)
- : JSVariableObjectData(&symbolTable, registers)
+ : JSVariableObjectData(&symbolTable, registers), calledAsConstructor(false)
{ }
JSC::SymbolTable symbolTable;
+
+ //specifies if the context of this activation object is called as constructor
+ bool calledAsConstructor;
};
-};
+ QScriptActivationObjectData *d_ptr() const { return static_cast<QScriptActivationObjectData *>(d); }
+};
} // namespace QScript
diff --git a/src/script/bridge/qscriptclassobject.cpp b/src/script/bridge/qscriptclassobject.cpp
index 2a26049..d07fa83 100644
--- a/src/script/bridge/qscriptclassobject.cpp
+++ b/src/script/bridge/qscriptclassobject.cpp
@@ -213,15 +213,15 @@ JSC::JSValue JSC_HOST_CALL ClassObjectDelegate::call(JSC::ExecState *exec, JSC::
QScriptObjectDelegate *delegate = obj->delegate();
if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject))
return JSC::throwError(exec, JSC::TypeError, "callee is not a ClassObject object");
+
+ //We might have nested eval inside our function so we should create another scope
+ QScriptPushScopeHelper scope(exec, true);
+
QScriptClass *scriptClass = static_cast<ClassObjectDelegate*>(delegate)->scriptClass();
QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
- JSC::ExecState *previousFrame = eng_p->currentFrame;
QScriptContext *ctx = eng_p->contextForFrame(exec);
- eng_p->currentFrame = exec;
QScriptValue scriptObject = eng_p->scriptValueFromJSCValue(obj);
QVariant result = scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx));
- eng_p->currentFrame = previousFrame;
- eng_p->releaseContextForFrame(exec);
return eng_p->jscValueFromVariant(result);
}
@@ -240,17 +240,16 @@ JSC::JSObject* ClassObjectDelegate::construct(JSC::ExecState *exec, JSC::JSObjec
QScriptObject *obj = static_cast<QScriptObject*>(callee);
QScriptObjectDelegate *delegate = obj->delegate();
QScriptClass *scriptClass = static_cast<ClassObjectDelegate*>(delegate)->scriptClass();
+
+ //We might have nested eval inside our function so we should create another scope
+ QScriptPushScopeHelper scope(exec, true);
+
QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
- JSC::ExecState *previousFrame = eng_p->currentFrame;
QScriptContext *ctx = eng_p->contextForFrame(exec);
- QScriptContextPrivate::get(ctx)->calledAsConstructor = true;
- eng_p->currentFrame = exec;
QScriptValue defaultObject = ctx->thisObject();
QScriptValue result = qvariant_cast<QScriptValue>(scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx)));
if (!result.isObject())
result = defaultObject;
- eng_p->currentFrame = previousFrame;
- eng_p->releaseContextForFrame(exec);
return JSC::asObject(eng_p->scriptValueToJSCValue(result));
}
diff --git a/src/script/bridge/qscriptfunction.cpp b/src/script/bridge/qscriptfunction.cpp
index 309315c..d51147a 100644
--- a/src/script/bridge/qscriptfunction.cpp
+++ b/src/script/bridge/qscriptfunction.cpp
@@ -86,23 +86,15 @@ JSC::JSValue FunctionWrapper::proxyCall(JSC::ExecState *exec, JSC::JSObject *cal
{
FunctionWrapper *self = static_cast<FunctionWrapper*>(callee);
QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(self->data->engine);
- 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) QScriptActivationObject(exec);
- exec->setScopeChain(exec->scopeChain()->copy()->push(scope));
+ QScriptPushScopeHelper scope(exec);
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);
}
@@ -111,25 +103,16 @@ JSC::JSObject* FunctionWrapper::proxyConstruct(JSC::ExecState *exec, JSC::JSObje
{
FunctionWrapper *self = static_cast<FunctionWrapper*>(callee);
QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(self->data->engine);
- JSC::ExecState *previousFrame = eng_p->currentFrame;
QScriptContext *ctx = eng_p->contextForFrame(exec);
- QScriptContextPrivate::get(ctx)->calledAsConstructor = true;
- eng_p->currentFrame = exec;
//We might have nested eval inside our function so we should create another scope
- JSC::JSObject* scope = new (exec) QScriptActivationObject(exec);
- exec->setScopeChain(exec->scopeChain()->copy()->push(scope));
+ QScriptPushScopeHelper scope(exec, true);
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));
}
@@ -159,21 +142,13 @@ JSC::JSValue FunctionWithArgWrapper::proxyCall(JSC::ExecState *exec, JSC::JSObje
{
FunctionWithArgWrapper *self = static_cast<FunctionWithArgWrapper*>(callee);
QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(self->data->engine);
- 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) QScriptActivationObject(exec);
- exec->setScopeChain(exec->scopeChain()->copy()->push(scope));
-
- QScriptValue result = self->data->function(ctx, self->data->engine, self->data->arg);
+ QScriptPushScopeHelper scope(exec);
- exec->setScopeChain(exec->scopeChain()->pop());
- exec->scopeChain()->deref();
+ QScriptValue result = self->data->function(eng_p->contextForFrame(exec), self->data->engine, self->data->arg);
- eng_p->currentFrame = previousFrame;
- eng_p->releaseContextForFrame(exec);
return eng_p->scriptValueToJSCValue(result);
}
@@ -182,25 +157,17 @@ JSC::JSObject* FunctionWithArgWrapper::proxyConstruct(JSC::ExecState *exec, JSC:
{
FunctionWithArgWrapper *self = static_cast<FunctionWithArgWrapper*>(callee);
QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(self->data->engine);
- JSC::ExecState *previousFrame = eng_p->currentFrame;
QScriptContext *ctx = eng_p->contextForFrame(exec);
- QScriptContextPrivate::get(ctx)->calledAsConstructor = true;
- eng_p->currentFrame = exec;
//We might have nested eval inside our function so we should create another scope
- JSC::JSObject* scope = new (exec) QScriptActivationObject(exec);
- exec->setScopeChain(exec->scopeChain()->copy()->push(scope));
+ QScriptPushScopeHelper scope(exec, true);
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));
}