summaryrefslogtreecommitdiff
path: root/src/script/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/bridge')
-rw-r--r--src/script/bridge/bridge.pri23
-rw-r--r--src/script/bridge/qscriptactivationobject.cpp154
-rw-r--r--src/script/bridge/qscriptactivationobject_p.h92
-rw-r--r--src/script/bridge/qscriptclassobject.cpp280
-rw-r--r--src/script/bridge/qscriptclassobject_p.h104
-rw-r--r--src/script/bridge/qscriptdeclarativeclass.cpp601
-rw-r--r--src/script/bridge/qscriptdeclarativeclass_p.h156
-rw-r--r--src/script/bridge/qscriptdeclarativeobject.cpp190
-rw-r--r--src/script/bridge/qscriptdeclarativeobject_p.h109
-rw-r--r--src/script/bridge/qscriptfunction.cpp176
-rw-r--r--src/script/bridge/qscriptfunction_p.h119
-rw-r--r--src/script/bridge/qscriptglobalobject.cpp158
-rw-r--r--src/script/bridge/qscriptglobalobject_p.h127
-rw-r--r--src/script/bridge/qscriptobject.cpp222
-rw-r--r--src/script/bridge/qscriptobject_p.h176
-rw-r--r--src/script/bridge/qscriptqobject.cpp2317
-rw-r--r--src/script/bridge/qscriptqobject_p.h322
-rw-r--r--src/script/bridge/qscriptstaticscopeobject.cpp157
-rw-r--r--src/script/bridge/qscriptstaticscopeobject_p.h103
-rw-r--r--src/script/bridge/qscriptvariant.cpp151
-rw-r--r--src/script/bridge/qscriptvariant_p.h75
21 files changed, 5812 insertions, 0 deletions
diff --git a/src/script/bridge/bridge.pri b/src/script/bridge/bridge.pri
new file mode 100644
index 0000000..ab0a322
--- /dev/null
+++ b/src/script/bridge/bridge.pri
@@ -0,0 +1,23 @@
+SOURCES += \
+ $$PWD/qscriptfunction.cpp \
+ $$PWD/qscriptobject.cpp \
+ $$PWD/qscriptclassobject.cpp \
+ $$PWD/qscriptvariant.cpp \
+ $$PWD/qscriptqobject.cpp \
+ $$PWD/qscriptglobalobject.cpp \
+ $$PWD/qscriptactivationobject.cpp \
+ $$PWD/qscriptstaticscopeobject.cpp \
+ $$PWD/qscriptdeclarativeobject.cpp \
+ $$PWD/qscriptdeclarativeclass.cpp
+
+HEADERS += \
+ $$PWD/qscriptfunction_p.h \
+ $$PWD/qscriptobject_p.h \
+ $$PWD/qscriptclassobject_p.h \
+ $$PWD/qscriptvariant_p.h \
+ $$PWD/qscriptqobject_p.h \
+ $$PWD/qscriptglobalobject_p.h \
+ $$PWD/qscriptactivationobject_p.h \
+ $$PWD/qscriptstaticscopeobject_p.h \
+ $$PWD/qscriptdeclarativeobject_p.h \
+ $$PWD/qscriptdeclarativeclass_p.h
diff --git a/src/script/bridge/qscriptactivationobject.cpp b/src/script/bridge/qscriptactivationobject.cpp
new file mode 100644
index 0000000..88be4f9
--- /dev/null
+++ b/src/script/bridge/qscriptactivationobject.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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 "qscriptactivationobject_p.h"
+
+#include "JSVariableObject.h"
+
+namespace JSC
+{
+ ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScript::QScriptActivationObject));
+}
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QScript::QScriptActivationObject
+ \internal
+
+ Represent a scope for native function call.
+*/
+
+namespace QScript
+{
+
+const JSC::ClassInfo QScriptActivationObject::info = { "QScriptActivationObject", 0, 0, 0 };
+
+QScriptActivationObject::QScriptActivationObject(JSC::ExecState *callFrame, JSC::JSObject *delegate)
+ : JSC::JSVariableObject(callFrame->globalData().activationStructure,
+ new QScriptActivationObjectData(callFrame->registers(), delegate))
+{
+}
+
+QScriptActivationObject::~QScriptActivationObject()
+{
+ delete d_ptr();
+}
+
+bool QScriptActivationObject::getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot)
+{
+ if (d_ptr()->delegate != 0)
+ return d_ptr()->delegate->getOwnPropertySlot(exec, propertyName, slot);
+ return JSC::JSVariableObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool QScriptActivationObject::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor)
+{
+ if (d_ptr()->delegate != 0)
+ return d_ptr()->delegate->getOwnPropertyDescriptor(exec, propertyName, descriptor);
+ return JSC::JSVariableObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
+void QScriptActivationObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, JSC::EnumerationMode mode)
+{
+ if (d_ptr()->delegate != 0) {
+ d_ptr()->delegate->getOwnPropertyNames(exec, propertyNames, mode);
+ return;
+ }
+ return JSC::JSVariableObject::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
+void QScriptActivationObject::putWithAttributes(JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes)
+{
+ if (d_ptr()->delegate != 0) {
+ d_ptr()->delegate->putWithAttributes(exec, propertyName, value, attributes);
+ return;
+ }
+
+ if (symbolTablePutWithAttributes(propertyName, value, attributes))
+ return;
+
+ JSC::PutPropertySlot slot;
+ JSObject::putWithAttributes(exec, propertyName, value, attributes, true, slot);
+}
+
+void QScriptActivationObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot& slot)
+{
+ if (d_ptr()->delegate != 0) {
+ d_ptr()->delegate->put(exec, propertyName, value, slot);
+ return;
+ }
+ JSC::JSVariableObject::put(exec, propertyName, value, slot);
+}
+
+void QScriptActivationObject::put(JSC::ExecState* exec, unsigned propertyName, JSC::JSValue value)
+{
+ if (d_ptr()->delegate != 0) {
+ d_ptr()->delegate->put(exec, propertyName, value);
+ return;
+ }
+ JSC::JSVariableObject::put(exec, propertyName, value);
+}
+
+bool QScriptActivationObject::deleteProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName)
+{
+ if (d_ptr()->delegate != 0)
+ return d_ptr()->delegate->deleteProperty(exec, propertyName);
+ return JSC::JSVariableObject::deleteProperty(exec, propertyName);
+}
+
+void QScriptActivationObject::defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction)
+{
+ if (d_ptr()->delegate != 0)
+ d_ptr()->delegate->defineGetter(exec, propertyName, getterFunction);
+ else
+ JSC::JSVariableObject::defineGetter(exec, propertyName, getterFunction);
+}
+
+void QScriptActivationObject::defineSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction)
+{
+ if (d_ptr()->delegate != 0)
+ d_ptr()->delegate->defineSetter(exec, propertyName, setterFunction);
+ else
+ JSC::JSVariableObject::defineSetter(exec, propertyName, setterFunction);
+}
+
+JSC::JSValue QScriptActivationObject::lookupGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName)
+{
+ if (d_ptr()->delegate != 0)
+ return d_ptr()->delegate->lookupGetter(exec, propertyName);
+ return JSC::JSVariableObject::lookupGetter(exec, propertyName);
+}
+
+JSC::JSValue QScriptActivationObject::lookupSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName)
+{
+ if (d_ptr()->delegate != 0)
+ return d_ptr()->delegate->lookupSetter(exec, propertyName);
+ return JSC::JSVariableObject::lookupSetter(exec, propertyName);
+}
+
+} // namespace QScript
+
+QT_END_NAMESPACE
+
diff --git a/src/script/bridge/qscriptactivationobject_p.h b/src/script/bridge/qscriptactivationobject_p.h
new file mode 100644
index 0000000..a4c69a9
--- /dev/null
+++ b/src/script/bridge/qscriptactivationobject_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTACTIVATIONOBJECT_P_H
+#define QSCRIPTACTIVATIONOBJECT_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 "JSVariableObject.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QScript
+{
+
+class QScriptActivationObject : public JSC::JSVariableObject {
+public:
+ QScriptActivationObject(JSC::ExecState *callFrame, JSC::JSObject *delegate = 0);
+ virtual ~QScriptActivationObject();
+ virtual bool isDynamicScope() const { return true; }
+
+ virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);
+ virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);
+
+ virtual void putWithAttributes(JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes);
+ virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot&);
+ virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue value);
+
+ virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName);
+
+ virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction);
+ virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction);
+ virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);
+ virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);
+
+ virtual const JSC::ClassInfo* classInfo() const { return &info; }
+ static const JSC::ClassInfo info;
+
+ struct QScriptActivationObjectData : public JSVariableObjectData {
+ QScriptActivationObjectData(JSC::Register* registers, JSC::JSObject *dlg)
+ : JSVariableObjectData(&symbolTable, registers),
+ delegate(dlg)
+ { }
+ JSC::SymbolTable symbolTable;
+ JSC::JSObject *delegate;
+ };
+
+ JSC::JSObject *delegate() const
+ { return d_ptr()->delegate; }
+ void setDelegate(JSC::JSObject *delegate)
+ { d_ptr()->delegate = delegate; }
+
+ QScriptActivationObjectData *d_ptr() const { return static_cast<QScriptActivationObjectData *>(d); }
+};
+
+} // namespace QScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/bridge/qscriptclassobject.cpp b/src/script/bridge/qscriptclassobject.cpp
new file mode 100644
index 0000000..2085756
--- /dev/null
+++ b/src/script/bridge/qscriptclassobject.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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 "qscriptclassobject_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"
+
+Q_DECLARE_METATYPE(QScriptContext*)
+Q_DECLARE_METATYPE(QScriptValue)
+Q_DECLARE_METATYPE(QScriptValueList)
+
+QT_BEGIN_NAMESPACE
+
+namespace QScript
+{
+
+ClassObjectDelegate::ClassObjectDelegate(QScriptClass *scriptClass)
+ : m_scriptClass(scriptClass)
+{
+}
+
+ClassObjectDelegate::~ClassObjectDelegate()
+{
+}
+
+QScriptObjectDelegate::Type ClassObjectDelegate::type() const
+{
+ return ClassObject;
+}
+
+bool ClassObjectDelegate::getOwnPropertySlot(QScriptObject* object,
+ JSC::ExecState *exec,
+ const JSC::Identifier &propertyName,
+ JSC::PropertySlot &slot)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ QScript::SaveFrameHelper saveFrame(engine, exec);
+ // for compatibility with the old back-end, normal JS properties
+ // are queried first.
+ if (QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot))
+ return true;
+
+ QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
+ QScriptString scriptName;
+ QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated);
+ QScriptStringPrivate::init(scriptName, &scriptName_d);
+ uint id = 0;
+ QScriptClass::QueryFlags flags = m_scriptClass->queryProperty(
+ scriptObject, scriptName, QScriptClass::HandlesReadAccess, &id);
+ if (flags & QScriptClass::HandlesReadAccess) {
+ QScriptValue value = m_scriptClass->property(scriptObject, scriptName, id);
+ if (!value.isValid()) {
+ // The class claims to have the property, but returned an invalid
+ // value. Silently convert to undefined to avoid the invalid value
+ // "escaping" into JS.
+ value = QScriptValue(QScriptValue::UndefinedValue);
+ }
+ slot.setValue(engine->scriptValueToJSCValue(value));
+ return true;
+ }
+ return false;
+}
+
+bool ClassObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object,
+ JSC::ExecState *exec,
+ const JSC::Identifier &propertyName,
+ JSC::PropertyDescriptor &descriptor)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ QScript::SaveFrameHelper saveFrame(engine, exec);
+ // for compatibility with the old back-end, normal JS properties
+ // are queried first.
+ if (QScriptObjectDelegate::getOwnPropertyDescriptor(object, exec, propertyName, descriptor))
+ return true;
+
+ QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
+ QScriptString scriptName;
+ QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated);
+ QScriptStringPrivate::init(scriptName, &scriptName_d);
+ uint id = 0;
+ QScriptClass::QueryFlags qflags = m_scriptClass->queryProperty(
+ scriptObject, scriptName, QScriptClass::HandlesReadAccess, &id);
+ if (qflags & QScriptClass::HandlesReadAccess) {
+ QScriptValue::PropertyFlags pflags = m_scriptClass->propertyFlags(scriptObject, scriptName, id);
+ unsigned attribs = 0;
+ if (pflags & QScriptValue::ReadOnly)
+ attribs |= JSC::ReadOnly;
+ if (pflags & QScriptValue::SkipInEnumeration)
+ attribs |= JSC::DontEnum;
+ if (pflags & QScriptValue::Undeletable)
+ attribs |= JSC::DontDelete;
+ if (pflags & QScriptValue::PropertyGetter)
+ attribs |= JSC::Getter;
+ if (pflags & QScriptValue::PropertySetter)
+ attribs |= JSC::Setter;
+ attribs |= pflags & QScriptValue::UserRange;
+ // Rather than calling the getter, we could return an access descriptor here.
+ QScriptValue value = m_scriptClass->property(scriptObject, scriptName, id);
+ if (!value.isValid()) {
+ // The class claims to have the property, but returned an invalid
+ // value. Silently convert to undefined to avoid the invalid value
+ // "escaping" into JS.
+ value = QScriptValue(QScriptValue::UndefinedValue);
+ }
+ descriptor.setDescriptor(engine->scriptValueToJSCValue(value), attribs);
+ return true;
+ }
+ return false;
+}
+
+void ClassObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec,
+ const JSC::Identifier &propertyName,
+ JSC::JSValue value, JSC::PutPropertySlot &slot)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ QScript::SaveFrameHelper saveFrame(engine, exec);
+ QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
+ QScriptString scriptName;
+ QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated);
+ QScriptStringPrivate::init(scriptName, &scriptName_d);
+ uint id = 0;
+ QScriptClass::QueryFlags flags = m_scriptClass->queryProperty(
+ scriptObject, scriptName, QScriptClass::HandlesWriteAccess, &id);
+ if (flags & QScriptClass::HandlesWriteAccess) {
+ m_scriptClass->setProperty(scriptObject, scriptName, id, engine->scriptValueFromJSCValue(value));
+ return;
+ }
+ QScriptObjectDelegate::put(object, exec, propertyName, value, slot);
+}
+
+bool ClassObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState *exec,
+ const JSC::Identifier &propertyName)
+{
+ // ### avoid duplication of put()
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ QScript::SaveFrameHelper saveFrame(engine, exec);
+ QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
+ QScriptString scriptName;
+ QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated);
+ QScriptStringPrivate::init(scriptName, &scriptName_d);
+ uint id = 0;
+ QScriptClass::QueryFlags flags = m_scriptClass->queryProperty(
+ scriptObject, scriptName, QScriptClass::HandlesWriteAccess, &id);
+ if (flags & QScriptClass::HandlesWriteAccess) {
+ if (m_scriptClass->propertyFlags(scriptObject, scriptName, id) & QScriptValue::Undeletable)
+ return false;
+ m_scriptClass->setProperty(scriptObject, scriptName, id, QScriptValue());
+ return true;
+ }
+ return QScriptObjectDelegate::deleteProperty(object, exec, propertyName);
+}
+
+void ClassObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState *exec,
+ JSC::PropertyNameArray &propertyNames,
+ JSC::EnumerationMode mode)
+{
+ // For compatibility with the old back-end, normal JS properties
+ // are added first.
+ QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, mode);
+
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ QScript::SaveFrameHelper saveFrame(engine, exec);
+ QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
+ QScriptClassPropertyIterator *it = m_scriptClass->newIterator(scriptObject);
+ if (it != 0) {
+ while (it->hasNext()) {
+ it->next();
+ QString name = it->name().toString();
+ propertyNames.add(JSC::Identifier(exec, name));
+ }
+ delete it;
+ }
+}
+
+JSC::CallType ClassObjectDelegate::getCallData(QScriptObject*, JSC::CallData &callData)
+{
+ if (!m_scriptClass->supportsExtension(QScriptClass::Callable))
+ return JSC::CallTypeNone;
+ callData.native.function = call;
+ return JSC::CallTypeHost;
+}
+
+JSC::JSValue JSC_HOST_CALL ClassObjectDelegate::call(JSC::ExecState *exec, JSC::JSObject *callee,
+ JSC::JSValue thisValue, const JSC::ArgList &args)
+{
+ if (!callee->inherits(&QScriptObject::info))
+ return JSC::throwError(exec, JSC::TypeError, "callee is not a ClassObject object");
+ QScriptObject *obj = static_cast<QScriptObject*>(callee);
+ QScriptObjectDelegate *delegate = obj->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject))
+ return JSC::throwError(exec, JSC::TypeError, "callee is not a ClassObject object");
+
+ QScriptClass *scriptClass = static_cast<ClassObjectDelegate*>(delegate)->scriptClass();
+ QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
+
+ JSC::ExecState *oldFrame = eng_p->currentFrame;
+ eng_p->pushContext(exec, thisValue, args, callee);
+ QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame);
+ QScriptValue scriptObject = eng_p->scriptValueFromJSCValue(obj);
+ QVariant result = scriptClass->extension(QScriptClass::Callable, QVariant::fromValue(ctx));
+ eng_p->popContext();
+ eng_p->currentFrame = oldFrame;
+ return QScriptEnginePrivate::jscValueFromVariant(exec, result);
+}
+
+JSC::ConstructType ClassObjectDelegate::getConstructData(QScriptObject*, JSC::ConstructData &constructData)
+{
+ if (!m_scriptClass->supportsExtension(QScriptClass::Callable))
+ return JSC::ConstructTypeNone;
+ constructData.native.function = construct;
+ return JSC::ConstructTypeHost;
+}
+
+JSC::JSObject* ClassObjectDelegate::construct(JSC::ExecState *exec, JSC::JSObject *callee,
+ const JSC::ArgList &args)
+{
+ Q_ASSERT(callee->inherits(&QScriptObject::info));
+ QScriptObject *obj = static_cast<QScriptObject*>(callee);
+ QScriptObjectDelegate *delegate = obj->delegate();
+ QScriptClass *scriptClass = static_cast<ClassObjectDelegate*>(delegate)->scriptClass();
+
+ QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
+ JSC::ExecState *oldFrame = eng_p->currentFrame;
+ eng_p->pushContext(exec, JSC::JSValue(), args, callee, true);
+ QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame);
+
+ QScriptValue defaultObject = ctx->thisObject();
+ QScriptValue result = qvariant_cast<QScriptValue>(scriptClass->extension(QScriptClass::Callable, QVariant::fromValue(ctx)));
+ if (!result.isObject())
+ result = defaultObject;
+ eng_p->popContext();
+ eng_p->currentFrame = oldFrame;
+ return JSC::asObject(eng_p->scriptValueToJSCValue(result));
+}
+
+bool ClassObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState *exec,
+ JSC::JSValue value, JSC::JSValue proto)
+{
+ if (!scriptClass()->supportsExtension(QScriptClass::HasInstance))
+ return QScriptObjectDelegate::hasInstance(object, exec, value, proto);
+ QScriptValueList args;
+ QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
+ QScript::SaveFrameHelper saveFrame(eng_p, exec);
+ args << eng_p->scriptValueFromJSCValue(object) << eng_p->scriptValueFromJSCValue(value);
+ QVariant result = scriptClass()->extension(QScriptClass::HasInstance, QVariant::fromValue(args));
+ return result.toBool();
+}
+
+} // namespace QScript
+
+QT_END_NAMESPACE
diff --git a/src/script/bridge/qscriptclassobject_p.h b/src/script/bridge/qscriptclassobject_p.h
new file mode 100644
index 0000000..10b727a
--- /dev/null
+++ b/src/script/bridge/qscriptclassobject_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTCLASSOBJECT_P_H
+#define QSCRIPTCLASSOBJECT_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 "qscriptobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QScriptClass;
+
+namespace QScript
+{
+
+class ClassObjectDelegate : public QScriptObjectDelegate
+{
+public:
+ ClassObjectDelegate(QScriptClass *scriptClass);
+ ~ClassObjectDelegate();
+
+ inline QScriptClass *scriptClass() const;
+ inline void setScriptClass(QScriptClass *scriptClass);
+
+ virtual Type type() const;
+
+ virtual bool getOwnPropertySlot(QScriptObject*, JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ JSC::PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(QScriptObject*, JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ JSC::PropertyDescriptor&);
+ 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);
+ virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*,
+ JSC::PropertyNameArray&,
+ JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);
+
+ virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&);
+ static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*,
+ JSC::JSValue, const JSC::ArgList&);
+ virtual JSC::ConstructType getConstructData(QScriptObject*, JSC::ConstructData&);
+ static JSC::JSObject* construct(JSC::ExecState*, JSC::JSObject*,
+ const JSC::ArgList&);
+
+ virtual bool hasInstance(QScriptObject*, JSC::ExecState*,
+ JSC::JSValue value, JSC::JSValue proto);
+
+private:
+ QScriptClass *m_scriptClass;
+};
+
+inline QScriptClass *ClassObjectDelegate::scriptClass() const
+{
+ return m_scriptClass;
+}
+
+inline void ClassObjectDelegate::setScriptClass(QScriptClass *scriptClass)
+{
+ Q_ASSERT(scriptClass != 0);
+ m_scriptClass = scriptClass;
+}
+
+} // namespace QScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp
new file mode 100644
index 0000000..6126b32
--- /dev/null
+++ b/src/script/bridge/qscriptdeclarativeclass.cpp
@@ -0,0 +1,601 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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 "qscriptstaticscopeobject_p.h"
+#include <QtScript/qscriptstring.h>
+#include <QtScript/qscriptengine.h>
+#include <QtScript/qscriptengineagent.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
+
+/*!
+\class QScriptDeclarativeClass::Value
+\internal
+\brief The QScriptDeclarativeClass::Value class acts as a container for JavaScript data types.
+
+QScriptDeclarativeClass::Value class is similar to QScriptValue, but it is slightly faster.
+Unlike QScriptValue, however, Value instances cannot be stored as they may not survive garbage
+collection. If you need to store a Value, convert it to a QScriptValue and store that.
+*/
+
+QScriptDeclarativeClass::Value::Value()
+{
+ new (this) JSC::JSValue(JSC::jsUndefined());
+}
+
+QScriptDeclarativeClass::Value::Value(const Value &other)
+{
+ new (this) JSC::JSValue((JSC::JSValue &)other);
+}
+
+static QScriptDeclarativeClass::Value jscToValue(const JSC::JSValue &val)
+{
+ return QScriptDeclarativeClass::Value((QScriptDeclarativeClass::Value &)val);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, int value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, uint value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *, bool value)
+{
+ if (value)
+ new (this) JSC::JSValue(JSC::JSValue::JSTrue);
+ else
+ new (this) JSC::JSValue(JSC::JSValue::JSFalse);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, double value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, float value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, const QString &value)
+{
+ new (this) JSC::JSValue(JSC::jsString(QScriptEnginePrivate::frameForContext(ctxt), value));
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, const QScriptValue &value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::get(ctxt->engine())->scriptValueToJSCValue(value));
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, int value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, uint value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, bool value)
+{
+ if (value)
+ new (this) JSC::JSValue(JSC::JSValue::JSTrue);
+ else
+ new (this) JSC::JSValue(JSC::JSValue::JSFalse);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, double value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, float value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, const QString &value)
+{
+ new (this) JSC::JSValue(JSC::jsString(QScriptEnginePrivate::get(eng)->currentFrame, value));
+}
+
+QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, const QScriptValue &value)
+{
+ new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->scriptValueToJSCValue(value));
+}
+
+QScriptDeclarativeClass::Value::~Value()
+{
+ ((JSC::JSValue *)(this))->~JSValue();
+}
+
+QScriptValue QScriptDeclarativeClass::Value::toScriptValue(QScriptEngine *engine) const
+{
+ return QScriptEnginePrivate::get(engine)->scriptValueFromJSCValue((JSC::JSValue &)*this);
+}
+
+QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier()
+ : identifier(0), engine(0)
+{
+ new (&d) JSC::Identifier();
+}
+
+QScriptDeclarativeClass::PersistentIdentifier::~PersistentIdentifier()
+{
+ if (engine) {
+ QScript::APIShim shim(engine);
+ ((JSC::Identifier &)d).JSC::Identifier::~Identifier();
+ } else {
+ ((JSC::Identifier &)d).JSC::Identifier::~Identifier();
+ }
+}
+
+QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier(const PersistentIdentifier &other)
+{
+ identifier = other.identifier;
+ engine = other.engine;
+ new (&d) JSC::Identifier((JSC::Identifier &)(other.d));
+}
+
+QScriptDeclarativeClass::PersistentIdentifier &
+QScriptDeclarativeClass::PersistentIdentifier::operator=(const PersistentIdentifier &other)
+{
+ identifier = other.identifier;
+ engine = other.engine;
+ ((JSC::Identifier &)d) = (JSC::Identifier &)(other.d);
+ return *this;
+}
+
+QString QScriptDeclarativeClass::PersistentIdentifier::toString() const
+{
+ return ((JSC::Identifier &)d).ustring();
+}
+
+QScriptDeclarativeClass::QScriptDeclarativeClass(QScriptEngine *engine)
+: 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));
+ QScript::APIShim shim(p);
+
+ JSC::ExecState* exec = p->currentFrame;
+ QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure);
+ result->setDelegate(new QScript::DeclarativeObjectDelegate(scriptClass, object));
+ return p->scriptValueFromJSCValue(result);
+}
+
+QScriptDeclarativeClass::Value
+QScriptDeclarativeClass::newObjectValue(QScriptEngine *engine,
+ QScriptDeclarativeClass *scriptClass,
+ Object *object)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(scriptClass);
+
+ QScriptEnginePrivate *p = static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(engine));
+ QScript::APIShim shim(p);
+
+ JSC::ExecState* exec = p->currentFrame;
+ QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure);
+ result->setDelegate(new QScript::DeclarativeObjectDelegate(scriptClass, object));
+ return jscToValue(JSC::JSValue(result));
+}
+
+QScriptDeclarativeClass *QScriptDeclarativeClass::scriptClass(const QScriptValue &v)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+ if (!d || !d->isJSC())
+ return 0;
+ return QScriptEnginePrivate::declarativeClass(d->jscValue);
+}
+
+QScriptDeclarativeClass::Object *QScriptDeclarativeClass::object(const QScriptValue &v)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+ if (!d || !d->isJSC())
+ return 0;
+ return QScriptEnginePrivate::declarativeObject(d->jscValue);
+}
+
+QScriptValue QScriptDeclarativeClass::function(const QScriptValue &v, const Identifier &name)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+
+ if (!d->isObject())
+ return QScriptValue();
+
+ QScript::APIShim shim(d->engine);
+ 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();
+
+ QScript::APIShim shim(d->engine);
+ 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();
+}
+
+QScriptDeclarativeClass::Value
+QScriptDeclarativeClass::functionValue(const QScriptValue &v, const Identifier &name)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+
+ if (!d->isObject())
+ return Value();
+
+ QScript::APIShim shim(d->engine);
+ 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 jscToValue(result);
+ }
+
+ return Value();
+}
+
+QScriptDeclarativeClass::Value
+QScriptDeclarativeClass::propertyValue(const QScriptValue &v, const Identifier &name)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+
+ if (!d->isObject())
+ return Value();
+
+ QScript::APIShim shim(d->engine);
+ 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 jscToValue(result);
+ }
+
+ return Value();
+}
+
+/*
+Returns the scope chain entry at \a index. If index is less than 0, returns
+entries starting at the end. For example, scopeChainValue(context, -1) will return
+the value last in the scope chain.
+*/
+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);
+ QScript::APIShim shim(engine);
+
+ JSC::ScopeChainNode *node = frame->scopeChain();
+ JSC::ScopeChainIterator it(node);
+
+ if (index < 0) {
+ int count = 0;
+ for (it = node->begin(); it != node->end(); ++it)
+ ++count;
+
+ index = qAbs(index);
+ if (index > count)
+ return QScriptValue();
+ else
+ index = count - index;
+ }
+
+ for (it = node->begin(); it != node->end(); ++it) {
+
+ if (index == 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 {
+ --index;
+ }
+
+ }
+
+ return QScriptValue();
+}
+
+/*!
+ 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 QScriptEngine::popContext()
+*/
+QScriptContext * QScriptDeclarativeClass::pushCleanContext(QScriptEngine *engine)
+{
+ if (!engine)
+ return 0;
+
+ QScriptEnginePrivate *d = QScriptEnginePrivate::get(engine);
+ QScript::APIShim shim(d);
+
+ JSC::CallFrame* newFrame = d->pushContext(d->currentFrame,
+ d->currentFrame->globalData().dynamicGlobalObject,
+ JSC::ArgList(), /*callee = */0, false, true);
+
+ if (engine->agent())
+ engine->agent()->contextPush();
+
+ return d->contextForFrame(newFrame);
+}
+
+QScriptDeclarativeClass::~QScriptDeclarativeClass()
+{
+}
+
+QScriptEngine *QScriptDeclarativeClass::engine() const
+{
+ return d_ptr->engine;
+}
+
+bool QScriptDeclarativeClass::supportsCall() const
+{
+ return d_ptr->supportsCall;
+}
+
+void QScriptDeclarativeClass::setSupportsCall(bool c)
+{
+ d_ptr->supportsCall = c;
+}
+
+QScriptDeclarativeClass::PersistentIdentifier
+QScriptDeclarativeClass::createPersistentIdentifier(const QString &str)
+{
+ QScriptEnginePrivate *p =
+ static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine));
+ QScript::APIShim shim(p);
+ JSC::ExecState* exec = p->currentFrame;
+
+ PersistentIdentifier rv(p);
+ 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));
+ QScript::APIShim shim(p);
+ JSC::ExecState* exec = p->currentFrame;
+
+ PersistentIdentifier rv(p);
+ 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());
+}
+
+bool QScriptDeclarativeClass::startsWithUpper(const Identifier &identifier)
+{
+ JSC::UString::Rep *r = (JSC::UString::Rep *)identifier;
+ if (r->size() < 1)
+ return false;
+ return QChar::category((ushort)(r->data()[0])) == QChar::Letter_Uppercase;
+}
+
+quint32 QScriptDeclarativeClass::toArrayIndex(const Identifier &identifier, bool *ok)
+{
+ JSC::UString::Rep *r = (JSC::UString::Rep *)identifier;
+ JSC::UString s(r);
+ return s.toArrayIndex(ok);
+}
+
+QScriptClass::QueryFlags
+QScriptDeclarativeClass::queryProperty(Object *object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ Q_UNUSED(flags);
+ return 0;
+}
+
+QScriptDeclarativeClass::Value
+QScriptDeclarativeClass::property(Object *object, const Identifier &name)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ return Value();
+}
+
+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;
+}
+
+QScriptDeclarativeClass::Value QScriptDeclarativeClass::call(Object *object,
+ QScriptContext *ctxt)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(ctxt);
+ return Value();
+}
+
+bool QScriptDeclarativeClass::compare(Object *o, Object *o2)
+{
+ return o == o2;
+}
+
+QStringList QScriptDeclarativeClass::propertyNames(Object *object)
+{
+ Q_UNUSED(object);
+ return QStringList();
+}
+
+bool QScriptDeclarativeClass::isQObject() const
+{
+ return false;
+}
+
+QObject *QScriptDeclarativeClass::toQObject(Object *, bool *ok)
+{
+ if (ok) *ok = false;
+ return 0;
+}
+
+QVariant QScriptDeclarativeClass::toVariant(Object *, bool *ok)
+{
+ if (ok) *ok = false;
+ return QVariant();
+}
+
+QScriptContext *QScriptDeclarativeClass::context() const
+{
+ return d_ptr->context;
+}
+
+/*!
+ Creates a scope object with a fixed set of undeletable properties.
+*/
+QScriptValue QScriptDeclarativeClass::newStaticScopeObject(
+ QScriptEngine *engine, int propertyCount, const QString *names,
+ const QScriptValue *values, const QScriptValue::PropertyFlags *flags)
+{
+ QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine);
+ QScript::APIShim shim(eng_p);
+ JSC::ExecState *exec = eng_p->currentFrame;
+ QScriptStaticScopeObject::PropertyInfo *props = new QScriptStaticScopeObject::PropertyInfo[propertyCount];
+ for (int i = 0; i < propertyCount; ++i) {
+ unsigned attribs = QScriptEnginePrivate::propertyFlagsToJSCAttributes(flags[i]);
+ Q_ASSERT_X(attribs & JSC::DontDelete, Q_FUNC_INFO, "All properties must be undeletable");
+ JSC::Identifier id = JSC::Identifier(exec, names[i]);
+ JSC::JSValue jsval = eng_p->scriptValueToJSCValue(values[i]);
+ props[i] = QScriptStaticScopeObject::PropertyInfo(id, jsval, attribs);
+ }
+ QScriptValue result = eng_p->scriptValueFromJSCValue(new (exec)QScriptStaticScopeObject(eng_p->staticScopeObjectStructure,
+ propertyCount, props));
+ delete[] props;
+ return result;
+}
+
+/*!
+ Creates a static scope object that's initially empty, but to which new
+ properties can be added.
+*/
+QScriptValue QScriptDeclarativeClass::newStaticScopeObject(QScriptEngine *engine)
+{
+ QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine);
+ QScript::APIShim shim(eng_p);
+ return eng_p->scriptValueFromJSCValue(new (eng_p->currentFrame)QScriptStaticScopeObject(eng_p->staticScopeObjectStructure));
+}
+
+QT_END_NAMESPACE
diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h
new file mode 100644
index 0000000..e4c18f5
--- /dev/null
+++ b/src/script/bridge/qscriptdeclarativeclass_p.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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:
+#define QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE
+ class Q_SCRIPT_EXPORT Value
+ {
+ public:
+ Value();
+ Value(const Value &);
+
+ Value(QScriptContext *, int);
+ Value(QScriptContext *, uint);
+ Value(QScriptContext *, bool);
+ Value(QScriptContext *, double);
+ Value(QScriptContext *, float);
+ Value(QScriptContext *, const QString &);
+ Value(QScriptContext *, const QScriptValue &);
+ Value(QScriptEngine *, int);
+ Value(QScriptEngine *, uint);
+ Value(QScriptEngine *, bool);
+ Value(QScriptEngine *, double);
+ Value(QScriptEngine *, float);
+ Value(QScriptEngine *, const QString &);
+ Value(QScriptEngine *, const QScriptValue &);
+ ~Value();
+
+ QScriptValue toScriptValue(QScriptEngine *) const;
+ private:
+ char dummy[8];
+ };
+
+ typedef void* Identifier;
+
+ struct Object { virtual ~Object() {} };
+
+ static QScriptValue newObject(QScriptEngine *, QScriptDeclarativeClass *, Object *);
+ static Value newObjectValue(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 Value functionValue(const QScriptValue &, const Identifier &);
+ static Value propertyValue(const QScriptValue &, const Identifier &);
+
+ static QScriptValue scopeChainValue(QScriptContext *, int index);
+ static QScriptContext *pushCleanContext(QScriptEngine *);
+
+ static QScriptValue newStaticScopeObject(
+ QScriptEngine *, int propertyCount, const QString *names,
+ const QScriptValue *values, const QScriptValue::PropertyFlags *flags);
+ static QScriptValue newStaticScopeObject(QScriptEngine *);
+
+ class Q_SCRIPT_EXPORT PersistentIdentifier
+ {
+ public:
+ Identifier identifier;
+
+ PersistentIdentifier();
+ ~PersistentIdentifier();
+ PersistentIdentifier(const PersistentIdentifier &other);
+ PersistentIdentifier &operator=(const PersistentIdentifier &other);
+
+ QString toString() const;
+ private:
+ friend class QScriptDeclarativeClass;
+ PersistentIdentifier(QScriptEnginePrivate *e) : identifier(0), engine(e), d(0) {}
+ QScriptEnginePrivate *engine;
+ void *d;
+ };
+
+ QScriptDeclarativeClass(QScriptEngine *engine);
+ virtual ~QScriptDeclarativeClass();
+
+ QScriptEngine *engine() const;
+
+ bool supportsCall() const;
+ void setSupportsCall(bool);
+
+ PersistentIdentifier createPersistentIdentifier(const QString &);
+ PersistentIdentifier createPersistentIdentifier(const Identifier &);
+
+ QString toString(const Identifier &);
+ bool startsWithUpper(const Identifier &);
+ quint32 toArrayIndex(const Identifier &, bool *ok);
+
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+
+ virtual Value property(Object *, const Identifier &);
+ virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+ virtual QScriptValue::PropertyFlags propertyFlags(Object *, const Identifier &);
+ virtual Value call(Object *, QScriptContext *);
+ virtual bool compare(Object *, Object *);
+
+ virtual QStringList propertyNames(Object *);
+
+ virtual bool isQObject() const;
+ virtual QObject *toQObject(Object *, bool *ok = 0);
+ virtual QVariant toVariant(Object *, bool *ok = 0);
+
+ QScriptContext *context() const;
+protected:
+ friend class QScriptDeclarativeClassPrivate;
+ 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..201f2c0
--- /dev/null
+++ b/src/script/bridge/qscriptdeclarativeobject.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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)
+{
+ QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep();
+
+ QScriptDeclarativeClassPrivate *p = QScriptDeclarativeClassPrivate::get(m_class);
+ p->context = reinterpret_cast<QScriptContext *>(exec);
+ QScriptClass::QueryFlags flags =
+ m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess);
+ if (flags & QScriptClass::HandlesReadAccess) {
+ QScriptDeclarativeClass::Value val = m_class->property(m_object, identifier);
+ p->context = 0;
+ slot.setValue((const JSC::JSValue &)val);
+ return true;
+ }
+ p->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);
+ QScript::SaveFrameHelper saveFrame(engine, exec);
+ QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep();
+
+ QScriptDeclarativeClassPrivate *p = QScriptDeclarativeClassPrivate::get(m_class);
+ p->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));
+ p->context = 0;
+ return;
+ }
+ p->context = 0;
+
+ QScriptObjectDelegate::put(object, exec, propertyName, value, slot);
+}
+
+bool DeclarativeObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState *exec,
+ const JSC::Identifier &propertyName)
+{
+ return QScriptObjectDelegate::deleteProperty(object, exec, propertyName);
+}
+
+void DeclarativeObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState *exec,
+ JSC::PropertyNameArray &propertyNames,
+ JSC::EnumerationMode mode)
+{
+ 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, mode);
+}
+
+JSC::CallType DeclarativeObjectDelegate::getCallData(QScriptObject *object, JSC::CallData &callData)
+{
+ if (!QScriptDeclarativeClassPrivate::get(m_class)->supportsCall)
+ return JSC::CallTypeNone;
+ callData.native.function = call;
+ return JSC::CallTypeHost;
+}
+
+JSC::JSValue DeclarativeObjectDelegate::call(JSC::ExecState *exec, JSC::JSObject *callee,
+ JSC::JSValue thisValue, const JSC::ArgList &args)
+{
+ if (!callee->inherits(&QScriptObject::info))
+ return JSC::throwError(exec, JSC::TypeError, "callee is not a DeclarativeObject object");
+ QScriptObject *obj = static_cast<QScriptObject*>(callee);
+ QScriptObjectDelegate *delegate = obj->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject))
+ return JSC::throwError(exec, JSC::TypeError, "callee is not a DeclarativeObject object");
+
+ QScriptDeclarativeClass *scriptClass = static_cast<DeclarativeObjectDelegate*>(delegate)->m_class;
+ QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
+
+ QScript::SaveFrameHelper saveFrame(eng_p, exec);
+ eng_p->pushContext(exec, thisValue, args, callee);
+ QScriptContext *ctxt = eng_p->contextForFrame(eng_p->currentFrame);
+
+ QScriptValue scriptObject = eng_p->scriptValueFromJSCValue(obj);
+ QScriptDeclarativeClass::Value result =
+ scriptClass->call(static_cast<DeclarativeObjectDelegate*>(delegate)->m_object, ctxt);
+
+ eng_p->popContext();
+ return (JSC::JSValue &)(result);
+}
+
+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);
+}
+
+bool DeclarativeObjectDelegate::compareToObject(QScriptObject *o, JSC::ExecState *exec, JSC::JSObject *o2)
+{
+ if (!o2->inherits(&QScriptObject::info))
+ return false;
+
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(o2);
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject))
+ return false;
+
+ DeclarativeObjectDelegate *other = static_cast<DeclarativeObjectDelegate*>(delegate);
+ if (m_class != other->m_class)
+ return false;
+ else
+ return m_class->compare(m_object, other->m_object);
+}
+
+} // 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..b2a30d7
--- /dev/null
+++ b/src/script/bridge/qscriptdeclarativeobject_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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;
+
+class QScriptDeclarativeClassPrivate
+{
+public:
+ QScriptDeclarativeClassPrivate() : engine(0), q_ptr(0), context(0), supportsCall(false) {}
+
+ QScriptEngine *engine;
+ QScriptDeclarativeClass *q_ptr;
+ QScriptContext *context;
+ bool supportsCall:1;
+
+ static QScriptDeclarativeClassPrivate *get(QScriptDeclarativeClass *c) {
+ return c->d_ptr.data();
+ }
+};
+
+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);
+ virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*,
+ JSC::PropertyNameArray&,
+ JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);
+
+ virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&);
+ static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*,
+ JSC::JSValue, const JSC::ArgList&);
+
+ virtual JSC::ConstructType getConstructData(QScriptObject*, JSC::ConstructData&);
+
+ virtual bool hasInstance(QScriptObject*, JSC::ExecState*,
+ JSC::JSValue value, JSC::JSValue proto);
+
+ bool compareToObject(QScriptObject *, JSC::ExecState *, JSC::JSObject *);
+
+private:
+ QScriptDeclarativeClass *m_class;
+ QScriptDeclarativeClass::Object *m_object;
+};
+
+} // namespace QScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/bridge/qscriptfunction.cpp b/src/script/bridge/qscriptfunction.cpp
new file mode 100644
index 0000000..0480ce7
--- /dev/null
+++ b/src/script/bridge/qscriptfunction.cpp
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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 "qscriptfunction_p.h"
+
+#include "private/qscriptengine_p.h"
+#include "qscriptcontext.h"
+#include "private/qscriptcontext_p.h"
+#include "private/qscriptvalue_p.h"
+#include "qscriptactivationobject_p.h"
+#include "qscriptobject_p.h"
+
+#include "JSGlobalObject.h"
+#include "DebuggerCallFrame.h"
+#include "Debugger.h"
+
+namespace JSC
+{
+ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScript::FunctionWrapper));
+ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScript::FunctionWithArgWrapper));
+}
+
+QT_BEGIN_NAMESPACE
+
+namespace QScript
+{
+
+const JSC::ClassInfo FunctionWrapper::info = { "QtNativeFunctionWrapper", &PrototypeFunction::info, 0, 0 };
+const JSC::ClassInfo FunctionWithArgWrapper::info = { "QtNativeFunctionWithArgWrapper", &PrototypeFunction::info, 0, 0 };
+
+FunctionWrapper::FunctionWrapper(JSC::ExecState *exec, int length, const JSC::Identifier &name,
+ QScriptEngine::FunctionSignature function)
+ : JSC::PrototypeFunction(exec, length, name, proxyCall),
+ data(new Data())
+{
+ data->function = function;
+}
+
+FunctionWrapper::~FunctionWrapper()
+{
+ delete data;
+}
+
+JSC::ConstructType FunctionWrapper::getConstructData(JSC::ConstructData& consData)
+{
+ consData.native.function = proxyConstruct;
+ consData.native.function.doNotCallDebuggerFunctionExit();
+ return JSC::ConstructTypeHost;
+}
+
+JSC::JSValue FunctionWrapper::proxyCall(JSC::ExecState *exec, JSC::JSObject *callee,
+ JSC::JSValue thisObject, const JSC::ArgList &args)
+{
+ FunctionWrapper *self = static_cast<FunctionWrapper*>(callee);
+ QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec);
+
+ JSC::ExecState *oldFrame = eng_p->currentFrame;
+ eng_p->pushContext(exec, thisObject, args, callee);
+ QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame);
+
+ QScriptValue result = self->data->function(ctx, QScriptEnginePrivate::get(eng_p));
+ if (!result.isValid())
+ result = QScriptValue(QScriptValue::UndefinedValue);
+
+ eng_p->popContext();
+ eng_p->currentFrame = oldFrame;
+
+ return eng_p->scriptValueToJSCValue(result);
+}
+
+JSC::JSObject* FunctionWrapper::proxyConstruct(JSC::ExecState *exec, JSC::JSObject *callee,
+ const JSC::ArgList &args)
+{
+ FunctionWrapper *self = static_cast<FunctionWrapper*>(callee);
+ QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec);
+
+ JSC::ExecState *oldFrame = eng_p->currentFrame;
+ eng_p->pushContext(exec, JSC::JSValue(), args, callee, true);
+ QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame);
+
+ QScriptValue result = self->data->function(ctx, QScriptEnginePrivate::get(eng_p));
+
+ if (JSC::Debugger* debugger = eng_p->originalGlobalObject()->debugger())
+ debugger->functionExit(QScriptValuePrivate::get(result)->jscValue, -1);
+
+ if (!result.isObject())
+ result = ctx->thisObject();
+
+ eng_p->popContext();
+ eng_p->currentFrame = oldFrame;
+
+ return JSC::asObject(eng_p->scriptValueToJSCValue(result));
+}
+
+FunctionWithArgWrapper::FunctionWithArgWrapper(JSC::ExecState *exec, int length, const JSC::Identifier &name,
+ QScriptEngine::FunctionWithArgSignature function, void *arg)
+ : JSC::PrototypeFunction(exec, length, name, proxyCall),
+ data(new Data())
+{
+ data->function = function;
+ data->arg = arg;
+}
+
+FunctionWithArgWrapper::~FunctionWithArgWrapper()
+{
+ delete data;
+}
+
+JSC::ConstructType FunctionWithArgWrapper::getConstructData(JSC::ConstructData& consData)
+{
+ consData.native.function = proxyConstruct;
+ return JSC::ConstructTypeHost;
+}
+
+JSC::JSValue FunctionWithArgWrapper::proxyCall(JSC::ExecState *exec, JSC::JSObject *callee,
+ JSC::JSValue thisObject, const JSC::ArgList &args)
+{
+ FunctionWithArgWrapper *self = static_cast<FunctionWithArgWrapper*>(callee);
+ QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec);
+
+ JSC::ExecState *oldFrame = eng_p->currentFrame;
+ eng_p->pushContext(exec, thisObject, args, callee);
+ QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame);
+
+ QScriptValue result = self->data->function(ctx, QScriptEnginePrivate::get(eng_p), self->data->arg);
+
+ eng_p->popContext();
+ eng_p->currentFrame = oldFrame;
+
+ return eng_p->scriptValueToJSCValue(result);
+}
+
+JSC::JSObject* FunctionWithArgWrapper::proxyConstruct(JSC::ExecState *exec, JSC::JSObject *callee,
+ const JSC::ArgList &args)
+{
+ FunctionWithArgWrapper *self = static_cast<FunctionWithArgWrapper*>(callee);
+ QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec);
+
+ JSC::ExecState *oldFrame = eng_p->currentFrame;
+ eng_p->pushContext(exec, JSC::JSValue(), args, callee, true);
+ QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame);
+
+ QScriptValue result = self->data->function(ctx, QScriptEnginePrivate::get(eng_p) , self->data->arg);
+ if (!result.isObject())
+ result = ctx->thisObject();
+
+ eng_p->popContext();
+ eng_p->currentFrame = oldFrame;
+
+ return JSC::asObject(eng_p->scriptValueToJSCValue(result));
+}
+
+} // namespace QScript
+
+QT_END_NAMESPACE
diff --git a/src/script/bridge/qscriptfunction_p.h b/src/script/bridge/qscriptfunction_p.h
new file mode 100644
index 0000000..075ba52
--- /dev/null
+++ b/src/script/bridge/qscriptfunction_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTFUNCTION_P_H
+#define QSCRIPTFUNCTIOn_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/qglobal.h>
+
+#include "qscriptengine.h"
+
+#include "PrototypeFunction.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QScript
+{
+
+class FunctionWrapper : public JSC::PrototypeFunction // ### subclass InternalFunction instead
+{
+public:
+ // work around CELL_SIZE limitation
+ struct Data
+ {
+ QScriptEngine::FunctionSignature function;
+ };
+
+ FunctionWrapper(JSC::ExecState*, int length, const JSC::Identifier&,
+ QScriptEngine::FunctionSignature);
+ ~FunctionWrapper();
+
+ virtual const JSC::ClassInfo* classInfo() const { return &info; }
+ static const JSC::ClassInfo info;
+
+ QScriptEngine::FunctionSignature function() const
+ { return data->function; }
+
+private:
+ virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
+
+ static JSC::JSValue JSC_HOST_CALL proxyCall(JSC::ExecState *, JSC::JSObject *,
+ JSC::JSValue, const JSC::ArgList &);
+ static JSC::JSObject* proxyConstruct(JSC::ExecState *, JSC::JSObject *,
+ const JSC::ArgList &);
+
+private:
+ Data *data;
+};
+
+class FunctionWithArgWrapper : public JSC::PrototypeFunction
+{
+public:
+ // work around CELL_SIZE limitation
+ struct Data
+ {
+ QScriptEngine::FunctionWithArgSignature function;
+ void *arg;
+ };
+
+ FunctionWithArgWrapper(JSC::ExecState*, int length, const JSC::Identifier&,
+ QScriptEngine::FunctionWithArgSignature, void *);
+ ~FunctionWithArgWrapper();
+
+ virtual const JSC::ClassInfo* classInfo() const { return &info; }
+ static const JSC::ClassInfo info;
+
+ QScriptEngine::FunctionWithArgSignature function() const
+ { return data->function; }
+
+ void *arg() const
+ { return data->arg; }
+
+private:
+ virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
+
+ static JSC::JSValue JSC_HOST_CALL proxyCall(JSC::ExecState *, JSC::JSObject *,
+ JSC::JSValue , const JSC::ArgList &);
+ static JSC::JSObject* proxyConstruct(JSC::ExecState *, JSC::JSObject *,
+ const JSC::ArgList &);
+
+private:
+ Data *data;
+};
+
+} // namespace QScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/bridge/qscriptglobalobject.cpp b/src/script/bridge/qscriptglobalobject.cpp
new file mode 100644
index 0000000..ee016e9
--- /dev/null
+++ b/src/script/bridge/qscriptglobalobject.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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 "qscriptglobalobject_p.h"
+
+#include "../api/qscriptengine.h"
+#include "../api/qscriptengine_p.h"
+
+namespace JSC
+{
+QT_USE_NAMESPACE
+
+ASSERT_CLASS_FITS_IN_CELL(QScript::GlobalObject);
+ASSERT_CLASS_FITS_IN_CELL(QScript::OriginalGlobalObjectProxy);
+
+} // namespace JSC
+
+QT_BEGIN_NAMESPACE
+
+namespace QScript
+{
+
+GlobalObject::GlobalObject()
+ : JSC::JSGlobalObject(), customGlobalObject(0)
+{
+}
+
+GlobalObject::~GlobalObject()
+{
+}
+
+void GlobalObject::markChildren(JSC::MarkStack& markStack)
+{
+ JSC::JSGlobalObject::markChildren(markStack);
+ if (customGlobalObject)
+ markStack.append(customGlobalObject);
+}
+
+bool GlobalObject::getOwnPropertySlot(JSC::ExecState* exec,
+ const JSC::Identifier& propertyName,
+ JSC::PropertySlot& slot)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ if (propertyName == exec->propertyNames().arguments && engine->currentFrame->argumentCount() > 0) {
+ JSC::JSValue args = engine->scriptValueToJSCValue(engine->contextForFrame(engine->currentFrame)->argumentsObject());
+ slot.setValue(args);
+ return true;
+ }
+ if (customGlobalObject)
+ return customGlobalObject->getOwnPropertySlot(exec, propertyName, slot);
+ return JSC::JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool GlobalObject::getOwnPropertyDescriptor(JSC::ExecState* exec,
+ const JSC::Identifier& propertyName,
+ JSC::PropertyDescriptor& descriptor)
+{
+ // Must match the logic of getOwnPropertySlot().
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ if (propertyName == exec->propertyNames().arguments && engine->currentFrame->argumentCount() > 0) {
+ // ### Can we get rid of this special handling of the arguments property?
+ JSC::JSValue args = engine->scriptValueToJSCValue(engine->contextForFrame(engine->currentFrame)->argumentsObject());
+ descriptor.setValue(args);
+ return true;
+ }
+ if (customGlobalObject)
+ return customGlobalObject->getOwnPropertyDescriptor(exec, propertyName, descriptor);
+ return JSC::JSGlobalObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
+void GlobalObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName,
+ JSC::JSValue value, JSC::PutPropertySlot& slot)
+{
+ if (customGlobalObject)
+ customGlobalObject->put(exec, propertyName, value, slot);
+ else
+ JSC::JSGlobalObject::put(exec, propertyName, value, slot);
+}
+
+void GlobalObject::putWithAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName,
+ JSC::JSValue value, unsigned attributes)
+{
+ if (customGlobalObject)
+ customGlobalObject->putWithAttributes(exec, propertyName, value, attributes);
+ else
+ JSC::JSGlobalObject::putWithAttributes(exec, propertyName, value, attributes);
+}
+
+bool GlobalObject::deleteProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName)
+{
+ if (customGlobalObject)
+ return customGlobalObject->deleteProperty(exec, propertyName);
+ return JSC::JSGlobalObject::deleteProperty(exec, propertyName);
+}
+
+void GlobalObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames,
+ JSC::EnumerationMode mode)
+{
+ if (customGlobalObject)
+ customGlobalObject->getOwnPropertyNames(exec, propertyNames, mode);
+ else
+ JSC::JSGlobalObject::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
+void GlobalObject::defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes)
+{
+ if (customGlobalObject)
+ customGlobalObject->defineGetter(exec, propertyName, getterFunction, attributes);
+ else
+ JSC::JSGlobalObject::defineGetter(exec, propertyName, getterFunction, attributes);
+}
+
+void GlobalObject::defineSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes)
+{
+ if (customGlobalObject)
+ customGlobalObject->defineSetter(exec, propertyName, setterFunction, attributes);
+ else
+ JSC::JSGlobalObject::defineSetter(exec, propertyName, setterFunction, attributes);
+}
+
+JSC::JSValue GlobalObject::lookupGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName)
+{
+ if (customGlobalObject)
+ return customGlobalObject->lookupGetter(exec, propertyName);
+ return JSC::JSGlobalObject::lookupGetter(exec, propertyName);
+}
+
+JSC::JSValue GlobalObject::lookupSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName)
+{
+ if (customGlobalObject)
+ return customGlobalObject->lookupSetter(exec, propertyName);
+ return JSC::JSGlobalObject::lookupSetter(exec, propertyName);
+}
+
+} // namespace QScript
+
+QT_END_NAMESPACE
diff --git a/src/script/bridge/qscriptglobalobject_p.h b/src/script/bridge/qscriptglobalobject_p.h
new file mode 100644
index 0000000..e17efdf
--- /dev/null
+++ b/src/script/bridge/qscriptglobalobject_p.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTGLOBALOBJECT_P_H
+#define QSCRIPTGLOBALOBJECT_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 "JSGlobalObject.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QScript
+{
+
+class GlobalObject : public JSC::JSGlobalObject
+{
+public:
+ GlobalObject();
+ virtual ~GlobalObject();
+ virtual JSC::UString className() const { return "global"; }
+ virtual void markChildren(JSC::MarkStack&);
+ virtual bool getOwnPropertySlot(JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ JSC::PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ JSC::PropertyDescriptor&);
+ virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName,
+ JSC::JSValue, JSC::PutPropertySlot&);
+ virtual void putWithAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName,
+ JSC::JSValue value, unsigned attributes);
+ virtual bool deleteProperty(JSC::ExecState*,
+ const JSC::Identifier& propertyName);
+ virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&,
+ JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);
+ virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes = 0);
+ virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes = 0);
+ virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);
+ virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);
+
+public:
+ JSC::JSObject *customGlobalObject;
+};
+
+class OriginalGlobalObjectProxy : public JSC::JSObject
+{
+public:
+ explicit OriginalGlobalObjectProxy(WTF::PassRefPtr<JSC::Structure> sid,
+ JSC::JSGlobalObject *object)
+ : JSC::JSObject(sid), originalGlobalObject(object)
+ {}
+ virtual ~OriginalGlobalObjectProxy()
+ {}
+ virtual JSC::UString className() const
+ { return originalGlobalObject->className(); }
+ virtual void markChildren(JSC::MarkStack& markStack)
+ {
+ markStack.append(originalGlobalObject);
+ JSC::JSObject::markChildren(markStack);
+ }
+ virtual bool getOwnPropertySlot(JSC::ExecState* exec,
+ const JSC::Identifier& propertyName,
+ JSC::PropertySlot& slot)
+ { return originalGlobalObject->JSC::JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot); }
+ virtual bool getOwnPropertyDescriptor(JSC::ExecState* exec,
+ const JSC::Identifier& propertyName,
+ JSC::PropertyDescriptor& descriptor)
+ { return originalGlobalObject->JSC::JSGlobalObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); }
+ virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName,
+ JSC::JSValue value, JSC::PutPropertySlot& slot)
+ { originalGlobalObject->JSC::JSGlobalObject::put(exec, propertyName, value, slot); }
+ virtual void putWithAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, unsigned attributes)
+ { originalGlobalObject->JSC::JSGlobalObject::putWithAttributes(exec, propertyName, value, attributes); }
+ virtual bool deleteProperty(JSC::ExecState* exec,
+ const JSC::Identifier& propertyName)
+ { return originalGlobalObject->JSC::JSGlobalObject::deleteProperty(exec, propertyName); }
+ virtual void getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties)
+ { originalGlobalObject->JSC::JSGlobalObject::getOwnPropertyNames(exec, propertyNames, mode); }
+ virtual void defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes)
+ { originalGlobalObject->JSC::JSGlobalObject::defineGetter(exec, propertyName, getterFunction, attributes); }
+ virtual void defineSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes)
+ { originalGlobalObject->JSC::JSGlobalObject::defineSetter(exec, propertyName, setterFunction, attributes); }
+ virtual JSC::JSValue lookupGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName)
+ { return originalGlobalObject->JSC::JSGlobalObject::lookupGetter(exec, propertyName); }
+ virtual JSC::JSValue lookupSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName)
+ { return originalGlobalObject->JSC::JSGlobalObject::lookupSetter(exec, propertyName); }
+private:
+ JSC::JSGlobalObject *originalGlobalObject;
+};
+
+} // namespace QScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/bridge/qscriptobject.cpp b/src/script/bridge/qscriptobject.cpp
new file mode 100644
index 0000000..5d57c66
--- /dev/null
+++ b/src/script/bridge/qscriptobject.cpp
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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 "qscriptobject_p.h"
+#include "private/qobject_p.h"
+
+namespace JSC
+{
+//QT_USE_NAMESPACE
+ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScriptObject));
+ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScriptObjectPrototype));
+}
+
+QT_BEGIN_NAMESPACE
+
+// masquerading as JSC::JSObject
+const JSC::ClassInfo QScriptObject::info = { "Object", 0, 0, 0 };
+
+QScriptObject::Data::~Data()
+{
+ delete delegate;
+}
+
+QScriptObject::QScriptObject(WTF::PassRefPtr<JSC::Structure> sid)
+ : JSC::JSObject(sid), d(0)
+{
+}
+
+QScriptObject::~QScriptObject()
+{
+ delete d;
+}
+
+bool QScriptObject::getOwnPropertySlot(JSC::ExecState* exec,
+ const JSC::Identifier& propertyName,
+ JSC::PropertySlot& slot)
+{
+ if (!d || !d->delegate)
+ return JSC::JSObject::getOwnPropertySlot(exec, propertyName, slot);
+ return d->delegate->getOwnPropertySlot(this, exec, propertyName, slot);
+}
+
+bool QScriptObject::getOwnPropertyDescriptor(JSC::ExecState* exec,
+ const JSC::Identifier& propertyName,
+ JSC::PropertyDescriptor& descriptor)
+{
+ if (!d || !d->delegate)
+ return JSC::JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+ return d->delegate->getOwnPropertyDescriptor(this, exec, propertyName, descriptor);
+}
+
+void QScriptObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName,
+ JSC::JSValue value, JSC::PutPropertySlot& slot)
+{
+ if (!d || !d->delegate) {
+ JSC::JSObject::put(exec, propertyName, value, slot);
+ return;
+ }
+ d->delegate->put(this, exec, propertyName, value, slot);
+}
+
+bool QScriptObject::deleteProperty(JSC::ExecState* exec,
+ const JSC::Identifier& propertyName)
+{
+ if (!d || !d->delegate)
+ return JSC::JSObject::deleteProperty(exec, propertyName);
+ return d->delegate->deleteProperty(this, exec, propertyName);
+}
+
+void QScriptObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames,
+ JSC::EnumerationMode mode)
+{
+ if (!d || !d->delegate) {
+ JSC::JSObject::getOwnPropertyNames(exec, propertyNames, mode);
+ return;
+ }
+ d->delegate->getOwnPropertyNames(this, exec, propertyNames, mode);
+}
+
+bool QScriptObject::compareToObject(JSC::ExecState* exec, JSC::JSObject *other)
+{
+ if (!d || !d->delegate) {
+ return JSC::JSObject::compareToObject(exec, other);
+ }
+ return d->delegate->compareToObject(this, exec, other);
+}
+
+void QScriptObject::markChildren(JSC::MarkStack& markStack)
+{
+ if (!d)
+ d = new Data();
+ if (d->isMarking)
+ return;
+ QBoolBlocker markBlocker(d->isMarking, true);
+ if (d && d->data)
+ markStack.append(d->data);
+ if (!d || !d->delegate) {
+ JSC::JSObject::markChildren(markStack);
+ return;
+ }
+ d->delegate->markChildren(this, markStack);
+}
+
+JSC::CallType QScriptObject::getCallData(JSC::CallData &data)
+{
+ if (!d || !d->delegate)
+ return JSC::JSObject::getCallData(data);
+ return d->delegate->getCallData(this, data);
+}
+
+JSC::ConstructType QScriptObject::getConstructData(JSC::ConstructData &data)
+{
+ if (!d || !d->delegate)
+ return JSC::JSObject::getConstructData(data);
+ return d->delegate->getConstructData(this, data);
+}
+
+bool QScriptObject::hasInstance(JSC::ExecState* exec, JSC::JSValue value, JSC::JSValue proto)
+{
+ if (!d || !d->delegate)
+ return JSC::JSObject::hasInstance(exec, value, proto);
+ return d->delegate->hasInstance(this, exec, value, proto);
+}
+
+QScriptObjectPrototype::QScriptObjectPrototype(JSC::ExecState*, WTF::PassRefPtr<JSC::Structure> structure,
+ JSC::Structure* /*prototypeFunctionStructure*/)
+ : QScriptObject(structure)
+{
+}
+
+QScriptObjectDelegate::QScriptObjectDelegate()
+{
+}
+
+QScriptObjectDelegate::~QScriptObjectDelegate()
+{
+}
+
+bool QScriptObjectDelegate::getOwnPropertySlot(QScriptObject* object, JSC::ExecState* exec,
+ const JSC::Identifier& propertyName,
+ JSC::PropertySlot& slot)
+{
+ return object->JSC::JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool QScriptObjectDelegate::getOwnPropertyDescriptor(QScriptObject* object, JSC::ExecState* exec,
+ const JSC::Identifier& propertyName,
+ JSC::PropertyDescriptor& descriptor)
+{
+ return object->JSC::JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
+
+void QScriptObjectDelegate::put(QScriptObject* object, JSC::ExecState* exec,
+ const JSC::Identifier& propertyName,
+ JSC::JSValue value, JSC::PutPropertySlot& slot)
+{
+ object->JSC::JSObject::put(exec, propertyName, value, slot);
+}
+
+bool QScriptObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState* exec,
+ const JSC::Identifier& propertyName)
+{
+ return object->JSC::JSObject::deleteProperty(exec, propertyName);
+}
+
+void QScriptObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState* exec,
+ JSC::PropertyNameArray& propertyNames,
+ JSC::EnumerationMode mode)
+{
+ object->JSC::JSObject::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
+void QScriptObjectDelegate::markChildren(QScriptObject* object, JSC::MarkStack& markStack)
+{
+ // ### should this call the virtual function instead??
+ object->JSC::JSObject::markChildren(markStack);
+}
+
+JSC::CallType QScriptObjectDelegate::getCallData(QScriptObject* object, JSC::CallData& data)
+{
+ return object->JSC::JSObject::getCallData(data);
+}
+
+JSC::ConstructType QScriptObjectDelegate::getConstructData(QScriptObject* object, JSC::ConstructData& data)
+{
+ return object->JSC::JSObject::getConstructData(data);
+}
+
+bool QScriptObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState* exec,
+ JSC::JSValue value, JSC::JSValue proto)
+{
+ return object->JSC::JSObject::hasInstance(exec, value, proto);
+}
+
+bool QScriptObjectDelegate::compareToObject(QScriptObject* object, JSC::ExecState* exec, JSC::JSObject* o)
+{
+ return object->JSC::JSObject::compareToObject(exec, o);
+}
+
+QT_END_NAMESPACE
diff --git a/src/script/bridge/qscriptobject_p.h b/src/script/bridge/qscriptobject_p.h
new file mode 100644
index 0000000..c9613ea
--- /dev/null
+++ b/src/script/bridge/qscriptobject_p.h
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTOBJECT_P_H
+#define QSCRIPTOBJECT_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 "JSObject.h"
+
+QT_BEGIN_NAMESPACE
+
+class QScriptObjectDelegate;
+
+class QScriptObject : public JSC::JSObject
+{
+public:
+ // work around CELL_SIZE limitation
+ struct Data
+ {
+ JSC::JSValue data; // QScriptValue::data
+ QScriptObjectDelegate *delegate;
+ bool isMarking; // recursion guard
+
+ Data() : delegate(0), isMarking(false) {}
+ ~Data();
+ };
+
+ explicit QScriptObject(WTF::PassRefPtr<JSC::Structure> sid);
+ virtual ~QScriptObject();
+
+ virtual bool getOwnPropertySlot(JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ JSC::PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);
+ virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName,
+ JSC::JSValue, JSC::PutPropertySlot&);
+ virtual bool deleteProperty(JSC::ExecState*,
+ const JSC::Identifier& propertyName);
+ virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&,
+ JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);
+ virtual void markChildren(JSC::MarkStack& markStack);
+ virtual JSC::CallType getCallData(JSC::CallData&);
+ virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
+ virtual bool hasInstance(JSC::ExecState*, JSC::JSValue value, JSC::JSValue proto);
+ virtual bool compareToObject(JSC::ExecState*, JSC::JSObject*);
+
+ virtual const JSC::ClassInfo* classInfo() const { return &info; }
+ static const JSC::ClassInfo info;
+
+ static WTF::PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags));
+ }
+
+ inline JSC::JSValue data() const;
+ inline void setData(JSC::JSValue data);
+
+ inline QScriptObjectDelegate *delegate() const;
+ inline void setDelegate(QScriptObjectDelegate *delegate);
+
+protected:
+ static const unsigned StructureFlags = JSC::ImplementsHasInstance | JSC::OverridesHasInstance | JSC::OverridesGetOwnPropertySlot | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | JSObject::StructureFlags;
+
+ Data *d;
+};
+
+class QScriptObjectPrototype : public QScriptObject
+{
+public:
+ QScriptObjectPrototype(JSC::ExecState*, WTF::PassRefPtr<JSC::Structure>,
+ JSC::Structure* prototypeFunctionStructure);
+};
+
+class QScriptObjectDelegate
+{
+public:
+ enum Type {
+ QtObject,
+ Variant,
+ ClassObject,
+ DeclarativeClassObject
+ };
+
+ QScriptObjectDelegate();
+ virtual ~QScriptObjectDelegate();
+
+ virtual Type type() const = 0;
+
+ virtual bool getOwnPropertySlot(QScriptObject*, JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ JSC::PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(QScriptObject*, JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ JSC::PropertyDescriptor&);
+ 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);
+ virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&,
+ JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);
+ virtual void markChildren(QScriptObject*, JSC::MarkStack& markStack);
+ 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);
+ virtual bool compareToObject(QScriptObject*, JSC::ExecState*, JSC::JSObject*);
+
+private:
+ Q_DISABLE_COPY(QScriptObjectDelegate)
+};
+
+inline JSC::JSValue QScriptObject::data() const
+{
+ if (!d)
+ return JSC::JSValue();
+ return d->data;
+}
+
+inline void QScriptObject::setData(JSC::JSValue data)
+{
+ if (!d)
+ d = new Data();
+ d->data = data;
+}
+
+inline QScriptObjectDelegate *QScriptObject::delegate() const
+{
+ if (!d)
+ return 0;
+ return d->delegate;
+}
+
+inline void QScriptObject::setDelegate(QScriptObjectDelegate *delegate)
+{
+ if (!d)
+ d = new Data();
+ else
+ delete d->delegate;
+ d->delegate = delegate;
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp
new file mode 100644
index 0000000..cee8319
--- /dev/null
+++ b/src/script/bridge/qscriptqobject.cpp
@@ -0,0 +1,2317 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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 "qscriptqobject_p.h"
+
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qdebug.h>
+#include <QtScript/qscriptable.h>
+#include "../api/qscriptengine_p.h"
+#include "../api/qscriptable_p.h"
+#include "../api/qscriptcontext_p.h"
+#include "qscriptfunction_p.h"
+
+#include "Error.h"
+#include "PrototypeFunction.h"
+#include "NativeFunctionWrapper.h"
+#include "PropertyNameArray.h"
+#include "JSFunction.h"
+#include "JSString.h"
+#include "JSValue.h"
+#include "JSArray.h"
+#include "RegExpObject.h"
+#include "RegExpConstructor.h"
+
+namespace JSC
+{
+QT_USE_NAMESPACE
+ASSERT_CLASS_FITS_IN_CELL(QScript::QObjectPrototype);
+ASSERT_CLASS_FITS_IN_CELL(QScript::QMetaObjectWrapperObject);
+ASSERT_CLASS_FITS_IN_CELL(QScript::QMetaObjectPrototype);
+ASSERT_CLASS_FITS_IN_CELL(QScript::QtFunction);
+ASSERT_CLASS_FITS_IN_CELL(QScript::QtPropertyFunction);
+}
+
+QT_BEGIN_NAMESPACE
+
+namespace QScript
+{
+
+struct QObjectConnection
+{
+ int slotIndex;
+ JSC::JSValue receiver;
+ JSC::JSValue slot;
+ JSC::JSValue senderWrapper;
+
+ QObjectConnection(int i, JSC::JSValue r, JSC::JSValue s,
+ JSC::JSValue sw)
+ : slotIndex(i), receiver(r), slot(s), senderWrapper(sw) {}
+ QObjectConnection() : slotIndex(-1) {}
+
+ bool hasTarget(JSC::JSValue r, JSC::JSValue s) const
+ {
+ if ((r && r.isObject()) != (receiver && receiver.isObject()))
+ return false;
+ if (((r && r.isObject()) && (receiver && receiver.isObject()))
+ && (r != receiver)) {
+ return false;
+ }
+ return (s == slot);
+ }
+
+ void mark(JSC::MarkStack& markStack)
+ {
+ if (senderWrapper) {
+ // see if the sender should be marked or not;
+ // if the C++ object is owned by script, we don't want
+ // it to stay alive due to a script connection.
+ Q_ASSERT(senderWrapper.inherits(&QScriptObject::info));
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(senderWrapper));
+ if (!JSC::Heap::isCellMarked(scriptObject)) {
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::QtObject));
+ QObjectDelegate *inst = static_cast<QObjectDelegate*>(delegate);
+ if ((inst->ownership() == QScriptEngine::ScriptOwnership)
+ || ((inst->ownership() == QScriptEngine::AutoOwnership)
+ && inst->value() && !inst->value()->parent())) {
+ senderWrapper = JSC::JSValue();
+ } else {
+ markStack.append(senderWrapper);
+ }
+ }
+ }
+ if (receiver)
+ markStack.append(receiver);
+ if (slot)
+ markStack.append(slot);
+ }
+};
+
+class QObjectNotifyCaller : public QObject
+{
+public:
+ void callConnectNotify(const char *signal)
+ { connectNotify(signal); }
+ void callDisconnectNotify(const char *signal)
+ { disconnectNotify(signal); }
+};
+
+class QObjectConnectionManager: public QObject
+{
+public:
+ QObjectConnectionManager(QScriptEnginePrivate *engine);
+ ~QObjectConnectionManager();
+
+ bool addSignalHandler(QObject *sender, int signalIndex,
+ JSC::JSValue receiver,
+ JSC::JSValue slot,
+ JSC::JSValue senderWrapper,
+ Qt::ConnectionType type);
+ bool removeSignalHandler(QObject *sender, int signalIndex,
+ JSC::JSValue receiver,
+ JSC::JSValue slot);
+
+ static const QMetaObject staticMetaObject;
+ virtual const QMetaObject *metaObject() const;
+ virtual void *qt_metacast(const char *);
+ virtual int qt_metacall(QMetaObject::Call, int, void **argv);
+
+ void execute(int slotIndex, void **argv);
+
+ void mark(JSC::MarkStack&);
+
+private:
+ QScriptEnginePrivate *engine;
+ int slotCounter;
+ QVector<QVector<QObjectConnection> > connections;
+};
+
+static bool hasMethodAccess(const QMetaMethod &method, int index, const QScriptEngine::QObjectWrapOptions &opt)
+{
+ return (method.access() != QMetaMethod::Private)
+ && ((index != 2) || !(opt & QScriptEngine::ExcludeDeleteLater))
+ && (!(opt & QScriptEngine::ExcludeSlots) || (method.methodType() != QMetaMethod::Slot));
+}
+
+static bool isEnumerableMetaProperty(const QMetaProperty &prop,
+ const QMetaObject *mo, int index)
+{
+ return prop.isScriptable() && prop.isValid()
+ // the following lookup is to ensure that we have the
+ // "most derived" occurrence of the property with this name
+ && (mo->indexOfProperty(prop.name()) == index);
+}
+
+/*! \internal
+ Calculates the length of the name of the given \a method by looking
+ for the first '(' character.
+*/
+static inline int methodNameLength(const QMetaMethod &method)
+{
+ const char *signature = method.signature();
+ const char *s = signature;
+ while (*s && (*s != '('))
+ ++s;
+ return s - signature;
+}
+
+/*! \internal
+ Makes a deep copy of the first \a nameLength characters of the given
+ method \a signature and returns the copy.
+*/
+static inline QByteArray methodName(const char *signature, int nameLength)
+{
+ return QByteArray(signature, nameLength);
+}
+
+/*! \internal
+
+ Returns true if the name of the given \a method is the same as that
+ specified by the (signature, nameLength) pair, otherwise returns
+ false.
+*/
+static inline bool methodNameEquals(const QMetaMethod &method,
+ const char *signature, int nameLength)
+{
+ const char *otherSignature = method.signature();
+ return !qstrncmp(otherSignature, signature, nameLength)
+ && (otherSignature[nameLength] == '(');
+}
+
+static QVariant variantFromValue(JSC::ExecState *exec, int targetType, JSC::JSValue value)
+{
+ QVariant v(targetType, (void *)0);
+ if (QScriptEnginePrivate::convertValue(exec, value, targetType, v.data()))
+ return v;
+ if (uint(targetType) == QVariant::LastType)
+ return QScriptEnginePrivate::toVariant(exec, value);
+ if (QScriptEnginePrivate::isVariant(value)) {
+ v = QScriptEnginePrivate::variantValue(value);
+ if (v.canConvert(QVariant::Type(targetType))) {
+ v.convert(QVariant::Type(targetType));
+ return v;
+ }
+ QByteArray typeName = v.typeName();
+ if (typeName.endsWith('*')
+ && (QMetaType::type(typeName.left(typeName.size()-1)) == targetType)) {
+ return QVariant(targetType, *reinterpret_cast<void* *>(v.data()));
+ }
+ }
+
+ return QVariant();
+}
+
+static const bool GeneratePropertyFunctions = true;
+
+static unsigned flagsForMetaProperty(const QMetaProperty &prop)
+{
+ return (JSC::DontDelete
+ | (!prop.isWritable() ? unsigned(JSC::ReadOnly) : unsigned(0))
+ | (GeneratePropertyFunctions
+ ? unsigned(JSC::Getter | JSC::Setter)
+ : unsigned(0))
+ | QObjectMemberAttribute);
+}
+
+static int indexOfMetaEnum(const QMetaObject *meta, const QByteArray &str)
+{
+ QByteArray scope;
+ QByteArray name;
+ int scopeIdx = str.lastIndexOf("::");
+ if (scopeIdx != -1) {
+ scope = str.left(scopeIdx);
+ name = str.mid(scopeIdx + 2);
+ } else {
+ name = str;
+ }
+ for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
+ QMetaEnum m = meta->enumerator(i);
+ if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope)))
+ return i;
+ }
+ return -1;
+}
+
+static inline QScriptable *scriptableFromQObject(QObject *qobj)
+{
+ void *ptr = qobj->qt_metacast("QScriptable");
+ return reinterpret_cast<QScriptable*>(ptr);
+}
+
+QtFunction::QtFunction(JSC::JSValue object, int initialIndex, bool maybeOverloaded,
+ JSC::JSGlobalData *data, WTF::PassRefPtr<JSC::Structure> sid,
+ const JSC::Identifier &ident)
+ : JSC::InternalFunction(data, sid, ident),
+ data(new Data(object, initialIndex, maybeOverloaded))
+{
+}
+
+QtFunction::~QtFunction()
+{
+ delete data;
+}
+
+JSC::CallType QtFunction::getCallData(JSC::CallData &callData)
+{
+ callData.native.function = call;
+ return JSC::CallTypeHost;
+}
+
+void QtFunction::markChildren(JSC::MarkStack& markStack)
+{
+ if (data->object)
+ markStack.append(data->object);
+ JSC::InternalFunction::markChildren(markStack);
+}
+
+QScriptObject *QtFunction::wrapperObject() const
+{
+ Q_ASSERT(JSC::asObject(data->object)->inherits(&QScriptObject::info));
+ return static_cast<QScriptObject*>(JSC::asObject(data->object));
+}
+
+QObject *QtFunction::qobject() const
+{
+ QScriptObject *scriptObject = wrapperObject();
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::QtObject));
+ return static_cast<QScript::QObjectDelegate*>(delegate)->value();
+}
+
+const QMetaObject *QtFunction::metaObject() const
+{
+ QObject *qobj = qobject();
+ if (!qobj)
+ return 0;
+ return qobj->metaObject();
+}
+
+int QtFunction::initialIndex() const
+{
+ return data->initialIndex;
+}
+
+bool QtFunction::maybeOverloaded() const
+{
+ return data->maybeOverloaded;
+}
+
+int QtFunction::mostGeneralMethod(QMetaMethod *out) const
+{
+ const QMetaObject *meta = metaObject();
+ if (!meta)
+ return -1;
+ int index = initialIndex();
+ QMetaMethod method = meta->method(index);
+ if (maybeOverloaded() && (method.attributes() & QMetaMethod::Cloned)) {
+ // find the most general method
+ do {
+ method = meta->method(--index);
+ } while (method.attributes() & QMetaMethod::Cloned);
+ }
+ if (out)
+ *out = method;
+ return index;
+}
+
+QList<int> QScript::QtFunction::overloadedIndexes() const
+{
+ if (!maybeOverloaded())
+ return QList<int>();
+ QList<int> result;
+ const QMetaObject *meta = metaObject();
+ QMetaMethod method = meta->method(initialIndex());
+ int nameLength = methodNameLength(method);
+ for (int index = mostGeneralMethod() - 1; index >= 0; --index) {
+ if (methodNameEquals(meta->method(index), method.signature(), nameLength))
+ result.append(index);
+ }
+ return result;
+}
+
+class QScriptMetaType
+{
+public:
+ enum Kind {
+ Invalid,
+ Variant,
+ MetaType,
+ Unresolved,
+ MetaEnum
+ };
+
+ inline QScriptMetaType()
+ : m_kind(Invalid) { }
+
+ inline Kind kind() const
+ { return m_kind; }
+
+ int typeId() const;
+
+ inline bool isValid() const
+ { return (m_kind != Invalid); }
+
+ inline bool isVariant() const
+ { return (m_kind == Variant); }
+
+ inline bool isMetaType() const
+ { return (m_kind == MetaType); }
+
+ inline bool isUnresolved() const
+ { return (m_kind == Unresolved); }
+
+ inline bool isMetaEnum() const
+ { return (m_kind == MetaEnum); }
+
+ QByteArray name() const;
+
+ inline int enumeratorIndex() const
+ { Q_ASSERT(isMetaEnum()); return m_typeId; }
+
+ inline bool operator==(const QScriptMetaType &other) const
+ {
+ return (m_kind == other.m_kind) && (m_typeId == other.m_typeId);
+ }
+
+ static inline QScriptMetaType variant()
+ { return QScriptMetaType(Variant); }
+
+ static inline QScriptMetaType metaType(int typeId, const QByteArray &name)
+ { return QScriptMetaType(MetaType, typeId, name); }
+
+ static inline QScriptMetaType metaEnum(int enumIndex, const QByteArray &name)
+ { return QScriptMetaType(MetaEnum, enumIndex, name); }
+
+ static inline QScriptMetaType unresolved(const QByteArray &name)
+ { return QScriptMetaType(Unresolved, /*typeId=*/0, name); }
+
+private:
+ inline QScriptMetaType(Kind kind, int typeId = 0, const QByteArray &name = QByteArray())
+ : m_kind(kind), m_typeId(typeId), m_name(name) { }
+
+ Kind m_kind;
+ int m_typeId;
+ QByteArray m_name;
+};
+
+int QScriptMetaType::typeId() const
+{
+ if (isVariant())
+ return QMetaType::type("QVariant");
+ return isMetaEnum() ? 2/*int*/ : m_typeId;
+}
+
+QByteArray QScriptMetaType::name() const
+{
+ if (!m_name.isEmpty())
+ return m_name;
+ else if (m_kind == Variant)
+ return "QVariant";
+ return QMetaType::typeName(typeId());
+}
+
+class QScriptMetaMethod
+{
+public:
+ inline QScriptMetaMethod()
+ { }
+ inline QScriptMetaMethod(const QVector<QScriptMetaType> &types)
+ : m_types(types), m_firstUnresolvedIndex(-1)
+ {
+ QVector<QScriptMetaType>::const_iterator it;
+ for (it = m_types.constBegin(); it != m_types.constEnd(); ++it) {
+ if ((*it).kind() == QScriptMetaType::Unresolved) {
+ m_firstUnresolvedIndex = it - m_types.constBegin();
+ break;
+ }
+ }
+ }
+ inline bool isValid() const
+ { return !m_types.isEmpty(); }
+
+ inline QScriptMetaType returnType() const
+ { return m_types.at(0); }
+
+ inline int argumentCount() const
+ { return m_types.count() - 1; }
+
+ inline QScriptMetaType argumentType(int arg) const
+ { return m_types.at(arg + 1); }
+
+ inline bool fullyResolved() const
+ { return m_firstUnresolvedIndex == -1; }
+
+ inline bool hasUnresolvedReturnType() const
+ { return (m_firstUnresolvedIndex == 0); }
+
+ inline int firstUnresolvedIndex() const
+ { return m_firstUnresolvedIndex; }
+
+ inline int count() const
+ { return m_types.count(); }
+
+ inline QScriptMetaType type(int index) const
+ { return m_types.at(index); }
+
+ inline QVector<QScriptMetaType> types() const
+ { return m_types; }
+
+private:
+ QVector<QScriptMetaType> m_types;
+ int m_firstUnresolvedIndex;
+};
+
+struct QScriptMetaArguments
+{
+ int matchDistance;
+ int index;
+ QScriptMetaMethod method;
+ QVarLengthArray<QVariant, 9> args;
+
+ inline QScriptMetaArguments(int dist, int idx, const QScriptMetaMethod &mtd,
+ const QVarLengthArray<QVariant, 9> &as)
+ : matchDistance(dist), index(idx), method(mtd), args(as) { }
+ inline QScriptMetaArguments()
+ : index(-1) { }
+
+ inline bool isValid() const
+ { return (index != -1); }
+};
+
+static QMetaMethod metaMethod(const QMetaObject *meta,
+ QMetaMethod::MethodType type,
+ int index)
+{
+ if (type != QMetaMethod::Constructor)
+ return meta->method(index);
+ else
+ return meta->constructor(index);
+}
+
+static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType callType,
+ QObject *thisQObject, const JSC::ArgList &scriptArgs,
+ const QMetaObject *meta, int initialIndex,
+ bool maybeOverloaded)
+{
+ QScriptMetaMethod chosenMethod;
+ int chosenIndex = -1;
+ QVarLengthArray<QVariant, 9> args;
+ QVector<QScriptMetaArguments> candidates;
+ QVector<QScriptMetaArguments> unresolved;
+ QVector<int> tooFewArgs;
+ QVector<int> conversionFailed;
+ int index;
+ int nameLength = 0;
+ const char *initialMethodSignature = 0;
+ exec->clearException();
+ QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(exec);
+ for (index = initialIndex; index >= 0; --index) {
+ QMetaMethod method = metaMethod(meta, callType, index);
+
+ if (index == initialIndex) {
+ initialMethodSignature = method.signature();
+ nameLength = methodNameLength(method);
+ } else {
+ if (!methodNameEquals(method, initialMethodSignature, nameLength))
+ continue;
+ }
+
+ QList<QByteArray> parameterTypeNames = method.parameterTypes();
+
+ QVector<QScriptMetaType> types;
+ types.resize(1 + parameterTypeNames.size());
+ QScriptMetaType *typesData = types.data();
+ // resolve return type
+ QByteArray returnTypeName = method.typeName();
+ int rtype = QMetaType::type(returnTypeName);
+ if ((rtype == 0) && !returnTypeName.isEmpty()) {
+ int enumIndex = indexOfMetaEnum(meta, returnTypeName);
+ if (enumIndex != -1)
+ typesData[0] = QScriptMetaType::metaEnum(enumIndex, returnTypeName);
+ else
+ typesData[0] = QScriptMetaType::unresolved(returnTypeName);
+ } else {
+ if (callType == QMetaMethod::Constructor)
+ typesData[0] = QScriptMetaType::metaType(QMetaType::QObjectStar, "QObject*");
+ else if (rtype == QMetaType::QVariant)
+ typesData[0] = QScriptMetaType::variant();
+ else
+ typesData[0] = QScriptMetaType::metaType(rtype, returnTypeName);
+ }
+
+ // resolve argument types
+ for (int i = 0; i < parameterTypeNames.count(); ++i) {
+ QByteArray argTypeName = parameterTypeNames.at(i);
+ int atype = QMetaType::type(argTypeName);
+ if (atype == 0) {
+ int enumIndex = indexOfMetaEnum(meta, argTypeName);
+ if (enumIndex != -1)
+ typesData[1 + i] = QScriptMetaType::metaEnum(enumIndex, argTypeName);
+ else
+ typesData[1 + i] = QScriptMetaType::unresolved(argTypeName);
+ } else if (atype == QMetaType::QVariant) {
+ typesData[1 + i] = QScriptMetaType::variant();
+ } else {
+ typesData[1 + i] = QScriptMetaType::metaType(atype, argTypeName);
+ }
+ }
+
+ QScriptMetaMethod mtd = QScriptMetaMethod(types);
+
+ if (int(scriptArgs.size()) < mtd.argumentCount()) {
+ tooFewArgs.append(index);
+ continue;
+ }
+
+ if (!mtd.fullyResolved()) {
+ // remember it so we can give an error message later, if necessary
+ unresolved.append(QScriptMetaArguments(/*matchDistance=*/INT_MAX, index,
+ mtd, QVarLengthArray<QVariant, 9>()));
+ if (mtd.hasUnresolvedReturnType())
+ continue;
+ }
+
+ if (args.count() != mtd.count())
+ args.resize(mtd.count());
+
+ QScriptMetaType retType = mtd.returnType();
+ args[0] = QVariant(retType.typeId(), (void *)0); // the result
+
+ // try to convert arguments
+ bool converted = true;
+ int matchDistance = 0;
+ for (int i = 0; converted && i < mtd.argumentCount(); ++i) {
+ JSC::JSValue actual;
+ if (i < (int)scriptArgs.size())
+ actual = scriptArgs.at(i);
+ else
+ actual = JSC::jsUndefined();
+ QScriptMetaType argType = mtd.argumentType(i);
+ int tid = -1;
+ QVariant v;
+ if (argType.isUnresolved()) {
+ v = QVariant(QMetaType::QObjectStar, (void *)0);
+ converted = QScriptEnginePrivate::convertToNativeQObject(
+ exec, actual, argType.name(), reinterpret_cast<void* *>(v.data()));
+ } else if (argType.isVariant()) {
+ if (QScriptEnginePrivate::isVariant(actual)) {
+ v = QScriptEnginePrivate::variantValue(actual);
+ } else {
+ v = QScriptEnginePrivate::toVariant(exec, actual);
+ converted = v.isValid() || actual.isUndefined() || actual.isNull();
+ }
+ } else {
+ tid = argType.typeId();
+ v = QVariant(tid, (void *)0);
+ converted = QScriptEnginePrivate::convertValue(exec, actual, tid, v.data());
+ if (exec->hadException())
+ return exec->exception();
+ }
+
+ if (!converted) {
+ if (QScriptEnginePrivate::isVariant(actual)) {
+ if (tid == -1)
+ tid = argType.typeId();
+ QVariant vv = QScriptEnginePrivate::variantValue(actual);
+ if (vv.canConvert(QVariant::Type(tid))) {
+ v = vv;
+ converted = v.convert(QVariant::Type(tid));
+ if (converted && (vv.userType() != tid))
+ matchDistance += 10;
+ } else {
+ QByteArray vvTypeName = vv.typeName();
+ if (vvTypeName.endsWith('*')
+ && (vvTypeName.left(vvTypeName.size()-1) == argType.name())) {
+ v = QVariant(tid, *reinterpret_cast<void* *>(vv.data()));
+ converted = true;
+ matchDistance += 10;
+ }
+ }
+ } else if (actual.isNumber() || actual.isString()) {
+ // see if it's an enum value
+ QMetaEnum m;
+ if (argType.isMetaEnum()) {
+ m = meta->enumerator(argType.enumeratorIndex());
+ } else {
+ int mi = indexOfMetaEnum(meta, argType.name());
+ if (mi != -1)
+ m = meta->enumerator(mi);
+ }
+ if (m.isValid()) {
+ if (actual.isNumber()) {
+ int ival = QScriptEnginePrivate::toInt32(exec, actual);
+ if (m.valueToKey(ival) != 0) {
+ v.setValue(ival);
+ converted = true;
+ matchDistance += 10;
+ }
+ } else {
+ JSC::UString sval = QScriptEnginePrivate::toString(exec, actual);
+ int ival = m.keyToValue(convertToLatin1(sval));
+ if (ival != -1) {
+ v.setValue(ival);
+ converted = true;
+ matchDistance += 10;
+ }
+ }
+ }
+ }
+ } else {
+ // determine how well the conversion matched
+ if (actual.isNumber()) {
+ switch (tid) {
+ case QMetaType::Double:
+ // perfect
+ break;
+ case QMetaType::Float:
+ matchDistance += 1;
+ break;
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ matchDistance += 2;
+ break;
+ case QMetaType::Long:
+ case QMetaType::ULong:
+ matchDistance += 3;
+ break;
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ matchDistance += 4;
+ break;
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ matchDistance += 5;
+ break;
+ case QMetaType::Char:
+ case QMetaType::UChar:
+ matchDistance += 6;
+ break;
+ default:
+ matchDistance += 10;
+ break;
+ }
+ } else if (actual.isString()) {
+ switch (tid) {
+ case QMetaType::QString:
+ // perfect
+ break;
+ default:
+ matchDistance += 10;
+ break;
+ }
+ } else if (actual.isBoolean()) {
+ switch (tid) {
+ case QMetaType::Bool:
+ // perfect
+ break;
+ default:
+ matchDistance += 10;
+ break;
+ }
+ } else if (QScriptEnginePrivate::isDate(actual)) {
+ switch (tid) {
+ case QMetaType::QDateTime:
+ // perfect
+ break;
+ case QMetaType::QDate:
+ matchDistance += 1;
+ break;
+ case QMetaType::QTime:
+ matchDistance += 2;
+ break;
+ default:
+ matchDistance += 10;
+ break;
+ }
+ } else if (QScriptEnginePrivate::isRegExp(actual)) {
+ switch (tid) {
+ case QMetaType::QRegExp:
+ // perfect
+ break;
+ default:
+ matchDistance += 10;
+ break;
+ }
+ } else if (QScriptEnginePrivate::isVariant(actual)) {
+ if (argType.isVariant()
+ || (QScriptEnginePrivate::toVariant(exec, actual).userType() == tid)) {
+ // perfect
+ } else {
+ matchDistance += 10;
+ }
+ } else if (QScriptEnginePrivate::isArray(actual)) {
+ switch (tid) {
+ case QMetaType::QStringList:
+ case QMetaType::QVariantList:
+ matchDistance += 5;
+ break;
+ default:
+ matchDistance += 10;
+ break;
+ }
+ } else if (QScriptEnginePrivate::isQObject(actual)) {
+ switch (tid) {
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ // perfect
+ break;
+ default:
+ matchDistance += 10;
+ break;
+ }
+ } else if (actual.isNull()) {
+ switch (tid) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ // perfect
+ break;
+ default:
+ if (!argType.name().endsWith('*'))
+ matchDistance += 10;
+ break;
+ }
+ } else {
+ matchDistance += 10;
+ }
+ }
+
+ if (converted)
+ args[i+1] = v;
+ }
+
+ if (converted) {
+ if ((scriptArgs.size() == (size_t)mtd.argumentCount())
+ && (matchDistance == 0)) {
+ // perfect match, use this one
+ chosenMethod = mtd;
+ chosenIndex = index;
+ break;
+ } else {
+ bool redundant = false;
+ if ((callType != QMetaMethod::Constructor)
+ && (index < meta->methodOffset())) {
+ // it is possible that a virtual method is redeclared in a subclass,
+ // in which case we want to ignore the superclass declaration
+ for (int i = 0; i < candidates.size(); ++i) {
+ const QScriptMetaArguments &other = candidates.at(i);
+ if (mtd.types() == other.method.types()) {
+ redundant = true;
+ break;
+ }
+ }
+ }
+ if (!redundant) {
+ QScriptMetaArguments metaArgs(matchDistance, index, mtd, args);
+ if (candidates.isEmpty()) {
+ candidates.append(metaArgs);
+ } else {
+ const QScriptMetaArguments &otherArgs = candidates.at(0);
+ if ((args.count() > otherArgs.args.count())
+ || ((args.count() == otherArgs.args.count())
+ && (matchDistance <= otherArgs.matchDistance))) {
+ candidates.prepend(metaArgs);
+ } else {
+ candidates.append(metaArgs);
+ }
+ }
+ }
+ }
+ } else if (mtd.fullyResolved()) {
+ conversionFailed.append(index);
+ }
+
+ if (!maybeOverloaded)
+ break;
+ }
+
+ JSC::JSValue result;
+ if ((chosenIndex == -1) && candidates.isEmpty()) {
+// context->calleeMetaIndex = initialIndex;
+//#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
+// engine->notifyFunctionEntry(context);
+//#endif
+ QString funName = QString::fromLatin1(methodName(initialMethodSignature, nameLength));
+ if (!conversionFailed.isEmpty()) {
+ QString message = QString::fromLatin1("incompatible type of argument(s) in call to %0(); candidates were\n")
+ .arg(funName);
+ for (int i = 0; i < conversionFailed.size(); ++i) {
+ if (i > 0)
+ message += QLatin1String("\n");
+ QMetaMethod mtd = metaMethod(meta, callType, conversionFailed.at(i));
+ message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature()));
+ }
+ result = JSC::throwError(exec, JSC::TypeError, message);
+ } else if (!unresolved.isEmpty()) {
+ QScriptMetaArguments argsInstance = unresolved.first();
+ int unresolvedIndex = argsInstance.method.firstUnresolvedIndex();
+ Q_ASSERT(unresolvedIndex != -1);
+ QScriptMetaType unresolvedType = argsInstance.method.type(unresolvedIndex);
+ QString unresolvedTypeName = QString::fromLatin1(unresolvedType.name());
+ QString message = QString::fromLatin1("cannot call %0(): ")
+ .arg(funName);
+ if (unresolvedIndex > 0) {
+ message.append(QString::fromLatin1("argument %0 has unknown type `%1'").
+ arg(unresolvedIndex).arg(unresolvedTypeName));
+ } else {
+ message.append(QString::fromLatin1("unknown return type `%0'")
+ .arg(unresolvedTypeName));
+ }
+ message.append(QString::fromLatin1(" (register the type with qScriptRegisterMetaType())"));
+ result = JSC::throwError(exec, JSC::TypeError, message);
+ } else {
+ QString message = QString::fromLatin1("too few arguments in call to %0(); candidates are\n")
+ .arg(funName);
+ for (int i = 0; i < tooFewArgs.size(); ++i) {
+ if (i > 0)
+ message += QLatin1String("\n");
+ QMetaMethod mtd = metaMethod(meta, callType, tooFewArgs.at(i));
+ message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature()));
+ }
+ result = JSC::throwError(exec, JSC::SyntaxError, message);
+ }
+ } else {
+ if (chosenIndex == -1) {
+ QScriptMetaArguments metaArgs = candidates.at(0);
+ if ((candidates.size() > 1)
+ && (metaArgs.args.count() == candidates.at(1).args.count())
+ && (metaArgs.matchDistance == candidates.at(1).matchDistance)) {
+ // ambiguous call
+ QByteArray funName = methodName(initialMethodSignature, nameLength);
+ QString message = QString::fromLatin1("ambiguous call of overloaded function %0(); candidates were\n")
+ .arg(QLatin1String(funName));
+ for (int i = 0; i < candidates.size(); ++i) {
+ if (i > 0)
+ message += QLatin1String("\n");
+ QMetaMethod mtd = metaMethod(meta, callType, candidates.at(i).index);
+ message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature()));
+ }
+ result = JSC::throwError(exec, JSC::TypeError, message);
+ } else {
+ chosenMethod = metaArgs.method;
+ chosenIndex = metaArgs.index;
+ args = metaArgs.args;
+ }
+ }
+
+ if (chosenIndex != -1) {
+ // call it
+// context->calleeMetaIndex = chosenIndex;
+
+ QVarLengthArray<void*, 9> array(args.count());
+ void **params = array.data();
+ for (int i = 0; i < args.count(); ++i) {
+ const QVariant &v = args[i];
+ switch (chosenMethod.type(i).kind()) {
+ case QScriptMetaType::Variant:
+ params[i] = const_cast<QVariant*>(&v);
+ break;
+ case QScriptMetaType::MetaType:
+ case QScriptMetaType::MetaEnum:
+ case QScriptMetaType::Unresolved:
+ params[i] = const_cast<void*>(v.constData());
+ break;
+ default:
+ Q_ASSERT(0);
+ }
+ }
+
+ QScriptable *scriptable = 0;
+ if (thisQObject)
+ scriptable = scriptableFromQObject(thisQObject);
+ QScriptEngine *oldEngine = 0;
+ if (scriptable) {
+ oldEngine = QScriptablePrivate::get(scriptable)->engine;
+ QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(engine);
+ }
+
+// ### fixme
+//#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
+// engine->notifyFunctionEntry(context);
+//#endif
+
+ if (callType == QMetaMethod::Constructor) {
+ Q_ASSERT(meta != 0);
+ meta->static_metacall(QMetaObject::CreateInstance, chosenIndex, params);
+ } else {
+ QMetaObject::metacall(thisQObject, QMetaObject::InvokeMetaMethod, chosenIndex, params);
+ }
+
+ if (scriptable)
+ QScriptablePrivate::get(scriptable)->engine = oldEngine;
+
+ if (exec->hadException()) {
+ result = exec->exception() ; // propagate
+ } else {
+ QScriptMetaType retType = chosenMethod.returnType();
+ if (retType.isVariant()) {
+ result = QScriptEnginePrivate::jscValueFromVariant(exec, *(QVariant *)params[0]);
+ } else if (retType.typeId() != 0) {
+ result = QScriptEnginePrivate::create(exec, retType.typeId(), params[0]);
+ if (!result)
+ result = engine->newVariant(QVariant(retType.typeId(), params[0]));
+ } else {
+ result = JSC::jsUndefined();
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+JSC::JSValue QtFunction::execute(JSC::ExecState *exec, JSC::JSValue thisValue,
+ const JSC::ArgList &scriptArgs)
+{
+ Q_ASSERT(data->object.inherits(&QScriptObject::info));
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(data->object));
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::QtObject));
+ QObject *qobj = static_cast<QScript::QObjectDelegate*>(delegate)->value();
+ if (!qobj)
+ return JSC::throwError(exec, JSC::GeneralError, QString::fromLatin1("cannot call function of deleted QObject"));
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+
+ const QMetaObject *meta = qobj->metaObject();
+ QObject *thisQObject = 0;
+ thisValue = engine->toUsableValue(thisValue);
+ if (thisValue.inherits(&QScriptObject::info)) {
+ delegate = static_cast<QScriptObject*>(JSC::asObject(thisValue))->delegate();
+ if (delegate && (delegate->type() == QScriptObjectDelegate::QtObject))
+ thisQObject = static_cast<QScript::QObjectDelegate*>(delegate)->value();
+ }
+ if (!thisQObject)
+ thisQObject = qobj; // ### TypeError
+
+ if (!meta->cast(thisQObject)) {
+ // invoking a function in the prototype
+ thisQObject = qobj;
+ }
+
+ return callQtMethod(exec, QMetaMethod::Method, thisQObject, scriptArgs,
+ meta, data->initialIndex, data->maybeOverloaded);
+}
+
+const JSC::ClassInfo QtFunction::info = { "QtFunction", &InternalFunction::info, 0, 0 };
+
+JSC::JSValue JSC_HOST_CALL QtFunction::call(JSC::ExecState *exec, JSC::JSObject *callee,
+ JSC::JSValue thisValue, const JSC::ArgList &args)
+{
+ if (!callee->inherits(&QtFunction::info))
+ return throwError(exec, JSC::TypeError, "callee is not a QtFunction object");
+ QtFunction *qfun = static_cast<QtFunction*>(callee);
+ QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
+ JSC::ExecState *previousFrame = eng_p->currentFrame;
+ eng_p->currentFrame = exec;
+ eng_p->pushContext(exec, thisValue, args, callee);
+ JSC::JSValue result = qfun->execute(eng_p->currentFrame, thisValue, args);
+ eng_p->popContext();
+ eng_p->currentFrame = previousFrame;
+ return result;
+}
+
+const JSC::ClassInfo QtPropertyFunction::info = { "QtPropertyFunction", &InternalFunction::info, 0, 0 };
+
+QtPropertyFunction::QtPropertyFunction(const QMetaObject *meta, int index,
+ JSC::JSGlobalData *data,
+ WTF::PassRefPtr<JSC::Structure> sid,
+ const JSC::Identifier &ident)
+ : JSC::InternalFunction(data, sid, ident),
+ data(new Data(meta, index))
+{
+}
+
+QtPropertyFunction::~QtPropertyFunction()
+{
+ delete data;
+}
+
+JSC::CallType QtPropertyFunction::getCallData(JSC::CallData &callData)
+{
+ callData.native.function = call;
+ return JSC::CallTypeHost;
+}
+
+JSC::JSValue JSC_HOST_CALL QtPropertyFunction::call(
+ JSC::ExecState *exec, JSC::JSObject *callee,
+ JSC::JSValue thisValue, const JSC::ArgList &args)
+{
+ if (!callee->inherits(&QtPropertyFunction::info))
+ return throwError(exec, JSC::TypeError, "callee is not a QtPropertyFunction object");
+ QtPropertyFunction *qfun = static_cast<QtPropertyFunction*>(callee);
+ return qfun->execute(exec, thisValue, args);
+}
+
+JSC::JSValue QtPropertyFunction::execute(JSC::ExecState *exec,
+ JSC::JSValue thisValue,
+ const JSC::ArgList &args)
+{
+ JSC::JSValue result = JSC::jsUndefined();
+
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ JSC::ExecState *previousFrame = engine->currentFrame;
+ engine->currentFrame = exec;
+
+ JSC::JSValue qobjectValue = engine->toUsableValue(thisValue);
+ QObject *qobject = QScriptEnginePrivate::toQObject(exec, qobjectValue);
+ while ((!qobject || (qobject->metaObject() != data->meta))
+ && JSC::asObject(qobjectValue)->prototype().isObject()) {
+ qobjectValue = JSC::asObject(qobjectValue)->prototype();
+ qobject = QScriptEnginePrivate::toQObject(exec, qobjectValue);
+ }
+ Q_ASSERT_X(qobject, Q_FUNC_INFO, "this-object must be a QObject");
+
+ QMetaProperty prop = data->meta->property(data->index);
+ Q_ASSERT(prop.isScriptable());
+ if (args.size() == 0) {
+ // get
+ if (prop.isValid()) {
+ QScriptable *scriptable = scriptableFromQObject(qobject);
+ QScriptEngine *oldEngine = 0;
+ if (scriptable) {
+ engine->pushContext(exec, thisValue, args, this);
+ oldEngine = QScriptablePrivate::get(scriptable)->engine;
+ QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(engine);
+ }
+
+ QVariant v = prop.read(qobject);
+
+ if (scriptable) {
+ QScriptablePrivate::get(scriptable)->engine = oldEngine;
+ engine->popContext();
+ }
+
+ result = QScriptEnginePrivate::jscValueFromVariant(exec, v);
+ }
+ } else {
+ // set
+ JSC::JSValue arg = args.at(0);
+ QVariant v;
+ if (prop.isEnumType() && arg.isString()
+ && !engine->hasDemarshalFunction(prop.userType())) {
+ // give QMetaProperty::write() a chance to convert from
+ // string to enum value
+ v = (QString)arg.toString(exec);
+ } else {
+ v = variantFromValue(exec, prop.userType(), arg);
+ }
+
+ QScriptable *scriptable = scriptableFromQObject(qobject);
+ QScriptEngine *oldEngine = 0;
+ if (scriptable) {
+ engine->pushContext(exec, thisValue, args, this);
+ oldEngine = QScriptablePrivate::get(scriptable)->engine;
+ QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(engine);
+ }
+
+ prop.write(qobject, v);
+
+ if (scriptable) {
+ QScriptablePrivate::get(scriptable)->engine = oldEngine;
+ engine->popContext();
+ }
+
+ result = arg;
+ }
+ engine->currentFrame = previousFrame;
+ return result;
+}
+
+const QMetaObject *QtPropertyFunction::metaObject() const
+{
+ return data->meta;
+}
+
+int QtPropertyFunction::propertyIndex() const
+{
+ return data->index;
+}
+
+
+QObjectDelegate::QObjectDelegate(
+ QObject *object, QScriptEngine::ValueOwnership ownership,
+ const QScriptEngine::QObjectWrapOptions &options)
+ : data(new Data(object, ownership, options))
+{
+}
+
+QObjectDelegate::~QObjectDelegate()
+{
+ switch (data->ownership) {
+ case QScriptEngine::QtOwnership:
+ break;
+ case QScriptEngine::ScriptOwnership:
+ if (data->value)
+ delete data->value; // ### fixme
+// eng->disposeQObject(value);
+ break;
+ case QScriptEngine::AutoOwnership:
+ if (data->value && !data->value->parent())
+ delete data->value; // ### fixme
+// eng->disposeQObject(value);
+ break;
+ }
+ delete data;
+}
+
+QScriptObjectDelegate::Type QObjectDelegate::type() const
+{
+ return QtObject;
+}
+
+bool QObjectDelegate::getOwnPropertySlot(QScriptObject *object, JSC::ExecState *exec,
+ const JSC::Identifier &propertyName,
+ JSC::PropertySlot &slot)
+{
+ //Note: this has to be kept in sync with getOwnPropertyDescriptor
+#ifndef QT_NO_PROPERTIES
+ QByteArray name = convertToLatin1(propertyName.ustring());
+ QObject *qobject = data->value;
+ if (!qobject) {
+ QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject")
+ .arg(QString::fromLatin1(name));
+ slot.setValue(JSC::throwError(exec, JSC::GeneralError, message));
+ return true;
+ }
+
+ const QMetaObject *meta = qobject->metaObject();
+ {
+ QHash<QByteArray, JSC::JSValue>::const_iterator it = data->cachedMembers.constFind(name);
+ if (it != data->cachedMembers.constEnd()) {
+ if (GeneratePropertyFunctions && (meta->indexOfProperty(name) != -1))
+ slot.setGetterSlot(JSC::asObject(it.value()));
+ else
+ slot.setValue(it.value());
+ return true;
+ }
+ }
+
+ const QScriptEngine::QObjectWrapOptions &opt = data->options;
+ QScriptEnginePrivate *eng = scriptEngineFromExec(exec);
+ int index = -1;
+ if (name.contains('(')) {
+ QByteArray normalized = QMetaObject::normalizedSignature(name);
+ if (-1 != (index = meta->indexOfMethod(normalized))) {
+ QMetaMethod method = meta->method(index);
+ if (hasMethodAccess(method, index, opt)) {
+ if (!(opt & QScriptEngine::ExcludeSuperClassMethods)
+ || (index >= meta->methodOffset())) {
+ QtFunction *fun = new (exec)QtFunction(
+ object, index, /*maybeOverloaded=*/false,
+ &exec->globalData(), eng->originalGlobalObject()->functionStructure(),
+ propertyName);
+ slot.setValue(fun);
+ data->cachedMembers.insert(name, fun);
+ return true;
+ }
+ }
+ }
+ }
+
+ index = meta->indexOfProperty(name);
+ if (index != -1) {
+ QMetaProperty prop = meta->property(index);
+ if (prop.isScriptable()) {
+ if (!(opt & QScriptEngine::ExcludeSuperClassProperties)
+ || (index >= meta->propertyOffset())) {
+ if (GeneratePropertyFunctions) {
+ QtPropertyFunction *fun = new (exec)QtPropertyFunction(
+ meta, index, &exec->globalData(),
+ eng->originalGlobalObject()->functionStructure(),
+ propertyName);
+ data->cachedMembers.insert(name, fun);
+ slot.setGetterSlot(fun);
+ } else {
+ JSC::JSValue val;
+ if (!prop.isValid())
+ val = JSC::jsUndefined();
+ else
+ val = QScriptEnginePrivate::jscValueFromVariant(exec, prop.read(qobject));
+ slot.setValue(val);
+ }
+ return true;
+ }
+ }
+ }
+
+ index = qobject->dynamicPropertyNames().indexOf(name);
+ if (index != -1) {
+ JSC::JSValue val = QScriptEnginePrivate::jscValueFromVariant(exec, qobject->property(name));
+ slot.setValue(val);
+ return true;
+ }
+
+ const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods)
+ ? meta->methodOffset() : 0;
+ for (index = meta->methodCount() - 1; index >= offset; --index) {
+ QMetaMethod method = meta->method(index);
+ if (hasMethodAccess(method, index, opt)
+ && methodNameEquals(method, name.constData(), name.length())) {
+ QtFunction *fun = new (exec)QtFunction(
+ object, index, /*maybeOverloaded=*/true,
+ &exec->globalData(), eng->originalGlobalObject()->functionStructure(),
+ propertyName);
+ slot.setValue(fun);
+ data->cachedMembers.insert(name, fun);
+ return true;
+ }
+ }
+
+ if (!(opt & QScriptEngine::ExcludeChildObjects)) {
+ QList<QObject*> children = qobject->children();
+ for (index = 0; index < children.count(); ++index) {
+ QObject *child = children.at(index);
+ if (child->objectName() == QString(propertyName.ustring())) {
+ QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject;
+ slot.setValue(eng->newQObject(child, QScriptEngine::QtOwnership, opt));
+ return true;
+ }
+ }
+ }
+
+ return QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot);
+#else //QT_NO_PROPERTIES
+ return false;
+#endif //QT_NO_PROPERTIES
+}
+
+
+bool QObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecState *exec,
+ const JSC::Identifier &propertyName,
+ JSC::PropertyDescriptor &descriptor)
+{
+ //Note: this has to be kept in sync with getOwnPropertySlot
+#ifndef QT_NO_PROPERTIES
+ QByteArray name = convertToLatin1(propertyName.ustring());
+ QObject *qobject = data->value;
+ if (!qobject) {
+ QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject")
+ .arg(QString::fromLatin1(name));
+ descriptor.setValue(JSC::throwError(exec, JSC::GeneralError, message));
+ return true;
+ }
+
+ const QScriptEngine::QObjectWrapOptions &opt = data->options;
+
+ const QMetaObject *meta = qobject->metaObject();
+ {
+ QHash<QByteArray, JSC::JSValue>::const_iterator it = data->cachedMembers.constFind(name);
+ if (it != data->cachedMembers.constEnd()) {
+ int index;
+ if (GeneratePropertyFunctions && ((index = meta->indexOfProperty(name)) != -1)) {
+ QMetaProperty prop = meta->property(index);
+ descriptor.setAccessorDescriptor(it.value(), it.value(), flagsForMetaProperty(prop));
+ if (!prop.isWritable())
+ descriptor.setWritable(false);
+ } else {
+ unsigned attributes = QObjectMemberAttribute;
+ if (opt & QScriptEngine::SkipMethodsInEnumeration)
+ attributes |= JSC::DontEnum;
+ descriptor.setDescriptor(it.value(), attributes);
+ }
+ return true;
+ }
+ }
+
+ QScriptEnginePrivate *eng = scriptEngineFromExec(exec);
+ int index = -1;
+ if (name.contains('(')) {
+ QByteArray normalized = QMetaObject::normalizedSignature(name);
+ if (-1 != (index = meta->indexOfMethod(normalized))) {
+ QMetaMethod method = meta->method(index);
+ if (hasMethodAccess(method, index, opt)) {
+ if (!(opt & QScriptEngine::ExcludeSuperClassMethods)
+ || (index >= meta->methodOffset())) {
+ QtFunction *fun = new (exec)QtFunction(
+ object, index, /*maybeOverloaded=*/false,
+ &exec->globalData(), eng->originalGlobalObject()->functionStructure(),
+ propertyName);
+ data->cachedMembers.insert(name, fun);
+ unsigned attributes = QObjectMemberAttribute;
+ if (opt & QScriptEngine::SkipMethodsInEnumeration)
+ attributes |= JSC::DontEnum;
+ descriptor.setDescriptor(fun, attributes);
+ return true;
+ }
+ }
+ }
+ }
+
+ index = meta->indexOfProperty(name);
+ if (index != -1) {
+ QMetaProperty prop = meta->property(index);
+ if (prop.isScriptable()) {
+ if (!(opt & QScriptEngine::ExcludeSuperClassProperties)
+ || (index >= meta->propertyOffset())) {
+ unsigned attributes = flagsForMetaProperty(prop);
+ if (GeneratePropertyFunctions) {
+ QtPropertyFunction *fun = new (exec)QtPropertyFunction(
+ meta, index, &exec->globalData(),
+ eng->originalGlobalObject()->functionStructure(),
+ propertyName);
+ data->cachedMembers.insert(name, fun);
+ descriptor.setAccessorDescriptor(fun, fun, attributes);
+ if (attributes & JSC::ReadOnly)
+ descriptor.setWritable(false);
+ } else {
+ JSC::JSValue val;
+ if (!prop.isValid())
+ val = JSC::jsUndefined();
+ else
+ val = QScriptEnginePrivate::jscValueFromVariant(exec, prop.read(qobject));
+ descriptor.setDescriptor(val, attributes);
+ }
+ return true;
+ }
+ }
+ }
+
+ index = qobject->dynamicPropertyNames().indexOf(name);
+ if (index != -1) {
+ JSC::JSValue val = QScriptEnginePrivate::jscValueFromVariant(exec, qobject->property(name));
+ descriptor.setDescriptor(val, QObjectMemberAttribute);
+ return true;
+ }
+
+ const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods)
+ ? meta->methodOffset() : 0;
+ for (index = meta->methodCount() - 1; index >= offset; --index) {
+ QMetaMethod method = meta->method(index);
+ if (hasMethodAccess(method, index, opt)
+ && methodNameEquals(method, name.constData(), name.length())) {
+ QtFunction *fun = new (exec)QtFunction(
+ object, index, /*maybeOverloaded=*/true,
+ &exec->globalData(), eng->originalGlobalObject()->functionStructure(),
+ propertyName);
+ unsigned attributes = QObjectMemberAttribute;
+ if (opt & QScriptEngine::SkipMethodsInEnumeration)
+ attributes |= JSC::DontEnum;
+ descriptor.setDescriptor(fun, attributes);
+ data->cachedMembers.insert(name, fun);
+ return true;
+ }
+ }
+
+ if (!(opt & QScriptEngine::ExcludeChildObjects)) {
+ QList<QObject*> children = qobject->children();
+ for (index = 0; index < children.count(); ++index) {
+ QObject *child = children.at(index);
+ if (child->objectName() == QString(propertyName.ustring())) {
+ QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject;
+ descriptor.setDescriptor(eng->newQObject(child, QScriptEngine::QtOwnership, opt),
+ JSC::ReadOnly | JSC::DontDelete | JSC::DontEnum);
+ return true;
+ }
+ }
+ }
+
+ return QScriptObjectDelegate::getOwnPropertyDescriptor(object, exec, propertyName, descriptor);
+#else //QT_NO_PROPERTIES
+ return false;
+#endif //QT_NO_PROPERTIES
+}
+
+void QObjectDelegate::put(QScriptObject *object, JSC::ExecState* exec,
+ const JSC::Identifier& propertyName,
+ JSC::JSValue value, JSC::PutPropertySlot &slot)
+{
+#ifndef QT_NO_PROPERTIES
+ QByteArray name = convertToLatin1(propertyName.ustring());
+ QObject *qobject = data->value;
+ if (!qobject) {
+ QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject")
+ .arg(QString::fromLatin1(name));
+ JSC::throwError(exec, JSC::GeneralError, message);
+ return;
+ }
+
+ const QScriptEngine::QObjectWrapOptions &opt = data->options;
+ const QMetaObject *meta = qobject->metaObject();
+ QScriptEnginePrivate *eng = scriptEngineFromExec(exec);
+ int index = -1;
+ if (name.contains('(')) {
+ QByteArray normalized = QMetaObject::normalizedSignature(name);
+ if (-1 != (index = meta->indexOfMethod(normalized))) {
+ QMetaMethod method = meta->method(index);
+ if (hasMethodAccess(method, index, opt)) {
+ if (!(opt & QScriptEngine::ExcludeSuperClassMethods)
+ || (index >= meta->methodOffset())) {
+ data->cachedMembers.insert(name, value);
+ return;
+ }
+ }
+ }
+ }
+
+ index = meta->indexOfProperty(name);
+ if (index != -1) {
+ QMetaProperty prop = meta->property(index);
+ if (prop.isScriptable()) {
+ if (!(opt & QScriptEngine::ExcludeSuperClassProperties)
+ || (index >= meta->propertyOffset())) {
+ if (GeneratePropertyFunctions) {
+ // ### ideally JSC would do this for us already, i.e. find out
+ // that the property is a setter and call the setter.
+ // Maybe QtPropertyFunction needs to inherit JSC::GetterSetter.
+ JSC::JSValue fun;
+ QHash<QByteArray, JSC::JSValue>::const_iterator it;
+ it = data->cachedMembers.constFind(name);
+ if (it != data->cachedMembers.constEnd()) {
+ fun = it.value();
+ } else {
+ fun = new (exec)QtPropertyFunction(
+ meta, index, &exec->globalData(),
+ eng->originalGlobalObject()->functionStructure(),
+ propertyName);
+ data->cachedMembers.insert(name, fun);
+ }
+ JSC::CallData callData;
+ JSC::CallType callType = fun.getCallData(callData);
+ JSC::JSValue argv[1] = { value };
+ JSC::ArgList args(argv, 1);
+ (void)JSC::call(exec, fun, callType, callData, object, args);
+ } else {
+ QVariant v;
+ if (prop.isEnumType() && value.isString()
+ && !eng->hasDemarshalFunction(prop.userType())) {
+ // give QMetaProperty::write() a chance to convert from
+ // string to enum value
+ v = (QString)value.toString(exec);
+ } else {
+ v = QScriptEnginePrivate::jscValueToVariant(exec, value, prop.userType());
+ }
+ (void)prop.write(qobject, v);
+ }
+ return;
+ }
+ }
+ }
+
+ const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods)
+ ? meta->methodOffset() : 0;
+ for (index = meta->methodCount() - 1; index >= offset; --index) {
+ QMetaMethod method = meta->method(index);
+ if (hasMethodAccess(method, index, opt)
+ && methodNameEquals(method, name.constData(), name.length())) {
+ data->cachedMembers.insert(name, value);
+ return;
+ }
+ }
+
+ index = qobject->dynamicPropertyNames().indexOf(name);
+ if ((index != -1) || (opt & QScriptEngine::AutoCreateDynamicProperties)) {
+ QVariant v = QScriptEnginePrivate::toVariant(exec, value);
+ (void)qobject->setProperty(name, v);
+ return;
+ }
+
+ QScriptObjectDelegate::put(object, exec, propertyName, value, slot);
+#endif //QT_NO_PROPERTIES
+}
+
+bool QObjectDelegate::deleteProperty(QScriptObject *object, JSC::ExecState *exec,
+ const JSC::Identifier& propertyName)
+{
+#ifndef QT_NO_PROPERTIES
+ QByteArray name = convertToLatin1(propertyName.ustring());
+ QObject *qobject = data->value;
+ if (!qobject) {
+ QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject")
+ .arg(QString::fromLatin1(name));
+ JSC::throwError(exec, JSC::GeneralError, message);
+ return false;
+ }
+
+ const QMetaObject *meta = qobject->metaObject();
+ {
+ QHash<QByteArray, JSC::JSValue>::iterator it = data->cachedMembers.find(name);
+ if (it != data->cachedMembers.end()) {
+ if (GeneratePropertyFunctions && (meta->indexOfProperty(name) != -1))
+ return false;
+ data->cachedMembers.erase(it);
+ return true;
+ }
+ }
+
+ const QScriptEngine::QObjectWrapOptions &opt = data->options;
+ int index = meta->indexOfProperty(name);
+ if (index != -1) {
+ QMetaProperty prop = meta->property(index);
+ if (prop.isScriptable() &&
+ (!(opt & QScriptEngine::ExcludeSuperClassProperties)
+ || (index >= meta->propertyOffset()))) {
+ return false;
+ }
+ }
+
+ index = qobject->dynamicPropertyNames().indexOf(name);
+ if (index != -1) {
+ (void)qobject->setProperty(name, QVariant());
+ return true;
+ }
+
+ return QScriptObjectDelegate::deleteProperty(object, exec, propertyName);
+#else //QT_NO_PROPERTIES
+ return false;
+#endif //QT_NO_PROPERTIES
+}
+
+void QObjectDelegate::getOwnPropertyNames(QScriptObject *object, JSC::ExecState *exec,
+ JSC::PropertyNameArray &propertyNames,
+ JSC::EnumerationMode mode)
+{
+#ifndef QT_NO_PROPERTIES
+ QObject *qobject = data->value;
+ if (!qobject) {
+ QString message = QString::fromLatin1("cannot get property names of deleted QObject");
+ JSC::throwError(exec, JSC::GeneralError, message);
+ return;
+ }
+
+ const QScriptEngine::QObjectWrapOptions &opt = data->options;
+ const QMetaObject *meta = qobject->metaObject();
+ {
+ int i = (opt & QScriptEngine::ExcludeSuperClassProperties)
+ ? meta->propertyOffset() : 0;
+ for ( ; i < meta->propertyCount(); ++i) {
+ QMetaProperty prop = meta->property(i);
+ if (isEnumerableMetaProperty(prop, meta, i)) {
+ QString name = QString::fromLatin1(prop.name());
+ propertyNames.add(JSC::Identifier(exec, name));
+ }
+ }
+ }
+
+ {
+ QList<QByteArray> dpNames = qobject->dynamicPropertyNames();
+ for (int i = 0; i < dpNames.size(); ++i) {
+ QString name = QString::fromLatin1(dpNames.at(i));
+ propertyNames.add(JSC::Identifier(exec, name));
+ }
+ }
+
+ if (!(opt & QScriptEngine::SkipMethodsInEnumeration)) {
+ int i = (opt & QScriptEngine::ExcludeSuperClassMethods)
+ ? meta->methodOffset() : 0;
+ for ( ; i < meta->methodCount(); ++i) {
+ QMetaMethod method = meta->method(i);
+ if (hasMethodAccess(method, i, opt)) {
+ QMetaMethod method = meta->method(i);
+ QString sig = QString::fromLatin1(method.signature());
+ propertyNames.add(JSC::Identifier(exec, sig));
+ }
+ }
+ }
+
+ QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, mode);
+#endif //QT_NO_PROPERTIES
+}
+
+void QObjectDelegate::markChildren(QScriptObject *object, JSC::MarkStack& markStack)
+{
+ QHash<QByteArray, JSC::JSValue>::const_iterator it;
+ for (it = data->cachedMembers.constBegin(); it != data->cachedMembers.constEnd(); ++it) {
+ JSC::JSValue val = it.value();
+ if (val)
+ markStack.append(val);
+ }
+
+ QScriptObjectDelegate::markChildren(object, markStack);
+}
+
+bool QObjectDelegate::compareToObject(QScriptObject *, JSC::ExecState *exec, JSC::JSObject *o2)
+{
+ if (!o2->inherits(&QScriptObject::info))
+ return false;
+ QScriptObject *object = static_cast<QScriptObject*>(o2);
+ QScriptObjectDelegate *delegate = object->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::QtObject))
+ return false;
+ return value() == static_cast<QObjectDelegate *>(delegate)->value();
+}
+
+static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChild(JSC::ExecState *exec, JSC::JSObject*,
+ JSC::JSValue thisValue, const JSC::ArgList &args)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ thisValue = engine->toUsableValue(thisValue);
+ if (!thisValue.inherits(&QScriptObject::info))
+ return throwError(exec, JSC::TypeError, "this object is not a QObject");
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(thisValue));
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::QtObject))
+ return throwError(exec, JSC::TypeError, "this object is not a QObject");
+ QObject *obj = static_cast<QObjectDelegate*>(delegate)->value();
+ QString name;
+ if (args.size() != 0)
+ name = args.at(0).toString(exec);
+ QObject *child = obj->findChild<QObject*>(name);
+ QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject;
+ return engine->newQObject(child, QScriptEngine::QtOwnership, opt);
+}
+
+static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChildren(JSC::ExecState *exec, JSC::JSObject*,
+ JSC::JSValue thisValue, const JSC::ArgList &args)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ thisValue = engine->toUsableValue(thisValue);
+ // extract the QObject
+ if (!thisValue.inherits(&QScriptObject::info))
+ return throwError(exec, JSC::TypeError, "this object is not a QObject");
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(thisValue));
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::QtObject))
+ return throwError(exec, JSC::TypeError, "this object is not a QObject");
+ const QObject *const obj = static_cast<QObjectDelegate*>(delegate)->value();
+
+ // find the children
+ QList<QObject *> children;
+ if (args.size() != 0) {
+ const JSC::JSValue arg = args.at(0);
+ if (arg.inherits(&JSC::RegExpObject::info)) {
+ const QObjectList allChildren= obj->children();
+
+ JSC::RegExpObject *const regexp = JSC::asRegExpObject(arg);
+
+ const int allChildrenCount = allChildren.size();
+ for (int i = 0; i < allChildrenCount; ++i) {
+ QObject *const child = allChildren.at(i);
+ const JSC::UString childName = child->objectName();
+ JSC::RegExpConstructor* regExpConstructor = engine->originalGlobalObject()->regExpConstructor();
+ int position;
+ int length;
+ regExpConstructor->performMatch(regexp->regExp(), childName, 0, position, length);
+ if (position >= 0)
+ children.append(child);
+ }
+ } else {
+ const QString name(args.at(0).toString(exec));
+ children = obj->findChildren<QObject*>(name);
+ }
+ } else {
+ children = obj->findChildren<QObject*>(QString());
+ }
+ // create the result array with the children
+ const int length = children.size();
+ JSC::JSArray *const result = JSC::constructEmptyArray(exec, length);
+
+ QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject;
+ for (int i = 0; i < length; ++i) {
+ QObject *const child = children.at(i);
+ result->put(exec, i, engine->newQObject(child, QScriptEngine::QtOwnership, opt));
+ }
+ return JSC::JSValue(result);
+}
+
+static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncToString(JSC::ExecState *exec, JSC::JSObject*,
+ JSC::JSValue thisValue, const JSC::ArgList&)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ thisValue = engine->toUsableValue(thisValue);
+ if (!thisValue.inherits(&QScriptObject::info))
+ return JSC::jsUndefined();
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(thisValue));
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::QtObject))
+ return JSC::jsUndefined();
+ QObject *obj = static_cast<QObjectDelegate*>(delegate)->value();
+ const QMetaObject *meta = obj ? obj->metaObject() : &QObject::staticMetaObject;
+ QString name = obj ? obj->objectName() : QString::fromUtf8("unnamed");
+ QString str = QString::fromUtf8("%0(name = \"%1\")")
+ .arg(QLatin1String(meta->className())).arg(name);
+ return JSC::jsString(exec, str);
+}
+
+QObjectPrototype::QObjectPrototype(JSC::ExecState* exec, WTF::PassRefPtr<JSC::Structure> structure,
+ JSC::Structure* prototypeFunctionStructure)
+ : QScriptObject(structure)
+{
+ setDelegate(new QObjectDelegate(new QObjectPrototypeObject(), QScriptEngine::AutoOwnership,
+ QScriptEngine::ExcludeSuperClassMethods
+ | QScriptEngine::ExcludeSuperClassProperties
+ | QScriptEngine::ExcludeChildObjects));
+
+ putDirectFunction(exec, new (exec) JSC::NativeFunctionWrapper(exec, prototypeFunctionStructure, /*length=*/0, exec->propertyNames().toString, qobjectProtoFuncToString), JSC::DontEnum);
+ putDirectFunction(exec, new (exec) JSC::NativeFunctionWrapper(exec, prototypeFunctionStructure, /*length=*/1, JSC::Identifier(exec, "findChild"), qobjectProtoFuncFindChild), JSC::DontEnum);
+ putDirectFunction(exec, new (exec) JSC::NativeFunctionWrapper(exec, prototypeFunctionStructure, /*length=*/1, JSC::Identifier(exec, "findChildren"), qobjectProtoFuncFindChildren), JSC::DontEnum);
+ this->structure()->setHasGetterSetterProperties(true);
+}
+
+const JSC::ClassInfo QMetaObjectWrapperObject::info = { "QMetaObject", 0, 0, 0 };
+
+QMetaObjectWrapperObject::QMetaObjectWrapperObject(
+ JSC::ExecState *exec, const QMetaObject *metaObject, JSC::JSValue ctor,
+ WTF::PassRefPtr<JSC::Structure> sid)
+ : JSC::JSObject(sid),
+ data(new Data(metaObject, ctor))
+{
+ if (!ctor)
+ data->prototype = new (exec)JSC::JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
+}
+
+QMetaObjectWrapperObject::~QMetaObjectWrapperObject()
+{
+ delete data;
+}
+
+bool QMetaObjectWrapperObject::getOwnPropertySlot(
+ JSC::ExecState *exec, const JSC::Identifier& propertyName,
+ JSC::PropertySlot &slot)
+{
+ const QMetaObject *meta = data->value;
+ if (!meta)
+ return false;
+
+ if (propertyName == exec->propertyNames().prototype) {
+ if (data->ctor)
+ slot.setValue(data->ctor.get(exec, propertyName));
+ else
+ slot.setValue(data->prototype);
+ return true;
+ }
+
+ QByteArray name = convertToLatin1(propertyName.ustring());
+
+ for (int i = 0; i < meta->enumeratorCount(); ++i) {
+ QMetaEnum e = meta->enumerator(i);
+ for (int j = 0; j < e.keyCount(); ++j) {
+ const char *key = e.key(j);
+ if (!qstrcmp(key, name.constData())) {
+ slot.setValue(JSC::JSValue(exec, e.value(j)));
+ return true;
+ }
+ }
+ }
+
+ return JSC::JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool QMetaObjectWrapperObject::getOwnPropertyDescriptor(
+ JSC::ExecState* exec, const JSC::Identifier& propertyName,
+ JSC::PropertyDescriptor& descriptor)
+{
+ const QMetaObject *meta = data->value;
+ if (!meta)
+ return false;
+
+ if (propertyName == exec->propertyNames().prototype) {
+ descriptor.setDescriptor(data->ctor
+ ? data->ctor.get(exec, propertyName)
+ : data->prototype,
+ JSC::DontDelete | JSC::DontEnum);
+ return true;
+ }
+
+ QByteArray name = QString(propertyName.ustring()).toLatin1();
+
+ for (int i = 0; i < meta->enumeratorCount(); ++i) {
+ QMetaEnum e = meta->enumerator(i);
+ for (int j = 0; j < e.keyCount(); ++j) {
+ const char *key = e.key(j);
+ if (!qstrcmp(key, name.constData())) {
+ descriptor.setDescriptor(JSC::JSValue(exec, e.value(j)),
+ JSC::ReadOnly | JSC::DontDelete);
+ return true;
+ }
+ }
+ }
+
+ return JSC::JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
+void QMetaObjectWrapperObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName,
+ JSC::JSValue value, JSC::PutPropertySlot &slot)
+{
+ if (propertyName == exec->propertyNames().prototype) {
+ if (data->ctor)
+ data->ctor.put(exec, propertyName, value, slot);
+ else
+ data->prototype = value;
+ return;
+ }
+ const QMetaObject *meta = data->value;
+ if (meta) {
+ QByteArray name = convertToLatin1(propertyName.ustring());
+ for (int i = 0; i < meta->enumeratorCount(); ++i) {
+ QMetaEnum e = meta->enumerator(i);
+ for (int j = 0; j < e.keyCount(); ++j) {
+ if (!qstrcmp(e.key(j), name.constData()))
+ return;
+ }
+ }
+ }
+ JSC::JSObject::put(exec, propertyName, value, slot);
+}
+
+bool QMetaObjectWrapperObject::deleteProperty(
+ JSC::ExecState *exec, const JSC::Identifier& propertyName)
+{
+ if (propertyName == exec->propertyNames().prototype)
+ return false;
+ const QMetaObject *meta = data->value;
+ if (meta) {
+ QByteArray name = convertToLatin1(propertyName.ustring());
+ for (int i = 0; i < meta->enumeratorCount(); ++i) {
+ QMetaEnum e = meta->enumerator(i);
+ for (int j = 0; j < e.keyCount(); ++j) {
+ if (!qstrcmp(e.key(j), name.constData()))
+ return false;
+ }
+ }
+ }
+ return JSC::JSObject::deleteProperty(exec, propertyName);
+}
+
+void QMetaObjectWrapperObject::getOwnPropertyNames(JSC::ExecState *exec,
+ JSC::PropertyNameArray &propertyNames,
+ JSC::EnumerationMode mode)
+{
+ const QMetaObject *meta = data->value;
+ if (!meta)
+ return;
+ for (int i = 0; i < meta->enumeratorCount(); ++i) {
+ QMetaEnum e = meta->enumerator(i);
+ for (int j = 0; j < e.keyCount(); ++j)
+ propertyNames.add(JSC::Identifier(exec, e.key(j)));
+ }
+ JSC::JSObject::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
+void QMetaObjectWrapperObject::markChildren(JSC::MarkStack& markStack)
+{
+ if (data->ctor)
+ markStack.append(data->ctor);
+ if (data->prototype)
+ markStack.append(data->prototype);
+ JSC::JSObject::markChildren(markStack);
+}
+
+JSC::CallType QMetaObjectWrapperObject::getCallData(JSC::CallData& callData)
+{
+ callData.native.function = call;
+ return JSC::CallTypeHost;
+}
+
+JSC::ConstructType QMetaObjectWrapperObject::getConstructData(JSC::ConstructData& constructData)
+{
+ constructData.native.function = construct;
+ return JSC::ConstructTypeHost;
+}
+
+JSC::JSValue JSC_HOST_CALL QMetaObjectWrapperObject::call(
+ JSC::ExecState *exec, JSC::JSObject *callee,
+ JSC::JSValue thisValue, const JSC::ArgList &args)
+{
+ QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
+ thisValue = eng_p->toUsableValue(thisValue);
+ if (!callee->inherits(&QMetaObjectWrapperObject::info))
+ return throwError(exec, JSC::TypeError, "callee is not a QMetaObject");
+ QMetaObjectWrapperObject *self = static_cast<QMetaObjectWrapperObject*>(callee);
+ JSC::ExecState *previousFrame = eng_p->currentFrame;
+ eng_p->pushContext(exec, thisValue, args, callee);
+ JSC::JSValue result = self->execute(eng_p->currentFrame, args);
+ eng_p->popContext();
+ eng_p->currentFrame = previousFrame;
+ return result;
+}
+
+JSC::JSObject* QMetaObjectWrapperObject::construct(JSC::ExecState *exec, JSC::JSObject *callee, const JSC::ArgList &args)
+{
+ QMetaObjectWrapperObject *self = static_cast<QMetaObjectWrapperObject*>(callee);
+ QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
+ JSC::ExecState *previousFrame = eng_p->currentFrame;
+ eng_p->pushContext(exec, JSC::JSValue(), args, callee, true);
+ JSC::JSValue result = self->execute(eng_p->currentFrame, args);
+ eng_p->popContext();
+ eng_p->currentFrame = previousFrame;
+ if (!result || !result.isObject())
+ return 0;
+ return JSC::asObject(result);
+}
+
+JSC::JSValue QMetaObjectWrapperObject::execute(JSC::ExecState *exec,
+ const JSC::ArgList &args)
+{
+ if (data->ctor) {
+ QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec);
+ QScriptContext *ctx = eng_p->contextForFrame(exec);
+ JSC::CallData callData;
+ JSC::CallType callType = data->ctor.getCallData(callData);
+ Q_UNUSED(callType);
+ Q_ASSERT_X(callType == JSC::CallTypeHost, Q_FUNC_INFO, "script constructors not supported");
+ if (data->ctor.inherits(&FunctionWithArgWrapper::info)) {
+ FunctionWithArgWrapper *wrapper = static_cast<FunctionWithArgWrapper*>(JSC::asObject(data->ctor));
+ QScriptValue result = wrapper->function()(ctx, QScriptEnginePrivate::get(eng_p), wrapper->arg());
+ return eng_p->scriptValueToJSCValue(result);
+ } else {
+ Q_ASSERT(data->ctor.inherits(&FunctionWrapper::info));
+ FunctionWrapper *wrapper = static_cast<FunctionWrapper*>(JSC::asObject(data->ctor));
+ QScriptValue result = wrapper->function()(ctx, QScriptEnginePrivate::get(eng_p));
+ return eng_p->scriptValueToJSCValue(result);
+ }
+ } else {
+ const QMetaObject *meta = data->value;
+ if (meta->constructorCount() > 0) {
+ JSC::JSValue result = callQtMethod(exec, QMetaMethod::Constructor, /*thisQObject=*/0,
+ args, meta, meta->constructorCount()-1, /*maybeOverloaded=*/true);
+ if (!exec->hadException()) {
+ Q_ASSERT(result && result.inherits(&QScriptObject::info));
+ QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(result));
+ QScript::QObjectDelegate *delegate = static_cast<QScript::QObjectDelegate*>(object->delegate());
+ delegate->setOwnership(QScriptEngine::AutoOwnership);
+ if (data->prototype)
+ object->setPrototype(data->prototype);
+ }
+ return result;
+ } else {
+ QString message = QString::fromLatin1("no constructor for %0")
+ .arg(QLatin1String(meta->className()));
+ return JSC::throwError(exec, JSC::TypeError, message);
+ }
+ }
+}
+
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
+};
+
+static JSC::JSValue JSC_HOST_CALL qmetaobjectProtoFuncClassName(
+ JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue thisValue, const JSC::ArgList&)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ thisValue = engine->toUsableValue(thisValue);
+ if (!thisValue.inherits(&QMetaObjectWrapperObject::info))
+ return throwError(exec, JSC::TypeError, "this object is not a QMetaObject");
+ const QMetaObject *meta = static_cast<QMetaObjectWrapperObject*>(JSC::asObject(thisValue))->value();
+ return JSC::jsString(exec, meta->className());
+}
+
+QMetaObjectPrototype::QMetaObjectPrototype(
+ JSC::ExecState *exec, WTF::PassRefPtr<JSC::Structure> structure,
+ JSC::Structure* prototypeFunctionStructure)
+ : QMetaObjectWrapperObject(exec, StaticQtMetaObject::get(), /*ctor=*/JSC::JSValue(), structure)
+{
+ putDirectFunction(exec, new (exec) JSC::NativeFunctionWrapper(exec, prototypeFunctionStructure, /*length=*/0, JSC::Identifier(exec, "className"), qmetaobjectProtoFuncClassName), JSC::DontEnum);
+}
+
+static const uint qt_meta_data_QObjectConnectionManager[] = {
+
+ // content:
+ 1, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 1, 10, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+
+ // slots: signature, parameters, type, tag, flags
+ 35, 34, 34, 34, 0x0a,
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_QObjectConnectionManager[] = {
+ "QScript::QObjectConnectionManager\0\0execute()\0"
+};
+
+const QMetaObject QObjectConnectionManager::staticMetaObject = {
+ { &QObject::staticMetaObject, qt_meta_stringdata_QObjectConnectionManager,
+ qt_meta_data_QObjectConnectionManager, 0 }
+};
+
+const QMetaObject *QObjectConnectionManager::metaObject() const
+{
+ return &staticMetaObject;
+}
+
+void *QObjectConnectionManager::qt_metacast(const char *_clname)
+{
+ if (!_clname) return 0;
+ if (!strcmp(_clname, qt_meta_stringdata_QObjectConnectionManager))
+ return static_cast<void*>(const_cast<QObjectConnectionManager*>(this));
+ return QObject::qt_metacast(_clname);
+}
+
+int QObjectConnectionManager::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QObject::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ execute(_id, _a);
+ _id -= slotCounter;
+ }
+ return _id;
+}
+
+void QObjectConnectionManager::execute(int slotIndex, void **argv)
+{
+ JSC::JSValue receiver;
+ JSC::JSValue slot;
+ JSC::JSValue senderWrapper;
+ int signalIndex = -1;
+ QScript::APIShim shim(engine);
+ for (int i = 0; i < connections.size(); ++i) {
+ const QVector<QObjectConnection> &cs = connections.at(i);
+ for (int j = 0; j < cs.size(); ++j) {
+ const QObjectConnection &c = cs.at(j);
+ if (c.slotIndex == slotIndex) {
+ receiver = c.receiver;
+ slot = c.slot;
+ senderWrapper = c.senderWrapper;
+ signalIndex = i;
+ break;
+ }
+ }
+ }
+ Q_ASSERT(slot && slot.isObject());
+
+ if (engine->isCollecting()) {
+ qWarning("QtScript: can't execute signal handler during GC");
+ // we can't do a script function call during GC,
+ // so we're forced to ignore this signal
+ return;
+ }
+
+#if 0
+ QScriptFunction *fun = engine->convertToNativeFunction(slot);
+ if (fun == 0) {
+ // the signal handler has been GC'ed. This can only happen when
+ // a QObject is owned by the engine, the engine is destroyed, and
+ // there is a script function connected to the destroyed() signal
+ Q_ASSERT(signalIndex <= 1); // destroyed(QObject*)
+ return;
+ }
+#endif
+
+ const QMetaObject *meta = sender()->metaObject();
+ const QMetaMethod method = meta->method(signalIndex);
+
+ QList<QByteArray> parameterTypes = method.parameterTypes();
+ int argc = parameterTypes.count();
+
+ JSC::ExecState *exec = engine->currentFrame;
+ QVarLengthArray<JSC::JSValue, 8> argsVector(argc);
+ for (int i = 0; i < argc; ++i) {
+ JSC::JSValue actual;
+ void *arg = argv[i + 1];
+ QByteArray typeName = parameterTypes.at(i);
+ int argType = QMetaType::type(parameterTypes.at(i));
+ if (!argType) {
+ qWarning("QScriptEngine: Unable to handle unregistered datatype '%s' "
+ "when invoking handler of signal %s::%s",
+ typeName.constData(), meta->className(), method.signature());
+ actual = JSC::jsUndefined();
+ } else if (argType == QMetaType::QVariant) {
+ actual = QScriptEnginePrivate::jscValueFromVariant(exec, *reinterpret_cast<QVariant*>(arg));
+ } else {
+ actual = QScriptEnginePrivate::create(exec, argType, arg);
+ }
+ argsVector[i] = actual;
+ }
+ JSC::ArgList jscArgs(argsVector.data(), argsVector.size());
+
+ JSC::JSValue senderObject;
+ if (senderWrapper && senderWrapper.inherits(&QScriptObject::info)) // ### check if it's actually a QObject wrapper
+ senderObject = senderWrapper;
+ else {
+ QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject;
+ senderObject = engine->newQObject(sender(), QScriptEngine::QtOwnership, opt);
+ }
+
+ JSC::JSValue thisObject;
+ if (receiver && receiver.isObject())
+ thisObject = receiver;
+ else
+ thisObject = engine->globalObject();
+
+ JSC::CallData callData;
+ JSC::CallType callType = slot.getCallData(callData);
+ if (exec->hadException())
+ exec->clearException(); // ### otherwise JSC asserts
+ JSC::call(exec, slot, callType, callData, thisObject, jscArgs);
+
+ if (exec->hadException()) {
+ if (slot.inherits(&QtFunction::info) && !static_cast<QtFunction*>(JSC::asObject(slot))->qobject()) {
+ // The function threw an error because the target QObject has been deleted.
+ // The connections list is stale; remove the signal handler and ignore the exception.
+ removeSignalHandler(sender(), signalIndex, receiver, slot);
+ exec->clearException();
+ } else {
+ engine->emitSignalHandlerException();
+ }
+ }
+}
+
+QObjectConnectionManager::QObjectConnectionManager(QScriptEnginePrivate *eng)
+ : engine(eng), slotCounter(0)
+{
+}
+
+QObjectConnectionManager::~QObjectConnectionManager()
+{
+}
+
+void QObjectConnectionManager::mark(JSC::MarkStack& markStack)
+{
+ for (int i = 0; i < connections.size(); ++i) {
+ QVector<QObjectConnection> &cs = connections[i];
+ for (int j = 0; j < cs.size(); ++j)
+ cs[j].mark(markStack);
+ }
+}
+
+bool QObjectConnectionManager::addSignalHandler(
+ QObject *sender, int signalIndex, JSC::JSValue receiver,
+ JSC::JSValue function, JSC::JSValue senderWrapper,
+ Qt::ConnectionType type)
+{
+ if (connections.size() <= signalIndex)
+ connections.resize(signalIndex+1);
+ QVector<QObjectConnection> &cs = connections[signalIndex];
+ int absSlotIndex = slotCounter + metaObject()->methodOffset();
+ bool ok = QMetaObject::connect(sender, signalIndex, this, absSlotIndex, type);
+ if (ok) {
+ cs.append(QObjectConnection(slotCounter++, receiver, function, senderWrapper));
+ QMetaMethod signal = sender->metaObject()->method(signalIndex);
+ QByteArray signalString;
+ signalString.append('2'); // signal code
+ signalString.append(signal.signature());
+ static_cast<QObjectNotifyCaller*>(sender)->callConnectNotify(signalString);
+ }
+ return ok;
+}
+
+bool QObjectConnectionManager::removeSignalHandler(
+ QObject *sender, int signalIndex,
+ JSC::JSValue receiver, JSC::JSValue slot)
+{
+ if (connections.size() <= signalIndex)
+ return false;
+ QVector<QObjectConnection> &cs = connections[signalIndex];
+ for (int i = 0; i < cs.size(); ++i) {
+ const QObjectConnection &c = cs.at(i);
+ if (c.hasTarget(receiver, slot)) {
+ int absSlotIndex = c.slotIndex + metaObject()->methodOffset();
+ bool ok = QMetaObject::disconnect(sender, signalIndex, this, absSlotIndex);
+ if (ok) {
+ cs.remove(i);
+ QMetaMethod signal = sender->metaObject()->method(signalIndex);
+ QByteArray signalString;
+ signalString.append('2'); // signal code
+ signalString.append(signal.signature());
+ static_cast<QScript::QObjectNotifyCaller*>(sender)->callDisconnectNotify(signalString);
+ }
+ return ok;
+ }
+ }
+ return false;
+}
+
+QObjectData::QObjectData(QScriptEnginePrivate *eng)
+ : engine(eng), connectionManager(0)
+{
+}
+
+QObjectData::~QObjectData()
+{
+ if (connectionManager) {
+ delete connectionManager;
+ connectionManager = 0;
+ }
+}
+
+void QObjectData::mark(JSC::MarkStack& markStack)
+{
+ if (connectionManager)
+ connectionManager->mark(markStack);
+ {
+ QList<QScript::QObjectWrapperInfo>::iterator it;
+ for (it = wrappers.begin(); it != wrappers.end(); ) {
+ const QScript::QObjectWrapperInfo &info = *it;
+ // ### don't mark if there are no other references.
+ // we need something like isMarked()
+ markStack.append(info.object);
+ ++it;
+ }
+ }
+}
+
+bool QObjectData::addSignalHandler(QObject *sender,
+ int signalIndex,
+ JSC::JSValue receiver,
+ JSC::JSValue slot,
+ JSC::JSValue senderWrapper,
+ Qt::ConnectionType type)
+{
+ if (!connectionManager)
+ connectionManager = new QObjectConnectionManager(engine);
+ return connectionManager->addSignalHandler(
+ sender, signalIndex, receiver, slot, senderWrapper, type);
+}
+
+bool QObjectData::removeSignalHandler(QObject *sender,
+ int signalIndex,
+ JSC::JSValue receiver,
+ JSC::JSValue slot)
+{
+ if (!connectionManager)
+ return false;
+ return connectionManager->removeSignalHandler(
+ sender, signalIndex, receiver, slot);
+}
+
+QScriptObject *QObjectData::findWrapper(QScriptEngine::ValueOwnership ownership,
+ const QScriptEngine::QObjectWrapOptions &options) const
+{
+ for (int i = 0; i < wrappers.size(); ++i) {
+ const QObjectWrapperInfo &info = wrappers.at(i);
+ if ((info.ownership == ownership) && (info.options == options))
+ return info.object;
+ }
+ return 0;
+}
+
+void QObjectData::registerWrapper(QScriptObject *wrapper,
+ QScriptEngine::ValueOwnership ownership,
+ const QScriptEngine::QObjectWrapOptions &options)
+{
+ wrappers.append(QObjectWrapperInfo(wrapper, ownership, options));
+}
+
+} // namespace QScript
+
+QT_END_NAMESPACE
+
+namespace JSC
+{
+ ASSERT_CLASS_FITS_IN_CELL(QScript::QtFunction);
+}
+
+#include "moc_qscriptqobject_p.cpp"
+
diff --git a/src/script/bridge/qscriptqobject_p.h b/src/script/bridge/qscriptqobject_p.h
new file mode 100644
index 0000000..7e62540
--- /dev/null
+++ b/src/script/bridge/qscriptqobject_p.h
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTQOBJECT_P_H
+#define QSCRIPTQOBJECT_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 "qscriptobject_p.h"
+
+#include "qscriptengine.h"
+#include <QtCore/qpointer.h>
+
+#include "InternalFunction.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QScript
+{
+
+enum AttributeExtension {
+ // ### Make sure there's no conflict with JSC::Attribute
+ QObjectMemberAttribute = 1 << 12
+};
+
+class QObjectDelegate : public QScriptObjectDelegate
+{
+public:
+ struct Data
+ {
+ QPointer<QObject> value;
+ QScriptEngine::ValueOwnership ownership;
+ QScriptEngine::QObjectWrapOptions options;
+
+ QHash<QByteArray, JSC::JSValue> cachedMembers;
+
+ Data(QObject *o, QScriptEngine::ValueOwnership own,
+ QScriptEngine::QObjectWrapOptions opt)
+ : value(o), ownership(own), options(opt) {}
+ };
+
+ QObjectDelegate(
+ QObject *object, QScriptEngine::ValueOwnership ownership,
+ const QScriptEngine::QObjectWrapOptions &options);
+ ~QObjectDelegate();
+
+ virtual Type type() const;
+
+ virtual bool getOwnPropertySlot(QScriptObject*, JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ JSC::PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(QScriptObject*, JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ JSC::PropertyDescriptor&);
+
+ 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);
+ virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*,
+ JSC::PropertyNameArray&,
+ JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);
+ virtual void markChildren(QScriptObject*, JSC::MarkStack& markStack);
+ virtual bool compareToObject(QScriptObject*, JSC::ExecState*, JSC::JSObject*);
+
+ inline QObject *value() const { return data->value; }
+ inline void setValue(QObject* value) { data->value = value; }
+
+ inline QScriptEngine::ValueOwnership ownership() const
+ { return data->ownership; }
+ inline void setOwnership(QScriptEngine::ValueOwnership ownership)
+ { data->ownership = ownership; }
+
+ inline QScriptEngine::QObjectWrapOptions options() const
+ { return data->options; }
+ inline void setOptions(QScriptEngine::QObjectWrapOptions options)
+ { data->options = options; }
+
+protected:
+ Data *data;
+};
+
+class QObjectPrototypeObject : public QObject
+{
+ Q_OBJECT
+public:
+ QObjectPrototypeObject(QObject *parent = 0)
+ : QObject(parent) { }
+ ~QObjectPrototypeObject() { }
+};
+
+class QObjectPrototype : public QScriptObject
+{
+public:
+ QObjectPrototype(JSC::ExecState*, WTF::PassRefPtr<JSC::Structure>,
+ JSC::Structure* prototypeFunctionStructure);
+};
+
+class QObjectConnectionManager;
+
+struct QObjectWrapperInfo
+{
+ QObjectWrapperInfo(QScriptObject *obj,
+ QScriptEngine::ValueOwnership own,
+ const QScriptEngine::QObjectWrapOptions &opt)
+ : object(obj), ownership(own), options(opt) {}
+
+ QScriptObject *object;
+ QScriptEngine::ValueOwnership ownership;
+ QScriptEngine::QObjectWrapOptions options;
+};
+
+class QObjectData // : public QObjectUserData
+{
+public:
+ QObjectData(QScriptEnginePrivate *engine);
+ ~QObjectData();
+
+ bool addSignalHandler(QObject *sender,
+ int signalIndex,
+ JSC::JSValue receiver,
+ JSC::JSValue slot,
+ JSC::JSValue senderWrapper,
+ Qt::ConnectionType type);
+ bool removeSignalHandler(QObject *sender,
+ int signalIndex,
+ JSC::JSValue receiver,
+ JSC::JSValue slot);
+
+ QScriptObject *findWrapper(QScriptEngine::ValueOwnership ownership,
+ const QScriptEngine::QObjectWrapOptions &options) const;
+ void registerWrapper(QScriptObject *wrapper,
+ QScriptEngine::ValueOwnership ownership,
+ const QScriptEngine::QObjectWrapOptions &options);
+
+ void mark(JSC::MarkStack&);
+
+private:
+ QScriptEnginePrivate *engine;
+ QScript::QObjectConnectionManager *connectionManager;
+ QList<QScript::QObjectWrapperInfo> wrappers;
+};
+
+class QtFunction: public JSC::InternalFunction
+{
+public:
+ // work around CELL_SIZE limitation
+ struct Data
+ {
+ JSC::JSValue object;
+ int initialIndex;
+ bool maybeOverloaded;
+
+ Data(JSC::JSValue o, int ii, bool mo)
+ : object(o), initialIndex(ii), maybeOverloaded(mo) {}
+ };
+
+ QtFunction(JSC::JSValue object, int initialIndex, bool maybeOverloaded,
+ JSC::JSGlobalData*, WTF::PassRefPtr<JSC::Structure>, const JSC::Identifier&);
+ virtual ~QtFunction();
+
+ virtual JSC::CallType getCallData(JSC::CallData&);
+ virtual void markChildren(JSC::MarkStack&);
+
+ virtual const JSC::ClassInfo* classInfo() const { return &info; }
+ static const JSC::ClassInfo info;
+
+ static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*,
+ JSC::JSValue, const JSC::ArgList&);
+
+ JSC::JSValue execute(JSC::ExecState *exec, JSC::JSValue thisValue,
+ const JSC::ArgList &args);
+
+ QScriptObject *wrapperObject() const;
+ QObject *qobject() const;
+ const QMetaObject *metaObject() const;
+ int initialIndex() const;
+ bool maybeOverloaded() const;
+ int mostGeneralMethod(QMetaMethod *out = 0) const;
+ QList<int> overloadedIndexes() const;
+
+private:
+ Data *data;
+};
+
+class QtPropertyFunction: public JSC::InternalFunction
+{
+public:
+ // work around CELL_SIZE limitation
+ struct Data
+ {
+ const QMetaObject *meta;
+ int index;
+
+ Data(const QMetaObject *m, int i)
+ : meta(m), index(i) {}
+ };
+
+ QtPropertyFunction(const QMetaObject *meta, int index,
+ JSC::JSGlobalData*, WTF::PassRefPtr<JSC::Structure>,
+ const JSC::Identifier&);
+ virtual ~QtPropertyFunction();
+
+ virtual JSC::CallType getCallData(JSC::CallData&);
+
+ virtual const JSC::ClassInfo* classInfo() const { return &info; }
+ static const JSC::ClassInfo info;
+
+ static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*,
+ JSC::JSValue, const JSC::ArgList&);
+
+ JSC::JSValue execute(JSC::ExecState *exec, JSC::JSValue thisValue,
+ const JSC::ArgList &args);
+
+ const QMetaObject *metaObject() const;
+ int propertyIndex() const;
+
+private:
+ Data *data;
+};
+
+class QMetaObjectWrapperObject : public JSC::JSObject
+{
+public:
+ // work around CELL_SIZE limitation
+ struct Data
+ {
+ const QMetaObject *value;
+ JSC::JSValue ctor;
+ JSC::JSValue prototype;
+
+ Data(const QMetaObject *mo, JSC::JSValue c)
+ : value(mo), ctor(c) {}
+ };
+
+ explicit QMetaObjectWrapperObject(
+ JSC::ExecState *, const QMetaObject *metaobject, JSC::JSValue ctor,
+ WTF::PassRefPtr<JSC::Structure> sid);
+ ~QMetaObjectWrapperObject();
+
+ virtual bool getOwnPropertySlot(JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ JSC::PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ JSC::PropertyDescriptor&);
+ virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName,
+ JSC::JSValue, JSC::PutPropertySlot&);
+ virtual bool deleteProperty(JSC::ExecState*,
+ const JSC::Identifier& propertyName);
+ virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&,
+ JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);
+ virtual void markChildren(JSC::MarkStack& markStack);
+
+ virtual JSC::CallType getCallData(JSC::CallData&);
+ virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
+
+ virtual const JSC::ClassInfo* classInfo() const { return &info; }
+ static const JSC::ClassInfo info;
+
+ static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*,
+ JSC::JSValue, const JSC::ArgList&);
+ static JSC::JSObject* construct(JSC::ExecState *, JSC::JSObject *, const JSC::ArgList &);
+
+ JSC::JSValue execute(JSC::ExecState *exec, const JSC::ArgList &args);
+
+ inline const QMetaObject *value() const { return data->value; }
+ inline void setValue(const QMetaObject* value) { data->value = value; }
+
+ static WTF::PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags));
+ }
+
+protected:
+ static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | JSC::ImplementsHasInstance | JSObject::StructureFlags;
+
+ Data *data;
+};
+
+class QMetaObjectPrototype : public QMetaObjectWrapperObject
+{
+public:
+ QMetaObjectPrototype(JSC::ExecState*, WTF::PassRefPtr<JSC::Structure>,
+ JSC::Structure* prototypeFunctionStructure);
+};
+
+} // namespace QScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/bridge/qscriptstaticscopeobject.cpp b/src/script/bridge/qscriptstaticscopeobject.cpp
new file mode 100644
index 0000000..1a2fa0f
--- /dev/null
+++ b/src/script/bridge/qscriptstaticscopeobject.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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 "qscriptstaticscopeobject_p.h"
+
+namespace JSC
+{
+ ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScriptStaticScopeObject));
+}
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QScriptStaticScopeObject
+ \internal
+
+ Represents a static scope object.
+
+ This class allows the VM to determine at JS script compile time whether
+ the object has a given property or not. If the object has the property,
+ a fast, index-based read/write operation will be used. If the object
+ doesn't have the property, the compiler knows it can safely skip this
+ object when dynamically resolving the property. Either way, this can
+ greatly improve performance.
+
+ \sa QScriptContext::pushScope()
+*/
+
+const JSC::ClassInfo QScriptStaticScopeObject::info = { "QScriptStaticScopeObject", 0, 0, 0 };
+
+/*!
+ Creates a static scope object with a fixed set of undeletable properties.
+
+ It's not possible to add new properties to the object after construction.
+*/
+QScriptStaticScopeObject::QScriptStaticScopeObject(WTF::NonNullPassRefPtr<JSC::Structure> structure,
+ int propertyCount, const PropertyInfo* props)
+ : JSC::JSVariableObject(structure, new Data(/*canGrow=*/false))
+{
+ int index = growRegisterArray(propertyCount);
+ for (int i = 0; i < propertyCount; ++i, --index) {
+ const PropertyInfo& prop = props[i];
+ JSC::SymbolTableEntry entry(index, prop.attributes);
+ symbolTable().add(prop.identifier.ustring().rep(), entry);
+ registerAt(index) = prop.value;
+ }
+}
+
+/*!
+ Creates an empty static scope object.
+
+ Properties can be added to the object after construction, either by
+ calling QScriptValue::setProperty(), or by pushing the object on the
+ scope chain; variable declarations ("var" statements) and function
+ declarations in JavaScript will create properties on the scope object.
+
+ Note that once the scope object has been used in a closure and the
+ resulting function has been compiled, it's no longer safe to add
+ properties to the scope object (because the VM will bypass this
+ object the next time the function is executed).
+*/
+QScriptStaticScopeObject::QScriptStaticScopeObject(WTF::NonNullPassRefPtr<JSC::Structure> structure)
+ : JSC::JSVariableObject(structure, new Data(/*canGrow=*/true))
+{
+}
+
+QScriptStaticScopeObject::~QScriptStaticScopeObject()
+{
+ delete d_ptr();
+}
+
+bool QScriptStaticScopeObject::getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot& slot)
+{
+ return symbolTableGet(propertyName, slot);
+}
+
+bool QScriptStaticScopeObject::getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor)
+{
+ return symbolTableGet(propertyName, descriptor);
+}
+
+void QScriptStaticScopeObject::putWithAttributes(JSC::ExecState* exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes)
+{
+ if (symbolTablePutWithAttributes(propertyName, value, attributes))
+ return;
+ Q_ASSERT(d_ptr()->canGrow);
+ addSymbolTableProperty(propertyName, value, attributes);
+}
+
+void QScriptStaticScopeObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot&)
+{
+ if (symbolTablePut(propertyName, value))
+ return;
+ Q_ASSERT(d_ptr()->canGrow);
+ addSymbolTableProperty(propertyName, value, /*attributes=*/0);
+}
+
+bool QScriptStaticScopeObject::deleteProperty(JSC::ExecState*, const JSC::Identifier&)
+{
+ return false;
+}
+
+void QScriptStaticScopeObject::markChildren(JSC::MarkStack& markStack)
+{
+ JSC::Register* registerArray = d_ptr()->registerArray.get();
+ if (!registerArray)
+ return;
+ markStack.appendValues(reinterpret_cast<JSC::JSValue*>(registerArray), d_ptr()->registerArraySize);
+}
+
+void QScriptStaticScopeObject::addSymbolTableProperty(const JSC::Identifier& name, JSC::JSValue value, unsigned attributes)
+{
+ int index = growRegisterArray(1);
+ JSC::SymbolTableEntry newEntry(index, attributes | JSC::DontDelete);
+ symbolTable().add(name.ustring().rep(), newEntry);
+ registerAt(index) = value;
+}
+
+/*!
+ Grows the register array by \a count elements, and returns the offset of
+ the newly added elements (note that the register file grows downwards,
+ starting at index -1).
+*/
+int QScriptStaticScopeObject::growRegisterArray(int count)
+{
+ size_t oldSize = d_ptr()->registerArraySize;
+ size_t newSize = oldSize + count;
+ JSC::Register* registerArray = new JSC::Register[newSize];
+ if (d_ptr()->registerArray)
+ memcpy(registerArray + count, d_ptr()->registerArray.get(), oldSize * sizeof(JSC::Register));
+ setRegisters(registerArray + newSize, registerArray);
+ d_ptr()->registerArraySize = newSize;
+ return -oldSize - 1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/script/bridge/qscriptstaticscopeobject_p.h b/src/script/bridge/qscriptstaticscopeobject_p.h
new file mode 100644
index 0000000..4b83692
--- /dev/null
+++ b/src/script/bridge/qscriptstaticscopeobject_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTSTATICSCOPEOBJECT_P_H
+#define QSCRIPTSTATICSCOPEOBJECT_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 "JSVariableObject.h"
+
+QT_BEGIN_NAMESPACE
+
+class QScriptStaticScopeObject : public JSC::JSVariableObject {
+public:
+ struct PropertyInfo {
+ PropertyInfo(const JSC::Identifier& i, JSC::JSValue v, unsigned a)
+ : identifier(i), value(v), attributes(a)
+ { }
+ PropertyInfo() {}
+
+ JSC::Identifier identifier;
+ JSC::JSValue value;
+ unsigned attributes;
+ };
+
+ QScriptStaticScopeObject(WTF::NonNullPassRefPtr<JSC::Structure> structure,
+ int propertyCount, const PropertyInfo*);
+ QScriptStaticScopeObject(WTF::NonNullPassRefPtr<JSC::Structure> structure);
+ virtual ~QScriptStaticScopeObject();
+
+ virtual bool isDynamicScope() const { return false; }
+
+ virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);
+
+ virtual void putWithAttributes(JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes);
+ virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot&);
+
+ virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName);
+
+ virtual void markChildren(JSC::MarkStack&);
+
+ virtual const JSC::ClassInfo* classInfo() const { return &info; }
+ static const JSC::ClassInfo info;
+
+ static WTF::PassRefPtr<JSC::Structure> createStructure(JSC::JSValue proto) {
+ return JSC::Structure::create(proto, JSC::TypeInfo(JSC::ObjectType, StructureFlags));
+ }
+
+protected:
+ static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::NeedsThisConversion | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | JSC::JSVariableObject::StructureFlags;
+
+ struct Data : public JSVariableObjectData {
+ Data(bool canGrow_)
+ : JSVariableObjectData(&symbolTable, /*registers=*/0),
+ canGrow(canGrow_), registerArraySize(0)
+ { }
+ bool canGrow;
+ int registerArraySize;
+ JSC::SymbolTable symbolTable;
+ };
+
+ Data* d_ptr() const { return static_cast<Data*>(JSVariableObject::d); }
+
+private:
+ void addSymbolTableProperty(const JSC::Identifier&, JSC::JSValue, unsigned attributes);
+ int growRegisterArray(int);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/bridge/qscriptvariant.cpp b/src/script/bridge/qscriptvariant.cpp
new file mode 100644
index 0000000..e083d89
--- /dev/null
+++ b/src/script/bridge/qscriptvariant.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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 "qscriptvariant_p.h"
+
+#include "../api/qscriptengine.h"
+#include "../api/qscriptengine_p.h"
+
+#include "Error.h"
+#include "PrototypeFunction.h"
+#include "JSFunction.h"
+#include "NativeFunctionWrapper.h"
+#include "JSString.h"
+
+namespace JSC
+{
+QT_USE_NAMESPACE
+ASSERT_CLASS_FITS_IN_CELL(QScript::QVariantPrototype);
+}
+
+QT_BEGIN_NAMESPACE
+
+namespace QScript
+{
+
+QVariantDelegate::QVariantDelegate(const QVariant &value)
+ : m_value(value)
+{
+}
+
+QVariantDelegate::~QVariantDelegate()
+{
+}
+
+QVariant &QVariantDelegate::value()
+{
+ return m_value;
+}
+
+void QVariantDelegate::setValue(const QVariant &value)
+{
+ m_value = value;
+}
+
+QScriptObjectDelegate::Type QVariantDelegate::type() const
+{
+ return Variant;
+}
+
+static JSC::JSValue JSC_HOST_CALL variantProtoFuncValueOf(JSC::ExecState *exec, JSC::JSObject*,
+ JSC::JSValue thisValue, const JSC::ArgList&)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ thisValue = engine->toUsableValue(thisValue);
+ if (!thisValue.inherits(&QScriptObject::info))
+ return throwError(exec, JSC::TypeError);
+ QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(thisValue))->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::Variant))
+ return throwError(exec, JSC::TypeError);
+ const QVariant &v = static_cast<QVariantDelegate*>(delegate)->value();
+ switch (v.type()) {
+ case QVariant::Invalid:
+ return JSC::jsUndefined();
+ case QVariant::String:
+ return JSC::jsString(exec, v.toString());
+
+ case QVariant::Int:
+ return JSC::jsNumber(exec, v.toInt());
+
+ case QVariant::Bool:
+ return JSC::jsBoolean(v.toBool());
+
+ case QVariant::Double:
+ return JSC::jsNumber(exec, v.toDouble());
+
+// case QVariant::Char:
+// return JSC::jsNumber(exec, v.toChar().unicode());
+
+ case QVariant::UInt:
+ return JSC::jsNumber(exec, v.toUInt());
+
+ default:
+ ;
+ }
+ return thisValue;
+}
+
+static JSC::JSValue JSC_HOST_CALL variantProtoFuncToString(JSC::ExecState *exec, JSC::JSObject *callee,
+ JSC::JSValue thisValue, const JSC::ArgList &args)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ thisValue = engine->toUsableValue(thisValue);
+ if (!thisValue.inherits(&QScriptObject::info))
+ return throwError(exec, JSC::TypeError, "This object is not a QVariant");
+ QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(thisValue))->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::Variant))
+ return throwError(exec, JSC::TypeError, "This object is not a QVariant");
+ const QVariant &v = static_cast<QVariantDelegate*>(delegate)->value();
+ JSC::UString result;
+ JSC::JSValue value = variantProtoFuncValueOf(exec, callee, thisValue, args);
+ if (value.isObject()) {
+ result = v.toString();
+ if (result.isEmpty() && !v.canConvert(QVariant::String))
+ result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(v.typeName()));
+ } else {
+ result = value.toString(exec);
+ }
+ return JSC::jsString(exec, result);
+}
+
+bool QVariantDelegate::compareToObject(QScriptObject *, JSC::ExecState *exec, JSC::JSObject *o2)
+{
+ const QVariant &variant1 = value();
+ return variant1 == QScriptEnginePrivate::toVariant(exec, o2);
+}
+
+QVariantPrototype::QVariantPrototype(JSC::ExecState* exec, WTF::PassRefPtr<JSC::Structure> structure,
+ JSC::Structure* prototypeFunctionStructure)
+ : QScriptObject(structure)
+{
+ setDelegate(new QVariantDelegate(QVariant()));
+
+ putDirectFunction(exec, new (exec) JSC::NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, variantProtoFuncToString), JSC::DontEnum);
+ putDirectFunction(exec, new (exec) JSC::NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, variantProtoFuncValueOf), JSC::DontEnum);
+}
+
+
+} // namespace QScript
+
+QT_END_NAMESPACE
diff --git a/src/script/bridge/qscriptvariant_p.h b/src/script/bridge/qscriptvariant_p.h
new file mode 100644
index 0000000..7469337
--- /dev/null
+++ b/src/script/bridge/qscriptvariant_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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-ONLY$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTVARIANT_P_H
+#define QSCRIPTVARIANT_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/qvariant.h>
+
+#include "qscriptobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QScript
+{
+
+class QVariantDelegate : public QScriptObjectDelegate
+{
+public:
+ QVariantDelegate(const QVariant &value);
+ ~QVariantDelegate();
+
+ virtual bool compareToObject(QScriptObject*, JSC::ExecState*, JSC::JSObject*);
+
+ QVariant &value();
+ void setValue(const QVariant &value);
+
+ Type type() const;
+
+private:
+ QVariant m_value;
+};
+
+class QVariantPrototype : public QScriptObject
+{
+public:
+ QVariantPrototype(JSC::ExecState*, WTF::PassRefPtr<JSC::Structure>,
+ JSC::Structure* prototypeFunctionStructure);
+};
+
+} // namespace QScript
+
+QT_END_NAMESPACE
+
+#endif