431 Commits

Author SHA1 Message Date
Samuel Williams
68f0150ff0
[ruby/json] Pass through all options if present.
https://github.com/ruby/json/commit/bea96e0a69
2025-02-19 11:04:09 +09:00
Jean Boussier
abcafb080c
[ruby/json] Release 2.10.1
https://github.com/ruby/json/commit/aa5b7d6acb
2025-02-12 13:15:01 +09:00
Jean Boussier
293ad8a4e9
Fix a compatibility issue with MultiJson.dump(obj, pretty: true)
Fix: https://github.com/ruby/json/issues/748

`MultiJson` pass `State#to_h` as options, and the `as_json`
property defaults to `false` but `false` wasn't accepted by
the constructor.
2025-02-12 13:15:01 +09:00
Jean Boussier
502bd6ba37 [ruby/json] Release 2.10.0
https://github.com/ruby/json/commit/8b56d47254
2025-02-12 13:12:12 +09:00
Étienne Barrié
b4bfbcaddc
Optimize Symbol generation in strict mode
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2025-02-06 16:02:03 +09:00
Étienne Barrié
f865148e19
Fix JSON::Coder to call as_json proc for NaN and Infinity
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2025-02-06 16:02:03 +09:00
Jean Boussier
98c56de823 [ruby/json] Refactor further to expose the simpler escape search possible
https://github.com/ruby/json/commit/e03515ac8b
2025-02-03 10:05:26 +09:00
Jean Boussier
98e1c2845a [ruby/json] Refactor convert_UTF8_to_JSON to split searching and escaping code
The goal is to be able to dispatch to more optimized search implementations
without having to duplicate the escaping code.

Somehow, this is a few % faster already:

```
== Encoding activitypub.json (52595 bytes)
ruby 3.4.1 (2024-12-25 revision https://github.com/ruby/json/commit/48d4efcb85) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
               after     2.257k i/100ms
Calculating -------------------------------------
               after     22.930k (± 1.3%) i/s   (43.61 μs/i) -    115.107k in   5.020814s

Comparison:
              before:    21604.0 i/s
               after:    22930.1 i/s - 1.06x  faster

== Encoding citm_catalog.json (500298 bytes)
ruby 3.4.1 (2024-12-25 revision https://github.com/ruby/json/commit/48d4efcb85) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
               after   137.000 i/100ms
Calculating -------------------------------------
               after      1.397k (± 1.1%) i/s  (715.57 μs/i) -      6.987k in   5.000408s

Comparison:
              before:     1344.4 i/s
               after:     1397.5 i/s - 1.04x  faster

== Encoding twitter.json (466906 bytes)
ruby 3.4.1 (2024-12-25 revision https://github.com/ruby/json/commit/48d4efcb85) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
               after   249.000 i/100ms
Calculating -------------------------------------
               after      2.464k (± 1.8%) i/s  (405.81 μs/i) -     12.450k in   5.054131s

Comparison:
              before:     2326.5 i/s
               after:     2464.2 i/s - 1.06x  faster
```

https://github.com/ruby/json/commit/8fb5ae807f
2025-02-03 10:05:25 +09:00
Nobuyoshi Nakada
dc3d2a3c2f
[ruby/json] Avoid plain char for ctype macros
On some platforms ctype functions are defined as macros accesing tables.
A plain char may be `signed` or `unsigned` per implementations and the
extension result implementation dependent.

gcc warns such case:

```
parser.c: In function 'rstring_cache_fetch':
parser.c:138:33: warning: array subscript has type 'char' [-Wchar-subscripts]
  138 |     if (RB_UNLIKELY(!isalpha(str[0]))) {
      |                              ~~~^~~
parser.c: In function 'rsymbol_cache_fetch':
parser.c:190:33: warning: array subscript has type 'char' [-Wchar-subscripts]
  190 |     if (RB_UNLIKELY(!isalpha(str[0]))) {
      |                              ~~~^~~
```

https://github.com/ruby/json/commit/4431b362f6
2025-01-30 16:56:02 +09:00
Edouard CHIN
7f70ef64af
[ruby/json] Few doc tweaks:
- Also modified the gemspec files' blob as the ragel's `parser.rl`
  file was removed in https://github.com/ruby/json/commit/c8d5236a921e

https://github.com/ruby/json/commit/b2b106e314
2025-01-30 16:56:02 +09:00
Étienne Barrié
89e316ad06
Introduce JSON::Coder
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2025-01-28 15:41:47 +09:00
Jean Boussier
53cf2170f9 [ruby/json] Update gemspec URIs
https://github.com/ruby/json/commit/edd61b4a8b
2025-01-28 15:39:17 +09:00
Jean Boussier
77af41ea65 [ruby/json] Add some JSON::Fragment documentation
https://github.com/ruby/json/commit/dbcf614e50
2025-01-28 15:39:17 +09:00
tompng
86b262179d [ruby/json] Reject invalid number: - -.1 -e0
https://github.com/ruby/json/commit/b9bfeecfa9
2025-01-20 14:20:55 +01:00
tompng
525d7a68e4 [ruby/json] Raise parse error on invalid comments
https://github.com/ruby/json/commit/2f57f40467
2025-01-20 14:20:55 +01:00
tompng
c026e44bb5 [ruby/json] Fix parsing incomplete unicode escape "\uaaa"
https://github.com/ruby/json/commit/86c0d4eb7e
2025-01-20 14:20:55 +01:00
Jean Boussier
2b4b7bdb10 [ruby/json] Fix JSON::Fragment#to_json signature
https://github.com/ruby/json/commit/f8817fe56c
2025-01-20 14:20:55 +01:00
Étienne Barrié
e8676cada8 [ruby/json] Introduce JSON::Fragment
https://github.com/ruby/json/commit/9e3500f345

Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2025-01-20 14:20:55 +01:00
Nobuyoshi Nakada
ba44e92573 ext/json no longer uses ragel 2025-01-20 21:37:20 +09:00
Jean Boussier
33708f2dc4 [ruby/json] Fix a regression in the parser with leading /
Ref: https://github.com/ruby/ruby/pull/12598

This could lead to an infinite loop.

https://github.com/ruby/json/commit/f8cfa2696a
2025-01-20 10:31:56 +01:00
Hiroshi SHIBATA
e3ba5207b5 Removed parser.rl from ext/json/parser/depend 2025-01-20 16:09:00 +09:00
Jean Boussier
df8f93848e [ruby/json] json_string_unescape: use memchr to search for backslashes
https://github.com/ruby/json/commit/5e6cfcf724
2025-01-20 16:09:00 +09:00
Jean Boussier
ba8f22c040 [ruby/json] Cleanup json_decode_float
Move all the decimal_class option parsing in the constructor.

https://github.com/ruby/json/commit/e9adefdc38
2025-01-20 16:09:00 +09:00
Jean Boussier
6c6f9672e2 [ruby/json] parser.c: Pass the JSON_ParserConfig pointer
Doesn't make a measurable performance difference but is a
bit clearer.

https://github.com/ruby/json/commit/314d117c61
2025-01-20 16:09:00 +09:00
Jean Boussier
f664e863d8 [ruby/json] Use RSTRING_END
https://github.com/ruby/json/commit/dd9c46c805
2025-01-20 16:09:00 +09:00
Jean Boussier
e4b54b0a36 [ruby/json] Replace fbuffer by stack buffers or RB_ALLOCV in parser.c
We only use that buffer for parsing integer and floats, these
are unlikely to be very big, and if so we can just use RB_ALLOCV as it will
almost always end in a small `alloca`.

This allow to no longer need `rb_protect` around the parser.

https://github.com/ruby/json/commit/994859916a
2025-01-20 16:09:00 +09:00
Jean Boussier
99e9eb5380 [ruby/json] Implement write barriers for ParserConfig objects
https://github.com/ruby/json/commit/591056a526
2025-01-20 16:09:00 +09:00
Jean Boussier
ef585744c0 Finalize Kevin's handrolled parser.
And get rid of the Ragel parser.

This is 7% faster on activitypub, 15% after on twitter and 11% faster
on citm_catalog.

There might be some more optimization opportunities, I did a quick
optimization pass to fix a regression in string parsing, but other
than that I haven't dug much in performance.
2025-01-20 16:09:00 +09:00
Jean Boussier
2f0741dd3c [ruby/json] Fix a method redefinition warning in C parser
Ref: https://github.com/ruby/json/pull/728
Ref: https://github.com/ruby/ruby/pull/12569

https://github.com/ruby/json/commit/30a4a86954
2025-01-14 09:08:02 +01:00
Jean Boussier
599fbeaffa [ruby/json] Refactor JSON::Ext::Parser to split configuration and parsing state
Ref: https://github.com/ruby/json/pull/718

The existing `Parser` interface is pretty bad, as it forces to
instantiate a new instance for each document.

Instead it's preferable to only take the config and do all the
initialization needed, and then keep the parsing state on the
stack on in ephemeral memory.

This refactor makes the `JSON::Coder` pull request much easier to
implement in a performant way.

https://github.com/ruby/json/commit/c8d5236a92

Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
2025-01-14 09:08:02 +01:00
Étienne Barrié
f301383cdd Remove Generator::State#_generate
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2025-01-14 12:24:37 +09:00
Jean Boussier
f756950d82
Improve lookup tables for string escaping.
Introduce a simplified table for the most common case, which is
`script_safe: false, ascii_only: false`.

On the `script_safe` table, now only `0xE2` does a multi-byte check.

Merge back `convert_ASCII_to_JSON`, as it no longer help much with
the simplified escape table.

```
== Encoding mixed utf8 (5003001 bytes)
ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
               after    38.000 i/100ms
Calculating -------------------------------------
               after    398.220 (± 3.0%) i/s    (2.51 ms/i) -      2.014k in   5.061659s

Comparison:
              before:      381.8 i/s
               after:      398.2 i/s - same-ish: difference falls within error

== Encoding mostly utf8 (5001001 bytes)
ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
               after    39.000 i/100ms
Calculating -------------------------------------
               after    393.337 (± 2.5%) i/s    (2.54 ms/i) -      1.989k in   5.059397s

Comparison:
              before:      304.3 i/s
               after:      393.3 i/s - 1.29x  faster

== Encoding twitter.json (466906 bytes)
ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
               after   244.000 i/100ms
Calculating -------------------------------------
               after      2.436k (± 0.9%) i/s  (410.43 μs/i) -     12.200k in   5.007702s

Comparison:
              before:     2125.9 i/s
               after:     2436.5 i/s - 1.15x  faster
```
2025-01-07 13:21:46 +09:00
Jean Boussier
91efe7b64f [ruby/json] Release 2.9.1
https://github.com/ruby/json/commit/f745ec145e
2024-12-19 08:45:31 +09:00
Naohisa Goto
979b19b741 [ruby/json] Add support for Solaris 10 which lacks strnlen()
Check for existence of strnlen() and use alternative code if it is missing.

https://github.com/ruby/json/commit/48d4bbc3a0
2024-12-19 08:45:31 +09:00
Jean Boussier
811bc15c75 [ruby/json] Release 2.9.0
https://github.com/ruby/json/commit/e1f6456499
2024-12-05 09:16:22 +01:00
Jean Boussier
1510d72bec [ruby/json] Fix generate(script_safe: true) to not confuse unrelated characters
Fix: https://github.com/ruby/json/issues/715

The first byte check was missing.

https://github.com/ruby/json/commit/93a7f8717d
2024-12-05 09:16:22 +01:00
Yusuke Endoh
209f8ba7c4 [ruby/json] Prevent a warning of "a candidate for gnu_printf format attribute"
GCC 13 prints the following warning.

https://rubyci.s3.amazonaws.com/ubuntu/ruby-master/log/20241127T001003Z.log.html.gz
```
compiling generator.c
generator.c: In function ‘raise_generator_error’:
generator.c:91:5: warning: function ‘raise_generator_error’ might be a candidate for ‘gnu_printf’ format attribute [-Wsuggest-attribute=format]
   91 |     VALUE str = rb_vsprintf(fmt, args);
      |     ^~~~~
```

This change prevents the warning by specifying the format attribute.

https://github.com/ruby/json/commit/b8c1490846
2024-11-27 23:35:20 +09:00
Jean Boussier
693a793521 JSON::GeneratorError expose invalid object
Fix: https://github.com/ruby/json/issues/710

Makes it easier to debug why a given tree of objects can't
be dumped as JSON.

Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
2024-11-26 15:11:05 +09:00
Jean Boussier
6805e88935 [ruby/json] Stop using rb_gc_mark_locations
It's using `rb_gc_mark_maybe` under the hood, which isn't what
we need.

https://github.com/ruby/json/commit/e10d0bffcd
2024-11-26 15:11:05 +09:00
Jean Boussier
ee0de3fd4e [ruby/json] JSON.dump: write directly into the provided IO
Ref: https://github.com/ruby/json/issues/524

Rather than to buffer everything in memory.

Unfortunately Ruby doesn't provide an API to write into
and IO without first allocating a string, which is a bit
wasteful.

https://github.com/ruby/json/commit/f017af6c0a
2024-11-26 15:11:05 +09:00
Jean Boussier
9c6217fd05 [ruby/json] Fix the BEWARE documentation in load and unsafe_load.
https://github.com/ruby/json/commit/2d62ec449f
2024-11-18 04:23:18 +01:00
Jean Boussier
f3e17a84f4 [ruby/json] Release 2.8.2
https://github.com/ruby/json/commit/d5e4a6e3fd
2024-11-18 04:23:18 +01:00
razokulover
62e1469e8b [ruby/json] Fix redundant to_str call
https://github.com/ruby/json/commit/61f022dfbd
2024-11-18 04:23:18 +01:00
Jean Boussier
a4183781ec [ruby/json] Only use the key cache if the Hash is in an Array
Otherwise the likeliness of seeing that key again is really low, and looking up
the cache is just a waste.

Before:

```
== Parsing small hash (65 bytes)
ruby 3.4.0dev (2024-11-13T12:32:57Z fstr-update-callba.. https://github.com/ruby/json/commit/9b44b455b3) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
                json   343.049k i/100ms
                  oj   213.943k i/100ms
          Oj::Parser    31.583k i/100ms
           rapidjson   303.433k i/100ms
Calculating -------------------------------------
                json      3.704M (± 1.5%) i/s  (270.01 ns/i) -     18.525M in   5.003078s
                  oj      2.200M (± 1.1%) i/s  (454.46 ns/i) -     11.125M in   5.056526s
          Oj::Parser    285.369k (± 4.8%) i/s    (3.50 μs/i) -      1.453M in   5.103866s
           rapidjson      3.216M (± 1.6%) i/s  (310.95 ns/i) -     16.082M in   5.001973s

Comparison:
                json:  3703517.4 i/s
           rapidjson:  3215983.0 i/s - 1.15x  slower
                  oj:  2200417.1 i/s - 1.68x  slower
          Oj::Parser:   285369.1 i/s - 12.98x  slower

== Parsing test from oj (258 bytes)
ruby 3.4.0dev (2024-11-13T12:32:57Z fstr-update-callba.. https://github.com/ruby/json/commit/9b44b455b3) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
                json    54.539k i/100ms
                  oj    41.473k i/100ms
          Oj::Parser    24.064k i/100ms
           rapidjson    51.466k i/100ms
Calculating -------------------------------------
                json    549.386k (± 1.6%) i/s    (1.82 μs/i) -      2.781M in   5.064316s
                  oj    417.003k (± 1.3%) i/s    (2.40 μs/i) -      2.115M in   5.073047s
          Oj::Parser    226.500k (± 4.7%) i/s    (4.42 μs/i) -      1.131M in   5.005466s
           rapidjson    526.124k (± 1.0%) i/s    (1.90 μs/i) -      2.676M in   5.087176s

Comparison:
                json:   549385.6 i/s
           rapidjson:   526124.3 i/s - 1.04x  slower
                  oj:   417003.4 i/s - 1.32x  slower
          Oj::Parser:   226500.4 i/s - 2.43x  slower
```

After:

```
== Parsing small hash (65 bytes)
ruby 3.4.0dev (2024-11-13T12:32:57Z fstr-update-callba.. https://github.com/ruby/json/commit/9b44b455b3) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
                json   361.394k i/100ms
                  oj   217.203k i/100ms
          Oj::Parser    28.855k i/100ms
           rapidjson   303.404k i/100ms
Calculating -------------------------------------
                json      3.859M (± 2.9%) i/s  (259.13 ns/i) -     19.515M in   5.061302s
                  oj      2.191M (± 1.6%) i/s  (456.49 ns/i) -     11.077M in   5.058043s
          Oj::Parser    315.132k (± 7.1%) i/s    (3.17 μs/i) -      1.587M in   5.065707s
           rapidjson      3.156M (± 4.0%) i/s  (316.88 ns/i) -     15.777M in   5.008949s

Comparison:
                json:  3859046.5 i/s
           rapidjson:  3155778.5 i/s - 1.22x  slower
                  oj:  2190616.0 i/s - 1.76x  slower
          Oj::Parser:   315132.4 i/s - 12.25x  slower

== Parsing test from oj (258 bytes)
ruby 3.4.0dev (2024-11-13T12:32:57Z fstr-update-callba.. https://github.com/ruby/json/commit/9b44b455b3) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
                json    55.682k i/100ms
                  oj    40.343k i/100ms
          Oj::Parser    25.119k i/100ms
           rapidjson    51.500k i/100ms
Calculating -------------------------------------
                json    555.808k (± 1.4%) i/s    (1.80 μs/i) -      2.784M in   5.010092s
                  oj    412.283k (± 1.7%) i/s    (2.43 μs/i) -      2.098M in   5.089900s
          Oj::Parser    279.306k (±13.3%) i/s    (3.58 μs/i) -      1.356M in   5.022079s
           rapidjson    517.177k (± 2.7%) i/s    (1.93 μs/i) -      2.626M in   5.082352s

Comparison:
                json:   555808.3 i/s
           rapidjson:   517177.1 i/s - 1.07x  slower
                  oj:   412283.2 i/s - 1.35x  slower
          Oj::Parser:   279306.5 i/s - 1.99x  slower
```

https://github.com/ruby/json/commit/00c45ddc9f
2024-11-14 11:21:39 +09:00
Jean Boussier
1b6a26e23a [ruby/json] JSON.load_file: explictly load the file as UTF-8
Fix: https://github.com/ruby/json/issues/697

This way even if `Encoding.default_external` is set to a weird value
the document will be parsed just fine.

https://github.com/ruby/json/commit/3a8505a8fa
2024-11-11 09:40:11 +09:00
Jean Boussier
58317328b6 [ruby/json] Rename parse_float into parse_number
https://github.com/ruby/json/commit/e51e796697
2024-11-11 09:40:10 +09:00
Aaron Patterson
c991f75c19 [ruby/json] Reduce comparisons when parsing numbers
Before this commit, we would try to scan for a float, then if that
failed, scan for an integer.  But floats and integers have many bytes in
common, so we would end up scanning the same bytes multiple times.

This patch combines integer and float scanning machines so that we only
have to scan bytes once.  If the machine finds "float parts", then it
executes the "isFloat" transition in the machine, which sets a boolean
letting us know that the parser found a float.

If we didn't find a float, but we did match, then we know it's an int.

https://github.com/ruby/json/commit/0c0e0930cd
2024-11-11 09:40:10 +09:00
Jean Boussier
f1be046a1d [ruby/json] Release 2.8.1
https://github.com/ruby/json/commit/49650f7312
2024-11-11 09:40:09 +09:00
Jean Boussier
a78cb959ec [ruby/json] Fix gemspec to include .jar files
Fix: https://github.com/ruby/json/issues/694

This was lost during the .gemspec merge and not noticed
because it was falling back to loading the jars from the
stdlib.

https://github.com/ruby/json/commit/07cf261251
2024-11-11 09:40:08 +09:00
Jean Boussier
e4c15b8ace [ruby/json] Release 2.8.0
https://github.com/ruby/json/commit/8071cc6f09
2024-11-06 23:31:30 +01:00