graphql 14.0.2 → 14.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/error/GraphQLError.js +1 -1
- package/error/GraphQLError.js.flow +3 -3
- package/error/GraphQLError.mjs +1 -1
- package/error/formatError.js +1 -1
- package/error/formatError.mjs +1 -1
- package/error/index.mjs +1 -1
- package/error/locatedError.js +1 -1
- package/error/locatedError.mjs +1 -1
- package/error/printError.js +1 -1
- package/error/printError.mjs +1 -1
- package/error/syntaxError.js +1 -1
- package/error/syntaxError.mjs +1 -1
- package/execution/execute.mjs +1 -1
- package/execution/index.mjs +1 -1
- package/execution/values.js +3 -3
- package/execution/values.js.flow +1 -1
- package/execution/values.mjs +2 -2
- package/graphql.js +1 -1
- package/graphql.mjs +1 -1
- package/index.js +12 -0
- package/index.js.flow +2 -0
- package/index.mjs +2 -2
- package/jsutils/dedent.js +1 -1
- package/jsutils/dedent.mjs +1 -1
- package/jsutils/defineToJSON.js +17 -6
- package/jsutils/defineToJSON.js.flow +14 -5
- package/jsutils/defineToJSON.mjs +14 -6
- package/jsutils/defineToStringTag.js +5 -5
- package/jsutils/defineToStringTag.js.flow +3 -3
- package/jsutils/defineToStringTag.mjs +4 -4
- package/jsutils/inspect.js +22 -11
- package/jsutils/inspect.js.flow +22 -2
- package/jsutils/inspect.mjs +21 -4
- package/jsutils/instanceOf.js +1 -1
- package/jsutils/instanceOf.mjs +1 -1
- package/jsutils/invariant.js +1 -1
- package/jsutils/invariant.mjs +1 -1
- package/jsutils/isInvalid.js +1 -1
- package/jsutils/isInvalid.mjs +1 -1
- package/jsutils/isNullish.js +1 -1
- package/jsutils/isNullish.mjs +1 -1
- package/jsutils/isPromise.js +1 -1
- package/jsutils/isPromise.mjs +1 -1
- package/jsutils/keyMap.js +1 -1
- package/jsutils/keyMap.mjs +1 -1
- package/jsutils/keyValMap.js +1 -1
- package/jsutils/keyValMap.mjs +1 -1
- package/jsutils/mapValue.js +54 -0
- package/jsutils/mapValue.js.flow +27 -0
- package/jsutils/mapValue.mjs +44 -0
- package/jsutils/memoize3.js +1 -1
- package/jsutils/memoize3.mjs +1 -1
- package/jsutils/nodejsCustomInspectSymbol.js +18 -0
- package/jsutils/nodejsCustomInspectSymbol.js.flow +15 -0
- package/jsutils/nodejsCustomInspectSymbol.mjs +10 -0
- package/jsutils/orList.js +17 -4
- package/jsutils/orList.js.flow +13 -7
- package/jsutils/orList.mjs +14 -4
- package/jsutils/promiseForObject.js +1 -1
- package/jsutils/promiseForObject.mjs +1 -1
- package/jsutils/promiseReduce.js +1 -1
- package/jsutils/promiseReduce.mjs +1 -1
- package/jsutils/quotedOrList.js +1 -1
- package/jsutils/quotedOrList.mjs +1 -1
- package/jsutils/suggestionList.js +1 -1
- package/jsutils/suggestionList.mjs +1 -1
- package/language/blockStringValue.js +1 -1
- package/language/blockStringValue.mjs +1 -1
- package/language/directiveLocation.js +1 -1
- package/language/directiveLocation.mjs +1 -1
- package/language/index.mjs +1 -1
- package/language/kinds.js +1 -1
- package/language/kinds.mjs +1 -1
- package/language/lexer.js +28 -12
- package/language/lexer.js.flow +33 -19
- package/language/lexer.mjs +27 -12
- package/language/location.js +1 -1
- package/language/location.mjs +1 -1
- package/language/parser.js +31 -38
- package/language/parser.js.flow +32 -48
- package/language/parser.mjs +30 -38
- package/language/predicates.js +1 -1
- package/language/predicates.mjs +1 -1
- package/language/printer.js +13 -7
- package/language/printer.js.flow +19 -9
- package/language/printer.mjs +13 -7
- package/language/source.js +8 -7
- package/language/source.mjs +1 -9
- package/language/visitor.js +6 -5
- package/language/visitor.js.flow +2 -4
- package/language/visitor.mjs +6 -5
- package/package.json +5 -2
- package/polyfills/find.js +31 -0
- package/polyfills/find.js.flow +29 -0
- package/polyfills/find.mjs +23 -0
- package/{jsutils → polyfills}/isFinite.js +1 -1
- package/{jsutils → polyfills}/isFinite.js.flow +0 -0
- package/{jsutils → polyfills}/isFinite.mjs +1 -1
- package/{jsutils → polyfills}/isInteger.js +1 -1
- package/{jsutils → polyfills}/isInteger.js.flow +0 -0
- package/{jsutils → polyfills}/isInteger.mjs +1 -1
- package/polyfills/objectEntries.js +26 -0
- package/polyfills/objectEntries.js.flow +19 -0
- package/polyfills/objectEntries.mjs +18 -0
- package/{jsutils → polyfills}/objectValues.js +1 -1
- package/{jsutils → polyfills}/objectValues.js.flow +1 -1
- package/{jsutils → polyfills}/objectValues.mjs +1 -1
- package/subscription/asyncIteratorReject.mjs +1 -1
- package/subscription/index.mjs +1 -1
- package/subscription/mapAsyncIterator.mjs +1 -1
- package/subscription/subscribe.js +1 -1
- package/subscription/subscribe.mjs +1 -1
- package/type/definition.js +31 -130
- package/type/definition.js.flow +35 -47
- package/type/definition.mjs +30 -131
- package/type/directives.js +25 -29
- package/type/directives.js.flow +24 -20
- package/type/directives.mjs +22 -30
- package/type/index.js +12 -0
- package/type/index.js.flow +4 -0
- package/type/index.mjs +5 -3
- package/type/introspection.js +3 -3
- package/type/introspection.js.flow +1 -1
- package/type/introspection.mjs +2 -2
- package/type/scalars.js +45 -34
- package/type/scalars.js.flow +40 -26
- package/type/scalars.mjs +44 -26
- package/type/schema.js +82 -87
- package/type/schema.js.flow +17 -9
- package/type/schema.mjs +79 -86
- package/type/validate.js +168 -175
- package/type/validate.js.flow +8 -49
- package/type/validate.mjs +159 -175
- package/utilities/TypeInfo.js +10 -23
- package/utilities/TypeInfo.js.flow +1 -1
- package/utilities/TypeInfo.mjs +2 -24
- package/utilities/assertValidName.js +1 -1
- package/utilities/assertValidName.mjs +1 -1
- package/utilities/astFromValue.js +2 -2
- package/utilities/astFromValue.js.flow +1 -1
- package/utilities/astFromValue.mjs +2 -2
- package/utilities/buildASTSchema.js +53 -53
- package/utilities/buildASTSchema.js.flow +14 -30
- package/utilities/buildASTSchema.mjs +45 -55
- package/utilities/buildClientSchema.js +3 -3
- package/utilities/buildClientSchema.js.flow +6 -2
- package/utilities/buildClientSchema.mjs +3 -3
- package/utilities/coerceValue.js +38 -19
- package/utilities/coerceValue.js.flow +41 -47
- package/utilities/coerceValue.mjs +38 -20
- package/utilities/concatAST.js +1 -1
- package/utilities/concatAST.mjs +1 -1
- package/utilities/extendSchema.js +228 -312
- package/utilities/extendSchema.js.flow +27 -152
- package/utilities/extendSchema.mjs +229 -312
- package/utilities/findBreakingChanges.js +7 -5
- package/utilities/findBreakingChanges.js.flow +3 -2
- package/utilities/findBreakingChanges.mjs +6 -5
- package/utilities/findDeprecatedUsages.js +1 -1
- package/utilities/findDeprecatedUsages.mjs +1 -1
- package/utilities/getOperationAST.js +1 -1
- package/utilities/getOperationAST.mjs +1 -1
- package/utilities/getOperationRootType.js +1 -1
- package/utilities/getOperationRootType.mjs +1 -1
- package/utilities/index.mjs +1 -1
- package/utilities/introspectionFromSchema.js +1 -1
- package/utilities/introspectionFromSchema.mjs +1 -1
- package/utilities/introspectionQuery.js +1 -1
- package/utilities/introspectionQuery.mjs +1 -1
- package/utilities/isValidJSValue.js +1 -1
- package/utilities/isValidJSValue.mjs +1 -1
- package/utilities/isValidLiteralValue.js +1 -1
- package/utilities/isValidLiteralValue.mjs +1 -1
- package/utilities/lexicographicSortSchema.js +2 -2
- package/utilities/lexicographicSortSchema.js.flow +1 -1
- package/utilities/lexicographicSortSchema.mjs +2 -2
- package/utilities/schemaPrinter.js +3 -3
- package/utilities/schemaPrinter.js.flow +1 -1
- package/utilities/schemaPrinter.mjs +2 -2
- package/utilities/separateOperations.js +1 -1
- package/utilities/separateOperations.mjs +1 -1
- package/utilities/typeComparators.js +1 -1
- package/utilities/typeComparators.mjs +1 -1
- package/utilities/typeFromAST.js +1 -1
- package/utilities/typeFromAST.mjs +1 -1
- package/utilities/valueFromAST.js +3 -3
- package/utilities/valueFromAST.js.flow +1 -1
- package/utilities/valueFromAST.mjs +2 -2
- package/utilities/valueFromASTUntyped.js +1 -1
- package/utilities/valueFromASTUntyped.mjs +1 -1
- package/validation/ValidationContext.js +57 -82
- package/validation/ValidationContext.js.flow +52 -49
- package/validation/ValidationContext.mjs +52 -77
- package/validation/index.mjs +1 -1
- package/validation/rules/ExecutableDefinitions.js +1 -1
- package/validation/rules/ExecutableDefinitions.js.flow +1 -1
- package/validation/rules/ExecutableDefinitions.mjs +1 -1
- package/validation/rules/FieldsOnCorrectType.js +1 -1
- package/validation/rules/FieldsOnCorrectType.mjs +1 -1
- package/validation/rules/FragmentsOnCompositeTypes.js +1 -1
- package/validation/rules/FragmentsOnCompositeTypes.mjs +1 -1
- package/validation/rules/KnownArgumentNames.mjs +1 -1
- package/validation/rules/KnownDirectives.js +1 -1
- package/validation/rules/KnownDirectives.mjs +1 -1
- package/validation/rules/KnownFragmentNames.js +1 -1
- package/validation/rules/KnownFragmentNames.mjs +1 -1
- package/validation/rules/KnownTypeNames.js +59 -21
- package/validation/rules/KnownTypeNames.js.flow +54 -20
- package/validation/rules/KnownTypeNames.mjs +56 -21
- package/validation/rules/LoneAnonymousOperation.js +1 -1
- package/validation/rules/LoneAnonymousOperation.mjs +1 -1
- package/validation/rules/LoneSchemaDefinition.js +1 -1
- package/validation/rules/LoneSchemaDefinition.mjs +1 -1
- package/validation/rules/NoFragmentCycles.js +1 -1
- package/validation/rules/NoFragmentCycles.js.flow +2 -2
- package/validation/rules/NoFragmentCycles.mjs +1 -1
- package/validation/rules/NoUndefinedVariables.js +1 -1
- package/validation/rules/NoUndefinedVariables.mjs +1 -1
- package/validation/rules/NoUnusedFragments.js +1 -1
- package/validation/rules/NoUnusedFragments.js.flow +2 -2
- package/validation/rules/NoUnusedFragments.mjs +1 -1
- package/validation/rules/NoUnusedVariables.js +1 -1
- package/validation/rules/NoUnusedVariables.mjs +1 -1
- package/validation/rules/OverlappingFieldsCanBeMerged.js +56 -32
- package/validation/rules/OverlappingFieldsCanBeMerged.js.flow +3 -3
- package/validation/rules/OverlappingFieldsCanBeMerged.mjs +47 -32
- package/validation/rules/PossibleFragmentSpreads.js +1 -1
- package/validation/rules/PossibleFragmentSpreads.mjs +1 -1
- package/validation/rules/PossibleTypeExtensions.js +158 -0
- package/validation/rules/PossibleTypeExtensions.js.flow +160 -0
- package/validation/rules/PossibleTypeExtensions.mjs +146 -0
- package/validation/rules/ProvidedRequiredArguments.mjs +1 -1
- package/validation/rules/ScalarLeafs.js +1 -1
- package/validation/rules/ScalarLeafs.mjs +1 -1
- package/validation/rules/SingleFieldSubscriptions.js +1 -1
- package/validation/rules/SingleFieldSubscriptions.mjs +1 -1
- package/validation/rules/UniqueArgumentNames.js +1 -1
- package/validation/rules/UniqueArgumentNames.mjs +1 -1
- package/validation/rules/UniqueDirectiveNames.js +55 -0
- package/validation/rules/UniqueDirectiveNames.js.flow +64 -0
- package/validation/rules/UniqueDirectiveNames.mjs +43 -0
- package/validation/rules/UniqueDirectivesPerLocation.js +1 -1
- package/validation/rules/UniqueDirectivesPerLocation.mjs +1 -1
- package/validation/rules/UniqueEnumValueNames.js +94 -0
- package/validation/rules/UniqueEnumValueNames.js.flow +87 -0
- package/validation/rules/UniqueEnumValueNames.mjs +81 -0
- package/validation/rules/UniqueFieldDefinitionNames.js +105 -0
- package/validation/rules/UniqueFieldDefinitionNames.js.flow +101 -0
- package/validation/rules/UniqueFieldDefinitionNames.mjs +92 -0
- package/validation/rules/UniqueFragmentNames.js +1 -1
- package/validation/rules/UniqueFragmentNames.mjs +1 -1
- package/validation/rules/UniqueInputFieldNames.js +1 -1
- package/validation/rules/UniqueInputFieldNames.mjs +1 -1
- package/validation/rules/UniqueOperationNames.js +1 -1
- package/validation/rules/UniqueOperationNames.mjs +1 -1
- package/validation/rules/UniqueOperationTypes.js +85 -0
- package/validation/rules/UniqueOperationTypes.js.flow +76 -0
- package/validation/rules/UniqueOperationTypes.mjs +73 -0
- package/validation/rules/UniqueTypeNames.js +62 -0
- package/validation/rules/UniqueTypeNames.js.flow +67 -0
- package/validation/rules/UniqueTypeNames.mjs +50 -0
- package/validation/rules/UniqueVariableNames.js +1 -1
- package/validation/rules/UniqueVariableNames.mjs +1 -1
- package/validation/rules/ValuesOfCorrectType.js +29 -13
- package/validation/rules/ValuesOfCorrectType.js.flow +4 -5
- package/validation/rules/ValuesOfCorrectType.mjs +28 -13
- package/validation/rules/VariablesAreInputTypes.js +1 -1
- package/validation/rules/VariablesAreInputTypes.mjs +1 -1
- package/validation/rules/VariablesInAllowedPosition.js +4 -4
- package/validation/rules/VariablesInAllowedPosition.mjs +4 -4
- package/validation/specifiedRules.js +14 -2
- package/validation/specifiedRules.js.flow +13 -0
- package/validation/specifiedRules.mjs +8 -2
- package/validation/validate.js +1 -1
- package/validation/validate.mjs +1 -1
- package/jsutils/find.js +0 -22
- package/jsutils/find.js.flow +0 -19
- package/jsutils/find.mjs +0 -15
package/language/lexer.js
CHANGED
|
@@ -7,6 +7,8 @@ exports.createLexer = createLexer;
|
|
|
7
7
|
exports.getTokenDesc = getTokenDesc;
|
|
8
8
|
exports.TokenKind = void 0;
|
|
9
9
|
|
|
10
|
+
var _defineToJSON = _interopRequireDefault(require("../jsutils/defineToJSON"));
|
|
11
|
+
|
|
10
12
|
var _error = require("../error");
|
|
11
13
|
|
|
12
14
|
var _blockStringValue = _interopRequireDefault(require("./blockStringValue"));
|
|
@@ -19,7 +21,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
19
21
|
* This source code is licensed under the MIT license found in the
|
|
20
22
|
* LICENSE file in the root directory of this source tree.
|
|
21
23
|
*
|
|
22
|
-
*
|
|
24
|
+
*
|
|
23
25
|
*/
|
|
24
26
|
|
|
25
27
|
/**
|
|
@@ -128,14 +130,14 @@ function Tok(kind, start, end, line, column, prev, value) {
|
|
|
128
130
|
} // Print a simplified form when appearing in JSON/util.inspect.
|
|
129
131
|
|
|
130
132
|
|
|
131
|
-
|
|
133
|
+
(0, _defineToJSON.default)(Tok, function () {
|
|
132
134
|
return {
|
|
133
135
|
kind: this.kind,
|
|
134
136
|
value: this.value,
|
|
135
137
|
line: this.line,
|
|
136
138
|
column: this.column
|
|
137
139
|
};
|
|
138
|
-
};
|
|
140
|
+
});
|
|
139
141
|
|
|
140
142
|
function printCharCode(code) {
|
|
141
143
|
return (// NaN/undefined represents access beyond the end of the file.
|
|
@@ -147,9 +149,9 @@ function printCharCode(code) {
|
|
|
147
149
|
/**
|
|
148
150
|
* Gets the next token from the source starting at the given position.
|
|
149
151
|
*
|
|
150
|
-
* This skips over whitespace
|
|
151
|
-
*
|
|
152
|
-
*
|
|
152
|
+
* This skips over whitespace until it finds the next lexable token, then lexes
|
|
153
|
+
* punctuators immediately or calls the appropriate helper function for more
|
|
154
|
+
* complicated tokens.
|
|
153
155
|
*/
|
|
154
156
|
|
|
155
157
|
|
|
@@ -305,7 +307,7 @@ function readToken(lexer, prev) {
|
|
|
305
307
|
|
|
306
308
|
case 34:
|
|
307
309
|
if (charCodeAt.call(body, pos + 1) === 34 && charCodeAt.call(body, pos + 2) === 34) {
|
|
308
|
-
return readBlockString(source, pos, line, col, prev);
|
|
310
|
+
return readBlockString(source, pos, line, col, prev, lexer);
|
|
309
311
|
}
|
|
310
312
|
|
|
311
313
|
return readString(source, pos, line, col, prev);
|
|
@@ -332,8 +334,7 @@ function unexpectedCharacterMessage(code) {
|
|
|
332
334
|
}
|
|
333
335
|
/**
|
|
334
336
|
* Reads from body starting at startPosition until it finds a non-whitespace
|
|
335
|
-
*
|
|
336
|
-
* lexing.
|
|
337
|
+
* character, then returns the position of that character for lexing.
|
|
337
338
|
*/
|
|
338
339
|
|
|
339
340
|
|
|
@@ -561,7 +562,7 @@ function readString(source, start, line, col, prev) {
|
|
|
561
562
|
*/
|
|
562
563
|
|
|
563
564
|
|
|
564
|
-
function readBlockString(source, start, line, col, prev) {
|
|
565
|
+
function readBlockString(source, start, line, col, prev, lexer) {
|
|
565
566
|
var body = source.body;
|
|
566
567
|
var position = start + 3;
|
|
567
568
|
var chunkStart = position;
|
|
@@ -578,10 +579,25 @@ function readBlockString(source, start, line, col, prev) {
|
|
|
578
579
|
|
|
579
580
|
if (code < 0x0020 && code !== 0x0009 && code !== 0x000a && code !== 0x000d) {
|
|
580
581
|
throw (0, _error.syntaxError)(source, position, "Invalid character within String: ".concat(printCharCode(code), "."));
|
|
581
|
-
}
|
|
582
|
+
}
|
|
582
583
|
|
|
584
|
+
if (code === 10) {
|
|
585
|
+
// new line
|
|
586
|
+
++position;
|
|
587
|
+
++lexer.line;
|
|
588
|
+
lexer.lineStart = position;
|
|
589
|
+
} else if (code === 13) {
|
|
590
|
+
// carriage return
|
|
591
|
+
if (charCodeAt.call(body, position + 1) === 10) {
|
|
592
|
+
position += 2;
|
|
593
|
+
} else {
|
|
594
|
+
++position;
|
|
595
|
+
}
|
|
583
596
|
|
|
584
|
-
|
|
597
|
+
++lexer.line;
|
|
598
|
+
lexer.lineStart = position;
|
|
599
|
+
} else if ( // Escape Triple-Quote (\""")
|
|
600
|
+
code === 92 && charCodeAt.call(body, position + 1) === 34 && charCodeAt.call(body, position + 2) === 34 && charCodeAt.call(body, position + 3) === 34) {
|
|
585
601
|
rawValue += slice.call(body, chunkStart, position) + '"""';
|
|
586
602
|
position += 4;
|
|
587
603
|
chunkStart = position;
|
package/language/lexer.js.flow
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* @flow strict
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import defineToJSON from '../jsutils/defineToJSON';
|
|
10
11
|
import type { Token } from './ast';
|
|
11
12
|
import type { Source } from './source';
|
|
12
13
|
import { syntaxError } from '../error';
|
|
@@ -162,14 +163,14 @@ function Tok(
|
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
// Print a simplified form when appearing in JSON/util.inspect.
|
|
165
|
-
Tok
|
|
166
|
+
defineToJSON(Tok, function() {
|
|
166
167
|
return {
|
|
167
168
|
kind: this.kind,
|
|
168
169
|
value: this.value,
|
|
169
170
|
line: this.line,
|
|
170
171
|
column: this.column,
|
|
171
172
|
};
|
|
172
|
-
};
|
|
173
|
+
});
|
|
173
174
|
|
|
174
175
|
function printCharCode(code) {
|
|
175
176
|
return (
|
|
@@ -177,19 +178,19 @@ function printCharCode(code) {
|
|
|
177
178
|
isNaN(code)
|
|
178
179
|
? TokenKind.EOF
|
|
179
180
|
: // Trust JSON for ASCII.
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
181
|
+
code < 0x007f
|
|
182
|
+
? JSON.stringify(String.fromCharCode(code))
|
|
183
|
+
: // Otherwise print the escaped form.
|
|
184
|
+
`"\\u${('00' + code.toString(16).toUpperCase()).slice(-4)}"`
|
|
184
185
|
);
|
|
185
186
|
}
|
|
186
187
|
|
|
187
188
|
/**
|
|
188
189
|
* Gets the next token from the source starting at the given position.
|
|
189
190
|
*
|
|
190
|
-
* This skips over whitespace
|
|
191
|
-
*
|
|
192
|
-
*
|
|
191
|
+
* This skips over whitespace until it finds the next lexable token, then lexes
|
|
192
|
+
* punctuators immediately or calls the appropriate helper function for more
|
|
193
|
+
* complicated tokens.
|
|
193
194
|
*/
|
|
194
195
|
function readToken(lexer: Lexer<*>, prev: Token): Token {
|
|
195
196
|
const source = lexer.source;
|
|
@@ -333,7 +334,7 @@ function readToken(lexer: Lexer<*>, prev: Token): Token {
|
|
|
333
334
|
charCodeAt.call(body, pos + 1) === 34 &&
|
|
334
335
|
charCodeAt.call(body, pos + 2) === 34
|
|
335
336
|
) {
|
|
336
|
-
return readBlockString(source, pos, line, col, prev);
|
|
337
|
+
return readBlockString(source, pos, line, col, prev, lexer);
|
|
337
338
|
}
|
|
338
339
|
return readString(source, pos, line, col, prev);
|
|
339
340
|
}
|
|
@@ -362,8 +363,7 @@ function unexpectedCharacterMessage(code) {
|
|
|
362
363
|
|
|
363
364
|
/**
|
|
364
365
|
* Reads from body starting at startPosition until it finds a non-whitespace
|
|
365
|
-
*
|
|
366
|
-
* lexing.
|
|
366
|
+
* character, then returns the position of that character for lexing.
|
|
367
367
|
*/
|
|
368
368
|
function positionAfterWhitespace(
|
|
369
369
|
body: string,
|
|
@@ -625,7 +625,7 @@ function readString(source, start, line, col, prev): Token {
|
|
|
625
625
|
*
|
|
626
626
|
* """("?"?(\\"""|\\(?!=""")|[^"\\]))*"""
|
|
627
627
|
*/
|
|
628
|
-
function readBlockString(source, start, line, col, prev): Token {
|
|
628
|
+
function readBlockString(source, start, line, col, prev, lexer): Token {
|
|
629
629
|
const body = source.body;
|
|
630
630
|
let position = start + 3;
|
|
631
631
|
let chunkStart = position;
|
|
@@ -668,8 +668,22 @@ function readBlockString(source, start, line, col, prev): Token {
|
|
|
668
668
|
);
|
|
669
669
|
}
|
|
670
670
|
|
|
671
|
-
|
|
672
|
-
|
|
671
|
+
if (code === 10) {
|
|
672
|
+
// new line
|
|
673
|
+
++position;
|
|
674
|
+
++lexer.line;
|
|
675
|
+
lexer.lineStart = position;
|
|
676
|
+
} else if (code === 13) {
|
|
677
|
+
// carriage return
|
|
678
|
+
if (charCodeAt.call(body, position + 1) === 10) {
|
|
679
|
+
position += 2;
|
|
680
|
+
} else {
|
|
681
|
+
++position;
|
|
682
|
+
}
|
|
683
|
+
++lexer.line;
|
|
684
|
+
lexer.lineStart = position;
|
|
685
|
+
} else if (
|
|
686
|
+
// Escape Triple-Quote (\""")
|
|
673
687
|
code === 92 &&
|
|
674
688
|
charCodeAt.call(body, position + 1) === 34 &&
|
|
675
689
|
charCodeAt.call(body, position + 2) === 34 &&
|
|
@@ -714,10 +728,10 @@ function char2hex(a) {
|
|
|
714
728
|
return a >= 48 && a <= 57
|
|
715
729
|
? a - 48 // 0-9
|
|
716
730
|
: a >= 65 && a <= 70
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
731
|
+
? a - 55 // A-F
|
|
732
|
+
: a >= 97 && a <= 102
|
|
733
|
+
? a - 87 // a-f
|
|
734
|
+
: -1;
|
|
721
735
|
}
|
|
722
736
|
|
|
723
737
|
/**
|
package/language/lexer.mjs
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
*
|
|
8
8
|
*/
|
|
9
|
+
import defineToJSON from '../jsutils/defineToJSON';
|
|
9
10
|
import { syntaxError } from '../error';
|
|
10
11
|
import blockStringValue from './blockStringValue';
|
|
11
12
|
/**
|
|
@@ -112,14 +113,14 @@ function Tok(kind, start, end, line, column, prev, value) {
|
|
|
112
113
|
} // Print a simplified form when appearing in JSON/util.inspect.
|
|
113
114
|
|
|
114
115
|
|
|
115
|
-
Tok
|
|
116
|
+
defineToJSON(Tok, function () {
|
|
116
117
|
return {
|
|
117
118
|
kind: this.kind,
|
|
118
119
|
value: this.value,
|
|
119
120
|
line: this.line,
|
|
120
121
|
column: this.column
|
|
121
122
|
};
|
|
122
|
-
};
|
|
123
|
+
});
|
|
123
124
|
|
|
124
125
|
function printCharCode(code) {
|
|
125
126
|
return (// NaN/undefined represents access beyond the end of the file.
|
|
@@ -131,9 +132,9 @@ function printCharCode(code) {
|
|
|
131
132
|
/**
|
|
132
133
|
* Gets the next token from the source starting at the given position.
|
|
133
134
|
*
|
|
134
|
-
* This skips over whitespace
|
|
135
|
-
*
|
|
136
|
-
*
|
|
135
|
+
* This skips over whitespace until it finds the next lexable token, then lexes
|
|
136
|
+
* punctuators immediately or calls the appropriate helper function for more
|
|
137
|
+
* complicated tokens.
|
|
137
138
|
*/
|
|
138
139
|
|
|
139
140
|
|
|
@@ -289,7 +290,7 @@ function readToken(lexer, prev) {
|
|
|
289
290
|
|
|
290
291
|
case 34:
|
|
291
292
|
if (charCodeAt.call(body, pos + 1) === 34 && charCodeAt.call(body, pos + 2) === 34) {
|
|
292
|
-
return readBlockString(source, pos, line, col, prev);
|
|
293
|
+
return readBlockString(source, pos, line, col, prev, lexer);
|
|
293
294
|
}
|
|
294
295
|
|
|
295
296
|
return readString(source, pos, line, col, prev);
|
|
@@ -316,8 +317,7 @@ function unexpectedCharacterMessage(code) {
|
|
|
316
317
|
}
|
|
317
318
|
/**
|
|
318
319
|
* Reads from body starting at startPosition until it finds a non-whitespace
|
|
319
|
-
*
|
|
320
|
-
* lexing.
|
|
320
|
+
* character, then returns the position of that character for lexing.
|
|
321
321
|
*/
|
|
322
322
|
|
|
323
323
|
|
|
@@ -545,7 +545,7 @@ function readString(source, start, line, col, prev) {
|
|
|
545
545
|
*/
|
|
546
546
|
|
|
547
547
|
|
|
548
|
-
function readBlockString(source, start, line, col, prev) {
|
|
548
|
+
function readBlockString(source, start, line, col, prev, lexer) {
|
|
549
549
|
var body = source.body;
|
|
550
550
|
var position = start + 3;
|
|
551
551
|
var chunkStart = position;
|
|
@@ -562,10 +562,25 @@ function readBlockString(source, start, line, col, prev) {
|
|
|
562
562
|
|
|
563
563
|
if (code < 0x0020 && code !== 0x0009 && code !== 0x000a && code !== 0x000d) {
|
|
564
564
|
throw syntaxError(source, position, "Invalid character within String: ".concat(printCharCode(code), "."));
|
|
565
|
-
}
|
|
565
|
+
}
|
|
566
566
|
|
|
567
|
+
if (code === 10) {
|
|
568
|
+
// new line
|
|
569
|
+
++position;
|
|
570
|
+
++lexer.line;
|
|
571
|
+
lexer.lineStart = position;
|
|
572
|
+
} else if (code === 13) {
|
|
573
|
+
// carriage return
|
|
574
|
+
if (charCodeAt.call(body, position + 1) === 10) {
|
|
575
|
+
position += 2;
|
|
576
|
+
} else {
|
|
577
|
+
++position;
|
|
578
|
+
}
|
|
567
579
|
|
|
568
|
-
|
|
580
|
+
++lexer.line;
|
|
581
|
+
lexer.lineStart = position;
|
|
582
|
+
} else if ( // Escape Triple-Quote (\""")
|
|
583
|
+
code === 92 && charCodeAt.call(body, position + 1) === 34 && charCodeAt.call(body, position + 2) === 34 && charCodeAt.call(body, position + 3) === 34) {
|
|
569
584
|
rawValue += slice.call(body, chunkStart, position) + '"""';
|
|
570
585
|
position += 4;
|
|
571
586
|
chunkStart = position;
|
package/language/location.js
CHANGED
package/language/location.mjs
CHANGED
package/language/parser.js
CHANGED
|
@@ -12,6 +12,8 @@ exports.parseNamedType = parseNamedType;
|
|
|
12
12
|
|
|
13
13
|
var _inspect = _interopRequireDefault(require("../jsutils/inspect"));
|
|
14
14
|
|
|
15
|
+
var _defineToJSON = _interopRequireDefault(require("../jsutils/defineToJSON"));
|
|
16
|
+
|
|
15
17
|
var _source = require("./source");
|
|
16
18
|
|
|
17
19
|
var _error = require("../error");
|
|
@@ -30,7 +32,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
30
32
|
* This source code is licensed under the MIT license found in the
|
|
31
33
|
* LICENSE file in the root directory of this source tree.
|
|
32
34
|
*
|
|
33
|
-
*
|
|
35
|
+
*
|
|
34
36
|
*/
|
|
35
37
|
|
|
36
38
|
/**
|
|
@@ -252,23 +254,12 @@ function parseVariableDefinitions(lexer) {
|
|
|
252
254
|
|
|
253
255
|
function parseVariableDefinition(lexer) {
|
|
254
256
|
var start = lexer.token;
|
|
255
|
-
|
|
256
|
-
if (lexer.options.experimentalVariableDefinitionDirectives) {
|
|
257
|
-
return {
|
|
258
|
-
kind: _kinds.Kind.VARIABLE_DEFINITION,
|
|
259
|
-
variable: parseVariable(lexer),
|
|
260
|
-
type: (expect(lexer, _lexer.TokenKind.COLON), parseTypeReference(lexer)),
|
|
261
|
-
defaultValue: skip(lexer, _lexer.TokenKind.EQUALS) ? parseValueLiteral(lexer, true) : undefined,
|
|
262
|
-
directives: parseDirectives(lexer, true),
|
|
263
|
-
loc: loc(lexer, start)
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
|
|
267
257
|
return {
|
|
268
258
|
kind: _kinds.Kind.VARIABLE_DEFINITION,
|
|
269
259
|
variable: parseVariable(lexer),
|
|
270
260
|
type: (expect(lexer, _lexer.TokenKind.COLON), parseTypeReference(lexer)),
|
|
271
261
|
defaultValue: skip(lexer, _lexer.TokenKind.EQUALS) ? parseValueLiteral(lexer, true) : undefined,
|
|
262
|
+
directives: parseDirectives(lexer, true),
|
|
272
263
|
loc: loc(lexer, start)
|
|
273
264
|
};
|
|
274
265
|
}
|
|
@@ -386,8 +377,9 @@ function parseConstArgument(lexer) {
|
|
|
386
377
|
function parseFragment(lexer) {
|
|
387
378
|
var start = lexer.token;
|
|
388
379
|
expect(lexer, _lexer.TokenKind.SPREAD);
|
|
380
|
+
var hasTypeCondition = skipKeyword(lexer, 'on');
|
|
389
381
|
|
|
390
|
-
if (peek(lexer, _lexer.TokenKind.NAME)
|
|
382
|
+
if (!hasTypeCondition && peek(lexer, _lexer.TokenKind.NAME)) {
|
|
391
383
|
return {
|
|
392
384
|
kind: _kinds.Kind.FRAGMENT_SPREAD,
|
|
393
385
|
name: parseFragmentName(lexer),
|
|
@@ -396,16 +388,9 @@ function parseFragment(lexer) {
|
|
|
396
388
|
};
|
|
397
389
|
}
|
|
398
390
|
|
|
399
|
-
var typeCondition;
|
|
400
|
-
|
|
401
|
-
if (lexer.token.value === 'on') {
|
|
402
|
-
lexer.advance();
|
|
403
|
-
typeCondition = parseNamedType(lexer);
|
|
404
|
-
}
|
|
405
|
-
|
|
406
391
|
return {
|
|
407
392
|
kind: _kinds.Kind.INLINE_FRAGMENT,
|
|
408
|
-
typeCondition:
|
|
393
|
+
typeCondition: hasTypeCondition ? parseNamedType(lexer) : undefined,
|
|
409
394
|
directives: parseDirectives(lexer, false),
|
|
410
395
|
selectionSet: parseSelectionSet(lexer),
|
|
411
396
|
loc: loc(lexer, start)
|
|
@@ -844,9 +829,8 @@ function parseObjectTypeDefinition(lexer) {
|
|
|
844
829
|
function parseImplementsInterfaces(lexer) {
|
|
845
830
|
var types = [];
|
|
846
831
|
|
|
847
|
-
if (lexer
|
|
848
|
-
|
|
849
|
-
|
|
832
|
+
if (skipKeyword(lexer, 'implements')) {
|
|
833
|
+
// Optional leading ampersand
|
|
850
834
|
skip(lexer, _lexer.TokenKind.AMP);
|
|
851
835
|
|
|
852
836
|
do {
|
|
@@ -1417,17 +1401,16 @@ function Loc(startToken, endToken, source) {
|
|
|
1417
1401
|
} // Print a simplified form when appearing in JSON/util.inspect.
|
|
1418
1402
|
|
|
1419
1403
|
|
|
1420
|
-
|
|
1404
|
+
(0, _defineToJSON.default)(Loc, function () {
|
|
1421
1405
|
return {
|
|
1422
1406
|
start: this.start,
|
|
1423
1407
|
end: this.end
|
|
1424
1408
|
};
|
|
1425
|
-
};
|
|
1409
|
+
});
|
|
1426
1410
|
/**
|
|
1427
1411
|
* Determines if the next token is of a given kind
|
|
1428
1412
|
*/
|
|
1429
1413
|
|
|
1430
|
-
|
|
1431
1414
|
function peek(lexer, kind) {
|
|
1432
1415
|
return lexer.token.kind === kind;
|
|
1433
1416
|
}
|
|
@@ -1438,13 +1421,12 @@ function peek(lexer, kind) {
|
|
|
1438
1421
|
|
|
1439
1422
|
|
|
1440
1423
|
function skip(lexer, kind) {
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
if (match) {
|
|
1424
|
+
if (lexer.token.kind === kind) {
|
|
1444
1425
|
lexer.advance();
|
|
1426
|
+
return true;
|
|
1445
1427
|
}
|
|
1446
1428
|
|
|
1447
|
-
return
|
|
1429
|
+
return false;
|
|
1448
1430
|
}
|
|
1449
1431
|
/**
|
|
1450
1432
|
* If the next token is of the given kind, return that token after advancing
|
|
@@ -1463,21 +1445,32 @@ function expect(lexer, kind) {
|
|
|
1463
1445
|
throw (0, _error.syntaxError)(lexer.source, token.start, "Expected ".concat(kind, ", found ").concat((0, _lexer.getTokenDesc)(token)));
|
|
1464
1446
|
}
|
|
1465
1447
|
/**
|
|
1466
|
-
* If the next token is a keyword with the given value, return
|
|
1467
|
-
*
|
|
1468
|
-
* false.
|
|
1448
|
+
* If the next token is a keyword with the given value, return true after advancing
|
|
1449
|
+
* the lexer. Otherwise, do not change the parser state and return false.
|
|
1469
1450
|
*/
|
|
1470
1451
|
|
|
1471
1452
|
|
|
1472
|
-
function
|
|
1453
|
+
function skipKeyword(lexer, value) {
|
|
1473
1454
|
var token = lexer.token;
|
|
1474
1455
|
|
|
1475
1456
|
if (token.kind === _lexer.TokenKind.NAME && token.value === value) {
|
|
1476
1457
|
lexer.advance();
|
|
1477
|
-
return
|
|
1458
|
+
return true;
|
|
1478
1459
|
}
|
|
1479
1460
|
|
|
1480
|
-
|
|
1461
|
+
return false;
|
|
1462
|
+
}
|
|
1463
|
+
/**
|
|
1464
|
+
* If the next token is a keyword with the given value, return that token after
|
|
1465
|
+
* advancing the lexer. Otherwise, do not change the parser state and throw
|
|
1466
|
+
* an error.
|
|
1467
|
+
*/
|
|
1468
|
+
|
|
1469
|
+
|
|
1470
|
+
function expectKeyword(lexer, value) {
|
|
1471
|
+
if (!skipKeyword(lexer, value)) {
|
|
1472
|
+
throw (0, _error.syntaxError)(lexer.source, lexer.token.start, "Expected \"".concat(value, "\", found ").concat((0, _lexer.getTokenDesc)(lexer.token)));
|
|
1473
|
+
}
|
|
1481
1474
|
}
|
|
1482
1475
|
/**
|
|
1483
1476
|
* Helper function for creating an error when an unexpected lexed token
|
package/language/parser.js.flow
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import inspect from '../jsutils/inspect';
|
|
11
|
+
import defineToJSON from '../jsutils/defineToJSON';
|
|
11
12
|
import { Source } from './source';
|
|
12
13
|
import { syntaxError } from '../error';
|
|
13
14
|
import type { GraphQLError } from '../error';
|
|
@@ -115,17 +116,6 @@ export type ParseOptions = {
|
|
|
115
116
|
* future.
|
|
116
117
|
*/
|
|
117
118
|
experimentalFragmentVariables?: boolean,
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* EXPERIMENTAL:
|
|
121
|
-
*
|
|
122
|
-
* If enabled, the parser understands directives on variable definitions:
|
|
123
|
-
*
|
|
124
|
-
* query Foo($var: String = "abc" @variable_definition_directive) {
|
|
125
|
-
* ...
|
|
126
|
-
* }
|
|
127
|
-
*/
|
|
128
|
-
experimentalVariableDefinitionDirectives?: boolean,
|
|
129
119
|
};
|
|
130
120
|
|
|
131
121
|
/**
|
|
@@ -341,19 +331,6 @@ function parseVariableDefinitions(
|
|
|
341
331
|
*/
|
|
342
332
|
function parseVariableDefinition(lexer: Lexer<*>): VariableDefinitionNode {
|
|
343
333
|
const start = lexer.token;
|
|
344
|
-
if (lexer.options.experimentalVariableDefinitionDirectives) {
|
|
345
|
-
return {
|
|
346
|
-
kind: Kind.VARIABLE_DEFINITION,
|
|
347
|
-
variable: parseVariable(lexer),
|
|
348
|
-
type: (expect(lexer, TokenKind.COLON), parseTypeReference(lexer)),
|
|
349
|
-
defaultValue: skip(lexer, TokenKind.EQUALS)
|
|
350
|
-
? parseValueLiteral(lexer, true)
|
|
351
|
-
: undefined,
|
|
352
|
-
directives: parseDirectives(lexer, true),
|
|
353
|
-
loc: loc(lexer, start),
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
|
|
357
334
|
return {
|
|
358
335
|
kind: Kind.VARIABLE_DEFINITION,
|
|
359
336
|
variable: parseVariable(lexer),
|
|
@@ -361,6 +338,7 @@ function parseVariableDefinition(lexer: Lexer<*>): VariableDefinitionNode {
|
|
|
361
338
|
defaultValue: skip(lexer, TokenKind.EQUALS)
|
|
362
339
|
? parseValueLiteral(lexer, true)
|
|
363
340
|
: undefined,
|
|
341
|
+
directives: parseDirectives(lexer, true),
|
|
364
342
|
loc: loc(lexer, start),
|
|
365
343
|
};
|
|
366
344
|
}
|
|
@@ -488,7 +466,9 @@ function parseFragment(
|
|
|
488
466
|
): FragmentSpreadNode | InlineFragmentNode {
|
|
489
467
|
const start = lexer.token;
|
|
490
468
|
expect(lexer, TokenKind.SPREAD);
|
|
491
|
-
|
|
469
|
+
|
|
470
|
+
const hasTypeCondition = skipKeyword(lexer, 'on');
|
|
471
|
+
if (!hasTypeCondition && peek(lexer, TokenKind.NAME)) {
|
|
492
472
|
return {
|
|
493
473
|
kind: Kind.FRAGMENT_SPREAD,
|
|
494
474
|
name: parseFragmentName(lexer),
|
|
@@ -496,14 +476,9 @@ function parseFragment(
|
|
|
496
476
|
loc: loc(lexer, start),
|
|
497
477
|
};
|
|
498
478
|
}
|
|
499
|
-
let typeCondition;
|
|
500
|
-
if (lexer.token.value === 'on') {
|
|
501
|
-
lexer.advance();
|
|
502
|
-
typeCondition = parseNamedType(lexer);
|
|
503
|
-
}
|
|
504
479
|
return {
|
|
505
480
|
kind: Kind.INLINE_FRAGMENT,
|
|
506
|
-
typeCondition,
|
|
481
|
+
typeCondition: hasTypeCondition ? parseNamedType(lexer) : undefined,
|
|
507
482
|
directives: parseDirectives(lexer, false),
|
|
508
483
|
selectionSet: parseSelectionSet(lexer),
|
|
509
484
|
loc: loc(lexer, start),
|
|
@@ -912,8 +887,7 @@ function parseObjectTypeDefinition(lexer: Lexer<*>): ObjectTypeDefinitionNode {
|
|
|
912
887
|
*/
|
|
913
888
|
function parseImplementsInterfaces(lexer: Lexer<*>): Array<NamedTypeNode> {
|
|
914
889
|
const types = [];
|
|
915
|
-
if (lexer
|
|
916
|
-
lexer.advance();
|
|
890
|
+
if (skipKeyword(lexer, 'implements')) {
|
|
917
891
|
// Optional leading ampersand
|
|
918
892
|
skip(lexer, TokenKind.AMP);
|
|
919
893
|
do {
|
|
@@ -1471,9 +1445,9 @@ function Loc(startToken: Token, endToken: Token, source: Source) {
|
|
|
1471
1445
|
}
|
|
1472
1446
|
|
|
1473
1447
|
// Print a simplified form when appearing in JSON/util.inspect.
|
|
1474
|
-
Loc
|
|
1448
|
+
defineToJSON(Loc, function() {
|
|
1475
1449
|
return { start: this.start, end: this.end };
|
|
1476
|
-
};
|
|
1450
|
+
});
|
|
1477
1451
|
|
|
1478
1452
|
/**
|
|
1479
1453
|
* Determines if the next token is of a given kind
|
|
@@ -1487,11 +1461,11 @@ function peek(lexer: Lexer<*>, kind: TokenKindEnum): boolean {
|
|
|
1487
1461
|
* the lexer. Otherwise, do not change the parser state and return false.
|
|
1488
1462
|
*/
|
|
1489
1463
|
function skip(lexer: Lexer<*>, kind: TokenKindEnum): boolean {
|
|
1490
|
-
|
|
1491
|
-
if (match) {
|
|
1464
|
+
if (lexer.token.kind === kind) {
|
|
1492
1465
|
lexer.advance();
|
|
1466
|
+
return true;
|
|
1493
1467
|
}
|
|
1494
|
-
return
|
|
1468
|
+
return false;
|
|
1495
1469
|
}
|
|
1496
1470
|
|
|
1497
1471
|
/**
|
|
@@ -1512,21 +1486,31 @@ function expect(lexer: Lexer<*>, kind: TokenKindEnum): Token {
|
|
|
1512
1486
|
}
|
|
1513
1487
|
|
|
1514
1488
|
/**
|
|
1515
|
-
* If the next token is a keyword with the given value, return
|
|
1516
|
-
*
|
|
1517
|
-
* false.
|
|
1489
|
+
* If the next token is a keyword with the given value, return true after advancing
|
|
1490
|
+
* the lexer. Otherwise, do not change the parser state and return false.
|
|
1518
1491
|
*/
|
|
1519
|
-
function
|
|
1492
|
+
function skipKeyword(lexer: Lexer<*>, value: string): boolean {
|
|
1520
1493
|
const token = lexer.token;
|
|
1521
1494
|
if (token.kind === TokenKind.NAME && token.value === value) {
|
|
1522
1495
|
lexer.advance();
|
|
1523
|
-
return
|
|
1496
|
+
return true;
|
|
1497
|
+
}
|
|
1498
|
+
return false;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
/**
|
|
1502
|
+
* If the next token is a keyword with the given value, return that token after
|
|
1503
|
+
* advancing the lexer. Otherwise, do not change the parser state and throw
|
|
1504
|
+
* an error.
|
|
1505
|
+
*/
|
|
1506
|
+
function expectKeyword(lexer: Lexer<*>, value: string): void {
|
|
1507
|
+
if (!skipKeyword(lexer, value)) {
|
|
1508
|
+
throw syntaxError(
|
|
1509
|
+
lexer.source,
|
|
1510
|
+
lexer.token.start,
|
|
1511
|
+
`Expected "${value}", found ${getTokenDesc(lexer.token)}`,
|
|
1512
|
+
);
|
|
1524
1513
|
}
|
|
1525
|
-
throw syntaxError(
|
|
1526
|
-
lexer.source,
|
|
1527
|
-
token.start,
|
|
1528
|
-
`Expected "${value}", found ${getTokenDesc(token)}`,
|
|
1529
|
-
);
|
|
1530
1514
|
}
|
|
1531
1515
|
|
|
1532
1516
|
/**
|