emit and parse fail to respect some escaping rules for quotes and backslashes
TimHambourger opened this issue · 0 comments
emit
and parse
both fail to respect some of the escaping rules for quotes and backslashes from rsql-parser (relevant excerpts quoted below). The result is that ValueNode
s whose value
contains double quotes get corrupted when round-tripping through emit
then parse
.
@rsql version 1.3.2
Node version 16.15.1
Repro steps
Run the following snippet in an ES6 JS environment:
import builder from "@rsql/builder";
import { emit } from "@rsql/emitter";
import { parse } from "@rsql/parser";
const node = builder.comparison("selector", "==", "foo\"bar\\baz");
console.log(node.right.value);
const rsql = emit(node);
console.log(rsql);
const roundTrippedNode = parse(rsql);
// In TS we'd need to assert that roundTrippedNode is a ComparisonNode for this to compile.
console.log(roundTrippedNode.right.value);
Expected outcome
Console contains the following logged values (per rsql-parser escaping rules):
foo"bar\baz
selector=="foo\"bar\\baz"
foo"bar\baz
Actual outcome
Console contains the following logged values:
foo"bar\baz
selector=="fo\"bar\baz"
fo\"bar\baz
Relevant rsql-parser escaping rules
From https://github.com/jirutka/rsql-parser#grammar-and-semantic (emphasis added):
If you need to use both single and double quotes inside a quoted argument, then you must escape one of them using
\
(backslash). If you want to use\
literally, then double it as\\
. Backslash has a special meaning only inside a quoted argument, not in unquoted argument.
Analysis
emit
escapes "
(double quote) as \"
, but in the process it consumes the preceding character. Furthermore, emit
fails to escape \
(backslash) as \\
, as is required if (and only if) the value is being wrapped in quotes.
Meanwhile, parse
correctly continues parsing the ValueNode
's value
past the \"
sequence, i.e. it doesn't mistake the "
in \"
as ending the ValueNode
's value
. But parse
fails to consume the \
in \"
in the process, as it fails to consume the later \
in bar\baz
.