/**************************************************************************** ** ** Copyright (C) 2012 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$ ** 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. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qv8variantwrapper_p.h" #include "qv8variantresource_p.h" #include "qv8engine_p.h" #include QT_BEGIN_NAMESPACE QV8VariantResource::QV8VariantResource(QV8Engine *engine, const QVariant &data) : QV8ObjectResource(engine), QDeclarativeEnginePrivate::ScarceResourceData(data), m_isScarceResource(false), m_vmePropertyReferenceCount(0) { } void QV8VariantResource::addVmePropertyReference() { if (m_isScarceResource && ++m_vmePropertyReferenceCount == 1) { // remove from the ep->scarceResources list // since it is now no longer eligible to be // released automatically by the engine. node.remove(); } } void QV8VariantResource::removeVmePropertyReference() { if (m_isScarceResource && --m_vmePropertyReferenceCount == 0) { // and add to the ep->scarceResources list // since it is now eligible to be released // automatically by the engine. QDeclarativeEnginePrivate::get(engine->engine())->scarceResources.insert(this); } } QV8VariantWrapper::QV8VariantWrapper() : m_engine(0) { } QV8VariantWrapper::~QV8VariantWrapper() { } void QV8VariantWrapper::init(QV8Engine *engine) { m_engine = engine; m_toString = qPersistentNew(v8::FunctionTemplate::New(ToString)->GetFunction()); m_valueOf = qPersistentNew(v8::FunctionTemplate::New(ValueOf)->GetFunction()); { v8::Local ft = v8::FunctionTemplate::New(); ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter); ft->InstanceTemplate()->SetHasExternalResource(true); ft->InstanceTemplate()->MarkAsUseUserObjectComparison(); ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0, m_toString, v8::DEFAULT, v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); ft->InstanceTemplate()->SetAccessor(v8::String::New("valueOf"), ValueOfGetter, 0, m_valueOf, v8::DEFAULT, v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); m_constructor = qPersistentNew(ft->GetFunction()); } { m_preserve = qPersistentNew(v8::FunctionTemplate::New(Preserve)->GetFunction()); m_destroy = qPersistentNew(v8::FunctionTemplate::New(Destroy)->GetFunction()); v8::Local ft = v8::FunctionTemplate::New(); ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter); ft->InstanceTemplate()->SetHasExternalResource(true); ft->InstanceTemplate()->MarkAsUseUserObjectComparison(); ft->InstanceTemplate()->SetAccessor(v8::String::New("preserve"), PreserveGetter, 0, m_preserve, v8::DEFAULT, v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); ft->InstanceTemplate()->SetAccessor(v8::String::New("destroy"), DestroyGetter, 0, m_destroy, v8::DEFAULT, v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0, m_toString, v8::DEFAULT, v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); ft->InstanceTemplate()->SetAccessor(v8::String::New("valueOf"), ValueOfGetter, 0, m_valueOf, v8::DEFAULT, v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); m_scarceConstructor = qPersistentNew(ft->GetFunction()); } } void QV8VariantWrapper::destroy() { qPersistentDispose(m_valueOf); qPersistentDispose(m_toString); qPersistentDispose(m_destroy); qPersistentDispose(m_preserve); qPersistentDispose(m_scarceConstructor); qPersistentDispose(m_constructor); } v8::Local QV8VariantWrapper::newVariant(const QVariant &value) { bool scarceResource = value.type() == QVariant::Pixmap || value.type() == QVariant::Image; // XXX NewInstance() should be optimized v8::Local rv; QV8VariantResource *r = new QV8VariantResource(m_engine, value); if (scarceResource) { QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_engine->engine()); Q_ASSERT(ep->scarceResourcesRefCount); rv = m_scarceConstructor->NewInstance(); r->m_isScarceResource = true; ep->scarceResources.insert(r); } else { rv = m_constructor->NewInstance(); } rv->SetExternalResource(r); return rv; } bool QV8VariantWrapper::isVariant(v8::Handle value) { return value->IsObject() && v8_resource_cast(value->ToObject()); } QVariant QV8VariantWrapper::toVariant(v8::Handle obj) { QV8VariantResource *r = v8_resource_cast(obj); return r?r->data:QVariant(); } QVariant QV8VariantWrapper::toVariant(QV8ObjectResource *r) { Q_ASSERT(r->resourceType() == QV8ObjectResource::VariantType); return static_cast(r)->data; } QVariant &QV8VariantWrapper::variantValue(v8::Handle value) { Q_ASSERT(isVariant(value)); QV8VariantResource *r = v8_resource_cast(value->ToObject()); return static_cast(r)->data; } v8::Handle QV8VariantWrapper::Getter(v8::Local /* property */, const v8::AccessorInfo & /* info */) { return v8::Handle(); } v8::Handle QV8VariantWrapper::Setter(v8::Local /* property */, v8::Local value, const v8::AccessorInfo & /* info */) { return value; } v8::Handle QV8VariantWrapper::PreserveGetter(v8::Local property, const v8::AccessorInfo &info) { Q_UNUSED(property); return info.Data(); } v8::Handle QV8VariantWrapper::DestroyGetter(v8::Local property, const v8::AccessorInfo &info) { Q_UNUSED(property); return info.Data(); } v8::Handle QV8VariantWrapper::ToStringGetter(v8::Local property, const v8::AccessorInfo &info) { Q_UNUSED(property); return info.Data(); } v8::Handle QV8VariantWrapper::ValueOfGetter(v8::Local property, const v8::AccessorInfo &info) { Q_UNUSED(property); return info.Data(); } v8::Handle QV8VariantWrapper::Preserve(const v8::Arguments &args) { QV8VariantResource *resource = v8_resource_cast(args.This()); if (resource) { resource->node.remove(); } return v8::Undefined(); } v8::Handle QV8VariantWrapper::Destroy(const v8::Arguments &args) { QV8VariantResource *resource = v8_resource_cast(args.This()); if (resource) { resource->data = QVariant(); resource->node.remove(); } return v8::Undefined(); } v8::Handle QV8VariantWrapper::ToString(const v8::Arguments &args) { QV8VariantResource *resource = v8_resource_cast(args.This()); if (resource) { QString result = resource->data.toString(); if (result.isEmpty() && !resource->data.canConvert(QVariant::String)) result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(resource->data.typeName())); return resource->engine->toString(result); } else { return v8::Undefined(); } } v8::Handle QV8VariantWrapper::ValueOf(const v8::Arguments &args) { QV8VariantResource *resource = v8_resource_cast(args.This()); if (resource) { QVariant v = resource->data; switch (v.type()) { case QVariant::Invalid: return v8::Undefined(); case QVariant::String: return resource->engine->toString(v.toString()); case QVariant::Int: case QVariant::Double: case QVariant::UInt: return v8::Number::New(v.toDouble()); case QVariant::Bool: return v8::Boolean::New(v.toBool()); default: break; } } return args.This(); } QT_END_NAMESPACE