1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the QtScript module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL-ONLY$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser
12 ** General Public License version 2.1 as published by the Free Software
13 ** Foundation and appearing in the file LICENSE.LGPL included in the
14 ** packaging of this file. Please review the following information to
15 ** ensure the GNU Lesser General Public License version 2.1 requirements
16 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** If you have questions regarding the use of this file, please contact
19 ** us via http://www.qt-project.org/.
22 ****************************************************************************/
24 #ifndef QSCRIPTORIGINALGLOBALOBJECT_P_H
25 #define QSCRIPTORIGINALGLOBALOBJECT_P_H
27 #include "QtCore/qglobal.h"
30 #include <private/qv8_p.h>
38 This class is a workaround for missing V8 API functionality. This class keeps all important
39 properties of an original (default) global object, so we can use it even if the global object was
42 FIXME this class is a container for workarounds :-) it should be replaced by proper API calls.
44 The class have to be created on the QV8Engine creation time (before any change got applied to
47 \attention All methods (apart from constructor) assumes that a context and a scope are prepared correctly.
49 class QScriptOriginalGlobalObject
52 inline QScriptOriginalGlobalObject() {}
53 inline void init(v8::Handle<v8::Context> context);
54 inline void destroy();
56 inline QJSValue::PropertyFlags getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property);
57 inline v8::Local<v8::Object> getOwnPropertyDescriptor(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property) const;
58 inline bool strictlyEquals(v8::Handle<v8::Object> object);
60 Q_DISABLE_COPY(QScriptOriginalGlobalObject)
62 // Copy of constructors and prototypes used in isType functions.
63 v8::Persistent<v8::Function> m_ownPropertyDescriptor;
64 v8::Persistent<v8::Object> m_globalObject;
67 void QScriptOriginalGlobalObject::init(v8::Handle<v8::Context> context)
69 // Please notice that engine is not fully initialized at this point.
71 v8::Context::Scope contextScope(context);
73 v8::HandleScope scope;
75 m_globalObject = v8::Persistent<v8::Object>::New(context->Global());
77 v8::Local<v8::Object> objectConstructor = m_globalObject->Get(v8::String::New("Object"))->ToObject();
78 Q_ASSERT(objectConstructor->IsObject());
79 { // Initialize m_ownPropertyDescriptor.
80 v8::Local<v8::Value> ownPropertyDescriptor = objectConstructor->Get(v8::String::New("getOwnPropertyDescriptor"));
81 Q_ASSERT(!ownPropertyDescriptor.IsEmpty());
82 m_ownPropertyDescriptor = v8::Persistent<v8::Function>::New(v8::Local<v8::Function>::Cast(ownPropertyDescriptor));
88 QScriptOriginalGlobalObject lives as long as QV8Engine that keeps it. In ~QSEP
89 the v8 context is removed, so we need to remove our handlers before. to break this dependency
90 destroy method should be called before or insight QSEP destructor.
92 inline void QScriptOriginalGlobalObject::destroy()
94 m_ownPropertyDescriptor.Dispose();
95 m_globalObject.Dispose();
96 // After this line this instance is unusable.
99 inline QJSValue::PropertyFlags QScriptOriginalGlobalObject::getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property)
101 Q_ASSERT(object->IsObject());
102 Q_ASSERT(!property.IsEmpty());
103 v8::Local<v8::Object> descriptor = getOwnPropertyDescriptor(object, property);
104 if (descriptor.IsEmpty()) {
105 // // Property isn't owned by this object.
106 // if (!(mode & QScriptValue::ResolvePrototype))
108 v8::Local<v8::Value> prototype = object->GetPrototype();
109 if (prototype->IsNull())
111 return getPropertyFlags(v8::Local<v8::Object>::Cast(prototype), property);
113 v8::Local<v8::String> writableName = v8::String::New("writable");
114 v8::Local<v8::String> configurableName = v8::String::New("configurable");
115 v8::Local<v8::String> enumerableName = v8::String::New("enumerable");
116 // v8::Local<v8::String> getName = v8::String::New("get");
117 // v8::Local<v8::String> setName = v8::String::New("set");
121 if (!descriptor->Get(configurableName)->BooleanValue())
122 flags |= QJSValue::Undeletable;
123 if (!descriptor->Get(enumerableName)->BooleanValue())
124 flags |= QJSValue::SkipInEnumeration;
126 //"writable" is only a property of the descriptor if it is not an accessor
127 if (descriptor->Has(writableName)) {
128 if (!descriptor->Get(writableName)->BooleanValue())
129 flags |= QJSValue::ReadOnly;
131 // if (descriptor->Get(getName)->IsObject())
132 // flags |= QScriptValue::PropertyGetter;
133 // if (descriptor->Get(setName)->IsObject())
134 // flags |= QScriptValue::PropertySetter;
137 return QJSValue::PropertyFlag(flags);
140 inline v8::Local<v8::Object> QScriptOriginalGlobalObject::getOwnPropertyDescriptor(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property) const
142 Q_ASSERT(object->IsObject());
143 Q_ASSERT(!property.IsEmpty());
144 // FIXME do we need try catch here?
145 v8::Handle<v8::Value> argv[] = {object, property};
146 v8::Local<v8::Value> descriptor = m_ownPropertyDescriptor->Call(m_globalObject, /* argc */ 2, argv);
147 if (descriptor.IsEmpty() || !descriptor->IsObject())
148 return v8::Local<v8::Object>();
149 return v8::Local<v8::Object>::Cast(descriptor);
152 inline bool QScriptOriginalGlobalObject::strictlyEquals(v8::Handle<v8::Object> object)
154 return m_globalObject->GetPrototype()->StrictEquals(object);