Implement JSON.parse
authorLars Knoll <lars.knoll@digia.com>
Fri, 18 Jan 2013 21:19:33 +0000 (22:19 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Sat, 19 Jan 2013 07:21:24 +0000 (08:21 +0100)
Change-Id: Ibb5f9226aaaea8653842c5a452e006dc05210a2c
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
qmljs_engine.cpp
qv4jsonobject.cpp [new file with mode: 0644]
qv4jsonobject.h [new file with mode: 0644]
tests/TestExpectations
v4.pro

index 8f0fa63..0145238 100644 (file)
@@ -44,6 +44,7 @@
 #include <qmljs_runtime.h>
 #include "qv4mm.h"
 #include <qv4argumentsobject.h>
+#include <qv4jsonobject.h>
 
 namespace QQmlJS {
 namespace VM {
@@ -201,6 +202,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
     glo->defineDefaultProperty(rootContext, QStringLiteral("TypeError"), typeErrorCtor);
     glo->defineDefaultProperty(rootContext, QStringLiteral("URIError"), uRIErrorCtor);
     glo->defineDefaultProperty(rootContext, QStringLiteral("Math"), Value::fromObject(newMathObject(rootContext)));
+    glo->defineDefaultProperty(rootContext, QStringLiteral("JSON"), Value::fromObject(new (memoryManager) JsonObject(rootContext)));
 
     glo->defineReadonlyProperty(this, QStringLiteral("undefined"), Value::undefinedValue());
     glo->defineReadonlyProperty(this, QStringLiteral("NaN"), Value::fromDouble(nan("")));
diff --git a/qv4jsonobject.cpp b/qv4jsonobject.cpp
new file mode 100644 (file)
index 0000000..91013e9
--- /dev/null
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the V4VM module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qv4jsonobject.h>
+#include <qv4ecmaobjects_p.h>
+#include <qjsondocument.h>
+#include <qjsonobject.h>
+#include <qjsonarray.h>
+#include <qjsonvalue.h>
+
+namespace QQmlJS {
+namespace VM {
+
+JsonObject::JsonObject(ExecutionContext *context)
+    : Object()
+{
+    prototype = context->engine->objectPrototype;
+
+    defineDefaultProperty(context, QStringLiteral("parse"), method_parse, 2);
+    defineDefaultProperty(context, QStringLiteral("stringify"), method_stringify);
+}
+
+
+Value JsonObject::method_parse(ExecutionContext *ctx)
+{
+    QString jtext = ctx->argument(0).toString(ctx)->toQString();
+
+    const QChar *ch = jtext.constData();
+    const QChar *end = ch + jtext.size();
+
+    bool simple = false;
+    while (ch < end) {
+        if (*ch == ' ' || *ch == '\t' || *ch == '\n' || *ch == '\r') {
+            ++ch;
+        } else if (*ch == '[' || *ch == '{') {
+            break;
+        } else {
+            // simple type
+            jtext.prepend('[');
+            jtext.append(']');
+            simple = true;
+            break;
+        }
+    }
+
+    QJsonParseError e;
+    QJsonDocument doc = QJsonDocument::fromJson(jtext.toUtf8(), &e);
+    if (e.error != QJsonParseError::NoError)
+        ctx->throwSyntaxError(0);
+
+    // iterate over the doc and convert to V4 types
+    Value result;
+    if (doc.isArray())
+            result = convertArray(ctx, doc.array());
+    else if (doc.isObject())
+        result = convertObject(ctx, doc.object());
+    else
+        result = Value::undefinedValue();
+
+    if (simple) {
+        result = result.objectValue()->__get__(ctx, (uint)0);
+    }
+
+    return result;
+}
+
+Value JsonObject::method_stringify(ExecutionContext *ctx)
+{
+    assert(!"Not implemented");
+}
+
+static void checkString(ExecutionContext *context, const QString &s)
+{
+    const QChar *ch = s.constData();
+    const QChar *end = ch + s.length();
+    while (ch < end) {
+        if (ch->unicode() <= 0x1f)
+            context->throwSyntaxError(0);
+        ++ch;
+    }
+}
+
+Value JsonObject::convertValue(ExecutionContext *context, const QJsonValue &value)
+{
+    switch (value.type()) {
+    case QJsonValue::Null:
+        return Value::nullValue();
+    case QJsonValue::Bool:
+        return Value::fromBoolean(value.toBool());
+    case QJsonValue::Double:
+        return Value::fromDouble(value.toDouble());
+    case QJsonValue::String: {
+        Value v = Value::fromString(context, value.toString());
+        checkString(context, v.stringValue()->toQString());
+        return v;
+    }
+    case QJsonValue::Array:
+        return convertArray(context, value.toArray());
+    case QJsonValue::Object:
+        return convertObject(context, value.toObject());
+    default:
+        assert(!"internal error in JSON conversion");
+        return Value::undefinedValue();
+    }
+}
+
+Value JsonObject::convertArray(ExecutionContext *context, const QJsonArray &array)
+{
+    ArrayObject *o = context->engine->newArrayObject(context);
+    for (int i = 0; i < array.size(); ++i) {
+        QJsonValue v = array.at(i);
+        o->array.set(i, convertValue(context, v));
+    }
+    o->array.setLengthUnchecked(array.size());
+    return Value::fromObject(o);
+}
+
+Value JsonObject::convertObject(ExecutionContext *context, const QJsonObject &object)
+{
+    Object *o = context->engine->newObject();
+    for (QJsonObject::const_iterator it = object.constBegin(); it != object.constEnd(); ++it) {
+        QString key = it.key();
+        checkString(context, key);
+        QJsonValue v = it.value();
+        o->__put__(context, key, convertValue(context, v));
+    }
+    return Value::fromObject(o);
+}
+
+
+}
+}
diff --git a/qv4jsonobject.h b/qv4jsonobject.h
new file mode 100644 (file)
index 0000000..1a6f24a
--- /dev/null
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the V4VM module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4JSONOBJECTS_H
+#define QV4SJONOBJECTS_H
+
+#include <qmljs_objects.h>
+
+namespace QQmlJS {
+namespace VM {
+
+struct JsonObject : Object {
+    JsonObject(ExecutionContext *context);
+    virtual QString className() { return QStringLiteral("JSON"); }
+
+    static Value method_parse(ExecutionContext *ctx);
+    static Value method_stringify(ExecutionContext *ctx);
+
+private:
+    static Value convertArray(ExecutionContext *context, const QJsonArray &array);
+    static Value convertObject(ExecutionContext *context, const QJsonObject &object);
+    static Value convertValue(ExecutionContext *context, const QJsonValue &value);
+
+};
+
+}
+}
+
+#endif
+
index e775a85..a125833 100644 (file)
@@ -115,10 +115,8 @@ S11.3.2_A4_T4 failing
 11.4.1-2-4 failing
 11.4.1-2-5 failing
 11.4.1-2-6 failing
-11.4.1-4.a-10 failing
 11.4.1-4.a-5 failing
 11.4.1-4.a-7 failing
-11.4.1-4.a-8 failing
 11.4.1-5-2 failing
 S11.4.1_A1 failing
 S11.4.1_A2.1 failing
@@ -327,36 +325,13 @@ S15.10.7.4_A10 failing
 S15.10.7.4_A9 failing
 S15.11.4.2_A1 failing
 S15.11.4.2_A2 failing
-15.12-0-1 failing
-15.12-0-2 failing
-15.12-0-3 failing
-15.12-0-4 failing
-15.12.1.1-0-1 failing
-15.12.1.1-0-9 failing
-15.12.1.1-g1-1 failing
-15.12.1.1-g1-2 failing
-15.12.1.1-g1-3 failing
-15.12.1.1-g1-4 failing
-15.12.1.1-g2-1 failing
-15.12.1.1-g2-5 failing
-15.12.1.1-g4-4 failing
-15.12.1.1-g5-1 failing
-15.12.1.1-g5-2 failing
-15.12.1.1-g5-3 failing
-15.12.1.1-g6-1 failing
-15.12.1.1-g6-2 failing
 15.12.1.1-g6-3 failing
 15.12.1.1-g6-4 failing
 15.12.1.1-g6-5 failing
 15.12.1.1-g6-6 failing
 15.12.1.1-g6-7 failing
-15.12.2-0-1 failing
-15.12.2-0-2 failing
-15.12.2-0-3 failing
 S15.12.2_A1 failing
-15.12.3-0-1 failing
 15.12.3-0-2 failing
-15.12.3-0-3 failing
 15.12.3-11-1 failing
 15.12.3-11-10 failing
 15.12.3-11-11 failing
@@ -412,7 +387,6 @@ S15.1.3.1_A1.9_T1 failing
 S15.1.3.1_A1.9_T2 failing
 S15.1.3.1_A1.9_T3 failing
 S15.1.3.1_A2.1_T1 failing
-15.2.3.11-4-27 failing
 15.12.3-11-2 failing
 15.12.3-11-26 failing
 15.12.3-11-3 failing
@@ -502,9 +476,6 @@ S15.1.3.4_A5.4 failing
 S15.1.3.4_A5.6 failing
 S15.1.3.4_A5.7 failing
 S15.1.3.4_A6_T1 failing
-15.2.3.12-3-27 failing
-15.2.3.13-2-12 failing
-15.2.3.2-2-18 failing
 S15.1.3.1_A2.2_T1 failing
 S15.1.3.1_A2.3_T1 failing
 S15.1.3.1_A2.4_T1 failing
@@ -575,8 +546,6 @@ S15.1.3.2_A5.3 failing
 15.2.3.3-4-161 failing
 15.2.3.3-4-162 failing
 15.2.3.3-4-164 failing
-15.2.3.3-4-176 failing
-15.2.3.3-4-177 failing
 15.2.3.3-4-212 failing
 15.2.3.3-4-213 failing
 15.2.3.3-4-214 failing
@@ -585,34 +554,8 @@ S15.1.3.2_A5.3 failing
 15.2.3.3-4-82 failing
 15.2.3.3-4-9 failing
 15.2.3.3-4-90 failing
-15.2.3.5-4-120 failing
-15.2.3.5-4-13 failing
-15.2.3.5-4-145 failing
-15.2.3.5-4-173 failing
-15.2.3.5-4-199 failing
-15.2.3.5-4-224 failing
-15.2.3.5-4-252 failing
-15.2.3.5-4-67 failing
-15.2.3.5-4-92 failing
 15.2.3.6-2-17-1 failing
-15.2.3.5-4-287 failing
 15.2.3.5-4-315 failing
-15.2.3.5-4-36 failing
-15.2.3.6-3-119 failing
-15.2.3.6-3-147-1 failing
-15.2.3.6-3-147 failing
-15.2.3.6-3-173-1 failing
-15.2.3.6-3-173 failing
-15.2.3.6-3-198 failing
-15.2.3.6-3-226-1 failing
-15.2.3.6-3-226 failing
-15.2.3.6-3-256-1 failing
-15.2.3.6-3-256 failing
-15.2.3.6-3-41-1 failing
-15.2.3.6-3-41 failing
-15.2.3.6-3-66 failing
-15.2.3.6-3-94-1 failing
-15.2.3.6-3-94 failing
 15.2.3.6-4-291-1 failing
 15.2.3.6-4-292-1 failing
 15.2.3.6-4-293-2 failing
@@ -625,32 +568,15 @@ S15.1.3.2_A5.3 failing
 15.2.3.6-4-300-1 failing
 15.2.3.6-4-360-3 failing
 15.2.3.6-4-360-7 failing
-15.2.3.6-4-41 failing
-15.2.3.6-4-410 failing
-15.2.3.6-4-586 failing
 15.2.3.6-4-621 failing
 15.2.3.6-4-622 failing
 15.2.3.6-4-623 failing
 15.2.3.6-4-624 failing
-15.2.3.7-2-14 failing
-15.2.3.7-5-a-15 failing
-15.2.3.7-5-b-105 failing
-15.2.3.7-5-b-133 failing
-15.2.3.7-5-b-159 failing
-15.2.3.7-5-b-184 failing
-15.2.3.7-5-b-212 failing
-15.2.3.7-5-b-247 failing
-15.2.3.7-5-b-27 failing
-15.2.3.7-5-b-52 failing
-15.2.3.7-5-b-80 failing
 15.2.3.7-6-a-110 failing
-15.2.3.7-6-a-20 failing
 15.2.3.7-6-a-280 failing
 15.2.3.7-6-a-286 failing
 15.2.3.7-6-a-288 failing
 15.2.3.7-6-a-289 failing
-15.3.4.5-2-7 failing
-15.4.3.2-1-11 failing
 S15.4.4.13_A2_T1 failing
 S15.4.4.13_A2_T2 failing
 S15.4.4.13_A2_T3 failing
@@ -659,12 +585,10 @@ S15.4.4.13_A3_T2 failing
 S15.4.4.13_A3_T3 failing
 S15.4.4.13_A4_T1 failing
 S15.4.4.13_A4_T2 failing
-15.4.4.14-1-13 failing
 15.4.4.14-9-a-10 failing
 15.4.4.14-9-a-17 failing
 15.4.4.14-9-a-7 failing
 15.4.4.14-9-a-9 failing
-15.4.4.15-1-13 failing
 15.4.4.15-3-2 failing
 15.4.4.15-3-29 failing
 15.4.4.15-5-14 failing
@@ -709,32 +633,15 @@ S15.4.4.13_A4_T2 failing
 15.4.4.15-8-b-ii-8 failing
 15.4.4.15-8-b-ii-9 failing
 15.4.4.16-1-10 failing
-15.4.4.16-1-13 failing
-15.4.4.16-5-17 failing
-15.4.4.16-7-c-iii-23 failing
 15.4.4.17-1-10 failing
-15.4.4.17-1-13 failing
-15.4.4.17-5-17 failing
-15.4.4.17-7-c-iii-23 failing
 15.4.4.18-1-10 failing
-15.4.4.18-1-13 failing
-15.4.4.18-5-17 failing
 15.4.4.19-1-10 failing
-15.4.4.19-1-13 failing
 15.4.4.19-5-1 failing
-15.4.4.19-5-17 failing
 15.4.4.20-1-10 failing
-15.4.4.20-1-13 failing
-15.4.4.20-5-17 failing
-15.4.4.20-9-c-iii-24 failing
 15.4.4.21-1-10 failing
-15.4.4.21-1-13 failing
 15.4.4.21-9-c-i-6 failing
-15.4.4.21-9-c-ii-33 failing
 15.4.4.22-1-10 failing
-15.4.4.22-1-13 failing
 15.4.4.22-9-c-i-6 failing
-15.4.4.22-9-c-ii-33 failing
 S15.4.4.3_A1_T1 failing
 S15.4.4.3_A3_T1 failing
 15.4.4.4-5-b-iii-3-b-1 failing
@@ -1260,16 +1167,6 @@ S15.2.4.4_A15 failing
 S15.4.4.4_A1_T2 failing
 
 # Regressions due to Object/property refactoring
-15.12.2-2-1 failing
-15.12.2-2-10 failing
-15.12.2-2-2 failing
-15.12.2-2-3 failing
-15.12.2-2-4 failing
-15.12.2-2-5 failing
-15.12.2-2-6 failing
-15.12.2-2-7 failing
-15.12.2-2-8 failing
-15.12.2-2-9 failing
 15.12.3-11-16 failing
 15.12.3-11-17 failing
 15.12.3-11-18 failing
@@ -1291,5 +1188,6 @@ S15.4.4.4_A1_T2 failing
 15.4.4.16-7-c-i-6 failing
 15.4.4.17-7-c-i-6 failing
 
-# Regressions introduced with https://codereview.qt-project.org/#change,45044
-15.4.4.21-8-b-iii-1-6 failing
\ No newline at end of file
+15.4.4.21-8-b-iii-1-6 failing
+15.12.3_4-1-1
+15.12.3_4-1-3
diff --git a/v4.pro b/v4.pro
index 9d6f5bd..b195d50 100644 (file)
--- a/v4.pro
+++ b/v4.pro
@@ -28,6 +28,7 @@ SOURCES += main.cpp \
     qv4managed.cpp \
     qv4array.cpp \
     qv4argumentsobject.cpp \
+    qv4jsonobject.cpp \
     qv4string.cpp \
     qv4objectiterator.cpp \
     qv4regexp.cpp
@@ -51,6 +52,7 @@ HEADERS += \
     qv4managed.h \
     qv4array.h \
     qv4argumentsobject.h \
+    qv4jsonobject.h \
     qv4string.h \
     qv4propertydescriptor.h \
     qv4propertytable.h \