diff --git a/CHANGES.md b/CHANGES.md index 3f455f7c4..13c5e0631 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,9 @@ ### Unreleased +* Emit a deprecation warning for the outdated `quirks_mode: true` argument. +* Emit a deprecation for `JSON.dump` positional `limit` argument. + ### 2026-07-31 (2.21.2) * Fix a use-after-free bug in `JSON::ResumableParser`. [GHSA-9hj4-r449-hfvc][CVE-2026-71847]. diff --git a/lib/json/common.rb b/lib/json/common.rb index fdcb860db..271f2460d 100644 --- a/lib/json/common.rb +++ b/lib/json/common.rb @@ -360,6 +360,9 @@ def to_json(state = nil, *) # JSON.parse('') # def parse(source, opts = nil) + if opts&.key?(:quirks_mode) + deprecation_warning("The `quirks_mode` option was removed since json 2.0 and has no effect. It will raise an error on json 3.0") + end opts = ParserOptions.prepare(opts) unless opts.nil? Parser.parse(source, opts) end @@ -451,6 +454,9 @@ def generate(obj, opts = nil) if State === opts opts.generate(obj) else + if opts&.key?(:quirks_mode) + deprecation_warning("The `quirks_mode` option was removed since json 2.0 and has no effect. It will raise an error on json 3.0") + end State.generate(obj, opts, nil) end end @@ -960,7 +966,14 @@ def dump(obj, anIO = nil, limit = nil, kwargs = nil) end opts = JSON._dump_default_options - opts = opts.merge(:max_nesting => limit) if limit + if limit + if RUBY_VERSION >= "3.0" + warn "JSON.dump's positional `limit` argument is deprecated and will be removed in json 3.0.0. Pass `max_nesting:` instead.", uplevel: 1, category: :deprecated + else + warn "JSON.dump's positional `limit` argument is deprecated and will be removed in json 3.0.0. Pass `max_nesting:` instead.", uplevel: 1 + end + opts = opts.merge(:max_nesting => limit) + end opts = opts.merge(kwargs) if kwargs begin diff --git a/test/json/json_common_interface_test.rb b/test/json/json_common_interface_test.rb index 37568b556..ac0d9a150 100644 --- a/test/json/json_common_interface_test.rb +++ b/test/json/json_common_interface_test.rb @@ -241,21 +241,37 @@ def test_dump obj = eval(too_deep) assert_equal too_deep, dump(obj) assert_kind_of String, Marshal.dump(obj) - assert_raise(ArgumentError) { dump(obj, 100) } + assert_deprecated_warning(/max_nesting/) do + assert_raise(ArgumentError) { dump(obj, 100) } + end assert_raise(ArgumentError) { Marshal.dump(obj, 100) } - assert_equal too_deep, dump(obj, 101) + assert_deprecated_warning(/max_nesting/) do + assert_equal too_deep, dump(obj, 101) + end assert_kind_of String, Marshal.dump(obj, 101) - assert_equal too_deep, JSON.dump(obj, StringIO.new, 101, strict: false).string - assert_equal too_deep, dump(obj, StringIO.new, 101, strict: false).string - assert_raise(JSON::GeneratorError) { JSON.dump(Object.new, StringIO.new, 101, strict: true).string } - assert_raise(JSON::GeneratorError) { dump(Object.new, StringIO.new, 101, strict: true).string } + assert_deprecated_warning(/max_nesting/) do + assert_equal too_deep, JSON.dump(obj, StringIO.new, 101, strict: false).string + end + assert_deprecated_warning(/max_nesting/) do + assert_equal too_deep, dump(obj, StringIO.new, 101, strict: false).string + end + assert_deprecated_warning(/max_nesting/) do + assert_raise(JSON::GeneratorError) { JSON.dump(Object.new, StringIO.new, 101, strict: true).string } + end + assert_deprecated_warning(/max_nesting/) do + assert_raise(JSON::GeneratorError) { dump(Object.new, StringIO.new, 101, strict: true).string } + end assert_equal too_deep, dump(obj, nil, nil, strict: false) - assert_equal too_deep, dump(obj, nil, 101, strict: false) + assert_deprecated_warning(/max_nesting/) do + assert_equal too_deep, dump(obj, nil, 101, strict: false) + end assert_equal too_deep, dump(obj, StringIO.new, nil, strict: false).string assert_equal too_deep, dump(obj, nil, strict: false) - assert_equal too_deep, dump(obj, 101, strict: false) + assert_deprecated_warning(/max_nesting/) do + assert_equal too_deep, dump(obj, 101, strict: false) + end assert_equal too_deep, dump(obj, StringIO.new, strict: false).string assert_equal too_deep, dump(obj, strict: false) end