json 2.7.2 → 2.7.3.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  module JSON
3
3
  MAP = {
4
4
  "\x0" => '\u0000',
@@ -35,7 +35,7 @@ module JSON
35
35
  "\x1f" => '\u001f',
36
36
  '"' => '\"',
37
37
  '\\' => '\\\\',
38
- } # :nodoc:
38
+ }.freeze # :nodoc:
39
39
 
40
40
  ESCAPE_PATTERN = /[\/"\\\x0-\x1f]/n # :nodoc:
41
41
 
@@ -43,7 +43,7 @@ module JSON
43
43
  '/' => '\\/',
44
44
  "\u2028".b => '\u2028',
45
45
  "\u2029".b => '\u2029',
46
- )
46
+ ).freeze
47
47
 
48
48
  SCRIPT_SAFE_ESCAPE_PATTERN = Regexp.union(ESCAPE_PATTERN, "\u2028".b, "\u2029".b)
49
49
 
@@ -75,7 +75,7 @@ module JSON
75
75
  [\x80-\xc1\xf5-\xff] # invalid
76
76
  )/nx) { |c|
77
77
  c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
78
- s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
78
+ s = c.encode(::Encoding::UTF_16BE, ::Encoding::UTF_8).unpack('H*')[0]
79
79
  s.force_encoding(::Encoding::ASCII_8BIT)
80
80
  s.gsub!(/.{4}/n, '\\\\u\&')
81
81
  s.force_encoding(::Encoding::UTF_8)
@@ -219,7 +219,9 @@ module JSON
219
219
  @script_safe
220
220
  end
221
221
 
222
- # Returns true, if forward slashes are escaped. Otherwise returns false.
222
+ # Returns true, if strict mode is enabled. Otherwise returns false.
223
+ # Strict mode only allow serializing JSON native types: Hash, Array,
224
+ # String, Integer, Float, true, false and nil.
223
225
  def strict?
224
226
  @strict
225
227
  end
@@ -237,6 +239,8 @@ module JSON
237
239
  opts.each do |key, value|
238
240
  instance_variable_set "@#{key}", value
239
241
  end
242
+
243
+ # NOTE: If adding new instance variables here, check whether #generate should check them for #generate_json
240
244
  @indent = opts[:indent] if opts.key?(:indent)
241
245
  @space = opts[:space] if opts.key?(:space)
242
246
  @space_before = opts[:space_before] if opts.key?(:space_before)
@@ -286,12 +290,71 @@ module JSON
286
290
  # created this method raises a
287
291
  # GeneratorError exception.
288
292
  def generate(obj)
289
- result = obj.to_json(self)
293
+ if @indent.empty? and @space.empty? and @space_before.empty? and @object_nl.empty? and @array_nl.empty? and
294
+ !@ascii_only and !@script_safe and @max_nesting == 0 and !@strict
295
+ result = generate_json(obj, ''.dup)
296
+ else
297
+ result = obj.to_json(self)
298
+ end
290
299
  JSON.valid_utf8?(result) or raise GeneratorError,
291
300
  "source sequence #{result.inspect} is illegal/malformed utf-8"
292
301
  result
293
302
  end
294
303
 
304
+ # Handles @allow_nan, @buffer_initial_length, other ivars must be the default value (see above)
305
+ private def generate_json(obj, buf)
306
+ case obj
307
+ when Hash
308
+ buf << '{'
309
+ first = true
310
+ obj.each_pair do |k,v|
311
+ buf << ',' unless first
312
+ fast_serialize_string(k.to_s, buf)
313
+ buf << ':'
314
+ generate_json(v, buf)
315
+ first = false
316
+ end
317
+ buf << '}'
318
+ when Array
319
+ buf << '['
320
+ first = true
321
+ obj.each do |e|
322
+ buf << ',' unless first
323
+ generate_json(e, buf)
324
+ first = false
325
+ end
326
+ buf << ']'
327
+ when String
328
+ fast_serialize_string(obj, buf)
329
+ when Integer
330
+ buf << obj.to_s
331
+ else
332
+ # Note: Float is handled this way since Float#to_s is slow anyway
333
+ buf << obj.to_json(self)
334
+ end
335
+ end
336
+
337
+ # Assumes !@ascii_only, !@script_safe
338
+ if Regexp.method_defined?(:match?)
339
+ private def fast_serialize_string(string, buf) # :nodoc:
340
+ buf << '"'
341
+ string = string.encode(::Encoding::UTF_8) unless string.encoding == ::Encoding::UTF_8
342
+ raise GeneratorError, "source sequence is illegal/malformed utf-8" unless string.valid_encoding?
343
+
344
+ if /["\\\x0-\x1f]/n.match?(string)
345
+ buf << string.gsub(/["\\\x0-\x1f]/n, MAP)
346
+ else
347
+ buf << string
348
+ end
349
+ buf << '"'
350
+ end
351
+ else
352
+ # Ruby 2.3 compatibility
353
+ private def fast_serialize_string(string, buf) # :nodoc:
354
+ buf << string.to_json(self)
355
+ end
356
+ end
357
+
295
358
  # Return the value returned by method +name+.
296
359
  def [](name)
297
360
  if respond_to?(name)
@@ -316,8 +379,8 @@ module JSON
316
379
  # Converts this object to a string (calling #to_s), converts
317
380
  # it to a JSON string, and returns the result. This is a fallback, if no
318
381
  # special method #to_json was defined for some object.
319
- def to_json(generator_state)
320
- if generator_state.strict?
382
+ def to_json(state = nil, *)
383
+ if state && State.from_state(state).strict?
321
384
  raise GeneratorError, "#{self.class} not allowed in JSON"
322
385
  else
323
386
  to_s.to_json
@@ -347,6 +410,7 @@ module JSON
347
410
  def json_transform(state)
348
411
  delim = ",#{state.object_nl}"
349
412
  result = "{#{state.object_nl}"
413
+ result = result.dup if result.frozen? # RUBY_VERSION < 3.0
350
414
  depth = state.depth += 1
351
415
  first = true
352
416
  indent = !state.object_nl.empty?
@@ -354,7 +418,8 @@ module JSON
354
418
  result << delim unless first
355
419
  result << state.indent * depth if indent
356
420
  result = "#{result}#{key.to_s.to_json(state)}#{state.space_before}:#{state.space}"
357
- if state.strict?
421
+ result = result.dup if result.frozen? # RUBY_VERSION < 3.0
422
+ if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value)
358
423
  raise GeneratorError, "#{value.class} not allowed in JSON"
359
424
  elsif value.respond_to?(:to_json)
360
425
  result << value.to_json(state)
@@ -387,17 +452,20 @@ module JSON
387
452
  private
388
453
 
389
454
  def json_transform(state)
390
- delim = ','
391
- delim << state.array_nl
392
- result = '['
393
- result << state.array_nl
455
+ result = '['.dup
456
+ if state.array_nl.empty?
457
+ delim = ","
458
+ else
459
+ result << state.array_nl
460
+ delim = ",#{state.array_nl}"
461
+ end
394
462
  depth = state.depth += 1
395
463
  first = true
396
464
  indent = !state.array_nl.empty?
397
465
  each { |value|
398
466
  result << delim unless first
399
467
  result << state.indent * depth if indent
400
- if state.strict?
468
+ if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value)
401
469
  raise GeneratorError, "#{value.class} not allowed in JSON"
402
470
  elsif value.respond_to?(:to_json)
403
471
  result << value.to_json(state)
@@ -448,14 +516,17 @@ module JSON
448
516
  def to_json(state = nil, *args)
449
517
  state = State.from_state(state)
450
518
  if encoding == ::Encoding::UTF_8
519
+ unless valid_encoding?
520
+ raise GeneratorError, "source sequence is illegal/malformed utf-8"
521
+ end
451
522
  string = self
452
523
  else
453
524
  string = encode(::Encoding::UTF_8)
454
525
  end
455
526
  if state.ascii_only?
456
- '"' << JSON.utf8_to_json_ascii(string, state.script_safe) << '"'
527
+ %("#{JSON.utf8_to_json_ascii(string, state.script_safe)}")
457
528
  else
458
- '"' << JSON.utf8_to_json(string, state.script_safe) << '"'
529
+ %("#{JSON.utf8_to_json(string, state.script_safe)}")
459
530
  end
460
531
  end
461
532
 
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ #frozen_string_literal: true
2
2
  require 'strscan'
3
3
 
4
4
  module JSON
@@ -39,11 +39,8 @@ module JSON
39
39
  //[^\n\r]*[\n\r]| # line comments
40
40
  /\* # c-style comments
41
41
  (?:
42
- [^*/]| # normal chars
43
- /[^*]| # slashes that do not start a nested comment
44
- \*[^/]| # asterisks that do not end this comment
45
- /(?=\*/) # single slash before this comment's end
46
- )*
42
+ [\s\S]*? # any char, repeated lazily
43
+ )
47
44
  \*/ # the End of this comment
48
45
  |[ \t\r\n]+ # whitespaces: space, horizontal tab, lf, cr
49
46
  )+
@@ -70,12 +67,16 @@ module JSON
70
67
  # * *create_additions*: If set to true, the Parser creates
71
68
  # additions when a matching class and create_id are found. This
72
69
  # option defaults to false.
73
- # * *object_class*: Defaults to Hash
74
- # * *array_class*: Defaults to Array
70
+ # * *object_class*: Defaults to Hash. If another type is provided, it will be used
71
+ # instead of Hash to represent JSON objects. The type must respond to
72
+ # +new+ without arguments, and return an object that respond to +[]=+.
73
+ # * *array_class*: Defaults to Array If another type is provided, it will be used
74
+ # instead of Hash to represent JSON arrays. The type must respond to
75
+ # +new+ without arguments, and return an object that respond to +<<+.
75
76
  # * *decimal_class*: Specifies which class to use instead of the default
76
77
  # (Float) when parsing decimal numbers. This class must accept a single
77
78
  # string argument in its constructor.
78
- def initialize(source, opts = {})
79
+ def initialize(source, opts = nil)
79
80
  opts ||= {}
80
81
  source = convert_encoding source
81
82
  super source
@@ -160,11 +161,6 @@ module JSON
160
161
  ?u => nil,
161
162
  })
162
163
 
163
- EMPTY_8BIT_STRING = ''
164
- if ::String.method_defined?(:encode)
165
- EMPTY_8BIT_STRING.force_encoding Encoding::ASCII_8BIT
166
- end
167
-
168
164
  STR_UMINUS = ''.respond_to?(:-@)
169
165
  def parse_string
170
166
  if scan(STRING)
@@ -173,18 +169,16 @@ module JSON
173
169
  if u = UNESCAPE_MAP[$&[1]]
174
170
  u
175
171
  else # \uXXXX
176
- bytes = EMPTY_8BIT_STRING.dup
172
+ bytes = ''.b
177
173
  i = 0
178
174
  while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
179
175
  bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
180
176
  i += 1
181
177
  end
182
- JSON.iconv('utf-8', 'utf-16be', bytes).force_encoding(::Encoding::ASCII_8BIT)
178
+ bytes.encode(Encoding::UTF_8, Encoding::UTF_16BE).force_encoding(::Encoding::BINARY)
183
179
  end
184
180
  end
185
- if string.respond_to?(:force_encoding)
186
- string.force_encoding(::Encoding::UTF_8)
187
- end
181
+ string.force_encoding(::Encoding::UTF_8)
188
182
 
189
183
  if @freeze
190
184
  if STR_UMINUS
data/lib/json/pure.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'json/common'
2
3
 
3
4
  module JSON
data/lib/json/version.rb CHANGED
@@ -1,9 +1,5 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
+
2
3
  module JSON
3
- # JSON version
4
- VERSION = '2.7.2'
5
- VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
6
- VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
7
- VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
8
- VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
4
+ VERSION = '2.7.3.rc1'
9
5
  end
data/lib/json.rb CHANGED
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  require 'json/common'
3
3
 
4
4
  ##
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.2
4
+ version: 2.7.3.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
- date: 2024-04-04 00:00:00.000000000 Z
11
+ date: 2024-10-23 00:00:00.000000000 Z
11
12
  dependencies: []
12
13
  description: This is a JSON implementation as a Ruby extension in C.
13
14
  email: flori@ping.de
@@ -15,24 +16,22 @@ executables: []
15
16
  extensions:
16
17
  - ext/json/ext/generator/extconf.rb
17
18
  - ext/json/ext/parser/extconf.rb
18
- - ext/json/extconf.rb
19
19
  extra_rdoc_files:
20
20
  - README.md
21
21
  files:
22
+ - BSDL
22
23
  - CHANGES.md
23
- - LICENSE
24
+ - COPYING
25
+ - LEGAL
24
26
  - README.md
25
27
  - ext/json/ext/fbuffer/fbuffer.h
26
- - ext/json/ext/generator/depend
27
28
  - ext/json/ext/generator/extconf.rb
28
29
  - ext/json/ext/generator/generator.c
29
30
  - ext/json/ext/generator/generator.h
30
- - ext/json/ext/parser/depend
31
31
  - ext/json/ext/parser/extconf.rb
32
32
  - ext/json/ext/parser/parser.c
33
33
  - ext/json/ext/parser/parser.h
34
34
  - ext/json/ext/parser/parser.rl
35
- - ext/json/extconf.rb
36
35
  - json.gemspec
37
36
  - lib/json.rb
38
37
  - lib/json/add/bigdecimal.rb
@@ -51,21 +50,23 @@ files:
51
50
  - lib/json/add/time.rb
52
51
  - lib/json/common.rb
53
52
  - lib/json/ext.rb
53
+ - lib/json/ext/generator/state.rb
54
54
  - lib/json/generic_object.rb
55
55
  - lib/json/pure.rb
56
56
  - lib/json/pure/generator.rb
57
57
  - lib/json/pure/parser.rb
58
58
  - lib/json/version.rb
59
- homepage: https://flori.github.io/json
59
+ homepage: https://ruby.github.io/json
60
60
  licenses:
61
61
  - Ruby
62
62
  metadata:
63
- bug_tracker_uri: https://github.com/flori/json/issues
64
- changelog_uri: https://github.com/flori/json/blob/master/CHANGES.md
65
- documentation_uri: https://flori.github.io/json/doc/index.html
66
- homepage_uri: https://flori.github.io/json
67
- source_code_uri: https://github.com/flori/json
68
- wiki_uri: https://github.com/flori/json/wiki
63
+ bug_tracker_uri: https://github.com/ruby/json/issues
64
+ changelog_uri: https://github.com/ruby/json/blob/master/CHANGES.md
65
+ documentation_uri: https://ruby.github.io/json/doc/index.html
66
+ homepage_uri: https://ruby.github.io/json
67
+ source_code_uri: https://github.com/ruby/json
68
+ wiki_uri: https://github.com/ruby/json/wiki
69
+ post_install_message:
69
70
  rdoc_options:
70
71
  - "--title"
71
72
  - JSON implementation for Ruby
@@ -84,7 +85,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
85
  - !ruby/object:Gem::Version
85
86
  version: '0'
86
87
  requirements: []
87
- rubygems_version: 3.6.0.dev
88
+ rubygems_version: 3.5.17
89
+ signing_key:
88
90
  specification_version: 4
89
91
  summary: JSON Implementation for Ruby
90
92
  test_files: []
@@ -1 +0,0 @@
1
- generator.o: generator.c generator.h $(srcdir)/../fbuffer/fbuffer.h
@@ -1 +0,0 @@
1
- parser.o: parser.c parser.h $(srcdir)/../fbuffer/fbuffer.h
data/ext/json/extconf.rb DELETED
@@ -1,3 +0,0 @@
1
- require 'mkmf'
2
-
3
- create_makefile('json')
File without changes