/**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtScript 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$ ** ****************************************************************************/ #ifndef QSCRIPTV8OBJECTWRAPPER_P_H #define QSCRIPTV8OBJECTWRAPPER_P_H #include "qscriptvalue.h" #include "qscriptvalue_p.h" #include "qscriptengine_p.h" #include "qscriptcontext_p.h" #include QT_BEGIN_NAMESPACE namespace QScriptV8ObjectWrapperHelper { template void weakCallback(v8::Persistent object, void *parameter) { Q_ASSERT(object.IsNearDeath()); T *data = reinterpret_cast(parameter); delete data; object.Dispose(); } template T *getDataPointer(v8::Handle self) { Q_ASSERT(!self.IsEmpty()); Q_ASSERT(self->InternalFieldCount() >= 1); T *data = reinterpret_cast(self->GetPointerFromInternalField(0)); Q_ASSERT(data != 0); return data; } template T *getDataPointer(const v8::AccessorInfo &info) { return getDataPointer(info.Holder()); } template T *getDataPointer(const v8::Arguments& args) { return getDataPointer(args.Holder()); } #ifdef QTSCRIPT_V8OBJECT_DATA_CALLBACK # error QTSCRIPT_V8OBJECT_DATA_CALLBACK name is in use #else #define QTSCRIPT_V8OBJECT_DATA_CALLBACK(arg, callback) \ v8::HandleScope handleScope; \ T *data = getDataPointer(arg); \ QScriptContextPrivate qScriptContext(data->engine, &arg); \ return handleScope.Close(callback); #endif template static v8::Handle namedPropertyGetter(v8::Local property, const v8::AccessorInfo &info) { QTSCRIPT_V8OBJECT_DATA_CALLBACK(info, data->property(property)); } template static v8::Handle indexedPropertyGetter(uint32_t index, const v8::AccessorInfo &info) { QTSCRIPT_V8OBJECT_DATA_CALLBACK(info, data->property(index)); } template static v8::Handle namedPropertyQuery(v8::Local property, const v8::AccessorInfo &info) { QTSCRIPT_V8OBJECT_DATA_CALLBACK(info, data->propertyFlags(property)); } template static v8::Handle indexedPropertyQuery(uint32_t index, const v8::AccessorInfo &info) { QTSCRIPT_V8OBJECT_DATA_CALLBACK(info, data->propertyFlags(index)); } template static v8::Handle namedPropertyDeleter(v8::Local property, const v8::AccessorInfo &info) { QTSCRIPT_V8OBJECT_DATA_CALLBACK(info, data->removeProperty(property)); } template static v8::Handle indexedPropertyDeleter(uint32_t index, const v8::AccessorInfo &info) { QTSCRIPT_V8OBJECT_DATA_CALLBACK(info, data->removeProperty(index)); } template static v8::Handle namedPropertySetter(v8::Local property, v8::Local value, const v8::AccessorInfo &info) { QTSCRIPT_V8OBJECT_DATA_CALLBACK(info, data->setProperty(property, value)); } template static v8::Handle indexedPropertySetter(uint32_t index, v8::Local value, const v8::AccessorInfo &info) { QTSCRIPT_V8OBJECT_DATA_CALLBACK(info, data->setProperty(index, value)); } template static v8::Handle namedPropertyEnumerator(const v8::AccessorInfo &info) { QTSCRIPT_V8OBJECT_DATA_CALLBACK(info, data->enumerate()); } template static v8::Handle indexedPropertyEnumerator(const v8::AccessorInfo &info) { QTSCRIPT_V8OBJECT_DATA_CALLBACK(info, data->enumerate()); } template v8::Handle callAsFunction(const v8::Arguments& args) { QTSCRIPT_V8OBJECT_DATA_CALLBACK(args, data->call()); } #undef QTSCRIPT_V8OBJECT_DATA_CALLBACK } //T must inherit from QScriptV8ObjectWrapper template QScriptEnginePrivate::*functionTemplate> struct QScriptV8ObjectWrapper { QScriptEnginePrivate *engine; static T *safeGet(const QScriptValuePrivate *p); static T *safeGet(v8::Handle object, QScriptEnginePrivate *engine); static T *get(v8::Handle object); static v8::Handle createInstance(T *data) { v8::HandleScope handleScope; Q_ASSERT(data->engine); if ((data->engine->*functionTemplate).IsEmpty()) data->engine->*functionTemplate = v8::Persistent::New(T::createFunctionTemplate(data->engine)); v8::Handle instanceTempl = (data->engine->*functionTemplate)->InstanceTemplate(); v8::Handle instance = instanceTempl->NewInstance(); Q_ASSERT(instance->InternalFieldCount() >= 1); instance->SetPointerInInternalField(0, data); v8::Persistent persistent = v8::Persistent::New(instance); persistent.MakeWeak(data, QScriptV8ObjectWrapperHelper::weakCallback); return handleScope.Close(instance); } }; template QScriptEnginePrivate::*functionTemplate> T* QScriptV8ObjectWrapper::get(v8::Handle object) { Q_ASSERT(object->InternalFieldCount() >= 1); T *data = reinterpret_cast(object->GetPointerFromInternalField(0)); return data; } template QScriptEnginePrivate::*functionTemplate> T* QScriptV8ObjectWrapper::safeGet(const QScriptValuePrivate* p) { // FIXME this algorithm should be shared with the QSEP, as it needs to distinguish between proxy // and normal objects. // If you need to modify it please update getOwnProperty and other methods checking if an object // is a script class instance. QScriptEnginePrivate *engine = p->engine(); if (!engine) return 0; v8::HandleScope handleScope; v8::Handle value = *p; v8::Handle funcTmpl = engine->*functionTemplate; if (!engine->hasInstance(funcTmpl, value)) return 0; v8::Local object = v8::Object::Cast(*value); return get(object); } template QScriptEnginePrivate::*functionTemplate> T* QScriptV8ObjectWrapper::safeGet(v8::Handle object, QScriptEnginePrivate *engine) { if (!engine || object.IsEmpty()) return 0; v8::HandleScope handleScope; v8::Handle funcTmpl = engine->*functionTemplate; if (!engine->hasInstance(funcTmpl, object)) return 0; return get(object); } QT_END_NAMESPACE #endif // QSCRIPTV8OBJECTWRAPPER_P_H