diff options
Diffstat (limited to 'src/script/api/qscriptvalue.cpp')
-rw-r--r-- | src/script/api/qscriptvalue.cpp | 2098 |
1 files changed, 645 insertions, 1453 deletions
diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index 91ce9c8..6fd2393 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -21,114 +21,36 @@ ** ****************************************************************************/ -#include "config.h" -#include "qscriptvalue.h" - -#include "qscriptvalue_p.h" +#include "qscriptisolate_p.h" #include "qscriptengine.h" #include "qscriptengine_p.h" -#include "qscriptstring_p.h" - -#include "JSGlobalObject.h" -#include "JSImmediate.h" -#include "JSObject.h" -#include "JSValue.h" -#include "JSFunction.h" -#include "Identifier.h" -#include "Operations.h" -#include "Arguments.h" +#include "qscriptstring.h" +#include "qscriptvalue.h" +#include "qscriptvalue_p.h" +#include "qscriptclass_p.h" +#include "qscriptdeclarativeclassobject_p.h" +#include "qscript_impl_p.h" +#include "qscriptshareddata_p.h" +#include <QtCore/qregexp.h> +#include <QtCore/qstring.h> -#include <QtCore/qvariant.h> -#include <QtCore/qvarlengtharray.h> -#include <QtCore/qnumeric.h> +QT_BEGIN_NAMESPACE /*! - \since 4.3 - \class QScriptValue - - \brief The QScriptValue class acts as a container for the Qt Script data types. - - \ingroup script - \mainclass - - QScriptValue supports the types defined in the \l{ECMA-262} - standard: The primitive types, which are Undefined, Null, Boolean, - Number, and String; and the Object type. Additionally, Qt Script - has built-in support for QVariant, QObject and QMetaObject. - - For the object-based types (including Date and RegExp), use the - newT() functions in QScriptEngine (e.g. QScriptEngine::newObject()) - to create a QScriptValue of the desired type. For the primitive types, - use one of the QScriptValue constructor overloads. - - The methods named isT() (e.g. isBool(), isUndefined()) can be - used to test if a value is of a certain type. The methods named - toT() (e.g. toBool(), toString()) can be used to convert a - QScriptValue to another type. You can also use the generic - qscriptvalue_cast() function. - - Object values have zero or more properties which are themselves - QScriptValues. Use setProperty() to set a property of an object, and - call property() to retrieve the value of a property. - - \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 0 - - Each property can have a set of attributes; these are specified as - the third (optional) argument to setProperty(). The attributes of a - property can be queried by calling the propertyFlags() function. The - following code snippet creates a property that cannot be modified by - script code: - - \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 1 - - If you want to iterate over the properties of a script object, use - the QScriptValueIterator class. - - Object values have an internal \c{prototype} property, which can be - accessed with prototype() and setPrototype(). Properties added to a - prototype are shared by all objects having that prototype; this is - referred to as prototype-based inheritance. In practice, it means - that (by default) the property() function will automatically attempt - to look up look the property in the prototype() (and in the - prototype of the prototype(), and so on), if the object itself does - not have the requested property. Note that this prototype-based - lookup is not performed by setProperty(); setProperty() will always - create the property in the script object itself. For more - information, see the \l{QtScript} documentation. - - Function objects (objects for which isFunction() returns true) can - be invoked by calling call(). Constructor functions can be used to - construct new objects by calling construct(). - - Use equals(), strictlyEquals() and lessThan() to compare a QScriptValue - to another. - - Object values can have custom data associated with them; see the - setData() and data() functions. By default, this data is not - accessible to scripts; it can be used to store any data you want to - associate with the script object. Typically this is used by custom - class objects (see QScriptClass) to store a C++ type that contains - the "native" object data. - - Note that a QScriptValue for which isObject() is true only carries a - reference to an actual object; copying the QScriptValue will only - copy the object reference, not the object itself. If you want to - clone an object (i.e. copy an object's properties to another - object), you can do so with the help of a \c{for-in} statement in - script code, or QScriptValueIterator in C++. - - \sa QScriptEngine, QScriptValueIterator + Constructs an invalid value. */ +QScriptValue::QScriptValue() + : d_ptr(InvalidValue()) +{ +} /*! - \enum QScriptValue::SpecialValue - - This enum is used to specify a single-valued type. - - \value UndefinedValue An undefined value. - - \value NullValue A null value. + Constructs a new QScriptValue with a boolean \a value. */ +QScriptValue::QScriptValue(bool value) + : d_ptr(new QScriptValuePrivate(value)) +{ +} /*! \enum QScriptValue::PropertyFlag @@ -153,783 +75,376 @@ */ /*! - \enum QScriptValue::ResolveFlag - - This enum specifies how to look up a property of an object. - - \value ResolveLocal Only check the object's own properties. - - \value ResolvePrototype Check the object's own properties first, then search the prototype chain. This is the default. - - \omitvalue ResolveScope Check the object's own properties first, then search the scope chain. - - \omitvalue ResolveFull Check the object's own properties first, then search the prototype chain, and finally search the scope chain. + Constructs a new QScriptValue with a number \a value. */ +QScriptValue::QScriptValue(int value) + : d_ptr(new QScriptValuePrivate(value)) +{ +} -QT_BEGIN_NAMESPACE +/*! + Constructs a new QScriptValue with a number \a value. +*/ +QScriptValue::QScriptValue(uint value) + : d_ptr(new QScriptValuePrivate(value)) +{ +} -void QScriptValuePrivate::detachFromEngine() +/*! + Constructs a new QScriptValue with a number \a value. +*/ +QScriptValue::QScriptValue(qsreal value) + : d_ptr(new QScriptValuePrivate(value)) { - if (isJSC()) - jscValue = JSC::JSValue(); - engine = 0; } /*! - \internal + Constructs a new QScriptValue with a string \a value. */ -QScriptValue::QScriptValue(QScriptValuePrivate *d) - : d_ptr(d) +QScriptValue::QScriptValue(const QString& value) + : d_ptr(new QScriptValuePrivate(value)) { } /*! - Constructs an invalid QScriptValue. + Constructs a new QScriptValue with a special \a value. */ -QScriptValue::QScriptValue() - : d_ptr(0) +QScriptValue::QScriptValue(SpecialValue value) + : d_ptr(new QScriptValuePrivate(value)) { } /*! - Destroys this QScriptValue. + Constructs a new QScriptValue with a string \a value. */ -QScriptValue::~QScriptValue() +QScriptValue::QScriptValue(const QLatin1String &value) + : d_ptr(new QScriptValuePrivate(value)) { } /*! - Constructs a new QScriptValue that is a copy of \a other. + Constructs a new QScriptValue with a string \a value. +*/ +QScriptValue::QScriptValue(const char* value) + : d_ptr(new QScriptValuePrivate(QString::fromUtf8(value))) +{ +} - Note that if \a other is an object (i.e., isObject() would return - true), then only a reference to the underlying object is copied into - the new script value (i.e., the object itself is not copied). +/*! + Block automatic convertion to bool + \internal */ -QScriptValue::QScriptValue(const QScriptValue &other) - : d_ptr(other.d_ptr) +QScriptValue::QScriptValue(void* d) { + Q_UNUSED(d); + Q_ASSERT(false); } /*! - \obsolete + Constructs a new QScriptValue from private + \internal +*/ +QScriptValue::QScriptValue(QScriptValuePrivate* d) + : d_ptr(d) +{ +} - Constructs a new QScriptValue with the special \a value and - registers it with the script \a engine. +/*! + Constructs a new QScriptValue from private + \internal */ -QScriptValue::QScriptValue(QScriptEngine *engine, QScriptValue::SpecialValue value) - : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine))) +QScriptValue::QScriptValue(QScriptPassPointer<QScriptValuePrivate> d) + : d_ptr(d.give()) { - switch (value) { - case NullValue: - d_ptr->initFrom(JSC::jsNull()); - break; - case UndefinedValue: - d_ptr->initFrom(JSC::jsUndefined()); - break; - } } /*! \obsolete - \fn QScriptValue::QScriptValue(QScriptEngine *engine, bool value) - Constructs a new QScriptValue with the boolean \a value and registers it with the script \a engine. */ -QScriptValue::QScriptValue(QScriptEngine *engine, bool val) - : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine))) +QScriptValue::QScriptValue(QScriptEngine* engine, bool value) { - d_ptr->initFrom(JSC::jsBoolean(val)); + if (engine) { + QScriptIsolate api(QScriptEnginePrivate::get(engine), QScriptIsolate::NotNullEngine); + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value); + } else { + d_ptr = new QScriptValuePrivate(value); + } } /*! - \fn QScriptValue::QScriptValue(QScriptEngine *engine, int value) \obsolete Constructs a new QScriptValue with the integer \a value and registers it with the script \a engine. */ -QScriptValue::QScriptValue(QScriptEngine *engine, int val) - : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine))) +QScriptValue::QScriptValue(QScriptEngine* engine, int value) { if (engine) { - QScript::APIShim shim(d_ptr->engine); - JSC::ExecState *exec = d_ptr->engine->currentFrame; - d_ptr->initFrom(JSC::jsNumber(exec, val)); - } else - d_ptr->initFrom(val); + QScriptIsolate api(QScriptEnginePrivate::get(engine), QScriptIsolate::NotNullEngine); + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value); + } else { + d_ptr = new QScriptValuePrivate(value); + } } /*! - \fn QScriptValue::QScriptValue(QScriptEngine *engine, uint value) \obsolete Constructs a new QScriptValue with the unsigned integer \a value and registers it with the script \a engine. */ -QScriptValue::QScriptValue(QScriptEngine *engine, uint val) - : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine))) +QScriptValue::QScriptValue(QScriptEngine* engine, uint value) { if (engine) { - QScript::APIShim shim(d_ptr->engine); - JSC::ExecState *exec = d_ptr->engine->currentFrame; - d_ptr->initFrom(JSC::jsNumber(exec, val)); - } else - d_ptr->initFrom(val); + QScriptIsolate api(QScriptEnginePrivate::get(engine), QScriptIsolate::NotNullEngine); + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value); + } else { + d_ptr = new QScriptValuePrivate(value); + } } /*! - \fn QScriptValue::QScriptValue(QScriptEngine *engine, qsreal value) \obsolete Constructs a new QScriptValue with the qsreal \a value and registers it with the script \a engine. */ -QScriptValue::QScriptValue(QScriptEngine *engine, qsreal val) - : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine))) +QScriptValue::QScriptValue(QScriptEngine* engine, qsreal value) { if (engine) { - QScript::APIShim shim(d_ptr->engine); - JSC::ExecState *exec = d_ptr->engine->currentFrame; - d_ptr->initFrom(JSC::jsNumber(exec, val)); - } else - d_ptr->initFrom(val); + QScriptIsolate api(QScriptEnginePrivate::get(engine), QScriptIsolate::NotNullEngine); + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value); + } else { + d_ptr = new QScriptValuePrivate(value); + } } /*! - \fn QScriptValue::QScriptValue(QScriptEngine *engine, const QString &value) \obsolete Constructs a new QScriptValue with the string \a value and registers it with the script \a engine. */ -QScriptValue::QScriptValue(QScriptEngine *engine, const QString &val) - : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine))) +QScriptValue::QScriptValue(QScriptEngine* engine, const QString& value) { if (engine) { - QScript::APIShim shim(d_ptr->engine); - JSC::ExecState *exec = d_ptr->engine->currentFrame; - d_ptr->initFrom(JSC::jsString(exec, val)); + QScriptIsolate api(QScriptEnginePrivate::get(engine), QScriptIsolate::NotNullEngine); + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value); } else { - d_ptr->initFrom(val); + d_ptr = new QScriptValuePrivate(value); } } /*! - \fn QScriptValue::QScriptValue(QScriptEngine *engine, const char *value) \obsolete Constructs a new QScriptValue with the string \a value and registers it with the script \a engine. */ - -#ifndef QT_NO_CAST_FROM_ASCII -QScriptValue::QScriptValue(QScriptEngine *engine, const char *val) - : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine))) +QScriptValue::QScriptValue(QScriptEngine* engine, const char* value) { if (engine) { - QScript::APIShim shim(d_ptr->engine); - JSC::ExecState *exec = d_ptr->engine->currentFrame; - d_ptr->initFrom(JSC::jsString(exec, val)); + QScriptIsolate api(QScriptEnginePrivate::get(engine), QScriptIsolate::NotNullEngine); + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), QString::fromUtf8(value)); } else { - d_ptr->initFrom(QString::fromAscii(val)); + d_ptr = new QScriptValuePrivate(QString::fromUtf8(value)); } } -#endif /*! - \since 4.5 - - Constructs a new QScriptValue with a special \a value. -*/ -QScriptValue::QScriptValue(SpecialValue value) - : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0)) -{ - switch (value) { - case NullValue: - d_ptr->initFrom(JSC::jsNull()); - break; - case UndefinedValue: - d_ptr->initFrom(JSC::jsUndefined()); - break; - } -} - -/*! - \since 4.5 - - Constructs a new QScriptValue with a boolean \a value. -*/ -QScriptValue::QScriptValue(bool value) - : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0)) -{ - d_ptr->initFrom(JSC::jsBoolean(value)); -} - -/*! - \since 4.5 - - Constructs a new QScriptValue with a number \a value. -*/ -QScriptValue::QScriptValue(int value) - : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0)) -{ - d_ptr->initFrom(value); -} - -/*! - \since 4.5 + \obsolete - Constructs a new QScriptValue with a number \a value. + Constructs a new QScriptValue with the special \a value and + registers it with the script \a engine. */ -QScriptValue::QScriptValue(uint value) - : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0)) +QScriptValue::QScriptValue(QScriptEngine* engine, SpecialValue value) { - d_ptr->initFrom(value); + if (engine) { + QScriptIsolate api(QScriptEnginePrivate::get(engine), QScriptIsolate::NotNullEngine); + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value); + } else { + d_ptr = new QScriptValuePrivate(value); + } } /*! - \since 4.5 + Constructs a new QScriptValue that is a copy of \a other. - Constructs a new QScriptValue with a number \a value. + Note that if \a other is an object (i.e., isObject() would return + true), then only a reference to the underlying object is copied into + the new script value (i.e., the object itself is not copied). */ -QScriptValue::QScriptValue(qsreal value) - : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0)) +QScriptValue::QScriptValue(const QScriptValue& other) + : d_ptr(other.d_ptr) { - d_ptr->initFrom(value); } /*! - \since 4.5 - - Constructs a new QScriptValue with a string \a value. + Destroys this QScriptValue. */ -QScriptValue::QScriptValue(const QString &value) - : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0)) +QScriptValue::~QScriptValue() { - d_ptr->initFrom(value); } /*! - \since 4.5 - - Constructs a new QScriptValue with a string \a value. + Returns true if this QScriptValue is valid; otherwise returns + false. */ -QScriptValue::QScriptValue(const QLatin1String &value) - : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0)) +bool QScriptValue::isValid() const { - d_ptr->initFrom(value); + Q_D(const QScriptValue); + QScriptIsolate api(d->engine()); + return d->isValid(); } /*! - \since 4.5 + Returns true if this QScriptValue is of the primitive type Boolean; + otherwise returns false. - Constructs a new QScriptValue with a string \a value. + \sa toBool() */ - -#ifndef QT_NO_CAST_FROM_ASCII -QScriptValue::QScriptValue(const char *value) - : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0)) +bool QScriptValue::isBool() const { - d_ptr->initFrom(QString::fromAscii(value)); + Q_D(const QScriptValue); + QScriptIsolate api(d->engine()); + return d->isBool(); } -#endif /*! - Assigns the \a other value to this QScriptValue. - - Note that if \a other is an object (isObject() returns true), - only a reference to the underlying object will be assigned; - the object itself will not be copied. -*/ -QScriptValue &QScriptValue::operator=(const QScriptValue &other) -{ - d_ptr = other.d_ptr; - return *this; -} + \obsolete -/*! - Returns true if this QScriptValue is an object of the Error class; + Use isBool() instead. + Returns true if this QScriptValue is of the primitive type Boolean; otherwise returns false. - - \sa QScriptContext::throwError() */ -bool QScriptValue::isError() const +bool QScriptValue::isBoolean() const { Q_D(const QScriptValue); - if (!d || !d->isJSC()) - return false; - return QScriptEnginePrivate::isError(d->jscValue); + QScriptIsolate api(d->engine()); + return d->isBool(); } /*! - Returns true if this QScriptValue is an object of the Array class; + Returns true if this QScriptValue is of the primitive type Number; otherwise returns false. - \sa QScriptEngine::newArray() + \sa toNumber() */ -bool QScriptValue::isArray() const +bool QScriptValue::isNumber() const { Q_D(const QScriptValue); - if (!d || !d->isJSC()) - return false; - return QScriptEnginePrivate::isArray(d->jscValue); + QScriptIsolate api(d->engine()); + return d->isNumber(); } /*! - Returns true if this QScriptValue is an object of the Date class; + Returns true if this QScriptValue is of the primitive type Null; otherwise returns false. - \sa QScriptEngine::newDate() + \sa QScriptEngine::nullValue() */ -bool QScriptValue::isDate() const +bool QScriptValue::isNull() const { Q_D(const QScriptValue); - if (!d || !d->isJSC()) - return false; - return QScriptEnginePrivate::isDate(d->jscValue); + QScriptIsolate api(d->engine()); + return d->isNull(); } /*! - Returns true if this QScriptValue is an object of the RegExp class; + Returns true if this QScriptValue is of the primitive type String; otherwise returns false. - \sa QScriptEngine::newRegExp() + \sa toString() */ -bool QScriptValue::isRegExp() const +bool QScriptValue::isString() const { Q_D(const QScriptValue); - if (!d || !d->isJSC()) - return false; - return QScriptEnginePrivate::isRegExp(d->jscValue); + QScriptIsolate api(d->engine()); + return d->isString(); } /*! - If this QScriptValue is an object, returns the internal prototype - (\c{__proto__} property) of this object; otherwise returns an - invalid QScriptValue. + Returns true if this QScriptValue is of the primitive type Undefined; + otherwise returns false. - \sa setPrototype(), isObject() + \sa QScriptEngine::undefinedValue() */ -QScriptValue QScriptValue::prototype() const +bool QScriptValue::isUndefined() const { Q_D(const QScriptValue); - if (!d || !d->isObject()) - return QScriptValue(); - return d->engine->scriptValueFromJSCValue(JSC::asObject(d->jscValue)->prototype()); + QScriptIsolate api(d->engine()); + return d->isUndefined(); } /*! - If this QScriptValue is an object, sets the internal prototype - (\c{__proto__} property) of this object to be \a prototype; - otherwise does nothing. - - The internal prototype should not be confused with the public - property with name "prototype"; the public prototype is usually - only set on functions that act as constructors. - - \sa prototype(), isObject() -*/ -void QScriptValue::setPrototype(const QScriptValue &prototype) -{ - Q_D(QScriptValue); - if (!d || !d->isObject()) - return; - - JSC::JSValue other = d->engine->scriptValueToJSCValue(prototype); - if (!other || !(other.isObject() || other.isNull())) - return; - - if (QScriptValuePrivate::getEngine(prototype) - && (QScriptValuePrivate::getEngine(prototype) != d->engine)) { - qWarning("QScriptValue::setPrototype() failed: " - "cannot set a prototype created in " - "a different engine"); - return; - } - JSC::JSObject *thisObject = JSC::asObject(d->jscValue); - - // check for cycle - JSC::JSValue nextPrototypeValue = other; - while (nextPrototypeValue && nextPrototypeValue.isObject()) { - JSC::JSObject *nextPrototype = JSC::asObject(nextPrototypeValue); - if (nextPrototype == thisObject) { - qWarning("QScriptValue::setPrototype() failed: cyclic prototype value"); - return; - } - nextPrototypeValue = nextPrototype->prototype(); - } - - thisObject->setPrototype(other); - - // Sync the internal Global Object prototype if appropriate. - if (((thisObject == d->engine->originalGlobalObjectProxy) - && !d->engine->customGlobalObject()) - || (thisObject == d->engine->customGlobalObject())) { - d->engine->originalGlobalObject()->setPrototype(other); - } -} + Returns true if this QScriptValue is an object of the Error class; + otherwise returns false. -/*! - \internal + \sa QScriptContext::throwError() */ -QScriptValue QScriptValue::scope() const +bool QScriptValue::isError() const { Q_D(const QScriptValue); - if (!d || !d->isObject()) - return QScriptValue(); - QScript::APIShim shim(d->engine); - // ### make hidden property - JSC::JSValue result = d->property("__qt_scope__", QScriptValue::ResolveLocal); - return d->engine->scriptValueFromJSCValue(result); -} - -/*! - \internal -*/ -void QScriptValue::setScope(const QScriptValue &scope) -{ - Q_D(QScriptValue); - if (!d || !d->isObject()) - return; - if (scope.isValid() && QScriptValuePrivate::getEngine(scope) - && (QScriptValuePrivate::getEngine(scope) != d->engine)) { - qWarning("QScriptValue::setScope() failed: " - "cannot set a scope object created in " - "a different engine"); - return; - } - JSC::JSValue other = d->engine->scriptValueToJSCValue(scope); - JSC::ExecState *exec = d->engine->currentFrame; - JSC::Identifier id = JSC::Identifier(exec, "__qt_scope__"); - if (!scope.isValid()) { - JSC::asObject(d->jscValue)->removeDirect(id); - } else { - // ### make hidden property - JSC::asObject(d->jscValue)->putDirect(id, other); - } + QScriptIsolate api(d->engine()); + return d->isError(); } /*! - Returns true if this QScriptValue is an instance of - \a other; otherwise returns false. + Returns true if this QScriptValue is an object of the Array class; + otherwise returns false. - This QScriptValue is considered to be an instance of \a other if - \a other is a function and the value of the \c{prototype} - property of \a other is in the prototype chain of this - QScriptValue. + \sa QScriptEngine::newArray() */ -bool QScriptValue::instanceOf(const QScriptValue &other) const +bool QScriptValue::isArray() const { Q_D(const QScriptValue); - if (!d || !d->isObject() || !other.isObject()) - return false; - if (QScriptValuePrivate::getEngine(other) != d->engine) { - qWarning("QScriptValue::instanceof: " - "cannot perform operation on a value created in " - "a different engine"); - return false; - } - JSC::JSValue jscProto = d->engine->scriptValueToJSCValue(other.property(QLatin1String("prototype"))); - if (!jscProto) - jscProto = JSC::jsUndefined(); - JSC::ExecState *exec = d->engine->currentFrame; - JSC::JSValue jscOther = d->engine->scriptValueToJSCValue(other); - return JSC::asObject(jscOther)->hasInstance(exec, d->jscValue, jscProto); -} - -// ### move - -namespace QScript -{ - -enum Type { - Undefined, - Null, - Boolean, - String, - Number, - Object -}; - -static Type type(const QScriptValue &v) -{ - if (v.isUndefined()) - return Undefined; - else if (v.isNull()) - return Null; - else if (v.isBoolean()) - return Boolean; - else if (v.isString()) - return String; - else if (v.isNumber()) - return Number; - Q_ASSERT(v.isObject()); - return Object; -} - -static QScriptValue ToPrimitive(const QScriptValue &object, JSC::PreferredPrimitiveType hint = JSC::NoPreference) -{ - Q_ASSERT(object.isObject()); - QScriptValuePrivate *pp = QScriptValuePrivate::get(object); - Q_ASSERT(pp->engine != 0); - QScript::APIShim shim(pp->engine); - JSC::ExecState *exec = pp->engine->currentFrame; - JSC::JSValue savedException; - QScriptEnginePrivate::saveException(exec, &savedException); - JSC::JSValue result = JSC::asObject(pp->jscValue)->toPrimitive(exec, hint); - QScriptEnginePrivate::restoreException(exec, savedException); - return pp->engine->scriptValueFromJSCValue(result); -} - -static bool IsNumerical(const QScriptValue &value) -{ - return value.isNumber() || value.isBool(); -} - -static bool LessThan(QScriptValue lhs, QScriptValue rhs) -{ - if (type(lhs) == type(rhs)) { - switch (type(lhs)) { - case Undefined: - case Null: - return false; - - case Number: - return lhs.toNumber() < rhs.toNumber(); - - case Boolean: - return lhs.toBool() < rhs.toBool(); - - case String: - return lhs.toString() < rhs.toString(); - - case Object: - break; - } // switch - } - - if (lhs.isObject()) - lhs = ToPrimitive(lhs, JSC::PreferNumber); - - if (rhs.isObject()) - rhs = ToPrimitive(rhs, JSC::PreferNumber); - - if (lhs.isString() && rhs.isString()) - return lhs.toString() < rhs.toString(); - - return lhs.toNumber() < rhs.toNumber(); -} - -static bool Equals(QScriptValue lhs, QScriptValue rhs) -{ - if (type(lhs) == type(rhs)) { - switch (type(lhs)) { - case QScript::Undefined: - case QScript::Null: - return true; - - case QScript::Number: - return lhs.toNumber() == rhs.toNumber(); - - case QScript::Boolean: - return lhs.toBool() == rhs.toBool(); - - case QScript::String: - return lhs.toString() == rhs.toString(); - - case QScript::Object: - if (lhs.isVariant()) - return lhs.strictlyEquals(rhs) || (lhs.toVariant() == rhs.toVariant()); -#ifndef QT_NO_QOBJECT - else if (lhs.isQObject()) - return (lhs.strictlyEquals(rhs)) || (lhs.toQObject() == rhs.toQObject()); -#endif - else - return lhs.strictlyEquals(rhs); - } - } - - if (lhs.isNull() && rhs.isUndefined()) - return true; - - else if (lhs.isUndefined() && rhs.isNull()) - return true; - - else if (IsNumerical(lhs) && rhs.isString()) - return lhs.toNumber() == rhs.toNumber(); - - else if (lhs.isString() && IsNumerical(rhs)) - return lhs.toNumber() == rhs.toNumber(); - - else if (lhs.isBool()) - return Equals(lhs.toNumber(), rhs); - - else if (rhs.isBool()) - return Equals(lhs, rhs.toNumber()); - - else if (lhs.isObject() && !rhs.isNull()) { - lhs = ToPrimitive(lhs); - - if (lhs.isValid() && !lhs.isObject()) - return Equals(lhs, rhs); - } - - else if (rhs.isObject() && ! lhs.isNull()) { - rhs = ToPrimitive(rhs); - if (rhs.isValid() && !rhs.isObject()) - return Equals(lhs, rhs); - } - - return false; -} - -} // namespace QScript + QScriptIsolate api(d->engine()); + return d->isArray(); + } /*! - Returns true if this QScriptValue is less than \a other, otherwise - returns false. The comparison follows the behavior described in - \l{ECMA-262} section 11.8.5, "The Abstract Relational Comparison - Algorithm". + Returns true if this QScriptValue is of the Object type; otherwise + returns false. - Note that if this QScriptValue or the \a other value are objects, - calling this function has side effects on the script engine, since - the engine will call the object's valueOf() function (and possibly - toString()) in an attempt to convert the object to a primitive value - (possibly resulting in an uncaught script exception). + Note that function values, variant values, and QObject values are + objects, so this function returns true for such values. - \sa equals() + \sa toObject(), QScriptEngine::newObject() */ -bool QScriptValue::lessThan(const QScriptValue &other) const +bool QScriptValue::isObject() const { Q_D(const QScriptValue); - // no equivalent function in JSC? There's a jsLess() in VM/Machine.cpp - if (!isValid() || !other.isValid()) - return false; - if (QScriptValuePrivate::getEngine(other) && d->engine - && (QScriptValuePrivate::getEngine(other) != d->engine)) { - qWarning("QScriptValue::lessThan: " - "cannot compare to a value created in " - "a different engine"); - return false; - } - return QScript::LessThan(*this, other); + QScriptIsolate api(d->engine()); + return d->isObject(); } /*! - Returns true if this QScriptValue is equal to \a other, otherwise - returns false. The comparison follows the behavior described in - \l{ECMA-262} section 11.9.3, "The Abstract Equality Comparison - Algorithm". - - This function can return true even if the type of this QScriptValue - is different from the type of the \a other value; i.e. the - comparison is not strict. For example, comparing the number 9 to - the string "9" returns true; comparing an undefined value to a null - value returns true; comparing a \c{Number} object whose primitive - value is 6 to a \c{String} object whose primitive value is "6" - returns true; and comparing the number 1 to the boolean value - \c{true} returns true. If you want to perform a comparison - without such implicit value conversion, use strictlyEquals(). - - Note that if this QScriptValue or the \a other value are objects, - calling this function has side effects on the script engine, since - the engine will call the object's valueOf() function (and possibly - toString()) in an attempt to convert the object to a primitive value - (possibly resulting in an uncaught script exception). + Returns true if this QScriptValue is a function; otherwise returns + false. - \sa strictlyEquals(), lessThan() + \sa call() */ -bool QScriptValue::equals(const QScriptValue &other) const +bool QScriptValue::isFunction() const { Q_D(const QScriptValue); - if (!d || !other.d_ptr) - return (d_ptr == other.d_ptr); - if (QScriptValuePrivate::getEngine(other) && d->engine - && (QScriptValuePrivate::getEngine(other) != d->engine)) { - qWarning("QScriptValue::equals: " - "cannot compare to a value created in " - "a different engine"); - return false; - } - if (d->isJSC() && other.d_ptr->isJSC()) { - QScriptEnginePrivate *eng_p = d->engine; - if (!eng_p) - eng_p = other.d_ptr->engine; - if (eng_p) { - QScript::APIShim shim(eng_p); - JSC::ExecState *exec = eng_p->currentFrame; - JSC::JSValue savedException; - QScriptEnginePrivate::saveException(exec, &savedException); - bool result = JSC::JSValue::equal(exec, d->jscValue, other.d_ptr->jscValue); - QScriptEnginePrivate::restoreException(exec, savedException); - return result; - } - } - return QScript::Equals(*this, other); + QScriptIsolate api(d->engine()); + return d->isCallable(); } /*! - Returns true if this QScriptValue is equal to \a other using strict - comparison (no conversion), otherwise returns false. The comparison - follows the behavior described in \l{ECMA-262} section 11.9.6, "The - Strict Equality Comparison Algorithm". - - If the type of this QScriptValue is different from the type of the - \a other value, this function returns false. If the types are equal, - the result depends on the type, as shown in the following table: - - \table - \header \o Type \o Result - \row \o Undefined \o true - \row \o Null \o true - \row \o Boolean \o true if both values are true, false otherwise - \row \o Number \o false if either value is NaN (Not-a-Number); true if values are equal, false otherwise - \row \o String \o true if both values are exactly the same sequence of characters, false otherwise - \row \o Object \o true if both values refer to the same object, false otherwise - \endtable + Returns true if this QScriptValue is a variant value; + otherwise returns false. - \sa equals() + \sa toVariant(), QScriptEngine::newVariant() */ -bool QScriptValue::strictlyEquals(const QScriptValue &other) const +bool QScriptValue::isVariant() const { Q_D(const QScriptValue); - if (!d || !other.d_ptr) - return (d_ptr == other.d_ptr); - if (QScriptValuePrivate::getEngine(other) && d->engine - && (QScriptValuePrivate::getEngine(other) != d->engine)) { - qWarning("QScriptValue::strictlyEquals: " - "cannot compare to a value created in " - "a different engine"); - return false; - } - - if (d->type != other.d_ptr->type) { - if (d->type == QScriptValuePrivate::JavaScriptCore) { - QScriptEnginePrivate *eng_p = d->engine ? d->engine : other.d_ptr->engine; - if (eng_p) - return JSC::JSValue::strictEqual(eng_p->currentFrame, d->jscValue, eng_p->scriptValueToJSCValue(other)); - } else if (other.d_ptr->type == QScriptValuePrivate::JavaScriptCore) { - QScriptEnginePrivate *eng_p = other.d_ptr->engine ? other.d_ptr->engine : d->engine; - if (eng_p) - return JSC::JSValue::strictEqual(eng_p->currentFrame, eng_p->scriptValueToJSCValue(*this), other.d_ptr->jscValue); - } - - return false; - } - switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: { - QScriptEnginePrivate *eng_p = d->engine ? d->engine : other.d_ptr->engine; - JSC::ExecState *exec = eng_p ? eng_p->currentFrame : 0; - return JSC::JSValue::strictEqual(exec, d->jscValue, other.d_ptr->jscValue); - } - case QScriptValuePrivate::Number: - return (d->numberValue == other.d_ptr->numberValue); - case QScriptValuePrivate::String: - return (d->stringValue == other.d_ptr->stringValue); - } - return false; + QScriptIsolate api(d->engine()); + return d->isVariant(); } /*! @@ -947,22 +462,8 @@ bool QScriptValue::strictlyEquals(const QScriptValue &other) const QString QScriptValue::toString() const { Q_D(const QScriptValue); - if (!d) - return QString(); - switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: { - if (d->engine) { - QScript::APIShim shim(d->engine); - return QScriptEnginePrivate::toString(d->engine->currentFrame, d->jscValue); - } else { - return QScriptEnginePrivate::toString(0, d->jscValue); - } } - case QScriptValuePrivate::Number: - return QScript::ToString(d->numberValue); - case QScriptValuePrivate::String: - return d->stringValue; - } - return QString(); + QScriptIsolate api(d->engine()); + return d->toString(); } /*! @@ -980,23 +481,27 @@ QString QScriptValue::toString() const qsreal QScriptValue::toNumber() const { Q_D(const QScriptValue); - if (!d) - return 0; - switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: { - if (d->engine) { - QScript::APIShim shim(d->engine); - return QScriptEnginePrivate::toNumber(d->engine->currentFrame, d->jscValue); - } else { - return QScriptEnginePrivate::toNumber(0, d->jscValue); - } - } - case QScriptValuePrivate::Number: - return d->numberValue; - case QScriptValuePrivate::String: - return QScript::ToNumber(d->stringValue); - } - return 0; + QScriptIsolate api(d->engine()); + return d->toNumber(); +} + +/*! + Returns the boolean value of this QScriptValue, using the conversion + rules described in \l{ECMA-262} section 9.2, "ToBoolean". + + Note that if this QScriptValue is an object, calling this function + has side effects on the script engine, since the engine will call + the object's valueOf() function (and possibly toString()) in an + attempt to convert the object to a primitive value (possibly + resulting in an uncaught script exception). + + \sa isBool() +*/ +bool QScriptValue::toBool() const +{ + Q_D(const QScriptValue); + QScriptIsolate api(d->engine()); + return d->toBool(); } /*! @@ -1007,30 +512,13 @@ qsreal QScriptValue::toNumber() const bool QScriptValue::toBoolean() const { Q_D(const QScriptValue); - if (!d) - return false; - switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: { - if (d->engine) { - QScript::APIShim shim(d->engine); - return QScriptEnginePrivate::toBool(d->engine->currentFrame, d->jscValue); - } else { - return QScriptEnginePrivate::toBool(0, d->jscValue); - } - } - case QScriptValuePrivate::Number: - return QScript::ToBool(d->numberValue); - case QScriptValuePrivate::String: - return QScript::ToBool(d->stringValue); - } - return false; + QScriptIsolate api(d->engine()); + return d->toBool(); } /*! - \since 4.5 - - Returns the boolean value of this QScriptValue, using the conversion - rules described in \l{ECMA-262} section 9.2, "ToBoolean". + Returns the integer value of this QScriptValue, using the conversion + rules described in \l{ECMA-262} section 9.4, "ToInteger". Note that if this QScriptValue is an object, calling this function has side effects on the script engine, since the engine will call @@ -1038,28 +526,13 @@ bool QScriptValue::toBoolean() const attempt to convert the object to a primitive value (possibly resulting in an uncaught script exception). - \sa isBool() + \sa toNumber() */ -bool QScriptValue::toBool() const +qsreal QScriptValue::toInteger() const { Q_D(const QScriptValue); - if (!d) - return false; - switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: { - if (d->engine) { - QScript::APIShim shim(d->engine); - return QScriptEnginePrivate::toBool(d->engine->currentFrame, d->jscValue); - } else { - return QScriptEnginePrivate::toBool(0, d->jscValue); - } - } - case QScriptValuePrivate::Number: - return QScript::ToBool(d->numberValue); - case QScriptValuePrivate::String: - return QScript::ToBool(d->stringValue); - } - return false; + QScriptIsolate api(d->engine()); + return d->toInteger(); } /*! @@ -1077,23 +550,8 @@ bool QScriptValue::toBool() const qint32 QScriptValue::toInt32() const { Q_D(const QScriptValue); - if (!d) - return 0; - switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: { - if (d->engine) { - QScript::APIShim shim(d->engine); - return QScriptEnginePrivate::toInt32(d->engine->currentFrame, d->jscValue); - } else { - return QScriptEnginePrivate::toInt32(0, d->jscValue); - } - } - case QScriptValuePrivate::Number: - return QScript::ToInt32(d->numberValue); - case QScriptValuePrivate::String: - return QScript::ToInt32(d->stringValue); - } - return 0; + QScriptIsolate api(d->engine()); + return d->toInt32(); } /*! @@ -1111,23 +569,8 @@ qint32 QScriptValue::toInt32() const quint32 QScriptValue::toUInt32() const { Q_D(const QScriptValue); - if (!d) - return 0; - switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: { - if (d->engine) { - QScript::APIShim shim(d->engine); - return QScriptEnginePrivate::toUInt32(d->engine->currentFrame, d->jscValue); - } else { - return QScriptEnginePrivate::toUInt32(0, d->jscValue); - } - } - case QScriptValuePrivate::Number: - return QScript::ToUInt32(d->numberValue); - case QScriptValuePrivate::String: - return QScript::ToUInt32(d->stringValue); - } - return 0; + QScriptIsolate api(d->engine()); + return d->toUInt32(); } /*! @@ -1145,57 +588,20 @@ quint32 QScriptValue::toUInt32() const quint16 QScriptValue::toUInt16() const { Q_D(const QScriptValue); - if (!d) - return 0; - switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: { - if (d->engine) { - QScript::APIShim shim(d->engine); - return QScriptEnginePrivate::toUInt16(d->engine->currentFrame, d->jscValue); - } else { - return QScriptEnginePrivate::toUInt16(0, d->jscValue); - } - } - case QScriptValuePrivate::Number: - return QScript::ToUInt16(d->numberValue); - case QScriptValuePrivate::String: - return QScript::ToUInt16(d->stringValue); - } - return 0; + QScriptIsolate api(d->engine()); + return d->toUInt16(); } /*! - Returns the integer value of this QScriptValue, using the conversion - rules described in \l{ECMA-262} section 9.4, "ToInteger". - - Note that if this QScriptValue is an object, calling this function - has side effects on the script engine, since the engine will call - the object's valueOf() function (and possibly toString()) in an - attempt to convert the object to a primitive value (possibly - resulting in an uncaught script exception). + \obsolete - \sa toNumber() + This function is obsolete; use QScriptEngine::toObject() instead. */ -qsreal QScriptValue::toInteger() const +QScriptValue QScriptValue::toObject() const { Q_D(const QScriptValue); - if (!d) - return 0; - switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: { - if (d->engine) { - QScript::APIShim shim(d->engine); - return QScriptEnginePrivate::toInteger(d->engine->currentFrame, d->jscValue); - } else { - return QScriptEnginePrivate::toInteger(0, d->jscValue); - } - } - case QScriptValuePrivate::Number: - return QScript::ToInteger(d->numberValue); - case QScriptValuePrivate::String: - return QScript::ToInteger(d->stringValue); - } - return 0; + QScriptIsolate api(d->engine()); + return QScriptValuePrivate::get(d->toObject()); } /*! @@ -1223,751 +629,522 @@ qsreal QScriptValue::toInteger() const QVariant QScriptValue::toVariant() const { Q_D(const QScriptValue); - if (!d) - return QVariant(); - switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: { - if (d->engine) { - QScript::APIShim shim(d->engine); - return QScriptEnginePrivate::toVariant(d->engine->currentFrame, d->jscValue); - } else { - return QScriptEnginePrivate::toVariant(0, d->jscValue); - } - } - case QScriptValuePrivate::Number: - return QVariant(d->numberValue); - case QScriptValuePrivate::String: - return QVariant(d->stringValue); - } - return QVariant(); + QScriptIsolate api(d->engine()); + QScriptDeclarativeClass *cls = QScriptDeclarativeClassObject::declarativeClass(d); + if (cls) + return cls->toVariant(QScriptDeclarativeClassObject::object(d)); + return d->toVariant(); } + /*! - \obsolete + Calls this QScriptValue as a function, using \a thisObject as + the `this' object in the function call, and passing \a args + as arguments to the function. Returns the value returned from + the function. - This function is obsolete; use QScriptEngine::toObject() instead. + If this QScriptValue is not a function, call() does nothing + and returns an invalid QScriptValue. + + Note that if \a thisObject is not an object, the global object + (see \l{QScriptEngine::globalObject()}) will be used as the + `this' object. + + Calling call() can cause an exception to occur in the script engine; + in that case, call() returns the value that was thrown (typically an + \c{Error} object). You can call + QScriptEngine::hasUncaughtException() to determine if an exception + occurred. + + \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 2 + + \sa construct() */ -QScriptValue QScriptValue::toObject() const +QScriptValue QScriptValue::call(const QScriptValue& thisObject, const QScriptValueList& args) { - Q_D(const QScriptValue); - if (!d || !d->engine) - return QScriptValue(); - return engine()->toObject(*this); + Q_D(QScriptValue); + QScriptIsolate api(d->engine()); + return d->call(QScriptValuePrivate::get(thisObject), args); } /*! - Returns a QDateTime representation of this value, in local time. - If this QScriptValue is not a date, or the value of the date is NaN - (Not-a-Number), an invalid QDateTime is returned. + Calls this QScriptValue as a function, using \a thisObject as + the `this' object in the function call, and passing \a arguments + as arguments to the function. Returns the value returned from + the function. - \sa isDate() + If this QScriptValue is not a function, call() does nothing + and returns an invalid QScriptValue. + + \a arguments can be an arguments object, an array, null or + undefined; any other type will cause a TypeError to be thrown. + + Note that if \a thisObject is not an object, the global object + (see \l{QScriptEngine::globalObject()}) will be used as the + `this' object. + + One common usage of this function is to forward native function + calls to another function: + + \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 3 + + \sa construct(), QScriptContext::argumentsObject() */ -QDateTime QScriptValue::toDateTime() const +QScriptValue QScriptValue::call(const QScriptValue &thisObject, const QScriptValue &arguments) { - Q_D(const QScriptValue); - if (!d || !d->engine) - return QDateTime(); - QScript::APIShim shim(d->engine); - return QScriptEnginePrivate::toDateTime(d->engine->currentFrame, d->jscValue); + Q_D(QScriptValue); + QScriptIsolate api(d->engine()); + return d->call(QScriptValuePrivate::get(thisObject), arguments); } -#ifndef QT_NO_REGEXP /*! - Returns the QRegExp representation of this value. - If this QScriptValue is not a regular expression, an empty - QRegExp is returned. + Creates a new \c{Object} and calls this QScriptValue as a + constructor, using the created object as the `this' object and + passing \a args as arguments. If the return value from the + constructor call is an object, then that object is returned; + otherwise the default constructed object is returned. - \sa isRegExp() + If this QScriptValue is not a function, construct() does nothing + and returns an invalid QScriptValue. + + Calling construct() can cause an exception to occur in the script + engine; in that case, construct() returns the value that was thrown + (typically an \c{Error} object). You can call + QScriptEngine::hasUncaughtException() to determine if an exception + occurred. + + \sa call(), QScriptEngine::newObject() */ -QRegExp QScriptValue::toRegExp() const +QScriptValue QScriptValue::construct(const QScriptValueList &args) { - Q_D(const QScriptValue); - if (!d || !d->engine) - return QRegExp(); - QScript::APIShim shim(d->engine); - return QScriptEnginePrivate::toRegExp(d->engine->currentFrame, d->jscValue); + Q_D(QScriptValue); + QScriptIsolate api(d->engine()); + return QScriptValuePrivate::get(d->construct(args)); } -#endif // QT_NO_REGEXP /*! - If this QScriptValue is a QObject, returns the QObject pointer - that the QScriptValue represents; otherwise, returns 0. + Creates a new \c{Object} and calls this QScriptValue as a + constructor, using the created object as the `this' object and + passing \a arguments as arguments. If the return value from the + constructor call is an object, then that object is returned; + otherwise the default constructed object is returned. + + If this QScriptValue is not a function, construct() does nothing + and returns an invalid QScriptValue. - If the QObject that this QScriptValue wraps has been deleted, - this function returns 0 (i.e. it is possible for toQObject() - to return 0 even when isQObject() returns true). + \a arguments can be an arguments object, an array, null or + undefined. Any other type will cause a TypeError to be thrown. - \sa isQObject() + \sa call(), QScriptEngine::newObject(), QScriptContext::argumentsObject() */ -QObject *QScriptValue::toQObject() const +QScriptValue QScriptValue::construct(const QScriptValue &arguments) { - Q_D(const QScriptValue); - if (!d || !d->engine) - return 0; - QScript::APIShim shim(d->engine); - return QScriptEnginePrivate::toQObject(d->engine->currentFrame, d->jscValue); + Q_D(QScriptValue); + QScriptIsolate api(d->engine()); + return QScriptValuePrivate::get(d->construct(arguments)); } -/*! - If this QScriptValue is a QMetaObject, returns the QMetaObject pointer - that the QScriptValue represents; otherwise, returns 0. - \sa isQMetaObject() +/*! + Returns the QScriptEngine that created this QScriptValue, + or 0 if this QScriptValue is invalid or the value is not + associated with a particular engine. */ -const QMetaObject *QScriptValue::toQMetaObject() const +QScriptEngine* QScriptValue::engine() const { Q_D(const QScriptValue); - if (!d || !d->engine) - return 0; - QScript::APIShim shim(d->engine); - return QScriptEnginePrivate::toQMetaObject(d->engine->currentFrame, d->jscValue); + QScriptIsolate api(d->engine()); + QScriptEnginePrivate* engine = d->engine(); + if (engine) + return QScriptEnginePrivate::get(engine); + return 0; } /*! - 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. + If this QScriptValue is an object, returns the internal prototype + (\c{__proto__} property) of this object; otherwise returns an + invalid QScriptValue. - \sa property() + \sa setPrototype(), isObject() */ - -void QScriptValue::setProperty(const QString &name, const QScriptValue &value, - const PropertyFlags &flags) +QScriptValue QScriptValue::prototype() const { - Q_D(QScriptValue); - if (!d || !d->isObject()) - return; - QScript::APIShim shim(d->engine); - QScriptEnginePrivate *valueEngine = QScriptValuePrivate::getEngine(value); - if (valueEngine && (valueEngine != d->engine)) { - qWarning("QScriptValue::setProperty(%s) failed: " - "cannot set value created in a different engine", - qPrintable(name)); - return; - } - JSC::JSValue jsValue = d->engine->scriptValueToJSCValue(value); - d->setProperty(name, jsValue, flags); + Q_D(const QScriptValue); + QScriptIsolate api(d->engine()); + return QScriptValuePrivate::get(d->prototype()); } /*! - Returns the value of this QScriptValue's property with the given \a name, - using the given \a mode to resolve the property. - - If no such property exists, an invalid QScriptValue is returned. + If this QScriptValue is an object, sets the internal prototype + (\c{__proto__} property) of this object to be \a prototype; + otherwise does nothing. - If the property is implemented using a getter function (i.e. has the - PropertyGetter flag set), calling property() has side-effects on the - script engine, since the getter function will be called (possibly - resulting in an uncaught script exception). If an exception - occurred, property() returns the value that was thrown (typically - an \c{Error} object). + The internal prototype should not be confused with the public + property with name "prototype"; the public prototype is usually + only set on functions that act as constructors. - \sa setProperty(), propertyFlags(), QScriptValueIterator + \sa prototype(), isObject() */ -QScriptValue QScriptValue::property(const QString &name, - const ResolveFlags &mode) const +void QScriptValue::setPrototype(const QScriptValue& prototype) { - Q_D(const QScriptValue); - if (!d || !d->isObject()) - return QScriptValue(); - QScript::APIShim shim(d->engine); - return d->engine->scriptValueFromJSCValue(d->property(name, mode)); + Q_D(QScriptValue); + QScriptIsolate api(d->engine()); + d->setPrototype(QScriptValuePrivate::get(prototype)); } /*! - \overload - - Returns the property at the given \a arrayIndex, using the given \a - mode to resolve the property. - - This function is provided for convenience and performance when - working with array objects. + Assigns the \a other value to this QScriptValue. - If this QScriptValue is not an Array object, this function behaves - as if property() was called with the string representation of \a - arrayIndex. + Note that if \a other is an object (isObject() returns true), + only a reference to the underlying object will be assigned; + the object itself will not be copied. */ -QScriptValue QScriptValue::property(quint32 arrayIndex, - const ResolveFlags &mode) const +QScriptValue& QScriptValue::operator=(const QScriptValue& other) { - Q_D(const QScriptValue); - if (!d || !d->isObject()) - return QScriptValue(); - QScript::APIShim shim(d->engine); - return d->engine->scriptValueFromJSCValue(d->property(arrayIndex, mode)); + d_ptr = other.d_ptr; + return *this; } /*! - \overload + Returns true if this QScriptValue is equal to \a other, otherwise + returns false. The comparison follows the behavior described in + \l{ECMA-262} section 11.9.3, "The Abstract Equality Comparison + Algorithm". - Sets the property at the given \a arrayIndex to the given \a value. + This function can return true even if the type of this QScriptValue + is different from the type of the \a other value; i.e. the + comparison is not strict. For example, comparing the number 9 to + the string "9" returns true; comparing an undefined value to a null + value returns true; comparing a \c{Number} object whose primitive + value is 6 to a \c{String} object whose primitive value is "6" + returns true; and comparing the number 1 to the boolean value + \c{true} returns true. If you want to perform a comparison + without such implicit value conversion, use strictlyEquals(). - This function is provided for convenience and performance when - working with array objects. + Note that if this QScriptValue or the \a other value are objects, + calling this function has side effects on the script engine, since + the engine will call the object's valueOf() function (and possibly + toString()) in an attempt to convert the object to a primitive value + (possibly resulting in an uncaught script exception). - If this QScriptValue is not an Array object, this function behaves - as if setProperty() was called with the string representation of \a - arrayIndex. + \sa strictlyEquals(), lessThan() */ -void QScriptValue::setProperty(quint32 arrayIndex, const QScriptValue &value, - const PropertyFlags &flags) +bool QScriptValue::equals(const QScriptValue& other) const { - Q_D(QScriptValue); - if (!d || !d->isObject()) - return; - if (QScriptValuePrivate::getEngine(value) - && (QScriptValuePrivate::getEngine(value) != d->engine)) { - qWarning("QScriptValue::setProperty() failed: " - "cannot set value created in a different engine"); - return; - } - QScript::APIShim shim(d->engine); - JSC::JSValue jsValue = d->engine->scriptValueToJSCValue(value); - d->setProperty(arrayIndex, jsValue, flags); + Q_D(const QScriptValue); + QScriptValuePrivate* otherValue = QScriptValuePrivate::get(other); + QScriptIsolate api(d->engine() ? d->engine() : otherValue->engine()); + return d_ptr->equals(otherValue); } /*! - \since 4.4 + Returns true if this QScriptValue is equal to \a other using strict + comparison (no conversion), otherwise returns false. The comparison + follows the behavior described in \l{ECMA-262} section 11.9.6, "The + Strict Equality Comparison Algorithm". - Returns the value of this QScriptValue's property with the given \a name, - using the given \a mode to resolve the property. + If the type of this QScriptValue is different from the type of the + \a other value, this function returns false. If the types are equal, + the result depends on the type, as shown in the following table: - 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. + \table + \header \o Type \o Result + \row \o Undefined \o true + \row \o Null \o true + \row \o Boolean \o true if both values are true, false otherwise + \row \o Number \o false if either value is NaN (Not-a-Number); true if values are equal, false otherwise + \row \o String \o true if both values are exactly the same sequence of characters, false otherwise + \row \o Object \o true if both values refer to the same object, false otherwise + \endtable - \sa QScriptEngine::toStringHandle(), setProperty() + \sa equals() */ -QScriptValue QScriptValue::property(const QScriptString &name, - const ResolveFlags &mode) const +bool QScriptValue::strictlyEquals(const QScriptValue& other) const { Q_D(const QScriptValue); - if (!d || !d->isObject() || !QScriptStringPrivate::isValid(name)) - return QScriptValue(); - QScript::APIShim shim(d->engine); - return d->engine->scriptValueFromJSCValue(d->property(name.d_ptr->identifier, mode)); + QScriptValuePrivate* o = QScriptValuePrivate::get(other); + QScriptIsolate api(d->engine() ? d->engine() : o->engine()); + return d_ptr->strictlyEquals(o); } /*! - \since 4.4 - - 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. + Returns true if this QScriptValue is less than \a other, otherwise + returns false. The comparison follows the behavior described in + \l{ECMA-262} section 11.8.5, "The Abstract Relational Comparison + Algorithm". - 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. + Note that if this QScriptValue or the \a other value are objects, + calling this function has side effects on the script engine, since + the engine will call the object's valueOf() function (and possibly + toString()) in an attempt to convert the object to a primitive value + (possibly resulting in an uncaught script exception). - \sa QScriptEngine::toStringHandle() + \sa equals() */ -void QScriptValue::setProperty(const QScriptString &name, - const QScriptValue &value, - const PropertyFlags &flags) +bool QScriptValue::lessThan(const QScriptValue &other) const { - Q_D(QScriptValue); - if (!d || !d->isObject() || !QScriptStringPrivate::isValid(name)) - return; - QScriptEnginePrivate *valueEngine = QScriptValuePrivate::getEngine(value); - if (valueEngine && (valueEngine != d->engine)) { - qWarning("QScriptValue::setProperty(%s) failed: " - "cannot set value created in a different engine", - qPrintable(name.toString())); - return; - } - QScript::APIShim shim(d->engine); - JSC::JSValue jsValue = d->engine->scriptValueToJSCValue(value); - d->setProperty(name.d_ptr->identifier, jsValue, flags); + Q_D(const QScriptValue); + QScriptValuePrivate *o = QScriptValuePrivate::get(other); + QScriptIsolate api(d->engine() ? d->engine() : o->engine()); + return d->lessThan(o); } /*! - Returns the flags of the property with the given \a name, using the - given \a mode to resolve the property. + Returns true if this QScriptValue is an instance of + \a other; otherwise returns false. - \sa property() + This QScriptValue is considered to be an instance of \a other if + \a other is a function and the value of the \c{prototype} + property of \a other is in the prototype chain of this + QScriptValue. */ -QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QString &name, - const ResolveFlags &mode) const +bool QScriptValue::instanceOf(const QScriptValue &other) const { Q_D(const QScriptValue); - if (!d || !d->isObject()) - return 0; - QScript::APIShim shim(d->engine); - JSC::ExecState *exec = d->engine->currentFrame; - return d->propertyFlags(JSC::Identifier(exec, name), mode); - + QScriptIsolate api(d->engine()); + return d->instanceOf(QScriptValuePrivate::get(other)); } /*! - \since 4.4 + Returns the value of this QScriptValue's property with the given \a name, + using the given \a mode to resolve the property. - Returns the flags of the property with the given \a name, using the - given \a mode to resolve the property. + If no such property exists, an invalid QScriptValue is returned. - \sa property() + If the property is implemented using a getter function (i.e. has the + PropertyGetter flag set), calling property() has side-effects on the + script engine, since the getter function will be called (possibly + resulting in an uncaught script exception). If an exception + occurred, property() returns the value that was thrown (typically + an \c{Error} object). + + \sa setProperty(), propertyFlags(), QScriptValueIterator */ -QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QScriptString &name, - const ResolveFlags &mode) const +QScriptValue QScriptValue::property(const QString& name, const ResolveFlags& mode) const { Q_D(const QScriptValue); - if (!d || !d->isObject() || !QScriptStringPrivate::isValid(name)) - return 0; - return d->propertyFlags(name.d_ptr->identifier, mode); + QScriptIsolate api(d->engine()); + return QScriptValuePrivate::get(d->property(name, mode)); } /*! - Calls this QScriptValue as a function, using \a thisObject as - the `this' object in the function call, and passing \a args - as arguments to the function. Returns the value returned from - the function. - - If this QScriptValue is not a function, call() does nothing - and returns an invalid QScriptValue. - - Note that if \a thisObject is not an object, the global object - (see \l{QScriptEngine::globalObject()}) will be used as the - `this' object. + \overload - Calling call() can cause an exception to occur in the script engine; - in that case, call() returns the value that was thrown (typically an - \c{Error} object). You can call - QScriptEngine::hasUncaughtException() to determine if an exception - occurred. + Returns the value of this QScriptValue's property with the given \a name, + using the given \a mode to resolve the property. - \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 2 + 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 construct() + \sa QScriptEngine::toStringHandle(), setProperty() */ -QScriptValue QScriptValue::call(const QScriptValue &thisObject, - const QScriptValueList &args) +QScriptValue QScriptValue::property(const QScriptString& name, const ResolveFlags& mode) const { Q_D(const QScriptValue); - if (!d || !d->isObject()) - return QScriptValue(); - QScript::APIShim shim(d->engine); - JSC::JSValue callee = d->jscValue; - JSC::CallData callData; - JSC::CallType callType = callee.getCallData(callData); - if (callType == JSC::CallTypeNone) - return QScriptValue(); - - if (QScriptValuePrivate::getEngine(thisObject) - && (QScriptValuePrivate::getEngine(thisObject) != d->engine)) { - qWarning("QScriptValue::call() failed: " - "cannot call function with thisObject created in " - "a different engine"); - return QScriptValue(); - } - - JSC::ExecState *exec = d->engine->currentFrame; - - JSC::JSValue jscThisObject = d->engine->scriptValueToJSCValue(thisObject); - if (!jscThisObject || !jscThisObject.isObject()) - jscThisObject = d->engine->globalObject(); - - QVarLengthArray<JSC::JSValue, 8> argsVector(args.size()); - for (int i = 0; i < args.size(); ++i) { - const QScriptValue &arg = args.at(i); - if (!arg.isValid()) { - argsVector[i] = JSC::jsUndefined(); - } else if (QScriptValuePrivate::getEngine(arg) - && (QScriptValuePrivate::getEngine(arg) != d->engine)) { - qWarning("QScriptValue::call() failed: " - "cannot call function with argument created in " - "a different engine"); - return QScriptValue(); - } else { - argsVector[i] = d->engine->scriptValueToJSCValue(arg); - } - } - JSC::ArgList jscArgs(argsVector.data(), argsVector.size()); - - JSC::JSValue savedException; - QScriptEnginePrivate::saveException(exec, &savedException); - JSC::JSValue result = JSC::call(exec, callee, callType, callData, jscThisObject, jscArgs); - if (exec->hadException()) { - result = exec->exception(); - } else { - QScriptEnginePrivate::restoreException(exec, savedException); - } - return d->engine->scriptValueFromJSCValue(result); + QScriptIsolate api(d->engine()); + return QScriptValuePrivate::get(d->property(QScriptStringPrivate::get(name), mode)); } /*! - Calls this QScriptValue as a function, using \a thisObject as - the `this' object in the function call, and passing \a arguments - as arguments to the function. Returns the value returned from - the function. - - If this QScriptValue is not a function, call() does nothing - and returns an invalid QScriptValue. - - \a arguments can be an arguments object, an array, null or - undefined; any other type will cause a TypeError to be thrown. - - Note that if \a thisObject is not an object, the global object - (see \l{QScriptEngine::globalObject()}) will be used as the - `this' object. + \overload - One common usage of this function is to forward native function - calls to another function: + Returns the property at the given \a arrayIndex, using the given \a + mode to resolve the property. - \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 3 + This function is provided for convenience and performance when + working with array objects. - \sa construct(), QScriptContext::argumentsObject() + If this QScriptValue is not an Array object, this function behaves + as if property() was called with the string representation of \a + arrayIndex. */ -QScriptValue QScriptValue::call(const QScriptValue &thisObject, - const QScriptValue &arguments) +QScriptValue QScriptValue::property(quint32 arrayIndex, const ResolveFlags& mode) const { - Q_D(QScriptValue); - if (!d || !d->isObject()) - return QScriptValue(); - QScript::APIShim shim(d->engine); - JSC::JSValue callee = d->jscValue; - JSC::CallData callData; - JSC::CallType callType = callee.getCallData(callData); - if (callType == JSC::CallTypeNone) - return QScriptValue(); - - if (QScriptValuePrivate::getEngine(thisObject) - && (QScriptValuePrivate::getEngine(thisObject) != d->engine)) { - qWarning("QScriptValue::call() failed: " - "cannot call function with thisObject created in " - "a different engine"); - return QScriptValue(); - } - - JSC::ExecState *exec = d->engine->currentFrame; + Q_D(const QScriptValue); + QScriptIsolate api(d->engine()); + return QScriptValuePrivate::get(d->property(arrayIndex, mode)); +} - JSC::JSValue jscThisObject = d->engine->scriptValueToJSCValue(thisObject); - if (!jscThisObject || !jscThisObject.isObject()) - jscThisObject = d->engine->globalObject(); +/*! + Sets the value of this QScriptValue's property with the given \a name to + the given \a value. - JSC::JSValue array = d->engine->scriptValueToJSCValue(arguments); - // copied from runtime/FunctionPrototype.cpp, functionProtoFuncApply() - JSC::MarkedArgumentBuffer applyArgs; - if (!array.isUndefinedOrNull()) { - if (!array.isObject()) { - return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array")); - } - if (JSC::asObject(array)->classInfo() == &JSC::Arguments::info) - JSC::asArguments(array)->fillArgList(exec, applyArgs); - else if (JSC::isJSArray(&exec->globalData(), array)) - JSC::asArray(array)->fillArgList(exec, applyArgs); - else if (JSC::asObject(array)->inherits(&JSC::JSArray::info)) { - unsigned length = JSC::asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec); - for (unsigned i = 0; i < length; ++i) - applyArgs.append(JSC::asArray(array)->get(exec, i)); - } else { - return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array")); - } - } + If this QScriptValue is not an object, this function does nothing. - JSC::JSValue savedException; - QScriptEnginePrivate::saveException(exec, &savedException); - JSC::JSValue result = JSC::call(exec, callee, callType, callData, jscThisObject, applyArgs); - if (exec->hadException()) { - result = exec->exception(); - } else { - QScriptEnginePrivate::restoreException(exec, savedException); - } - return d->engine->scriptValueFromJSCValue(result); -} + 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. -/*! - Creates a new \c{Object} and calls this QScriptValue as a - constructor, using the created object as the `this' object and - passing \a args as arguments. If the return value from the - constructor call is an object, then that object is returned; - otherwise the default constructed object is returned. + If \a value is invalid, the property is removed. - If this QScriptValue is not a function, construct() does nothing - and returns an invalid QScriptValue. + 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). - Calling construct() can cause an exception to occur in the script - engine; in that case, construct() returns the value that was thrown - (typically an \c{Error} object). You can call - QScriptEngine::hasUncaughtException() to determine if an exception - occurred. + 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 call(), QScriptEngine::newObject() + \sa property() */ -QScriptValue QScriptValue::construct(const QScriptValueList &args) +void QScriptValue::setProperty(const QString& name, const QScriptValue& value, const PropertyFlags& flags) { - Q_D(const QScriptValue); - if (!d || !d->isObject()) - return QScriptValue(); - QScript::APIShim shim(d->engine); - JSC::JSValue callee = d->jscValue; - JSC::ConstructData constructData; - JSC::ConstructType constructType = callee.getConstructData(constructData); - if (constructType == JSC::ConstructTypeNone) - return QScriptValue(); - - JSC::ExecState *exec = d->engine->currentFrame; - - QVarLengthArray<JSC::JSValue, 8> argsVector(args.size()); - for (int i = 0; i < args.size(); ++i) { - QScriptValue arg = args.at(i); - if (QScriptValuePrivate::getEngine(arg) != d->engine && QScriptValuePrivate::getEngine(arg)) { - qWarning("QScriptValue::construct() failed: " - "cannot construct function with argument created in " - "a different engine"); - return QScriptValue(); - } - if (!arg.isValid()) - argsVector[i] = JSC::jsUndefined(); - else - argsVector[i] = d->engine->scriptValueToJSCValue(args.at(i)); - } - - JSC::ArgList jscArgs(argsVector.data(), argsVector.size()); - - JSC::JSValue savedException; - QScriptEnginePrivate::saveException(exec, &savedException); - JSC::JSValue result; - JSC::JSObject *newObject = JSC::construct(exec, callee, constructType, constructData, jscArgs); - if (exec->hadException()) { - result = exec->exception(); - } else { - result = newObject; - QScriptEnginePrivate::restoreException(exec, savedException); - } - return d->engine->scriptValueFromJSCValue(result); + Q_D(QScriptValue); + QScriptIsolate api(d->engine()); + d->setProperty(name, QScriptValuePrivate::get(value), QScriptConverter::toPropertyAttributes(flags)); } /*! - Creates a new \c{Object} and calls this QScriptValue as a - constructor, using the created object as the `this' object and - passing \a arguments as arguments. If the return value from the - constructor call is an object, then that object is returned; - otherwise the default constructed object is returned. + \overload - If this QScriptValue is not a function, construct() does nothing - and returns an invalid QScriptValue. + Sets the property at the given \a arrayIndex to the given \a value. - \a arguments can be an arguments object, an array, null or - undefined. Any other type will cause a TypeError to be thrown. + This function is provided for convenience and performance when + working with array objects. - \sa call(), QScriptEngine::newObject(), QScriptContext::argumentsObject() + If this QScriptValue is not an Array object, this function behaves + as if setProperty() was called with the string representation of \a + arrayIndex. */ -QScriptValue QScriptValue::construct(const QScriptValue &arguments) +void QScriptValue::setProperty(quint32 arrayIndex, const QScriptValue& value, const PropertyFlags& flags) { Q_D(QScriptValue); - if (!d || !d->isObject()) - return QScriptValue(); - QScript::APIShim shim(d->engine); - JSC::JSValue callee = d->jscValue; - JSC::ConstructData constructData; - JSC::ConstructType constructType = callee.getConstructData(constructData); - if (constructType == JSC::ConstructTypeNone) - return QScriptValue(); - - JSC::ExecState *exec = d->engine->currentFrame; - - if (QScriptValuePrivate::getEngine(arguments) != d->engine && QScriptValuePrivate::getEngine(arguments)) { - qWarning("QScriptValue::construct() failed: " - "cannot construct function with argument created in " - "a different engine"); - return QScriptValue(); - } - JSC::JSValue array = d->engine->scriptValueToJSCValue(arguments); - // copied from runtime/FunctionPrototype.cpp, functionProtoFuncApply() - JSC::MarkedArgumentBuffer applyArgs; - if (!array.isUndefinedOrNull()) { - if (!array.isObject()) { - return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array")); - } - if (JSC::asObject(array)->classInfo() == &JSC::Arguments::info) - JSC::asArguments(array)->fillArgList(exec, applyArgs); - else if (JSC::isJSArray(&exec->globalData(), array)) - JSC::asArray(array)->fillArgList(exec, applyArgs); - else if (JSC::asObject(array)->inherits(&JSC::JSArray::info)) { - unsigned length = JSC::asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec); - for (unsigned i = 0; i < length; ++i) - applyArgs.append(JSC::asArray(array)->get(exec, i)); - } else { - return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array")); - } - } - - JSC::JSValue savedException; - QScriptEnginePrivate::saveException(exec, &savedException); - JSC::JSValue result; - JSC::JSObject *newObject = JSC::construct(exec, callee, constructType, constructData, applyArgs); - if (exec->hadException()) { - result = exec->exception(); - } else { - result = newObject; - QScriptEnginePrivate::restoreException(exec, savedException); - } - return d->engine->scriptValueFromJSCValue(result); + QScriptIsolate api(d->engine()); + d->setProperty(arrayIndex, QScriptValuePrivate::get(value), QScriptConverter::toPropertyAttributes(flags)); } /*! - Returns the QScriptEngine that created this QScriptValue, - or 0 if this QScriptValue is invalid or the value is not - associated with a particular engine. -*/ -QScriptEngine *QScriptValue::engine() const -{ - Q_D(const QScriptValue); - if (!d) - return 0; - return QScriptEnginePrivate::get(d->engine); -} + 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. -/*! - \obsolete + 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. - Use isBool() instead. + \sa QScriptEngine::toStringHandle() */ -bool QScriptValue::isBoolean() const +void QScriptValue::setProperty(const QScriptString& name, const QScriptValue& value, const PropertyFlags& flags) { - Q_D(const QScriptValue); - return d && d->isJSC() && d->jscValue.isBoolean(); + Q_D(QScriptValue); + QScriptIsolate api(d->engine()); + d->setProperty(QScriptStringPrivate::get(name), QScriptValuePrivate::get(value), QScriptConverter::toPropertyAttributes(flags)); } /*! - \since 4.5 - - Returns true if this QScriptValue is of the primitive type Boolean; - otherwise returns false. + Returns the flags of the property with the given \a name, using the + given \a mode to resolve the property. - \sa toBool() + \sa property() */ -bool QScriptValue::isBool() const +QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QString& name, const ResolveFlags& mode) const { Q_D(const QScriptValue); - return d && d->isJSC() && d->jscValue.isBoolean(); + QScriptIsolate api(d->engine()); + return d->propertyFlags(name, mode); } /*! - Returns true if this QScriptValue is of the primitive type Number; - otherwise returns false. + Returns the flags of the property with the given \a name, using the + given \a mode to resolve the property. - \sa toNumber() + \sa property() */ -bool QScriptValue::isNumber() const +QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QScriptString& name, const ResolveFlags& mode) const { Q_D(const QScriptValue); - if (!d) - return false; - switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: - return d->jscValue.isNumber(); - case QScriptValuePrivate::Number: - return true; - case QScriptValuePrivate::String: - return false; - } - return false; + QScriptIsolate api(d->engine()); + return d->propertyFlags(QScriptStringPrivate::get(name), mode); } /*! - Returns true if this QScriptValue is of the primitive type String; - otherwise returns false. - - \sa toString() -*/ -bool QScriptValue::isString() const + * If this QScriptValue is a QObject, returns the QObject pointer + * that the QScriptValue represents; otherwise, returns 0. + * + * If the QObject that this QScriptValue wraps has been deleted, + * this function returns 0 (i.e. it is possible for toQObject() + * to return 0 even when isQObject() returns true). + * + * \sa isQObject() + */ +QObject *QScriptValue::toQObject() const { Q_D(const QScriptValue); - if (!d) - return false; - switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: - return d->jscValue.isString(); - case QScriptValuePrivate::Number: - return false; - case QScriptValuePrivate::String: - return true; - } - return false; + QScriptIsolate api(d->engine()); + QScriptDeclarativeClass *cls = QScriptDeclarativeClassObject::declarativeClass(d); + if (cls) + return cls->toQObject(QScriptDeclarativeClassObject::object(d)); + return d->toQObject(); } /*! - Returns true if this QScriptValue is a function; otherwise returns - false. + If this QScriptValue is a QMetaObject, returns the QMetaObject pointer + that the QScriptValue represents; otherwise, returns 0. - \sa call() + \sa isQMetaObject() */ -bool QScriptValue::isFunction() const +const QMetaObject *QScriptValue::toQMetaObject() const { Q_D(const QScriptValue); - if (!d || !d->isJSC()) - return false; - return QScript::isFunction(d->jscValue); + QScriptIsolate api(d->engine()); + return d->toQMetaObject(); } /*! - Returns true if this QScriptValue is of the primitive type Null; - otherwise returns false. + Returns a QDateTime representation of this value, in local time. + If this QScriptValue is not a date, or the value of the date is NaN + (Not-a-Number), an invalid QDateTime is returned. - \sa QScriptEngine::nullValue() + \sa isDate() */ -bool QScriptValue::isNull() const +QDateTime QScriptValue::toDateTime() const { Q_D(const QScriptValue); - return d && d->isJSC() && d->jscValue.isNull(); + QScriptIsolate api(d->engine()); + return d->toDataTime(); } /*! - Returns true if this QScriptValue is of the primitive type Undefined; - otherwise returns false. + Returns the QRegExp representation of this value. + If this QScriptValue is not a regular expression, an empty + QRegExp is returned. - \sa QScriptEngine::undefinedValue() + \sa isRegExp() */ -bool QScriptValue::isUndefined() const +QRegExp QScriptValue::toRegExp() const { Q_D(const QScriptValue); - return d && d->isJSC() && d->jscValue.isUndefined(); + QScriptIsolate api(d->engine()); + return d->toRegExp(); } /*! - Returns true if this QScriptValue is of the Object type; otherwise - returns false. - - Note that function values, variant values, and QObject values are - objects, so this function returns true for such values. + Returns true if this QScriptValue is an object of the Date class; + otherwise returns false. - \sa toObject(), QScriptEngine::newObject() + \sa QScriptEngine::newDate() */ -bool QScriptValue::isObject() const +bool QScriptValue::isDate() const { Q_D(const QScriptValue); - return d && d->isObject(); + QScriptIsolate api(d->engine()); + return d->isDate(); } /*! - Returns true if this QScriptValue is a variant value; + Returns true if this QScriptValue is an object of the RegExp class; otherwise returns false. - \sa toVariant(), QScriptEngine::newVariant() + \sa QScriptEngine::newRegExp() */ -bool QScriptValue::isVariant() const +bool QScriptValue::isRegExp() const { Q_D(const QScriptValue); - if (!d || !d->isJSC()) - return false; - return QScriptEnginePrivate::isVariant(d->jscValue); + QScriptIsolate api(d->engine()); + return d->isRegExp(); } /*! @@ -1982,9 +1159,11 @@ bool QScriptValue::isVariant() const bool QScriptValue::isQObject() const { Q_D(const QScriptValue); - if (!d || !d->isJSC()) - return false; - return QScriptEnginePrivate::isQObject(d->jscValue); + QScriptIsolate api(d->engine()); + QScriptDeclarativeClass *cls = QScriptDeclarativeClassObject::declarativeClass(d); + if (cls) + return cls->isQObject(); + return d->isQObject(); } /*! @@ -1996,19 +1175,27 @@ bool QScriptValue::isQObject() const bool QScriptValue::isQMetaObject() const { Q_D(const QScriptValue); - if (!d || !d->isJSC()) - return false; - return QScriptEnginePrivate::isQMetaObject(d->jscValue); + QScriptIsolate api(d->engine()); + return d->isQMetaObject(); } /*! - Returns true if this QScriptValue is valid; otherwise returns - false. + \internal */ -bool QScriptValue::isValid() const +QScriptValue QScriptValue::scope() const { - Q_D(const QScriptValue); - return d && (!d->isJSC() || !!d->jscValue); + // FIXME can it be removed? + Q_UNIMPLEMENTED(); + return QScriptValue(); +} + +/*! + \internal +*/ +void QScriptValue::setScope(const QScriptValue &) +{ + // FIXME can it be removed? + Q_UNIMPLEMENTED(); } /*! @@ -2022,15 +1209,8 @@ bool QScriptValue::isValid() const QScriptValue QScriptValue::data() const { Q_D(const QScriptValue); - if (!d || !d->isObject()) - return QScriptValue(); - if (d->jscValue.inherits(&QScriptObject::info)) { - QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); - return d->engine->scriptValueFromJSCValue(scriptObject->data()); - } else { - // ### make hidden property - return property(QLatin1String("__qt_data__"), QScriptValue::ResolveLocal); - } + QScriptIsolate api(d->engine()); + return QScriptValuePrivate::get(d->data()); } /*! @@ -2043,26 +1223,11 @@ QScriptValue QScriptValue::data() const \sa QScriptEngine::reportAdditionalMemoryCost() */ -void QScriptValue::setData(const QScriptValue &data) +void QScriptValue::setData(const QScriptValue &value) { - Q_D(QScriptValue); - if (!d || !d->isObject()) - return; - QScript::APIShim shim(d->engine); - JSC::JSValue other = d->engine->scriptValueToJSCValue(data); - if (d->jscValue.inherits(&QScriptObject::info)) { - QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); - scriptObject->setData(other); - } else { - JSC::ExecState *exec = d->engine->currentFrame; - JSC::Identifier id = JSC::Identifier(exec, "__qt_data__"); - if (!data.isValid()) { - JSC::asObject(d->jscValue)->removeDirect(id); - } else { - // ### make hidden property - JSC::asObject(d->jscValue)->putDirect(id, other); - } - } + Q_D(const QScriptValue); + QScriptIsolate api(d->engine()); + d->setData(QScriptValuePrivate::get(value)); } /*! @@ -2076,13 +1241,8 @@ void QScriptValue::setData(const QScriptValue &data) QScriptClass *QScriptValue::scriptClass() const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info)) - return 0; - QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); - QScriptObjectDelegate *delegate = scriptObject->delegate(); - if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject)) - return 0; - return static_cast<QScript::ClassObjectDelegate*>(delegate)->scriptClass(); + QScriptIsolate api(d->engine()); + return QScriptClassPrivate::safeGet(d->scriptClass()); } /*! @@ -2098,29 +1258,59 @@ QScriptClass *QScriptValue::scriptClass() const \sa scriptClass(), setData() */ -void QScriptValue::setScriptClass(QScriptClass *scriptClass) +void QScriptValue::setScriptClass(QScriptClass *scriptclass) { Q_D(QScriptValue); - if (!d || !d->isObject()) - return; - if (!d->jscValue.inherits(&QScriptObject::info)) { - qWarning("QScriptValue::setScriptClass() failed: " - "cannot change class of non-QScriptObject"); + QScriptIsolate api(d->engine()); + d->setScriptClass(QScriptClassPrivate::safeGet(scriptclass)); +} + +/*! + \internal + Get script class if it exists + \note it can be null +*/ +QScriptClassPrivate* QScriptValuePrivate::scriptClass() const +{ + QScriptClassObject *data = QScriptClassObject::safeGet(this); + if (data) + return data->scriptClass(); + return 0; +} + +void QScriptValuePrivate::setScriptClass(QScriptClassPrivate *scriptclass) +{ + if (!isObject()) return; - } - QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); - if (!scriptClass) { - scriptObject->setDelegate(0); - } else { - QScriptObjectDelegate *delegate = scriptObject->delegate(); - if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject)) { - delegate = new QScript::ClassObjectDelegate(scriptClass); - scriptObject->setDelegate(delegate); + + v8::HandleScope scope; + // FIXME this algorithm is bad. It creates new value instead to add functionality to exiting one + // This code would fail + // engine.evaluate("a = new Object()"); + // QSV obj1 = engine.evaluate("a"); + // QSV obj2 = engine.evaluate("a"); + // obj1.setScriptClass(scriptclass); + // QVERIFY(obj1.strictlyEquals(obj2); + + QScriptClassObject *data = QScriptClassObject::safeGet(this); + if (data) { + data->setScriptClass(scriptclass); + if (!scriptclass) { + if (data->original().IsEmpty()) + data->setOriginal(v8::Object::New()); + reinitialize(engine(), data->original()); } - static_cast<QScript::ClassObjectDelegate*>(delegate)->setScriptClass(scriptClass); + return; } + if (!scriptclass) + return; + + v8::Handle<v8::Object> self = v8::Handle<v8::Object>::Cast(m_value); + v8::Handle<v8::Value> newObject = QScriptClassObject::newInstance(scriptclass, self, engine()); + reinitialize(engine(), newObject); } + /*! \internal @@ -2131,6 +1321,8 @@ void QScriptValue::setScriptClass(QScriptClass *scriptClass) */ qint64 QScriptValue::objectId() const { - return d_ptr?d_ptr->objectId():-1; + Q_D(const QScriptValue); + return d->objectId(); } + QT_END_NAMESPACE |