src/script/api/qscriptvalue.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
    27 #include "qscriptvalue_p.h"
    27 #include "qscriptvalue_p.h"
    28 #include "qscriptengine.h"
    28 #include "qscriptengine.h"
    29 #include "qscriptengine_p.h"
    29 #include "qscriptengine_p.h"
    30 #include "qscriptstring_p.h"
    30 #include "qscriptstring_p.h"
    31 
    31 
    32 #include "JSArray.h"
       
    33 #include "JSGlobalObject.h"
    32 #include "JSGlobalObject.h"
    34 #include "JSImmediate.h"
    33 #include "JSImmediate.h"
    35 #include "JSObject.h"
    34 #include "JSObject.h"
    36 #include "JSValue.h"
    35 #include "JSValue.h"
    37 #include "JSFunction.h"
    36 #include "JSFunction.h"
    38 #include "DateInstance.h"
       
    39 #include "ErrorInstance.h"
       
    40 #include "RegExpObject.h"
       
    41 #include "Identifier.h"
    37 #include "Identifier.h"
    42 #include "Operations.h"
    38 #include "Operations.h"
    43 #include "Arguments.h"
    39 #include "Arguments.h"
    44 
    40 
    45 #include <QtCore/qdatetime.h>
       
    46 #include <QtCore/qregexp.h>
       
    47 #include <QtCore/qvariant.h>
    41 #include <QtCore/qvariant.h>
    48 #include <QtCore/qvarlengtharray.h>
    42 #include <QtCore/qvarlengtharray.h>
    49 #include <QtCore/qnumeric.h>
    43 #include <QtCore/qnumeric.h>
    50 
       
    51 #include "utils/qscriptdate_p.h"
       
    52 #include "bridge/qscriptobject_p.h"
       
    53 #include "bridge/qscriptclassobject_p.h"
       
    54 #include "bridge/qscriptvariant_p.h"
       
    55 #include "bridge/qscriptqobject_p.h"
       
    56 #include "bridge/qscriptdeclarativeclass_p.h"
       
    57 #include "bridge/qscriptdeclarativeobject_p.h"
       
    58 
    44 
    59 /*!
    45 /*!
    60   \since 4.3
    46   \since 4.3
    61   \class QScriptValue
    47   \class QScriptValue
    62 
    48 
   178     \omitvalue ResolveScope Check the object's own properties first, then search the scope chain.
   164     \omitvalue ResolveScope Check the object's own properties first, then search the scope chain.
   179 
   165 
   180     \omitvalue ResolveFull Check the object's own properties first, then search the prototype chain, and finally search the scope chain.
   166     \omitvalue ResolveFull Check the object's own properties first, then search the prototype chain, and finally search the scope chain.
   181 */
   167 */
   182 
   168 
   183 // ### move
       
   184 
       
   185 #include <QtCore/qnumeric.h>
       
   186 #include <math.h>
       
   187 
       
   188 QT_BEGIN_NAMESPACE
   169 QT_BEGIN_NAMESPACE
   189 
       
   190 namespace QScript
       
   191 {
       
   192 
       
   193 static const qsreal D32 = 4294967296.0;
       
   194 
       
   195 qint32 ToInt32(qsreal n)
       
   196 {
       
   197     if (qIsNaN(n) || qIsInf(n) || (n == 0))
       
   198         return 0;
       
   199 
       
   200     qsreal sign = (n < 0) ? -1.0 : 1.0;
       
   201     qsreal abs_n = fabs(n);
       
   202 
       
   203     n = ::fmod(sign * ::floor(abs_n), D32);
       
   204     const double D31 = D32 / 2.0;
       
   205 
       
   206     if (sign == -1 && n < -D31)
       
   207         n += D32;
       
   208 
       
   209     else if (sign != -1 && n >= D31)
       
   210         n -= D32;
       
   211 
       
   212     return qint32 (n);
       
   213 }
       
   214 
       
   215 quint32 ToUint32(qsreal n)
       
   216 {
       
   217     if (qIsNaN(n) || qIsInf(n) || (n == 0))
       
   218         return 0;
       
   219 
       
   220     qsreal sign = (n < 0) ? -1.0 : 1.0;
       
   221     qsreal abs_n = fabs(n);
       
   222 
       
   223     n = ::fmod(sign * ::floor(abs_n), D32);
       
   224 
       
   225     if (n < 0)
       
   226         n += D32;
       
   227 
       
   228     return quint32 (n);
       
   229 }
       
   230 
       
   231 quint16 ToUint16(qsreal n)
       
   232 {
       
   233     static const qsreal D16 = 65536.0;
       
   234 
       
   235     if (qIsNaN(n) || qIsInf(n) || (n == 0))
       
   236         return 0;
       
   237 
       
   238     qsreal sign = (n < 0) ? -1.0 : 1.0;
       
   239     qsreal abs_n = fabs(n);
       
   240 
       
   241     n = ::fmod(sign * ::floor(abs_n), D16);
       
   242 
       
   243     if (n < 0)
       
   244         n += D16;
       
   245 
       
   246     return quint16 (n);
       
   247 }
       
   248 
       
   249 qsreal ToInteger(qsreal n)
       
   250 {
       
   251     if (qIsNaN(n))
       
   252         return 0;
       
   253 
       
   254     if (n == 0 || qIsInf(n))
       
   255         return n;
       
   256 
       
   257     int sign = n < 0 ? -1 : 1;
       
   258     return sign * ::floor(::fabs(n));
       
   259 }
       
   260 
       
   261 } // namespace QScript
       
   262 
       
   263 QScriptValue QScriptValuePrivate::propertyHelper(const JSC::Identifier &id, int resolveMode) const
       
   264 {
       
   265     JSC::JSValue result;
       
   266     if (!(resolveMode & QScriptValue::ResolvePrototype)) {
       
   267         // Look in the object's own properties
       
   268         JSC::ExecState *exec = engine->currentFrame;
       
   269         JSC::JSObject *object = JSC::asObject(jscValue);
       
   270         JSC::PropertySlot slot(object);
       
   271         if (object->getOwnPropertySlot(exec, id, slot))
       
   272             result = slot.getValue(exec, id);
       
   273     }
       
   274     if (!result && (resolveMode & QScriptValue::ResolveScope)) {
       
   275         // ### check if it's a function object and look in the scope chain
       
   276         QScriptValue scope = property(QString::fromLatin1("__qt_scope__"), QScriptValue::ResolveLocal);
       
   277         if (scope.isObject())
       
   278             result = engine->scriptValueToJSCValue(QScriptValuePrivate::get(scope)->property(id, resolveMode));
       
   279     }
       
   280     return engine->scriptValueFromJSCValue(result);
       
   281 }
       
   282 
       
   283 QScriptValue QScriptValuePrivate::propertyHelper(quint32 index, int resolveMode) const
       
   284 {
       
   285     JSC::JSValue result;
       
   286     if (!(resolveMode & QScriptValue::ResolvePrototype)) {
       
   287         // Look in the object's own properties
       
   288         JSC::ExecState *exec = engine->currentFrame;
       
   289         JSC::JSObject *object = JSC::asObject(jscValue);
       
   290         JSC::PropertySlot slot(object);
       
   291         if (object->getOwnPropertySlot(exec, index, slot))
       
   292             result = slot.getValue(exec, index);
       
   293     }
       
   294     return engine->scriptValueFromJSCValue(result);
       
   295 }
       
   296 
       
   297 void QScriptValuePrivate::setProperty(const JSC::Identifier &id, const QScriptValue &value,
       
   298                                       const QScriptValue::PropertyFlags &flags)
       
   299 {
       
   300     QScriptEnginePrivate *valueEngine = QScriptValuePrivate::getEngine(value);
       
   301     if (valueEngine && (valueEngine != engine)) {
       
   302         qWarning("QScriptValue::setProperty(%s) failed: "
       
   303                  "cannot set value created in a different engine",
       
   304                  qPrintable(QString(id.ustring())));
       
   305         return;
       
   306     }
       
   307     JSC::ExecState *exec = engine->currentFrame;
       
   308     JSC::JSValue jsValue = engine->scriptValueToJSCValue(value);
       
   309     JSC::JSObject *thisObject = JSC::asObject(jscValue);
       
   310     JSC::JSValue setter = thisObject->lookupSetter(exec, id);
       
   311     JSC::JSValue getter = thisObject->lookupGetter(exec, id);
       
   312     if ((flags & QScriptValue::PropertyGetter) || (flags & QScriptValue::PropertySetter)) {
       
   313         if (!jsValue) {
       
   314             // deleting getter/setter
       
   315             if ((flags & QScriptValue::PropertyGetter) && (flags & QScriptValue::PropertySetter)) {
       
   316                 // deleting both: just delete the property
       
   317                 thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false);
       
   318             } else if (flags & QScriptValue::PropertyGetter) {
       
   319                 // preserve setter, if there is one
       
   320                 thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false);
       
   321                 if (setter && setter.isObject())
       
   322                     thisObject->defineSetter(exec, id, JSC::asObject(setter));
       
   323             } else { // flags & QScriptValue::PropertySetter
       
   324                 // preserve getter, if there is one
       
   325                 thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false);
       
   326                 if (getter && getter.isObject())
       
   327                     thisObject->defineGetter(exec, id, JSC::asObject(getter));
       
   328             }
       
   329         } else {
       
   330             if (jsValue.isObject()) { // ### should check if it has callData()
       
   331                 // defining getter/setter
       
   332                 if (id == exec->propertyNames().underscoreProto) {
       
   333                     qWarning("QScriptValue::setProperty() failed: "
       
   334                              "cannot set getter or setter of native property `__proto__'");
       
   335                 } else {
       
   336                     if (flags & QScriptValue::PropertyGetter)
       
   337                         thisObject->defineGetter(exec, id, JSC::asObject(jsValue));
       
   338                     if (flags & QScriptValue::PropertySetter)
       
   339                         thisObject->defineSetter(exec, id, JSC::asObject(jsValue));
       
   340                 }
       
   341             } else {
       
   342                 qWarning("QScriptValue::setProperty(): getter/setter must be a function");
       
   343             }
       
   344         }
       
   345     } else {
       
   346         // setting the value
       
   347         if (getter && getter.isObject() && !(setter && setter.isObject())) {
       
   348             qWarning("QScriptValue::setProperty() failed: "
       
   349                      "property '%s' has a getter but no setter",
       
   350                      qPrintable(QString(id.ustring())));
       
   351             return;
       
   352         }
       
   353         if (!jsValue) {
       
   354             // ### check if it's a getter/setter property
       
   355             thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false);
       
   356         } else if (flags != QScriptValue::KeepExistingFlags) {
       
   357             if (thisObject->hasOwnProperty(exec, id))
       
   358                 thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false); // ### hmmm - can't we just update the attributes?
       
   359             unsigned attribs = 0;
       
   360             if (flags & QScriptValue::ReadOnly)
       
   361                 attribs |= JSC::ReadOnly;
       
   362             if (flags & QScriptValue::SkipInEnumeration)
       
   363                 attribs |= JSC::DontEnum;
       
   364             if (flags & QScriptValue::Undeletable)
       
   365                 attribs |= JSC::DontDelete;
       
   366             attribs |= flags & QScriptValue::UserRange;
       
   367             thisObject->putWithAttributes(exec, id, jsValue, attribs);
       
   368         } else {
       
   369             JSC::PutPropertySlot slot;
       
   370             thisObject->put(exec, id, jsValue, slot);
       
   371         }
       
   372     }
       
   373 }
       
   374 
       
   375 QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(const JSC::Identifier &id,
       
   376                                                                const QScriptValue::ResolveFlags &mode) const
       
   377 {
       
   378     JSC::ExecState *exec = engine->currentFrame;
       
   379     JSC::JSObject *object = JSC::asObject(jscValue);
       
   380     unsigned attribs = 0;
       
   381     JSC::PropertyDescriptor descriptor;
       
   382     if (object->getOwnPropertyDescriptor(exec, id, descriptor))
       
   383         attribs = descriptor.attributes();
       
   384     else if (!object->getPropertyAttributes(exec, id, attribs)) {
       
   385         if ((mode & QScriptValue::ResolvePrototype) && object->prototype() && object->prototype().isObject()) {
       
   386             QScriptValue proto = engine->scriptValueFromJSCValue(object->prototype());
       
   387             return QScriptValuePrivate::get(proto)->propertyFlags(id, mode);
       
   388         }
       
   389         return 0;
       
   390     }
       
   391     QScriptValue::PropertyFlags result = 0;
       
   392     if (attribs & JSC::ReadOnly)
       
   393         result |= QScriptValue::ReadOnly;
       
   394     if (attribs & JSC::DontEnum)
       
   395         result |= QScriptValue::SkipInEnumeration;
       
   396     if (attribs & JSC::DontDelete)
       
   397         result |= QScriptValue::Undeletable;
       
   398     //We cannot rely on attribs JSC::Setter/Getter because they are not necesserly set by JSC (bug?)
       
   399     if (attribs & JSC::Getter || !object->lookupGetter(exec, id).isUndefinedOrNull())
       
   400         result |= QScriptValue::PropertyGetter;
       
   401     if (attribs & JSC::Setter || !object->lookupSetter(exec, id).isUndefinedOrNull())
       
   402         result |= QScriptValue::PropertySetter;
       
   403     if (attribs & QScript::QObjectMemberAttribute)
       
   404         result |= QScriptValue::QObjectMember;
       
   405     result |= QScriptValue::PropertyFlag(attribs & QScriptValue::UserRange);
       
   406     return result;
       
   407 }
       
   408 
       
   409 QVariant &QScriptValuePrivate::variantValue() const
       
   410 {
       
   411     Q_ASSERT(jscValue.inherits(&QScriptObject::info));
       
   412     QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(jscValue))->delegate();
       
   413     Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::Variant));
       
   414     return static_cast<QScript::QVariantDelegate*>(delegate)->value();
       
   415 }
       
   416 
       
   417 void QScriptValuePrivate::setVariantValue(const QVariant &value)
       
   418 {
       
   419     Q_ASSERT(jscValue.inherits(&QScriptObject::info));
       
   420     QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(jscValue))->delegate();
       
   421     Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::Variant));
       
   422     static_cast<QScript::QVariantDelegate*>(delegate)->setValue(value);
       
   423 }
       
   424 
   170 
   425 void QScriptValuePrivate::detachFromEngine()
   171 void QScriptValuePrivate::detachFromEngine()
   426 {
   172 {
   427     if (isJSC())
   173     if (isJSC())
   428         jscValue = JSC::JSValue();
   174         jscValue = JSC::JSValue();
   705   \sa QScriptContext::throwError()
   451   \sa QScriptContext::throwError()
   706 */
   452 */
   707 bool QScriptValue::isError() const
   453 bool QScriptValue::isError() const
   708 {
   454 {
   709     Q_D(const QScriptValue);
   455     Q_D(const QScriptValue);
   710     if (!d || !d->isObject())
   456     if (!d || !d->isJSC())
   711         return false;
   457         return false;
   712     return d->jscValue.inherits(&JSC::ErrorInstance::info);
   458     return QScriptEnginePrivate::isError(d->jscValue);
   713 }
   459 }
   714 
   460 
   715 /*!
   461 /*!
   716   Returns true if this QScriptValue is an object of the Array class;
   462   Returns true if this QScriptValue is an object of the Array class;
   717   otherwise returns false.
   463   otherwise returns false.
   719   \sa QScriptEngine::newArray()
   465   \sa QScriptEngine::newArray()
   720 */
   466 */
   721 bool QScriptValue::isArray() const
   467 bool QScriptValue::isArray() const
   722 {
   468 {
   723     Q_D(const QScriptValue);
   469     Q_D(const QScriptValue);
   724     if (!d || !d->isObject())
   470     if (!d || !d->isJSC())
   725         return false;
   471         return false;
   726     return d->jscValue.inherits(&JSC::JSArray::info);
   472     return QScriptEnginePrivate::isArray(d->jscValue);
   727 }
   473 }
   728 
   474 
   729 /*!
   475 /*!
   730   Returns true if this QScriptValue is an object of the Date class;
   476   Returns true if this QScriptValue is an object of the Date class;
   731   otherwise returns false.
   477   otherwise returns false.
   733   \sa QScriptEngine::newDate()
   479   \sa QScriptEngine::newDate()
   734 */
   480 */
   735 bool QScriptValue::isDate() const
   481 bool QScriptValue::isDate() const
   736 {
   482 {
   737     Q_D(const QScriptValue);
   483     Q_D(const QScriptValue);
   738     if (!d || !d->isObject())
   484     if (!d || !d->isJSC())
   739         return false;
   485         return false;
   740     return d->jscValue.inherits(&JSC::DateInstance::info);
   486     return QScriptEnginePrivate::isDate(d->jscValue);
   741 }
   487 }
   742 
   488 
   743 /*!
   489 /*!
   744   Returns true if this QScriptValue is an object of the RegExp class;
   490   Returns true if this QScriptValue is an object of the RegExp class;
   745   otherwise returns false.
   491   otherwise returns false.
   747   \sa QScriptEngine::newRegExp()
   493   \sa QScriptEngine::newRegExp()
   748 */
   494 */
   749 bool QScriptValue::isRegExp() const
   495 bool QScriptValue::isRegExp() const
   750 {
   496 {
   751     Q_D(const QScriptValue);
   497     Q_D(const QScriptValue);
   752     if (!d || !d->isObject())
   498     if (!d || !d->isJSC())
   753         return false;
   499         return false;
   754     return d->jscValue.inherits(&JSC::RegExpObject::info);
   500     return QScriptEnginePrivate::isRegExp(d->jscValue);
   755 }
   501 }
   756 
   502 
   757 /*!
   503 /*!
   758   If this QScriptValue is an object, returns the internal prototype
   504   If this QScriptValue is an object, returns the internal prototype
   759   (\c{__proto__} property) of this object; otherwise returns an
   505   (\c{__proto__} property) of this object; otherwise returns an
   822 QScriptValue QScriptValue::scope() const
   568 QScriptValue QScriptValue::scope() const
   823 {
   569 {
   824     Q_D(const QScriptValue);
   570     Q_D(const QScriptValue);
   825     if (!d || !d->isObject())
   571     if (!d || !d->isObject())
   826         return QScriptValue();
   572         return QScriptValue();
       
   573     QScript::APIShim shim(d->engine);
   827     // ### make hidden property
   574     // ### make hidden property
   828     return d->property(QLatin1String("__qt_scope__"), QScriptValue::ResolveLocal);
   575     JSC::JSValue result = d->property("__qt_scope__", QScriptValue::ResolveLocal);
       
   576     return d->engine->scriptValueFromJSCValue(result);
   829 }
   577 }
   830 
   578 
   831 /*!
   579 /*!
   832   \internal
   580   \internal
   833 */
   581 */
   910         return Number;
   658         return Number;
   911     Q_ASSERT(v.isObject());
   659     Q_ASSERT(v.isObject());
   912     return Object;
   660     return Object;
   913 }
   661 }
   914 
   662 
   915 QScriptValue ToPrimitive(const QScriptValue &object, JSC::PreferredPrimitiveType hint = JSC::NoPreference)
   663 static QScriptValue ToPrimitive(const QScriptValue &object, JSC::PreferredPrimitiveType hint = JSC::NoPreference)
   916 {
   664 {
   917     Q_ASSERT(object.isObject());
   665     Q_ASSERT(object.isObject());
   918     QScriptValuePrivate *pp = QScriptValuePrivate::get(object);
   666     QScriptValuePrivate *pp = QScriptValuePrivate::get(object);
   919     Q_ASSERT(pp->engine != 0);
   667     Q_ASSERT(pp->engine != 0);
       
   668     QScript::APIShim shim(pp->engine);
   920     JSC::ExecState *exec = pp->engine->currentFrame;
   669     JSC::ExecState *exec = pp->engine->currentFrame;
   921     JSC::JSValue savedException;
   670     JSC::JSValue savedException;
   922     QScriptValuePrivate::saveException(exec, &savedException);
   671     QScriptEnginePrivate::saveException(exec, &savedException);
   923     JSC::JSValue result = JSC::asObject(pp->jscValue)->toPrimitive(exec, hint);
   672     JSC::JSValue result = JSC::asObject(pp->jscValue)->toPrimitive(exec, hint);
   924     QScriptValuePrivate::restoreException(exec, savedException);
   673     QScriptEnginePrivate::restoreException(exec, savedException);
   925     return pp->engine->scriptValueFromJSCValue(result);
   674     return pp->engine->scriptValueFromJSCValue(result);
   926 }
   675 }
   927 
   676 
   928 static bool IsNumerical(const QScriptValue &value)
   677 static bool IsNumerical(const QScriptValue &value)
   929 {
   678 {
  1108     if (d->isJSC() && other.d_ptr->isJSC()) {
   857     if (d->isJSC() && other.d_ptr->isJSC()) {
  1109         QScriptEnginePrivate *eng_p = d->engine;
   858         QScriptEnginePrivate *eng_p = d->engine;
  1110         if (!eng_p)
   859         if (!eng_p)
  1111             eng_p = other.d_ptr->engine;
   860             eng_p = other.d_ptr->engine;
  1112         if (eng_p) {
   861         if (eng_p) {
       
   862             QScript::APIShim shim(eng_p);
  1113             JSC::ExecState *exec = eng_p->currentFrame;
   863             JSC::ExecState *exec = eng_p->currentFrame;
  1114             JSC::JSValue savedException;
   864             JSC::JSValue savedException;
  1115             QScriptValuePrivate::saveException(exec, &savedException);
   865             QScriptEnginePrivate::saveException(exec, &savedException);
  1116             bool result = JSC::JSValue::equal(exec, d->jscValue, other.d_ptr->jscValue);
   866             bool result = JSC::JSValue::equal(exec, d->jscValue, other.d_ptr->jscValue);
  1117             QScriptValuePrivate::restoreException(exec, savedException);
   867             QScriptEnginePrivate::restoreException(exec, savedException);
  1118             return result;
   868             return result;
  1119         }
   869         }
  1120     }
   870     }
  1121     return QScript::Equals(*this, other);
   871     return QScript::Equals(*this, other);
  1122 }
   872 }
  1158 
   908 
  1159     if (d->type != other.d_ptr->type) {
   909     if (d->type != other.d_ptr->type) {
  1160         if (d->type == QScriptValuePrivate::JavaScriptCore) {
   910         if (d->type == QScriptValuePrivate::JavaScriptCore) {
  1161             QScriptEnginePrivate *eng_p = d->engine ? d->engine : other.d_ptr->engine;
   911             QScriptEnginePrivate *eng_p = d->engine ? d->engine : other.d_ptr->engine;
  1162             if (eng_p)
   912             if (eng_p)
  1163                 return JSC::JSValue::strictEqual(d->jscValue, eng_p->scriptValueToJSCValue(other));
   913                 return JSC::JSValue::strictEqual(eng_p->currentFrame, d->jscValue, eng_p->scriptValueToJSCValue(other));
  1164         } else if (other.d_ptr->type == QScriptValuePrivate::JavaScriptCore) {
   914         } else if (other.d_ptr->type == QScriptValuePrivate::JavaScriptCore) {
  1165             QScriptEnginePrivate *eng_p = other.d_ptr->engine ? other.d_ptr->engine : d->engine;
   915             QScriptEnginePrivate *eng_p = other.d_ptr->engine ? other.d_ptr->engine : d->engine;
  1166             if (eng_p)
   916             if (eng_p)
  1167                 return JSC::JSValue::strictEqual(eng_p->scriptValueToJSCValue(*this), other.d_ptr->jscValue);
   917                 return JSC::JSValue::strictEqual(eng_p->currentFrame, eng_p->scriptValueToJSCValue(*this), other.d_ptr->jscValue);
  1168         }
   918         }
  1169 
   919 
  1170         return false;
   920         return false;
  1171     }
   921     }
  1172     switch (d->type) {
   922     switch (d->type) {
  1173     case QScriptValuePrivate::JavaScriptCore:
   923     case QScriptValuePrivate::JavaScriptCore: {
  1174         return JSC::JSValue::strictEqual(d->jscValue, other.d_ptr->jscValue);
   924         QScriptEnginePrivate *eng_p = d->engine ? d->engine : other.d_ptr->engine;
       
   925         JSC::ExecState *exec = eng_p ? eng_p->currentFrame : 0;
       
   926         return JSC::JSValue::strictEqual(exec, d->jscValue, other.d_ptr->jscValue);
       
   927     }
  1175     case QScriptValuePrivate::Number:
   928     case QScriptValuePrivate::Number:
  1176         return (d->numberValue == other.d_ptr->numberValue);
   929         return (d->numberValue == other.d_ptr->numberValue);
  1177     case QScriptValuePrivate::String:
   930     case QScriptValuePrivate::String:
  1178         return (d->stringValue == other.d_ptr->stringValue);
   931         return (d->stringValue == other.d_ptr->stringValue);
  1179     }
   932     }
  1197     Q_D(const QScriptValue);
   950     Q_D(const QScriptValue);
  1198     if (!d)
   951     if (!d)
  1199         return QString();
   952         return QString();
  1200     switch (d->type) {
   953     switch (d->type) {
  1201     case QScriptValuePrivate::JavaScriptCore: {
   954     case QScriptValuePrivate::JavaScriptCore: {
  1202         JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
   955         if (d->engine) {
  1203         JSC::JSValue savedException;
   956             QScript::APIShim shim(d->engine);
  1204         QScriptValuePrivate::saveException(exec, &savedException);
   957             return QScriptEnginePrivate::toString(d->engine->currentFrame, d->jscValue);
  1205         JSC::UString str = d->jscValue.toString(exec);
   958         } else {
  1206         if (exec && exec->hadException() && !str.size()) {
   959             return QScriptEnginePrivate::toString(0, d->jscValue);
  1207             JSC::JSValue savedException2;
   960         }    }
  1208             QScriptValuePrivate::saveException(exec, &savedException2);
       
  1209             str = savedException2.toString(exec);
       
  1210             QScriptValuePrivate::restoreException(exec, savedException2);
       
  1211         }
       
  1212         if (savedException)
       
  1213             QScriptValuePrivate::restoreException(exec, savedException);
       
  1214         return str;
       
  1215     }
       
  1216     case QScriptValuePrivate::Number:
   961     case QScriptValuePrivate::Number:
  1217         return JSC::UString::from(d->numberValue);
   962         return QScript::ToString(d->numberValue);
  1218     case QScriptValuePrivate::String:
   963     case QScriptValuePrivate::String:
  1219         return d->stringValue;
   964         return d->stringValue;
  1220     }
   965     }
  1221     return QString();
   966     return QString();
  1222 }
   967 }
  1238     Q_D(const QScriptValue);
   983     Q_D(const QScriptValue);
  1239     if (!d)
   984     if (!d)
  1240         return 0;
   985         return 0;
  1241     switch (d->type) {
   986     switch (d->type) {
  1242     case QScriptValuePrivate::JavaScriptCore: {
   987     case QScriptValuePrivate::JavaScriptCore: {
  1243         JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
   988         if (d->engine) {
  1244         JSC::JSValue savedException;
   989             QScript::APIShim shim(d->engine);
  1245         QScriptValuePrivate::saveException(exec, &savedException);
   990             return QScriptEnginePrivate::toNumber(d->engine->currentFrame, d->jscValue);
  1246         qsreal result = d->jscValue.toNumber(exec);
   991         } else {
  1247         QScriptValuePrivate::restoreException(exec, savedException);
   992             return QScriptEnginePrivate::toNumber(0, d->jscValue);
  1248         return result;
   993         }
  1249     }
   994     }
  1250     case QScriptValuePrivate::Number:
   995     case QScriptValuePrivate::Number:
  1251         return d->numberValue;
   996         return d->numberValue;
  1252     case QScriptValuePrivate::String:
   997     case QScriptValuePrivate::String:
  1253         return ((JSC::UString)d->stringValue).toDouble();
   998         return QScript::ToNumber(d->stringValue);
  1254     }
   999     }
  1255     return 0;
  1000     return 0;
  1256 }
  1001 }
  1257 
  1002 
  1258 /*!
  1003 /*!
  1265     Q_D(const QScriptValue);
  1010     Q_D(const QScriptValue);
  1266     if (!d)
  1011     if (!d)
  1267         return false;
  1012         return false;
  1268     switch (d->type) {
  1013     switch (d->type) {
  1269     case QScriptValuePrivate::JavaScriptCore: {
  1014     case QScriptValuePrivate::JavaScriptCore: {
  1270         JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
  1015         if (d->engine) {
  1271         JSC::JSValue savedException;
  1016             QScript::APIShim shim(d->engine);
  1272         QScriptValuePrivate::saveException(exec, &savedException);
  1017             return QScriptEnginePrivate::toBool(d->engine->currentFrame, d->jscValue);
  1273         bool result = d->jscValue.toBoolean(exec);
  1018         } else {
  1274         QScriptValuePrivate::restoreException(exec, savedException);
  1019             return QScriptEnginePrivate::toBool(0, d->jscValue);
  1275         return result;
  1020         }
  1276     }
  1021     }
  1277     case QScriptValuePrivate::Number:
  1022     case QScriptValuePrivate::Number:
  1278         return (d->numberValue != 0) && !qIsNaN(d->numberValue);
  1023         return QScript::ToBool(d->numberValue);
  1279     case QScriptValuePrivate::String:
  1024     case QScriptValuePrivate::String:
  1280         return (!d->stringValue.isEmpty());
  1025         return QScript::ToBool(d->stringValue);
  1281     }
  1026     }
  1282     return false;
  1027     return false;
  1283 }
  1028 }
  1284 
  1029 
  1285 /*!
  1030 /*!
  1301     Q_D(const QScriptValue);
  1046     Q_D(const QScriptValue);
  1302     if (!d)
  1047     if (!d)
  1303         return false;
  1048         return false;
  1304     switch (d->type) {
  1049     switch (d->type) {
  1305     case QScriptValuePrivate::JavaScriptCore: {
  1050     case QScriptValuePrivate::JavaScriptCore: {
  1306         JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
  1051         if (d->engine) {
  1307         JSC::JSValue savedException;
  1052             QScript::APIShim shim(d->engine);
  1308         QScriptValuePrivate::saveException(exec, &savedException);
  1053             return QScriptEnginePrivate::toBool(d->engine->currentFrame, d->jscValue);
  1309         bool result = d->jscValue.toBoolean(exec);
  1054         } else {
  1310         QScriptValuePrivate::restoreException(exec, savedException);
  1055             return QScriptEnginePrivate::toBool(0, d->jscValue);
  1311         return result;
  1056         }
  1312     }
  1057     }
  1313     case QScriptValuePrivate::Number:
  1058     case QScriptValuePrivate::Number:
  1314         return (d->numberValue != 0) && !qIsNaN(d->numberValue);
  1059         return QScript::ToBool(d->numberValue);
  1315     case QScriptValuePrivate::String:
  1060     case QScriptValuePrivate::String:
  1316         return (!d->stringValue.isEmpty());
  1061         return QScript::ToBool(d->stringValue);
  1317     }
  1062     }
  1318     return false;
  1063     return false;
  1319 }
  1064 }
  1320 
  1065 
  1321 /*!
  1066 /*!
  1335     Q_D(const QScriptValue);
  1080     Q_D(const QScriptValue);
  1336     if (!d)
  1081     if (!d)
  1337         return 0;
  1082         return 0;
  1338     switch (d->type) {
  1083     switch (d->type) {
  1339     case QScriptValuePrivate::JavaScriptCore: {
  1084     case QScriptValuePrivate::JavaScriptCore: {
  1340         JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
  1085         if (d->engine) {
  1341         JSC::JSValue savedException;
  1086             QScript::APIShim shim(d->engine);
  1342         QScriptValuePrivate::saveException(exec, &savedException);
  1087             return QScriptEnginePrivate::toInt32(d->engine->currentFrame, d->jscValue);
  1343         qint32 result = d->jscValue.toInt32(exec);
  1088         } else {
  1344         QScriptValuePrivate::restoreException(exec, savedException);
  1089             return QScriptEnginePrivate::toInt32(0, d->jscValue);
  1345         return result;
  1090         }
  1346     }
  1091     }
  1347     case QScriptValuePrivate::Number:
  1092     case QScriptValuePrivate::Number:
  1348         return QScript::ToInt32(d->numberValue);
  1093         return QScript::ToInt32(d->numberValue);
  1349     case QScriptValuePrivate::String:
  1094     case QScriptValuePrivate::String:
  1350         return QScript::ToInt32(((JSC::UString)d->stringValue).toDouble());
  1095         return QScript::ToInt32(d->stringValue);
  1351     }
  1096     }
  1352     return 0;
  1097     return 0;
  1353 }
  1098 }
  1354 
  1099 
  1355 /*!
  1100 /*!
  1369     Q_D(const QScriptValue);
  1114     Q_D(const QScriptValue);
  1370     if (!d)
  1115     if (!d)
  1371         return 0;
  1116         return 0;
  1372     switch (d->type) {
  1117     switch (d->type) {
  1373     case QScriptValuePrivate::JavaScriptCore: {
  1118     case QScriptValuePrivate::JavaScriptCore: {
  1374         JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
  1119         if (d->engine) {
  1375         JSC::JSValue savedException;
  1120             QScript::APIShim shim(d->engine);
  1376         QScriptValuePrivate::saveException(exec, &savedException);
  1121             return QScriptEnginePrivate::toUInt32(d->engine->currentFrame, d->jscValue);
  1377         quint32 result = d->jscValue.toUInt32(exec);
  1122         } else {
  1378         QScriptValuePrivate::restoreException(exec, savedException);
  1123             return QScriptEnginePrivate::toUInt32(0, d->jscValue);
  1379         return result;
  1124         }
  1380     }
  1125     }
  1381     case QScriptValuePrivate::Number:
  1126     case QScriptValuePrivate::Number:
  1382         return QScript::ToUint32(d->numberValue);
  1127         return QScript::ToUInt32(d->numberValue);
  1383     case QScriptValuePrivate::String:
  1128     case QScriptValuePrivate::String:
  1384         return QScript::ToUint32(((JSC::UString)d->stringValue).toDouble());
  1129         return QScript::ToUInt32(d->stringValue);
  1385     }
  1130     }
  1386     return 0;
  1131     return 0;
  1387 }
  1132 }
  1388 
  1133 
  1389 /*!
  1134 /*!
  1403     Q_D(const QScriptValue);
  1148     Q_D(const QScriptValue);
  1404     if (!d)
  1149     if (!d)
  1405         return 0;
  1150         return 0;
  1406     switch (d->type) {
  1151     switch (d->type) {
  1407     case QScriptValuePrivate::JavaScriptCore: {
  1152     case QScriptValuePrivate::JavaScriptCore: {
  1408         // ### no equivalent function in JSC
  1153         if (d->engine) {
  1409         return QScript::ToUint16(toNumber());
  1154             QScript::APIShim shim(d->engine);
       
  1155             return QScriptEnginePrivate::toUInt16(d->engine->currentFrame, d->jscValue);
       
  1156         } else {
       
  1157             return QScriptEnginePrivate::toUInt16(0, d->jscValue);
       
  1158         }
  1410     }
  1159     }
  1411     case QScriptValuePrivate::Number:
  1160     case QScriptValuePrivate::Number:
  1412         return QScript::ToUint16(d->numberValue);
  1161         return QScript::ToUInt16(d->numberValue);
  1413     case QScriptValuePrivate::String:
  1162     case QScriptValuePrivate::String:
  1414         return QScript::ToUint16(((JSC::UString)d->stringValue).toDouble());
  1163         return QScript::ToUInt16(d->stringValue);
  1415     }
  1164     }
  1416     return 0;
  1165     return 0;
  1417 }
  1166 }
  1418 
  1167 
  1419 /*!
  1168 /*!
  1433     Q_D(const QScriptValue);
  1182     Q_D(const QScriptValue);
  1434     if (!d)
  1183     if (!d)
  1435         return 0;
  1184         return 0;
  1436     switch (d->type) {
  1185     switch (d->type) {
  1437     case QScriptValuePrivate::JavaScriptCore: {
  1186     case QScriptValuePrivate::JavaScriptCore: {
  1438         JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
  1187         if (d->engine) {
  1439         JSC::JSValue savedException;
  1188             QScript::APIShim shim(d->engine);
  1440         QScriptValuePrivate::saveException(exec, &savedException);
  1189             return QScriptEnginePrivate::toInteger(d->engine->currentFrame, d->jscValue);
  1441         qsreal result = d->jscValue.toInteger(exec);
  1190         } else {
  1442         QScriptValuePrivate::restoreException(exec, savedException);
  1191             return QScriptEnginePrivate::toInteger(0, d->jscValue);
  1443         return result;
  1192         }
  1444     }
  1193     }
  1445     case QScriptValuePrivate::Number:
  1194     case QScriptValuePrivate::Number:
  1446         return QScript::ToInteger(d->numberValue);
  1195         return QScript::ToInteger(d->numberValue);
  1447     case QScriptValuePrivate::String:
  1196     case QScriptValuePrivate::String:
  1448         return QScript::ToInteger(((JSC::UString)d->stringValue).toDouble());
  1197         return QScript::ToInteger(d->stringValue);
  1449     }
  1198     }
  1450     return 0;
  1199     return 0;
  1451 }
  1200 }
  1452 
  1201 
  1453 /*!
  1202 /*!
  1476 {
  1225 {
  1477     Q_D(const QScriptValue);
  1226     Q_D(const QScriptValue);
  1478     if (!d)
  1227     if (!d)
  1479         return QVariant();
  1228         return QVariant();
  1480     switch (d->type) {
  1229     switch (d->type) {
  1481     case QScriptValuePrivate::JavaScriptCore:
  1230     case QScriptValuePrivate::JavaScriptCore: {
  1482         if (isObject()) {
  1231         if (d->engine) {
  1483             if (isVariant())
  1232             QScript::APIShim shim(d->engine);
  1484                 return d->variantValue();
  1233             return QScriptEnginePrivate::toVariant(d->engine->currentFrame, d->jscValue);
  1485 #ifndef QT_NO_QOBJECT
  1234         } else {
  1486             else if (isQObject())
  1235             return QScriptEnginePrivate::toVariant(0, d->jscValue);
  1487                 return qVariantFromValue(toQObject());
       
  1488 #endif
       
  1489             else if (isDate())
       
  1490                 return QVariant(toDateTime());
       
  1491 #ifndef QT_NO_REGEXP
       
  1492             else if (isRegExp())
       
  1493                 return QVariant(toRegExp());
       
  1494 #endif
       
  1495             else if (isArray())
       
  1496                 return QScriptEnginePrivate::variantListFromArray(*this);
       
  1497             else if (QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(*this))
       
  1498                 return dc->toVariant(QScriptDeclarativeClass::object(*this));
       
  1499             // try to convert to primitive
       
  1500             JSC::ExecState *exec = d->engine->currentFrame;
       
  1501             JSC::JSValue savedException;
       
  1502             QScriptValuePrivate::saveException(exec, &savedException);
       
  1503             JSC::JSValue prim = d->jscValue.toPrimitive(exec);
       
  1504             QScriptValuePrivate::restoreException(exec, savedException);
       
  1505             if (!prim.isObject())
       
  1506                 return d->engine->scriptValueFromJSCValue(prim).toVariant();
       
  1507         } else if (isNumber()) {
       
  1508             return QVariant(toNumber());
       
  1509         } else if (isString()) {
       
  1510             return QVariant(toString());
       
  1511         } else if (isBool()) {
       
  1512             return QVariant(toBool());
       
  1513         }
  1236         }
  1514         return QVariant();
  1237     }
  1515     case QScriptValuePrivate::Number:
  1238     case QScriptValuePrivate::Number:
  1516         return QVariant(d->numberValue);
  1239         return QVariant(d->numberValue);
  1517     case QScriptValuePrivate::String:
  1240     case QScriptValuePrivate::String:
  1518         return QVariant(d->stringValue);
  1241         return QVariant(d->stringValue);
  1519     }
  1242     }
  1541   \sa isDate()
  1264   \sa isDate()
  1542 */
  1265 */
  1543 QDateTime QScriptValue::toDateTime() const
  1266 QDateTime QScriptValue::toDateTime() const
  1544 {
  1267 {
  1545     Q_D(const QScriptValue);
  1268     Q_D(const QScriptValue);
  1546     if (!isDate())
  1269     if (!d || !d->engine)
  1547         return QDateTime();
  1270         return QDateTime();
  1548     qsreal t = static_cast<JSC::DateInstance*>(JSC::asObject(d->jscValue))->internalNumber();
  1271     return QScriptEnginePrivate::toDateTime(d->engine->currentFrame, d->jscValue);
  1549     return QScript::ToDateTime(t, Qt::LocalTime);
       
  1550 }
  1272 }
  1551 
  1273 
  1552 #ifndef QT_NO_REGEXP
  1274 #ifndef QT_NO_REGEXP
  1553 /*!
  1275 /*!
  1554   Returns the QRegExp representation of this value.
  1276   Returns the QRegExp representation of this value.
  1558   \sa isRegExp()
  1280   \sa isRegExp()
  1559 */
  1281 */
  1560 QRegExp QScriptValue::toRegExp() const
  1282 QRegExp QScriptValue::toRegExp() const
  1561 {
  1283 {
  1562     Q_D(const QScriptValue);
  1284     Q_D(const QScriptValue);
  1563     if (!isRegExp())
  1285     if (!d || !d->engine)
  1564         return QRegExp();
  1286          return QRegExp();
  1565     QString pattern = d->property(QLatin1String("source"), QScriptValue::ResolvePrototype).toString();
  1287     return QScriptEnginePrivate::toRegExp(d->engine->currentFrame, d->jscValue);
  1566     Qt::CaseSensitivity kase = Qt::CaseSensitive;
       
  1567     if (d->property(QLatin1String("ignoreCase"), QScriptValue::ResolvePrototype).toBool())
       
  1568         kase = Qt::CaseInsensitive;
       
  1569     return QRegExp(pattern, kase, QRegExp::RegExp2);
       
  1570 }
  1288 }
  1571 #endif // QT_NO_REGEXP
  1289 #endif // QT_NO_REGEXP
  1572 
  1290 
  1573 /*!
  1291 /*!
  1574   If this QScriptValue is a QObject, returns the QObject pointer
  1292   If this QScriptValue is a QObject, returns the QObject pointer
  1581   \sa isQObject()
  1299   \sa isQObject()
  1582 */
  1300 */
  1583 QObject *QScriptValue::toQObject() const
  1301 QObject *QScriptValue::toQObject() const
  1584 {
  1302 {
  1585     Q_D(const QScriptValue);
  1303     Q_D(const QScriptValue);
  1586     if (isQObject()) {
  1304     if (!d || !d->engine)
  1587         QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
  1305         return 0;
  1588         QScriptObjectDelegate *delegate = object->delegate();
  1306     return QScriptEnginePrivate::toQObject(d->engine->currentFrame, d->jscValue);
  1589         if (delegate->type() == QScriptObjectDelegate::DeclarativeClassObject)
       
  1590             return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass()->toQObject(QScriptDeclarativeClass::object(*this));
       
  1591         return static_cast<QScript::QObjectDelegate*>(delegate)->value();
       
  1592     } else if (isVariant()) {
       
  1593         QVariant var = toVariant();
       
  1594         int type = var.userType();
       
  1595         if ((type == QMetaType::QObjectStar) || (type == QMetaType::QWidgetStar))
       
  1596             return *reinterpret_cast<QObject* const *>(var.constData());
       
  1597     }
       
  1598     return 0;
       
  1599 }
  1307 }
  1600 
  1308 
  1601 /*!
  1309 /*!
  1602   If this QScriptValue is a QMetaObject, returns the QMetaObject pointer
  1310   If this QScriptValue is a QMetaObject, returns the QMetaObject pointer
  1603   that the QScriptValue represents; otherwise, returns 0.
  1311   that the QScriptValue represents; otherwise, returns 0.
  1605   \sa isQMetaObject()
  1313   \sa isQMetaObject()
  1606 */
  1314 */
  1607 const QMetaObject *QScriptValue::toQMetaObject() const
  1315 const QMetaObject *QScriptValue::toQMetaObject() const
  1608 {
  1316 {
  1609     Q_D(const QScriptValue);
  1317     Q_D(const QScriptValue);
  1610     if (isQMetaObject())
  1318     if (!d || !d->engine)
  1611         return static_cast<QScript::QMetaObjectWrapperObject*>(JSC::asObject(d->jscValue))->value();
  1319         return 0;
  1612     return 0;
  1320     return QScriptEnginePrivate::toQMetaObject(d->engine->currentFrame, d->jscValue);
  1613 }
  1321 }
  1614 
  1322 
  1615 /*!
  1323 /*!
  1616   Sets the value of this QScriptValue's property with the given \a name to
  1324   Sets the value of this QScriptValue's property with the given \a name to
  1617   the given \a value.
  1325   the given \a value.
  1641                                const PropertyFlags &flags)
  1349                                const PropertyFlags &flags)
  1642 {
  1350 {
  1643     Q_D(QScriptValue);
  1351     Q_D(QScriptValue);
  1644     if (!d || !d->isObject())
  1352     if (!d || !d->isObject())
  1645         return;
  1353         return;
  1646     JSC::ExecState *exec = d->engine->currentFrame;
  1354     QScript::APIShim shim(d->engine);
  1647     d->setProperty(JSC::Identifier(exec, name), value, flags);
  1355     QScriptEnginePrivate *valueEngine = QScriptValuePrivate::getEngine(value);
       
  1356     if (valueEngine && (valueEngine != d->engine)) {
       
  1357         qWarning("QScriptValue::setProperty(%s) failed: "
       
  1358                  "cannot set value created in a different engine",
       
  1359                  qPrintable(name));
       
  1360         return;
       
  1361     }
       
  1362     JSC::JSValue jsValue = d->engine->scriptValueToJSCValue(value);
       
  1363     d->setProperty(name, jsValue, flags);
  1648 }
  1364 }
  1649 
  1365 
  1650 /*!
  1366 /*!
  1651   Returns the value of this QScriptValue's property with the given \a name,
  1367   Returns the value of this QScriptValue's property with the given \a name,
  1652   using the given \a mode to resolve the property.
  1368   using the given \a mode to resolve the property.
  1666                                     const ResolveFlags &mode) const
  1382                                     const ResolveFlags &mode) const
  1667 {
  1383 {
  1668     Q_D(const QScriptValue);
  1384     Q_D(const QScriptValue);
  1669     if (!d || !d->isObject())
  1385     if (!d || !d->isObject())
  1670         return QScriptValue();
  1386         return QScriptValue();
  1671     return d->property(name, mode);
  1387     QScript::APIShim shim(d->engine);
       
  1388     return d->engine->scriptValueFromJSCValue(d->property(name, mode));
  1672 }
  1389 }
  1673 
  1390 
  1674 /*!
  1391 /*!
  1675   \overload
  1392   \overload
  1676 
  1393 
  1688                                     const ResolveFlags &mode) const
  1405                                     const ResolveFlags &mode) const
  1689 {
  1406 {
  1690     Q_D(const QScriptValue);
  1407     Q_D(const QScriptValue);
  1691     if (!d || !d->isObject())
  1408     if (!d || !d->isObject())
  1692         return QScriptValue();
  1409         return QScriptValue();
  1693     return d->property(arrayIndex, mode);
  1410     return d->engine->scriptValueFromJSCValue(d->property(arrayIndex, mode));
  1694 }
  1411 }
  1695 
  1412 
  1696 /*!
  1413 /*!
  1697   \overload
  1414   \overload
  1698 
  1415 
  1715         && (QScriptValuePrivate::getEngine(value) != d->engine)) {
  1432         && (QScriptValuePrivate::getEngine(value) != d->engine)) {
  1716         qWarning("QScriptValue::setProperty() failed: "
  1433         qWarning("QScriptValue::setProperty() failed: "
  1717                  "cannot set value created in a different engine");
  1434                  "cannot set value created in a different engine");
  1718         return;
  1435         return;
  1719     }
  1436     }
  1720     JSC::ExecState *exec = d->engine->currentFrame;
  1437     JSC::JSValue jsValue = d->engine->scriptValueToJSCValue(value);
  1721     JSC::JSValue jscValue = d->engine->scriptValueToJSCValue(value);
  1438     d->setProperty(arrayIndex, jsValue, flags);
  1722     if (!jscValue) {
       
  1723         JSC::asObject(d->jscValue)->deleteProperty(exec, arrayIndex, /*checkDontDelete=*/false);
       
  1724     } else {
       
  1725         if ((flags & QScriptValue::PropertyGetter) || (flags & QScriptValue::PropertySetter)) {
       
  1726             // fall back to string-based setProperty(), since there is no
       
  1727             // JSC::JSObject::defineGetter(unsigned)
       
  1728             d->setProperty(JSC::Identifier::from(exec, arrayIndex), value, flags);
       
  1729         } else {
       
  1730             if (flags != QScriptValue::KeepExistingFlags) {
       
  1731 //                if (JSC::asObject(d->jscValue)->hasOwnProperty(exec, arrayIndex))
       
  1732 //                    JSC::asObject(d->jscValue)->deleteProperty(exec, arrayIndex);
       
  1733                 unsigned attribs = 0;
       
  1734                 if (flags & QScriptValue::ReadOnly)
       
  1735                     attribs |= JSC::ReadOnly;
       
  1736                 if (flags & QScriptValue::SkipInEnumeration)
       
  1737                     attribs |= JSC::DontEnum;
       
  1738                 if (flags & QScriptValue::Undeletable)
       
  1739                     attribs |= JSC::DontDelete;
       
  1740                 attribs |= flags & QScriptValue::UserRange;
       
  1741                 JSC::asObject(d->jscValue)->putWithAttributes(exec, arrayIndex, jscValue, attribs);
       
  1742             } else {
       
  1743                 JSC::asObject(d->jscValue)->put(exec, arrayIndex, jscValue);
       
  1744             }
       
  1745         }
       
  1746     }
       
  1747 }
  1439 }
  1748 
  1440 
  1749 /*!
  1441 /*!
  1750   \since 4.4
  1442   \since 4.4
  1751 
  1443 
  1762                                     const ResolveFlags &mode) const
  1454                                     const ResolveFlags &mode) const
  1763 {
  1455 {
  1764     Q_D(const QScriptValue);
  1456     Q_D(const QScriptValue);
  1765     if (!d || !d->isObject() || !QScriptStringPrivate::isValid(name))
  1457     if (!d || !d->isObject() || !QScriptStringPrivate::isValid(name))
  1766         return QScriptValue();
  1458         return QScriptValue();
  1767     return d->property(name.d_ptr->identifier, mode);
  1459     QScript::APIShim shim(d->engine);
       
  1460     return d->engine->scriptValueFromJSCValue(d->property(name.d_ptr->identifier, mode));
  1768 }
  1461 }
  1769 
  1462 
  1770 /*!
  1463 /*!
  1771   \since 4.4
  1464   \since 4.4
  1772 
  1465 
  1785                                const PropertyFlags &flags)
  1478                                const PropertyFlags &flags)
  1786 {
  1479 {
  1787     Q_D(QScriptValue);
  1480     Q_D(QScriptValue);
  1788     if (!d || !d->isObject() || !QScriptStringPrivate::isValid(name))
  1481     if (!d || !d->isObject() || !QScriptStringPrivate::isValid(name))
  1789         return;
  1482         return;
  1790     d->setProperty(name.d_ptr->identifier, value, flags);
  1483     QScriptEnginePrivate *valueEngine = QScriptValuePrivate::getEngine(value);
       
  1484     if (valueEngine && (valueEngine != d->engine)) {
       
  1485         qWarning("QScriptValue::setProperty(%s) failed: "
       
  1486                  "cannot set value created in a different engine",
       
  1487                  qPrintable(name.toString()));
       
  1488         return;
       
  1489     }
       
  1490     QScript::APIShim shim(d->engine);
       
  1491     JSC::JSValue jsValue = d->engine->scriptValueToJSCValue(value);
       
  1492     d->setProperty(name.d_ptr->identifier, jsValue, flags);
  1791 }
  1493 }
  1792 
  1494 
  1793 /*!
  1495 /*!
  1794   Returns the flags of the property with the given \a name, using the
  1496   Returns the flags of the property with the given \a name, using the
  1795   given \a mode to resolve the property.
  1497   given \a mode to resolve the property.
  1800                                                         const ResolveFlags &mode) const
  1502                                                         const ResolveFlags &mode) const
  1801 {
  1503 {
  1802     Q_D(const QScriptValue);
  1504     Q_D(const QScriptValue);
  1803     if (!d || !d->isObject())
  1505     if (!d || !d->isObject())
  1804         return 0;
  1506         return 0;
       
  1507     QScript::APIShim shim(d->engine);
  1805     JSC::ExecState *exec = d->engine->currentFrame;
  1508     JSC::ExecState *exec = d->engine->currentFrame;
  1806     return d->propertyFlags(JSC::Identifier(exec, name), mode);
  1509     return d->propertyFlags(JSC::Identifier(exec, name), mode);
  1807 
  1510 
  1808 }
  1511 }
  1809 
  1512 
  1849 */
  1552 */
  1850 QScriptValue QScriptValue::call(const QScriptValue &thisObject,
  1553 QScriptValue QScriptValue::call(const QScriptValue &thisObject,
  1851                                 const QScriptValueList &args)
  1554                                 const QScriptValueList &args)
  1852 {
  1555 {
  1853     Q_D(const QScriptValue);
  1556     Q_D(const QScriptValue);
  1854     if (!d || !d->isJSC())
  1557     if (!d || !d->isObject())
  1855         return QScriptValue();
  1558         return QScriptValue();
       
  1559     QScript::APIShim shim(d->engine);
  1856     JSC::JSValue callee = d->jscValue;
  1560     JSC::JSValue callee = d->jscValue;
  1857     JSC::CallData callData;
  1561     JSC::CallData callData;
  1858     JSC::CallType callType = callee.getCallData(callData);
  1562     JSC::CallType callType = callee.getCallData(callData);
  1859     if (callType == JSC::CallTypeNone)
  1563     if (callType == JSC::CallTypeNone)
  1860         return QScriptValue();
  1564         return QScriptValue();
  1889         }
  1593         }
  1890     }
  1594     }
  1891     JSC::ArgList jscArgs(argsVector.data(), argsVector.size());
  1595     JSC::ArgList jscArgs(argsVector.data(), argsVector.size());
  1892 
  1596 
  1893     JSC::JSValue savedException;
  1597     JSC::JSValue savedException;
  1894     QScriptValuePrivate::saveException(exec, &savedException);
  1598     QScriptEnginePrivate::saveException(exec, &savedException);
  1895     JSC::JSValue result = JSC::call(exec, callee, callType, callData, jscThisObject, jscArgs);
  1599     JSC::JSValue result = JSC::call(exec, callee, callType, callData, jscThisObject, jscArgs);
  1896     if (exec->hadException()) {
  1600     if (exec->hadException()) {
  1897         result = exec->exception();
  1601         result = exec->exception();
  1898     } else {
  1602     } else {
  1899         QScriptValuePrivate::restoreException(exec, savedException);
  1603         QScriptEnginePrivate::restoreException(exec, savedException);
  1900     }
  1604     }
  1901     return d->engine->scriptValueFromJSCValue(result);
  1605     return d->engine->scriptValueFromJSCValue(result);
  1902 }
  1606 }
  1903 
  1607 
  1904 /*!
  1608 /*!
  1926 */
  1630 */
  1927 QScriptValue QScriptValue::call(const QScriptValue &thisObject,
  1631 QScriptValue QScriptValue::call(const QScriptValue &thisObject,
  1928                                 const QScriptValue &arguments)
  1632                                 const QScriptValue &arguments)
  1929 {
  1633 {
  1930     Q_D(QScriptValue);
  1634     Q_D(QScriptValue);
  1931     if (!d || !d->isJSC())
  1635     if (!d || !d->isObject())
  1932         return QScriptValue();
  1636         return QScriptValue();
       
  1637     QScript::APIShim shim(d->engine);
  1933     JSC::JSValue callee = d->jscValue;
  1638     JSC::JSValue callee = d->jscValue;
  1934     JSC::CallData callData;
  1639     JSC::CallData callData;
  1935     JSC::CallType callType = callee.getCallData(callData);
  1640     JSC::CallType callType = callee.getCallData(callData);
  1936     if (callType == JSC::CallTypeNone)
  1641     if (callType == JSC::CallTypeNone)
  1937         return QScriptValue();
  1642         return QScriptValue();
  1969             return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array"));
  1674             return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array"));
  1970         }
  1675         }
  1971     }
  1676     }
  1972 
  1677 
  1973     JSC::JSValue savedException;
  1678     JSC::JSValue savedException;
  1974     QScriptValuePrivate::saveException(exec, &savedException);
  1679     QScriptEnginePrivate::saveException(exec, &savedException);
  1975     JSC::JSValue result = JSC::call(exec, callee, callType, callData, jscThisObject, applyArgs);
  1680     JSC::JSValue result = JSC::call(exec, callee, callType, callData, jscThisObject, applyArgs);
  1976     if (exec->hadException()) {
  1681     if (exec->hadException()) {
  1977         result = exec->exception();
  1682         result = exec->exception();
  1978     } else {
  1683     } else {
  1979         QScriptValuePrivate::restoreException(exec, savedException);
  1684         QScriptEnginePrivate::restoreException(exec, savedException);
  1980     }
  1685     }
  1981     return d->engine->scriptValueFromJSCValue(result);
  1686     return d->engine->scriptValueFromJSCValue(result);
  1982 }
  1687 }
  1983 
  1688 
  1984 /*!
  1689 /*!
  2000   \sa call(), QScriptEngine::newObject()
  1705   \sa call(), QScriptEngine::newObject()
  2001 */
  1706 */
  2002 QScriptValue QScriptValue::construct(const QScriptValueList &args)
  1707 QScriptValue QScriptValue::construct(const QScriptValueList &args)
  2003 {
  1708 {
  2004     Q_D(const QScriptValue);
  1709     Q_D(const QScriptValue);
  2005     if (!d || !d->isJSC())
  1710     if (!d || !d->isObject())
  2006         return QScriptValue();
  1711         return QScriptValue();
       
  1712     QScript::APIShim shim(d->engine);
  2007     JSC::JSValue callee = d->jscValue;
  1713     JSC::JSValue callee = d->jscValue;
  2008     JSC::ConstructData constructData;
  1714     JSC::ConstructData constructData;
  2009     JSC::ConstructType constructType = callee.getConstructData(constructData);
  1715     JSC::ConstructType constructType = callee.getConstructData(constructData);
  2010     if (constructType == JSC::ConstructTypeNone)
  1716     if (constructType == JSC::ConstructTypeNone)
  2011         return QScriptValue();
  1717         return QScriptValue();
  2021     }
  1727     }
  2022 
  1728 
  2023     JSC::ArgList jscArgs(argsVector.data(), argsVector.size());
  1729     JSC::ArgList jscArgs(argsVector.data(), argsVector.size());
  2024 
  1730 
  2025     JSC::JSValue savedException;
  1731     JSC::JSValue savedException;
  2026     QScriptValuePrivate::saveException(exec, &savedException);
  1732     QScriptEnginePrivate::saveException(exec, &savedException);
  2027     JSC::JSObject *result = JSC::construct(exec, callee, constructType, constructData, jscArgs);
  1733     JSC::JSObject *result = JSC::construct(exec, callee, constructType, constructData, jscArgs);
  2028     if (exec->hadException()) {
  1734     if (exec->hadException()) {
  2029         result = JSC::asObject(exec->exception());
  1735         result = JSC::asObject(exec->exception());
  2030     } else {
  1736     } else {
  2031         QScriptValuePrivate::restoreException(exec, savedException);
  1737         QScriptEnginePrivate::restoreException(exec, savedException);
  2032     }
  1738     }
  2033     return d->engine->scriptValueFromJSCValue(result);
  1739     return d->engine->scriptValueFromJSCValue(result);
  2034 }
  1740 }
  2035 
  1741 
  2036 /*!
  1742 /*!
  2049   \sa call(), QScriptEngine::newObject(), QScriptContext::argumentsObject()
  1755   \sa call(), QScriptEngine::newObject(), QScriptContext::argumentsObject()
  2050 */
  1756 */
  2051 QScriptValue QScriptValue::construct(const QScriptValue &arguments)
  1757 QScriptValue QScriptValue::construct(const QScriptValue &arguments)
  2052 {
  1758 {
  2053     Q_D(QScriptValue);
  1759     Q_D(QScriptValue);
  2054     if (!d || !d->isJSC())
  1760     if (!d || !d->isObject())
  2055         return QScriptValue();
  1761         return QScriptValue();
       
  1762     QScript::APIShim shim(d->engine);
  2056     JSC::JSValue callee = d->jscValue;
  1763     JSC::JSValue callee = d->jscValue;
  2057     JSC::ConstructData constructData;
  1764     JSC::ConstructData constructData;
  2058     JSC::ConstructType constructType = callee.getConstructData(constructData);
  1765     JSC::ConstructType constructType = callee.getConstructData(constructData);
  2059     if (constructType == JSC::ConstructTypeNone)
  1766     if (constructType == JSC::ConstructTypeNone)
  2060         return QScriptValue();
  1767         return QScriptValue();
  2080             return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array"));
  1787             return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array"));
  2081         }
  1788         }
  2082     }
  1789     }
  2083 
  1790 
  2084     JSC::JSValue savedException;
  1791     JSC::JSValue savedException;
  2085     QScriptValuePrivate::saveException(exec, &savedException);
  1792     QScriptEnginePrivate::saveException(exec, &savedException);
  2086     JSC::JSObject *result = JSC::construct(exec, callee, constructType, constructData, applyArgs);
  1793     JSC::JSObject *result = JSC::construct(exec, callee, constructType, constructData, applyArgs);
  2087     if (exec->hadException()) {
  1794     if (exec->hadException()) {
  2088         if (exec->exception().isObject())
  1795         if (exec->exception().isObject())
  2089             result = JSC::asObject(exec->exception());
  1796             result = JSC::asObject(exec->exception());
  2090     } else {
  1797     } else {
  2091         QScriptValuePrivate::restoreException(exec, savedException);
  1798         QScriptEnginePrivate::restoreException(exec, savedException);
  2092     }
  1799     }
  2093     return d->engine->scriptValueFromJSCValue(result);
  1800     return d->engine->scriptValueFromJSCValue(result);
  2094 }
  1801 }
  2095 
  1802 
  2096 /*!
  1803 /*!
  2235   \sa toVariant(), QScriptEngine::newVariant()
  1942   \sa toVariant(), QScriptEngine::newVariant()
  2236 */
  1943 */
  2237 bool QScriptValue::isVariant() const
  1944 bool QScriptValue::isVariant() const
  2238 {
  1945 {
  2239     Q_D(const QScriptValue);
  1946     Q_D(const QScriptValue);
  2240     if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info))
  1947     if (!d || !d->isJSC())
  2241         return false;
  1948         return false;
  2242     QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
  1949     return QScriptEnginePrivate::isVariant(d->jscValue);
  2243     QScriptObjectDelegate *delegate = object->delegate();
       
  2244     return (delegate && (delegate->type() == QScriptObjectDelegate::Variant));
       
  2245 }
  1950 }
  2246 
  1951 
  2247 /*!
  1952 /*!
  2248   Returns true if this QScriptValue is a QObject; otherwise returns
  1953   Returns true if this QScriptValue is a QObject; otherwise returns
  2249   false.
  1954   false.
  2254   \sa toQObject(), QScriptEngine::newQObject()
  1959   \sa toQObject(), QScriptEngine::newQObject()
  2255 */
  1960 */
  2256 bool QScriptValue::isQObject() const
  1961 bool QScriptValue::isQObject() const
  2257 {
  1962 {
  2258     Q_D(const QScriptValue);
  1963     Q_D(const QScriptValue);
  2259     if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info))
  1964     if (!d || !d->isJSC())
  2260         return false;
  1965         return false;
  2261     QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
  1966     return QScriptEnginePrivate::isQObject(d->jscValue);
  2262     QScriptObjectDelegate *delegate = object->delegate();
       
  2263     return (delegate && (delegate->type() == QScriptObjectDelegate::QtObject ||
       
  2264                          (delegate->type() == QScriptObjectDelegate::DeclarativeClassObject &&
       
  2265                           static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass()->isQObject())));
       
  2266 }
  1967 }
  2267 
  1968 
  2268 /*!
  1969 /*!
  2269   Returns true if this QScriptValue is a QMetaObject; otherwise returns
  1970   Returns true if this QScriptValue is a QMetaObject; otherwise returns
  2270   false.
  1971   false.
  2272   \sa toQMetaObject(), QScriptEngine::newQMetaObject()
  1973   \sa toQMetaObject(), QScriptEngine::newQMetaObject()
  2273 */
  1974 */
  2274 bool QScriptValue::isQMetaObject() const
  1975 bool QScriptValue::isQMetaObject() const
  2275 {
  1976 {
  2276     Q_D(const QScriptValue);
  1977     Q_D(const QScriptValue);
  2277     if (!d || !d->isObject())
  1978     if (!d || !d->isJSC())
  2278         return false;
  1979         return false;
  2279     return JSC::asObject(d->jscValue)->inherits(&QScript::QMetaObjectWrapperObject::info);
  1980     return QScriptEnginePrivate::isQMetaObject(d->jscValue);
  2280 }
  1981 }
  2281 
  1982 
  2282 /*!
  1983 /*!
  2283   Returns true if this QScriptValue is valid; otherwise returns
  1984   Returns true if this QScriptValue is valid; otherwise returns
  2284   false.
  1985   false.
  2305     if (d->jscValue.inherits(&QScriptObject::info)) {
  2006     if (d->jscValue.inherits(&QScriptObject::info)) {
  2306         QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
  2007         QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
  2307         return d->engine->scriptValueFromJSCValue(scriptObject->data());
  2008         return d->engine->scriptValueFromJSCValue(scriptObject->data());
  2308     } else {
  2009     } else {
  2309         // ### make hidden property
  2010         // ### make hidden property
  2310         return d->property(QLatin1String("__qt_data__"), QScriptValue::ResolveLocal);
  2011         return property(QLatin1String("__qt_data__"), QScriptValue::ResolveLocal);
  2311     }
  2012     }
  2312 }
  2013 }
  2313 
  2014 
  2314 /*!
  2015 /*!
  2315   \since 4.4
  2016   \since 4.4
  2316 
  2017 
  2317   Sets the internal \a data of this QScriptValue object. You can use
  2018   Sets the internal \a data of this QScriptValue object. You can use
  2318   this function to set object-specific data that won't be directly
  2019   this function to set object-specific data that won't be directly
  2319   accessible to scripts, but may be retrieved in C++ using the data()
  2020   accessible to scripts, but may be retrieved in C++ using the data()
  2320   function.
  2021   function.
       
  2022 
       
  2023   \sa QScriptEngine::reportAdditionalMemoryCost()
  2321 */
  2024 */
  2322 void QScriptValue::setData(const QScriptValue &data)
  2025 void QScriptValue::setData(const QScriptValue &data)
  2323 {
  2026 {
  2324     Q_D(QScriptValue);
  2027     Q_D(QScriptValue);
  2325     if (!d || !d->isObject())
  2028     if (!d || !d->isObject())