graphql 2.0.16 → 2.0.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/ast/visitor.rb +42 -35
  3. data/lib/graphql/analysis/ast.rb +2 -2
  4. data/lib/graphql/backtrace/tracer.rb +1 -1
  5. data/lib/graphql/execution/interpreter/resolve.rb +19 -0
  6. data/lib/graphql/execution/interpreter/runtime.rb +106 -88
  7. data/lib/graphql/execution/interpreter.rb +14 -9
  8. data/lib/graphql/execution/lazy.rb +6 -12
  9. data/lib/graphql/execution/multiplex.rb +2 -1
  10. data/lib/graphql/graphql_ext.bundle +0 -0
  11. data/lib/graphql/introspection/directive_type.rb +2 -2
  12. data/lib/graphql/introspection/field_type.rb +1 -1
  13. data/lib/graphql/introspection/schema_type.rb +2 -2
  14. data/lib/graphql/introspection/type_type.rb +5 -5
  15. data/lib/graphql/language/lexer.rb +216 -1505
  16. data/lib/graphql/language/lexer.ri +744 -0
  17. data/lib/graphql/language/nodes.rb +39 -31
  18. data/lib/graphql/language/parser.rb +9 -9
  19. data/lib/graphql/language/parser.y +9 -9
  20. data/lib/graphql/language/visitor.rb +191 -83
  21. data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
  22. data/lib/graphql/query/context.rb +45 -11
  23. data/lib/graphql/query.rb +15 -2
  24. data/lib/graphql/schema/argument.rb +0 -4
  25. data/lib/graphql/schema/directive.rb +12 -2
  26. data/lib/graphql/schema/enum.rb +24 -17
  27. data/lib/graphql/schema/enum_value.rb +5 -3
  28. data/lib/graphql/schema/field.rb +53 -45
  29. data/lib/graphql/schema/interface.rb +0 -10
  30. data/lib/graphql/schema/late_bound_type.rb +2 -0
  31. data/lib/graphql/schema/member/base_dsl_methods.rb +15 -14
  32. data/lib/graphql/schema/member/has_arguments.rb +104 -57
  33. data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
  34. data/lib/graphql/schema/member/has_fields.rb +14 -2
  35. data/lib/graphql/schema/member/has_interfaces.rb +49 -8
  36. data/lib/graphql/schema/member/has_validators.rb +31 -5
  37. data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
  38. data/lib/graphql/schema/object.rb +2 -4
  39. data/lib/graphql/schema/resolver/has_payload_type.rb +9 -9
  40. data/lib/graphql/schema/timeout.rb +23 -27
  41. data/lib/graphql/schema/warden.rb +26 -4
  42. data/lib/graphql/schema.rb +37 -19
  43. data/lib/graphql/static_validation/literal_validator.rb +15 -1
  44. data/lib/graphql/static_validation/validator.rb +1 -1
  45. data/lib/graphql/subscriptions/event.rb +2 -7
  46. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  47. data/lib/graphql/tracing/appoptics_trace.rb +231 -0
  48. data/lib/graphql/tracing/appsignal_trace.rb +66 -0
  49. data/lib/graphql/tracing/data_dog_trace.rb +148 -0
  50. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  51. data/lib/graphql/tracing/notifications_trace.rb +41 -0
  52. data/lib/graphql/tracing/platform_trace.rb +107 -0
  53. data/lib/graphql/tracing/platform_tracing.rb +15 -3
  54. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  55. data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
  56. data/lib/graphql/tracing/scout_trace.rb +72 -0
  57. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  58. data/lib/graphql/tracing.rb +136 -39
  59. data/lib/graphql/type_kinds.rb +6 -3
  60. data/lib/graphql/types/relay/connection_behaviors.rb +0 -4
  61. data/lib/graphql/types/relay/edge_behaviors.rb +0 -4
  62. data/lib/graphql/types/string.rb +1 -1
  63. data/lib/graphql/version.rb +1 -1
  64. data/lib/graphql.rb +7 -8
  65. metadata +15 -4
  66. data/lib/graphql/language/lexer.rl +0 -280
@@ -5,12 +5,13 @@ module GraphQL
5
5
  # These objects are singletons, eg `GraphQL::TypeKinds::UNION`, `GraphQL::TypeKinds::SCALAR`.
6
6
  class TypeKind
7
7
  attr_reader :name, :description
8
- def initialize(name, abstract: false, fields: false, wraps: false, input: false, description: nil)
8
+ def initialize(name, abstract: false, leaf: false, fields: false, wraps: false, input: false, description: nil)
9
9
  @name = name
10
10
  @abstract = abstract
11
11
  @fields = fields
12
12
  @wraps = wraps
13
13
  @input = input
14
+ @leaf = leaf
14
15
  @composite = fields? || abstract?
15
16
  @description = description
16
17
  end
@@ -27,6 +28,8 @@ module GraphQL
27
28
  # Is this TypeKind a valid query input?
28
29
  def input?; @input; end
29
30
  def to_s; @name; end
31
+ # Is this TypeKind a primitive value?
32
+ def leaf?; @leaf; end
30
33
  # Is this TypeKind composed of many values?
31
34
  def composite?; @composite; end
32
35
 
@@ -64,11 +67,11 @@ module GraphQL
64
67
  end
65
68
 
66
69
  TYPE_KINDS = [
67
- SCALAR = TypeKind.new("SCALAR", input: true, description: 'Indicates this type is a scalar.'),
70
+ SCALAR = TypeKind.new("SCALAR", input: true, leaf: true, description: 'Indicates this type is a scalar.'),
68
71
  OBJECT = TypeKind.new("OBJECT", fields: true, description: 'Indicates this type is an object. `fields` and `interfaces` are valid fields.'),
69
72
  INTERFACE = TypeKind.new("INTERFACE", abstract: true, fields: true, description: 'Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.'),
70
73
  UNION = TypeKind.new("UNION", abstract: true, description: 'Indicates this type is a union. `possibleTypes` is a valid field.'),
71
- ENUM = TypeKind.new("ENUM", input: true, description: 'Indicates this type is an enum. `enumValues` is a valid field.'),
74
+ ENUM = TypeKind.new("ENUM", input: true, leaf: true, description: 'Indicates this type is an enum. `enumValues` is a valid field.'),
72
75
  INPUT_OBJECT = TypeKind.new("INPUT_OBJECT", input: true, description: 'Indicates this type is an input object. `inputFields` is a valid field.'),
73
76
  LIST = TypeKind.new("LIST", wraps: true, description: 'Indicates this type is a list. `ofType` is a valid field.'),
74
77
  NON_NULL = TypeKind.new("NON_NULL", wraps: true, description: 'Indicates this type is a non-null. `ofType` is a valid field.'),
@@ -79,10 +79,6 @@ module GraphQL
79
79
  true # Let nodes be filtered out
80
80
  end
81
81
 
82
- def accessible?(ctx)
83
- node_type.accessible?(ctx)
84
- end
85
-
86
82
  def visible?(ctx)
87
83
  # if this is an abstract base class, there may be no `node_type`
88
84
  node_type ? node_type.visible?(ctx) : super
@@ -41,10 +41,6 @@ module GraphQL
41
41
  true
42
42
  end
43
43
 
44
- def accessible?(ctx)
45
- node_type.accessible?(ctx)
46
- end
47
-
48
44
  def visible?(ctx)
49
45
  node_type.visible?(ctx)
50
46
  end
@@ -7,7 +7,7 @@ module GraphQL
7
7
 
8
8
  def self.coerce_result(value, ctx)
9
9
  str = value.to_s
10
- if str.encoding == Encoding::UTF_8
10
+ if str.encoding == Encoding::UTF_8 || str.ascii_only?
11
11
  str
12
12
  elsif str.frozen?
13
13
  str.encode(Encoding::UTF_8)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.0.16"
3
+ VERSION = "2.0.18"
4
4
  end
data/lib/graphql.rb CHANGED
@@ -42,8 +42,8 @@ This is probably a bug in GraphQL-Ruby, please report this error on GitHub: http
42
42
  # Turn a query string or schema definition into an AST
43
43
  # @param graphql_string [String] a GraphQL query string or schema definition
44
44
  # @return [GraphQL::Language::Nodes::Document]
45
- def self.parse(graphql_string, tracer: GraphQL::Tracing::NullTracer)
46
- parse_with_racc(graphql_string, tracer: tracer)
45
+ def self.parse(graphql_string, trace: GraphQL::Tracing::NullTrace)
46
+ parse_with_racc(graphql_string, trace: trace)
47
47
  end
48
48
 
49
49
  # Read the contents of `filename` and parse them as GraphQL
@@ -54,18 +54,17 @@ This is probably a bug in GraphQL-Ruby, please report this error on GitHub: http
54
54
  parse_with_racc(content, filename: filename)
55
55
  end
56
56
 
57
- def self.parse_with_racc(string, filename: nil, tracer: GraphQL::Tracing::NullTracer)
58
- GraphQL::Language::Parser.parse(string, filename: filename, tracer: tracer)
57
+ def self.parse_with_racc(string, filename: nil, trace: GraphQL::Tracing::NullTrace)
58
+ GraphQL::Language::Parser.parse(string, filename: filename, trace: trace)
59
59
  end
60
60
 
61
61
  # @return [Array<GraphQL::Language::Token>]
62
62
  def self.scan(graphql_string)
63
- scan_with_ragel(graphql_string)
64
- end
65
-
66
- def self.scan_with_ragel(graphql_string)
67
63
  GraphQL::Language::Lexer.tokenize(graphql_string)
68
64
  end
65
+
66
+ NOT_CONFIGURED = Object.new
67
+ private_constant :NOT_CONFIGURED
69
68
  end
70
69
 
71
70
  # Order matters for these:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.16
4
+ version: 2.0.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-19 00:00:00.000000000 Z
11
+ date: 2023-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips
@@ -317,6 +317,7 @@ files:
317
317
  - lib/graphql/execution/multiplex.rb
318
318
  - lib/graphql/execution_error.rb
319
319
  - lib/graphql/filter.rb
320
+ - lib/graphql/graphql_ext.bundle
320
321
  - lib/graphql/integer_decoding_error.rb
321
322
  - lib/graphql/integer_encoding_error.rb
322
323
  - lib/graphql/introspection.rb
@@ -341,7 +342,7 @@ files:
341
342
  - lib/graphql/language/document_from_schema_definition.rb
342
343
  - lib/graphql/language/generation.rb
343
344
  - lib/graphql/language/lexer.rb
344
- - lib/graphql/language/lexer.rl
345
+ - lib/graphql/language/lexer.ri
345
346
  - lib/graphql/language/nodes.rb
346
347
  - lib/graphql/language/parser.rb
347
348
  - lib/graphql/language/parser.y
@@ -534,16 +535,26 @@ files:
534
535
  - lib/graphql/subscriptions/instrumentation.rb
535
536
  - lib/graphql/subscriptions/serialize.rb
536
537
  - lib/graphql/tracing.rb
538
+ - lib/graphql/tracing/active_support_notifications_trace.rb
537
539
  - lib/graphql/tracing/active_support_notifications_tracing.rb
540
+ - lib/graphql/tracing/appoptics_trace.rb
538
541
  - lib/graphql/tracing/appoptics_tracing.rb
542
+ - lib/graphql/tracing/appsignal_trace.rb
539
543
  - lib/graphql/tracing/appsignal_tracing.rb
544
+ - lib/graphql/tracing/data_dog_trace.rb
540
545
  - lib/graphql/tracing/data_dog_tracing.rb
546
+ - lib/graphql/tracing/new_relic_trace.rb
541
547
  - lib/graphql/tracing/new_relic_tracing.rb
548
+ - lib/graphql/tracing/notifications_trace.rb
542
549
  - lib/graphql/tracing/notifications_tracing.rb
550
+ - lib/graphql/tracing/platform_trace.rb
543
551
  - lib/graphql/tracing/platform_tracing.rb
552
+ - lib/graphql/tracing/prometheus_trace.rb
544
553
  - lib/graphql/tracing/prometheus_tracing.rb
545
554
  - lib/graphql/tracing/prometheus_tracing/graphql_collector.rb
555
+ - lib/graphql/tracing/scout_trace.rb
546
556
  - lib/graphql/tracing/scout_tracing.rb
557
+ - lib/graphql/tracing/statsd_trace.rb
547
558
  - lib/graphql/tracing/statsd_tracing.rb
548
559
  - lib/graphql/type_kinds.rb
549
560
  - lib/graphql/types.rb
@@ -597,7 +608,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
597
608
  - !ruby/object:Gem::Version
598
609
  version: '0'
599
610
  requirements: []
600
- rubygems_version: 3.3.3
611
+ rubygems_version: 3.4.1
601
612
  signing_key:
602
613
  specification_version: 4
603
614
  summary: A GraphQL language and runtime for Ruby
@@ -1,280 +0,0 @@
1
- %%{
2
- machine graphql_lexer;
3
-
4
- IDENTIFIER = [_A-Za-z][_0-9A-Za-z]*;
5
- NEWLINE = [\c\r\n];
6
- BLANK = [, \t]+;
7
- COMMENT = '#' [^\n\r]*;
8
- INT = '-'? ('0'|[1-9][0-9]*);
9
- FLOAT_DECIMAL = '.'[0-9]+;
10
- FLOAT_EXP = ('e' | 'E')?('+' | '-')?[0-9]+;
11
- FLOAT = INT FLOAT_DECIMAL? FLOAT_EXP?;
12
- ON = 'on';
13
- FRAGMENT = 'fragment';
14
- TRUE = 'true';
15
- FALSE = 'false';
16
- NULL = 'null';
17
- QUERY = 'query';
18
- MUTATION = 'mutation';
19
- SUBSCRIPTION = 'subscription';
20
- SCHEMA = 'schema';
21
- SCALAR = 'scalar';
22
- TYPE = 'type';
23
- EXTEND = 'extend';
24
- IMPLEMENTS = 'implements';
25
- INTERFACE = 'interface';
26
- UNION = 'union';
27
- ENUM = 'enum';
28
- INPUT = 'input';
29
- DIRECTIVE = 'directive';
30
- REPEATABLE = 'repeatable';
31
- LCURLY = '{';
32
- RCURLY = '}';
33
- LPAREN = '(';
34
- RPAREN = ')';
35
- LBRACKET = '[';
36
- RBRACKET = ']';
37
- COLON = ':';
38
- QUOTE = '"';
39
- BACKSLASH = '\\';
40
- # Could limit to hex here, but “bad unicode escape” on 0XXF is probably a
41
- # more helpful error than “unknown char”
42
- UNICODE_DIGIT = [0-9A-Za-z];
43
- FOUR_DIGIT_UNICODE = UNICODE_DIGIT{4};
44
- N_DIGIT_UNICODE = LCURLY UNICODE_DIGIT{4,} RCURLY;
45
- UNICODE_ESCAPE = '\\u' (FOUR_DIGIT_UNICODE | N_DIGIT_UNICODE);
46
- # https://graphql.github.io/graphql-spec/June2018/#sec-String-Value
47
- STRING_ESCAPE = '\\' [\\/bfnrt];
48
- BLOCK_QUOTE = '"""';
49
- ESCAPED_BLOCK_QUOTE = '\\"""';
50
- BLOCK_STRING_CHAR = (ESCAPED_BLOCK_QUOTE | ^QUOTE | QUOTE{1,2} ^QUOTE);
51
- ESCAPED_QUOTE = '\\"';
52
- STRING_CHAR = ((ESCAPED_QUOTE | ^QUOTE) - BACKSLASH) | UNICODE_ESCAPE | STRING_ESCAPE;
53
- VAR_SIGN = '$';
54
- DIR_SIGN = '@';
55
- ELLIPSIS = '...';
56
- EQUALS = '=';
57
- BANG = '!';
58
- PIPE = '|';
59
- AMP = '&';
60
-
61
- QUOTED_STRING = QUOTE STRING_CHAR* QUOTE;
62
- BLOCK_STRING = BLOCK_QUOTE BLOCK_STRING_CHAR* QUOTE{0,2} BLOCK_QUOTE;
63
- # catch-all for anything else. must be at the bottom for precedence.
64
- UNKNOWN_CHAR = /./;
65
-
66
- # Used with ragel -V for graphviz visualization
67
- str := |*
68
- QUOTED_STRING => { emit_string(ts, te, meta, block: false) };
69
- *|;
70
-
71
- main := |*
72
- INT => { emit(:INT, ts, te, meta) };
73
- FLOAT => { emit(:FLOAT, ts, te, meta) };
74
- ON => { emit(:ON, ts, te, meta, "on") };
75
- FRAGMENT => { emit(:FRAGMENT, ts, te, meta, "fragment") };
76
- TRUE => { emit(:TRUE, ts, te, meta, "true") };
77
- FALSE => { emit(:FALSE, ts, te, meta, "false") };
78
- NULL => { emit(:NULL, ts, te, meta, "null") };
79
- QUERY => { emit(:QUERY, ts, te, meta, "query") };
80
- MUTATION => { emit(:MUTATION, ts, te, meta, "mutation") };
81
- SUBSCRIPTION => { emit(:SUBSCRIPTION, ts, te, meta, "subscription") };
82
- SCHEMA => { emit(:SCHEMA, ts, te, meta) };
83
- SCALAR => { emit(:SCALAR, ts, te, meta) };
84
- TYPE => { emit(:TYPE, ts, te, meta) };
85
- EXTEND => { emit(:EXTEND, ts, te, meta) };
86
- IMPLEMENTS => { emit(:IMPLEMENTS, ts, te, meta) };
87
- INTERFACE => { emit(:INTERFACE, ts, te, meta) };
88
- UNION => { emit(:UNION, ts, te, meta) };
89
- ENUM => { emit(:ENUM, ts, te, meta) };
90
- INPUT => { emit(:INPUT, ts, te, meta) };
91
- DIRECTIVE => { emit(:DIRECTIVE, ts, te, meta) };
92
- REPEATABLE => { emit(:REPEATABLE, ts, te, meta, "repeatable") };
93
- RCURLY => { emit(:RCURLY, ts, te, meta, "}") };
94
- LCURLY => { emit(:LCURLY, ts, te, meta, "{") };
95
- RPAREN => { emit(:RPAREN, ts, te, meta, ")") };
96
- LPAREN => { emit(:LPAREN, ts, te, meta, "(")};
97
- RBRACKET => { emit(:RBRACKET, ts, te, meta, "]") };
98
- LBRACKET => { emit(:LBRACKET, ts, te, meta, "[") };
99
- COLON => { emit(:COLON, ts, te, meta, ":") };
100
- QUOTED_STRING => { emit_string(ts, te, meta, block: false) };
101
- BLOCK_STRING => { emit_string(ts, te, meta, block: true) };
102
- VAR_SIGN => { emit(:VAR_SIGN, ts, te, meta, "$") };
103
- DIR_SIGN => { emit(:DIR_SIGN, ts, te, meta, "@") };
104
- ELLIPSIS => { emit(:ELLIPSIS, ts, te, meta, "...") };
105
- EQUALS => { emit(:EQUALS, ts, te, meta, "=") };
106
- BANG => { emit(:BANG, ts, te, meta, "!") };
107
- PIPE => { emit(:PIPE, ts, te, meta, "|") };
108
- AMP => { emit(:AMP, ts, te, meta, "&") };
109
- IDENTIFIER => { emit(:IDENTIFIER, ts, te, meta) };
110
- COMMENT => { record_comment(ts, te, meta) };
111
-
112
- NEWLINE => {
113
- meta[:line] += 1
114
- meta[:col] = 1
115
- };
116
-
117
- BLANK => { meta[:col] += te - ts };
118
-
119
- UNKNOWN_CHAR => { emit(:UNKNOWN_CHAR, ts, te, meta) };
120
-
121
- *|;
122
- }%%
123
-
124
- # frozen_string_literal: true
125
-
126
- module GraphQL
127
- module Language
128
- module Lexer
129
- def self.tokenize(query_string)
130
- run_lexer(query_string)
131
- end
132
-
133
- # Replace any escaped unicode or whitespace with the _actual_ characters
134
- # To avoid allocating more strings, this modifies the string passed into it
135
- def self.replace_escaped_characters_in_place(raw_string)
136
- raw_string.gsub!(ESCAPES, ESCAPES_REPLACE)
137
- raw_string.gsub!(UTF_8) do |_matched_str|
138
- codepoint_1 = ($1 || $2).to_i(16)
139
- codepoint_2 = $3
140
-
141
- if codepoint_2
142
- codepoint_2 = codepoint_2.to_i(16)
143
- if (codepoint_1 >= 0xD800 && codepoint_1 <= 0xDBFF) && # leading surrogate
144
- (codepoint_2 >= 0xDC00 && codepoint_2 <= 0xDFFF) # trailing surrogate
145
- # A surrogate pair
146
- combined = ((codepoint_1 - 0xD800) * 0x400) + (codepoint_2 - 0xDC00) + 0x10000
147
- [combined].pack('U'.freeze)
148
- else
149
- # Two separate code points
150
- [codepoint_1].pack('U'.freeze) + [codepoint_2].pack('U'.freeze)
151
- end
152
- else
153
- [codepoint_1].pack('U'.freeze)
154
- end
155
- end
156
- nil
157
- end
158
-
159
- private
160
-
161
- %% write data;
162
-
163
- def self.run_lexer(query_string)
164
- data = query_string.unpack(PACK_DIRECTIVE)
165
- eof = data.length
166
-
167
- # Since `Lexer` is a module, store all lexer state
168
- # in this local variable:
169
- meta = {
170
- line: 1,
171
- col: 1,
172
- data: data,
173
- tokens: [],
174
- previous_token: nil,
175
- }
176
-
177
- p ||= 0
178
- pe ||= data.length
179
-
180
- %% write init;
181
-
182
- %% write exec;
183
-
184
- meta[:tokens]
185
- end
186
-
187
- def self.record_comment(ts, te, meta)
188
- token = GraphQL::Language::Token.new(
189
- :COMMENT,
190
- meta[:data][ts, te - ts].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING),
191
- meta[:line],
192
- meta[:col],
193
- meta[:previous_token],
194
- )
195
-
196
- meta[:previous_token] = token
197
-
198
- meta[:col] += te - ts
199
- end
200
-
201
- def self.emit(token_name, ts, te, meta, token_value = nil)
202
- token_value ||= meta[:data][ts, te - ts].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING)
203
- meta[:tokens] << token = GraphQL::Language::Token.new(
204
- token_name,
205
- token_value,
206
- meta[:line],
207
- meta[:col],
208
- meta[:previous_token],
209
- )
210
- meta[:previous_token] = token
211
- # Bump the column counter for the next token
212
- meta[:col] += te - ts
213
- end
214
-
215
- ESCAPES = /\\["\\\/bfnrt]/
216
- ESCAPES_REPLACE = {
217
- '\\"' => '"',
218
- "\\\\" => "\\",
219
- "\\/" => '/',
220
- "\\b" => "\b",
221
- "\\f" => "\f",
222
- "\\n" => "\n",
223
- "\\r" => "\r",
224
- "\\t" => "\t",
225
- }
226
-
227
- UTF_8 = /\\u(?:([\dAa-f]{4})|\{([\da-f]{4,})\})(?:\\u([\dAa-f]{4}))?/i
228
-
229
-
230
- VALID_STRING = /\A(?:[^\\]|#{ESCAPES}|#{UTF_8})*\z/o
231
-
232
- PACK_DIRECTIVE = "c*"
233
- UTF_8_ENCODING = "UTF-8"
234
-
235
- def self.emit_string(ts, te, meta, block:)
236
- quotes_length = block ? 3 : 1
237
- value = meta[:data][ts + quotes_length, te - ts - 2 * quotes_length].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING) || ''
238
- line_incr = 0
239
- if block && !value.empty?
240
- line_incr = value.count("\n")
241
- value = GraphQL::Language::BlockString.trim_whitespace(value)
242
- end
243
-
244
- if !value.valid_encoding? || !value.match?(VALID_STRING)
245
- meta[:tokens] << token = GraphQL::Language::Token.new(
246
- :BAD_UNICODE_ESCAPE,
247
- value,
248
- meta[:line],
249
- meta[:col],
250
- meta[:previous_token],
251
- )
252
- else
253
- replace_escaped_characters_in_place(value)
254
-
255
- if !value.valid_encoding?
256
- meta[:tokens] << token = GraphQL::Language::Token.new(
257
- :BAD_UNICODE_ESCAPE,
258
- value,
259
- meta[:line],
260
- meta[:col],
261
- meta[:previous_token],
262
- )
263
- else
264
- meta[:tokens] << token = GraphQL::Language::Token.new(
265
- :STRING,
266
- value,
267
- meta[:line],
268
- meta[:col],
269
- meta[:previous_token],
270
- )
271
- end
272
- end
273
-
274
- meta[:previous_token] = token
275
- meta[:col] += te - ts
276
- meta[:line] += line_incr
277
- end
278
- end
279
- end
280
- end