2 Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
20 #ifndef qscriptoriginalglobalobject_p_h
21 #define qscriptoriginalglobalobject_p_h
23 #include <JavaScriptCore/JavaScript.h>
24 #include <JavaScriptCore/JSRetainPtr.h>
25 #include <QtCore/qvector.h>
29 This class is a workaround for missing JSC C API functionality. This class keeps all important
30 properties of an original (default) global object, so we can use it even if the global object was
33 FIXME this class is a container for workarounds :-) it should be replaced by proper JSC C API calls.
35 The class have to be created on the QScriptEnginePrivate creation time (before any change got applied to
38 class QScriptOriginalGlobalObject
{
40 inline QScriptOriginalGlobalObject(JSGlobalContextRef context
);
41 inline ~QScriptOriginalGlobalObject();
43 inline bool objectHasOwnProperty(JSObjectRef object
, JSStringRef property
) const;
44 inline QVector
<JSStringRef
> objectGetOwnPropertyNames(JSObjectRef object
) const;
46 inline bool isDate(JSValueRef value
) const;
47 inline bool isArray(JSValueRef value
) const;
48 inline bool isError(JSValueRef value
) const;
50 inline JSValueRef
functionPrototype() const;
52 inline bool isType(JSValueRef value
, JSObjectRef constructor
, JSValueRef prototype
) const;
53 inline void initializeMember(JSObjectRef globalObject
, JSStringRef prototypeName
, const char* type
, JSObjectRef
& constructor
, JSValueRef
& prototype
);
55 // Copy of the global context reference (the same as in QScriptEnginePrivate).
56 JSGlobalContextRef m_context
;
58 // Copy of constructors and prototypes used in isType functions.
59 JSObjectRef m_arrayConstructor
;
60 JSValueRef m_arrayPrototype
;
61 JSObjectRef m_errorConstructor
;
62 JSValueRef m_errorPrototype
;
63 JSObjectRef m_functionConstructor
;
64 JSValueRef m_functionPrototype
;
65 JSObjectRef m_dateConstructor
;
66 JSValueRef m_datePrototype
;
68 // Reference to standard JS functions that are not exposed by JSC C API.
69 JSObjectRef m_hasOwnPropertyFunction
;
70 JSObjectRef m_getOwnPropertyNamesFunction
;
73 QScriptOriginalGlobalObject::QScriptOriginalGlobalObject(JSGlobalContextRef context
)
74 : m_context(JSGlobalContextRetain(context
))
76 JSObjectRef globalObject
= JSContextGetGlobalObject(m_context
);
77 JSValueRef exception
= 0;
78 JSRetainPtr
<JSStringRef
> propertyName
;
80 propertyName
.adopt(JSStringCreateWithUTF8CString("prototype"));
81 initializeMember(globalObject
, propertyName
.get(), "Array", m_arrayConstructor
, m_arrayPrototype
);
82 initializeMember(globalObject
, propertyName
.get(), "Error", m_errorConstructor
, m_errorPrototype
);
83 initializeMember(globalObject
, propertyName
.get(), "Function", m_functionConstructor
, m_functionPrototype
);
84 initializeMember(globalObject
, propertyName
.get(), "Date", m_dateConstructor
, m_datePrototype
);
86 propertyName
.adopt(JSStringCreateWithUTF8CString("hasOwnProperty"));
87 m_hasOwnPropertyFunction
= const_cast<JSObjectRef
>(JSObjectGetProperty(m_context
, globalObject
, propertyName
.get(), &exception
));
88 JSValueProtect(m_context
, m_hasOwnPropertyFunction
);
89 Q_ASSERT(JSValueIsObject(m_context
, m_hasOwnPropertyFunction
));
90 Q_ASSERT(JSObjectIsFunction(m_context
, m_hasOwnPropertyFunction
));
93 propertyName
.adopt(JSStringCreateWithUTF8CString("Object"));
94 JSObjectRef objectConstructor
95 = const_cast<JSObjectRef
>(JSObjectGetProperty(m_context
, globalObject
, propertyName
.get(), &exception
));
96 propertyName
.adopt(JSStringCreateWithUTF8CString("getOwnPropertyNames"));
97 m_getOwnPropertyNamesFunction
98 = const_cast<JSObjectRef
>(JSObjectGetProperty(m_context
, objectConstructor
, propertyName
.get(), &exception
));
99 JSValueProtect(m_context
, m_getOwnPropertyNamesFunction
);
100 Q_ASSERT(JSValueIsObject(m_context
, m_getOwnPropertyNamesFunction
));
101 Q_ASSERT(JSObjectIsFunction(m_context
, m_getOwnPropertyNamesFunction
));
102 Q_ASSERT(!exception
);
105 inline void QScriptOriginalGlobalObject::initializeMember(JSObjectRef globalObject
, JSStringRef prototypeName
, const char* type
, JSObjectRef
& constructor
, JSValueRef
& prototype
)
107 JSRetainPtr
<JSStringRef
> typeName(Adopt
, JSStringCreateWithUTF8CString(type
));
108 JSValueRef exception
= 0;
110 // Save references to the Type constructor and prototype.
111 JSValueRef typeConstructor
= JSObjectGetProperty(m_context
, globalObject
, typeName
.get(), &exception
);
112 Q_ASSERT(JSValueIsObject(m_context
, typeConstructor
));
113 constructor
= JSValueToObject(m_context
, typeConstructor
, &exception
);
114 JSValueProtect(m_context
, constructor
);
116 // Note that this is not the [[Prototype]] internal property (which we could
117 // get via JSObjectGetPrototype), but the Type.prototype, that will be set
118 // as [[Prototype]] of Type instances.
119 prototype
= JSObjectGetProperty(m_context
, constructor
, prototypeName
, &exception
);
120 Q_ASSERT(JSValueIsObject(m_context
, prototype
));
121 JSValueProtect(m_context
, prototype
);
122 Q_ASSERT(!exception
);
125 QScriptOriginalGlobalObject::~QScriptOriginalGlobalObject()
127 JSValueUnprotect(m_context
, m_arrayConstructor
);
128 JSValueUnprotect(m_context
, m_arrayPrototype
);
129 JSValueUnprotect(m_context
, m_errorConstructor
);
130 JSValueUnprotect(m_context
, m_errorPrototype
);
131 JSValueUnprotect(m_context
, m_functionConstructor
);
132 JSValueUnprotect(m_context
, m_functionPrototype
);
133 JSValueUnprotect(m_context
, m_dateConstructor
);
134 JSValueUnprotect(m_context
, m_datePrototype
);
135 JSValueUnprotect(m_context
, m_hasOwnPropertyFunction
);
136 JSValueUnprotect(m_context
, m_getOwnPropertyNamesFunction
);
137 JSGlobalContextRelease(m_context
);
140 inline bool QScriptOriginalGlobalObject::objectHasOwnProperty(JSObjectRef object
, JSStringRef property
) const
142 // FIXME This function should be replaced by JSC C API.
143 JSValueRef exception
= 0;
144 JSValueRef propertyName
[] = { JSValueMakeString(m_context
, property
) };
145 JSValueRef result
= JSObjectCallAsFunction(m_context
, m_hasOwnPropertyFunction
, object
, 1, propertyName
, &exception
);
146 return exception
? false : JSValueToBoolean(m_context
, result
);
151 This method gives ownership of all JSStringRefs.
153 inline QVector
<JSStringRef
> QScriptOriginalGlobalObject::objectGetOwnPropertyNames(JSObjectRef object
) const
155 JSValueRef exception
= 0;
156 JSObjectRef propertyNames
157 = const_cast<JSObjectRef
>(JSObjectCallAsFunction(m_context
,
158 m_getOwnPropertyNamesFunction
,
160 /* argumentCount */ 1,
163 Q_ASSERT(JSValueIsObject(m_context
, propertyNames
));
164 Q_ASSERT(!exception
);
165 JSStringRef lengthName
= QScriptConverter::toString("length");
166 int count
= JSValueToNumber(m_context
, JSObjectGetProperty(m_context
, propertyNames
, lengthName
, &exception
), &exception
);
168 Q_ASSERT(!exception
);
169 QVector
<JSStringRef
> names
;
170 names
.reserve(count
);
171 for (int i
= 0; i
< count
; ++i
) {
172 JSValueRef tmp
= JSObjectGetPropertyAtIndex(m_context
, propertyNames
, i
, &exception
);
173 names
.append(JSValueToStringCopy(m_context
, tmp
, &exception
));
174 Q_ASSERT(!exception
);
179 inline bool QScriptOriginalGlobalObject::isDate(JSValueRef value
) const
181 return isType(value
, m_dateConstructor
, m_datePrototype
);
184 inline bool QScriptOriginalGlobalObject::isArray(JSValueRef value
) const
186 return isType(value
, m_arrayConstructor
, m_arrayPrototype
);
189 inline bool QScriptOriginalGlobalObject::isError(JSValueRef value
) const
191 return isType(value
, m_errorConstructor
, m_errorPrototype
);
194 inline JSValueRef
QScriptOriginalGlobalObject::functionPrototype() const
196 return m_functionPrototype
;
199 inline bool QScriptOriginalGlobalObject::isType(JSValueRef value
, JSObjectRef constructor
, JSValueRef prototype
) const
201 // JSC API doesn't export the [[Class]] information for the builtins. But we know that a value
202 // is an object of the Type if it was created with the Type constructor or if it is the Type.prototype.
203 JSValueRef exception
= 0;
204 bool result
= JSValueIsInstanceOfConstructor(m_context
, value
, constructor
, &exception
) || JSValueIsStrictEqual(m_context
, value
, prototype
);
205 Q_ASSERT(!exception
);
209 #endif // qscriptoriginalglobalobject_p_h