Changeset 55427 in webkit


Ignore:
Timestamp:
Mar 2, 2010 1:39:02 PM (14 years ago)
Author:
eric@webkit.org
Message:

2010-03-02 Jedrzej Nowacki <jedrzej.nowacki@nokia.com>

Reviewed by Simon Hausmann.

Fix QScriptValue::toString().

More ECMA Script compliance, especially for values as NaN, Inifinite
and really big/small numbers.

[Qt] QScriptValue::toString() returns incorrect values
https://bugs.webkit.org/show_bug.cgi?id=34850

  • qt/api/qscriptconverter_p.h: (QScriptConverter::toString):
  • qt/api/qscriptvalue_p.h: (QScriptValuePrivate::toString):
  • qt/tests/qscriptvalue/tst_qscriptvalue.cpp:
  • qt/tests/qscriptvalue/tst_qscriptvalue.h:
  • qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp: (tst_QScriptValue::toString_initData): (tst_QScriptValue::toString_makeData): (tst_QScriptValue::toString_test):
Location:
trunk/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r55426 r55427  
     12010-03-02  Jedrzej Nowacki  <jedrzej.nowacki@nokia.com>
     2
     3        Reviewed by Simon Hausmann.
     4
     5        Fix QScriptValue::toString().
     6
     7        More ECMA Script compliance, especially for values as NaN, Inifinite
     8        and really big/small numbers.
     9
     10        [Qt] QScriptValue::toString() returns incorrect values
     11        https://bugs.webkit.org/show_bug.cgi?id=34850
     12
     13        * qt/api/qscriptconverter_p.h:
     14        (QScriptConverter::toString):
     15        * qt/api/qscriptvalue_p.h:
     16        (QScriptValuePrivate::toString):
     17        * qt/tests/qscriptvalue/tst_qscriptvalue.cpp:
     18        * qt/tests/qscriptvalue/tst_qscriptvalue.h:
     19        * qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp:
     20        (tst_QScriptValue::toString_initData):
     21        (tst_QScriptValue::toString_makeData):
     22        (tst_QScriptValue::toString_test):
     23
    1242010-03-02  Jedrzej Nowacki  <jedrzej.nowacki@nokia.com>
    225
  • trunk/JavaScriptCore/qt/api/qscriptconverter_p.h

    r55426 r55427  
    2424#include <QtCore/qnumeric.h>
    2525#include <QtCore/qstring.h>
     26
     27extern char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **digits_str);
    2628
    2729/*
     
    6062        return JSStringCreateWithUTF8CString(str);
    6163    }
     64    static QString toString(double value)
     65    {
     66        // FIXME this should be easier. The ideal fix is to create
     67        // a new function in JSC C API which could cover the functionality.
     68
     69        if (qIsNaN(value))
     70            return QString::fromLatin1("NaN");
     71        if (qIsInf(value))
     72            return QString::fromLatin1(value < 0 ? "-Infinity" : "Infinity");
     73        if (!value)
     74            return QString::fromLatin1("0");
     75
     76        QByteArray buf;
     77        buf.reserve(24);
     78        int decpt;
     79        int sign;
     80        char* result = 0;
     81        (void)qdtoa(value, 0, 0, &decpt, &sign, 0, &result);
     82
     83        if (!result)
     84            return QString();
     85
     86        if (decpt <= 0 && decpt > -6) {
     87            buf.fill('0', -decpt + 2 + sign);
     88            if (sign) // fix the sign.
     89                buf[0] = '-';
     90            buf[sign + 1] = '.';
     91            buf += result;
     92        } else {
     93            if (sign)
     94                buf += '-';
     95            buf += result;
     96            int length = buf.length() - sign;
     97            if (decpt <= 21 && decpt > 0) {
     98                if (length <= decpt)
     99                    buf += QByteArray().fill('0', decpt - length);
     100                else
     101                    buf.insert(decpt + sign, '.');
     102            } else if (result[0] >= '0' && result[0] <= '9') {
     103                if (length > 1)
     104                    buf.insert(1 + sign, '.');
     105                buf += 'e';
     106                buf += (decpt >= 0) ? '+' : '-';
     107                int e = decpt - 1;
     108                if (e < 0)
     109                    e = -e;
     110                if (e >= 100)
     111                    buf += '0' + e / 100;
     112                if (e >= 10)
     113                    buf += '0' + (e % 100) / 10;
     114                buf += '0' + e % 10;
     115            }
     116        }
     117        free(result);
     118        return QString::fromLatin1(buf);
     119    }
    62120};
    63121
  • trunk/JavaScriptCore/qt/api/qscriptvalue_p.h

    r54773 r55427  
    456456        return m_string;
    457457    case CNumber:
    458         return QString::number(m_number);
     458        return QScriptConverter::toString(m_number);
    459459    case CSpecial:
    460460        return m_number == QScriptValue::NullValue ? QString::fromLatin1("null") : QString::fromLatin1("undefined");
  • trunk/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp

    r54340 r55427  
    275275}
    276276
    277 void tst_QScriptValue::toString_data()
     277void tst_QScriptValue::toStringSimple_data()
    278278{
    279279    QTest::addColumn<QString>("code");
     
    290290
    291291/* Test conversion to string from different JSC types */
    292 void tst_QScriptValue::toString()
     292void tst_QScriptValue::toStringSimple()
    293293{
    294294    QFETCH(QString, code);
  • trunk/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h

    r54773 r55427  
    3737
    3838private slots:
    39     void toString_data();
    40     void toString();
     39    void toStringSimple_data();
     40    void toStringSimple();
    4141    void copyConstructor_data();
    4242    void copyConstructor();
     
    7676    void isValid_data();
    7777    void isValid();
     78
     79    void toString_data();
     80    void toString();
    7881
    7982    void toNumber_data();
     
    147150    void isValid_test(const char* expr, const QScriptValue& value);
    148151
     152    void toString_initData();
     153    void toString_makeData(const char*);
     154    void toString_test(const char*, const QScriptValue&);
     155
    149156    void toNumber_initData();
    150157    void toNumber_makeData(const char*);
  • trunk/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp

    r54773 r55427  
    557557DEFINE_TEST_FUNCTION(isObject)
    558558
     559void tst_QScriptValue::toString_initData()
     560{
     561    QTest::addColumn<QString>("expected");
     562    initScriptValues();
     563}
     564
     565void tst_QScriptValue::toString_makeData(const char* expr)
     566{
     567    static QHash<QString, QString> toString;
     568    if (toString.isEmpty()) {
     569        toString.insert("QScriptValue()", "");
     570        toString.insert("QScriptValue(QScriptValue::UndefinedValue)", "undefined");
     571        toString.insert("QScriptValue(QScriptValue::NullValue)", "null");
     572        toString.insert("QScriptValue(true)", "true");
     573        toString.insert("QScriptValue(false)", "false");
     574        toString.insert("QScriptValue(int(122))", "122");
     575        toString.insert("QScriptValue(uint(124))", "124");
     576        toString.insert("QScriptValue(0)", "0");
     577        toString.insert("QScriptValue(0.0)", "0");
     578        toString.insert("QScriptValue(123.0)", "123");
     579        toString.insert("QScriptValue(6.37e-8)", "6.37e-8");
     580        toString.insert("QScriptValue(-6.37e-8)", "-6.37e-8");
     581        toString.insert("QScriptValue(0x43211234)", "1126240820");
     582        toString.insert("QScriptValue(0x10000)", "65536");
     583        toString.insert("QScriptValue(0x10001)", "65537");
     584        toString.insert("QScriptValue(qSNaN())", "NaN");
     585        toString.insert("QScriptValue(qQNaN())", "NaN");
     586        toString.insert("QScriptValue(qInf())", "Infinity");
     587        toString.insert("QScriptValue(-qInf())", "-Infinity");
     588        toString.insert("QScriptValue(\"NaN\")", "NaN");
     589        toString.insert("QScriptValue(\"Infinity\")", "Infinity");
     590        toString.insert("QScriptValue(\"-Infinity\")", "-Infinity");
     591        toString.insert("QScriptValue(\"ciao\")", "ciao");
     592        toString.insert("QScriptValue(QString::fromLatin1(\"ciao\"))", "ciao");
     593        toString.insert("QScriptValue(QString(\"\"))", "");
     594        toString.insert("QScriptValue(QString())", "");
     595        toString.insert("QScriptValue(QString(\"0\"))", "0");
     596        toString.insert("QScriptValue(QString(\"123\"))", "123");
     597        toString.insert("QScriptValue(QString(\"12.4\"))", "12.4");
     598        toString.insert("QScriptValue(0, QScriptValue::UndefinedValue)", "undefined");
     599        toString.insert("QScriptValue(0, QScriptValue::NullValue)", "null");
     600        toString.insert("QScriptValue(0, true)", "true");
     601        toString.insert("QScriptValue(0, false)", "false");
     602        toString.insert("QScriptValue(0, int(122))", "122");
     603        toString.insert("QScriptValue(0, uint(124))", "124");
     604        toString.insert("QScriptValue(0, 0)", "0");
     605        toString.insert("QScriptValue(0, 0.0)", "0");
     606        toString.insert("QScriptValue(0, 123.0)", "123");
     607        toString.insert("QScriptValue(0, 6.37e-8)", "6.37e-8");
     608        toString.insert("QScriptValue(0, -6.37e-8)", "-6.37e-8");
     609        toString.insert("QScriptValue(0, 0x43211234)", "1126240820");
     610        toString.insert("QScriptValue(0, 0x10000)", "65536");
     611        toString.insert("QScriptValue(0, 0x10001)", "65537");
     612        toString.insert("QScriptValue(0, qSNaN())", "NaN");
     613        toString.insert("QScriptValue(0, qQNaN())", "NaN");
     614        toString.insert("QScriptValue(0, qInf())", "Infinity");
     615        toString.insert("QScriptValue(0, -qInf())", "-Infinity");
     616        toString.insert("QScriptValue(0, \"NaN\")", "NaN");
     617        toString.insert("QScriptValue(0, \"Infinity\")", "Infinity");
     618        toString.insert("QScriptValue(0, \"-Infinity\")", "-Infinity");
     619        toString.insert("QScriptValue(0, \"ciao\")", "ciao");
     620        toString.insert("QScriptValue(0, QString::fromLatin1(\"ciao\"))", "ciao");
     621        toString.insert("QScriptValue(0, QString(\"\"))", "");
     622        toString.insert("QScriptValue(0, QString())", "");
     623        toString.insert("QScriptValue(0, QString(\"0\"))", "0");
     624        toString.insert("QScriptValue(0, QString(\"123\"))", "123");
     625        toString.insert("QScriptValue(0, QString(\"12.3\"))", "12.3");
     626        toString.insert("QScriptValue(engine, QScriptValue::UndefinedValue)", "undefined");
     627        toString.insert("QScriptValue(engine, QScriptValue::NullValue)", "null");
     628        toString.insert("QScriptValue(engine, true)", "true");
     629        toString.insert("QScriptValue(engine, false)", "false");
     630        toString.insert("QScriptValue(engine, int(122))", "122");
     631        toString.insert("QScriptValue(engine, uint(124))", "124");
     632        toString.insert("QScriptValue(engine, 0)", "0");
     633        toString.insert("QScriptValue(engine, 0.0)", "0");
     634        toString.insert("QScriptValue(engine, 123.0)", "123");
     635        toString.insert("QScriptValue(engine, 6.37e-8)", "6.37e-8");
     636        toString.insert("QScriptValue(engine, -6.37e-8)", "-6.37e-8");
     637        toString.insert("QScriptValue(engine, 0x43211234)", "1126240820");
     638        toString.insert("QScriptValue(engine, 0x10000)", "65536");
     639        toString.insert("QScriptValue(engine, 0x10001)", "65537");
     640        toString.insert("QScriptValue(engine, qSNaN())", "NaN");
     641        toString.insert("QScriptValue(engine, qQNaN())", "NaN");
     642        toString.insert("QScriptValue(engine, qInf())", "Infinity");
     643        toString.insert("QScriptValue(engine, -qInf())", "-Infinity");
     644        toString.insert("QScriptValue(engine, \"NaN\")", "NaN");
     645        toString.insert("QScriptValue(engine, \"Infinity\")", "Infinity");
     646        toString.insert("QScriptValue(engine, \"-Infinity\")", "-Infinity");
     647        toString.insert("QScriptValue(engine, \"ciao\")", "ciao");
     648        toString.insert("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", "ciao");
     649        toString.insert("QScriptValue(engine, QString(\"\"))", "");
     650        toString.insert("QScriptValue(engine, QString())", "");
     651        toString.insert("QScriptValue(engine, QString(\"0\"))", "0");
     652        toString.insert("QScriptValue(engine, QString(\"123\"))", "123");
     653        toString.insert("QScriptValue(engine, QString(\"1.23\"))", "1.23");
     654        toString.insert("engine->evaluate(\"[]\")", "");
     655        toString.insert("engine->evaluate(\"{}\")", "undefined");
     656        toString.insert("engine->evaluate(\"Object.prototype\")", "[object Object]");
     657        toString.insert("engine->evaluate(\"Date.prototype\")", "Invalid Date");
     658        toString.insert("engine->evaluate(\"Array.prototype\")", "");
     659        toString.insert("engine->evaluate(\"Function.prototype\")", "function () {\n    [native code]\n}");
     660        toString.insert("engine->evaluate(\"Error.prototype\")", "Error: Unknown error");
     661        toString.insert("engine->evaluate(\"Object\")", "function Object() {\n    [native code]\n}");
     662        toString.insert("engine->evaluate(\"Array\")", "function Array() {\n    [native code]\n}");
     663        toString.insert("engine->evaluate(\"Number\")", "function Number() {\n    [native code]\n}");
     664        toString.insert("engine->evaluate(\"Function\")", "function Function() {\n    [native code]\n}");
     665        toString.insert("engine->evaluate(\"(function() { return 1; })\")", "function () { return 1; }");
     666        toString.insert("engine->evaluate(\"(function() { return 'ciao'; })\")", "function () { return 'ciao'; }");
     667        toString.insert("engine->evaluate(\"(function() { throw new Error('foo'); })\")", "function () { throw new Error('foo'); }");
     668        toString.insert("engine->evaluate(\"/foo/\")", "/foo/");
     669        toString.insert("engine->evaluate(\"new Object()\")", "[object Object]");
     670        toString.insert("engine->evaluate(\"new Array()\")", "");
     671        toString.insert("engine->evaluate(\"new Error()\")", "Error: Unknown error");
     672    }
     673    newRow(expr) << toString.value(expr);
     674}
     675
     676void tst_QScriptValue::toString_test(const char*, const QScriptValue& value)
     677{
     678    QFETCH(QString, expected);
     679    QCOMPARE(value.toString(), expected);
     680}
     681
     682DEFINE_TEST_FUNCTION(toString)
     683
    559684void tst_QScriptValue::toNumber_initData()
    560685{
Note: See TracChangeset for help on using the changeset viewer.