From 65612dbb38295bf3cf0bdc5d7d9b65aefaebf500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 31 Jul 2025 10:54:59 +0200 Subject: [PATCH 1/2] [rubygems/rubygems] Fix daily CI Platform specific versions of ffi-1.17.2 are not compatible with Ruby 3.5, so Bundler fails to resolve in Ruby 3.5 using recorded VCR responses. Use the generic version of ffi-1.17.2, which should work for all rubies, consistently to fix that. https://github.com/rubygems/rubygems/commit/a192f7e35d --- spec/bundler/realworld/ffi_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/bundler/realworld/ffi_spec.rb b/spec/bundler/realworld/ffi_spec.rb index ad8b463ce23aea..bede372b410b53 100644 --- a/spec/bundler/realworld/ffi_spec.rb +++ b/spec/bundler/realworld/ffi_spec.rb @@ -47,7 +47,7 @@ module FOO install_gemfile <<-G source "https://rubygems.org" - gem 'ffi' + gem 'ffi', force_ruby_platform: true G bundle "exec ruby foo.rb" From 1c6b36af18f33882f152e412c8ec1f06f1303197 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Sun, 3 Aug 2025 10:33:30 +0200 Subject: [PATCH 2/2] Only define `String.json_create` & al when `json/add` is required All the `json/add` related methods for string were always defined unconditionally from the generators. It's preferable to only define them if `json/add` is actually used. --- ext/json/generator/generator.c | 65 +-------------------------------- ext/json/lib/json/add/core.rb | 1 + ext/json/lib/json/add/string.rb | 35 ++++++++++++++++++ 3 files changed, 37 insertions(+), 64 deletions(-) create mode 100644 ext/json/lib/json/add/string.rb diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index d60fbba41bd323..5248a9e26aae3e 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -31,7 +31,7 @@ typedef struct JSON_Generator_StateStruct { #define RB_UNLIKELY(cond) (cond) #endif -static VALUE mJSON, cState, cFragment, mString_Extend, eGeneratorError, eNestingError, Encoding_UTF_8; +static VALUE mJSON, cState, cFragment, eGeneratorError, eNestingError, Encoding_UTF_8; static ID i_to_s, i_to_json, i_new, i_pack, i_unpack, i_create_id, i_extend, i_encode; static VALUE sym_indent, sym_space, sym_space_before, sym_object_nl, sym_array_nl, sym_max_nesting, sym_allow_nan, @@ -835,18 +835,6 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self) return cState_partial_generate(Vstate, self, generate_json_float, Qfalse); } -/* - * call-seq: String.included(modul) - * - * Extends _modul_ with the String::Extend module. - */ -static VALUE mString_included_s(VALUE self, VALUE modul) -{ - VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend); - rb_call_super(1, &modul); - return result; -} - /* * call-seq: to_json(*) * @@ -861,51 +849,6 @@ static VALUE mString_to_json(int argc, VALUE *argv, VALUE self) return cState_partial_generate(Vstate, self, generate_json_string, Qfalse); } -/* - * call-seq: to_json_raw_object() - * - * This method creates a raw object hash, that can be nested into - * other data structures and will be generated as a raw string. This - * method should be used, if you want to convert raw strings to JSON - * instead of UTF-8 strings, e. g. binary data. - */ -static VALUE mString_to_json_raw_object(VALUE self) -{ - VALUE ary; - VALUE result = rb_hash_new(); - rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self))); - ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*")); - rb_hash_aset(result, rb_utf8_str_new_lit("raw"), ary); - return result; -} - -/* - * call-seq: to_json_raw(*args) - * - * This method creates a JSON text from the result of a call to - * to_json_raw_object of this String. - */ -static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self) -{ - VALUE obj = mString_to_json_raw_object(self); - Check_Type(obj, T_HASH); - return mHash_to_json(argc, argv, obj); -} - -/* - * call-seq: json_create(o) - * - * Raw Strings are JSON Objects (the raw bytes are stored in an array for the - * key "raw"). The Ruby String can be created by this module method. - */ -static VALUE mString_Extend_json_create(VALUE self, VALUE o) -{ - VALUE ary; - Check_Type(o, T_HASH); - ary = rb_hash_aref(o, rb_str_new2("raw")); - return rb_funcall(ary, i_pack, 1, rb_str_new2("C*")); -} - /* * call-seq: to_json(*) * @@ -2091,13 +2034,7 @@ void Init_generator(void) rb_define_method(mFloat, "to_json", mFloat_to_json, -1); VALUE mString = rb_define_module_under(mGeneratorMethods, "String"); - rb_define_singleton_method(mString, "included", mString_included_s, 1); rb_define_method(mString, "to_json", mString_to_json, -1); - rb_define_method(mString, "to_json_raw", mString_to_json_raw, -1); - rb_define_method(mString, "to_json_raw_object", mString_to_json_raw_object, 0); - - mString_Extend = rb_define_module_under(mString, "Extend"); - rb_define_method(mString_Extend, "json_create", mString_Extend_json_create, 1); VALUE mTrueClass = rb_define_module_under(mGeneratorMethods, "TrueClass"); rb_define_method(mTrueClass, "to_json", mTrueClass_to_json, -1); diff --git a/ext/json/lib/json/add/core.rb b/ext/json/lib/json/add/core.rb index 485f097fff4317..61ff4542129ba4 100644 --- a/ext/json/lib/json/add/core.rb +++ b/ext/json/lib/json/add/core.rb @@ -7,6 +7,7 @@ require 'json/add/exception' require 'json/add/range' require 'json/add/regexp' +require 'json/add/string' require 'json/add/struct' require 'json/add/symbol' require 'json/add/time' diff --git a/ext/json/lib/json/add/string.rb b/ext/json/lib/json/add/string.rb new file mode 100644 index 00000000000000..46f07967cd624d --- /dev/null +++ b/ext/json/lib/json/add/string.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true +unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED + require 'json' +end + +class String + # call-seq: json_create(o) + # + # Raw Strings are JSON Objects (the raw bytes are stored in an array for the + # key "raw"). The Ruby String can be created by this class method. + def self.json_create(object) + object["raw"].pack("C*") + end + + # call-seq: to_json_raw_object() + # + # This method creates a raw object hash, that can be nested into + # other data structures and will be generated as a raw string. This + # method should be used, if you want to convert raw strings to JSON + # instead of UTF-8 strings, e. g. binary data. + def to_json_raw_object + { + JSON.create_id => self.class.name, + "raw" => unpack("C*"), + } + end + + # call-seq: to_json_raw(*args) + # + # This method creates a JSON text from the result of a call to + # to_json_raw_object of this String. + def to_json_raw(...) + to_json_raw_object.to_json(...) + end +end \ No newline at end of file