qscriptoriginalglobalobject_p.h [plain text]
#ifndef qscriptoriginalglobalobject_p_h
#define qscriptoriginalglobalobject_p_h
#include <JavaScriptCore/JavaScript.h>
#include <JavaScriptCore/JSRetainPtr.h>
#include <QtCore/qvector.h>
class QScriptOriginalGlobalObject {
public:
inline QScriptOriginalGlobalObject(JSGlobalContextRef context);
inline ~QScriptOriginalGlobalObject();
inline bool objectHasOwnProperty(JSObjectRef object, JSStringRef property) const;
inline QVector<JSStringRef> objectGetOwnPropertyNames(JSObjectRef object) const;
inline bool isDate(JSValueRef value) const;
inline bool isArray(JSValueRef value) const;
inline bool isError(JSValueRef value) const;
inline JSValueRef functionPrototype() const;
private:
inline bool isType(JSValueRef value, JSObjectRef constructor, JSValueRef prototype) const;
inline void initializeMember(JSObjectRef globalObject, JSStringRef prototypeName, const char* type, JSObjectRef& constructor, JSValueRef& prototype);
JSGlobalContextRef m_context;
JSObjectRef m_arrayConstructor;
JSValueRef m_arrayPrototype;
JSObjectRef m_errorConstructor;
JSValueRef m_errorPrototype;
JSObjectRef m_functionConstructor;
JSValueRef m_functionPrototype;
JSObjectRef m_dateConstructor;
JSValueRef m_datePrototype;
JSObjectRef m_hasOwnPropertyFunction;
JSObjectRef m_getOwnPropertyNamesFunction;
};
QScriptOriginalGlobalObject::QScriptOriginalGlobalObject(JSGlobalContextRef context)
: m_context(JSGlobalContextRetain(context))
{
JSObjectRef globalObject = JSContextGetGlobalObject(m_context);
JSValueRef exception = 0;
JSRetainPtr<JSStringRef> propertyName;
propertyName.adopt(JSStringCreateWithUTF8CString("prototype"));
initializeMember(globalObject, propertyName.get(), "Array", m_arrayConstructor, m_arrayPrototype);
initializeMember(globalObject, propertyName.get(), "Error", m_errorConstructor, m_errorPrototype);
initializeMember(globalObject, propertyName.get(), "Function", m_functionConstructor, m_functionPrototype);
initializeMember(globalObject, propertyName.get(), "Date", m_dateConstructor, m_datePrototype);
propertyName.adopt(JSStringCreateWithUTF8CString("hasOwnProperty"));
m_hasOwnPropertyFunction = const_cast<JSObjectRef>(JSObjectGetProperty(m_context, globalObject, propertyName.get(), &exception));
JSValueProtect(m_context, m_hasOwnPropertyFunction);
Q_ASSERT(JSValueIsObject(m_context, m_hasOwnPropertyFunction));
Q_ASSERT(JSObjectIsFunction(m_context, m_hasOwnPropertyFunction));
Q_ASSERT(!exception);
propertyName.adopt(JSStringCreateWithUTF8CString("Object"));
JSObjectRef objectConstructor
= const_cast<JSObjectRef>(JSObjectGetProperty(m_context, globalObject, propertyName.get(), &exception));
propertyName.adopt(JSStringCreateWithUTF8CString("getOwnPropertyNames"));
m_getOwnPropertyNamesFunction
= const_cast<JSObjectRef>(JSObjectGetProperty(m_context, objectConstructor, propertyName.get(), &exception));
JSValueProtect(m_context, m_getOwnPropertyNamesFunction);
Q_ASSERT(JSValueIsObject(m_context, m_getOwnPropertyNamesFunction));
Q_ASSERT(JSObjectIsFunction(m_context, m_getOwnPropertyNamesFunction));
Q_ASSERT(!exception);
}
inline void QScriptOriginalGlobalObject::initializeMember(JSObjectRef globalObject, JSStringRef prototypeName, const char* type, JSObjectRef& constructor, JSValueRef& prototype)
{
JSRetainPtr<JSStringRef> typeName(Adopt, JSStringCreateWithUTF8CString(type));
JSValueRef exception = 0;
JSValueRef typeConstructor = JSObjectGetProperty(m_context, globalObject, typeName.get(), &exception);
Q_ASSERT(JSValueIsObject(m_context, typeConstructor));
constructor = JSValueToObject(m_context, typeConstructor, &exception);
JSValueProtect(m_context, constructor);
prototype = JSObjectGetProperty(m_context, constructor, prototypeName, &exception);
Q_ASSERT(JSValueIsObject(m_context, prototype));
JSValueProtect(m_context, prototype);
Q_ASSERT(!exception);
}
QScriptOriginalGlobalObject::~QScriptOriginalGlobalObject()
{
JSValueUnprotect(m_context, m_arrayConstructor);
JSValueUnprotect(m_context, m_arrayPrototype);
JSValueUnprotect(m_context, m_errorConstructor);
JSValueUnprotect(m_context, m_errorPrototype);
JSValueUnprotect(m_context, m_functionConstructor);
JSValueUnprotect(m_context, m_functionPrototype);
JSValueUnprotect(m_context, m_dateConstructor);
JSValueUnprotect(m_context, m_datePrototype);
JSValueUnprotect(m_context, m_hasOwnPropertyFunction);
JSValueUnprotect(m_context, m_getOwnPropertyNamesFunction);
JSGlobalContextRelease(m_context);
}
inline bool QScriptOriginalGlobalObject::objectHasOwnProperty(JSObjectRef object, JSStringRef property) const
{
JSValueRef exception = 0;
JSValueRef propertyName[] = { JSValueMakeString(m_context, property) };
JSValueRef result = JSObjectCallAsFunction(m_context, m_hasOwnPropertyFunction, object, 1, propertyName, &exception);
return exception ? false : JSValueToBoolean(m_context, result);
}
inline QVector<JSStringRef> QScriptOriginalGlobalObject::objectGetOwnPropertyNames(JSObjectRef object) const
{
JSValueRef exception = 0;
JSObjectRef propertyNames
= const_cast<JSObjectRef>(JSObjectCallAsFunction(m_context,
m_getOwnPropertyNamesFunction,
0,
1,
&object,
&exception));
Q_ASSERT(JSValueIsObject(m_context, propertyNames));
Q_ASSERT(!exception);
JSStringRef lengthName = QScriptConverter::toString("length");
int count = JSValueToNumber(m_context, JSObjectGetProperty(m_context, propertyNames, lengthName, &exception), &exception);
Q_ASSERT(!exception);
QVector<JSStringRef> names;
names.reserve(count);
for (int i = 0; i < count; ++i) {
JSValueRef tmp = JSObjectGetPropertyAtIndex(m_context, propertyNames, i, &exception);
names.append(JSValueToStringCopy(m_context, tmp, &exception));
Q_ASSERT(!exception);
}
return names;
}
inline bool QScriptOriginalGlobalObject::isDate(JSValueRef value) const
{
return isType(value, m_dateConstructor, m_datePrototype);
}
inline bool QScriptOriginalGlobalObject::isArray(JSValueRef value) const
{
return isType(value, m_arrayConstructor, m_arrayPrototype);
}
inline bool QScriptOriginalGlobalObject::isError(JSValueRef value) const
{
return isType(value, m_errorConstructor, m_errorPrototype);
}
inline JSValueRef QScriptOriginalGlobalObject::functionPrototype() const
{
return m_functionPrototype;
}
inline bool QScriptOriginalGlobalObject::isType(JSValueRef value, JSObjectRef constructor, JSValueRef prototype) const
{
JSValueRef exception = 0;
bool result = JSValueIsInstanceOfConstructor(m_context, value, constructor, &exception) || JSValueIsStrictEqual(m_context, value, prototype);
Q_ASSERT(!exception);
return result;
}
#endif // qscriptoriginalglobalobject_p_h