Use JSON escaping for JSON string output
The previous code used Value::ToString to convert GN strings into quoted
JSON strings, but this caused incorrect escaping behavior. For example,
the string "$" needs to be escaped in Ninja to prevent accidental
variable expansion but not in JSON.
Change-Id: I91c8e9b2486a67af5a3ba41efdb731aa31cc6df3
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/18900
Commit-Queue: Takuto Ikuta <tikuta@google.com>
Reviewed-by: Takuto Ikuta <tikuta@google.com>
diff --git a/src/gn/output_conversion.cc b/src/gn/output_conversion.cc
index 971e740..3bfbb10 100644
--- a/src/gn/output_conversion.cc
+++ b/src/gn/output_conversion.cc
@@ -4,6 +4,7 @@
#include "gn/output_conversion.h"
+#include "gn/escape.h"
#include "gn/settings.h"
#include "gn/value.h"
@@ -37,8 +38,10 @@
RenderScopeToJSON(value, out, indent + 1);
else if (value.type() == Value::LIST)
RenderListToJSON(value, out, indent + 1);
+ else if (value.type() == Value::STRING)
+ EscapeJSONStringToStream(out, value.ToString(false), EscapeOptions());
else
- out << value.ToString(true);
+ out << value.ToString(false);
first = false;
}
out << "\n";
@@ -61,8 +64,11 @@
RenderScopeToJSON(pair.second, out, indent + 1);
else if (pair.second.type() == Value::LIST)
RenderListToJSON(pair.second, out, indent + 1);
+ else if (pair.second.type() == Value::STRING)
+ EscapeJSONStringToStream(out, pair.second.ToString(false),
+ EscapeOptions());
else
- out << pair.second.ToString(true);
+ out << pair.second.ToString(false);
first = false;
}
out << "\n";
diff --git a/src/gn/output_conversion_unittest.cc b/src/gn/output_conversion_unittest.cc
index 43fdad5..1eaf2ab 100644
--- a/src/gn/output_conversion_unittest.cc
+++ b/src/gn/output_conversion_unittest.cc
@@ -186,8 +186,11 @@
auto c_scope = std::make_unique<Scope>(settings());
Value e_value(nullptr, Value::LIST);
e_value.list_value().push_back(Value(nullptr, "bar"));
+ e_value.list_value().push_back(Value(nullptr, "$"));
auto e_value_scope = std::make_unique<Scope>(settings());
+ Value d_value(nullptr, "$");
+ e_value_scope->SetValue("d", d_value, nullptr);
Value f_value(nullptr, "baz");
e_value_scope->SetValue("f", f_value, nullptr);
e_value.list_value().push_back(Value(nullptr, std::move(e_value_scope)));
@@ -202,7 +205,9 @@
"c": {
"e": [
"bar",
+ "$",
{
+ "d": "$",
"f": "baz"
}
]