74151bddae2793019a07fa63eed421965ec6c214
[profile/ivi/qtdeclarative.git] / src / declarative / qml / v8 / qscriptoriginalglobalobject_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the QtScript module of the Qt Toolkit.
8 **
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.
17 **
18 ** If you have questions regarding the use of this file, please contact
19 ** us via http://www.qt-project.org/.
20 ** $QT_END_LICENSE$
21 **
22 ****************************************************************************/
23
24 #ifndef QSCRIPTORIGINALGLOBALOBJECT_P_H
25 #define QSCRIPTORIGINALGLOBALOBJECT_P_H
26
27 #include "QtCore/qglobal.h"
28 #include "qjsvalue.h"
29
30 #include <private/qv8_p.h>
31
32 QT_BEGIN_NAMESPACE
33
34 class QV8Engine;
35
36 /*!
37     \internal
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
40     changed.
41
42     FIXME this class is a container for workarounds :-) it should be replaced by proper API calls.
43
44     The class have to be created on the QV8Engine creation time (before any change got applied to
45     global object).
46
47     \attention All methods (apart from constructor) assumes that a context and a scope are prepared correctly.
48 */
49 class QScriptOriginalGlobalObject
50 {
51 public:
52     inline QScriptOriginalGlobalObject() {}
53     inline void init(v8::Handle<v8::Context> context);
54     inline void destroy();
55
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);
59 private:
60     Q_DISABLE_COPY(QScriptOriginalGlobalObject)
61
62     // Copy of constructors and prototypes used in isType functions.
63     v8::Persistent<v8::Function> m_ownPropertyDescriptor;
64     v8::Persistent<v8::Object> m_globalObject;
65 };
66
67 void QScriptOriginalGlobalObject::init(v8::Handle<v8::Context> context)
68 {
69     // Please notice that engine is not fully initialized at this point.
70
71     v8::Context::Scope contextScope(context);
72
73     v8::HandleScope scope;
74
75     m_globalObject = v8::Persistent<v8::Object>::New(context->Global());
76
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));
83     }
84 }
85
86 /*!
87     \internal
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.
91 */
92 inline void QScriptOriginalGlobalObject::destroy()
93 {
94     m_ownPropertyDescriptor.Dispose();
95     m_globalObject.Dispose();
96     // After this line this instance is unusable.
97 }
98
99 inline QJSValue::PropertyFlags QScriptOriginalGlobalObject::getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property)
100 {
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))
107 //            return 0;
108         v8::Local<v8::Value> prototype = object->GetPrototype();
109         if (prototype->IsNull())
110             return 0;
111         return getPropertyFlags(v8::Local<v8::Object>::Cast(prototype), property);
112     }
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");
118
119     unsigned flags = 0;
120
121     if (!descriptor->Get(configurableName)->BooleanValue())
122         flags |= QJSValue::Undeletable;
123     if (!descriptor->Get(enumerableName)->BooleanValue())
124         flags |= QJSValue::SkipInEnumeration;
125
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;
130     } else {
131 //        if (descriptor->Get(getName)->IsObject())
132 //            flags |= QScriptValue::PropertyGetter;
133 //        if (descriptor->Get(setName)->IsObject())
134 //            flags |= QScriptValue::PropertySetter;
135     }
136
137     return QJSValue::PropertyFlag(flags);
138 }
139
140 inline v8::Local<v8::Object> QScriptOriginalGlobalObject::getOwnPropertyDescriptor(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property) const
141 {
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);
150 }
151
152 inline bool QScriptOriginalGlobalObject::strictlyEquals(v8::Handle<v8::Object> object)
153 {
154     return m_globalObject->GetPrototype()->StrictEquals(object);
155 }
156
157 QT_END_NAMESPACE
158
159 #endif