Jean Boussier
f171a263f7
[ruby/json] Fix: generate_json_float to reserve enough memory for large negative floats.
...
Fix: https://github.com/ruby/json/issues/807
Since https://github.com/ruby/json/pull/800 , `fpconv_dtoa` can actually
generate up to 28 chars.
d73ae93d3c
2025-05-26 11:46:12 +09:00
Cody Horton
3468811ed1
[ruby/json] fix for pretty_generate throwing wrong number of arguments error
...
8433571dcf
2025-05-19 11:19:17 +09:00
Jean Boussier
af79914002
[ruby/json] Favor decimal notation over scientific notation for floats
...
e.g.
```
JSON.dump(1746861937.7842371)
```
master:
```
"1.7468619377
+9"
```
This branch and older json versions:
```
1746861937
.7842371
```
In the end it's shorter, and according to `canada.json` benchmark
performance is the same.
866f72a437
2025-05-12 11:09:11 +09:00
Scott Myron
a3ec53bbb0
[ruby/json] Introduce ARM Neon and SSE2 SIMD.
...
(https://github.com/ruby/json/pull/743 )
See the pull request for the long development history: https://github.com/ruby/json/pull/743
```
== Encoding activitypub.json (52595 bytes)
ruby 3.4.2 (2025-02-15 revision d2930f8e7a
) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
after 2.913k i/100ms
Calculating -------------------------------------
after 29.377k (± 2.0%) i/s (34.04 μs/i) - 148.563k in 5.059169s
Comparison:
before: 23314.1 i/s
after: 29377.3 i/s - 1.26x faster
== Encoding citm_catalog.json (500298 bytes)
ruby 3.4.2 (2025-02-15 revision d2930f8e7a
) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
after 152.000 i/100ms
Calculating -------------------------------------
after 1.569k (± 0.8%) i/s (637.49 μs/i) - 7.904k in 5.039001s
Comparison:
before: 1485.6 i/s
after: 1568.7 i/s - 1.06x faster
== Encoding twitter.json (466906 bytes)
ruby 3.4.2 (2025-02-15 revision d2930f8e7a
) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
after 309.000 i/100ms
Calculating -------------------------------------
after 3.115k (± 3.1%) i/s (321.01 μs/i) - 15.759k in 5.063776s
Comparison:
before: 2508.3 i/s
after: 3115.2 i/s - 1.24x faster
```
49003523da
2025-04-30 08:12:41 +02:00
Jean Boussier
5566a7f740
[ruby/json] Handle non-string keys returning immediate values via to_s
...
We can't directly call `RBASIC_CLASS` as the return value of
`to_s` may be an immediate.
12dc394d11
2025-04-30 08:12:41 +02:00
Jean Boussier
3bbb52f5c5
[ruby/json] Add missing assert_deprecated_warning
...
1b16a82980
2025-03-28 12:44:53 +09:00
Jean Boussier
26e55562ce
[ruby/json] Cleanup JSON.pretty_generate
...
01c47a0555
2025-03-28 12:44:53 +09:00
Jean Boussier
2b9a9300ac
[ruby/json] Deprecate JSON.fast_generate
...
6508455d82
2025-03-28 12:44:53 +09:00
Hiroshi SHIBATA
ee85745c61
Removed trailing spaces
2025-03-27 11:37:27 +09:00
eno
d1f3c81258
Faster integer formatting
...
This commit provides an alternative implementation for a
long → decimal conversion.
The main difference is that it uses an algorithm pulled from
https://github.com/jeaiii/itoa .
The source there is C++, it was converted by hand to C for
inclusion with this gem.
jeaiii's algorithm is covered by the MIT License, see source code.
On addition this version now also generates the string directly into
the fbuffer, foregoing the need to run a separate memory copy.
As a result, I see a speedup of 32% on Apple Silicon M1 for an
integer set of benchmarks.
2025-03-27 11:37:27 +09:00
eno
528c08cc5f
[ruby/json] Adjust fpconv to add ".0" to integers
...
Adds a test case
fix
fa5bdf87cb
2025-03-24 14:35:04 +09:00
Rahim Packir Saibo
e20f1f76f4
[ruby/json] Fix JSON::GeneratorError#detailed_message with Ruby < 3.2
...
2e015ff839
2025-03-06 18:29:27 +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
É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
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 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 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 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
```
8fb5ae807f
2025-02-03 10:05:25 +09:00
Jean Boussier
50e34fd768
Allow JSON::Fragment to be used even in strict mode
2025-01-28 15:42:20 +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
Étienne Barrié
e8676cada8
[ruby/json] Introduce JSON::Fragment
...
9e3500f345
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2025-01-20 14:20:55 +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.
93a7f8717d
2024-12-05 09:16:22 +01: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
ca8f21ace8
[ruby/json] Resync
2024-11-05 18:00:36 +01:00
Jean Boussier
f664e7eaab
[ruby/json] Add tests for the behavior of JSON.generate with base types subclasses
...
Ref: https://github.com/ruby/json/pull/674
Ref: https://github.com/ruby/json/pull/668
The behavior on such case it quite unclear, the goal here is to
figure out whatever was the behavior on Cext version of `json 2.7.0`
and get all implementations to converge.
We can then decide to make them all behave differently if we so wish.
614921dcef
2024-11-05 18:00:36 +01:00
Jean Boussier
ef5565f5d1
JSON.generate: call to_json on String subclasses
...
Fix: https://github.com/ruby/json/issues/667
This is yet another behavior on which the various implementations
differed, but the C implementation used to call `to_json` on String
subclasses used as keys.
This was optimized out in e125072130229e54a651f7b11d7d5a782ae7fb65
but there is an Active Support test case for it, so it's best to
make all 3 implementation respect this behavior.
2024-11-01 13:04:24 +09:00
Jean Boussier
3782600f0f
[ruby/json] Emit warnings when dumping binary strings
...
Because of it's Ruby 1.8 heritage, the C extension doesn't care
much about strings encoding. We should get stricter over time.
42402fc13f
2024-11-01 13:04:24 +09:00
Jean Boussier
cc2e67a138
Elide Generator::State allocation until a to_json
method has to be called
...
Fix: https://github.com/ruby/json/issues/655
For very small documents, the biggest performance gap with alternatives is
that the API impose that we allocate the `State` object. In a real world app
this doesn't make much of a difference, but when running in a micro-benchmark
this doubles the allocations, causing twice the amount of GC runs, making us
look bad.
However, unless we have to call a `to_json` method, the `State` object isn't
visible, so with some refactoring, we can elude that allocation entirely.
Instead we allocate the State internal struct on the stack, and if we need
to call a `to_json` method, we allocate the `State` and spill the struct on
the heap.
As a result, `JSON.generate` is now as fast as re-using a `State` instance,
as long as only primitives are generated.
Before:
```
== Encoding small mixed (34 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec
) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 598.654k i/100ms
json 400.542k i/100ms
oj 533.353k i/100ms
Calculating -------------------------------------
json (reuse) 6.371M (± 8.6%) i/s (156.96 ns/i) - 31.729M in 5.059195s
json 4.120M (± 6.6%) i/s (242.72 ns/i) - 20.828M in 5.090549s
oj 5.622M (± 6.4%) i/s (177.86 ns/i) - 28.268M in 5.061473s
Comparison:
json (reuse): 6371126.6 i/s
oj: 5622452.0 i/s - same-ish: difference falls within error
json: 4119991.1 i/s - 1.55x slower
== Encoding small nested array (121 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec
) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 248.125k i/100ms
json 215.255k i/100ms
oj 217.531k i/100ms
Calculating -------------------------------------
json (reuse) 2.628M (± 6.1%) i/s (380.55 ns/i) - 13.151M in 5.030281s
json 2.185M (± 6.7%) i/s (457.74 ns/i) - 10.978M in 5.057655s
oj 2.217M (± 6.7%) i/s (451.10 ns/i) - 11.094M in 5.044844s
Comparison:
json (reuse): 2627799.4 i/s
oj: 2216824.8 i/s - 1.19x slower
json: 2184669.5 i/s - 1.20x slower
== Encoding small hash (65 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec
) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 641.334k i/100ms
json 322.745k i/100ms
oj 642.450k i/100ms
Calculating -------------------------------------
json (reuse) 7.133M (± 6.5%) i/s (140.19 ns/i) - 35.915M in 5.068201s
json 4.615M (± 7.0%) i/s (216.70 ns/i) - 22.915M in 5.003718s
oj 6.912M (± 6.4%) i/s (144.68 ns/i) - 34.692M in 5.047690s
Comparison:
json (reuse): 7133123.3 i/s
oj: 6911977.1 i/s - same-ish: difference falls within error
json: 4614696.6 i/s - 1.55x slower
```
After:
```
== Encoding small mixed (34 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec
) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 572.751k i/100ms
json 457.741k i/100ms
oj 512.247k i/100ms
Calculating -------------------------------------
json (reuse) 6.324M (± 6.9%) i/s (158.12 ns/i) - 31.501M in 5.023093s
json 6.263M (± 6.9%) i/s (159.66 ns/i) - 31.126M in 5.017086s
oj 5.569M (± 6.6%) i/s (179.56 ns/i) - 27.661M in 5.003739s
Comparison:
json (reuse): 6324183.5 i/s
json: 6263204.9 i/s - same-ish: difference falls within error
oj: 5569049.2 i/s - same-ish: difference falls within error
== Encoding small nested array (121 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec
) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 258.505k i/100ms
json 242.335k i/100ms
oj 220.678k i/100ms
Calculating -------------------------------------
json (reuse) 2.589M (± 9.6%) i/s (386.17 ns/i) - 12.925M in 5.071853s
json 2.594M (± 6.6%) i/s (385.46 ns/i) - 13.086M in 5.083035s
oj 2.250M (± 2.3%) i/s (444.43 ns/i) - 11.255M in 5.004707s
Comparison:
json (reuse): 2589499.6 i/s
json: 2594321.0 i/s - same-ish: difference falls within error
oj: 2250064.0 i/s - 1.15x slower
== Encoding small hash (65 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec
) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 656.373k i/100ms
json 644.135k i/100ms
oj 650.283k i/100ms
Calculating -------------------------------------
json (reuse) 7.202M (± 7.1%) i/s (138.84 ns/i) - 36.101M in 5.051438s
json 7.278M (± 1.7%) i/s (137.40 ns/i) - 36.716M in 5.046300s
oj 7.036M (± 1.7%) i/s (142.12 ns/i) - 35.766M in 5.084729s
Comparison:
json (reuse): 7202447.9 i/s
json: 7277883.0 i/s - same-ish: difference falls within error
oj: 7036115.2 i/s - same-ish: difference falls within error
```
2024-11-01 13:04:24 +09:00
Jean Boussier
b094ee3f23
Handle all formatting configs potentially being nil
.
...
Fix: https://github.com/ruby/json/issues/653
I don't think this was really fully supported in the past, but
it kinda worked with some of the implementations.
2024-10-29 13:25:01 +09:00
Jean Boussier
a5bd0c638a
[ruby/json] Workaround rubygems $LOAD_PATH bug
...
Ref: https://github.com/ruby/json/issues/647
Ref: https://github.com/rubygems/rubygems/pull/6490
Older rubygems are executing `extconf.rb` with a broken `$LOAD_PATH`
causing the `json` gem native extension to be loaded with the stdlib
version of the `.rb` files.
This fails with
```
json/common.rb:82:in `initialize': wrong number of arguments (given 1, expected 0) (ArgumentError)
```
Since this is just for `extconf.rb` we can probably just accept that
extra argument and ignore it.
The bug was fixed in rubygems 3.4.9 / 2023-03-20
1f5e849fe0
2024-10-26 18:44:15 +09:00
Jean Boussier
1045b9f820
[ruby/json] Modernize heredocs
...
fb25e94aea
2024-10-26 18:44:15 +09:00
Jean Boussier
bfdf02ea72
pretty_generate: don't apply object_nl / array_nl for empty containers
...
Fix: https://github.com/ruby/json/issues/437
Before:
```json
{
"foo": {
},
"bar": [
]
}
```
After:
```json
{
"foo": {},
"bar": []
}
```
2024-10-26 18:44:15 +09:00
Jean Boussier
fc9f0cb8c5
[ruby/json] JSON.dump / String#to_json: raise on invalid encoding
...
This regressed since 2.7.2.
35407d6635
2024-10-26 18:44:15 +09:00
Benoit Daloze
2c6e3bc71e
Raise the correct exception in fast_serialize_string
...
* Related to https://github.com/ruby/json/issues/344
2024-10-26 18:44:15 +09:00
Étienne Barrié
82f7550f65
Use frozen string literals
...
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2024-10-26 18:44:15 +09:00
Étienne Barrié
11348c583f
Use Encoding constants, String#b
...
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2024-10-26 18:44:15 +09:00
Jean Boussier
8feed977a0
[ruby/json] Assume Encoding is defined
...
8713aa4812
2024-10-18 11:30:55 +09:00
Hiroshi SHIBATA
8af6606b22
Restore missing test-case from c5a6d80427
...
Co-authored-by: "Jean Boussier" <byroot@ruby-lang.org>
2024-10-16 11:24:25 +09:00
Hiroshi SHIBATA
fe33475605
Removed trailing space
2024-10-08 14:10:05 +09:00
Jean Boussier
718c4f7e1e
JSONPure: String#to_json should raise on invalid encoding
...
Fix : #344
This matches the ext behavior.
2024-10-08 14:10:05 +09:00
Jean Boussier
8fdd3d0ed6
JSON::Pure fix strict mode
...
Followup: https://github.com/flori/json/pull/519
Fix: https://github.com/flori/json/issues/584
2024-10-08 14:10:05 +09:00
Étienne Barrié
f4883e7904
[flori/json] Use the compiled extension in test
...
148afef84c
2024-09-03 11:51:51 +09:00
Hiroshi SHIBATA
abc3d124f7
[flori/json] The modern Ruby uses utf-8 encodings by default
...
11b31210ac
2023-12-05 12:04:10 +09:00
Takashi Kokubun
e6b35e8a6d
[flori/json] Overload kwargs in JSON.dump
...
936f280f9f
2023-12-05 12:04:08 +09:00
Jean Boussier
a22ed89438
[flori/json] JSON.dump: handle unenclosed hashes regression
...
Fix: https://github.com/flori/json/issues/553
We can never add keyword arguments to `dump` otherwise
existing code using unenclosed hash will break.
8e0076a3f2
2023-12-05 12:04:07 +09:00
Hiroshi SHIBATA
86045fca24
Manually merged from flori/json
...
> https://github.com/flori/json/pull/525
> Rename escape_slash in script_safe and also escape E+2028 and E+2029
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
> https://github.com/flori/json/pull/454
> Remove unnecessary initialization of create_id in JSON.parse()
Co-authored-by: Watson <watson1978@gmail.com>
2023-12-01 16:47:06 +09:00
Jean Boussier
0dfeb17296
Rename escape_slash in script_safe and also escape E+2028 and E+2029
...
It is rather common to directly interpolate JSON string inside
<script> tags in HTML as to provide configuration or parameters to a
script.
However this may lead to XSS vulnerabilities, to prevent that 3
characters need to be escaped:
- `/` (forward slash)
- `U+2028` (LINE SEPARATOR)
- `U+2029` (PARAGRAPH SEPARATOR)
The forward slash need to be escaped to prevent closing the script
tag early, and the other two are valid JSON but invalid Javascript
and can be used to break JS parsing.
Given that the intent of escaping forward slash is the same than escaping
U+2028 and U+2029, I chos to rename and repurpose the existing `escape_slash`
option.
2023-12-01 16:47:06 +09:00
Hiroshi SHIBATA
e42df781d9
[flori/json] define_method is also private at Ruby 2.3 and 2.4
...
3804f38bf4
2023-10-11 15:45:17 +09:00
Hiroshi SHIBATA
1b19e9198d
[flori/json] remove_method of Module is private at Ruby 2.3 and 2.4
...
6cbadf6b6e
2023-10-11 15:45:17 +09:00
Hiroshi SHIBATA
c75d54a36c
Fixup 1851824b1c
2023-09-13 16:23:18 +09:00
Hiroshi SHIBATA
1851824b1c
[flori/json] alias_method is private on Ruby 2.3 and 2.4
...
573ef94bc5
2023-09-13 16:01:19 +09:00
Yusuke Endoh
77db0ca6c8
Prevent a warning: method redefined; discarding old included
...
```
[ 3463/25719] JSONGeneratorTest#test_string_ext_included_calls_super/home/chkbuild/chkbuild/tmp/build/20230905T063003Z/ruby/test/json/json_generator_test.rb:411: warning: method redefined; discarding old included
/home/chkbuild/chkbuild/tmp/build/20230905T063003Z/ruby/test/json/json_generator_test.rb:399: warning: previous definition of included was here
```
20230905
T063003Z.log.html.gz
2023-09-05 17:29:53 +09:00
Peter Zhu
91de37c23e
Remove --disable-gems in assert_in_out_err
...
assert_in_out_err adds --disable=gems so we don't need to add
--disable-gems in the args list.
2023-08-28 15:05:19 -04:00