Home | History | Annotate | Download | only in api
      1 /*
      2     Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
      3 
      4     This library is free software; you can redistribute it and/or
      5     modify it under the terms of the GNU Library General Public
      6     License as published by the Free Software Foundation; either
      7     version 2 of the License, or (at your option) any later version.
      8 
      9     This library is distributed in the hope that it will be useful,
     10     but WITHOUT ANY WARRANTY; without even the implied warranty of
     11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12     Library General Public License for more details.
     13 
     14     You should have received a copy of the GNU Library General Public License
     15     along with this library; see the file COPYING.LIB.  If not, write to
     16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17     Boston, MA 02110-1301, USA.
     18 */
     19 
     20 #ifndef qscriptvalue_p_h
     21 #define qscriptvalue_p_h
     22 
     23 #include "qscriptconverter_p.h"
     24 #include "qscriptengine_p.h"
     25 #include "qscriptvalue.h"
     26 #include <JavaScriptCore/JavaScript.h>
     27 #include <QtCore/qmath.h>
     28 #include <QtCore/qnumeric.h>
     29 #include <QtCore/qshareddata.h>
     30 #include <QtCore/qvarlengtharray.h>
     31 
     32 class QScriptEngine;
     33 class QScriptValue;
     34 
     35 /*
     36   \internal
     37   \class QScriptValuePrivate
     38 
     39   Implementation of QScriptValue.
     40   The implementation is based on a state machine. The states names are included in
     41   QScriptValuePrivate::States. Each method should check for the current state and then perform a
     42   correct action.
     43 
     44   States:
     45     Invalid -> QSVP is invalid, no assumptions should be made about class members (apart from m_value).
     46     CString -> QSVP is created from QString or const char* and no JSC engine has been associated yet.
     47         Current value is kept in m_string,
     48     CNumber -> QSVP is created from int, uint, double... and no JSC engine has been bind yet. Current
     49         value is kept in m_number
     50     CBool -> QSVP is created from bool and no JSC engine has been associated yet. Current value is kept
     51         in m_number
     52     CSpecial -> QSVP is Undefined or Null, but a JSC engine hasn't been associated yet, current value
     53         is kept in m_number (cast of QScriptValue::SpecialValue)
     54     JSValue -> QSVP is associated with engine, but there is no information about real type, the state
     55         have really short live cycle. Normally it is created as a function call result.
     56     JSNative -> QSVP is associated with engine, and it is sure that it isn't a JavaScript object.
     57     JSObject -> QSVP is associated with engine, and it is sure that it is a JavaScript object.
     58 
     59   Each state keep all necessary information to invoke all methods, if not it should be changed to
     60   a proper state. Changed state shouldn't be reverted.
     61 */
     62 
     63 class QScriptValuePrivate : public QSharedData {
     64 public:
     65     inline static QScriptValuePrivate* get(const QScriptValue& q);
     66     inline static QScriptValue get(const QScriptValuePrivate* d);
     67     inline static QScriptValue get(QScriptValuePrivate* d);
     68 
     69     inline ~QScriptValuePrivate();
     70 
     71     inline QScriptValuePrivate();
     72     inline QScriptValuePrivate(const QString& string);
     73     inline QScriptValuePrivate(bool value);
     74     inline QScriptValuePrivate(int number);
     75     inline QScriptValuePrivate(uint number);
     76     inline QScriptValuePrivate(qsreal number);
     77     inline QScriptValuePrivate(QScriptValue::SpecialValue value);
     78 
     79     inline QScriptValuePrivate(const QScriptEngine* engine, bool value);
     80     inline QScriptValuePrivate(const QScriptEngine* engine, int value);
     81     inline QScriptValuePrivate(const QScriptEngine* engine, uint value);
     82     inline QScriptValuePrivate(const QScriptEngine* engine, qsreal value);
     83     inline QScriptValuePrivate(const QScriptEngine* engine, const QString& value);
     84     inline QScriptValuePrivate(const QScriptEngine* engine, QScriptValue::SpecialValue value);
     85 
     86     inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value);
     87     inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value, JSObjectRef object);
     88 
     89     inline bool isValid() const;
     90     inline bool isBool();
     91     inline bool isNumber();
     92     inline bool isNull();
     93     inline bool isString();
     94     inline bool isUndefined();
     95     inline bool isError();
     96     inline bool isObject();
     97     inline bool isFunction();
     98 
     99     inline QString toString() const;
    100     inline qsreal toNumber() const;
    101     inline bool toBool() const;
    102     inline qsreal toInteger() const;
    103     inline qint32 toInt32() const;
    104     inline quint32 toUInt32() const;
    105     inline quint16 toUInt16() const;
    106 
    107     inline bool equals(QScriptValuePrivate* other);
    108     inline bool strictlyEquals(const QScriptValuePrivate* other) const;
    109     inline bool assignEngine(QScriptEnginePrivate* engine);
    110 
    111     inline QScriptValuePrivate* call(const QScriptValuePrivate* , const QScriptValueList& args);
    112 
    113     inline JSGlobalContextRef context() const;
    114     inline JSValueRef value() const;
    115     inline JSObjectRef object() const;
    116     inline QScriptEnginePrivate* engine() const;
    117 
    118 private:
    119     // Please, update class documentation when you change the enum.
    120     enum States {
    121         Invalid = 0,
    122         CString = 0x1000,
    123         CNumber,
    124         CBool,
    125         CSpecial,
    126         JSValue = 0x2000, // JS values are equal or higher then this value.
    127         JSNative,
    128         JSObject
    129     } m_state;
    130     QScriptEnginePtr m_engine;
    131     QString m_string;
    132     qsreal m_number;
    133     JSValueRef m_value;
    134     JSObjectRef m_object;
    135 
    136     inline void setValue(JSValueRef);
    137 
    138     inline bool inherits(const char*);
    139 
    140     inline bool isJSBased() const;
    141     inline bool isNumberBased() const;
    142     inline bool isStringBased() const;
    143 };
    144 
    145 QScriptValuePrivate* QScriptValuePrivate::get(const QScriptValue& q) { return q.d_ptr.data(); }
    146 
    147 QScriptValue QScriptValuePrivate::get(const QScriptValuePrivate* d)
    148 {
    149     return QScriptValue(const_cast<QScriptValuePrivate*>(d));
    150 }
    151 
    152 QScriptValue QScriptValuePrivate::get(QScriptValuePrivate* d)
    153 {
    154     return QScriptValue(d);
    155 }
    156 
    157 QScriptValuePrivate::~QScriptValuePrivate()
    158 {
    159     if (m_value)
    160         JSValueUnprotect(context(), m_value);
    161 }
    162 
    163 QScriptValuePrivate::QScriptValuePrivate()
    164     : m_state(Invalid)
    165     , m_value(0)
    166 {
    167 }
    168 
    169 QScriptValuePrivate::QScriptValuePrivate(const QString& string)
    170     : m_state(CString)
    171     , m_string(string)
    172     , m_value(0)
    173 {
    174 }
    175 
    176 QScriptValuePrivate::QScriptValuePrivate(bool value)
    177     : m_state(CBool)
    178     , m_number(value)
    179     , m_value(0)
    180 {
    181 }
    182 
    183 QScriptValuePrivate::QScriptValuePrivate(int number)
    184     : m_state(CNumber)
    185     , m_number(number)
    186     , m_value(0)
    187 {
    188 }
    189 
    190 QScriptValuePrivate::QScriptValuePrivate(uint number)
    191     : m_state(CNumber)
    192     , m_number(number)
    193     , m_value(0)
    194 {
    195 }
    196 
    197 QScriptValuePrivate::QScriptValuePrivate(qsreal number)
    198     : m_state(CNumber)
    199     , m_number(number)
    200     , m_value(0)
    201 {
    202 }
    203 
    204 QScriptValuePrivate::QScriptValuePrivate(QScriptValue::SpecialValue value)
    205     : m_state(CSpecial)
    206     , m_number(value)
    207     , m_value(0)
    208 {
    209 }
    210 
    211 QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, bool value)
    212     : m_state(JSNative)
    213 {
    214     if (!engine) {
    215         // slower path reinitialization
    216         m_state = CBool;
    217         m_number = value;
    218         m_value = 0;
    219     } else {
    220         m_engine = QScriptEnginePrivate::get(engine);
    221         m_value = m_engine->makeJSValue(value);
    222         JSValueProtect(context(), m_value);
    223     }
    224 }
    225 
    226 QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, int value)
    227     : m_state(JSNative)
    228 {
    229     if (!engine) {
    230         // slower path reinitialization
    231         m_state = CNumber;
    232         m_number = value;
    233         m_value = 0;
    234     } else {
    235         m_engine = QScriptEnginePrivate::get(engine);
    236         m_value = m_engine->makeJSValue(value);
    237         JSValueProtect(context(), m_value);
    238     }
    239 }
    240 
    241 QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, uint value)
    242     : m_state(JSNative)
    243 {
    244     if (!engine) {
    245         // slower path reinitialization
    246         m_state = CNumber;
    247         m_number = value;
    248         m_value = 0;
    249     } else {
    250         m_engine = QScriptEnginePrivate::get(engine);
    251         m_value = m_engine->makeJSValue(value);
    252         JSValueProtect(context(), m_value);
    253     }
    254 }
    255 
    256 QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, qsreal value)
    257     : m_state(JSNative)
    258 {
    259     if (!engine) {
    260         // slower path reinitialization
    261         m_state = CNumber;
    262         m_number = value;
    263         m_value = 0;
    264     } else {
    265         m_engine = QScriptEnginePrivate::get(engine);
    266         m_value = m_engine->makeJSValue(value);
    267         JSValueProtect(context(), m_value);
    268     }
    269 }
    270 
    271 QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, const QString& value)
    272     : m_state(JSNative)
    273 {
    274     if (!engine) {
    275         // slower path reinitialization
    276         m_state = CString;
    277         m_string = value;
    278         m_value = 0;
    279     } else {
    280         m_engine = QScriptEnginePrivate::get(engine);
    281         m_value = m_engine->makeJSValue(value);
    282         JSValueProtect(context(), m_value);
    283     }
    284 }
    285 
    286 QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, QScriptValue::SpecialValue value)
    287     : m_state(JSNative)
    288 {
    289     if (!engine) {
    290         // slower path reinitialization
    291         m_state = CSpecial;
    292         m_number = value;
    293         m_value = 0;
    294     } else {
    295         m_engine = QScriptEnginePrivate::get(engine);
    296         m_value = m_engine->makeJSValue(value);
    297         JSValueProtect(context(), m_value);
    298     }
    299 }
    300 
    301 QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value)
    302     : m_state(JSValue)
    303     , m_engine(const_cast<QScriptEnginePrivate*>(engine))
    304     , m_value(value)
    305 {
    306     Q_ASSERT(engine);
    307     JSValueProtect(context(), m_value);
    308 }
    309 
    310 QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value, JSObjectRef object)
    311     : m_state(JSObject)
    312     , m_engine(const_cast<QScriptEnginePrivate*>(engine))
    313     , m_value(value)
    314     , m_object(object)
    315 {
    316     Q_ASSERT(engine);
    317     JSValueProtect(context(), m_value);
    318 }
    319 
    320 bool QScriptValuePrivate::isValid() const { return m_state != Invalid; }
    321 
    322 bool QScriptValuePrivate::isBool()
    323 {
    324     switch (m_state) {
    325     case CBool:
    326         return true;
    327     case JSValue:
    328         if (isObject())
    329             return false;
    330         // Fall-through.
    331     case JSNative:
    332         return JSValueIsBoolean(context(), value());
    333     default:
    334         return false;
    335     }
    336 }
    337 
    338 bool QScriptValuePrivate::isNumber()
    339 {
    340     switch (m_state) {
    341     case CNumber:
    342         return true;
    343     case JSValue:
    344         if (isObject())
    345             return false;
    346         // Fall-through.
    347     case JSNative:
    348         return JSValueIsNumber(context(), value());
    349     default:
    350         return false;
    351     }
    352 }
    353 
    354 bool QScriptValuePrivate::isNull()
    355 {
    356     switch (m_state) {
    357     case CSpecial:
    358         return m_number == static_cast<int>(QScriptValue::NullValue);
    359     case JSValue:
    360         if (isObject())
    361             return false;
    362         // Fall-through.
    363     case JSNative:
    364         return JSValueIsNull(context(), value());
    365     default:
    366         return false;
    367     }
    368 }
    369 
    370 bool QScriptValuePrivate::isString()
    371 {
    372     switch (m_state) {
    373     case CString:
    374         return true;
    375     case JSValue:
    376         if (isObject())
    377             return false;
    378         // Fall-through.
    379     case JSNative:
    380         return JSValueIsString(context(), value());
    381     default:
    382         return false;
    383     }
    384 }
    385 
    386 bool QScriptValuePrivate::isUndefined()
    387 {
    388     switch (m_state) {
    389     case CSpecial:
    390         return m_number == static_cast<int>(QScriptValue::UndefinedValue);
    391     case JSValue:
    392         if (isObject())
    393             return false;
    394         // Fall-through.
    395     case JSNative:
    396         return JSValueIsUndefined(context(), value());
    397     default:
    398         return false;
    399     }
    400 }
    401 
    402 bool QScriptValuePrivate::isError()
    403 {
    404     switch (m_state) {
    405     case JSValue:
    406         if (!isObject())
    407             return false;
    408         // Fall-through.
    409     case JSObject:
    410         return inherits("Error");
    411     default:
    412         return false;
    413     }
    414 }
    415 
    416 bool QScriptValuePrivate::isObject()
    417 {
    418     switch (m_state) {
    419     case JSObject:
    420         return true;
    421     case JSValue:
    422         m_object = JSValueToObject(context(), value(), /* exception */ 0);
    423         if (!m_object)
    424             return false;
    425         m_state = JSObject;
    426         return true;
    427     default:
    428         return false;
    429     }
    430 }
    431 
    432 bool QScriptValuePrivate::isFunction()
    433 {
    434     switch (m_state) {
    435     case JSValue:
    436         m_object = JSValueToObject(context(), value(), /* exception */ 0);
    437         if (!m_object)
    438             return false;
    439         m_state = JSObject;
    440         // Fall-through.
    441     case JSObject:
    442         return JSObjectIsFunction(context(), object());
    443     default:
    444         return false;
    445     }
    446 }
    447 
    448 QString QScriptValuePrivate::toString() const
    449 {
    450     switch (m_state) {
    451     case Invalid:
    452         return QString();
    453     case CBool:
    454         return m_number ? QString::fromLatin1("true") : QString::fromLatin1("false");
    455     case CString:
    456         return m_string;
    457     case CNumber:
    458         return QString::number(m_number);
    459     case CSpecial:
    460         return m_number == QScriptValue::NullValue ? QString::fromLatin1("null") : QString::fromLatin1("undefined");
    461     case JSValue:
    462     case JSNative:
    463     case JSObject:
    464         return QScriptConverter::toString(JSValueToStringCopy(context(), value(), /* exception */ 0));
    465     }
    466 
    467     Q_ASSERT_X(false, "toString()", "Not all states are included in the previous switch statement.");
    468     return QString(); // Avoid compiler warning.
    469 }
    470 
    471 qsreal QScriptValuePrivate::toNumber() const
    472 {
    473     switch (m_state) {
    474     case JSValue:
    475     case JSNative:
    476     case JSObject:
    477         return JSValueToNumber(context(), value(), /* exception */ 0);
    478     case CNumber:
    479         return m_number;
    480     case CBool:
    481         return m_number ? 1 : 0;
    482     case Invalid:
    483         return 0;
    484     case CSpecial:
    485         return m_number == QScriptValue::NullValue ? 0 : qQNaN();
    486     case CString:
    487         bool ok;
    488         qsreal result = m_string.toDouble(&ok);
    489         if (ok)
    490             return result;
    491         result = m_string.toInt(&ok, 0); // Try other bases.
    492         if (ok)
    493             return result;
    494         if (m_string == "Infinity" || m_string == "-Infinity")
    495             return qInf();
    496         return m_string.length() ? qQNaN() : 0;
    497     }
    498 
    499     Q_ASSERT_X(false, "toNumber()", "Not all states are included in the previous switch statement.");
    500     return 0; // Avoid compiler warning.
    501 }
    502 
    503 bool QScriptValuePrivate::toBool() const
    504 {
    505     switch (m_state) {
    506     case JSValue:
    507     case JSNative:
    508         return JSValueToBoolean(context(), value());
    509     case JSObject:
    510         return true;
    511     case CNumber:
    512         return !(qIsNaN(m_number) || !m_number);
    513     case CBool:
    514         return m_number;
    515     case Invalid:
    516     case CSpecial:
    517         return false;
    518     case CString:
    519         return m_string.length();
    520     }
    521 
    522     Q_ASSERT_X(false, "toBool()", "Not all states are included in the previous switch statement.");
    523     return false; // Avoid compiler warning.
    524 }
    525 
    526 qsreal QScriptValuePrivate::toInteger() const
    527 {
    528     // TODO it is not true implementation!
    529     return toNumber();
    530 }
    531 
    532 qint32 QScriptValuePrivate::toInt32() const
    533 {
    534     // TODO it is not true implementation!
    535     return toNumber();
    536 }
    537 
    538 quint32 QScriptValuePrivate::toUInt32() const
    539 {
    540     // TODO it is not true implementation!
    541     return toNumber();
    542 }
    543 
    544 quint16 QScriptValuePrivate::toUInt16() const
    545 {
    546     // TODO it is not true implementation!
    547     return toNumber();
    548 }
    549 
    550 
    551 bool QScriptValuePrivate::equals(QScriptValuePrivate* other)
    552 {
    553     if (!isValid() || !other->isValid())
    554         return false;
    555 
    556     if ((m_state == other->m_state) && !isJSBased()) {
    557         if (isNumberBased())
    558             return m_number == other->m_number;
    559         return m_string == other->m_string;
    560     }
    561 
    562     if (isJSBased() && !other->isJSBased()) {
    563         if (!other->assignEngine(engine())) {
    564             qWarning("equals(): Cannot compare to a value created in a different engine");
    565             return false;
    566         }
    567     } else if (!isJSBased() && other->isJSBased()) {
    568         if (!other->assignEngine(other->engine())) {
    569             qWarning("equals(): Cannot compare to a value created in a different engine");
    570             return false;
    571         }
    572     }
    573 
    574     return JSValueIsEqual(context(), value(), other->value(), /* exception */ 0);
    575 }
    576 
    577 bool QScriptValuePrivate::strictlyEquals(const QScriptValuePrivate* other) const
    578 {
    579     if (m_state != other->m_state)
    580         return false;
    581     if (isJSBased()) {
    582         if (other->engine() != engine()) {
    583             qWarning("strictlyEquals(): Cannot compare to a value created in a different engine");
    584             return false;
    585         }
    586         return JSValueIsStrictEqual(context(), value(), other->value());
    587     }
    588     if (isStringBased())
    589         return m_string == other->m_string;
    590     if (isNumberBased())
    591         return m_number == other->m_number;
    592 
    593     return false; // Invalid state.
    594 }
    595 
    596 /*!
    597   Tries to assign \a engine to this value. Returns true on success; otherwise returns false.
    598 */
    599 bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
    600 {
    601     JSValueRef value;
    602     switch (m_state) {
    603     case CBool:
    604         value = engine->makeJSValue(static_cast<bool>(m_number));
    605         break;
    606     case CString:
    607         value = engine->makeJSValue(m_string);
    608         break;
    609     case CNumber:
    610         value = engine->makeJSValue(m_number);
    611         break;
    612     case CSpecial:
    613         value = engine->makeJSValue(static_cast<QScriptValue::SpecialValue>(m_number));
    614         break;
    615     default:
    616         if (!isJSBased())
    617             Q_ASSERT_X(!isJSBased(), "assignEngine()", "Not all states are included in the previous switch statement.");
    618         else
    619             qWarning("JSValue can't be rassigned to an another engine.");
    620         return false;
    621     }
    622     m_engine = engine;
    623     m_state = JSNative;
    624     setValue(value);
    625     return true;
    626 }
    627 
    628 QScriptValuePrivate* QScriptValuePrivate::call(const QScriptValuePrivate*, const QScriptValueList& args)
    629 {
    630     switch (m_state) {
    631     case JSValue:
    632         m_object = JSValueToObject(context(), value(), /* exception */ 0);
    633         if (!object()) {
    634             m_state = JSValue;
    635             return new QScriptValuePrivate;
    636         }
    637         m_state = JSObject;
    638         // Fall-through.
    639     case JSObject:
    640         {
    641             // Convert all arguments and bind to the engine.
    642             int argc = args.size();
    643             QVarLengthArray<JSValueRef, 8> argv(argc);
    644             QScriptValueList::const_iterator i = args.constBegin();
    645             for (int j = 0; i != args.constEnd(); j++, i++) {
    646                 QScriptValuePrivate* value = QScriptValuePrivate::get(*i);
    647                 if (!value->assignEngine(engine())) {
    648                     qWarning("QScriptValue::call() failed: cannot call function with values created in a different engine");
    649                     return new QScriptValuePrivate;
    650                 }
    651                 argv[j] = value->value();
    652             }
    653 
    654             // Make the call
    655             JSValueRef exception = 0;
    656             JSValueRef result = JSObjectCallAsFunction(context(), object(), /* thisObject */ 0, argc, argv.constData(), &exception);
    657             if (!result && exception)
    658                 return new QScriptValuePrivate(engine(), exception);
    659             if (result && !exception)
    660                 return new QScriptValuePrivate(engine(), result);
    661         }
    662         // this QSV is not a function <-- !result && !exception. Fall-through.
    663     default:
    664         return new QScriptValuePrivate;
    665     }
    666 }
    667 
    668 QScriptEnginePrivate* QScriptValuePrivate::engine() const
    669 {
    670     // As long as m_engine is an autoinitializated pointer we can safely return it without
    671     // checking current state.
    672     return m_engine.data();
    673 }
    674 
    675 JSGlobalContextRef QScriptValuePrivate::context() const
    676 {
    677     Q_ASSERT(isJSBased());
    678     return m_engine->context();
    679 }
    680 
    681 JSValueRef QScriptValuePrivate::value() const
    682 {
    683     Q_ASSERT(isJSBased());
    684     return m_value;
    685 }
    686 
    687 JSObjectRef QScriptValuePrivate::object() const
    688 {
    689     Q_ASSERT(m_state == JSObject);
    690     return m_object;
    691 }
    692 
    693 void QScriptValuePrivate::setValue(JSValueRef value)
    694 {
    695     if (m_value)
    696         JSValueUnprotect(context(), m_value);
    697     if (value)
    698         JSValueProtect(context(), value);
    699     m_value = value;
    700 }
    701 
    702 /*!
    703   \internal
    704   Returns true if QSV is created from constructor with the given \a name, it has to be a
    705   built-in type.
    706 */
    707 bool QScriptValuePrivate::inherits(const char* name)
    708 {
    709     Q_ASSERT(isJSBased());
    710     JSObjectRef globalObject = JSContextGetGlobalObject(context());
    711     JSValueRef error = JSObjectGetProperty(context(), globalObject, QScriptConverter::toString(name), 0);
    712     return JSValueIsInstanceOfConstructor(context(), value(), JSValueToObject(context(), error, /* exception */ 0), /* exception */ 0);
    713 }
    714 
    715 /*!
    716   \internal
    717   Returns true if QSV have an engine associated.
    718 */
    719 bool QScriptValuePrivate::isJSBased() const { return m_state >= JSValue; }
    720 
    721 /*!
    722   \internal
    723   Returns true if current value of QSV is placed in m_number.
    724 */
    725 bool QScriptValuePrivate::isNumberBased() const { return !isJSBased() && !isStringBased() && m_state != Invalid; }
    726 
    727 /*!
    728   \internal
    729   Returns true if current value of QSV is placed in m_string.
    730 */
    731 bool QScriptValuePrivate::isStringBased() const { return m_state == CString; }
    732 
    733 #endif // qscriptvalue_p_h
    734