diff options
-rw-r--r-- | src/script/api/qscriptengine.cpp | 19 | ||||
-rw-r--r-- | src/script/api/qscriptengine_p.h | 1 | ||||
-rw-r--r-- | src/script/bridge/qscriptqobject.cpp | 103 | ||||
-rw-r--r-- | src/script/bridge/qscriptqobject_p.h | 11 |
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; } |