summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/qt/api
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/qt/api')
-rw-r--r--JavaScriptCore/qt/api/qscriptconverter_p.h14
-rw-r--r--JavaScriptCore/qt/api/qscriptengine_p.cpp21
-rw-r--r--JavaScriptCore/qt/api/qscriptengine_p.h12
-rw-r--r--JavaScriptCore/qt/api/qscriptstring_p.h12
-rw-r--r--JavaScriptCore/qt/api/qscriptvalue.cpp112
-rw-r--r--JavaScriptCore/qt/api/qscriptvalue.h30
-rw-r--r--JavaScriptCore/qt/api/qscriptvalue_p.h282
7 files changed, 467 insertions, 16 deletions
diff --git a/JavaScriptCore/qt/api/qscriptconverter_p.h b/JavaScriptCore/qt/api/qscriptconverter_p.h
index cd86e20..0c57d95 100644
--- a/JavaScriptCore/qt/api/qscriptconverter_p.h
+++ b/JavaScriptCore/qt/api/qscriptconverter_p.h
@@ -20,7 +20,9 @@
#ifndef qscriptconverter_p_h
#define qscriptconverter_p_h
+#include "qscriptvalue.h"
#include <JavaScriptCore/JavaScript.h>
+#include <QtCore/qglobal.h>
#include <QtCore/qnumeric.h>
#include <QtCore/qstring.h>
#include <QtCore/qvarlengtharray.h>
@@ -127,6 +129,18 @@ public:
buf.append(0);
return QString::fromLatin1(buf.constData());
}
+
+ static JSPropertyAttributes toPropertyFlags(const QFlags<QScriptValue::PropertyFlag>& flags)
+ {
+ JSPropertyAttributes attr = 0;
+ if (flags.testFlag(QScriptValue::ReadOnly))
+ attr |= kJSPropertyAttributeReadOnly;
+ if (flags.testFlag(QScriptValue::Undeletable))
+ attr |= kJSPropertyAttributeDontDelete;
+ if (flags.testFlag(QScriptValue::SkipInEnumeration))
+ attr |= kJSPropertyAttributeDontEnum;
+ return attr;
+ }
};
#endif // qscriptconverter_p_h
diff --git a/JavaScriptCore/qt/api/qscriptengine_p.cpp b/JavaScriptCore/qt/api/qscriptengine_p.cpp
index 23e41c4..360de29 100644
--- a/JavaScriptCore/qt/api/qscriptengine_p.cpp
+++ b/JavaScriptCore/qt/api/qscriptengine_p.cpp
@@ -32,11 +32,32 @@ QScriptEnginePrivate::QScriptEnginePrivate(const QScriptEngine* engine)
: q_ptr(const_cast<QScriptEngine*>(engine))
, m_context(JSGlobalContextCreate(0))
, m_exception(0)
+ , m_arrayConstructor(0)
+ , m_arrayPrototype(0)
{
+ JSObjectRef globalObject = JSContextGetGlobalObject(m_context);
+
+ // Save references to the Array constructor and prototype.
+ JSRetainPtr<JSStringRef> arrayName(Adopt, JSStringCreateWithUTF8CString("Array"));
+ JSValueRef arrayConstructor = JSObjectGetProperty(m_context, globalObject, arrayName.get(), /* exception */ 0);
+ Q_ASSERT(JSValueIsObject(m_context, arrayConstructor));
+ m_arrayConstructor = JSValueToObject(m_context, arrayConstructor, /* exception */ 0);
+ JSValueProtect(m_context, m_arrayConstructor);
+
+ // Note that this is not the [[Prototype]] internal property (which we could
+ // get via JSObjectGetPrototype), but the Array.prototype, that will be set
+ // as [[Prototype]] of Array instances.
+ JSRetainPtr<JSStringRef> prototypeName(Adopt, JSStringCreateWithUTF8CString("prototype"));
+ JSValueRef arrayPrototype = JSObjectGetProperty(m_context, m_arrayConstructor, prototypeName.get(), /* exception */ 0);
+ Q_ASSERT(JSValueIsObject(m_context, arrayPrototype));
+ m_arrayPrototype = arrayPrototype;
+ JSValueProtect(m_context, m_arrayPrototype);
}
QScriptEnginePrivate::~QScriptEnginePrivate()
{
+ JSValueUnprotect(m_context, m_arrayConstructor);
+ JSValueUnprotect(m_context, m_arrayPrototype);
if (m_exception)
JSValueUnprotect(m_context, m_exception);
JSGlobalContextRelease(m_context);
diff --git a/JavaScriptCore/qt/api/qscriptengine_p.h b/JavaScriptCore/qt/api/qscriptengine_p.h
index 30ee039..401c051 100644
--- a/JavaScriptCore/qt/api/qscriptengine_p.h
+++ b/JavaScriptCore/qt/api/qscriptengine_p.h
@@ -77,10 +77,15 @@ public:
inline QScriptStringPrivate* toStringHandle(const QString& str) const;
inline operator JSGlobalContextRef() const;
+
+ inline bool isArray(JSValueRef value) const;
private:
QScriptEngine* q_ptr;
JSGlobalContextRef m_context;
JSValueRef m_exception;
+
+ JSObjectRef m_arrayConstructor;
+ JSValueRef m_arrayPrototype;
};
@@ -211,4 +216,11 @@ QScriptEnginePrivate::operator JSGlobalContextRef() const
return m_context;
}
+bool QScriptEnginePrivate::isArray(JSValueRef value) const
+{
+ // JSC API doesn't export the [[Class]] information for the builtins. But we know that a value
+ // is an array if it was created with the Array constructor or if it is the Array.prototype.
+ return JSValueIsInstanceOfConstructor(m_context, value, m_arrayConstructor, /* exception */ 0) || JSValueIsStrictEqual(m_context, value, m_arrayPrototype);
+}
+
#endif
diff --git a/JavaScriptCore/qt/api/qscriptstring_p.h b/JavaScriptCore/qt/api/qscriptstring_p.h
index d4fc88e..fe84f4d 100644
--- a/JavaScriptCore/qt/api/qscriptstring_p.h
+++ b/JavaScriptCore/qt/api/qscriptstring_p.h
@@ -46,6 +46,8 @@ public:
inline quint64 id() const;
+ inline operator JSStringRef() const;
+
private:
JSStringRef m_string;
};
@@ -109,4 +111,14 @@ quint64 QScriptStringPrivate::id() const
return reinterpret_cast<quint32>(m_string);
}
+/*!
+ \internal
+ This method should be used for invoking JSC functions.
+ \note This method keeps ownership of an internal JSStringRef.
+*/
+QScriptStringPrivate::operator JSStringRef() const
+{
+ return m_string;
+}
+
#endif // qscriptstring_p_h
diff --git a/JavaScriptCore/qt/api/qscriptvalue.cpp b/JavaScriptCore/qt/api/qscriptvalue.cpp
index e309fb7..a7d0b7b 100644
--- a/JavaScriptCore/qt/api/qscriptvalue.cpp
+++ b/JavaScriptCore/qt/api/qscriptvalue.cpp
@@ -313,6 +313,17 @@ bool QScriptValue::isError() const
}
/*!
+ Returns true if this QScriptValue is an object of the Array class;
+ otherwise returns false.
+
+ \sa QScriptEngine::newArray()
+*/
+bool QScriptValue::isArray() const
+{
+ return d_ptr->isArray();
+}
+
+/*!
Returns true if this QScriptValue is of the Object type; otherwise
returns false.
@@ -651,6 +662,23 @@ QScriptValue QScriptValue::property(const QString& name, const ResolveFlags& mod
/*!
\overload
+ Returns the value of this QScriptValue's property with the given \a name,
+ using the given \a mode to resolve the property.
+
+ This overload of property() is useful when you need to look up the
+ same property repeatedly, since the lookup can be performed faster
+ when the name is represented as an interned string.
+
+ \sa QScriptEngine::toStringHandle(), setProperty()
+*/
+QScriptValue QScriptValue::property(const QScriptString& name, const ResolveFlags& mode) const
+{
+ return QScriptValuePrivate::get(d_ptr->property(QScriptStringPrivate::get(name).constData(), mode));
+}
+
+/*!
+ \overload
+
Returns the property at the given \a arrayIndex, using the given \a
mode to resolve the property.
@@ -665,3 +693,87 @@ QScriptValue QScriptValue::property(quint32 arrayIndex, const ResolveFlags& mode
{
return QScriptValuePrivate::get(d_ptr->property(arrayIndex, mode));
}
+
+/*!
+ Sets the value of this QScriptValue's property with the given \a name to
+ the given \a value.
+
+ If this QScriptValue is not an object, this function does nothing.
+
+ If this QScriptValue does not already have a property with name \a name,
+ a new property is created; the given \a flags then specify how this
+ property may be accessed by script code.
+
+ If \a value is invalid, the property is removed.
+
+ If the property is implemented using a setter function (i.e. has the
+ PropertySetter flag set), calling setProperty() has side-effects on
+ the script engine, since the setter function will be called with the
+ given \a value as argument (possibly resulting in an uncaught script
+ exception).
+
+ Note that you cannot specify custom getter or setter functions for
+ built-in properties, such as the \c{length} property of Array objects
+ or meta properties of QObject objects.
+
+ \sa property()
+*/
+void QScriptValue::setProperty(const QString& name, const QScriptValue& value, const PropertyFlags& flags)
+{
+ d_ptr->setProperty(name, QScriptValuePrivate::get(value), flags);
+}
+
+/*!
+ \overload
+
+ Sets the property at the given \a arrayIndex to the given \a value.
+
+ This function is provided for convenience and performance when
+ working with array objects.
+
+ If this QScriptValue is not an Array object, this function behaves
+ as if setProperty() was called with the string representation of \a
+ arrayIndex.
+*/
+void QScriptValue::setProperty(quint32 arrayIndex, const QScriptValue& value, const PropertyFlags& flags)
+{
+ d_ptr->setProperty(arrayIndex, QScriptValuePrivate::get(value), flags);
+}
+
+/*!
+ Sets the value of this QScriptValue's property with the given \a
+ name to the given \a value. The given \a flags specify how this
+ property may be accessed by script code.
+
+ This overload of setProperty() is useful when you need to set the
+ same property repeatedly, since the operation can be performed
+ faster when the name is represented as an interned string.
+
+ \sa QScriptEngine::toStringHandle()
+*/
+void QScriptValue::setProperty(const QScriptString& name, const QScriptValue& value, const PropertyFlags& flags)
+{
+ d_ptr->setProperty(QScriptStringPrivate::get(name).constData(), QScriptValuePrivate::get(value), flags);
+}
+
+/*!
+ Returns the flags of the property with the given \a name, using the
+ given \a mode to resolve the property.
+
+ \sa property()
+*/
+QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QString& name, const ResolveFlags& mode) const
+{
+ return d_ptr->propertyFlags(name, mode);
+}
+
+/*!
+ Returns the flags of the property with the given \a name, using the
+ given \a mode to resolve the property.
+
+ \sa property()
+*/
+QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QScriptString& name, const ResolveFlags& mode) const
+{
+ return d_ptr->propertyFlags(QScriptStringPrivate::get(name).constData(), mode);
+}
diff --git a/JavaScriptCore/qt/api/qscriptvalue.h b/JavaScriptCore/qt/api/qscriptvalue.h
index c55d461..991a6a0 100644
--- a/JavaScriptCore/qt/api/qscriptvalue.h
+++ b/JavaScriptCore/qt/api/qscriptvalue.h
@@ -20,6 +20,7 @@
#ifndef qscriptvalue_h
#define qscriptvalue_h
+#include "qscriptstring.h"
#include <QtCore/qlist.h>
#include <QtCore/qshareddata.h>
@@ -34,12 +35,25 @@ typedef double qsreal;
class QScriptValue {
public:
enum ResolveFlag {
- ResolveLocal = 0x00,
- ResolvePrototype = 0x01
+ ResolveLocal = 0x00,
+ ResolvePrototype = 0x01,
+ ResolveScope = 0x02,
+ ResolveFull = ResolvePrototype | ResolveScope
};
-
Q_DECLARE_FLAGS(ResolveFlags, ResolveFlag)
+ enum PropertyFlag {
+ ReadOnly = 0x00000001,
+ Undeletable = 0x00000002,
+ SkipInEnumeration = 0x00000004,
+ PropertyGetter = 0x00000008,
+ PropertySetter = 0x00000010,
+ QObjectMember = 0x00000020,
+ KeepExistingFlags = 0x00000800,
+ UserRange = 0xff000000 // Users may use these as they see fit.
+ };
+ Q_DECLARE_FLAGS(PropertyFlags, PropertyFlag)
+
enum SpecialValue {
NullValue,
UndefinedValue
@@ -75,8 +89,16 @@ public:
bool instanceOf(const QScriptValue& other) const;
QScriptValue property(const QString& name, const ResolveFlags& mode = ResolvePrototype) const;
+ QScriptValue property(const QScriptString& name, const ResolveFlags& mode = ResolvePrototype) const;
QScriptValue property(quint32 arrayIndex, const ResolveFlags& mode = ResolvePrototype) const;
+ void setProperty(const QString& name, const QScriptValue& value, const PropertyFlags& flags = KeepExistingFlags);
+ void setProperty(quint32 arrayIndex, const QScriptValue& value, const PropertyFlags& flags = KeepExistingFlags);
+ void setProperty(const QScriptString& name, const QScriptValue& value, const PropertyFlags& flags = KeepExistingFlags);
+
+ PropertyFlags propertyFlags(const QString& name, const ResolveFlags& mode = ResolvePrototype) const;
+ PropertyFlags propertyFlags(const QScriptString& name, const ResolveFlags& mode = ResolvePrototype) const;
+
QScriptEngine* engine() const;
bool isValid() const;
@@ -89,6 +111,7 @@ public:
bool isUndefined() const;
bool isObject() const;
bool isError() const;
+ bool isArray() const;
QString toString() const;
qsreal toNumber() const;
@@ -102,7 +125,6 @@ public:
QScriptValue call(const QScriptValue& thisObject = QScriptValue(),
const QScriptValueList& args = QScriptValueList());
-
private:
QScriptValue(void*);
QScriptValue(QScriptValuePrivate*);
diff --git a/JavaScriptCore/qt/api/qscriptvalue_p.h b/JavaScriptCore/qt/api/qscriptvalue_p.h
index 49bec97..1d319ba 100644
--- a/JavaScriptCore/qt/api/qscriptvalue_p.h
+++ b/JavaScriptCore/qt/api/qscriptvalue_p.h
@@ -101,6 +101,7 @@ public:
inline bool isError();
inline bool isObject();
inline bool isFunction();
+ inline bool isArray();
inline QString toString() const;
inline qsreal toNumber() const;
@@ -121,7 +122,28 @@ public:
inline bool assignEngine(QScriptEnginePrivate* engine);
inline QScriptValuePrivate* property(const QString& name, const QScriptValue::ResolveFlags& mode);
+ inline QScriptValuePrivate* property(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode);
inline QScriptValuePrivate* property(quint32 arrayIndex, const QScriptValue::ResolveFlags& mode);
+ inline JSValueRef property(quint32 property, JSValueRef* exception);
+ inline JSValueRef property(JSStringRef property, JSValueRef* exception);
+ inline bool hasOwnProperty(quint32 property);
+ inline bool hasOwnProperty(JSStringRef property);
+ template<typename T>
+ inline QScriptValuePrivate* property(T name, const QScriptValue::ResolveFlags& mode);
+
+ inline void setProperty(const QString& name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
+ inline void setProperty(const QScriptStringPrivate* name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
+ inline void setProperty(const quint32 indexArray, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
+ inline void setProperty(quint32 property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception);
+ inline void setProperty(JSStringRef property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception);
+ inline void deleteProperty(quint32 property, JSValueRef* exception);
+ inline void deleteProperty(JSStringRef property, JSValueRef* exception);
+ template<typename T>
+ inline void setProperty(T name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
+
+ QScriptValue::PropertyFlags propertyFlags(const QString& name, const QScriptValue::ResolveFlags& mode);
+ QScriptValue::PropertyFlags propertyFlags(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode);
+ QScriptValue::PropertyFlags propertyFlags(const JSStringRef name, const QScriptValue::ResolveFlags& mode);
inline QScriptValuePrivate* call(const QScriptValuePrivate* , const QScriptValueList& args);
@@ -427,6 +449,20 @@ bool QScriptValuePrivate::isFunction()
}
}
+bool QScriptValuePrivate::isArray()
+{
+ switch (m_state) {
+ case JSValue:
+ if (refinedJSValue() != JSObject)
+ return false;
+ // Fall-through.
+ case JSObject:
+ return m_engine->isArray(*this);
+ default:
+ return false;
+ }
+}
+
QString QScriptValuePrivate::toString() const
{
switch (m_state) {
@@ -744,6 +780,7 @@ inline bool QScriptValuePrivate::instanceOf(QScriptValuePrivate* other)
*/
bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
{
+ Q_ASSERT(engine);
JSValueRef value;
switch (m_state) {
case CBool:
@@ -778,31 +815,252 @@ bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
inline QScriptValuePrivate* QScriptValuePrivate::property(const QString& name, const QScriptValue::ResolveFlags& mode)
{
+ JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(name));
+ return property<JSStringRef>(propertyName.get(), mode);
+}
+
+inline QScriptValuePrivate* QScriptValuePrivate::property(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode)
+{
+ return property<JSStringRef>(*name, mode);
+}
+
+inline QScriptValuePrivate* QScriptValuePrivate::property(quint32 arrayIndex, const QScriptValue::ResolveFlags& mode)
+{
+ return property<quint32>(arrayIndex, mode);
+}
+
+/*!
+ \internal
+ This method was created to unify access to the JSObjectGetPropertyAtIndex and the JSObjectGetProperty.
+*/
+inline JSValueRef QScriptValuePrivate::property(quint32 property, JSValueRef* exception)
+{
+ return JSObjectGetPropertyAtIndex(*m_engine, *this, property, exception);
+}
+
+/*!
+ \internal
+ This method was created to unify access to the JSObjectGetPropertyAtIndex and the JSObjectGetProperty.
+*/
+inline JSValueRef QScriptValuePrivate::property(JSStringRef property, JSValueRef* exception)
+{
+ return JSObjectGetProperty(*m_engine, *this, property, exception);
+}
+
+/*!
+ \internal
+ This method was created to unify acccess to hasOwnProperty, same function for an array index
+ and a property name access.
+*/
+inline bool QScriptValuePrivate::hasOwnProperty(quint32 property)
+{
+ Q_ASSERT(isObject());
+ // FIXME it could be faster, but JSC C API doesn't expose needed functionality.
+ JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(QString::number(property)));
+ return hasOwnProperty(propertyName.get());
+}
+
+/*!
+ \internal
+ This method was created to unify acccess to hasOwnProperty, same function for an array index
+ and a property name access.
+*/
+inline bool QScriptValuePrivate::hasOwnProperty(JSStringRef property)
+{
+ Q_ASSERT(isObject());
+ // FIXME it could be faster, but JSC C API doesn't expose needed functionality.
+ JSRetainPtr<JSStringRef> hasOwnPropertyName(Adopt, JSStringCreateWithUTF8CString("hasOwnProperty"));
+ JSValueRef exception = 0;
+ JSValueRef hasOwnProperty = JSObjectGetProperty(*m_engine, *this, hasOwnPropertyName.get(), &exception);
+ JSValueRef propertyName[] = { JSValueMakeString(*m_engine, property) };
+ JSValueRef result = JSObjectCallAsFunction(*m_engine, const_cast<JSObjectRef>(hasOwnProperty), *this, 1, propertyName, &exception);
+ return exception ? false : JSValueToBoolean(*m_engine, result);
+}
+
+/*!
+ \internal
+ This function gets property of an object.
+ \arg propertyName could be type of quint32 (an array index) or JSStringRef (a property name).
+*/
+template<typename T>
+inline QScriptValuePrivate* QScriptValuePrivate::property(T propertyName, const QScriptValue::ResolveFlags& mode)
+{
if (!isObject())
- return new QScriptValuePrivate;
+ return new QScriptValuePrivate();
- if (mode & QScriptValue::ResolveLocal) {
- qWarning("QScriptValue::property(): ResolveLocal not supported yet.");
+ if ((mode == QScriptValue::ResolveLocal) && (!hasOwnProperty(propertyName)))
+ return new QScriptValuePrivate();
+
+ JSValueRef exception = 0;
+ JSValueRef value = property(propertyName, &exception);
+
+ if (exception) {
+ m_engine->setException(exception, QScriptEnginePrivate::NotNullException);
+ return new QScriptValuePrivate(engine(), exception);
+ }
+ if (JSValueIsUndefined(*m_engine, value))
return new QScriptValuePrivate;
+ return new QScriptValuePrivate(engine(), value);
+}
+
+inline void QScriptValuePrivate::setProperty(const QString& name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
+{
+ JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(name));
+ setProperty<JSStringRef>(propertyName.get(), value, flags);
+}
+
+inline void QScriptValuePrivate::setProperty(quint32 arrayIndex, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
+{
+ setProperty<quint32>(arrayIndex, value, flags);
+}
+
+inline void QScriptValuePrivate::setProperty(const QScriptStringPrivate* name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
+{
+ setProperty<JSStringRef>(*name, value, flags);
+}
+
+/*!
+ \internal
+ This method was created to unify access to the JSObjectSetPropertyAtIndex and the JSObjectSetProperty.
+*/
+inline void QScriptValuePrivate::setProperty(quint32 property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception)
+{
+ Q_ASSERT(isObject());
+ if (flags) {
+ // FIXME This could be better, but JSC C API doesn't expose needed functionality. It is
+ // not possible to create / modify a property attribute via an array index.
+ JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(QString::number(property)));
+ JSObjectSetProperty(*m_engine, *this, propertyName.get(), value, flags, exception);
+ return;
}
+ JSObjectSetPropertyAtIndex(*m_engine, *this, property, value, exception);
+}
- JSRetainPtr<JSStringRef> nameRef(Adopt, QScriptConverter::toString(name));
- QScriptValuePrivate* result = new QScriptValuePrivate(m_engine.constData(), JSObjectGetProperty(*m_engine, *this, nameRef.get(), /* exception */ 0));
+/*!
+ \internal
+ This method was created to unify access to the JSObjectSetPropertyAtIndex and the JSObjectSetProperty.
+*/
+inline void QScriptValuePrivate::setProperty(JSStringRef property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception)
+{
+ Q_ASSERT(isObject());
+ JSObjectSetProperty(*m_engine, *this, property, value, flags, exception);
+}
- return result;
+/*!
+ \internal
+ This method was created to unify access to the JSObjectDeleteProperty and a teoretical JSObjectDeletePropertyAtIndex
+ which doesn't exist now.
+*/
+inline void QScriptValuePrivate::deleteProperty(quint32 property, JSValueRef* exception)
+{
+ // FIXME It could be faster, we need a JSC C API for deleting array index properties.
+ JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(QString::number(property)));
+ JSObjectDeleteProperty(*m_engine, *this, propertyName.get(), exception);
}
-inline QScriptValuePrivate* QScriptValuePrivate::property(quint32 arrayIndex, const QScriptValue::ResolveFlags& mode)
+/*!
+ \internal
+ This method was created to unify access to the JSObjectDeleteProperty and a teoretical JSObjectDeletePropertyAtIndex.
+*/
+inline void QScriptValuePrivate::deleteProperty(JSStringRef property, JSValueRef* exception)
+{
+ Q_ASSERT(isObject());
+ JSObjectDeleteProperty(*m_engine, *this, property, exception);
+}
+
+template<typename T>
+inline void QScriptValuePrivate::setProperty(T name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
{
if (!isObject())
- return new QScriptValuePrivate;
+ return;
- if (mode & QScriptValue::ResolveLocal) {
- qWarning("QScriptValue::property(): ResolveLocal not supported yet.");
- return new QScriptValuePrivate;
+ if (!value->isJSBased())
+ value->assignEngine(engine());
+
+ JSValueRef exception = 0;
+ if (!value->isValid()) {
+ // Remove the property.
+ deleteProperty(name, &exception);
+ m_engine->setException(exception);
+ return;
+ }
+ if (m_engine != value->m_engine) {
+ qWarning("QScriptValue::setProperty() failed: cannot set value created in a different engine");
+ return;
+ }
+
+ setProperty(name, *value, QScriptConverter::toPropertyFlags(flags), &exception);
+ m_engine->setException(exception);
+}
+
+inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(const QString& name, const QScriptValue::ResolveFlags& mode)
+{
+ JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(name));
+ return propertyFlags(propertyName.get(), mode);
+}
+
+inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode)
+{
+ return propertyFlags(*name, mode);
+}
+
+inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(JSStringRef name, const QScriptValue::ResolveFlags& mode)
+{
+ unsigned flags = 0;
+ if (!isObject())
+ return QScriptValue::PropertyFlags(flags);
+
+ // FIXME It could be faster and nicer, but new JSC C API should be created.
+ static JSStringRef objectName = QScriptConverter::toString("Object");
+ static JSStringRef propertyDescriptorName = QScriptConverter::toString("getOwnPropertyDescriptor");
+
+ // FIXME This is dangerous if global object was modified (bug 41839).
+ JSValueRef exception = 0;
+ JSObjectRef globalObject = JSContextGetGlobalObject(*m_engine);
+ JSValueRef objectConstructor = JSObjectGetProperty(*m_engine, globalObject, objectName, &exception);
+ Q_ASSERT(JSValueIsObject(*m_engine, objectConstructor));
+ JSValueRef propertyDescriptorGetter = JSObjectGetProperty(*m_engine, const_cast<JSObjectRef>(objectConstructor), propertyDescriptorName, &exception);
+ Q_ASSERT(JSValueIsObject(*m_engine, propertyDescriptorGetter));
+
+ JSValueRef arguments[] = { *this, JSValueMakeString(*m_engine, name) };
+ JSObjectRef propertyDescriptor
+ = const_cast<JSObjectRef>(JSObjectCallAsFunction(*m_engine,
+ const_cast<JSObjectRef>(propertyDescriptorGetter),
+ /* thisObject */ 0,
+ /* argumentCount */ 2,
+ arguments,
+ &exception));
+ if (exception) {
+ // Invalid property.
+ return QScriptValue::PropertyFlags(flags);
+ }
+
+ if (!JSValueIsObject(*m_engine, propertyDescriptor)) {
+ // Property isn't owned by this object.
+ JSObjectRef proto;
+ if (mode == QScriptValue::ResolveLocal
+ || ((proto = const_cast<JSObjectRef>(JSObjectGetPrototype(*m_engine, *this))) && JSValueIsNull(*m_engine, proto))) {
+ return QScriptValue::PropertyFlags(flags);
+ }
+ QScriptValuePrivate p(engine(), proto);
+ return p.propertyFlags(name, QScriptValue::ResolvePrototype);
}
- return new QScriptValuePrivate(m_engine.constData(), JSObjectGetPropertyAtIndex(*m_engine, *this, arrayIndex, /* exception */ 0));
+ static JSStringRef writableName = QScriptConverter::toString("writable");
+ static JSStringRef configurableName = QScriptConverter::toString("configurable");
+ static JSStringRef enumerableName = QScriptConverter::toString("enumerable");
+
+ bool readOnly = !JSValueToBoolean(*m_engine, JSObjectGetProperty(*m_engine, propertyDescriptor, writableName, &exception));
+ if (!exception && readOnly)
+ flags |= QScriptValue::ReadOnly;
+ bool undeletable = !JSValueToBoolean(*m_engine, JSObjectGetProperty(*m_engine, propertyDescriptor, configurableName, &exception));
+ if (!exception && undeletable)
+ flags |= QScriptValue::Undeletable;
+ bool skipInEnum = !JSValueToBoolean(*m_engine, JSObjectGetProperty(*m_engine, propertyDescriptor, enumerableName, &exception));
+ if (!exception && skipInEnum)
+ flags |= QScriptValue::SkipInEnumeration;
+
+ return QScriptValue::PropertyFlags(flags);
}
QScriptValuePrivate* QScriptValuePrivate::call(const QScriptValuePrivate*, const QScriptValueList& args)