summaryrefslogtreecommitdiffstats
path: root/src/script
diff options
context:
space:
mode:
Diffstat (limited to 'src/script')
-rw-r--r--src/script/api/qscriptengine.cpp224
-rw-r--r--src/script/api/qscriptengine.h27
-rw-r--r--src/script/api/qscriptengine_p.h2
-rw-r--r--src/script/api/qscriptvalue.cpp5
-rw-r--r--src/script/bridge/bridge.pri8
-rw-r--r--src/script/bridge/qscriptdeclarativeclass.cpp316
-rw-r--r--src/script/bridge/qscriptdeclarativeclass_p.h126
-rw-r--r--src/script/bridge/qscriptdeclarativeobject.cpp190
-rw-r--r--src/script/bridge/qscriptdeclarativeobject_p.h111
-rw-r--r--src/script/bridge/qscriptobject_p.h3
10 files changed, 1006 insertions, 6 deletions
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index b1f36be..029d3a5 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -340,6 +340,25 @@ public:
JSC::JSValue prototype;
};
+class QScriptProgramPrivate
+{
+public:
+ QScriptProgramPrivate() : refcount(1), hasException(false) { }
+ ~QScriptProgramPrivate() { if (evalNode) evalNode->destroyData(); }
+
+ void addref() { ++refcount; }
+ void release() { if (--refcount) delete this; }
+
+ int refcount;
+
+ bool hasException;
+ QScriptValue exception;
+
+ JSC::SourceCode source;
+ WTF::RefPtr<JSC::EvalNode> evalNode;
+};
+
+
namespace QScript
{
@@ -2113,7 +2132,121 @@ QScriptSyntaxCheckResult QScriptEnginePrivate::checkSyntax(const QString &progra
return QScriptSyntaxCheckResult(p);
}
+QScriptProgram QScriptEngine::compile(const QString &program, const QString &fileName, int lineNumber)
+{
+ Q_D(QScriptEngine);
+
+ QScriptProgram rv;
+ rv.d = new QScriptProgramPrivate;
+
+ JSC::JSLock lock(false); // ### hmmm
+ QBoolBlocker inEval(d->inEval, true);
+ currentContext()->activationObject(); //force the creation of a context for native function;
+
+ JSC::Debugger* debugger = d->originalGlobalObject()->debugger();
+
+ JSC::UString jscProgram = program;
+ JSC::UString jscFileName = fileName;
+ JSC::ExecState* exec = d->currentFrame;
+ WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider
+ = QScript::UStringSourceProviderWithFeedback::create(jscProgram, jscFileName, lineNumber, d);
+ intptr_t sourceId = provider->asID();
+ JSC::SourceCode &source = rv.d->source;
+ source = JSC::SourceCode(provider, lineNumber); //after construction of SourceCode provider variable will be null.
+
+ if (debugger)
+ debugger->evaluateStart(sourceId);
+
+ exec->clearException();
+ JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject());
+
+ int errorLine;
+ JSC::UString errorMessage;
+ WTF::RefPtr<JSC::EvalNode> &evalNode = rv.d->evalNode;
+ evalNode = exec->globalData().parser->parse<JSC::EvalNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, source, &errorLine, &errorMessage);
+ if (!evalNode) {
+ JSC::JSValue exceptionValue = JSC::Error::create(exec, JSC::SyntaxError, errorMessage, errorLine, source.provider()->asID(), source.provider()->url());
+ exec->setException(exceptionValue);
+
+ if (debugger) {
+ debugger->exceptionThrow(JSC::DebuggerCallFrame(exec, exceptionValue), sourceId, false);
+ debugger->evaluateStop(exceptionValue, sourceId);
+ }
+
+ rv.d->hasException = true;
+ rv.d->exception = d->scriptValueFromJSCValue(exceptionValue);
+ } else if (debugger) {
+ debugger->evaluateStop(JSC::JSValue(), sourceId);
+ }
+
+ return rv;
+}
+
+QScriptValue QScriptEngine::evaluate(const QScriptProgram &program)
+{
+ Q_D(QScriptEngine);
+
+ if (0 == program.d)
+ return QScriptValue();
+ else if (program.d->hasException)
+ return program.d->exception;
+ else if (!program.d->evalNode)
+ return QScriptValue();
+
+ JSC::JSLock lock(false); // ### hmmm
+ QBoolBlocker inEval(d->inEval, true);
+ currentContext()->activationObject(); //force the creation of a context for native function;
+
+ JSC::Debugger* debugger = d->originalGlobalObject()->debugger();
+
+ JSC::ExecState* exec = d->currentFrame;
+
+ intptr_t sourceId = program.d->source.provider()->asID();
+
+ if (debugger)
+ debugger->evaluateStart(sourceId);
+
+ exec->clearException();
+ JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject());
+
+ WTF::RefPtr<JSC::EvalNode> &evalNode = program.d->evalNode;
+
+ JSC::EvalExecutable executable(exec, program.d->source);
+ executable.compile(exec, evalNode, exec->scopeChain());
+ JSC::JSValue thisValue = d->thisForContext(exec);
+ JSC::JSObject* thisObject = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
+ JSC::JSValue exceptionValue;
+ d->timeoutChecker()->setShouldAbort(false);
+ if (d->processEventsInterval > 0)
+ d->timeoutChecker()->reset();
+ JSC::JSValue result = exec->interpreter()->execute(&executable, exec, thisObject, exec->scopeChain(), &exceptionValue);
+
+ if (d->timeoutChecker()->shouldAbort()) {
+ if (d->abortResult.isError())
+ exec->setException(d->scriptValueToJSCValue(d->abortResult));
+
+ if (debugger)
+ debugger->evaluateStop(d->scriptValueToJSCValue(d->abortResult), sourceId);
+
+ return d->abortResult;
+ }
+
+ if (exceptionValue) {
+ exec->setException(exceptionValue);
+
+ if (debugger)
+ debugger->evaluateStop(exceptionValue, sourceId);
+
+ return d->scriptValueFromJSCValue(exceptionValue);
+ }
+
+ if (debugger)
+ debugger->evaluateStop(result, sourceId);
+
+ Q_ASSERT(!exec->hadException());
+ return d->scriptValueFromJSCValue(result);
+}
/*!
Evaluates \a program, using \a lineNumber as the base line number,
@@ -2266,6 +2399,35 @@ QScriptContext *QScriptEngine::pushContext()
return d->contextForFrame(newFrame);
}
+/*!
+ Enters a new execution context and returns the associated
+ QScriptContext object.
+
+ Once you are done with the context, you should call popContext() to
+ restore the old context.
+
+ By default, the `this' object of the new context is the Global Object.
+ The context's \l{QScriptContext::callee()}{callee}() will be invalid.
+
+ Unlike pushContext(), the default scope chain is reset to include
+ only the global object and the QScriptContext's activation object.
+
+ \sa popContext()
+*/
+QScriptContext *QScriptEngine::pushCleanContext()
+{
+ Q_D(QScriptEngine);
+
+ JSC::CallFrame* newFrame = d->pushContext(d->currentFrame, d->currentFrame->globalData().dynamicGlobalObject,
+ JSC::ArgList(), /*callee = */0, false, true);
+
+ if (agent())
+ agent()->contextPush();
+
+ return d->contextForFrame(newFrame);
+}
+
+
/*! \internal
push a context for a native function.
JSC native function doesn't have different stackframe or context. so we need to create one.
@@ -2277,7 +2439,8 @@ QScriptContext *QScriptEngine::pushContext()
return the new top frame. (might be the same as exec if a new stackframe was not needed) or 0 if stack overflow
*/
JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSValue _thisObject,
- const JSC::ArgList& args, JSC::JSObject *callee, bool calledAsConstructor)
+ const JSC::ArgList& args, JSC::JSObject *callee, bool calledAsConstructor,
+ bool clearScopeChain)
{
JSC::JSValue thisObject = _thisObject;
if (calledAsConstructor) {
@@ -2311,7 +2474,14 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV
for (it = args.begin(); it != args.end(); ++it)
newCallFrame[++dst] = *it;
newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize;
- newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
+
+ if (!clearScopeChain) {
+ newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
+ } else {
+ JSC::JSObject *jscObject = originalGlobalObject();
+ JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), jscObject);
+ newCallFrame->init(0, /*vPC=*/0, scn, exec, flags | ShouldRestoreCallFrame, argc, callee);
+ }
} else {
setContextFlags(newCallFrame, flags);
#if ENABLE(JIT)
@@ -3707,6 +3877,9 @@ QScriptValue QScriptEngine::objectById(qint64 id) const
return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue((JSC::JSCell*)id);
}
+
+
+
/*!
\since 4.5
\class QScriptSyntaxCheckResult
@@ -3835,4 +4008,51 @@ Q_AUTOTEST_EXPORT bool qt_script_isJITEnabled()
}
#endif
+QScriptProgram::QScriptProgram()
+: d(0)
+{
+}
+
+QScriptProgram::~QScriptProgram()
+{
+ if (d) d->release();
+}
+
+QScriptProgram::QScriptProgram(const QScriptProgram &c)
+: d(c.d)
+{
+ if (d) d->addref();
+}
+
+QScriptProgram &QScriptProgram::operator=(const QScriptProgram &c)
+{
+ if (c.d) c.d->addref();
+ if (d) d->release();
+ d = c.d;
+ return *this;
+}
+
+bool QScriptProgram::isNull() const
+{
+ return d == 0;
+}
+
+bool QScriptProgram::hasSyntaxError() const
+{
+ if (d) return d->hasException;
+ else return false;
+}
+
+QScriptValue QScriptProgram::syntaxError() const
+{
+ if (d) return d->exception;
+ else return QScriptValue();
+}
+
+QString QScriptProgram::programSource() const
+{
+ if (d) return d->source.toString();
+ else return QString();
+}
+
QT_END_NAMESPACE
diff --git a/src/script/api/qscriptengine.h b/src/script/api/qscriptengine.h
index 701f9c6..cd86aca 100644
--- a/src/script/api/qscriptengine.h
+++ b/src/script/api/qscriptengine.h
@@ -120,6 +120,29 @@ private:
friend class QScriptEnginePrivate;
};
+class QScriptProgramPrivate;
+class Q_SCRIPT_EXPORT QScriptProgram
+{
+public:
+ QScriptProgram();
+ QScriptProgram(const QScriptProgram &);
+ ~QScriptProgram();
+
+ QScriptProgram &operator=(const QScriptProgram &);
+
+ bool isNull() const;
+
+ bool hasSyntaxError() const;
+ QScriptValue syntaxError() const;
+
+ QString programSource() const;
+
+private:
+ friend class QScriptEngine;
+ QScriptProgramPrivate *d;
+};
+
+class QScriptCode;
class Q_SCRIPT_EXPORT QScriptEngine
#ifndef QT_NO_QOBJECT
: public QObject
@@ -159,11 +182,15 @@ public:
QScriptContext *currentContext() const;
QScriptContext *pushContext();
+ QScriptContext *pushCleanContext();
void popContext();
bool canEvaluate(const QString &program) const;
static QScriptSyntaxCheckResult checkSyntax(const QString &program);
+ QScriptProgram compile(const QString &program, const QString &fileName = QString(), int lineNumber = 1);
+ QScriptValue evaluate(const QScriptProgram &);
+
QScriptValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1);
bool isEvaluating() const;
diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h
index 5f31054..7218ee1 100644
--- a/src/script/api/qscriptengine_p.h
+++ b/src/script/api/qscriptengine_p.h
@@ -162,7 +162,7 @@ public:
static JSC::Register *thisRegisterForFrame(JSC::ExecState *frame);
JSC::CallFrame *pushContext(JSC::CallFrame *exec, JSC::JSValue thisObject, const JSC::ArgList& args,
- JSC::JSObject *callee, bool calledAsConstructor = false);
+ JSC::JSObject *callee, bool calledAsConstructor = false, bool clearScopeChain = false);
void popContext();
void mark(JSC::MarkStack& markStack);
diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp
index 92c987c..7136a85 100644
--- a/src/script/api/qscriptvalue.cpp
+++ b/src/script/api/qscriptvalue.cpp
@@ -71,6 +71,7 @@
#include "bridge/qscriptclassobject_p.h"
#include "bridge/qscriptvariant_p.h"
#include "bridge/qscriptqobject_p.h"
+#include "bridge/qscriptdeclarativeclass_p.h"
/*!
\since 4.3
@@ -1529,6 +1530,8 @@ QVariant QScriptValue::toVariant() const
#endif
else if (isArray())
return QScriptEnginePrivate::variantListFromArray(*this);
+ else if (QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(*this))
+ return dc->toVariant(QScriptDeclarativeClass::object(*this));
// try to convert to primitive
JSC::ExecState *exec = d->engine->currentFrame;
JSC::JSValue savedException;
@@ -1619,6 +1622,8 @@ QObject *QScriptValue::toQObject() const
if (isQObject()) {
QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
return static_cast<QScript::QObjectDelegate*>(object->delegate())->value();
+ } else if (QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(*this)) {
+ return dc->toQObject(QScriptDeclarativeClass::object(*this));
} else if (isVariant()) {
QVariant var = toVariant();
int type = var.userType();
diff --git a/src/script/bridge/bridge.pri b/src/script/bridge/bridge.pri
index 666a07e..09e2dfb 100644
--- a/src/script/bridge/bridge.pri
+++ b/src/script/bridge/bridge.pri
@@ -5,7 +5,9 @@ SOURCES += \
$$PWD/qscriptvariant.cpp \
$$PWD/qscriptqobject.cpp \
$$PWD/qscriptglobalobject.cpp \
- $$PWD/qscriptactivationobject.cpp
+ $$PWD/qscriptactivationobject.cpp \
+ $$PWD/qscriptdeclarativeobject.cpp \
+ $$PWD/qscriptdeclarativeclass.cpp
HEADERS += \
$$PWD/qscriptfunction_p.h \
@@ -14,4 +16,6 @@ HEADERS += \
$$PWD/qscriptvariant_p.h \
$$PWD/qscriptqobject_p.h \
$$PWD/qscriptglobalobject_p.h \
- $$PWD/qscriptactivationobject_p.h
+ $$PWD/qscriptactivationobject_p.h \
+ $$PWD/qscriptdeclarativeobject_p.h \
+ $$PWD/qscriptdeclarativeclass_p.h
diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp
new file mode 100644
index 0000000..a7667cb
--- /dev/null
+++ b/src/script/bridge/qscriptdeclarativeclass.cpp
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscriptdeclarativeclass_p.h"
+#include "qscriptdeclarativeobject_p.h"
+#include "qscriptobject_p.h"
+#include <QtScript/qscriptstring.h>
+#include <QtScript/qscriptengine.h>
+#include <private/qscriptengine_p.h>
+#include <private/qscriptvalue_p.h>
+#include <private/qscriptqobject_p.h>
+#include <private/qscriptactivationobject_p.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier()
+{
+ new (&d) JSC::Identifier();
+}
+
+QScriptDeclarativeClass::PersistentIdentifier::~PersistentIdentifier()
+{
+ ((JSC::Identifier &)d).JSC::Identifier::~Identifier();
+}
+
+QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier(const PersistentIdentifier &other)
+{
+ identifier = other.identifier;
+ new (&d) JSC::Identifier((JSC::Identifier &)(other.d));
+}
+
+QScriptDeclarativeClass::PersistentIdentifier &
+QScriptDeclarativeClass::PersistentIdentifier::operator=(const PersistentIdentifier &other)
+{
+ identifier = other.identifier;
+ ((JSC::Identifier &)d) = (JSC::Identifier &)(other.d);
+ return *this;
+}
+
+class QScriptDeclarativeClassPrivate
+{
+public:
+ QScriptDeclarativeClassPrivate() : engine(0), q_ptr(0) {}
+
+ QScriptEngine *engine;
+ QScriptDeclarativeClass *q_ptr;
+};
+
+QScriptDeclarativeClass::QScriptDeclarativeClass(QScriptEngine *engine)
+: context(0), d_ptr(new QScriptDeclarativeClassPrivate)
+{
+ Q_ASSERT(sizeof(void*) == sizeof(JSC::Identifier));
+ d_ptr->q_ptr = this;
+ d_ptr->engine = engine;
+}
+
+QScriptValue QScriptDeclarativeClass::newObject(QScriptEngine *engine,
+ QScriptDeclarativeClass *scriptClass,
+ Object *object)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(scriptClass);
+
+ QScriptEnginePrivate *p = static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(engine));
+
+ JSC::ExecState* exec = p->currentFrame;
+ QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure);
+ result->setDelegate(new QScript::DeclarativeObjectDelegate(scriptClass, object));
+ return p->scriptValueFromJSCValue(result);
+}
+
+QScriptDeclarativeClass *QScriptDeclarativeClass::scriptClass(const QScriptValue &v)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+ if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info))
+ return 0;
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject))
+ return 0;
+ return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass();
+}
+
+QScriptDeclarativeClass::Object *QScriptDeclarativeClass::object(const QScriptValue &v)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+ if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info))
+ return 0;
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject))
+ return 0;
+ return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->object();
+}
+
+QScriptValue QScriptDeclarativeClass::function(const QScriptValue &v, const Identifier &name)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+
+ if (!d->isObject())
+ return QScriptValue();
+
+ JSC::ExecState *exec = d->engine->currentFrame;
+ JSC::JSObject *object = d->jscValue.getObject();
+ JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
+ JSC::JSValue result;
+
+ JSC::Identifier id(exec, (JSC::UString::Rep *)name);
+
+ if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) {
+ result = slot.getValue(exec, id);
+ if (QScript::isFunction(result))
+ return d->engine->scriptValueFromJSCValue(result);
+ }
+
+ return QScriptValue();
+}
+
+QScriptValue QScriptDeclarativeClass::property(const QScriptValue &v, const Identifier &name)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+
+ if (!d->isObject())
+ return QScriptValue();
+
+ JSC::ExecState *exec = d->engine->currentFrame;
+ JSC::JSObject *object = d->jscValue.getObject();
+ JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
+ JSC::JSValue result;
+
+ JSC::Identifier id(exec, (JSC::UString::Rep *)name);
+
+ if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) {
+ result = slot.getValue(exec, id);
+ return d->engine->scriptValueFromJSCValue(result);
+ }
+
+ return QScriptValue();
+}
+
+/*
+Returns the scope chain entry \a index from the end. This is equivalent to:
+ context->scopeChain().at(context->scopeChain.length() - 1 - index)
+*/
+QScriptValue QScriptDeclarativeClass::scopeChainValue(QScriptContext *context, int index)
+{
+ context->activationObject(); //ensure the creation of the normal scope for native context
+ const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(context);
+ QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
+
+ JSC::ScopeChainNode *node = frame->scopeChain();
+ JSC::ScopeChainIterator it(node);
+
+ int count = 0;
+ for (it = node->begin(); it != node->end(); ++it)
+ ++count;
+
+ if (count < index)
+ return QScriptValue();
+
+ count -= index;
+
+ for (it = node->begin(); it != node->end(); ++it) {
+
+ if (count == 0) {
+
+ JSC::JSObject *object = *it;
+ if (!object) return QScriptValue();
+
+ if (object->inherits(&QScript::QScriptActivationObject::info)
+ && (static_cast<QScript::QScriptActivationObject*>(object)->delegate() != 0)) {
+ // Return the object that property access is being delegated to
+ object = static_cast<QScript::QScriptActivationObject*>(object)->delegate();
+ }
+ return engine->scriptValueFromJSCValue(object);
+
+ } else {
+ --count;
+ }
+
+ }
+
+ return QScriptValue();
+}
+
+QScriptDeclarativeClass::~QScriptDeclarativeClass()
+{
+}
+
+QScriptEngine *QScriptDeclarativeClass::engine() const
+{
+ return d_ptr->engine;
+}
+
+QScriptDeclarativeClass::PersistentIdentifier
+QScriptDeclarativeClass::createPersistentIdentifier(const QString &str)
+{
+ QScriptEnginePrivate *p =
+ static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine));
+ JSC::ExecState* exec = p->currentFrame;
+
+ PersistentIdentifier rv(true);
+ new (&rv.d) JSC::Identifier(exec, (UChar *)str.constData(), str.size());
+ rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep();
+ return rv;
+}
+
+QScriptDeclarativeClass::PersistentIdentifier
+QScriptDeclarativeClass::createPersistentIdentifier(const Identifier &id)
+{
+ QScriptEnginePrivate *p =
+ static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine));
+ JSC::ExecState* exec = p->currentFrame;
+
+ PersistentIdentifier rv(true);
+ new (&rv.d) JSC::Identifier(exec, (JSC::UString::Rep *)id);
+ rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep();
+ return rv;
+}
+
+QString QScriptDeclarativeClass::toString(const Identifier &identifier)
+{
+ JSC::UString::Rep *r = (JSC::UString::Rep *)identifier;
+ return QString((QChar *)r->data(), r->size());
+}
+
+QScriptClass::QueryFlags
+QScriptDeclarativeClass::queryProperty(Object *object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ Q_UNUSED(flags);
+ return 0;
+}
+
+QScriptValue QScriptDeclarativeClass::property(Object *object, const Identifier &name)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ return QScriptValue();
+}
+
+void QScriptDeclarativeClass::setProperty(Object *object, const Identifier &name,
+ const QScriptValue &value)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ Q_UNUSED(value);
+}
+
+QScriptValue::PropertyFlags
+QScriptDeclarativeClass::propertyFlags(Object *object, const Identifier &name)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ return 0;
+}
+
+QStringList QScriptDeclarativeClass::propertyNames(Object *object)
+{
+ Q_UNUSED(object);
+ return QStringList();
+}
+
+QObject *QScriptDeclarativeClass::toQObject(Object *, bool *ok)
+{
+ if (ok) *ok = false;
+ return 0;
+}
+
+QVariant QScriptDeclarativeClass::toVariant(Object *, bool *ok)
+{
+ if (ok) *ok = false;
+ return QVariant();
+}
+
diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h
new file mode 100644
index 0000000..0d05ec5
--- /dev/null
+++ b/src/script/bridge/qscriptdeclarativeclass_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTDECLARATIVECLASS_P_H
+#define QSCRIPTDECLARATIVECLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobjectdefs.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtScript/qscriptclass.h>
+
+QT_BEGIN_NAMESPACE
+
+class QScriptDeclarativeClassPrivate;
+class PersistentIdentifierPrivate;
+class QScriptContext;
+class Q_SCRIPT_EXPORT QScriptDeclarativeClass
+{
+public:
+ typedef void* Identifier;
+
+ struct Object { virtual ~Object() {} };
+
+ static QScriptValue newObject(QScriptEngine *, QScriptDeclarativeClass *, Object *);
+ static QScriptDeclarativeClass *scriptClass(const QScriptValue &);
+ static Object *object(const QScriptValue &);
+
+ static QScriptValue function(const QScriptValue &, const Identifier &);
+ static QScriptValue property(const QScriptValue &, const Identifier &);
+
+ static QScriptValue scopeChainValue(QScriptContext *, int index);
+
+ class Q_SCRIPT_EXPORT PersistentIdentifier
+ {
+ public:
+ Identifier identifier;
+
+ PersistentIdentifier();
+ ~PersistentIdentifier();
+ PersistentIdentifier(const PersistentIdentifier &other);
+ PersistentIdentifier &operator=(const PersistentIdentifier &other);
+
+ private:
+ friend class QScriptDeclarativeClass;
+ PersistentIdentifier(bool) : identifier(0), d(0) {}
+ void *d;
+ };
+
+ QScriptDeclarativeClass(QScriptEngine *engine);
+ virtual ~QScriptDeclarativeClass();
+
+ QScriptEngine *engine() const;
+
+ PersistentIdentifier createPersistentIdentifier(const QString &);
+ PersistentIdentifier createPersistentIdentifier(const Identifier &);
+
+ QString toString(const Identifier &);
+
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+
+ virtual QScriptValue property(Object *, const Identifier &);
+ virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+ virtual QScriptValue::PropertyFlags propertyFlags(Object *, const Identifier &);
+
+ virtual QStringList propertyNames(Object *);
+
+ virtual QObject *toQObject(Object *, bool *ok = 0);
+ virtual QVariant toVariant(Object *, bool *ok = 0);
+
+ QScriptContext *context;
+protected:
+ QScopedPointer<QScriptDeclarativeClassPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/bridge/qscriptdeclarativeobject.cpp b/src/script/bridge/qscriptdeclarativeobject.cpp
new file mode 100644
index 0000000..ffdebb0
--- /dev/null
+++ b/src/script/bridge/qscriptdeclarativeobject.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h"
+#include "qscriptdeclarativeobject_p.h"
+
+#include "../api/qscriptengine.h"
+#include "../api/qscriptengine_p.h"
+#include "../api/qscriptcontext.h"
+#include "../api/qscriptcontext_p.h"
+#include "../api/qscriptclass.h"
+#include "../api/qscriptclasspropertyiterator.h"
+
+#include "Error.h"
+#include "PropertyNameArray.h"
+
+#include <QtCore/qstringlist.h>
+
+Q_DECLARE_METATYPE(QScriptContext*)
+Q_DECLARE_METATYPE(QScriptValue)
+Q_DECLARE_METATYPE(QScriptValueList)
+
+QT_BEGIN_NAMESPACE
+
+namespace QScript
+{
+
+DeclarativeObjectDelegate::DeclarativeObjectDelegate(QScriptDeclarativeClass *c,
+ QScriptDeclarativeClass::Object *o)
+: m_class(c), m_object(o)
+{
+}
+
+DeclarativeObjectDelegate::~DeclarativeObjectDelegate()
+{
+ delete m_object;
+}
+
+QScriptObjectDelegate::Type DeclarativeObjectDelegate::type() const
+{
+ return DeclarativeClassObject;
+}
+
+bool DeclarativeObjectDelegate::getOwnPropertySlot(QScriptObject* object,
+ JSC::ExecState *exec,
+ const JSC::Identifier &propertyName,
+ JSC::PropertySlot &slot)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep();
+
+ m_class->context = reinterpret_cast<QScriptContext *>(exec);
+ QScriptClass::QueryFlags flags =
+ m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess);
+ if (flags & QScriptClass::HandlesReadAccess) {
+ QScriptValue value = m_class->property(m_object, identifier);
+ m_class->context = 0;
+ slot.setValue(engine->scriptValueToJSCValue(value));
+ return true;
+ }
+ m_class->context = 0;
+
+ return QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot);
+}
+
+void DeclarativeObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec,
+ const JSC::Identifier &propertyName,
+ JSC::JSValue value, JSC::PutPropertySlot &slot)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep();
+
+ m_class->context = reinterpret_cast<QScriptContext *>(exec);
+ QScriptClass::QueryFlags flags =
+ m_class->queryProperty(m_object, identifier, QScriptClass::HandlesWriteAccess);
+ if (flags & QScriptClass::HandlesWriteAccess) {
+ m_class->setProperty(m_object, identifier, engine->scriptValueFromJSCValue(value));
+ m_class->context = 0;
+ return;
+ }
+ m_class->context = 0;
+
+ QScriptObjectDelegate::put(object, exec, propertyName, value, slot);
+}
+
+bool DeclarativeObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState *exec,
+ const JSC::Identifier &propertyName,
+ bool checkDontDelete)
+{
+ return QScriptObjectDelegate::deleteProperty(object, exec, propertyName, checkDontDelete);
+}
+
+bool DeclarativeObjectDelegate::getPropertyAttributes(const QScriptObject* object,
+ JSC::ExecState *exec,
+ const JSC::Identifier &propertyName,
+ unsigned &attribs) const
+{
+ QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep();
+
+ QScriptClass::QueryFlags flags =
+ m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess);
+ if (flags & QScriptClass::HandlesReadAccess) {
+ QScriptValue::PropertyFlags flags = m_class->propertyFlags(m_object, identifier);
+ attribs = 0;
+ if (flags & QScriptValue::ReadOnly)
+ attribs |= JSC::ReadOnly;
+ if (flags & QScriptValue::SkipInEnumeration)
+ attribs |= JSC::DontEnum;
+ if (flags & QScriptValue::Undeletable)
+ attribs |= JSC::DontDelete;
+ if (flags & QScriptValue::PropertyGetter)
+ attribs |= JSC::Getter;
+ if (flags & QScriptValue::PropertySetter)
+ attribs |= JSC::Setter;
+ attribs |= flags & QScriptValue::UserRange;
+ return true;
+ }
+ return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attribs);
+}
+
+void DeclarativeObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState *exec,
+ JSC::PropertyNameArray &propertyNames,
+ bool includeNonEnumerable)
+{
+ QStringList properties = m_class->propertyNames(m_object);
+ for (int ii = 0; ii < properties.count(); ++ii) {
+ const QString &name = properties.at(ii);
+ propertyNames.add(JSC::Identifier(exec, name));
+ }
+
+ QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, includeNonEnumerable);
+}
+
+JSC::CallType DeclarativeObjectDelegate::getCallData(QScriptObject *object, JSC::CallData &callData)
+{
+ return QScriptObjectDelegate::getCallData(object, callData);
+}
+
+JSC::ConstructType DeclarativeObjectDelegate::getConstructData(QScriptObject* object, JSC::ConstructData &constructData)
+{
+ return QScriptObjectDelegate::getConstructData(object, constructData);
+}
+
+bool DeclarativeObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState *exec,
+ JSC::JSValue value, JSC::JSValue proto)
+{
+ return QScriptObjectDelegate::hasInstance(object, exec, value, proto);
+}
+
+} // namespace QScript
+
+QT_END_NAMESPACE
diff --git a/src/script/bridge/qscriptdeclarativeobject_p.h b/src/script/bridge/qscriptdeclarativeobject_p.h
new file mode 100644
index 0000000..9c14774
--- /dev/null
+++ b/src/script/bridge/qscriptdeclarativeobject_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTDECLARATIVEOBJECT_P_H
+#define QSCRIPTDECLARATIVEOBJECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobjectdefs.h>
+
+#include "config.h"
+#include "qscriptobject_p.h"
+#include "qscriptdeclarativeclass_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QScriptClass;
+
+namespace QScript
+{
+
+class DeclarativeObjectDelegate : public QScriptObjectDelegate
+{
+public:
+ DeclarativeObjectDelegate(QScriptDeclarativeClass *c, QScriptDeclarativeClass::Object *o);
+ ~DeclarativeObjectDelegate();
+
+ virtual Type type() const;
+
+ QScriptDeclarativeClass *scriptClass() const { return m_class; }
+ QScriptDeclarativeClass::Object *object() const { return m_object; }
+
+ virtual bool getOwnPropertySlot(QScriptObject*, JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ JSC::PropertySlot&);
+ virtual void put(QScriptObject*, JSC::ExecState* exec,
+ const JSC::Identifier& propertyName,
+ JSC::JSValue, JSC::PutPropertySlot&);
+ virtual bool deleteProperty(QScriptObject*, JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ bool checkDontDelete = true);
+ virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*,
+ const JSC::Identifier&,
+ unsigned&) const;
+ virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*,
+ JSC::PropertyNameArray&,
+ bool includeNonEnumerable = false);
+
+ virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&);
+ virtual JSC::ConstructType getConstructData(QScriptObject*, JSC::ConstructData&);
+
+ virtual bool hasInstance(QScriptObject*, JSC::ExecState*,
+ JSC::JSValue value, JSC::JSValue proto);
+
+private:
+ QScriptDeclarativeClass *m_class;
+ QScriptDeclarativeClass::Object *m_object;
+};
+
+} // namespace QScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/bridge/qscriptobject_p.h b/src/script/bridge/qscriptobject_p.h
index c1cee31..a5858ac 100644
--- a/src/script/bridge/qscriptobject_p.h
+++ b/src/script/bridge/qscriptobject_p.h
@@ -127,7 +127,8 @@ public:
enum Type {
QtObject,
Variant,
- ClassObject
+ ClassObject,
+ DeclarativeClassObject
};
QScriptObjectDelegate();