Просмотр исходного кода

fix: handle JS string concatenation when parsing a node's configSchema

The hand-rolled JS-object-literal-to-JSON parser in node_store.cpp read
each quoted string literal in isolation, so a description written as
'a' + 'b' + 'c' across lines (as http-request.js's failOnErrorStatus
does) left the + operators as raw text between two JSON strings.
nlohmann::json::parse then rejected the whole configSchema, the parse
failure was logged but the node was still migrated with a null
configSchema, and the API omitted the field entirely - which is what
made the editor show "No configuration options for this node type."
for every http-request node.

appendJsString now follows a chain of +-joined string literals into one
JSON string instead of leaving the operator in the output. Verified
against the running database: http-request's configSchema now carries
all 20 properties declared in nodes/core/http-request.js, matching
execute()'s use of config.* exactly, and no other node was found with
a missing schema from the same cause.
fszontagh 1 месяц назад
Родитель
Сommit
875c668318
1 измененных файлов с 36 добавлено и 4 удалено
  1. 36 4
      src/webserver/nodes/node_store.cpp

+ 36 - 4
src/webserver/nodes/node_store.cpp

@@ -17,11 +17,11 @@ using namespace common;
 // it - strings, escapes and comments recognised - and rewritten as JSON.
 // it - strings, escapes and comments recognised - and rewritten as JSON.
 namespace {
 namespace {
 
 
-// Appends one JavaScript string literal to out as a JSON string. Reading starts
-// at the opening quote and leaves i on the closing one.
-void appendJsString(const std::string& code, size_t& i, std::string& out) {
+// Appends one JavaScript string literal's content (escaped for JSON, but
+// without the surrounding quotes) to out. Reading starts at the opening quote
+// and leaves i on the closing one.
+void appendJsStringContent(const std::string& code, size_t& i, std::string& out) {
     const char quote = code[i];
     const char quote = code[i];
-    out += '"';
     ++i;
     ++i;
 
 
     while (i < code.size() && code[i] != quote) {
     while (i < code.size() && code[i] != quote) {
@@ -63,8 +63,40 @@ void appendJsString(const std::string& code, size_t& i, std::string& out) {
         }
         }
         ++i;
         ++i;
     }
     }
+}
+
+// Appends one JavaScript string literal to out as a JSON string, following
+// through any `'a' + 'b' + 'c'` concatenation into a single JSON string -
+// authors wrap a long description across lines this way, and JSON has no
+// concatenation operator of its own to leave behind. Reading starts at the
+// opening quote of the first literal and leaves i on the closing quote of the
+// last one in the chain.
+void appendJsString(const std::string& code, size_t& i, std::string& out) {
+    std::string content;
+    appendJsStringContent(code, i, content);
+
+    for (;;) {
+        size_t j = i + 1;
+        while (j < code.size() && std::isspace(static_cast<unsigned char>(code[j]))) {
+            ++j;
+        }
+        if (j >= code.size() || code[j] != '+') {
+            break;
+        }
+        ++j;
+        while (j < code.size() && std::isspace(static_cast<unsigned char>(code[j]))) {
+            ++j;
+        }
+        if (j >= code.size() || (code[j] != '\'' && code[j] != '"' && code[j] != '`')) {
+            break;   // "+" concatenates something that is not a string literal
+        }
+        i = j;
+        appendJsStringContent(code, i, content);
+    }
 
 
     out += '"';
     out += '"';
+    out += content;
+    out += '"';
 }
 }
 
 
 // Drops whatever trailing whitespace and one trailing comma sit at the end of
 // Drops whatever trailing whitespace and one trailing comma sit at the end of