Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
1619cf7
io_buffer: add safe callback wrappers for String views. (#17473)
ioquatix Jun 25, 2026
bc1348a
[ruby/rubygems] Guard the vendored URI against double loading
hsbt Jun 25, 2026
0953a29
[ruby/rubygems] Ship RubyGems' vendored URI in the Bundler gem
hsbt Jun 25, 2026
223f796
[ruby/rubygems] Use RubyGems' vendored URI in Bundler
hsbt Jun 25, 2026
c215429
[ruby/rubygems] Track the shipped RubyGems URI in the file invariant
hsbt Jun 25, 2026
37fa88d
Remove flaky test_escape_html_allocates_same_as_escapeHTML
byroot Jun 24, 2026
713d4e1
[ruby/rubygems] Pass locked platforms to materialization instead of m…
hsbt Jun 15, 2026
fc01306
[ruby/rubygems] Guide users to the ruby fallback variant on frozen in…
hsbt Jun 15, 2026
c818da0
[ruby/rubygems] Pass locked_platforms by keyword to candidate_platforms
hsbt Jun 25, 2026
4ea11c6
[ruby/rubygems] Cover that the ruby fallback hint is skipped for ruby…
hsbt Jun 25, 2026
12ef8a6
[ruby/error_highlight] Return nil instead of raising NotImplementedEr…
rwstauner Jun 24, 2026
b3cf097
re.c: Remove unecessary RBOOL in `rb_reg_equal`
byroot Jun 25, 2026
f400c87
[ruby/json] Fix wrong call-seq for `JSON::ResumableParser#eos?`
kou Jun 25, 2026
a746dd8
[ruby/json] Declare types as RUBY_TYPED_THREAD_SAFE_FREE
byroot Jun 24, 2026
ac13526
Fix unused-but-set-global warnings in clang-23
nobu Jun 24, 2026
91edd1b
[DOC] Update bundled gems list at ac135260de1d1302e989b31e9d83cf
matzbot Jun 25, 2026
061b1bc
[ruby/json] Fix unused-but-set-global warnings in clang-23
nobu Jun 25, 2026
b5c564c
[ruby/openssl] Fix unused-but-set-global warnings in clang-23
nobu Jun 25, 2026
6df734c
[ruby/psych] Fix unused-but-set-global warnings in clang-23
nobu Jun 25, 2026
d534fd1
[DOC] Doc for Pathname.mkpath
BurdetteLamar Jun 25, 2026
3c3269b
[DOC] Update Pathname.birthtime (#17368)
BurdetteLamar Jun 25, 2026
a31b13e
[DOC] Update for Pathname.ctime (#17370)
BurdetteLamar Jun 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ releases.
* net-imap 0.6.4.1
* 0.6.2 to [v0.6.3][net-imap-v0.6.3], [v0.6.4][net-imap-v0.6.4], [v0.6.4.1][net-imap-v0.6.4.1]
* rbs 4.0.3
* 3.10.0 to [v3.10.1][rbs-v3.10.1], [v3.10.2][rbs-v3.10.2], [v3.10.3][rbs-v3.10.3], [v3.10.4][rbs-v3.10.4], [v4.0.0.dev.5][rbs-v4.0.0.dev.5], [v4.0.0][rbs-v4.0.0], [v4.0.2][rbs-v4.0.2]
* 3.10.0 to [v3.10.1][rbs-v3.10.1], [v3.10.2][rbs-v3.10.2], [v3.10.3][rbs-v3.10.3], [v3.10.4][rbs-v3.10.4], [v4.0.0.dev.5][rbs-v4.0.0.dev.5], [v4.0.0][rbs-v4.0.0], [v4.0.2][rbs-v4.0.2], [v4.0.3][rbs-v4.0.3]
* typeprof 0.32.0
* mutex_m 0.3.0
* bigdecimal 4.1.2
Expand Down Expand Up @@ -271,6 +271,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable.
[rbs-v4.0.0.dev.5]: https://github.com/ruby/rbs/releases/tag/v4.0.0.dev.5
[rbs-v4.0.0]: https://github.com/ruby/rbs/releases/tag/v4.0.0
[rbs-v4.0.2]: https://github.com/ruby/rbs/releases/tag/v4.0.2
[rbs-v4.0.3]: https://github.com/ruby/rbs/releases/tag/v4.0.3
[bigdecimal-v4.1.0]: https://github.com/ruby/bigdecimal/releases/tag/v4.1.0
[bigdecimal-v4.1.1]: https://github.com/ruby/bigdecimal/releases/tag/v4.1.1
[bigdecimal-v4.1.2]: https://github.com/ruby/bigdecimal/releases/tag/v4.1.2
Expand Down
3 changes: 0 additions & 3 deletions complex.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ static VALUE RFLOAT_0;
VALUE rb_cComplex;

static ID id_abs, id_arg,
id_denominator, id_numerator,
id_real_p, id_i_real, id_i_imag,
id_finite_p, id_infinite_p, id_rationalize,
id_PI;
Expand Down Expand Up @@ -2696,8 +2695,6 @@ Init_Complex(void)
VALUE compat;
id_abs = rb_intern_const("abs");
id_arg = rb_intern_const("arg");
id_denominator = rb_intern_const("denominator");
id_numerator = rb_intern_const("numerator");
id_real_p = rb_intern_const("real?");
id_i_real = rb_intern_const("@real");
id_i_imag = rb_intern_const("@image"); /* @image, not @imag */
Expand Down
1 change: 1 addition & 0 deletions depend
Original file line number Diff line number Diff line change
Expand Up @@ -7354,6 +7354,7 @@ io_buffer.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
io_buffer.$(OBJEXT): $(top_srcdir)/internal/gc.h
io_buffer.$(OBJEXT): $(top_srcdir)/internal/imemo.h
io_buffer.$(OBJEXT): $(top_srcdir)/internal/io.h
io_buffer.$(OBJEXT): $(top_srcdir)/internal/io_buffer.h
io_buffer.$(OBJEXT): $(top_srcdir)/internal/numeric.h
io_buffer.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
io_buffer.$(OBJEXT): $(top_srcdir)/internal/serial.h
Expand Down
3 changes: 3 additions & 0 deletions ext/-test-/io_buffer/extconf.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: false
require_relative "../auto_ext.rb"
auto_ext(inc: true)
105 changes: 105 additions & 0 deletions ext/-test-/io_buffer/io_buffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "ruby.h"
#include "internal/io_buffer.h"

static VALUE
io_buffer_get_string(VALUE buffer, VALUE argument)
{
(void)argument;
return rb_funcall(buffer, rb_intern("get_string"), 0);
}

static VALUE
io_buffer_readonly_p(VALUE buffer, VALUE argument)
{
(void)argument;
return rb_funcall(buffer, rb_intern("readonly?"), 0);
}

static VALUE
io_buffer_object_id(VALUE buffer, VALUE argument)
{
(void)argument;
return rb_obj_id(buffer);
}

static VALUE
io_buffer_set_string(VALUE buffer, VALUE string)
{
return rb_funcall(buffer, rb_intern("set_string"), 1, string);
}

static VALUE
io_buffer_modify_string(VALUE buffer, VALUE string)
{
(void)buffer;
rb_str_cat(string, "!", 1);
return Qnil;
}

static VALUE
io_buffer_raise(VALUE buffer, VALUE argument)
{
(void)buffer;
(void)argument;
rb_raise(rb_eRuntimeError, "interrupted");
}

static VALUE
io_buffer_for_reading_get_string(VALUE self, VALUE object)
{
return rb_io_buffer_for_reading(object, io_buffer_get_string, Qnil);
}

static VALUE
io_buffer_for_reading_readonly_p(VALUE self, VALUE object)
{
return rb_io_buffer_for_reading(object, io_buffer_readonly_p, Qnil);
}

static VALUE
io_buffer_for_reading_object_id(VALUE self, VALUE object)
{
return rb_io_buffer_for_reading(object, io_buffer_object_id, Qnil);
}

static VALUE
io_buffer_for_reading_raise(VALUE self, VALUE string)
{
StringValue(string);
return rb_io_buffer_for_reading(string, io_buffer_raise, Qnil);
}

static VALUE
io_buffer_for_writing_set_string(VALUE self, VALUE object, VALUE string)
{
StringValue(string);
return rb_io_buffer_for_writing(object, io_buffer_set_string, string);
}

static VALUE
io_buffer_for_writing_readonly_p(VALUE self, VALUE object)
{
return rb_io_buffer_for_writing(object, io_buffer_readonly_p, Qnil);
}

static VALUE
io_buffer_for_writing_modify_string(VALUE self, VALUE string)
{
StringValue(string);
return rb_io_buffer_for_writing(string, io_buffer_modify_string, string);
}

void
Init_io_buffer(void)
{
VALUE mBug = rb_define_module("Bug");
VALUE mIOBuffer = rb_define_module_under(mBug, "IOBuffer");

rb_define_singleton_method(mIOBuffer, "for_reading_get_string", io_buffer_for_reading_get_string, 1);
rb_define_singleton_method(mIOBuffer, "for_reading_readonly?", io_buffer_for_reading_readonly_p, 1);
rb_define_singleton_method(mIOBuffer, "for_reading_object_id", io_buffer_for_reading_object_id, 1);
rb_define_singleton_method(mIOBuffer, "for_reading_raise", io_buffer_for_reading_raise, 1);
rb_define_singleton_method(mIOBuffer, "for_writing_set_string", io_buffer_for_writing_set_string, 2);
rb_define_singleton_method(mIOBuffer, "for_writing_readonly?", io_buffer_for_writing_readonly_p, 1);
rb_define_singleton_method(mIOBuffer, "for_writing_modify_string", io_buffer_for_writing_modify_string, 1);
}
2 changes: 1 addition & 1 deletion ext/json/generator/generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ static const rb_data_type_t JSON_Generator_State_type = {
.dsize = State_memsize,
.dcompact = State_compact,
},
.flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_EMBEDDABLE,
.flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_EMBEDDABLE,
};

static void state_init(JSON_Generator_State *state)
Expand Down
4 changes: 4 additions & 0 deletions ext/json/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@

/* shims */

#ifndef RUBY_TYPED_THREAD_SAFE_FREE
#define RUBY_TYPED_THREAD_SAFE_FREE RUBY_TYPED_FREE_IMMEDIATELY
#endif

#ifndef UNDEF_P
#define UNDEF_P(val) (val == Qundef)
#endif
Expand Down
17 changes: 11 additions & 6 deletions ext/json/parser/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
static VALUE mJSON, eNestingError, eParserError, Encoding_UTF_8;
static VALUE CNaN, CInfinity, CMinusInfinity, JSON_empty_string;

static ID i_new, i_try_convert, i_uminus, i_encode, i_at_line, i_at_column;
static ID i_new, i_try_convert, i_encode, i_at_line, i_at_column;
#ifndef HAVE_RB_STR_TO_INTERNED_STR
static ID i_uminus;
#endif

static VALUE sym_max_nesting, sym_allow_nan, sym_allow_trailing_comma, sym_allow_comments,
sym_allow_control_characters, sym_allow_invalid_escape, sym_symbolize_names,
Expand Down Expand Up @@ -314,7 +317,7 @@ static const rb_data_type_t JSON_Parser_rvalue_stack_type = {
},
// We deliberately don't declare rvalue_stack as RUBY_TYPED_WB_PROTECTED
// because it churns a lot of values so trigering write barriers every time is very costly.
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE,
.flags = RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_EMBEDDABLE,
};

static rvalue_stack *rvalue_stack_spill(rvalue_stack *old_stack, VALUE *handle, rvalue_stack **stack_ref)
Expand Down Expand Up @@ -511,7 +514,7 @@ static const rb_data_type_t JSON_Parser_frame_stack_type = {
.dfree = json_frame_stack_free,
.dsize = json_frame_stack_memsize,
},
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE,
.flags = RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE,
};

static json_frame_stack *json_frame_stack_spill(json_frame_stack *old_stack, VALUE *handle, json_frame_stack **stack_ref)
Expand Down Expand Up @@ -2180,7 +2183,7 @@ static const rb_data_type_t JSON_ParserConfig_type = {
.dsize = JSON_ParserConfig_memsize,
.dcompact = JSON_ParserConfig_compact,
},
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_EMBEDDABLE,
.flags = RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_EMBEDDABLE,
};

static VALUE cJSON_parser_s_allocate(VALUE klass)
Expand Down Expand Up @@ -2265,7 +2268,7 @@ static const rb_data_type_t JSON_ResumableParser_type = {
// RUBY_TYPED_WB_PROTECTED is deliberately not declared because
// this is a superset of JSON_Parser_rvalue_stack_type, so we'd need
// to trigger a lot of write barriers.
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE,
.flags = RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_EMBEDDABLE,
};

static VALUE cResumableParser_allocate(VALUE klass)
Expand Down Expand Up @@ -2712,7 +2715,7 @@ static VALUE cResumableParser_rest(VALUE self)
}

/*
* call-seq: value? -> true or false
* call-seq: eos? -> true or false
*
* Returns whether the internal buffer has been entirely consumed.
*/
Expand Down Expand Up @@ -2812,7 +2815,9 @@ void Init_parser(void)

i_new = rb_intern("new");
i_try_convert = rb_intern("try_convert");
#ifndef HAVE_RB_STR_TO_INTERNED_STR
i_uminus = rb_intern("-@");
#endif
i_encode = rb_intern("encode");
i_at_line = rb_intern("@line");
i_at_column = rb_intern("@column");
Expand Down
8 changes: 6 additions & 2 deletions ext/openssl/ossl_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -697,11 +697,12 @@ to_der_internal(VALUE self, int constructed, int indef_len, VALUE body)
int tag_number = ossl_asn1_tag(self);
int default_tag_number = ossl_asn1_default_tag(self);
int body_length, total_length;
VALUE tagging = ossl_asn1_get_tagging(self);
VALUE str;
unsigned char *p;

body_length = RSTRING_LENINT(body);
if (ossl_asn1_get_tagging(self) == sym_EXPLICIT) {
if (tagging == sym_EXPLICIT) {
int inner_length, e_encoding = indef_len ? 2 : 1;

if (default_tag_number == -1)
Expand All @@ -722,7 +723,7 @@ to_der_internal(VALUE self, int constructed, int indef_len, VALUE body)
ASN1_put_eoc(&p); /* For wrapper object */
}
}
else {
else if (NIL_P(tagging) || tagging == sym_IMPLICIT) {
total_length = ASN1_object_size(encoding, body_length, tag_number);
str = rb_str_new(NULL, total_length);
p = (unsigned char *)RSTRING_PTR(str);
Expand All @@ -732,6 +733,9 @@ to_der_internal(VALUE self, int constructed, int indef_len, VALUE body)
if (indef_len)
ASN1_put_eoc(&p);
}
else {
ossl_raise(eASN1Error, "invalid tagging method");
}
assert(p - (unsigned char *)RSTRING_PTR(str) == total_length);
return str;
}
Expand Down
2 changes: 0 additions & 2 deletions ext/psych/psych_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
VALUE cPsychParser;

static ID id_read;
static ID id_path;
static ID id_empty;
static ID id_start_stream;
static ID id_end_stream;
Expand Down Expand Up @@ -559,7 +558,6 @@ void Init_psych_parser(void)
rb_define_method(cPsychParser, "mark", mark, 0);

id_read = rb_intern("read");
id_path = rb_intern("path");
id_empty = rb_intern("empty");
id_start_stream = rb_intern("start_stream");
id_end_stream = rb_intern("end_stream");
Expand Down
6 changes: 6 additions & 0 deletions hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -5138,7 +5138,11 @@ rb_hash_new_with_bulk_insert(long argc, const VALUE *argv)
return val;
}

#undef USE_ORIGENVIRON
#if !defined(_WIN32) && !(defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
# define USE_ORIGENVIRON 1
static char **origenviron;
#endif
#ifdef _WIN32
#define GET_ENVIRON(e) ((e) = rb_w32_get_environ())
#define FREE_ENVIRON(e) rb_w32_free_environ(e)
Expand Down Expand Up @@ -7678,7 +7682,9 @@ Init_Hash(void)
* Hack to get RDoc to regard ENV as a class:
* envtbl = rb_define_class("ENV", rb_cObject);
*/
#ifdef USE_ORIGENVIRON
origenviron = environ;
#endif
envtbl = TypedData_Wrap_Struct(rb_cObject, &env_data_type, NULL);
rb_extend_object(envtbl, rb_mEnumerable);
RB_OBJ_SET_SHAREABLE(envtbl);
Expand Down
30 changes: 30 additions & 0 deletions internal/io_buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include <ruby/ruby.h>
#include <ruby/io/buffer.h>

RUBY_SYMBOL_EXPORT_BEGIN

/**
* Wrap string_or_buffer as a read-only IO::Buffer view and invoke callback(buffer, argument).
*
* - IO::Buffer: callback is called directly with no wrapping.
* - String: locked to prevent GC compaction from moving the backing memory,
* wrapped in a read-only IO::Buffer, callback called inside rb_ensure, buffer
* freed and string unlocked on exit.
* - Other: TypeError raised.
*/
VALUE rb_io_buffer_for_reading(VALUE string_or_buffer, VALUE (*callback)(VALUE buffer, VALUE argument), VALUE argument);

/**
* Wrap string_or_buffer as a writable IO::Buffer view and invoke callback(buffer, argument).
*
* - Read-only IO::Buffer: ArgumentError raised.
* - IO::Buffer: callback is called directly with no wrapping.
* - String: locked, wrapped in a writable IO::Buffer, callback called inside
* rb_ensure, buffer freed and string unlocked on exit.
* - Other: TypeError raised.
*/
VALUE rb_io_buffer_for_writing(VALUE string_or_buffer, VALUE (*callback)(VALUE buffer, VALUE argument), VALUE argument);

RUBY_SYMBOL_EXPORT_END
7 changes: 3 additions & 4 deletions io.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,10 @@ VALUE rb_mWaitWritable;

static VALUE rb_eEAGAINWaitReadable;
static VALUE rb_eEAGAINWaitWritable;
#if EAGAIN != EWOULDBLOCK
static VALUE rb_eEWOULDBLOCKWaitReadable;
static VALUE rb_eEWOULDBLOCKWaitWritable;
#endif
static VALUE rb_eEINPROGRESSWaitWritable;
static VALUE rb_eEINPROGRESSWaitReadable;

Expand All @@ -208,7 +210,7 @@ VALUE rb_default_rs;

static VALUE argf;

static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding, id_fileno;
static ID id_write, id_read, id_flush, id_readpartial, id_set_encoding, id_fileno;
static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
static VALUE sym_textmode, sym_binmode, sym_autoclose;
static VALUE sym_SET, sym_CUR, sym_END;
Expand Down Expand Up @@ -15698,7 +15700,6 @@ Init_IO(void)

id_write = rb_intern_const("write");
id_read = rb_intern_const("read");
id_getc = rb_intern_const("getc");
id_flush = rb_intern_const("flush");
id_readpartial = rb_intern_const("readpartial");
id_set_encoding = rb_intern_const("set_encoding");
Expand Down Expand Up @@ -15746,10 +15747,8 @@ Init_IO(void)
rb_eEAGAINWaitWritable = rb_define_class_under(rb_cIO, "EAGAINWaitWritable", rb_eEAGAIN);
rb_include_module(rb_eEAGAINWaitWritable, rb_mWaitWritable);
#if EAGAIN == EWOULDBLOCK
rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
/* same as IO::EAGAINWaitReadable */
rb_define_const(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable);
rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
/* same as IO::EAGAINWaitWritable */
rb_define_const(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable);
#else
Expand Down
Loading