/**************************************************************************** ** ** Copyright (C) 2010 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 #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier() { new (&d) JSC::Identifier(); } QScriptDeclarativeClass::PersistentIdentifier::~PersistentIdentifier() { ((JSC::Identifier &)d).JSC::Identifier::~Identifier(); } QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier(const PersistentIdentifier &other) { identifier = other.identifier; new (&d) JSC::Identifier((JSC::Identifier &)(other.d)); } QScriptDeclarativeClass::PersistentIdentifier & QScriptDeclarativeClass::PersistentIdentifier::operator=(const PersistentIdentifier &other) { identifier = other.identifier; ((JSC::Identifier &)d) = (JSC::Identifier &)(other.d); return *this; } 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(QObjectPrivate::get(engine)); JSC::ExecState* exec = p->currentFrame; QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure); result->setDelegate(new QScript::DeclarativeObjectDelegate(scriptClass, object)); return p->scriptValueFromJSCValue(result); } QScriptDeclarativeClass *QScriptDeclarativeClass::scriptClass(const QScriptValue &v) { QScriptValuePrivate *d = QScriptValuePrivate::get(v); if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info)) return 0; QScriptObject *scriptObject = static_cast(JSC::asObject(d->jscValue)); QScriptObjectDelegate *delegate = scriptObject->delegate(); if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) return 0; return static_cast(delegate)->scriptClass(); } QScriptDeclarativeClass::Object *QScriptDeclarativeClass::object(const QScriptValue &v) { QScriptValuePrivate *d = QScriptValuePrivate::get(v); if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info)) return 0; QScriptObject *scriptObject = static_cast(JSC::asObject(d->jscValue)); QScriptObjectDelegate *delegate = scriptObject->delegate(); if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) return 0; return static_cast(delegate)->object(); } QScriptValue QScriptDeclarativeClass::function(const QScriptValue &v, const Identifier &name) { QScriptValuePrivate *d = QScriptValuePrivate::get(v); if (!d->isObject()) return QScriptValue(); JSC::ExecState *exec = d->engine->currentFrame; JSC::JSObject *object = d->jscValue.getObject(); JSC::PropertySlot slot(const_cast(object)); JSC::JSValue result; JSC::Identifier id(exec, (JSC::UString::Rep *)name); if (const_cast(object)->getOwnPropertySlot(exec, id, slot)) { result = slot.getValue(exec, id); if (QScript::isFunction(result)) return d->engine->scriptValueFromJSCValue(result); } return QScriptValue(); } QScriptValue QScriptDeclarativeClass::property(const QScriptValue &v, const Identifier &name) { QScriptValuePrivate *d = QScriptValuePrivate::get(v); if (!d->isObject()) return QScriptValue(); JSC::ExecState *exec = d->engine->currentFrame; JSC::JSObject *object = d->jscValue.getObject(); JSC::PropertySlot slot(const_cast(object)); JSC::JSValue result; JSC::Identifier id(exec, (JSC::UString::Rep *)name); if (const_cast(object)->getOwnPropertySlot(exec, id, slot)) { result = slot.getValue(exec, id); return d->engine->scriptValueFromJSCValue(result); } return QScriptValue(); } /* 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); 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(object)->delegate() != 0)) { // Return the object that property access is being delegated to object = static_cast(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); 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; } QScriptDeclarativeClass::PersistentIdentifier QScriptDeclarativeClass::createPersistentIdentifier(const QString &str) { QScriptEnginePrivate *p = static_cast(QObjectPrivate::get(d_ptr->engine)); JSC::ExecState* exec = p->currentFrame; PersistentIdentifier rv(true); new (&rv.d) JSC::Identifier(exec, (UChar *)str.constData(), str.size()); rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep(); return rv; } QScriptDeclarativeClass::PersistentIdentifier QScriptDeclarativeClass::createPersistentIdentifier(const Identifier &id) { QScriptEnginePrivate *p = static_cast(QObjectPrivate::get(d_ptr->engine)); JSC::ExecState* exec = p->currentFrame; PersistentIdentifier rv(true); new (&rv.d) JSC::Identifier(exec, (JSC::UString::Rep *)id); rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep(); return rv; } QString QScriptDeclarativeClass::toString(const Identifier &identifier) { JSC::UString::Rep *r = (JSC::UString::Rep *)identifier; return QString((QChar *)r->data(), r->size()); } 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; } QScriptValue QScriptDeclarativeClass::property(Object *object, const Identifier &name) { Q_UNUSED(object); Q_UNUSED(name); return QScriptValue(); } void QScriptDeclarativeClass::setProperty(Object *object, const Identifier &name, const QScriptValue &value) { Q_UNUSED(object); Q_UNUSED(name); Q_UNUSED(value); } QScriptValue::PropertyFlags QScriptDeclarativeClass::propertyFlags(Object *object, const Identifier &name) { Q_UNUSED(object); Q_UNUSED(name); return 0; } QStringList QScriptDeclarativeClass::propertyNames(Object *object) { Q_UNUSED(object); return QStringList(); } 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; } QT_END_NAMESPACE