Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: graphql/graphql-js
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v14.5.4
Choose a base ref
...
head repository: graphql/graphql-js
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v14.5.5
Choose a head ref
  • 6 commits
  • 12 files changed
  • 3 contributors

Commits on Sep 3, 2019

  1. Verified

    This commit was signed with the committer’s verified signature.
    driesvints Dries Vints
    Copy the full SHA
    6609d39 View commit details

Commits on Sep 6, 2019

  1. Typos (#2157)

    Cito authored and IvanGoncharov committed Sep 6, 2019
    1
    Copy the full SHA
    ff282d7 View commit details

Commits on Sep 11, 2019

  1. Copy the full SHA
    5c42dc6 View commit details

Commits on Sep 12, 2019

  1. RFC: Lexing is Greedy (#2163)

    Adds the test cases described in graphql/graphql-spec#599
    
    Makes the lookahead restriction change necessary for the new tests to pass for numbers, all other tests are already passing.
    leebyron authored Sep 12, 2019
    Copy the full SHA
    c68acd8 View commit details
  2. Minor fix in extensions-test (#2168)

    Cito authored and IvanGoncharov committed Sep 12, 2019
    Copy the full SHA
    a53d5b3 View commit details

Commits on Sep 13, 2019

  1. v14.5.5

    IvanGoncharov committed Sep 13, 2019
    Copy the full SHA
    38bd337 View commit details
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "graphql",
"version": "14.5.4",
"version": "14.5.5",
"description": "A Query Language and Runtime which can target any service.",
"license": "MIT",
"private": true,
144 changes: 133 additions & 11 deletions src/language/__tests__/lexer-test.js
Original file line number Diff line number Diff line change
@@ -49,6 +49,65 @@ describe('Lexer', () => {
});
});

it('tracks line breaks', () => {
expect(lexOne('foo')).to.contain({
kind: TokenKind.NAME,
start: 0,
end: 3,
line: 1,
column: 1,
value: 'foo',
});
expect(lexOne('\nfoo')).to.contain({
kind: TokenKind.NAME,
start: 1,
end: 4,
line: 2,
column: 1,
value: 'foo',
});
expect(lexOne('\rfoo')).to.contain({
kind: TokenKind.NAME,
start: 1,
end: 4,
line: 2,
column: 1,
value: 'foo',
});
expect(lexOne('\r\nfoo')).to.contain({
kind: TokenKind.NAME,
start: 2,
end: 5,
line: 2,
column: 1,
value: 'foo',
});
expect(lexOne('\n\rfoo')).to.contain({
kind: TokenKind.NAME,
start: 2,
end: 5,
line: 3,
column: 1,
value: 'foo',
});
expect(lexOne('\r\r\n\nfoo')).to.contain({
kind: TokenKind.NAME,
start: 4,
end: 7,
line: 4,
column: 1,
value: 'foo',
});
expect(lexOne('\n\n\r\rfoo')).to.contain({
kind: TokenKind.NAME,
start: 4,
end: 7,
line: 5,
column: 1,
value: 'foo',
});
});

it('records line and column', () => {
expect(lexOne('\n \r\n \r foo\n')).to.contain({
kind: TokenKind.NAME,
@@ -111,24 +170,18 @@ describe('Lexer', () => {
it('errors respect whitespace', () => {
let caughtError;
try {
lexOne(dedent`
?
`);
lexOne(['', '', ' ?', ''].join('\n'));
} catch (error) {
caughtError = error;
}
expect(String(caughtError) + '\n').to.equal(dedent`
Syntax Error: Cannot parse the unexpected character "?".
GraphQL request:3:5
2 |
2 |
3 | ?
| ^
4 |
4 |
`);
});

@@ -145,10 +198,10 @@ describe('Lexer', () => {
Syntax Error: Cannot parse the unexpected character "?".
foo.js:13:6
12 |
12 |
13 | ?
| ^
14 |
14 |
`);
});

@@ -170,6 +223,13 @@ describe('Lexer', () => {
});

it('lexes strings', () => {
expect(lexOne('""')).to.contain({
kind: TokenKind.STRING,
start: 0,
end: 2,
value: '',
});

expect(lexOne('"simple"')).to.contain({
kind: TokenKind.STRING,
start: 0,
@@ -216,6 +276,10 @@ describe('Lexer', () => {
it('lex reports useful string errors', () => {
expectSyntaxError('"', 'Unterminated string.', { line: 1, column: 2 });

expectSyntaxError('"""', 'Unterminated string.', { line: 1, column: 4 });

expectSyntaxError('""""', 'Unterminated string.', { line: 1, column: 5 });

expectSyntaxError('"no end quote', 'Unterminated string.', {
line: 1,
column: 14,
@@ -293,6 +357,13 @@ describe('Lexer', () => {
});

it('lexes block strings', () => {
expect(lexOne('""""""')).to.contain({
kind: TokenKind.BLOCK_STRING,
start: 0,
end: 6,
value: '',
});

expect(lexOne('"""simple"""')).to.contain({
kind: TokenKind.BLOCK_STRING,
start: 0,
@@ -544,6 +615,20 @@ describe('Lexer', () => {
column: 2,
});

expectSyntaxError('01', 'Invalid number, unexpected digit after 0: "1".', {
line: 1,
column: 2,
});

expectSyntaxError(
'01.23',
'Invalid number, unexpected digit after 0: "1".',
{
line: 1,
column: 2,
},
);

expectSyntaxError('+1', 'Cannot parse the unexpected character "+".', {
line: 1,
column: 1,
@@ -554,6 +639,16 @@ describe('Lexer', () => {
column: 3,
});

expectSyntaxError('1e', 'Invalid number, expected digit but got: <EOF>.', {
line: 1,
column: 3,
});

expectSyntaxError('1E', 'Invalid number, expected digit but got: <EOF>.', {
line: 1,
column: 3,
});

expectSyntaxError('1.e1', 'Invalid number, expected digit but got: "e".', {
line: 1,
column: 3,
@@ -584,6 +679,33 @@ describe('Lexer', () => {
line: 1,
column: 5,
});

expectSyntaxError(
'1.2e3e',
'Invalid number, expected digit but got: "e".',
{
line: 1,
column: 6,
},
);

expectSyntaxError(
'1.2e3.4',
'Invalid number, expected digit but got: ".".',
{
line: 1,
column: 6,
},
);

expectSyntaxError(
'1.23.4',
'Invalid number, expected digit but got: ".".',
{
line: 1,
column: 5,
},
);
});

it('lexes punctuation', () => {
2 changes: 1 addition & 1 deletion src/language/__tests__/parser-test.js
Original file line number Diff line number Diff line change
@@ -379,7 +379,7 @@ describe('Parser', () => {
expect(() => parse(document)).to.throw('Syntax Error');
});

it('contains location information that only stringifys start/end', () => {
it('contains location information that only stringifies start/end', () => {
const result = parse('{ id }');

expect(JSON.stringify(result.loc)).to.equal('{"start":0,"end":6}');
2 changes: 1 addition & 1 deletion src/language/__tests__/printLocation-test.js
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ describe('printSourceLocation', () => {
Test:9:1
9 | *
| ^
10 |
10 |
`);
});
});
10 changes: 10 additions & 0 deletions src/language/lexer.js
Original file line number Diff line number Diff line change
@@ -444,6 +444,16 @@ function readNumber(source, start, firstCode, line, col, prev): Token {
code = body.charCodeAt(++position);
}
position = readDigits(source, position, code);
code = body.charCodeAt(position);
}
// Numbers cannot be followed by . or e
if (code === 46 || code === 69 || code === 101) {
throw syntaxError(
source,
position,
`Invalid number, expected digit but got: ${printCharCode(code)}.`,
);
}
return new Tok(
4 changes: 3 additions & 1 deletion src/language/printLocation.js
Original file line number Diff line number Diff line change
@@ -72,7 +72,9 @@ function printPrefixedLines(lines: $ReadOnlyArray<[string, string]>): string {

const padLen = Math.max(...existingLines.map(([prefix]) => prefix.length));
return existingLines
.map(([prefix, line]) => lpad(padLen, prefix) + ' | ' + line)
.map(
([prefix, line]) => lpad(padLen, prefix) + (line ? ' | ' + line : ' |'),
)
.join('\n');
}

8 changes: 5 additions & 3 deletions src/type/__tests__/extensions-test.js
Original file line number Diff line number Diff line change
@@ -149,11 +149,13 @@ describe('Type System: Extensions', () => {
});

it('with extensions', () => {
const interfaceExtensions = Object.freeze({ SomeObjectExt: 'object' });
const interfaceExtensions = Object.freeze({
SomeInterfaceExt: 'interface',
});
const fieldExtensions = Object.freeze({ SomeFieldExt: 'field' });
const argExtensions = Object.freeze({ SomeArgExt: 'arg' });

const someInterface = new GraphQLObjectType({
const someInterface = new GraphQLInterfaceType({
name: 'SomeInterface',
fields: {
someField: {
@@ -200,7 +202,7 @@ describe('Type System: Extensions', () => {
});

it('with extensions', () => {
const unionExtensions = Object.freeze({ SomeScalarExt: 'union' });
const unionExtensions = Object.freeze({ SomeUnionExt: 'union' });

const someUnion = new GraphQLUnionType({
name: 'SomeUnion',
2 changes: 1 addition & 1 deletion src/type/__tests__/scalars-test.js
Original file line number Diff line number Diff line change
@@ -322,7 +322,7 @@ describe('Type System: Specified scalar types', () => {
expect(parseLiteral('0')).to.equal('0');
expect(parseLiteral('-1')).to.equal('-1');

// Support arbituary long numbers even if they can't be represented in JS
// Support arbitrary long numbers even if they can't be represented in JS
expect(parseLiteral('90071992547409910')).to.equal('90071992547409910');
expect(parseLiteral('-90071992547409910')).to.equal('-90071992547409910');

32 changes: 32 additions & 0 deletions src/utilities/__tests__/findBreakingChanges-test.js
Original file line number Diff line number Diff line change
@@ -921,6 +921,38 @@ describe('findDangerousChanges', () => {
expect(findDangerousChanges(oldSchema, newSchema)).to.deep.equal([]);
});

it('should ignore changes in field definitions order', () => {
const oldSchema = buildSchema(`
input Input1 {
a: String
b: String
c: String
}
type Type1 {
field1(
arg1: Input1 = { a: "a", b: "b", c: "c" }
): String
}
`);

const newSchema = buildSchema(`
input Input1 {
c: String
b: String
a: String
}
type Type1 {
field1(
arg1: Input1 = { a: "a", b: "b", c: "c" }
): String
}
`);

expect(findDangerousChanges(oldSchema, newSchema)).to.deep.equal([]);
});

it('should detect if a value was added to an enum type', () => {
const oldSchema = buildSchema(`
enum EnumType1 {
16 changes: 15 additions & 1 deletion src/utilities/findBreakingChanges.js
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import inspect from '../jsutils/inspect';
import invariant from '../jsutils/invariant';

import { print } from '../language/printer';
import { visit } from '../language/visitor';

import { type GraphQLSchema } from '../type/schema';
import {
@@ -395,6 +396,9 @@ function findArgChanges(
description: `${oldType.name}.${oldField.name} arg ${oldArg.name} defaultValue was removed.`,
});
} else {
// Since we looking only for client's observable changes we should
// compare default values in the same representation as they are
// represented inside introspection.
const oldValueStr = stringifyValue(oldArg.defaultValue, oldArg.type);
const newValueStr = stringifyValue(newArg.defaultValue, newArg.type);

@@ -518,7 +522,17 @@ function typeKindName(type: GraphQLNamedType): string {
function stringifyValue(value: mixed, type: GraphQLInputType): string {
const ast = astFromValue(value, type);
invariant(ast != null);
return print(ast);

const sortedAST = visit(ast, {
ObjectValue(objectNode) {
const fields = [...objectNode.fields].sort((fieldA, fieldB) =>
fieldA.name.value.localeCompare(fieldB.name.value),
);
return { ...objectNode, fields };
},
});

return print(sortedAST);
}

function diff<T: { name: string, ... }>(
2 changes: 1 addition & 1 deletion src/validation/__tests__/KnownTypeNames-test.js
Original file line number Diff line number Diff line change
@@ -175,7 +175,7 @@ describe('Validate: Known type names', () => {
]);
});

it('doesnot consider non-type definitions', () => {
it('does not consider non-type definitions', () => {
expectSDLErrors(`
query Foo { __typename }
fragment Foo on Query { __typename }
4 changes: 2 additions & 2 deletions src/version.js
Original file line number Diff line number Diff line change
@@ -8,14 +8,14 @@
/**
* A string containing the version of the GraphQL.js library
*/
export const version = '14.5.4';
export const version = '14.5.5';

/**
* An object containing the components of the GraphQL.js version string
*/
export const versionInfo = Object.freeze({
major: 14,
minor: 5,
patch: 4,
patch: 5,
preReleaseTag: null,
});