json 2.5.1 → 2.6.0

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/CHANGES.md +5 -5
  3. data/README.md +3 -3
  4. data/VERSION +1 -1
  5. data/ext/json/ext/generator/generator.c +1 -11
  6. data/ext/json/ext/parser/extconf.rb +1 -0
  7. data/ext/json/ext/parser/parser.c +2972 -1813
  8. data/ext/json/ext/parser/parser.h +5 -1
  9. data/ext/json/ext/parser/parser.rl +66 -28
  10. data/json.gemspec +2 -8
  11. data/lib/json/pure/parser.rb +1 -1
  12. data/lib/json/version.rb +1 -1
  13. data/lib/json.rb +1 -1
  14. metadata +6 -87
  15. data/Gemfile +0 -14
  16. data/lib/json/ext/.keep +0 -0
  17. data/tests/fixtures/fail10.json +0 -1
  18. data/tests/fixtures/fail11.json +0 -1
  19. data/tests/fixtures/fail12.json +0 -1
  20. data/tests/fixtures/fail13.json +0 -1
  21. data/tests/fixtures/fail14.json +0 -1
  22. data/tests/fixtures/fail18.json +0 -1
  23. data/tests/fixtures/fail19.json +0 -1
  24. data/tests/fixtures/fail2.json +0 -1
  25. data/tests/fixtures/fail20.json +0 -1
  26. data/tests/fixtures/fail21.json +0 -1
  27. data/tests/fixtures/fail22.json +0 -1
  28. data/tests/fixtures/fail23.json +0 -1
  29. data/tests/fixtures/fail24.json +0 -1
  30. data/tests/fixtures/fail25.json +0 -1
  31. data/tests/fixtures/fail27.json +0 -2
  32. data/tests/fixtures/fail28.json +0 -2
  33. data/tests/fixtures/fail29.json +0 -1
  34. data/tests/fixtures/fail3.json +0 -1
  35. data/tests/fixtures/fail30.json +0 -1
  36. data/tests/fixtures/fail31.json +0 -1
  37. data/tests/fixtures/fail32.json +0 -1
  38. data/tests/fixtures/fail4.json +0 -1
  39. data/tests/fixtures/fail5.json +0 -1
  40. data/tests/fixtures/fail6.json +0 -1
  41. data/tests/fixtures/fail7.json +0 -1
  42. data/tests/fixtures/fail8.json +0 -1
  43. data/tests/fixtures/fail9.json +0 -1
  44. data/tests/fixtures/obsolete_fail1.json +0 -1
  45. data/tests/fixtures/pass1.json +0 -56
  46. data/tests/fixtures/pass15.json +0 -1
  47. data/tests/fixtures/pass16.json +0 -1
  48. data/tests/fixtures/pass17.json +0 -1
  49. data/tests/fixtures/pass2.json +0 -1
  50. data/tests/fixtures/pass26.json +0 -1
  51. data/tests/fixtures/pass3.json +0 -6
  52. data/tests/json_addition_test.rb +0 -199
  53. data/tests/json_common_interface_test.rb +0 -169
  54. data/tests/json_encoding_test.rb +0 -107
  55. data/tests/json_ext_parser_test.rb +0 -15
  56. data/tests/json_fixtures_test.rb +0 -40
  57. data/tests/json_generator_test.rb +0 -399
  58. data/tests/json_generic_object_test.rb +0 -82
  59. data/tests/json_parser_test.rb +0 -497
  60. data/tests/json_string_matching_test.rb +0 -38
  61. data/tests/lib/core_assertions.rb +0 -763
  62. data/tests/lib/envutil.rb +0 -365
  63. data/tests/lib/find_executable.rb +0 -22
  64. data/tests/lib/helper.rb +0 -4
  65. data/tests/ractor_test.rb +0 -30
  66. data/tests/test_helper.rb +0 -17
data/tests/lib/envutil.rb DELETED
@@ -1,365 +0,0 @@
1
- # -*- coding: us-ascii -*-
2
- # frozen_string_literal: true
3
- require "open3"
4
- require "timeout"
5
- require_relative "find_executable"
6
- begin
7
- require 'rbconfig'
8
- rescue LoadError
9
- end
10
- begin
11
- require "rbconfig/sizeof"
12
- rescue LoadError
13
- end
14
-
15
- module EnvUtil
16
- def rubybin
17
- if ruby = ENV["RUBY"]
18
- return ruby
19
- end
20
- ruby = "ruby"
21
- exeext = RbConfig::CONFIG["EXEEXT"]
22
- rubyexe = (ruby + exeext if exeext and !exeext.empty?)
23
- 3.times do
24
- if File.exist? ruby and File.executable? ruby and !File.directory? ruby
25
- return File.expand_path(ruby)
26
- end
27
- if rubyexe and File.exist? rubyexe and File.executable? rubyexe
28
- return File.expand_path(rubyexe)
29
- end
30
- ruby = File.join("..", ruby)
31
- end
32
- if defined?(RbConfig.ruby)
33
- RbConfig.ruby
34
- else
35
- "ruby"
36
- end
37
- end
38
- module_function :rubybin
39
-
40
- LANG_ENVS = %w"LANG LC_ALL LC_CTYPE"
41
-
42
- DEFAULT_SIGNALS = Signal.list
43
- DEFAULT_SIGNALS.delete("TERM") if /mswin|mingw/ =~ RUBY_PLATFORM
44
-
45
- RUBYLIB = ENV["RUBYLIB"]
46
-
47
- class << self
48
- attr_accessor :timeout_scale
49
- attr_reader :original_internal_encoding, :original_external_encoding,
50
- :original_verbose, :original_warning
51
-
52
- def capture_global_values
53
- @original_internal_encoding = Encoding.default_internal
54
- @original_external_encoding = Encoding.default_external
55
- @original_verbose = $VERBOSE
56
- @original_warning = %i[deprecated experimental].to_h {|i| [i, Warning[i]]} if RUBY_VERSION > "2.7"
57
- end
58
- end
59
-
60
- def apply_timeout_scale(t)
61
- if scale = EnvUtil.timeout_scale
62
- t * scale
63
- else
64
- t
65
- end
66
- end
67
- module_function :apply_timeout_scale
68
-
69
- def timeout(sec, klass = nil, message = nil, &blk)
70
- return yield(sec) if sec == nil or sec.zero?
71
- sec = apply_timeout_scale(sec)
72
- Timeout.timeout(sec, klass, message, &blk)
73
- end
74
- module_function :timeout
75
-
76
- def terminate(pid, signal = :TERM, pgroup = nil, reprieve = 1)
77
- reprieve = apply_timeout_scale(reprieve) if reprieve
78
-
79
- signals = Array(signal).select do |sig|
80
- DEFAULT_SIGNALS[sig.to_s] or
81
- DEFAULT_SIGNALS[Signal.signame(sig)] rescue false
82
- end
83
- signals |= [:ABRT, :KILL]
84
- case pgroup
85
- when 0, true
86
- pgroup = -pid
87
- when nil, false
88
- pgroup = pid
89
- end
90
-
91
- lldb = true if /darwin/ =~ RUBY_PLATFORM
92
-
93
- while signal = signals.shift
94
-
95
- if lldb and [:ABRT, :KILL].include?(signal)
96
- lldb = false
97
- # sudo -n: --non-interactive
98
- # lldb -p: attach
99
- # -o: run command
100
- system(*%W[sudo -n lldb -p #{pid} --batch -o bt\ all -o call\ rb_vmdebug_stack_dump_all_threads() -o quit])
101
- true
102
- end
103
-
104
- begin
105
- Process.kill signal, pgroup
106
- rescue Errno::EINVAL
107
- next
108
- rescue Errno::ESRCH
109
- break
110
- end
111
- if signals.empty? or !reprieve
112
- Process.wait(pid)
113
- else
114
- begin
115
- Timeout.timeout(reprieve) {Process.wait(pid)}
116
- rescue Timeout::Error
117
- else
118
- break
119
- end
120
- end
121
- end
122
- $?
123
- end
124
- module_function :terminate
125
-
126
- def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = false,
127
- encoding: nil, timeout: 10, reprieve: 1, timeout_error: Timeout::Error,
128
- stdout_filter: nil, stderr_filter: nil,
129
- signal: :TERM,
130
- rubybin: EnvUtil.rubybin, precommand: nil,
131
- **opt)
132
- timeout = apply_timeout_scale(timeout)
133
-
134
- in_c, in_p = IO.pipe
135
- out_p, out_c = IO.pipe if capture_stdout
136
- err_p, err_c = IO.pipe if capture_stderr && capture_stderr != :merge_to_stdout
137
- opt[:in] = in_c
138
- opt[:out] = out_c if capture_stdout
139
- opt[:err] = capture_stderr == :merge_to_stdout ? out_c : err_c if capture_stderr
140
- if encoding
141
- out_p.set_encoding(encoding) if out_p
142
- err_p.set_encoding(encoding) if err_p
143
- end
144
- c = "C"
145
- child_env = {}
146
- LANG_ENVS.each {|lc| child_env[lc] = c}
147
- if Array === args and Hash === args.first
148
- child_env.update(args.shift)
149
- end
150
- if RUBYLIB and lib = child_env["RUBYLIB"]
151
- child_env["RUBYLIB"] = [lib, RUBYLIB].join(File::PATH_SEPARATOR)
152
- end
153
- child_env['ASAN_OPTIONS'] = ENV['ASAN_OPTIONS'] if ENV['ASAN_OPTIONS']
154
- args = [args] if args.kind_of?(String)
155
- pid = spawn(child_env, *precommand, rubybin, *args, **opt)
156
- in_c.close
157
- out_c&.close
158
- out_c = nil
159
- err_c&.close
160
- err_c = nil
161
- if block_given?
162
- return yield in_p, out_p, err_p, pid
163
- else
164
- th_stdout = Thread.new { out_p.read } if capture_stdout
165
- th_stderr = Thread.new { err_p.read } if capture_stderr && capture_stderr != :merge_to_stdout
166
- in_p.write stdin_data.to_str unless stdin_data.empty?
167
- in_p.close
168
- if (!th_stdout || th_stdout.join(timeout)) && (!th_stderr || th_stderr.join(timeout))
169
- timeout_error = nil
170
- else
171
- status = terminate(pid, signal, opt[:pgroup], reprieve)
172
- terminated = Time.now
173
- end
174
- stdout = th_stdout.value if capture_stdout
175
- stderr = th_stderr.value if capture_stderr && capture_stderr != :merge_to_stdout
176
- out_p.close if capture_stdout
177
- err_p.close if capture_stderr && capture_stderr != :merge_to_stdout
178
- status ||= Process.wait2(pid)[1]
179
- stdout = stdout_filter.call(stdout) if stdout_filter
180
- stderr = stderr_filter.call(stderr) if stderr_filter
181
- if timeout_error
182
- bt = caller_locations
183
- msg = "execution of #{bt.shift.label} expired timeout (#{timeout} sec)"
184
- msg = failure_description(status, terminated, msg, [stdout, stderr].join("\n"))
185
- raise timeout_error, msg, bt.map(&:to_s)
186
- end
187
- return stdout, stderr, status
188
- end
189
- ensure
190
- [th_stdout, th_stderr].each do |th|
191
- th.kill if th
192
- end
193
- [in_c, in_p, out_c, out_p, err_c, err_p].each do |io|
194
- io&.close
195
- end
196
- [th_stdout, th_stderr].each do |th|
197
- th.join if th
198
- end
199
- end
200
- module_function :invoke_ruby
201
-
202
- def verbose_warning
203
- class << (stderr = "".dup)
204
- alias write concat
205
- def flush; end
206
- end
207
- stderr, $stderr = $stderr, stderr
208
- $VERBOSE = true
209
- yield stderr
210
- return $stderr
211
- ensure
212
- stderr, $stderr = $stderr, stderr
213
- $VERBOSE = EnvUtil.original_verbose
214
- EnvUtil.original_warning.each {|i, v| Warning[i] = v}
215
- end
216
- module_function :verbose_warning
217
-
218
- def default_warning
219
- $VERBOSE = false
220
- yield
221
- ensure
222
- $VERBOSE = EnvUtil.original_verbose
223
- end
224
- module_function :default_warning
225
-
226
- def suppress_warning
227
- $VERBOSE = nil
228
- yield
229
- ensure
230
- $VERBOSE = EnvUtil.original_verbose
231
- end
232
- module_function :suppress_warning
233
-
234
- def under_gc_stress(stress = true)
235
- stress, GC.stress = GC.stress, stress
236
- yield
237
- ensure
238
- GC.stress = stress
239
- end
240
- module_function :under_gc_stress
241
-
242
- def with_default_external(enc)
243
- suppress_warning { Encoding.default_external = enc }
244
- yield
245
- ensure
246
- suppress_warning { Encoding.default_external = EnvUtil.original_external_encoding }
247
- end
248
- module_function :with_default_external
249
-
250
- def with_default_internal(enc)
251
- suppress_warning { Encoding.default_internal = enc }
252
- yield
253
- ensure
254
- suppress_warning { Encoding.default_internal = EnvUtil.original_internal_encoding }
255
- end
256
- module_function :with_default_internal
257
-
258
- def labeled_module(name, &block)
259
- Module.new do
260
- singleton_class.class_eval {
261
- define_method(:to_s) {name}
262
- alias inspect to_s
263
- alias name to_s
264
- }
265
- class_eval(&block) if block
266
- end
267
- end
268
- module_function :labeled_module
269
-
270
- def labeled_class(name, superclass = Object, &block)
271
- Class.new(superclass) do
272
- singleton_class.class_eval {
273
- define_method(:to_s) {name}
274
- alias inspect to_s
275
- alias name to_s
276
- }
277
- class_eval(&block) if block
278
- end
279
- end
280
- module_function :labeled_class
281
-
282
- if /darwin/ =~ RUBY_PLATFORM
283
- DIAGNOSTIC_REPORTS_PATH = File.expand_path("~/Library/Logs/DiagnosticReports")
284
- DIAGNOSTIC_REPORTS_TIMEFORMAT = '%Y-%m-%d-%H%M%S'
285
- @ruby_install_name = RbConfig::CONFIG['RUBY_INSTALL_NAME']
286
-
287
- def self.diagnostic_reports(signame, pid, now)
288
- return unless %w[ABRT QUIT SEGV ILL TRAP].include?(signame)
289
- cmd = File.basename(rubybin)
290
- cmd = @ruby_install_name if "ruby-runner#{RbConfig::CONFIG["EXEEXT"]}" == cmd
291
- path = DIAGNOSTIC_REPORTS_PATH
292
- timeformat = DIAGNOSTIC_REPORTS_TIMEFORMAT
293
- pat = "#{path}/#{cmd}_#{now.strftime(timeformat)}[-_]*.crash"
294
- first = true
295
- 30.times do
296
- first ? (first = false) : sleep(0.1)
297
- Dir.glob(pat) do |name|
298
- log = File.read(name) rescue next
299
- if /\AProcess:\s+#{cmd} \[#{pid}\]$/ =~ log
300
- File.unlink(name)
301
- File.unlink("#{path}/.#{File.basename(name)}.plist") rescue nil
302
- return log
303
- end
304
- end
305
- end
306
- nil
307
- end
308
- else
309
- def self.diagnostic_reports(signame, pid, now)
310
- end
311
- end
312
-
313
- def self.failure_description(status, now, message = "", out = "")
314
- pid = status.pid
315
- if signo = status.termsig
316
- signame = Signal.signame(signo)
317
- sigdesc = "signal #{signo}"
318
- end
319
- log = diagnostic_reports(signame, pid, now)
320
- if signame
321
- sigdesc = "SIG#{signame} (#{sigdesc})"
322
- end
323
- if status.coredump?
324
- sigdesc = "#{sigdesc} (core dumped)"
325
- end
326
- full_message = ''.dup
327
- message = message.call if Proc === message
328
- if message and !message.empty?
329
- full_message << message << "\n"
330
- end
331
- full_message << "pid #{pid}"
332
- full_message << " exit #{status.exitstatus}" if status.exited?
333
- full_message << " killed by #{sigdesc}" if sigdesc
334
- if out and !out.empty?
335
- full_message << "\n" << out.b.gsub(/^/, '| ')
336
- full_message.sub!(/(?<!\n)\z/, "\n")
337
- end
338
- if log
339
- full_message << "Diagnostic reports:\n" << log.b.gsub(/^/, '| ')
340
- end
341
- full_message
342
- end
343
-
344
- def self.gc_stress_to_class?
345
- unless defined?(@gc_stress_to_class)
346
- _, _, status = invoke_ruby(["-e""exit GC.respond_to?(:add_stress_to_class)"])
347
- @gc_stress_to_class = status.success?
348
- end
349
- @gc_stress_to_class
350
- end
351
- end
352
-
353
- if defined?(RbConfig)
354
- module RbConfig
355
- @ruby = EnvUtil.rubybin
356
- class << self
357
- undef ruby if method_defined?(:ruby)
358
- attr_reader :ruby
359
- end
360
- dir = File.dirname(ruby)
361
- CONFIG['bindir'] = dir
362
- end
363
- end
364
-
365
- EnvUtil.capture_global_values
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
- require "rbconfig"
3
-
4
- module EnvUtil
5
- def find_executable(cmd, *args)
6
- exts = RbConfig::CONFIG["EXECUTABLE_EXTS"].split | [RbConfig::CONFIG["EXEEXT"]]
7
- ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
8
- next if path.empty?
9
- path = File.join(path, cmd)
10
- exts.each do |ext|
11
- cmdline = [path + ext, *args]
12
- begin
13
- return cmdline if yield(IO.popen(cmdline, "r", err: [:child, :out], &:read))
14
- rescue
15
- next
16
- end
17
- end
18
- end
19
- nil
20
- end
21
- module_function :find_executable
22
- end
data/tests/lib/helper.rb DELETED
@@ -1,4 +0,0 @@
1
- require "test/unit"
2
- require_relative "core_assertions"
3
-
4
- Test::Unit::TestCase.include Test::Unit::CoreAssertions
data/tests/ractor_test.rb DELETED
@@ -1,30 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: false
3
-
4
- require 'test_helper'
5
-
6
- class JSONInRactorTest < Test::Unit::TestCase
7
- def test_generate
8
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
9
- begin;
10
- $VERBOSE = nil
11
- require "json"
12
- r = Ractor.new do
13
- json = JSON.generate({
14
- 'a' => 2,
15
- 'b' => 3.141,
16
- 'c' => 'c',
17
- 'd' => [ 1, "b", 3.14 ],
18
- 'e' => { 'foo' => 'bar' },
19
- 'g' => "\"\0\037",
20
- 'h' => 1000.0,
21
- 'i' => 0.001
22
- })
23
- JSON.parse(json)
24
- end
25
- expected_json = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},' +
26
- '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
27
- assert_equal(JSON.parse(expected_json), r.take)
28
- end;
29
- end
30
- end if defined?(Ractor)
data/tests/test_helper.rb DELETED
@@ -1,17 +0,0 @@
1
- case ENV['JSON']
2
- when 'pure'
3
- $:.unshift File.join(__dir__, '../lib')
4
- require 'json/pure'
5
- when 'ext'
6
- $:.unshift File.join(__dir__, '../ext'), File.join(__dir__, '../lib')
7
- require 'json/ext'
8
- else
9
- $:.unshift File.join(__dir__, '../ext'), File.join(__dir__, '../lib')
10
- require 'json'
11
- end
12
-
13
- require 'test/unit'
14
- begin
15
- require 'byebug'
16
- rescue LoadError
17
- end