json 1.8.3 → 2.4.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.
Files changed (83) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.travis.yml +9 -12
  4. data/{CHANGES → CHANGES.md} +219 -90
  5. data/Gemfile +10 -6
  6. data/{COPYING-json-jruby → LICENSE} +5 -6
  7. data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
  8. data/{README.rdoc → README.md} +201 -134
  9. data/Rakefile +35 -113
  10. data/VERSION +1 -1
  11. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  12. data/ext/json/ext/generator/generator.c +255 -101
  13. data/ext/json/ext/generator/generator.h +12 -4
  14. data/ext/json/ext/parser/extconf.rb +28 -0
  15. data/ext/json/ext/parser/parser.c +410 -462
  16. data/ext/json/ext/parser/parser.h +5 -5
  17. data/ext/json/ext/parser/parser.rl +166 -181
  18. data/ext/json/extconf.rb +1 -1
  19. data/java/src/json/ext/ByteListTranscoder.java +1 -2
  20. data/java/src/json/ext/Generator.java +39 -36
  21. data/java/src/json/ext/GeneratorMethods.java +1 -2
  22. data/java/src/json/ext/GeneratorService.java +1 -2
  23. data/java/src/json/ext/GeneratorState.java +33 -56
  24. data/java/src/json/ext/OptionsReader.java +2 -3
  25. data/java/src/json/ext/Parser.java +146 -417
  26. data/java/src/json/ext/Parser.rl +62 -126
  27. data/java/src/json/ext/ParserService.java +1 -2
  28. data/java/src/json/ext/RuntimeInfo.java +1 -6
  29. data/java/src/json/ext/StringDecoder.java +1 -2
  30. data/java/src/json/ext/StringEncoder.java +13 -2
  31. data/java/src/json/ext/Utils.java +1 -2
  32. data/json-java.gemspec +22 -7
  33. data/json.gemspec +0 -0
  34. data/json_pure.gemspec +22 -29
  35. data/lib/json/add/bigdecimal.rb +3 -2
  36. data/lib/json/add/complex.rb +4 -4
  37. data/lib/json/add/core.rb +1 -0
  38. data/lib/json/add/date.rb +1 -1
  39. data/lib/json/add/date_time.rb +1 -1
  40. data/lib/json/add/exception.rb +1 -1
  41. data/lib/json/add/ostruct.rb +3 -3
  42. data/lib/json/add/range.rb +1 -1
  43. data/lib/json/add/rational.rb +3 -3
  44. data/lib/json/add/regexp.rb +3 -3
  45. data/lib/json/add/set.rb +29 -0
  46. data/lib/json/add/struct.rb +1 -1
  47. data/lib/json/add/symbol.rb +1 -1
  48. data/lib/json/add/time.rb +1 -1
  49. data/lib/json/common.rb +350 -152
  50. data/lib/json/ext.rb +0 -6
  51. data/lib/json/generic_object.rb +5 -4
  52. data/lib/json/pure/generator.rb +83 -126
  53. data/lib/json/pure/parser.rb +62 -84
  54. data/lib/json/pure.rb +2 -8
  55. data/lib/json/version.rb +2 -1
  56. data/lib/json.rb +550 -29
  57. data/references/rfc7159.txt +899 -0
  58. data/tests/fixtures/obsolete_fail1.json +1 -0
  59. data/tests/{test_json_addition.rb → json_addition_test.rb} +28 -25
  60. data/tests/json_common_interface_test.rb +169 -0
  61. data/tests/json_encoding_test.rb +107 -0
  62. data/tests/json_ext_parser_test.rb +15 -0
  63. data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +13 -8
  64. data/tests/{test_json_generate.rb → json_generator_test.rb} +134 -39
  65. data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
  66. data/tests/json_parser_test.rb +497 -0
  67. data/tests/json_string_matching_test.rb +38 -0
  68. data/tests/test_helper.rb +17 -0
  69. data/tools/diff.sh +18 -0
  70. data/tools/fuzz.rb +1 -9
  71. metadata +47 -53
  72. data/COPYING +0 -58
  73. data/GPL +0 -340
  74. data/TODO +0 -1
  75. data/data/example.json +0 -1
  76. data/data/index.html +0 -38
  77. data/data/prototype.js +0 -4184
  78. data/tests/fixtures/fail1.json +0 -1
  79. data/tests/setup_variant.rb +0 -11
  80. data/tests/test_json.rb +0 -553
  81. data/tests/test_json_encoding.rb +0 -65
  82. data/tests/test_json_string_matching.rb +0 -39
  83. data/tests/test_json_unicode.rb +0 -72
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
+ # frozen_string_literal: false
3
4
 
4
- require 'test/unit'
5
- require File.join(File.dirname(__FILE__), 'setup_variant')
5
+ require 'test_helper'
6
6
 
7
- class TestJSONGenerate < Test::Unit::TestCase
7
+ class JSONGeneratorTest < Test::Unit::TestCase
8
8
  include JSON
9
9
 
10
10
  def setup
@@ -40,25 +40,67 @@ class TestJSONGenerate < Test::Unit::TestCase
40
40
  EOT
41
41
  end
42
42
 
43
+ def silence
44
+ v = $VERBOSE
45
+ $VERBOSE = nil
46
+ yield
47
+ ensure
48
+ $VERBOSE = v
49
+ end
50
+
51
+ def test_remove_const_segv
52
+ stress = GC.stress
53
+ const = JSON::SAFE_STATE_PROTOTYPE.dup
54
+
55
+ bignum_too_long_to_embed_as_string = 1234567890123456789012345
56
+ expect = bignum_too_long_to_embed_as_string.to_s
57
+ GC.stress = true
58
+
59
+ 10.times do |i|
60
+ tmp = bignum_too_long_to_embed_as_string.to_json
61
+ raise "'\#{expect}' is expected, but '\#{tmp}'" unless tmp == expect
62
+ end
63
+
64
+ silence do
65
+ JSON.const_set :SAFE_STATE_PROTOTYPE, nil
66
+ end
67
+
68
+ 10.times do |i|
69
+ assert_raise TypeError do
70
+ bignum_too_long_to_embed_as_string.to_json
71
+ end
72
+ end
73
+ ensure
74
+ GC.stress = stress
75
+ silence do
76
+ JSON.const_set :SAFE_STATE_PROTOTYPE, const
77
+ end
78
+ end if JSON.const_defined?("Ext") && RUBY_ENGINE != 'jruby'
79
+
43
80
  def test_generate
44
81
  json = generate(@hash)
45
- assert_equal(JSON.parse(@json2), JSON.parse(json))
82
+ assert_equal(parse(@json2), parse(json))
46
83
  json = JSON[@hash]
47
- assert_equal(JSON.parse(@json2), JSON.parse(json))
84
+ assert_equal(parse(@json2), parse(json))
48
85
  parsed_json = parse(json)
49
86
  assert_equal(@hash, parsed_json)
50
87
  json = generate({1=>2})
51
88
  assert_equal('{"1":2}', json)
52
89
  parsed_json = parse(json)
53
90
  assert_equal({"1"=>2}, parsed_json)
54
- assert_raise(GeneratorError) { generate(666) }
55
- assert_equal '666', generate(666, :quirks_mode => true)
91
+ assert_equal '666', generate(666)
56
92
  end
57
93
 
58
94
  def test_generate_pretty
95
+ json = pretty_generate({})
96
+ assert_equal(<<'EOT'.chomp, json)
97
+ {
98
+ }
99
+ EOT
59
100
  json = pretty_generate(@hash)
60
- # hashes aren't (insertion) ordered on every ruby implementation assert_equal(@json3, json)
61
- assert_equal(JSON.parse(@json3), JSON.parse(json))
101
+ # hashes aren't (insertion) ordered on every ruby implementation
102
+ # assert_equal(@json3, json)
103
+ assert_equal(parse(@json3), parse(json))
62
104
  parsed_json = parse(json)
63
105
  assert_equal(@hash, parsed_json)
64
106
  json = pretty_generate({1=>2})
@@ -69,8 +111,7 @@ EOT
69
111
  EOT
70
112
  parsed_json = parse(json)
71
113
  assert_equal({"1"=>2}, parsed_json)
72
- assert_raise(GeneratorError) { pretty_generate(666) }
73
- assert_equal '666', pretty_generate(666, :quirks_mode => true)
114
+ assert_equal '666', pretty_generate(666)
74
115
  end
75
116
 
76
117
  def test_generate_custom
@@ -88,30 +129,26 @@ EOT
88
129
 
89
130
  def test_fast_generate
90
131
  json = fast_generate(@hash)
91
- assert_equal(JSON.parse(@json2), JSON.parse(json))
132
+ assert_equal(parse(@json2), parse(json))
92
133
  parsed_json = parse(json)
93
134
  assert_equal(@hash, parsed_json)
94
135
  json = fast_generate({1=>2})
95
136
  assert_equal('{"1":2}', json)
96
137
  parsed_json = parse(json)
97
138
  assert_equal({"1"=>2}, parsed_json)
98
- assert_raise(GeneratorError) { fast_generate(666) }
99
- assert_equal '666', fast_generate(666, :quirks_mode => true)
139
+ assert_equal '666', fast_generate(666)
100
140
  end
101
141
 
102
142
  def test_own_state
103
143
  state = State.new
104
144
  json = generate(@hash, state)
105
- assert_equal(JSON.parse(@json2), JSON.parse(json))
145
+ assert_equal(parse(@json2), parse(json))
106
146
  parsed_json = parse(json)
107
147
  assert_equal(@hash, parsed_json)
108
148
  json = generate({1=>2}, state)
109
149
  assert_equal('{"1":2}', json)
110
150
  parsed_json = parse(json)
111
151
  assert_equal({"1"=>2}, parsed_json)
112
- assert_raise(GeneratorError) { generate(666, state) }
113
- state.quirks_mode = true
114
- assert state.quirks_mode?
115
152
  assert_equal '666', generate(666, state)
116
153
  end
117
154
 
@@ -123,12 +160,12 @@ EOT
123
160
  assert s[:check_circular?]
124
161
  h = { 1=>2 }
125
162
  h[3] = h
126
- assert_raises(JSON::NestingError) { generate(h) }
127
- assert_raises(JSON::NestingError) { generate(h, s) }
163
+ assert_raise(JSON::NestingError) { generate(h) }
164
+ assert_raise(JSON::NestingError) { generate(h, s) }
128
165
  s = JSON.state.new
129
166
  a = [ 1, 2 ]
130
167
  a << a
131
- assert_raises(JSON::NestingError) { generate(a, s) }
168
+ assert_raise(JSON::NestingError) { generate(a, s) }
132
169
  assert s.check_circular?
133
170
  assert s[:check_circular?]
134
171
  end
@@ -140,8 +177,8 @@ EOT
140
177
  :array_nl => "\n",
141
178
  :ascii_only => false,
142
179
  :buffer_initial_length => 1024,
143
- :quirks_mode => false,
144
180
  :depth => 0,
181
+ :escape_slash => false,
145
182
  :indent => " ",
146
183
  :max_nesting => 100,
147
184
  :object_nl => "\n",
@@ -157,8 +194,8 @@ EOT
157
194
  :array_nl => "",
158
195
  :ascii_only => false,
159
196
  :buffer_initial_length => 1024,
160
- :quirks_mode => false,
161
197
  :depth => 0,
198
+ :escape_slash => false,
162
199
  :indent => "",
163
200
  :max_nesting => 100,
164
201
  :object_nl => "",
@@ -174,8 +211,8 @@ EOT
174
211
  :array_nl => "",
175
212
  :ascii_only => false,
176
213
  :buffer_initial_length => 1024,
177
- :quirks_mode => false,
178
214
  :depth => 0,
215
+ :escape_slash => false,
179
216
  :indent => "",
180
217
  :max_nesting => 0,
181
218
  :object_nl => "",
@@ -185,34 +222,34 @@ EOT
185
222
  end
186
223
 
187
224
  def test_allow_nan
188
- assert_raises(GeneratorError) { generate([JSON::NaN]) }
225
+ assert_raise(GeneratorError) { generate([JSON::NaN]) }
189
226
  assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
190
- assert_raises(GeneratorError) { fast_generate([JSON::NaN]) }
191
- assert_raises(GeneratorError) { pretty_generate([JSON::NaN]) }
227
+ assert_raise(GeneratorError) { fast_generate([JSON::NaN]) }
228
+ assert_raise(GeneratorError) { pretty_generate([JSON::NaN]) }
192
229
  assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true)
193
- assert_raises(GeneratorError) { generate([JSON::Infinity]) }
230
+ assert_raise(GeneratorError) { generate([JSON::Infinity]) }
194
231
  assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true)
195
- assert_raises(GeneratorError) { fast_generate([JSON::Infinity]) }
196
- assert_raises(GeneratorError) { pretty_generate([JSON::Infinity]) }
232
+ assert_raise(GeneratorError) { fast_generate([JSON::Infinity]) }
233
+ assert_raise(GeneratorError) { pretty_generate([JSON::Infinity]) }
197
234
  assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true)
198
- assert_raises(GeneratorError) { generate([JSON::MinusInfinity]) }
235
+ assert_raise(GeneratorError) { generate([JSON::MinusInfinity]) }
199
236
  assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true)
200
- assert_raises(GeneratorError) { fast_generate([JSON::MinusInfinity]) }
201
- assert_raises(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
237
+ assert_raise(GeneratorError) { fast_generate([JSON::MinusInfinity]) }
238
+ assert_raise(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
202
239
  assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true)
203
240
  end
204
241
 
205
242
  def test_depth
206
243
  ary = []; ary << ary
207
244
  assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
208
- assert_raises(JSON::NestingError) { JSON.generate(ary) }
245
+ assert_raise(JSON::NestingError) { generate(ary) }
209
246
  assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
210
247
  assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
211
- assert_raises(JSON::NestingError) { JSON.pretty_generate(ary) }
248
+ assert_raise(JSON::NestingError) { JSON.pretty_generate(ary) }
212
249
  assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
213
250
  s = JSON.state.new
214
251
  assert_equal 0, s.depth
215
- assert_raises(JSON::NestingError) { ary.to_json(s) }
252
+ assert_raise(JSON::NestingError) { ary.to_json(s) }
216
253
  assert_equal 100, s.depth
217
254
  end
218
255
 
@@ -285,12 +322,13 @@ EOT
285
322
  if defined?(JSON::Ext::Generator)
286
323
  def test_broken_bignum # [ruby-core:38867]
287
324
  pid = fork do
288
- Bignum.class_eval do
325
+ x = 1 << 64
326
+ x.class.class_eval do
289
327
  def to_s
290
328
  end
291
329
  end
292
330
  begin
293
- JSON::Ext::Generator::State.new.generate(1<<64)
331
+ JSON::Ext::Generator::State.new.generate(x)
294
332
  exit 1
295
333
  rescue TypeError
296
334
  exit 0
@@ -331,7 +369,64 @@ EOT
331
369
 
332
370
  def test_json_generate
333
371
  assert_raise JSON::GeneratorError do
334
- assert_equal true, JSON.generate(["\xea"])
372
+ assert_equal true, generate(["\xea"])
373
+ end
374
+ end
375
+
376
+ def test_nesting
377
+ too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
378
+ too_deep_ary = eval too_deep
379
+ assert_raise(JSON::NestingError) { generate too_deep_ary }
380
+ assert_raise(JSON::NestingError) { generate too_deep_ary, :max_nesting => 100 }
381
+ ok = generate too_deep_ary, :max_nesting => 101
382
+ assert_equal too_deep, ok
383
+ ok = generate too_deep_ary, :max_nesting => nil
384
+ assert_equal too_deep, ok
385
+ ok = generate too_deep_ary, :max_nesting => false
386
+ assert_equal too_deep, ok
387
+ ok = generate too_deep_ary, :max_nesting => 0
388
+ assert_equal too_deep, ok
389
+ end
390
+
391
+ def test_backslash
392
+ data = [ '\\.(?i:gif|jpe?g|png)$' ]
393
+ json = '["\\\\.(?i:gif|jpe?g|png)$"]'
394
+ assert_equal json, generate(data)
395
+ #
396
+ data = [ '\\"' ]
397
+ json = '["\\\\\""]'
398
+ assert_equal json, generate(data)
399
+ #
400
+ data = [ '/' ]
401
+ json = '["/"]'
402
+ assert_equal json, generate(data)
403
+ #
404
+ data = [ '/' ]
405
+ json = '["\/"]'
406
+ assert_equal json, generate(data, :escape_slash => true)
407
+ #
408
+ data = ['"']
409
+ json = '["\""]'
410
+ assert_equal json, generate(data)
411
+ #
412
+ data = ["'"]
413
+ json = '["\\\'"]'
414
+ assert_equal '["\'"]', generate(data)
415
+ end
416
+
417
+ def test_string_subclass
418
+ s = Class.new(String) do
419
+ def to_s; self; end
420
+ undef to_json
421
+ end
422
+ assert_nothing_raised(SystemStackError) do
423
+ assert_equal '["foo"]', JSON.generate([s.new('foo')])
424
+ end
425
+ end
426
+
427
+ if defined?(Encoding)
428
+ def test_nonutf8_encoding
429
+ assert_equal("\"5\u{b0}\"", "5\xb0".force_encoding("iso-8859-1").to_json)
335
430
  end
336
431
  end
337
432
  end
@@ -1,9 +1,7 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
1
+ #frozen_string_literal: false
2
+ require 'test_helper'
3
3
 
4
- require 'test/unit'
5
- require File.join(File.dirname(__FILE__), 'setup_variant')
6
- class TestJSONGenericObject < Test::Unit::TestCase
4
+ class JSONGenericObjectTest < Test::Unit::TestCase
7
5
  include JSON
8
6
 
9
7
  def setup
@@ -26,11 +24,20 @@ class TestJSONGenericObject < Test::Unit::TestCase
26
24
  end
27
25
 
28
26
  def test_parse_json
29
- assert_kind_of Hash, JSON('{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }', :create_additions => true)
27
+ assert_kind_of Hash,
28
+ JSON(
29
+ '{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }',
30
+ :create_additions => true
31
+ )
30
32
  switch_json_creatable do
31
- assert_equal @go, l = JSON('{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }', :create_additions => true)
33
+ assert_equal @go, l =
34
+ JSON(
35
+ '{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }',
36
+ :create_additions => true
37
+ )
32
38
  assert_equal 1, l.a
33
- assert_equal @go, l = JSON('{ "a": 1, "b": 2 }', :object_class => GenericObject)
39
+ assert_equal @go,
40
+ l = JSON('{ "a": 1, "b": 2 }', :object_class => GenericObject)
34
41
  assert_equal 1, l.a
35
42
  assert_equal GenericObject[:a => GenericObject[:b => 2]],
36
43
  l = JSON('{ "a": { "b": 2 } }', :object_class => GenericObject)