diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/script/api/qscriptcontext.cpp | 18 | ||||
-rw-r--r-- | src/script/api/qscriptcontext_p.h | 1 | ||||
-rw-r--r-- | src/script/api/qscriptengine.cpp | 20 | ||||
-rw-r--r-- | src/script/api/qscriptengine_p.h | 18 | ||||
-rw-r--r-- | src/script/bridge/qscriptactivationobject.cpp | 3 | ||||
-rw-r--r-- | src/script/bridge/qscriptactivationobject_p.h | 15 | ||||
-rw-r--r-- | src/script/bridge/qscriptclassobject.cpp | 17 | ||||
-rw-r--r-- | src/script/bridge/qscriptfunction.cpp | 43 |
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)); } |