summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/script/api/qscriptengine.cpp19
-rw-r--r--src/script/api/qscriptengine_p.h1
-rw-r--r--src/script/bridge/qscriptqobject.cpp103
-rw-r--r--src/script/bridge/qscriptqobject_p.h11
4 files changed, 123 insertions, 11 deletions
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index b5ba4ff..af09572 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -669,8 +669,8 @@ JSC::JSValue functionPrint(JSC::ExecState* exec, JSC::JSObject*, JSC::JSValue, c
JSC::JSValue functionGC(JSC::ExecState* exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&)
{
- JSC::JSLock lock(false);
- exec->heap()->collect();
+ QScriptEnginePrivate *engine = static_cast<GlobalObject*>(exec->lexicalGlobalObject())->engine;
+ engine->collectGarbage();
return JSC::jsUndefined();
}
@@ -1050,6 +1050,15 @@ bool QScriptEnginePrivate::isCollecting() const
return globalObject->globalData()->heap.isBusy();
}
+void QScriptEnginePrivate::collectGarbage()
+{
+ // ### why isn't the global object always marked by the Collector?
+ if (!globalObject->marked())
+ globalObject->mark();
+ JSC::JSLock lock(false);
+ globalData->heap.collect();
+}
+
#ifndef QT_NO_QOBJECT
JSC::JSValue QScriptEnginePrivate::newQObject(
@@ -3135,11 +3144,7 @@ QStringList QScriptEngine::importedExtensions() const
void QScriptEngine::collectGarbage()
{
Q_D(QScriptEngine);
- // ### why isn't the global object always marked by the Collector?
- if (!d->globalObject->marked())
- d->globalObject->mark();
- JSC::JSLock lock(false);
- d->globalData->heap.collect();
+ d->collectGarbage();
}
/*!
diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h
index 1626428..e6db40e 100644
--- a/src/script/api/qscriptengine_p.h
+++ b/src/script/api/qscriptengine_p.h
@@ -111,6 +111,7 @@ public:
void releaseContextForFrame(JSC::ExecState *frame);
bool isCollecting() const;
+ void collectGarbage();
#ifndef QT_NO_QOBJECT
JSC::JSValue newQObject(QObject *object,
diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp
index 23d61e3..e289aad 100644
--- a/src/script/bridge/qscriptqobject.cpp
+++ b/src/script/bridge/qscriptqobject.cpp
@@ -1591,12 +1591,16 @@ bool QMetaObjectWrapperObject::getOwnPropertySlot(
if (!meta)
return false;
- QByteArray name = qtStringFromJSCUString(propertyName.ustring()).toLatin1();
- if (name == "prototype") {
- qWarning("getting of metaobject.prototype not implemented");
- 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 = qtStringFromJSCUString(propertyName.ustring()).toLatin1();
+
for (int i = 0; i < meta->enumeratorCount(); ++i) {
QMetaEnum e = meta->enumerator(i);
for (int j = 0; j < e.keyCount(); ++j) {
@@ -1614,6 +1618,13 @@ bool QMetaObjectWrapperObject::getOwnPropertySlot(
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 = qtStringFromJSCUString(propertyName.ustring()).toLatin1();
@@ -1631,6 +1642,8 @@ void QMetaObjectWrapperObject::put(JSC::ExecState* exec, const JSC::Identifier&
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 = qtStringFromJSCUString(propertyName.ustring()).toLatin1();
@@ -1649,6 +1662,10 @@ bool QMetaObjectWrapperObject::getPropertyAttributes(JSC::ExecState *exec,
const JSC::Identifier &propertyName,
unsigned &attributes) const
{
+ if (propertyName == exec->propertyNames().prototype) {
+ attributes = JSC::DontDelete;
+ return true;
+ }
const QMetaObject *meta = data->value;
if (meta) {
QByteArray name = qtStringFromJSCUString(propertyName.ustring()).toLatin1();
@@ -1678,6 +1695,84 @@ void QMetaObjectWrapperObject::getPropertyNames(JSC::ExecState *exec, JSC::Prope
JSC::JSObject::getPropertyNames(exec, propertyNames);
}
+void QMetaObjectWrapperObject::mark()
+{
+ Q_ASSERT(!marked());
+ if (data->ctor && !data->ctor.marked())
+ data->ctor.mark();
+ if (data->prototype && !data->prototype.marked())
+ data->prototype.mark();
+ JSC::JSObject::mark();
+}
+
+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)
+{
+ if (!callee->isObject(&QMetaObjectWrapperObject::info))
+ return throwError(exec, JSC::TypeError, "callee is not a QMetaObject");
+ QMetaObjectWrapperObject *self = static_cast<QMetaObjectWrapperObject*>(callee);
+ QScriptEnginePrivate *eng_p = static_cast<QScript::GlobalObject*>(exec->lexicalGlobalObject())->engine;
+ JSC::ExecState *previousFrame = eng_p->currentFrame;
+ eng_p->currentFrame = exec;
+ JSC::JSValue result = self->execute(exec, args);
+ 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 = static_cast<QScript::GlobalObject*>(exec->lexicalGlobalObject())->engine;
+ JSC::ExecState *previousFrame = eng_p->currentFrame;
+ eng_p->currentFrame = exec;
+ JSC::JSValue result = self->execute(exec, args);
+ 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) {
+ JSC::CallData callData;
+ JSC::CallType callType = data->ctor.getCallData(callData);
+ return JSC::call(exec, data->ctor, callType, callData, /*thisValue=*/JSC::JSValue(), args);
+ } else {
+ if (data->value->constructorCount() > 0) {
+ Q_ASSERT_X(false, Q_FUNC_INFO, "implement me");
+#if 0
+ callQtMethod(context, QMetaMethod::Constructor, /*thisQObject=*/0,
+ value, value->constructorCount()-1, /*maybeOverloaded=*/true);
+ if (context->state() == QScriptContext::NormalState) {
+ ExtQObject::Instance *inst = ExtQObject::Instance::get(context->m_result);
+ Q_ASSERT(inst != 0);
+ inst->ownership = QScriptEngine::AutoOwnership;
+ context->m_result.setPrototype(prototype);
+ }
+#endif
+ } else {
+ QString message = QString::fromLatin1("no constructor for %0")
+ .arg(QLatin1String(data->value->className()));
+ return JSC::throwError(exec, JSC::TypeError, qtStringToJSCUString(message));
+ }
+ }
+}
+
struct StaticQtMetaObject : public QObject
{
static const QMetaObject *get()
diff --git a/src/script/bridge/qscriptqobject_p.h b/src/script/bridge/qscriptqobject_p.h
index 766c3c7..8a4edf3 100644
--- a/src/script/bridge/qscriptqobject_p.h
+++ b/src/script/bridge/qscriptqobject_p.h
@@ -243,6 +243,7 @@ public:
{
const QMetaObject *value;
JSC::JSValue ctor;
+ JSC::JSValue prototype;
Data(const QMetaObject *mo, JSC::JSValue c)
: value(mo), ctor(c) {}
@@ -263,10 +264,20 @@ public:
virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&,
unsigned&) const;
virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
+ virtual void mark();
+
+ 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; }