diff options
Diffstat (limited to 'JavaScriptCore/qt/api')
-rw-r--r-- | JavaScriptCore/qt/api/QtScript.pro | 12 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptconverter_p.h | 82 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptengine.cpp | 78 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptengine.h | 10 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptengine_p.cpp | 40 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptengine_p.h | 44 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptprogram.cpp | 136 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptprogram.h | 53 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptprogram_p.h | 129 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptstring.cpp | 131 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptstring.h | 58 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptstring_p.h | 112 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptsyntaxcheckresult.cpp | 148 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptsyntaxcheckresult.h | 50 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptsyntaxcheckresult_p.h | 73 | ||||
-rw-r--r-- | JavaScriptCore/qt/api/qscriptvalue_p.h | 96 |
16 files changed, 1203 insertions, 49 deletions
diff --git a/JavaScriptCore/qt/api/QtScript.pro b/JavaScriptCore/qt/api/QtScript.pro index c87eaf4..88629c7 100644 --- a/JavaScriptCore/qt/api/QtScript.pro +++ b/JavaScriptCore/qt/api/QtScript.pro @@ -13,14 +13,20 @@ CONFIG(debug, debug|release) { OBJECTS_DIR = obj/release } +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../.. include($$PWD/../../../WebKit.pri) + include($$PWD/../../JavaScriptCore.pri) +addJavaScriptCoreLib(../..) INCLUDEPATH += $$PWD/../../API SOURCES += $$PWD/qscriptengine.cpp \ $$PWD/qscriptengine_p.cpp \ $$PWD/qscriptvalue.cpp \ + $$PWD/qscriptstring.cpp \ + $$PWD/qscriptprogram.cpp \ + $$PWD/qscriptsyntaxcheckresult.cpp \ HEADERS += $$PWD/qtscriptglobal.h \ $$PWD/qscriptengine.h \ @@ -28,9 +34,13 @@ HEADERS += $$PWD/qtscriptglobal.h \ $$PWD/qscriptvalue.h \ $$PWD/qscriptvalue_p.h \ $$PWD/qscriptconverter_p.h \ + $$PWD/qscriptstring.h \ + $$PWD/qscriptstring_p.h \ + $$PWD/qscriptprogram.h \ + $$PWD/qscriptprogram_p.h \ + $$PWD/qscriptsyntaxcheckresult.h \ !static: DEFINES += QT_MAKEDLL DESTDIR = $$OUTPUT_DIR/lib - diff --git a/JavaScriptCore/qt/api/qscriptconverter_p.h b/JavaScriptCore/qt/api/qscriptconverter_p.h index c3ca41f..cd86e20 100644 --- a/JavaScriptCore/qt/api/qscriptconverter_p.h +++ b/JavaScriptCore/qt/api/qscriptconverter_p.h @@ -21,7 +21,11 @@ #define qscriptconverter_p_h #include <JavaScriptCore/JavaScript.h> +#include <QtCore/qnumeric.h> #include <QtCore/qstring.h> +#include <QtCore/qvarlengtharray.h> + +extern char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **digits_str); /* \internal @@ -33,6 +37,19 @@ */ class QScriptConverter { public: + static quint32 toArrayIndex(const JSStringRef jsstring) + { + // FIXME this function should be exported by JSC C API. + QString qstring = toString(jsstring); + + bool ok; + quint32 idx = qstring.toUInt(&ok); + if (!ok || toString(idx) != qstring) + idx = 0xffffffff; + + return idx; + } + static QString toString(const JSStringRef str) { return QString(reinterpret_cast<const QChar*>(JSStringGetCharactersPtr(str)), JSStringGetLength(str)); @@ -45,6 +62,71 @@ public: { return JSStringCreateWithUTF8CString(str); } + static QString toString(double value) + { + // FIXME this should be easier. The ideal fix is to create + // a new function in JSC C API which could cover the functionality. + + if (qIsNaN(value)) + return QString::fromLatin1("NaN"); + if (qIsInf(value)) + return QString::fromLatin1(value < 0 ? "-Infinity" : "Infinity"); + if (!value) + return QString::fromLatin1("0"); + + QVarLengthArray<char, 25> buf; + int decpt; + int sign; + char* result = 0; + char* endresult; + (void)qdtoa(value, 0, 0, &decpt, &sign, &endresult, &result); + + if (!result) + return QString(); + + int resultLen = endresult - result; + if (decpt <= 0 && decpt > -6) { + buf.resize(-decpt + 2 + sign); + qMemSet(buf.data(), '0', -decpt + 2 + sign); + if (sign) // fix the sign. + buf[0] = '-'; + buf[sign + 1] = '.'; + buf.append(result, resultLen); + } else { + if (sign) + buf.append('-'); + int length = buf.size() - sign + resultLen; + if (decpt <= 21 && decpt > 0) { + if (length <= decpt) { + const char* zeros = "0000000000000000000000000"; + buf.append(result, resultLen); + buf.append(zeros, decpt - length); + } else { + buf.append(result, decpt); + buf.append('.'); + buf.append(result + decpt, resultLen - decpt); + } + } else if (result[0] >= '0' && result[0] <= '9') { + if (length > 1) { + buf.append(result, 1); + buf.append('.'); + buf.append(result + 1, resultLen - 1); + } else + buf.append(result, resultLen); + buf.append('e'); + buf.append(decpt >= 0 ? '+' : '-'); + int e = qAbs(decpt - 1); + if (e >= 100) + buf.append('0' + e / 100); + if (e >= 10) + buf.append('0' + (e % 100) / 10); + buf.append('0' + e % 10); + } + } + free(result); + buf.append(0); + return QString::fromLatin1(buf.constData()); + } }; #endif // qscriptconverter_p_h diff --git a/JavaScriptCore/qt/api/qscriptengine.cpp b/JavaScriptCore/qt/api/qscriptengine.cpp index fbeb902..d49c578 100644 --- a/JavaScriptCore/qt/api/qscriptengine.cpp +++ b/JavaScriptCore/qt/api/qscriptengine.cpp @@ -22,6 +22,8 @@ #include "qscriptengine.h" #include "qscriptengine_p.h" +#include "qscriptprogram_p.h" +#include "qscriptsyntaxcheckresult_p.h" #include "qscriptvalue_p.h" /*! @@ -42,6 +44,23 @@ QScriptEngine::~QScriptEngine() } /*! + Checks the syntax of the given \a program. Returns a + QScriptSyntaxCheckResult object that contains the result of the check. +*/ +QScriptSyntaxCheckResult QScriptEngine::checkSyntax(const QString &program) +{ + // FIXME This is not optimal. + // The JSC C API needs a context to perform a syntax check, it means that a QScriptEnginePrivate + // had to be created. This function is static so we have to create QScriptEnginePrivate for each + // call. We can't remove the "static" for compatibility reason, at least up to Qt5. + // QScriptSyntaxCheckResultPrivate takes ownership of newly created engine. The engine will be + // kept as long as it is needed for lazy evaluation of properties of + // the QScriptSyntaxCheckResultPrivate. + QScriptEnginePrivate* engine = new QScriptEnginePrivate(/* q_ptr */ 0); + return QScriptSyntaxCheckResultPrivate::get(engine->checkSyntax(program)); +} + +/*! Evaluates \a program, using \a lineNumber as the base line number, and returns the result of the evaluation. @@ -71,6 +90,11 @@ QScriptValue QScriptEngine::evaluate(const QString& program, const QString& file return QScriptValuePrivate::get(d_ptr->evaluate(program, fileName, lineNumber)); } +QScriptValue QScriptEngine::evaluate(const QScriptProgram& program) +{ + return QScriptValuePrivate::get(d_ptr->evaluate(QScriptProgramPrivate::get(program))); +} + /*! Runs the garbage collector. @@ -81,6 +105,8 @@ QScriptValue QScriptEngine::evaluate(const QString& program, const QString& file when the QScriptEngine decides that it's wise to do so (i.e. when a certain number of new objects have been created). However, you can call this function to explicitly request that garbage collection should be performed as soon as possible. + + \sa reportAdditionalMemoryCost() */ void QScriptEngine::collectGarbage() { @@ -88,6 +114,43 @@ void QScriptEngine::collectGarbage() } /*! + Reports an additional memory cost of the given \a size, measured in + bytes, to the garbage collector. + + This function can be called to indicate that a JavaScript object has + memory associated with it that isn't managed by Qt Script itself. + Reporting the additional cost makes it more likely that the garbage + collector will be triggered. + + Note that if the additional memory is shared with objects outside + the scripting environment, the cost should not be reported, since + collecting the JavaScript object would not cause the memory to be + freed anyway. + + Negative \a size values are ignored, i.e. this function can't be + used to report that the additional memory has been deallocated. + + \sa collectGarbage() +*/ +void QScriptEngine::reportAdditionalMemoryCost(int cost) +{ + d_ptr->reportAdditionalMemoryCost(cost); +} + +/*! + Returns a handle that represents the given string, \a str. + + QScriptString can be used to quickly look up properties, and + compare property names, of script objects. + + \sa QScriptValue::property() +*/ +QScriptString QScriptEngine::toStringHandle(const QString& str) +{ + return QScriptStringPrivate::get(d_ptr->toStringHandle(str)); +} + +/*! Returns a QScriptValue of the primitive type Null. \sa undefinedValue() @@ -106,3 +169,18 @@ QScriptValue QScriptEngine::undefinedValue() { return QScriptValue(this, QScriptValue::UndefinedValue); } + +/*! + Returns this engine's Global Object. + + By default, the Global Object contains the built-in objects that are + part of \l{ECMA-262}, such as Math, Date and String. Additionally, + you can set properties of the Global Object to make your own + extensions available to all script code. Non-local variables in + script code will be created as properties of the Global Object, as + well as local variables in global code. +*/ +QScriptValue QScriptEngine::globalObject() const +{ + return QScriptValuePrivate::get(d_ptr->globalObject()); +} diff --git a/JavaScriptCore/qt/api/qscriptengine.h b/JavaScriptCore/qt/api/qscriptengine.h index b8bd5e6..e10888d 100644 --- a/JavaScriptCore/qt/api/qscriptengine.h +++ b/JavaScriptCore/qt/api/qscriptengine.h @@ -20,6 +20,9 @@ #ifndef qscriptengine_h #define qscriptengine_h +#include "qscriptprogram.h" +#include "qscriptstring.h" +#include "qscriptsyntaxcheckresult.h" #include <QtCore/qobject.h> #include <QtCore/qshareddata.h> #include <QtCore/qstring.h> @@ -35,11 +38,18 @@ public: QScriptEngine(); ~QScriptEngine(); + static QScriptSyntaxCheckResult checkSyntax(const QString& program); QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1); + QScriptValue evaluate(const QScriptProgram& program); + void collectGarbage(); + void reportAdditionalMemoryCost(int cost); + + QScriptString toStringHandle(const QString& str); QScriptValue nullValue(); QScriptValue undefinedValue(); + QScriptValue globalObject() const; private: friend class QScriptEnginePrivate; diff --git a/JavaScriptCore/qt/api/qscriptengine_p.cpp b/JavaScriptCore/qt/api/qscriptengine_p.cpp index de8a355..38185ab 100644 --- a/JavaScriptCore/qt/api/qscriptengine_p.cpp +++ b/JavaScriptCore/qt/api/qscriptengine_p.cpp @@ -21,6 +21,7 @@ #include "qscriptengine_p.h" +#include "qscriptprogram_p.h" #include "qscriptvalue_p.h" /*! @@ -38,6 +39,19 @@ QScriptEnginePrivate::~QScriptEnginePrivate() JSGlobalContextRelease(m_context); } +QScriptSyntaxCheckResultPrivate* QScriptEnginePrivate::checkSyntax(const QString& program) +{ + JSValueRef exception; + JSStringRef source = QScriptConverter::toString(program); + bool syntaxIsCorrect = JSCheckScriptSyntax(m_context, source, /* url */ 0, /* starting line */ 1, &exception); + JSStringRelease(source); + if (syntaxIsCorrect) { + return new QScriptSyntaxCheckResultPrivate(this); + } + JSValueProtect(m_context, exception); + return new QScriptSyntaxCheckResultPrivate(this, const_cast<JSObjectRef>(exception)); +} + /*! Evaluates program and returns the result of the evaluation. \internal @@ -46,9 +60,25 @@ QScriptValuePrivate* QScriptEnginePrivate::evaluate(const QString& program, cons { JSStringRef script = QScriptConverter::toString(program); JSStringRef file = QScriptConverter::toString(fileName); - JSValueRef exception; - JSValueRef result = JSEvaluateScript(m_context, script, /* Global Object */ 0, file, lineNumber, &exception); - if (!result) - return new QScriptValuePrivate(this, exception); // returns an exception - return new QScriptValuePrivate(this, result); + QScriptValuePrivate* result = new QScriptValuePrivate(this, evaluate(script, file, lineNumber)); + JSStringRelease(script); + JSStringRelease(file); + return result; +} + +/*! + Evaluates program and returns the result of the evaluation. + \internal +*/ +QScriptValuePrivate* QScriptEnginePrivate::evaluate(const QScriptProgramPrivate* program) +{ + if (program->isNull()) + return new QScriptValuePrivate; + return new QScriptValuePrivate(this, evaluate(program->program(), program->file(), program->line())); +} + +QScriptValuePrivate* QScriptEnginePrivate::globalObject() const +{ + JSObjectRef globalObject = JSContextGetGlobalObject(context()); + return new QScriptValuePrivate(this, globalObject, globalObject); } diff --git a/JavaScriptCore/qt/api/qscriptengine_p.h b/JavaScriptCore/qt/api/qscriptengine_p.h index 8e27c42..2bda68e 100644 --- a/JavaScriptCore/qt/api/qscriptengine_p.h +++ b/JavaScriptCore/qt/api/qscriptengine_p.h @@ -22,12 +22,16 @@ #include "qscriptconverter_p.h" #include "qscriptengine.h" +#include "qscriptstring_p.h" +#include "qscriptsyntaxcheckresult_p.h" #include "qscriptvalue.h" #include <JavaScriptCore/JavaScript.h> +#include <JSBasePrivate.h> #include <QtCore/qshareddata.h> #include <QtCore/qstring.h> class QScriptEngine; +class QScriptSyntaxCheckResultPrivate; class QScriptEnginePrivate : public QSharedData { public: @@ -37,8 +41,13 @@ public: QScriptEnginePrivate(const QScriptEngine*); ~QScriptEnginePrivate(); + QScriptSyntaxCheckResultPrivate* checkSyntax(const QString& program); QScriptValuePrivate* evaluate(const QString& program, const QString& fileName, int lineNumber); + QScriptValuePrivate* evaluate(const QScriptProgramPrivate* program); + inline JSValueRef evaluate(JSStringRef program, JSStringRef fileName, int lineNumber); + inline void collectGarbage(); + inline void reportAdditionalMemoryCost(int cost); inline JSValueRef makeJSValue(double number) const; inline JSValueRef makeJSValue(int number) const; @@ -47,17 +56,42 @@ public: inline JSValueRef makeJSValue(bool number) const; inline JSValueRef makeJSValue(QScriptValue::SpecialValue value) const; + QScriptValuePrivate* globalObject() const; + + inline QScriptStringPrivate* toStringHandle(const QString& str) const; + inline JSGlobalContextRef context() const; private: QScriptEngine* q_ptr; JSGlobalContextRef m_context; }; + +/*! + Evaluates given JavaScript program and returns result of the evaluation. + \attention this function doesn't take ownership of the parameters. + \internal +*/ +JSValueRef QScriptEnginePrivate::evaluate(JSStringRef program, JSStringRef fileName, int lineNumber) +{ + JSValueRef exception; + JSValueRef result = JSEvaluateScript(m_context, program, /* Global Object */ 0, fileName, lineNumber, &exception); + if (!result) + return exception; // returns an exception + return result; +} + void QScriptEnginePrivate::collectGarbage() { JSGarbageCollect(m_context); } +void QScriptEnginePrivate::reportAdditionalMemoryCost(int cost) +{ + if (cost > 0) + JSReportExtraMemoryCost(m_context, cost); +} + JSValueRef QScriptEnginePrivate::makeJSValue(double number) const { return JSValueMakeNumber(m_context, number); @@ -75,7 +109,10 @@ JSValueRef QScriptEnginePrivate::makeJSValue(uint number) const JSValueRef QScriptEnginePrivate::makeJSValue(const QString& string) const { - return JSValueMakeString(m_context, QScriptConverter::toString(string)); + JSStringRef tmp = QScriptConverter::toString(string); + JSValueRef result = JSValueMakeString(m_context, tmp); + JSStringRelease(tmp); + return result; } JSValueRef QScriptEnginePrivate::makeJSValue(bool value) const @@ -90,6 +127,11 @@ JSValueRef QScriptEnginePrivate::makeJSValue(QScriptValue::SpecialValue value) c return JSValueMakeUndefined(m_context); } +QScriptStringPrivate* QScriptEnginePrivate::toStringHandle(const QString& str) const +{ + return new QScriptStringPrivate(str); +} + JSGlobalContextRef QScriptEnginePrivate::context() const { return m_context; diff --git a/JavaScriptCore/qt/api/qscriptprogram.cpp b/JavaScriptCore/qt/api/qscriptprogram.cpp new file mode 100644 index 0000000..d7d4948 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptprogram.cpp @@ -0,0 +1,136 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#include "qscriptprogram.h" + +#include "qscriptprogram_p.h" + +/*! + \internal + + \class QScriptProgram + + \brief The QScriptProgram class encapsulates a Qt Script program. + + \ingroup script + + QScriptProgram retains the compiled representation of the script if + possible. Thus, QScriptProgram can be used to evaluate the same + script multiple times more efficiently. + + \code + QScriptEngine engine; + QScriptProgram program("1 + 2"); + QScriptValue result = engine.evaluate(program); + \endcode +*/ + +/*! + Constructs a null QScriptProgram. +*/ +QScriptProgram::QScriptProgram() + : d_ptr(new QScriptProgramPrivate) +{} + +/*! + Constructs a new QScriptProgram with the given \a sourceCode, \a + fileName and \a firstLineNumber. +*/ +QScriptProgram::QScriptProgram(const QString& sourceCode, + const QString fileName, + int firstLineNumber) + : d_ptr(new QScriptProgramPrivate(sourceCode, fileName, firstLineNumber)) +{} + +/*! + Destroys this QScriptProgram. +*/ +QScriptProgram::~QScriptProgram() +{} + +/*! + Constructs a new QScriptProgram that is a copy of \a other. +*/ +QScriptProgram::QScriptProgram(const QScriptProgram& other) +{ + d_ptr = other.d_ptr; +} + +/*! + Assigns the \a other value to this QScriptProgram. +*/ +QScriptProgram& QScriptProgram::operator=(const QScriptProgram& other) +{ + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns true if this QScriptProgram is null; otherwise + returns false. +*/ +bool QScriptProgram::isNull() const +{ + return d_ptr->isNull(); +} + +/*! + Returns the source code of this program. +*/ +QString QScriptProgram::sourceCode() const +{ + return d_ptr->sourceCode(); +} + +/*! + Returns the filename associated with this program. +*/ +QString QScriptProgram::fileName() const +{ + return d_ptr->fileName(); +} + +/*! + Returns the line number associated with this program. +*/ +int QScriptProgram::firstLineNumber() const +{ + return d_ptr->firstLineNumber(); +} + +/*! + Returns true if this QScriptProgram is equal to \a other; + otherwise returns false. +*/ +bool QScriptProgram::operator==(const QScriptProgram& other) const +{ + return d_ptr == other.d_ptr || *d_ptr == *other.d_ptr; +} + +/*! + Returns true if this QScriptProgram is not equal to \a other; + otherwise returns false. +*/ +bool QScriptProgram::operator!=(const QScriptProgram& other) const +{ + return d_ptr != other.d_ptr && *d_ptr != *other.d_ptr; +} + diff --git a/JavaScriptCore/qt/api/qscriptprogram.h b/JavaScriptCore/qt/api/qscriptprogram.h new file mode 100644 index 0000000..93c8a3c --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptprogram.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef qscriptprogram_h +#define qscriptprogram_h + +#include "qtscriptglobal.h" +#include <QtCore/qshareddata.h> +#include <QtCore/qstring.h> + +class QScriptProgramPrivate; +class Q_JAVASCRIPT_EXPORT QScriptProgram { +public: + QScriptProgram(); + QScriptProgram(const QString& sourceCode, + const QString fileName = QString(), + int firstLineNumber = 1); + QScriptProgram(const QScriptProgram& other); + ~QScriptProgram(); + + QScriptProgram& operator=(const QScriptProgram& other); + + bool isNull() const; + + QString sourceCode() const; + QString fileName() const; + int firstLineNumber() const; + + bool operator==(const QScriptProgram& other) const; + bool operator!=(const QScriptProgram& other) const; + +private: + QExplicitlySharedDataPointer<QScriptProgramPrivate> d_ptr; + Q_DECLARE_PRIVATE(QScriptProgram) +}; + +#endif // qscriptprogram_h diff --git a/JavaScriptCore/qt/api/qscriptprogram_p.h b/JavaScriptCore/qt/api/qscriptprogram_p.h new file mode 100644 index 0000000..6e80e85 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptprogram_p.h @@ -0,0 +1,129 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef qscriptprogram_p_h +#define qscriptprogram_p_h + +#include "qscriptconverter_p.h" +#include "qscriptprogram.h" +#include <JavaScriptCore/JavaScript.h> +#include <QtCore/qshareddata.h> +#include <QtCore/qstring.h> + +/* + FIXME The QScriptProgramPrivate potentially could be much faster. In current implementation we + gain CPU time only by avoiding QString -> JSStringRef conversion. In the ideal world we should + have a function inside the JSC C API that could provide us "parse once, execute multiple times" + functionality. +*/ + +class QScriptProgramPrivate : public QSharedData { +public: + inline static QScriptProgramPrivate* get(const QScriptProgram& program); + inline QScriptProgramPrivate(); + inline QScriptProgramPrivate(const QString& sourceCode, + const QString fileName, + int firstLineNumber); + + inline ~QScriptProgramPrivate(); + + inline bool isNull() const; + + inline QString sourceCode() const; + inline QString fileName() const; + inline int firstLineNumber() const; + + inline bool operator==(const QScriptProgramPrivate& other) const; + inline bool operator!=(const QScriptProgramPrivate& other) const; + + inline JSStringRef program() const; + inline JSStringRef file() const; + inline int line() const; +private: + JSStringRef m_program; + JSStringRef m_fileName; + int m_line; +}; + +QScriptProgramPrivate* QScriptProgramPrivate::get(const QScriptProgram& program) +{ + return const_cast<QScriptProgramPrivate*>(program.d_ptr.constData()); +} + +QScriptProgramPrivate::QScriptProgramPrivate() + : m_program(0) + , m_fileName(0) + , m_line(-1) +{} + +QScriptProgramPrivate::QScriptProgramPrivate(const QString& sourceCode, + const QString fileName, + int firstLineNumber) + : m_program(QScriptConverter::toString(sourceCode)) + , m_fileName(QScriptConverter::toString(fileName)) + , m_line(firstLineNumber) +{} + +QScriptProgramPrivate::~QScriptProgramPrivate() +{ + if (!isNull()) { + JSStringRelease(m_program); + JSStringRelease(m_fileName); + } +} + +bool QScriptProgramPrivate::isNull() const +{ + return !m_program; +} + +QString QScriptProgramPrivate::sourceCode() const +{ + return QScriptConverter::toString(m_program); +} + +QString QScriptProgramPrivate::fileName() const +{ + return QScriptConverter::toString(m_fileName); +} + +int QScriptProgramPrivate::firstLineNumber() const +{ + return m_line; +} + +bool QScriptProgramPrivate::operator==(const QScriptProgramPrivate& other) const +{ + return m_line == other.m_line + && JSStringIsEqual(m_fileName, other.m_fileName) + && JSStringIsEqual(m_program, other.m_program); +} + +bool QScriptProgramPrivate::operator!=(const QScriptProgramPrivate& other) const +{ + return m_line != other.m_line + || !JSStringIsEqual(m_fileName, other.m_fileName) + || !JSStringIsEqual(m_program, other.m_program); +} + +JSStringRef QScriptProgramPrivate::program() const { return m_program; } +JSStringRef QScriptProgramPrivate::file() const {return m_fileName; } +int QScriptProgramPrivate::line() const { return m_line; } + +#endif // qscriptprogram_p_h diff --git a/JavaScriptCore/qt/api/qscriptstring.cpp b/JavaScriptCore/qt/api/qscriptstring.cpp new file mode 100644 index 0000000..83c03c5 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptstring.cpp @@ -0,0 +1,131 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#include "qscriptstring.h" + +#include "qscriptstring_p.h" +#include <QtCore/qhash.h> + +/*! + Constructs an invalid QScriptString. +*/ +QScriptString::QScriptString() + : d_ptr(new QScriptStringPrivate()) +{ +} +/*! + Constructs an QScriptString from internal representation + \internal +*/ +QScriptString::QScriptString(QScriptStringPrivate* d) + : d_ptr(d) +{ +} + +/*! + Constructs a new QScriptString that is a copy of \a other. +*/ +QScriptString::QScriptString(const QScriptString& other) +{ + d_ptr = other.d_ptr; +} + +/*! + Destroys this QScriptString. +*/ +QScriptString::~QScriptString() +{ +} + +/*! + Assigns the \a other value to this QScriptString. +*/ +QScriptString& QScriptString::operator=(const QScriptString& other) +{ + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns true if this QScriptString is valid; otherwise + returns false. +*/ +bool QScriptString::isValid() const +{ + return d_ptr->isValid(); +} + +/*! + Returns true if this QScriptString is equal to \a other; + otherwise returns false. +*/ +bool QScriptString::operator==(const QScriptString& other) const +{ + return d_ptr == other.d_ptr || *d_ptr == *(other.d_ptr); +} + +/*! + Returns true if this QScriptString is not equal to \a other; + otherwise returns false. +*/ +bool QScriptString::operator!=(const QScriptString& other) const +{ + return d_ptr != other.d_ptr || *d_ptr != *(other.d_ptr); +} + +/*! + Attempts to convert this QScriptString to a QtScript array index, + and returns the result. + + If a conversion error occurs, *\a{ok} is set to false; otherwise + *\a{ok} is set to true. +*/ +quint32 QScriptString::toArrayIndex(bool* ok) const +{ + return d_ptr->toArrayIndex(ok); +} + +/*! + Returns the string that this QScriptString represents, or a + null string if this QScriptString is not valid. + + \sa isValid() +*/ +QString QScriptString::toString() const +{ + return d_ptr->toString(); +} + +/*! + Returns the string that this QScriptString represents, or a + null string if this QScriptString is not valid. + + \sa toString() +*/ +QScriptString::operator QString() const +{ + return d_ptr->toString(); +} + +uint qHash(const QScriptString& key) +{ + return qHash(QScriptStringPrivate::get(key)->id()); +} diff --git a/JavaScriptCore/qt/api/qscriptstring.h b/JavaScriptCore/qt/api/qscriptstring.h new file mode 100644 index 0000000..16593bc --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptstring.h @@ -0,0 +1,58 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef qscriptstring_h +#define qscriptstring_h + +#include "qtscriptglobal.h" +#include <QtCore/qshareddata.h> +#include <QtCore/qstring.h> + +class QScriptStringPrivate; +typedef QExplicitlySharedDataPointer<QScriptStringPrivate> QScriptStringPtr; + +class Q_JAVASCRIPT_EXPORT QScriptString { +public: + QScriptString(); + QScriptString(const QScriptString& other); + ~QScriptString(); + + QScriptString& operator=(const QScriptString& other); + + bool isValid() const; + + bool operator==(const QScriptString& other) const; + bool operator!=(const QScriptString& other) const; + + quint32 toArrayIndex(bool* ok = 0) const; + + QString toString() const; + operator QString() const; + +private: + QScriptString(QScriptStringPrivate* d); + + QScriptStringPtr d_ptr; + + friend class QScriptStringPrivate; +}; + +uint qHash(const QScriptString& key); + +#endif // qscriptstring_h diff --git a/JavaScriptCore/qt/api/qscriptstring_p.h b/JavaScriptCore/qt/api/qscriptstring_p.h new file mode 100644 index 0000000..f4fd117 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptstring_p.h @@ -0,0 +1,112 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef qscriptstring_p_h +#define qscriptstring_p_h + +#include "qscriptconverter_p.h" +#include "qscriptstring.h" +#include <JavaScriptCore/JavaScript.h> +#include <QtCore/qnumeric.h> +#include <QtCore/qshareddata.h> + +class QScriptStringPrivate : public QSharedData { +public: + inline QScriptStringPrivate(); + inline QScriptStringPrivate(const QString& qtstring); + inline ~QScriptStringPrivate(); + + static inline QScriptString get(QScriptStringPrivate* d); + static inline QScriptStringPtr get(const QScriptString& p); + + inline bool isValid() const; + + inline bool operator==(const QScriptStringPrivate& other) const; + inline bool operator!=(const QScriptStringPrivate& other) const; + + inline quint32 toArrayIndex(bool* ok = 0) const; + + inline QString toString() const; + + inline quint64 id() const; + +private: + JSStringRef m_string; +}; + + +QScriptStringPrivate::QScriptStringPrivate() + : m_string(0) +{} + +QScriptStringPrivate::QScriptStringPrivate(const QString& qtstring) + : m_string(JSStringRetain(QScriptConverter::toString(qtstring))) +{} + +QScriptStringPrivate::~QScriptStringPrivate() +{ + if (isValid()) + JSStringRelease(m_string); +} + +QScriptString QScriptStringPrivate::get(QScriptStringPrivate* d) +{ + Q_ASSERT(d); + return QScriptString(d); +} + +QScriptStringPtr QScriptStringPrivate::get(const QScriptString& p) +{ + return p.d_ptr; +} + +bool QScriptStringPrivate::isValid() const +{ + return m_string; +} + +bool QScriptStringPrivate::operator==(const QScriptStringPrivate& other) const +{ + return isValid() && other.isValid() && JSStringIsEqual(m_string, other.m_string); +} + +bool QScriptStringPrivate::operator!=(const QScriptStringPrivate& other) const +{ + return isValid() && other.isValid() && !JSStringIsEqual(m_string, other.m_string); +} + +quint32 QScriptStringPrivate::toArrayIndex(bool* ok) const +{ + quint32 idx = QScriptConverter::toArrayIndex(m_string); + if (ok) + *ok = (idx != 0xffffffff); + return idx; +} + +QString QScriptStringPrivate::toString() const +{ + return QScriptConverter::toString(m_string); +} + +quint64 QScriptStringPrivate::id() const +{ + return reinterpret_cast<quint32>(m_string); +} + +#endif // qscriptstring_p_h diff --git a/JavaScriptCore/qt/api/qscriptsyntaxcheckresult.cpp b/JavaScriptCore/qt/api/qscriptsyntaxcheckresult.cpp new file mode 100644 index 0000000..5cf02ef --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptsyntaxcheckresult.cpp @@ -0,0 +1,148 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#include "qscriptsyntaxcheckresult.h" +#include "qscriptsyntaxcheckresult_p.h" + +/*! + \class QScriptSyntaxCheckResult + + \brief The QScriptSyntaxCheckResult class provides the result of a script syntax check. + + \ingroup script + \mainclass + + QScriptSyntaxCheckResult is returned by QScriptEngine::checkSyntax() to + provide information about the syntactical (in)correctness of a script. +*/ + +/*! + \enum QScriptSyntaxCheckResult::State + + This enum specifies the state of a syntax check. + + \value Error The program contains a syntax error. + \value Intermediate The program is incomplete. + \value Valid The program is a syntactically correct Qt Script program. +*/ + +/*! + Constructs a new QScriptSyntaxCheckResult from the \a other result. +*/ +QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult& other) + : d_ptr(other.d_ptr) +{} + +/*! + Constructs a new QScriptSyntaxCheckResult from an internal representation. + \internal +*/ +QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate* d) + : d_ptr(d) +{} + +/*! + Destroys this QScriptSyntaxCheckResult. +*/ +QScriptSyntaxCheckResult::~QScriptSyntaxCheckResult() +{} + +/*! + Assigns the \a other result to this QScriptSyntaxCheckResult, and returns a + reference to this QScriptSyntaxCheckResult. +*/ +QScriptSyntaxCheckResult& QScriptSyntaxCheckResult::operator=(const QScriptSyntaxCheckResult& other) +{ + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns the state of this QScriptSyntaxCheckResult. +*/ +QScriptSyntaxCheckResult::State QScriptSyntaxCheckResult::state() const +{ + return d_ptr->state(); +} + +/*! + Returns the error line number of this QScriptSyntaxCheckResult, or -1 if + there is no error. + + \sa state(), errorMessage() +*/ +int QScriptSyntaxCheckResult::errorLineNumber() const +{ + return d_ptr->errorLineNumber(); +} + +/*! + Returns the error column number of this QScriptSyntaxCheckResult, or -1 if + there is no error. + + \sa state(), errorLineNumber() +*/ +int QScriptSyntaxCheckResult::errorColumnNumber() const +{ + return d_ptr->errorColumnNumber(); +} + +/*! + Returns the error message of this QScriptSyntaxCheckResult, or an empty + string if there is no error. + + \sa state(), errorLineNumber() +*/ +QString QScriptSyntaxCheckResult::errorMessage() const +{ + return d_ptr->errorMessage(); +} + +QScriptSyntaxCheckResultPrivate::~QScriptSyntaxCheckResultPrivate() +{ + if (m_exception) + JSValueUnprotect(m_engine->context(), m_exception); +} + +QString QScriptSyntaxCheckResultPrivate::errorMessage() const +{ + if (!m_exception) + return QString(); + + JSStringRef tmp = JSValueToStringCopy(m_engine->context(), m_exception, /* exception */ 0); + QString message = QScriptConverter::toString(tmp); + JSStringRelease(tmp); + return message; +} + +int QScriptSyntaxCheckResultPrivate::errorLineNumber() const +{ + if (!m_exception) + return -1; + // m_exception is an instance of the Exception so it has "line" attribute. + JSStringRef lineAttrName = QScriptConverter::toString("line"); + JSValueRef line = JSObjectGetProperty(m_engine->context(), + m_exception, + lineAttrName, + /* exceptions */0); + JSStringRelease(lineAttrName); + return JSValueToNumber(m_engine->context(), line, /* exceptions */0); +} diff --git a/JavaScriptCore/qt/api/qscriptsyntaxcheckresult.h b/JavaScriptCore/qt/api/qscriptsyntaxcheckresult.h new file mode 100644 index 0000000..aa57744 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptsyntaxcheckresult.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef qscriptsyntaxcheckresult_h +#define qscriptsyntaxcheckresult_h + +#include "qtscriptglobal.h" +#include <QtCore/qshareddata.h> + +class QScriptSyntaxCheckResultPrivate; +class Q_JAVASCRIPT_EXPORT QScriptSyntaxCheckResult { +public: + enum State { + Error, + Intermediate, + Valid + }; + + QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult& other); + ~QScriptSyntaxCheckResult(); + QScriptSyntaxCheckResult& operator=(const QScriptSyntaxCheckResult& other); + + State state() const; + int errorLineNumber() const; + int errorColumnNumber() const; + QString errorMessage() const; + +private: + QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate* d); + QExplicitlySharedDataPointer<QScriptSyntaxCheckResultPrivate> d_ptr; + + friend class QScriptSyntaxCheckResultPrivate; +}; +#endif // qscriptsyntaxcheckresult_h diff --git a/JavaScriptCore/qt/api/qscriptsyntaxcheckresult_p.h b/JavaScriptCore/qt/api/qscriptsyntaxcheckresult_p.h new file mode 100644 index 0000000..6e1a131 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptsyntaxcheckresult_p.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef qscriptsyntaxcheckresult_p_h +#define qscriptsyntaxcheckresult_p_h + +#include "qscriptconverter_p.h" +#include "qscriptengine_p.h" +#include "qscriptsyntaxcheckresult.h" +#include <JavaScriptCore/JavaScript.h> +#include <QtCore/qshareddata.h> + +class QScriptSyntaxCheckResultPrivate : public QSharedData { +public: + static inline QScriptSyntaxCheckResult get(QScriptSyntaxCheckResultPrivate* p); + inline QScriptSyntaxCheckResultPrivate(const QScriptEnginePrivate* engine); + inline QScriptSyntaxCheckResultPrivate(const QScriptEnginePrivate* engine, JSObjectRef value); + ~QScriptSyntaxCheckResultPrivate(); + + inline QScriptSyntaxCheckResult::State state() const; + int errorLineNumber() const; + inline int errorColumnNumber() const; + QString errorMessage() const; +private: + JSObjectRef m_exception; + QScriptEnginePtr m_engine; +}; + +QScriptSyntaxCheckResult QScriptSyntaxCheckResultPrivate::get(QScriptSyntaxCheckResultPrivate* p) +{ + return QScriptSyntaxCheckResult(p); +} + +QScriptSyntaxCheckResultPrivate::QScriptSyntaxCheckResultPrivate(const QScriptEnginePrivate* engine) + : m_exception(0) + , m_engine(const_cast<QScriptEnginePrivate*>(engine)) +{} + +QScriptSyntaxCheckResultPrivate::QScriptSyntaxCheckResultPrivate(const QScriptEnginePrivate* engine, JSObjectRef value) + : m_exception(value) + , m_engine(const_cast<QScriptEnginePrivate*>(engine)) +{} + +QScriptSyntaxCheckResult::State QScriptSyntaxCheckResultPrivate::state() const +{ + // FIXME This function doesn't return QScriptSyntaxCheckResult::Intermediate + return m_exception ? QScriptSyntaxCheckResult::Error : QScriptSyntaxCheckResult::Valid; +} + +int QScriptSyntaxCheckResultPrivate::errorColumnNumber() const +{ + // FIXME JSC C API doesn't expose the error column number. + return m_exception ? 1 : -1; +} + + +#endif // qscriptsyntaxcheckresult_p_h diff --git a/JavaScriptCore/qt/api/qscriptvalue_p.h b/JavaScriptCore/qt/api/qscriptvalue_p.h index 8db43a7..830b38e 100644 --- a/JavaScriptCore/qt/api/qscriptvalue_p.h +++ b/JavaScriptCore/qt/api/qscriptvalue_p.h @@ -38,10 +38,10 @@ class QScriptValue; Implementation of QScriptValue. The implementation is based on a state machine. The states names are included in - QScriptValuePrivate::States. Each method should check for the current state and then perform a + QScriptValuePrivate::State. Each method should check for the current state and then perform a correct action. - States: + State: Invalid -> QSVP is invalid, no assumptions should be made about class members (apart from m_value). CString -> QSVP is created from QString or const char* and no JSC engine has been associated yet. Current value is kept in m_string, @@ -53,7 +53,7 @@ class QScriptValue; is kept in m_number (cast of QScriptValue::SpecialValue) JSValue -> QSVP is associated with engine, but there is no information about real type, the state have really short live cycle. Normally it is created as a function call result. - JSNative -> QSVP is associated with engine, and it is sure that it isn't a JavaScript object. + JSPrimitive -> QSVP is associated with engine, and it is sure that it isn't a JavaScript object. JSObject -> QSVP is associated with engine, and it is sure that it is a JavaScript object. Each state keep all necessary information to invoke all methods, if not it should be changed to @@ -117,14 +117,14 @@ public: private: // Please, update class documentation when you change the enum. - enum States { + enum State { Invalid = 0, CString = 0x1000, CNumber, CBool, CSpecial, JSValue = 0x2000, // JS values are equal or higher then this value. - JSNative, + JSPrimitive, JSObject } m_state; QScriptEnginePtr m_engine; @@ -136,6 +136,7 @@ private: inline void setValue(JSValueRef); inline bool inherits(const char*); + inline State refinedJSValue(); inline bool isJSBased() const; inline bool isNumberBased() const; @@ -209,7 +210,7 @@ QScriptValuePrivate::QScriptValuePrivate(QScriptValue::SpecialValue value) } QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, bool value) - : m_state(JSNative) + : m_state(JSPrimitive) { if (!engine) { // slower path reinitialization @@ -224,7 +225,7 @@ QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, bool value } QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, int value) - : m_state(JSNative) + : m_state(JSPrimitive) { if (!engine) { // slower path reinitialization @@ -239,7 +240,7 @@ QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, int value) } QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, uint value) - : m_state(JSNative) + : m_state(JSPrimitive) { if (!engine) { // slower path reinitialization @@ -254,7 +255,7 @@ QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, uint value } QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, qsreal value) - : m_state(JSNative) + : m_state(JSPrimitive) { if (!engine) { // slower path reinitialization @@ -269,7 +270,7 @@ QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, qsreal val } QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, const QString& value) - : m_state(JSNative) + : m_state(JSPrimitive) { if (!engine) { // slower path reinitialization @@ -284,7 +285,7 @@ QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, const QStr } QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, QScriptValue::SpecialValue value) - : m_state(JSNative) + : m_state(JSPrimitive) { if (!engine) { // slower path reinitialization @@ -325,10 +326,10 @@ bool QScriptValuePrivate::isBool() case CBool: return true; case JSValue: - if (isObject()) + if (refinedJSValue() != JSPrimitive) return false; // Fall-through. - case JSNative: + case JSPrimitive: return JSValueIsBoolean(context(), value()); default: return false; @@ -341,10 +342,10 @@ bool QScriptValuePrivate::isNumber() case CNumber: return true; case JSValue: - if (isObject()) + if (refinedJSValue() != JSPrimitive) return false; // Fall-through. - case JSNative: + case JSPrimitive: return JSValueIsNumber(context(), value()); default: return false; @@ -357,10 +358,10 @@ bool QScriptValuePrivate::isNull() case CSpecial: return m_number == static_cast<int>(QScriptValue::NullValue); case JSValue: - if (isObject()) + if (refinedJSValue() != JSPrimitive) return false; // Fall-through. - case JSNative: + case JSPrimitive: return JSValueIsNull(context(), value()); default: return false; @@ -373,10 +374,10 @@ bool QScriptValuePrivate::isString() case CString: return true; case JSValue: - if (isObject()) + if (refinedJSValue() != JSPrimitive) return false; // Fall-through. - case JSNative: + case JSPrimitive: return JSValueIsString(context(), value()); default: return false; @@ -389,10 +390,10 @@ bool QScriptValuePrivate::isUndefined() case CSpecial: return m_number == static_cast<int>(QScriptValue::UndefinedValue); case JSValue: - if (isObject()) + if (refinedJSValue() != JSPrimitive) return false; // Fall-through. - case JSNative: + case JSPrimitive: return JSValueIsUndefined(context(), value()); default: return false; @@ -403,7 +404,7 @@ bool QScriptValuePrivate::isError() { switch (m_state) { case JSValue: - if (!isObject()) + if (refinedJSValue() != JSObject) return false; // Fall-through. case JSObject: @@ -416,14 +417,11 @@ bool QScriptValuePrivate::isError() bool QScriptValuePrivate::isObject() { switch (m_state) { - case JSObject: - return true; case JSValue: - m_object = JSValueToObject(context(), value(), /* exception */ 0); - if (!m_object) - return false; - m_state = JSObject; + return refinedJSValue() == JSObject; + case JSObject: return true; + default: return false; } @@ -433,10 +431,8 @@ bool QScriptValuePrivate::isFunction() { switch (m_state) { case JSValue: - m_object = JSValueToObject(context(), value(), /* exception */ 0); - if (!m_object) + if (refinedJSValue() != JSObject) return false; - m_state = JSObject; // Fall-through. case JSObject: return JSObjectIsFunction(context(), object()); @@ -455,11 +451,11 @@ QString QScriptValuePrivate::toString() const case CString: return m_string; case CNumber: - return QString::number(m_number); + return QScriptConverter::toString(m_number); case CSpecial: return m_number == QScriptValue::NullValue ? QString::fromLatin1("null") : QString::fromLatin1("undefined"); case JSValue: - case JSNative: + case JSPrimitive: case JSObject: return QScriptConverter::toString(JSValueToStringCopy(context(), value(), /* exception */ 0)); } @@ -472,7 +468,7 @@ qsreal QScriptValuePrivate::toNumber() const { switch (m_state) { case JSValue: - case JSNative: + case JSPrimitive: case JSObject: return JSValueToNumber(context(), value(), /* exception */ 0); case CNumber: @@ -504,7 +500,7 @@ bool QScriptValuePrivate::toBool() const { switch (m_state) { case JSValue: - case JSNative: + case JSPrimitive: return JSValueToBoolean(context(), value()); case JSObject: return true; @@ -631,7 +627,7 @@ bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine) return false; } m_engine = engine; - m_state = JSNative; + m_state = JSPrimitive; setValue(value); return true; } @@ -640,12 +636,8 @@ QScriptValuePrivate* QScriptValuePrivate::call(const QScriptValuePrivate*, const { switch (m_state) { case JSValue: - m_object = JSValueToObject(context(), value(), /* exception */ 0); - if (!object()) { - m_state = JSValue; + if (refinedJSValue() != JSObject) return new QScriptValuePrivate; - } - m_state = JSObject; // Fall-through. case JSObject: { @@ -719,12 +711,32 @@ bool QScriptValuePrivate::inherits(const char* name) { Q_ASSERT(isJSBased()); JSObjectRef globalObject = JSContextGetGlobalObject(context()); - JSValueRef error = JSObjectGetProperty(context(), globalObject, QScriptConverter::toString(name), 0); + JSStringRef errorAttrName = QScriptConverter::toString(name); + JSValueRef error = JSObjectGetProperty(context(), globalObject, errorAttrName, /* exception */ 0); + JSStringRelease(errorAttrName); return JSValueIsInstanceOfConstructor(context(), value(), JSValueToObject(context(), error, /* exception */ 0), /* exception */ 0); } /*! \internal + Refines the state of this QScriptValuePrivate. Returns the new state. +*/ +QScriptValuePrivate::State QScriptValuePrivate::refinedJSValue() +{ + Q_ASSERT(m_state == JSValue); + if (!JSValueIsObject(context(), value())) { + m_state = JSPrimitive; + } else { + m_state = JSObject; + // We are sure that value is an JSObject, so we can const_cast safely without + // calling JSC C API (JSValueToObject(context(), value(), /* exceptions */ 0)). + m_object = const_cast<JSObjectRef>(m_value); + } + return m_state; +} + +/*! + \internal Returns true if QSV have an engine associated. */ bool QScriptValuePrivate::isJSBased() const { return m_state >= JSValue; } |