Skip to content

Commit

Permalink
Update built-in scalar's parseLiteral method to throw TypeError (#1827)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielrearden authored and IvanGoncharov committed Sep 19, 2019
1 parent 06ef5db commit dd3b265
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 93 deletions.
3 changes: 2 additions & 1 deletion src/type/__tests__/enumType-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,8 @@ describe('Type System: Enum Values', () => {
expect(result).to.deep.equal({
errors: [
{
message: 'Expected value of type "Int", found GREEN.',
message:
'Expected value of type "Int", found GREEN; Int cannot represent non-integer value: GREEN',
locations: [{ line: 1, column: 22 }],
},
],
Expand Down
182 changes: 136 additions & 46 deletions src/type/__tests__/scalars-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,40 @@ describe('Type System: Specified scalar types', () => {
expect(parseLiteral('0')).to.equal(0);
expect(parseLiteral('-1')).to.equal(-1);

expect(parseLiteral('9876504321')).to.equal(undefined);
expect(parseLiteral('-9876504321')).to.equal(undefined);

expect(parseLiteral('1.0')).to.equal(undefined);
expect(parseLiteral('null')).to.equal(undefined);
expect(parseLiteral('""')).to.equal(undefined);
expect(parseLiteral('"123"')).to.equal(undefined);
expect(parseLiteral('false')).to.equal(undefined);
expect(parseLiteral('[1]')).to.equal(undefined);
expect(parseLiteral('{ value: 1 }')).to.equal(undefined);
expect(parseLiteral('ENUM_VALUE')).to.equal(undefined);
expect(parseLiteral('$var')).to.equal(undefined);
expect(() => parseLiteral('9876504321')).to.throw(
'Int cannot represent non 32-bit signed integer value: 9876504321',
);
expect(() => parseLiteral('-9876504321')).to.throw(
'Int cannot represent non 32-bit signed integer value: -9876504321',
);

expect(() => parseLiteral('1.0')).to.throw(
'Int cannot represent non-integer value: 1.0',
);
expect(() => parseLiteral('null')).to.throw(
'Int cannot represent non-integer value: null',
);
expect(() => parseLiteral('""')).to.throw(
'Int cannot represent non-integer value: ""',
);
expect(() => parseLiteral('"123"')).to.throw(
'Int cannot represent non-integer value: "123"',
);
expect(() => parseLiteral('false')).to.throw(
'Int cannot represent non-integer value: false',
);
expect(() => parseLiteral('[1]')).to.throw(
'Int cannot represent non-integer value: [1]',
);
expect(() => parseLiteral('{ value: 1 }')).to.throw(
'Int cannot represent non-integer value: {value: 1}',
);
expect(() => parseLiteral('ENUM_VALUE')).to.throw(
'Int cannot represent non-integer value: ENUM_VALUE',
);
expect(() => parseLiteral('$var')).to.throw(
'Int cannot represent non-integer value: $var',
);
});
});

Expand Down Expand Up @@ -149,15 +171,33 @@ describe('Type System: Specified scalar types', () => {
expect(parseLiteral('0.1')).to.equal(0.1);
expect(parseLiteral(Math.PI.toString())).to.equal(Math.PI);

expect(parseLiteral('null')).to.equal(undefined);
expect(parseLiteral('""')).to.equal(undefined);
expect(parseLiteral('"123"')).to.equal(undefined);
expect(parseLiteral('"123.5"')).to.equal(undefined);
expect(parseLiteral('false')).to.equal(undefined);
expect(parseLiteral('[0.1]')).to.equal(undefined);
expect(parseLiteral('{ value: 0.1 }')).to.equal(undefined);
expect(parseLiteral('ENUM_VALUE')).to.equal(undefined);
expect(parseLiteral('$var')).to.equal(undefined);
expect(() => parseLiteral('null')).to.throw(
'Float cannot represent non numeric value: null',
);
expect(() => parseLiteral('""')).to.throw(
'Float cannot represent non numeric value: ""',
);
expect(() => parseLiteral('"123"')).to.throw(
'Float cannot represent non numeric value: "123"',
);
expect(() => parseLiteral('"123.5"')).to.throw(
'Float cannot represent non numeric value: "123.5"',
);
expect(() => parseLiteral('false')).to.throw(
'Float cannot represent non numeric value: false',
);
expect(() => parseLiteral('[0.1]')).to.throw(
'Float cannot represent non numeric value: [0.1]',
);
expect(() => parseLiteral('{ value: 0.1 }')).to.throw(
'Float cannot represent non numeric value: {value: 0.1}',
);
expect(() => parseLiteral('ENUM_VALUE')).to.throw(
'Float cannot represent non numeric value: ENUM_VALUE',
);
expect(() => parseLiteral('$var')).to.throw(
'Float cannot represent non numeric value: $var',
);
});
});

Expand Down Expand Up @@ -200,14 +240,30 @@ describe('Type System: Specified scalar types', () => {
expect(parseLiteral('"foo"')).to.equal('foo');
expect(parseLiteral('"""bar"""')).to.equal('bar');

expect(parseLiteral('null')).to.equal(undefined);
expect(parseLiteral('1')).to.equal(undefined);
expect(parseLiteral('0.1')).to.equal(undefined);
expect(parseLiteral('false')).to.equal(undefined);
expect(parseLiteral('["foo"]')).to.equal(undefined);
expect(parseLiteral('{ value: "foo" }')).to.equal(undefined);
expect(parseLiteral('ENUM_VALUE')).to.equal(undefined);
expect(parseLiteral('$var')).to.equal(undefined);
expect(() => parseLiteral('null')).to.throw(
'String cannot represent a non string value: null',
);
expect(() => parseLiteral('1')).to.throw(
'String cannot represent a non string value: 1',
);
expect(() => parseLiteral('0.1')).to.throw(
'String cannot represent a non string value: 0.1',
);
expect(() => parseLiteral('false')).to.throw(
'String cannot represent a non string value: false',
);
expect(() => parseLiteral('["foo"]')).to.throw(
'String cannot represent a non string value: ["foo"]',
);
expect(() => parseLiteral('{ value: "foo" }')).to.throw(
'String cannot represent a non string value: {value: "foo"}',
);
expect(() => parseLiteral('ENUM_VALUE')).to.throw(
'String cannot represent a non string value: ENUM_VALUE',
);
expect(() => parseLiteral('$var')).to.throw(
'String cannot represent a non string value: $var',
);
});
});

Expand Down Expand Up @@ -257,16 +313,36 @@ describe('Type System: Specified scalar types', () => {
expect(parseLiteral('true')).to.equal(true);
expect(parseLiteral('false')).to.equal(false);

expect(parseLiteral('null')).to.equal(undefined);
expect(parseLiteral('0')).to.equal(undefined);
expect(parseLiteral('1')).to.equal(undefined);
expect(parseLiteral('0.1')).to.equal(undefined);
expect(parseLiteral('""')).to.equal(undefined);
expect(parseLiteral('"false"')).to.equal(undefined);
expect(parseLiteral('[false]')).to.equal(undefined);
expect(parseLiteral('{ value: false }')).to.equal(undefined);
expect(parseLiteral('ENUM_VALUE')).to.equal(undefined);
expect(parseLiteral('$var')).to.equal(undefined);
expect(() => parseLiteral('null')).to.throw(
'Boolean cannot represent a non boolean value: null',
);
expect(() => parseLiteral('0')).to.throw(
'Boolean cannot represent a non boolean value: 0',
);
expect(() => parseLiteral('1')).to.throw(
'Boolean cannot represent a non boolean value: 1',
);
expect(() => parseLiteral('0.1')).to.throw(
'Boolean cannot represent a non boolean value: 0.1',
);
expect(() => parseLiteral('""')).to.throw(
'Boolean cannot represent a non boolean value: ""',
);
expect(() => parseLiteral('"false"')).to.throw(
'Boolean cannot represent a non boolean value: "false"',
);
expect(() => parseLiteral('[false]')).to.throw(
'Boolean cannot represent a non boolean value: [false]',
);
expect(() => parseLiteral('{ value: false }')).to.throw(
'Boolean cannot represent a non boolean value: {value: false}',
);
expect(() => parseLiteral('ENUM_VALUE')).to.throw(
'Boolean cannot represent a non boolean value: ENUM_VALUE',
);
expect(() => parseLiteral('$var')).to.throw(
'Boolean cannot represent a non boolean value: $var',
);
});
});

Expand Down Expand Up @@ -326,13 +402,27 @@ describe('Type System: Specified scalar types', () => {
expect(parseLiteral('90071992547409910')).to.equal('90071992547409910');
expect(parseLiteral('-90071992547409910')).to.equal('-90071992547409910');

expect(parseLiteral('null')).to.equal(undefined);
expect(parseLiteral('0.1')).to.equal(undefined);
expect(parseLiteral('false')).to.equal(undefined);
expect(parseLiteral('["1"]')).to.equal(undefined);
expect(parseLiteral('{ value: "1" }')).to.equal(undefined);
expect(parseLiteral('ENUM_VALUE')).to.equal(undefined);
expect(parseLiteral('$var')).to.equal(undefined);
expect(() => parseLiteral('null')).to.throw(
'ID cannot represent a non-string and non-integer value: null',
);
expect(() => parseLiteral('0.1')).to.throw(
'ID cannot represent a non-string and non-integer value: 0.1',
);
expect(() => parseLiteral('false')).to.throw(
'ID cannot represent a non-string and non-integer value: false',
);
expect(() => parseLiteral('["1"]')).to.throw(
'ID cannot represent a non-string and non-integer value: ["1"]',
);
expect(() => parseLiteral('{ value: "1" }')).to.throw(
'ID cannot represent a non-string and non-integer value: {value: "1"}',
);
expect(() => parseLiteral('ENUM_VALUE')).to.throw(
'ID cannot represent a non-string and non-integer value: ENUM_VALUE',
);
expect(() => parseLiteral('$var')).to.throw(
'ID cannot represent a non-string and non-integer value: $var',
);
});
});
});
5 changes: 5 additions & 0 deletions src/type/__tests__/serialization-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ describe('Type System: Scalar coercion', () => {
expect(() => GraphQLString.serialize(badObjValue)).to.throw(
'String cannot represent value: {}',
);

const badValueOfObjValue = { valueOf: 'valueOf string' };
expect(() => GraphQLString.serialize(badValueOfObjValue)).to.throw(
'String cannot represent value: { valueOf: "valueOf string" }',
);
});

it('serializes output as Boolean', () => {
Expand Down
50 changes: 36 additions & 14 deletions src/type/scalars.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import inspect from '../jsutils/inspect';
import isObjectLike from '../jsutils/isObjectLike';

import { Kind } from '../language/kinds';
import { print } from '../language/printer';

import { GraphQLScalarType, isScalarType } from './definition';

Expand Down Expand Up @@ -62,13 +63,18 @@ export const GraphQLInt = new GraphQLScalarType({
serialize: serializeInt,
parseValue: coerceInt,
parseLiteral(ast) {
if (ast.kind === Kind.INT) {
const num = parseInt(ast.value, 10);
if (num <= MAX_INT && num >= MIN_INT) {
return num;
}
if (ast.kind !== Kind.INT) {
throw new TypeError(
'Int cannot represent non-integer value: ' + print(ast),
);
}
const num = parseInt(ast.value, 10);
if (num > MAX_INT || num < MIN_INT) {
throw new TypeError(
'Int cannot represent non 32-bit signed integer value: ' + ast.value,
);
}
return undefined;
return num;
},
});

Expand Down Expand Up @@ -105,9 +111,12 @@ export const GraphQLFloat = new GraphQLScalarType({
serialize: serializeFloat,
parseValue: coerceFloat,
parseLiteral(ast) {
return ast.kind === Kind.FLOAT || ast.kind === Kind.INT
? parseFloat(ast.value)
: undefined;
if (ast.kind !== Kind.FLOAT && ast.kind !== Kind.INT) {
throw new TypeError(
'Float cannot represent non numeric value: ' + print(ast),
);
}
return parseFloat(ast.value);
},
});

Expand Down Expand Up @@ -163,7 +172,12 @@ export const GraphQLString = new GraphQLScalarType({
serialize: serializeString,
parseValue: coerceString,
parseLiteral(ast) {
return ast.kind === Kind.STRING ? ast.value : undefined;
if (ast.kind !== Kind.STRING) {
throw new TypeError(
'String cannot represent a non string value: ' + print(ast),
);
}
return ast.value;
},
});

Expand Down Expand Up @@ -194,7 +208,12 @@ export const GraphQLBoolean = new GraphQLScalarType({
serialize: serializeBoolean,
parseValue: coerceBoolean,
parseLiteral(ast) {
return ast.kind === Kind.BOOLEAN ? ast.value : undefined;
if (ast.kind !== Kind.BOOLEAN) {
throw new TypeError(
'Boolean cannot represent a non boolean value: ' + print(ast),
);
}
return ast.value;
},
});

Expand Down Expand Up @@ -227,9 +246,12 @@ export const GraphQLID = new GraphQLScalarType({
serialize: serializeID,
parseValue: coerceID,
parseLiteral(ast) {
return ast.kind === Kind.STRING || ast.kind === Kind.INT
? ast.value
: undefined;
if (ast.kind !== Kind.STRING && ast.kind !== Kind.INT) {
throw new TypeError(
'ID cannot represent a non-string and non-integer value: ' + print(ast),
);
}
return ast.value;
},
});

Expand Down
Loading

0 comments on commit dd3b265

Please sign in to comment.