Ticket #3403: charts_fix.patch

File charts_fix.patch, 12.0 KB (added by wraitii, 7 years ago)
  • source/gui/scripting/GuiScriptConversions.cpp

    diff --git a/source/gui/scripting/GuiScriptConversions.cpp b/source/gui/scripting/GuiScriptConversions.cpp
    index b2a83c1..9c2d9d2 100644
    a b  
    1717
    1818#include "precompiled.h"
    1919
    20 #include "scriptinterface/ScriptInterface.h"
     20#include "scriptinterface/ScriptConversions.h"
    2121
    2222#include "gui/IGUIObject.h"
    2323#include "lib/external_libraries/libsdl.h"
    2424#include "ps/Hotkey.h"
     25#include "maths/Vector2D.h"
    2526
    2627#define SET(obj, name, value) STMT(JS::RootedValue v_(cx); AssignOrToJSVal(cx, &v_, (value)); JS_SetProperty(cx, obj, (name), v_))
    2728    // ignore JS_SetProperty return value, because errors should be impossible
    template<> void ScriptInterface::ToJSVal<IGUIObject*>(JSContext* UNUSED(cx), JS:  
    121122    else
    122123        ret.setObject(*val->GetJSObject());
    123124}
     125
     126// define some vectors
     127VECTOR(CVector2D)
     128VECTOR(std::vector<CVector2D>)
     129
  • source/gui/scripting/JSInterface_IGUIObject.cpp

    diff --git a/source/gui/scripting/JSInterface_IGUIObject.cpp b/source/gui/scripting/JSInterface_IGUIObject.cpp
    index 471b00c..48b1890 100644
    a b bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Handle  
    302302        {
    303303            CGUISeries value;
    304304            GUI<CGUISeries>::GetSetting(e, propName, value);
    305 
    306             JS::RootedObject obj(cx, JS_NewArrayObject(cx, JS::HandleValueArray::empty()));
    307             vp.setObject(*obj);
    308 
    309             for (u32 i = 0; i < value.m_Series.size(); ++i)
    310             {
    311                 JS::RootedObject inner_obj(cx, JS_NewArrayObject(cx, JS::HandleValueArray::empty()));
    312                 for (u32 j = 0; j < value.m_Series[i].size(); ++j)
    313                 {
    314                     JS::RootedObject val(cx, JS_NewArrayObject(cx, JS::HandleValueArray::empty()));
    315 
    316                     JS::RootedValue val_x(cx), val_y(cx);
    317                     ScriptInterface::ToJSVal(cx, &val_x, value.m_Series[i][j].X);
    318                     ScriptInterface::ToJSVal(cx, &val_y, value.m_Series[i][j].Y);
    319                     JS_SetElement(cx, val, 0, val_x);
    320                     JS_SetElement(cx, val, 1, val_y);
    321 
    322                     JS_SetElement(cx, inner_obj, j, val);
    323                 }
    324                 JS_SetElement(cx, obj, i, inner_obj);
    325             }
    326 
     305            ScriptInterface::ToJSVal(cx, vp, value.m_Series);
    327306            break;
    328307        }
    329308
    bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Handle  
    619598
    620599    case GUIST_CGUISeries:
    621600    {
    622         u32 length;
    623         if (!vp.isObject() || !JS_GetArrayLength(cx, vpObj, &length))
    624         {
    625             JS_ReportError(cx, "Table only accepts a GUISeries object");
    626             return false;
    627         }
    628 
    629601        CGUISeries series;
    630         series.m_Series.resize(length);
    631         for (u32 i = 0; i < length; ++i)
     602        if (ScriptInterface::FromJSVal(cx, vp, series.m_Series))
     603            GUI<CGUISeries>::SetSetting(e, propName, series);
     604        else
    632605        {
    633             JS::RootedValue data_value(cx);
    634             if (!JS_GetElement(cx, vpObj, i, &data_value))
    635             {
    636                 JS_ReportError(cx, "Failed to get a data of series");
    637                 return false;
    638             }
    639 
    640             JS::RootedObject data(cx, data_value.toObjectOrNull());
    641             u32 data_length;
    642             if (!JS_GetArrayLength(cx, data, &data_length))
    643             {
    644                 JS_ReportError(cx, "Series only accepts a chart data");
    645                 return false;
    646             }
    647 
    648             series.m_Series[i].resize(data_length);
    649             for (u32 j = 0; j < data_length; ++j)
    650             {
    651                 JS::RootedValue element_value(cx);
    652                 if (!JS_GetElement(cx, data, j, &element_value))
    653                 {
    654                     JS_ReportError(cx, "Failed to get a chart data element");
    655                     return false;
    656                 }
    657 
    658                 JS::RootedObject element(cx, element_value.toObjectOrNull());
    659                 u32 element_length;
    660                 if (!JS_GetArrayLength(cx, element, &element_length) || element_length < 2)
    661                 {
    662                     JS_ReportError(cx, "Chart data only accepts a point");
    663                     return false;
    664                 }
    665 
    666                 JS::RootedValue element_x(cx), element_y(cx);
    667                 if (!JS_GetElement(cx, element, 0, &element_x) || !JS_GetElement(cx, element, 1, &element_y))
    668                 {
    669                     JS_ReportError(cx, "Failed to get a chart point");
    670                     return false;
    671                 }
    672 
    673                 if (!ScriptInterface::FromJSVal(cx, element_x, series.m_Series[i][j].X) ||
    674                     !ScriptInterface::FromJSVal(cx, element_y, series.m_Series[i][j].Y))
    675                     return false;
    676             }
     606            JS_ReportError(cx, "Invalid value for chart series '%s'", propName.c_str());
     607            return false;
    677608        }
    678 
    679         GUI<CGUISeries>::SetSetting(e, propName, series);
    680609        break;
    681610    }
    682611
  • source/scriptinterface/ScriptConversions.cpp

    diff --git a/source/scriptinterface/ScriptConversions.cpp b/source/scriptinterface/ScriptConversions.cpp
    index bf7e910..538c32a 100644
    a b  
    1515 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
    1616 */
    1717
    18 #include "precompiled.h"
    19 
    20 #include "ScriptInterface.h"
     18#include "ScriptConversions.h"
    2119
    2220#include "graphics/Entity.h"
     21#include "maths/Vector2D.h"
    2322#include "ps/utf16string.h"
    24 #include "ps/CLogger.h"
    2523#include "ps/CStr.h"
    26 #include "scriptinterface/ScriptExtraHeaders.h" // for typed arrays
    27 
    28 #define FAIL(msg) STMT(JS_ReportError(cx, msg); return false)
    29 
    30 // Implicit type conversions often hide bugs, so warn about them
    31 #define WARN_IF_NOT(c, v) STMT(if (!(c)) { JS_ReportWarning(cx, "Script value conversion check failed: %s (got type %s)", #c, InformalValueTypeName(v)); })
    3224
    3325// TODO: SpiderMonkey: Follow upstream progresses about JS_InformalValueTypeName in the API
    3426// https://bugzilla.mozilla.org/show_bug.cgi?id=1285917
    template<> void ScriptInterface::ToJSVal<CStr8>(JSContext* cx, JS::MutableHandle  
    376368}
    377369
    378370////////////////////////////////////////////////////////////////
    379 // Compound types:
    380 
    381 template<typename T> static void ToJSVal_vector(JSContext* cx, JS::MutableHandleValue ret, const std::vector<T>& val)
    382 {
    383     JSAutoRequest rq(cx);
    384     JS::RootedObject obj(cx, JS_NewArrayObject(cx, 0));
    385     if (!obj)
    386     {
    387         ret.setUndefined();
    388         return;
    389     }
    390     for (u32 i = 0; i < val.size(); ++i)
    391     {
    392         JS::RootedValue el(cx);
    393         ScriptInterface::ToJSVal<T>(cx, &el, val[i]);
    394         JS_SetElement(cx, obj, i, el);
    395     }
    396     ret.setObject(*obj);
    397 }
    398 
    399 template<typename T> static bool FromJSVal_vector(JSContext* cx, JS::HandleValue v, std::vector<T>& out)
    400 {
    401     JSAutoRequest rq(cx);
    402     JS::RootedObject obj(cx);
    403     if (!v.isObject())
    404         FAIL("Argument must be an array");
    405     obj = &v.toObject();
    406     if (!(JS_IsArrayObject(cx, obj) || JS_IsTypedArrayObject(obj)))
    407         FAIL("Argument must be an array");
    408 
    409     u32 length;
    410     if (!JS_GetArrayLength(cx, obj, &length))
    411         FAIL("Failed to get array length");
    412     out.reserve(length);
    413     for (u32 i = 0; i < length; ++i)
    414     {
    415         JS::RootedValue el(cx);
    416         if (!JS_GetElement(cx, obj, i, &el))
    417             FAIL("Failed to read array element");
    418         T el2;
    419         if (!ScriptInterface::FromJSVal<T>(cx, el, el2))
    420             return false;
    421         out.push_back(el2);
    422     }
    423     return true;
    424 }
    425 
     371// Compound types
    426372// Instantiate various vector types:
    427373
    428 #define VECTOR(T) \
    429     template<> void ScriptInterface::ToJSVal<std::vector<T> >(JSContext* cx, JS::MutableHandleValue ret, const std::vector<T>& val) \
    430     { \
    431         ToJSVal_vector(cx, ret, val); \
    432     } \
    433     template<> bool ScriptInterface::FromJSVal<std::vector<T> >(JSContext* cx, JS::HandleValue v, std::vector<T>& out) \
    434     { \
    435         return FromJSVal_vector(cx, v, out); \
    436     }
    437 
    438374VECTOR(int)
    439375VECTOR(u32)
    440376VECTOR(u16)
    template<> bool ScriptInterface::FromJSVal<std::vector<Entity> >(JSContext* cx,  
    453389{
    454390    return FromJSVal_vector(cx, v, out);
    455391}
     392
     393template<> void ScriptInterface::ToJSVal<CVector2D>(JSContext* cx, JS::MutableHandleValue ret, const CVector2D& val)
     394{
     395    std::vector<float> vec = {val.X, val.Y};
     396    ToJSVal_vector(cx, ret, vec);
     397}
     398
     399template<> bool ScriptInterface::FromJSVal<CVector2D>(JSContext* cx, JS::HandleValue v, CVector2D& out)
     400{
     401    std::vector<float> vec;
     402
     403    if (!FromJSVal_vector(cx, v, vec))
     404        return false;
     405
     406    if (vec.size() != 2)
     407        return false;
     408
     409    out.X = vec[0];
     410    out.Y = vec[1];
     411
     412    return true;
     413}
  • new file source/scriptinterface/ScriptConversions.h

    diff --git a/source/scriptinterface/ScriptConversions.h b/source/scriptinterface/ScriptConversions.h
    new file mode 100644
    index 0000000..d136de3
    - +  
     1/* Copyright (C) 2016 Wildfire Games.
     2 * This file is part of 0 A.D.
     3 *
     4 * 0 A.D. is free software: you can redistribute it and/or modify
     5 * it under the terms of the GNU General Public License as published by
     6 * the Free Software Foundation, either version 2 of the License, or
     7 * (at your option) any later version.
     8 *
     9 * 0 A.D. 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
     12 * GNU General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU General Public License
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18#ifndef INCLUDED_SCRIPTCONVERSIONS
     19#define INCLUDED_SCRIPTCONVERSIONS
     20
     21#include "precompiled.h"
     22
     23#include "ScriptInterface.h"
     24#include "ps/CLogger.h"
     25#include "scriptinterface/ScriptExtraHeaders.h" // for typed arrays
     26
     27#define FAIL(msg) STMT(JS_ReportError(cx, msg); return false)
     28
     29// Implicit type conversions often hide bugs, so warn about them
     30#define WARN_IF_NOT(c, v) STMT(if (!(c)) { JS_ReportWarning(cx, "Script value conversion check failed: %s (got type %s)", #c, InformalValueTypeName(v)); })
     31
     32template<typename T> static void ToJSVal_vector(JSContext* cx, JS::MutableHandleValue ret, const std::vector<T>& val)
     33{
     34    JSAutoRequest rq(cx);
     35    JS::RootedObject obj(cx, JS_NewArrayObject(cx, 0));
     36    if (!obj)
     37    {
     38        ret.setUndefined();
     39        return;
     40    }
     41    for (u32 i = 0; i < val.size(); ++i)
     42    {
     43        JS::RootedValue el(cx);
     44        ScriptInterface::ToJSVal<T>(cx, &el, val[i]);
     45        JS_SetElement(cx, obj, i, el);
     46    }
     47    ret.setObject(*obj);
     48}
     49
     50template<typename T> static bool FromJSVal_vector(JSContext* cx, JS::HandleValue v, std::vector<T>& out)
     51{
     52    JSAutoRequest rq(cx);
     53    JS::RootedObject obj(cx);
     54    if (!v.isObject())
     55        FAIL("Argument must be an array");
     56    obj = &v.toObject();
     57    if (!(JS_IsArrayObject(cx, obj) || JS_IsTypedArrayObject(obj)))
     58        FAIL("Argument must be an array");
     59
     60    u32 length;
     61    if (!JS_GetArrayLength(cx, obj, &length))
     62        FAIL("Failed to get array length");
     63    out.reserve(length);
     64    for (u32 i = 0; i < length; ++i)
     65    {
     66        JS::RootedValue el(cx);
     67        if (!JS_GetElement(cx, obj, i, &el))
     68            FAIL("Failed to read array element");
     69        T el2;
     70        if (!ScriptInterface::FromJSVal<T>(cx, el, el2))
     71            return false;
     72        out.push_back(el2);
     73    }
     74    return true;
     75}
     76
     77#define VECTOR(T) \
     78template<> void ScriptInterface::ToJSVal<std::vector<T> >(JSContext* cx, JS::MutableHandleValue ret, const std::vector<T>& val) \
     79{ \
     80ToJSVal_vector(cx, ret, val); \
     81} \
     82template<> bool ScriptInterface::FromJSVal<std::vector<T> >(JSContext* cx, JS::HandleValue v, std::vector<T>& out) \
     83{ \
     84return FromJSVal_vector(cx, v, out); \
     85}
     86
     87#endif //INCLUDED_SCRIPTCONVERSIONS
  • source/simulation2/scripting/EngineScriptConversions.cpp

    diff --git a/source/simulation2/scripting/EngineScriptConversions.cpp b/source/simulation2/scripting/EngineScriptConversions.cpp
    index 5aa970c..299e2d7 100644
    a b  
    1717
    1818#include "precompiled.h"
    1919
    20 #include "scriptinterface/ScriptInterface.h"
    21 #include "scriptinterface/ScriptExtraHeaders.h" // for typed arrays
     20#include "scriptinterface/ScriptConversions.h"
    2221
    2322#include "maths/Fixed.h"
    2423#include "maths/FixedVector2D.h"
    template<> void ScriptInterface::ToJSVal<Grid<u16> >(JSContext* cx, JS::MutableH  
    299298    ret.setObject(*obj);
    300299}
    301300
    302 // TODO: This is copy-pasted from scriptinterface/ScriptConversions.cpp (#define VECTOR stuff), would be nice to remove the duplication
    303 template<> void ScriptInterface::ToJSVal<std::vector<CFixedVector2D> >(JSContext* cx, JS::MutableHandleValue ret, const std::vector<CFixedVector2D>& val)
    304 {
    305     JSAutoRequest rq(cx);
    306     JS::RootedObject obj(cx, JS_NewArrayObject(cx, 0));
    307     if (!obj)
    308     {
    309         ret.setUndefined();
    310         return;
    311     }
    312     for (size_t i = 0; i < val.size(); ++i)
    313     {
    314         JS::RootedValue el(cx);
    315         ScriptInterface::ToJSVal<CFixedVector2D>(cx, &el, val[i]);
    316         JS_SetElement(cx, obj, i, el);
    317     }
    318     ret.setObject(*obj);
    319 }
     301// define vectors
     302VECTOR(CFixedVector2D)