json 2.15.2 → 2.17.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b883349b3a8a8c1ccb003e74779a577e3a16e8c3d8541693fb477a78aeac3a68
4
- data.tar.gz: efb11cf9e69ece0ebb11d33aec23401b0c1ed1d7a39c351f82998ba82cbd47b8
3
+ metadata.gz: a35454680e80a622fb539155325b2f693e90b352aad3f24b7f9eafc5ca797963
4
+ data.tar.gz: 9eee4f7ce5348a1eb44100766d5a7b326a4e76691fbfd3db8a2410020fb75ec1
5
5
  SHA512:
6
- metadata.gz: f78e23c6bd8b8dcddaaf051d6ae60253fd6c96e108395b475d825d9daf3fba4f754f280ae095f456ee67917dd991c8477caa86038f378f23d49e17744467cb7a
7
- data.tar.gz: 64946a58a223efb1e333ff15eba3776d44505cfb78ba0102350177b6351f4643107db5f37ddb65c41569b4d58b5147176c8043b182abd152c74c63351be958fd
6
+ metadata.gz: 0771fad39331fe9d47dbd855a02f662053a79ff08679c8bc76855dcfd3edbcdb32746cc0db435e6ea14815eacdbe97bf1152b704eacb7ddf1423917eb2545923
7
+ data.tar.gz: 742dc87f4cc0306e613cfb65824aaee600aa53f0715135190ffaa4ca1f25aa6820a10b1860befcf90f3dcf6676bd5bb304f0e2858ec1e5933f66b089fca82e78
data/CHANGES.md CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  ### Unreleased
4
4
 
5
+ ### 2025-12-03 (2.17.0)
6
+
7
+ * Improve `JSON.load` and `JSON.unsafe_load` to allow passing options as second argument.
8
+ * Fix the parser to no longer ignore invalid escapes in strings.
9
+ Only `\"`, `\\`, `\b`, `\f`, `\n`, `\r`, `\t` and `\u` are valid JSON escapes.
10
+ * Fixed `JSON::Coder` to use the depth it was initialized with.
11
+ * On TruffleRuby, fix the generator to not call `to_json` on the return value of `as_json` for `Float::NAN`.
12
+ * Fixed handling of `state.depth`: when `to_json` changes `state.depth` but does not restore it, it is reset
13
+ automatically to its initial value.
14
+ In particular, when a `NestingError` is raised, `depth` is no longer equal to `max_nesting` after the call to
15
+ generate, and is reset to its initial value. Similarly when `to_json` raises an exception.
16
+
17
+ ### 2025-11-07 (2.16.0)
18
+
19
+ * Deprecate `JSON::State#[]` and `JSON::State#[]=`. Consider using `JSON::Coder` instead.
20
+ * `JSON::Coder` now also yields to the block when encountering strings with invalid encoding.
21
+ * Fix GeneratorError messages to be UTF-8 encoded.
22
+ * Fix memory leak when `Exception` is raised, or `throw` is used during JSON generation.
23
+ * Optimized floating point number parsing by integrating the ryu algorithm (thanks to Josef Šimánek).
24
+ * Optimized numbers parsing using SWAR (thanks to Scott Myron).
25
+ * Optimized parsing of pretty printed documents using SWAR (thanks to Scott Myron).
26
+
5
27
  ### 2025-10-25 (2.15.2)
6
28
 
7
29
  * Fix `JSON::Coder` to have one dedicated depth counter per invocation.
data/LEGAL CHANGED
@@ -6,3 +6,15 @@
6
6
  All the files in this distribution are covered under either the Ruby's
7
7
  license (see the file COPYING) or public-domain except some files
8
8
  mentioned below.
9
+
10
+ ext/json/ext/vendor/fpconv.h::
11
+ This file is adapted from https://github.com/night-shift/fpconv
12
+ It is licensed under Boost Software License 1.0.
13
+
14
+ ext/json/ext/vendor/jeaiii-ltoa.h::
15
+ This file is adapted from https://github.com/jeaiii/itoa
16
+ It is licensed under the MIT License
17
+
18
+ ext/json/ext/vendor/ryu.h::
19
+ This file is adapted from the Ryu algorithm by Ulf Adams https://github.com/ulfjack/ryu.
20
+ It is dual-licensed under Apache License 2.0 OR Boost Software License 1.0.
data/README.md CHANGED
@@ -113,7 +113,23 @@ puts MyApp::API_JSON_CODER.dump(Time.now.utc) # => "2025-01-21T08:41:44.286Z"
113
113
  The provided block is called for all objects that don't have a native JSON equivalent, and
114
114
  must return a Ruby object that has a native JSON equivalent.
115
115
 
116
- It is also called for objects that do have a JSON equivalent, but are used as Hash keys, for instance `{ 1 => 2}`.
116
+ It is also called for objects that do have a JSON equivalent, but are used as Hash keys, for instance `{ 1 => 2}`,
117
+ as well as for strings that aren't valid UTF-8:
118
+
119
+ ```ruby
120
+ coder = JSON::Combining.new do |object, is_object_key|
121
+ case object
122
+ when String
123
+ if !string.valid_encoding? || string.encoding != Encoding::UTF_8
124
+ Base64.encode64(string)
125
+ else
126
+ string
127
+ end
128
+ else
129
+ object
130
+ end
131
+ end
132
+ ```
117
133
 
118
134
  ## Combining JSON fragments
119
135
 
@@ -1,55 +1,9 @@
1
1
  #ifndef _FBUFFER_H_
2
2
  #define _FBUFFER_H_
3
3
 
4
- #include "ruby.h"
5
- #include "ruby/encoding.h"
4
+ #include "../json.h"
6
5
  #include "../vendor/jeaiii-ltoa.h"
7
6
 
8
- /* shims */
9
- /* This is the fallback definition from Ruby 3.4 */
10
-
11
- #ifndef RBIMPL_STDBOOL_H
12
- #if defined(__cplusplus)
13
- # if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L)
14
- # include <cstdbool>
15
- # endif
16
- #elif defined(HAVE_STDBOOL_H)
17
- # include <stdbool.h>
18
- #elif !defined(HAVE__BOOL)
19
- typedef unsigned char _Bool;
20
- # define bool _Bool
21
- # define true ((_Bool)+1)
22
- # define false ((_Bool)+0)
23
- # define __bool_true_false_are_defined
24
- #endif
25
- #endif
26
-
27
- #ifndef NOINLINE
28
- #if defined(__has_attribute) && __has_attribute(noinline)
29
- #define NOINLINE() __attribute__((noinline))
30
- #else
31
- #define NOINLINE()
32
- #endif
33
- #endif
34
-
35
- #ifndef RB_UNLIKELY
36
- #define RB_UNLIKELY(expr) expr
37
- #endif
38
-
39
- #ifndef RB_LIKELY
40
- #define RB_LIKELY(expr) expr
41
- #endif
42
-
43
- #ifndef MAYBE_UNUSED
44
- # define MAYBE_UNUSED(x) x
45
- #endif
46
-
47
- #ifdef RUBY_DEBUG
48
- #ifndef JSON_DEBUG
49
- #define JSON_DEBUG RUBY_DEBUG
50
- #endif
51
- #endif
52
-
53
7
  enum fbuffer_type {
54
8
  FBUFFER_HEAP_ALLOCATED = 0,
55
9
  FBUFFER_STACK_ALLOCATED = 1,
@@ -60,7 +14,7 @@ typedef struct FBufferStruct {
60
14
  unsigned long initial_length;
61
15
  unsigned long len;
62
16
  unsigned long capa;
63
- #ifdef JSON_DEBUG
17
+ #if JSON_DEBUG
64
18
  unsigned long requested;
65
19
  #endif
66
20
  char *ptr;
@@ -91,14 +45,14 @@ static void fbuffer_stack_init(FBuffer *fb, unsigned long initial_length, char *
91
45
  fb->ptr = stack_buffer;
92
46
  fb->capa = stack_buffer_size;
93
47
  }
94
- #ifdef JSON_DEBUG
48
+ #if JSON_DEBUG
95
49
  fb->requested = 0;
96
50
  #endif
97
51
  }
98
52
 
99
53
  static inline void fbuffer_consumed(FBuffer *fb, unsigned long consumed)
100
54
  {
101
- #ifdef JSON_DEBUG
55
+ #if JSON_DEBUG
102
56
  if (consumed > fb->requested) {
103
57
  rb_bug("fbuffer: Out of bound write");
104
58
  }
@@ -168,7 +122,7 @@ static void fbuffer_do_inc_capa(FBuffer *fb, unsigned long requested)
168
122
 
169
123
  static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
170
124
  {
171
- #ifdef JSON_DEBUG
125
+ #if JSON_DEBUG
172
126
  fb->requested = requested;
173
127
  #endif
174
128
 
@@ -194,7 +148,7 @@ static inline void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long
194
148
  /* Appends a character into a buffer. The buffer needs to have sufficient capacity, via fbuffer_inc_capa(...). */
195
149
  static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr)
196
150
  {
197
- #ifdef JSON_DEBUG
151
+ #if JSON_DEBUG
198
152
  if (fb->requested < 1) {
199
153
  rb_bug("fbuffer: unreserved write");
200
154
  }
@@ -220,7 +174,7 @@ static void fbuffer_append_str_repeat(FBuffer *fb, VALUE str, size_t repeat)
220
174
 
221
175
  fbuffer_inc_capa(fb, repeat * len);
222
176
  while (repeat) {
223
- #ifdef JSON_DEBUG
177
+ #if JSON_DEBUG
224
178
  fb->requested = len;
225
179
  #endif
226
180
  fbuffer_append_reserved(fb, newstr, len);
@@ -283,14 +237,11 @@ static VALUE fbuffer_finalize(FBuffer *fb)
283
237
  {
284
238
  if (fb->io) {
285
239
  fbuffer_flush(fb);
286
- fbuffer_free(fb);
287
240
  rb_io_flush(fb->io);
288
241
  return fb->io;
289
242
  } else {
290
- VALUE result = rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
291
- fbuffer_free(fb);
292
- return result;
243
+ return rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
293
244
  }
294
245
  }
295
246
 
296
- #endif
247
+ #endif // _FBUFFER_H_
@@ -6,7 +6,7 @@ if RUBY_ENGINE == 'truffleruby'
6
6
  else
7
7
  append_cflags("-std=c99")
8
8
  $defs << "-DJSON_GENERATOR"
9
- $defs << "-DJSON_DEBUG" if ENV["JSON_DEBUG"]
9
+ $defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"
10
10
 
11
11
  if enable_config('generator-use-simd', default=!ENV["JSON_DISABLE_SIMD"])
12
12
  load __dir__ + "/../simd/conf.rb"