Mirror: The spec-compliant minimum of client-side GraphQL.

Fix string and block string matches being too eager (#17)

* Add test cases for strings greedily matching

* Fix blockStringRe and stringRe eagerly parsing

* Add changeset

Changed files
+31 -2
.changeset
src
+5
.changeset/loud-countries-mix.md
···
+
---
+
'@0no-co/graphql.web': patch
+
---
+
+
Fix string and block string matches eagerly matching past the end boundary of strings and ignoring escaped closing characters. In certain cases, `"""` and `"` boundaries would be skipped if any other string boundary follows in the input document.
+24
src/__tests__/parser.test.ts
···
value: '\t\t',
block: false,
});
+
+
expect(parseValue('" \\" "')).toEqual({
+
kind: Kind.STRING,
+
value: ' " ',
+
block: false,
+
});
+
+
expect(parseValue('"x" "x"')).toEqual({
+
kind: Kind.STRING,
+
value: 'x',
+
block: false,
+
});
});
it('parses objects', () => {
···
expect(parseValue('"""\n\n first\n second\n"""')).toEqual({
kind: Kind.STRING,
value: 'first\nsecond',
+
block: true,
+
});
+
+
expect(parseValue('""" \\""" """')).toEqual({
+
kind: Kind.STRING,
+
value: ' """ ',
+
block: true,
+
});
+
+
expect(parseValue('"""x""" """x"""')).toEqual({
+
kind: Kind.STRING,
+
value: 'x',
block: true,
});
});
+2 -2
src/parser.ts
···
const floatPartRe = /(?:\.\d+)?[eE][+-]?\d+|\.\d+/y;
const complexStringRe = /\\/g;
-
const blockStringRe = /"""(?:[\s\S]+(?="""))?"""/y;
-
const stringRe = /"(?:[^"\r\n]+)?"/y;
+
const blockStringRe = /"""(?:[\s\S]*?[^\\])?"""/y;
+
const stringRe = /"(?:[^\r\n]*?[^\\])?"/y;
function value(constant: true): ast.ConstValueNode;
function value(constant: boolean): ast.ValueNode;