1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qv8contextwrapper_p.h"
43 #include "qv8engine_p.h"
45 #include <private/qdeclarativeengine_p.h>
46 #include <private/qdeclarativecontext_p.h>
48 #include <private/qjsvalue_p.h>
49 #include <private/qscript_impl_p.h>
53 class QV8TypeResource : public QV8ObjectResource
55 V8_RESOURCE_TYPE(TypeType);
58 QV8TypeResource(QV8Engine *engine);
59 virtual ~QV8TypeResource();
61 QV8TypeWrapper::TypeNameMode mode;
63 QDeclarativeGuard<QObject> object;
65 QDeclarativeType *type;
66 QDeclarativeTypeNameCache *typeNamespace;
67 const void *importNamespace;
70 QV8TypeResource::QV8TypeResource(QV8Engine *engine)
71 : QV8ObjectResource(engine), mode(QV8TypeWrapper::IncludeEnums), type(0), typeNamespace(0), importNamespace(0)
75 QV8TypeResource::~QV8TypeResource()
77 if (typeNamespace) typeNamespace->release();
80 QV8TypeWrapper::QV8TypeWrapper()
85 QV8TypeWrapper::~QV8TypeWrapper()
89 void QV8TypeWrapper::destroy()
91 qPersistentDispose(m_constructor);
94 void QV8TypeWrapper::init(QV8Engine *engine)
97 v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
98 ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter);
99 ft->InstanceTemplate()->SetHasExternalResource(true);
100 m_constructor = qPersistentNew<v8::Function>(ft->GetFunction());
103 // Returns a type wrapper for type t on o. This allows access of enums, and attached properties.
104 v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t, TypeNameMode mode)
107 // XXX NewInstance() should be optimized
108 v8::Local<v8::Object> rv = m_constructor->NewInstance();
109 QV8TypeResource *r = new QV8TypeResource(m_engine);
110 r->mode = mode; r->object = o; r->type = t;
111 rv->SetExternalResource(r);
115 // Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a
117 v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeNameCache *t,
118 const void *importNamespace, TypeNameMode mode)
121 Q_ASSERT(importNamespace);
122 // XXX NewInstance() should be optimized
123 v8::Local<v8::Object> rv = m_constructor->NewInstance();
124 QV8TypeResource *r = new QV8TypeResource(m_engine);
126 r->mode = mode; r->object = o; r->typeNamespace = t; r->importNamespace = importNamespace;
127 rv->SetExternalResource(r);
131 v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property,
132 const v8::AccessorInfo &info)
134 v8::Object::ExternalResource *r = info.This()->GetExternalResource();
135 QV8TypeResource *resource = v8_resource_cast<QV8TypeResource>(info.This());
138 return v8::Undefined();
140 QV8Engine *v8engine = resource->engine;
141 QObject *object = resource->object;
143 QHashedV8String propertystring(property);
145 if (resource->type) {
146 QDeclarativeType *type = resource->type;
148 if (QV8Engine::startsWithUpper(property)) {
149 int value = type->enumValue(propertystring);
151 return v8::Integer::New(value);
153 // Fall through to return empty handle
155 } else if (resource->object) {
156 QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
158 return v8engine->qobjectWrapper()->getProperty(ao, propertystring,
159 QV8QObjectWrapper::IgnoreRevision);
161 // Fall through to return empty handle
164 // Fall through to return empty handle
166 } else if (resource->typeNamespace) {
167 Q_ASSERT(resource->importNamespace);
168 QDeclarativeTypeNameCache::Result r = resource->typeNamespace->query(propertystring,
169 resource->importNamespace);
174 return v8engine->typeWrapper()->newObject(object, r.type, resource->mode);
175 } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi(resource->importNamespace)) {
177 if (moduleApi->scriptCallback) {
178 moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine());
179 moduleApi->scriptCallback = 0;
180 moduleApi->qobjectCallback = 0;
181 } else if (moduleApi->qobjectCallback) {
182 moduleApi->qobjectApi = moduleApi->qobjectCallback(v8engine->engine(), v8engine->engine());
183 moduleApi->scriptCallback = 0;
184 moduleApi->qobjectCallback = 0;
187 if (moduleApi->qobjectApi) {
188 v8::Handle<v8::Value> rv = v8engine->qobjectWrapper()->getProperty(moduleApi->qobjectApi, propertystring, QV8QObjectWrapper::IgnoreRevision);
190 } else if (moduleApi->scriptApi.isValid()) {
191 // NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable.
192 QJSValuePrivate *apiprivate = QJSValuePrivate::get(moduleApi->scriptApi);
193 QScopedPointer<QJSValuePrivate> propertyValue(apiprivate->property(property).give());
194 return propertyValue->asV8Value(v8engine);
196 return v8::Handle<v8::Value>();
200 // Fall through to return empty handle
203 Q_ASSERT(!"Unreachable");
206 return v8::Handle<v8::Value>();
209 v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property,
210 v8::Local<v8::Value> value,
211 const v8::AccessorInfo &info)
213 v8::Object::ExternalResource *r = info.This()->GetExternalResource();
214 QV8TypeResource *resource = v8_resource_cast<QV8TypeResource>(info.This());
219 QV8Engine *v8engine = resource->engine;
221 QHashedV8String propertystring(property);
223 if (resource->type && resource->object) {
224 QDeclarativeType *type = resource->type;
225 QObject *object = resource->object;
226 QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
228 v8engine->qobjectWrapper()->setProperty(ao, propertystring, value,
229 QV8QObjectWrapper::IgnoreRevision);
230 } else if (resource->typeNamespace) {
231 if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi(resource->importNamespace)) {
232 if (moduleApi->scriptCallback) {
233 moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine());
234 moduleApi->scriptCallback = 0;
235 moduleApi->qobjectCallback = 0;
236 } else if (moduleApi->qobjectCallback) {
237 moduleApi->qobjectApi = moduleApi->qobjectCallback(v8engine->engine(), v8engine->engine());
238 moduleApi->scriptCallback = 0;
239 moduleApi->qobjectCallback = 0;
242 if (moduleApi->qobjectApi) {
243 v8engine->qobjectWrapper()->setProperty(moduleApi->qobjectApi, propertystring, value,
244 QV8QObjectWrapper::IgnoreRevision);
245 } else if (moduleApi->scriptApi.isValid()) {
246 QScopedPointer<QJSValuePrivate> setvalp(new QJSValuePrivate(v8engine, value));
247 QJSValuePrivate *apiprivate = QJSValuePrivate::get(moduleApi->scriptApi);
248 if (apiprivate->propertyFlags(property) & QJSValue::ReadOnly) {
249 QString error = QLatin1String("Cannot assign to read-only property \"") +
250 v8engine->toString(property) + QLatin1Char('\"');
251 v8::ThrowException(v8::Exception::Error(v8engine->toString(error)));
253 apiprivate->setProperty(property, setvalp.data());