Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1c664d8
Defer unloading box-local extension DLLs on Windows
hsbt Aug 26, 2026
efa8744
Revert "[ruby/rubygems] Skip the RUBY_BOX gem CLI canary on Windows"
hsbt Aug 26, 2026
04c367a
[ruby/resolv] Enforce DNS label and name size limits when encoding
hsbt Jul 31, 2026
f681ca8
[ruby/resolv] Count the encoded form when limiting DNS name length
hsbt Jul 31, 2026
5bf9c3c
[ruby/resolv] Raise ResolvError for an oversized name
hsbt Jul 31, 2026
d17b921
[ruby/resolv] Make the 63 octet label limit an invariant of Label::Str
hsbt Jul 31, 2026
eafd447
[ruby/resolv] Describe the label limit the way the encoder now applie…
hsbt Jul 31, 2026
55f7313
[ruby/resolv] Do not register on-demand classes for unknown DNS types…
hsbt Jul 16, 2026
1745c36
[ruby/resolv] Shorten the comments added in the previous commit
hsbt Jul 31, 2026
c77b594
[ruby/resolv] Compare generic resources by their type and class values
hsbt Jul 31, 2026
5ee95de
[ruby/resolv] Compare generic classes by descent and stop building th…
hsbt Jul 31, 2026
4dd33ca
ZJIT: Fix lattice bug in SSA minimization (#18482)
jacob-shops Aug 27, 2026
c56fa94
Don't record EP escape in JIT when not enabled
peterzhu2118 Aug 27, 2026
5537927
Bump taiki-e/install-action
dependabot[bot] Aug 27, 2026
5496feb
[ruby/rubygems] Drop the settings write behind the removed --no-prune…
hsbt Aug 26, 2026
1b33a60
[ruby/rubygems] Rename the no_prune setting to keep_outdated_cache
hsbt Aug 26, 2026
3d13990
ZJIT: Eliminate constant-valued block params (#18369)
tekknolagi Aug 27, 2026
38a7467
[ruby/rubygems] Error out when `bundle init --gemspec` gets no specif…
hsbt Aug 26, 2026
b4322d9
Fix reference update bug in iseq_scan_bits
peterzhu2118 Aug 27, 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
2 changes: 1 addition & 1 deletion .github/workflows/zjit-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ jobs:
rustup install ${{ matrix.rust_version }} --profile minimal
rustup default ${{ matrix.rust_version }}

- uses: taiki-e/install-action@6cd13508893c0e7eab5f273c2575d3859bd7229a # v2.86.6
- uses: taiki-e/install-action@b6ff580856c41316412a0b9b60540fbc6f8c82cc # v2.86.7
with:
tool: nextest@0.9
if: ${{ matrix.test_task == 'zjit-check' }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/zjit-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ jobs:
ruby-version: '3.1'
bundler: none

- uses: taiki-e/install-action@6cd13508893c0e7eab5f273c2575d3859bd7229a # v2.86.6
- uses: taiki-e/install-action@b6ff580856c41316412a0b9b60540fbc6f8c82cc # v2.86.7
with:
tool: nextest@0.9
if: ${{ matrix.test_task == 'zjit-check' }}
Expand Down
51 changes: 36 additions & 15 deletions box.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ bool ruby_box_crashed = false; // extern, changed only in vm.c

VALUE rb_resolve_feature_path(VALUE klass, VALUE fname);
static VALUE rb_box_inspect(VALUE obj);
static void cleanup_all_local_extensions(VALUE libmap);

void
rb_box_set_gem_flags(rb_box_gem_flags_t *flags)
Expand Down Expand Up @@ -303,8 +302,6 @@ box_entry_free(void *ptr)
st_foreach(box->classext_cow_classes, free_classext_for_box, (st_data_t)box);
}

cleanup_all_local_extensions(box->ruby_dln_libmap);

free_box_st_tables(ptr);
SIZED_FREE(box);
}
Expand Down Expand Up @@ -808,24 +805,48 @@ rb_box_cleanup_local_extension(VALUE cleanup)
(void)p;
}

static int
cleanup_local_extension_i(VALUE key, VALUE value, VALUE arg)
{
#if defined(_WIN32)
HMODULE h = (HMODULE)NUM2PTR(value);
WCHAR module_path[MAXPATHLEN];
DWORD len = GetModuleFileNameW(h, module_path, numberof(module_path));
struct box_local_ext_list {
struct box_local_ext_list *next;
HMODULE handle;
};
static struct box_local_ext_list *box_local_exts;
#endif

FreeLibrary(h);
if (len > 0 && len < numberof(module_path)) DeleteFileW(module_path);
void
rb_box_defer_unload_local_extension(void *handle)
{
#if defined(_WIN32)
/* A box-local copy of an extension DLL must stay loaded as long as
* objects created by it can be finalized; unloading is deferred to
* rb_box_unload_local_extensions after the objspace is destructed.
* The loaded copy cannot be deleted on Windows, so the file is also
* removed there instead of in box_ext_cleanup_free. */
struct box_local_ext_list *ext = malloc(sizeof(struct box_local_ext_list));
if (!ext) return;
ext->handle = (HMODULE)handle;
ext->next = box_local_exts;
box_local_exts = ext;
#endif
return ST_DELETE;
}

static void
cleanup_all_local_extensions(VALUE libmap)
void
rb_box_unload_local_extensions(void)
{
rb_hash_foreach(libmap, cleanup_local_extension_i, 0);
#if defined(_WIN32)
struct box_local_ext_list *ext = box_local_exts;
box_local_exts = NULL;
while (ext) {
struct box_local_ext_list *next = ext->next;
WCHAR module_path[MAXPATHLEN];
DWORD len = GetModuleFileNameW(ext->handle, module_path, numberof(module_path));

FreeLibrary(ext->handle);
if (len > 0 && len < numberof(module_path)) DeleteFileW(module_path);
free(ext);
ext = next;
}
#endif
}

VALUE
Expand Down
2 changes: 2 additions & 0 deletions internal/box.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ VALUE rb_get_box_object(rb_box_t *ns);

VALUE rb_box_local_extension(VALUE box, VALUE fname, VALUE path, VALUE *cleanup);
void rb_box_cleanup_local_extension(VALUE cleanup);
void rb_box_defer_unload_local_extension(void *handle);
void rb_box_unload_local_extensions(void);

void rb_initialize_mandatory_boxes(void);
void rb_box_init_done(void);
Expand Down
19 changes: 12 additions & 7 deletions iseq.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,14 @@ rb_iseq_free(const rb_iseq_t *iseq)
iseq_clear_ic_references(iseq);
struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
#if USE_YJIT
rb_yjit_iseq_free(iseq);
if (rb_yjit_enabled_p) rb_yjit_iseq_free(iseq);
if (FL_TEST_RAW((VALUE)iseq, ISEQ_TRANSLATED)) {
RUBY_ASSERT(rb_yjit_live_iseq_count > 0);
rb_yjit_live_iseq_count--;
}
#endif
#if USE_ZJIT
rb_zjit_iseq_free(iseq);
if (rb_zjit_enabled_p) rb_zjit_iseq_free(iseq);
#endif
SIZED_FREE_N(body->iseq_encoded, body->iseq_size);
SIZED_FREE_N(body->insns_info.body, body->insns_info.size);
Expand Down Expand Up @@ -300,11 +300,16 @@ iseq_scan_bits(unsigned int page, iseq_bits_t bits, VALUE *code, VALUE *original

while (bits) {
offset = ntz_intptr(bits);
VALUE op = code[page_offset + offset];
rb_gc_mark_and_move(&code[page_offset + offset]);
VALUE newop = code[page_offset + offset];
if (original_iseq && newop != op) {
original_iseq[page_offset + offset] = newop;
if (original_iseq) {
VALUE op = original_iseq[page_offset + offset];
rb_gc_mark_and_move(&code[page_offset + offset]);
VALUE newop = code[page_offset + offset];
if (op != newop) {
original_iseq[page_offset + offset] = newop;
}
}
else {
rb_gc_mark_and_move(&code[page_offset + offset]);
}
bits &= bits - 1; // Reset Lowest Set Bit (BLSR)
}
Expand Down
9 changes: 5 additions & 4 deletions lib/bundler/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,12 @@ def remove(*gems)
method_option "with", type: :array, banner: "Include gems that are part of the specified named group (removed)."
method_option "cooldown", type: :numeric, banner: "Only consider gem versions published at least N days ago. Use 0 to disable."
def install
%w[clean deployment frozen no-prune path shebang without with].each do |option|
%w[clean deployment frozen path shebang without with].each do |option|
remembered_flag_deprecation(option)
end

remembered_flag_deprecation("no-prune", option_name: "keep_outdated_cache")

print_remembered_flag_deprecation("--system", "path.system", "true") if ARGV.include?("--system")

remembered_flag_deprecation("deployment", negative: true)
Expand Down Expand Up @@ -473,9 +475,8 @@ def cache
print_remembered_flag_deprecation("--all", "cache_all", "true") if ARGV.include?("--all")
print_remembered_flag_deprecation("--no-all", "cache_all", "false") if ARGV.include?("--no-all")

%w[frozen no-prune].each do |option|
remembered_flag_deprecation(option)
end
remembered_flag_deprecation("frozen")
remembered_flag_deprecation("no-prune", option_name: "keep_outdated_cache")

if flag_passed?("--path")
removed_message =
Expand Down
4 changes: 4 additions & 0 deletions lib/bundler/cli/init.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ def run
end

spec = Bundler.load_gemspec_uncached(gemspec)
unless spec
Bundler.ui.error "Gem specification #{gemspec} did not produce a specification"
exit 1
end

File.open(gemfile, "wb") do |file|
file << "# Generated from #{gemspec}\n"
Expand Down
2 changes: 0 additions & 2 deletions lib/bundler/cli/install.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ def normalize_settings
Bundler::CLI::Common.validate_cooldown!(options["cooldown"])
Bundler.settings.set_command_option_if_given :cooldown, options["cooldown"]

Bundler.settings.set_command_option_if_given :no_prune, options["no-prune"]

Bundler.settings.set_command_option_if_given :no_install, options["no-install"]

Bundler.settings.set_command_option_if_given :clean, options["clean"]
Expand Down
4 changes: 3 additions & 1 deletion lib/bundler/man/bundle-config.1
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ The store can also be selected per host with \fBcredential_store\.<host>\fR (\fB
.IP "\(bu" 4
\fBjobs\fR (\fBBUNDLE_JOBS\fR): The number of gems Bundler can download and install in parallel\. Defaults to the number of available processors\.
.IP "\(bu" 4
\fBkeep_outdated_cache\fR (\fBBUNDLE_KEEP_OUTDATED_CACHE\fR): Whether Bundler should leave outdated gems unpruned when caching\. Defaults to false\.
.IP "\(bu" 4
\fBlockfile\fR (\fBBUNDLE_LOCKFILE\fR): The path to the lockfile that bundler should use\. By default, Bundler adds \fB\.lock\fR to the end of the \fBgemfile\fR entry\. Can be set to \fBfalse\fR in the Gemfile to disable lockfile creation entirely (see gemfile(5))\.
.IP "\(bu" 4
\fBlockfile_checksums\fR (\fBBUNDLE_LOCKFILE_CHECKSUMS\fR): Whether Bundler should include a checksums section in new lockfiles, to protect from compromised gem sources\. Defaults to true\. Bundler's own checksum is only included when its \fB\.gem\fR file is cached, which may not be the case when Bundler is installed as a default gem\.
Expand All @@ -161,7 +163,7 @@ The store can also be selected per host with \fBcredential_store\.<host>\fR (\fB
.IP "\(bu" 4
\fBno_install_plugin\fR (\fBBUNDLE_NO_INSTALL_PLUGIN\fR): Whether Bundler should skip installing RubyGems plugins during installation\. When set, plugin files are not written to the plugins directory\. To install plugins later, unset this setting and run \fBbundle pristine <gem>\fR\.
.IP "\(bu" 4
\fBno_prune\fR (\fBBUNDLE_NO_PRUNE\fR): Whether Bundler should leave outdated gems unpruned when caching\.
\fBno_prune\fR (\fBBUNDLE_NO_PRUNE\fR): Deprecated name for \fBkeep_outdated_cache\fR\. Each priority level is checked for \fBkeep_outdated_cache\fR and then for \fBno_prune\fR, and the first value found wins\. \fBno_prune\fR will be removed in Bundler 5\.
.IP "\(bu" 4
\fBonly\fR (\fBBUNDLE_ONLY\fR): A space\-separated list of groups to install only gems of the specified groups\. Please check carefully if you want to install also gems without a group, because they get put inside \fBdefault\fR group\. For example \fBonly test:default\fR will install all gems specified in test group and without one\.
.IP "\(bu" 4
Expand Down
7 changes: 6 additions & 1 deletion lib/bundler/man/bundle-config.1.ronn
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,9 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
* `jobs` (`BUNDLE_JOBS`):
The number of gems Bundler can download and install in parallel.
Defaults to the number of available processors.
* `keep_outdated_cache` (`BUNDLE_KEEP_OUTDATED_CACHE`):
Whether Bundler should leave outdated gems unpruned when caching. Defaults
to false.
* `lockfile` (`BUNDLE_LOCKFILE`):
The path to the lockfile that bundler should use. By default, Bundler adds
`.lock` to the end of the `gemfile` entry. Can be set to `false` in the
Expand All @@ -295,7 +298,9 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
When set, plugin files are not written to the plugins directory.
To install plugins later, unset this setting and run `bundle pristine <gem>`.
* `no_prune` (`BUNDLE_NO_PRUNE`):
Whether Bundler should leave outdated gems unpruned when caching.
Deprecated name for `keep_outdated_cache`. Each priority level is checked
for `keep_outdated_cache` and then for `no_prune`, and the first value
found wins. `no_prune` will be removed in Bundler 5.
* `only` (`BUNDLE_ONLY`):
A space-separated list of groups to install only gems of the specified groups.
Please check carefully if you want to install also gems without a group, because
Expand Down
2 changes: 1 addition & 1 deletion lib/bundler/runtime.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def cache(custom_path = nil, local = false)
FileUtils.touch(File.expand_path("../.bundlecache", git_dir))
end

prune_cache(cache_path) unless Bundler.settings[:no_prune]
prune_cache(cache_path) unless Bundler.settings[:keep_outdated_cache]
end

def prune_cache(cache_path)
Expand Down
49 changes: 39 additions & 10 deletions lib/bundler/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Settings
ignore_messages
init_gems_rb
inline
keep_outdated_cache
lockfile_checksums
no_build_extension
no_install
Expand Down Expand Up @@ -95,6 +96,14 @@ class Settings
"BUNDLE_UPDATE_REQUIRES_ALL_FLAG" => false,
}.freeze

##
# Settings renamed in Bundler 4, mapping the current name to the one it
# replaced. The old name is still read, and goes away in Bundler 5.

RENAMED_KEYS = {
"keep_outdated_cache" => "no_prune",
}.freeze

def initialize(root = nil)
@root = root
@local_config = load_config(local_config_file)
Expand All @@ -111,16 +120,7 @@ def initialize(root = nil)
end

def [](name)
key = key_for(name)

value = nil
configs.each do |_, config|
value = config[key]
next if value.nil?
break
end

converted_value(value, name)
converted_value(configured_value(name), name)
end

def set_command_option(key, value)
Expand Down Expand Up @@ -398,6 +398,35 @@ def value_for(name, config)
converted_value(config[key_for(name)], name)
end

##
# A renamed setting is resolved one level at a time rather than by looking
# for the current name everywhere first, so that the old name keeps the
# documented priority order: an old name set locally still beats a current
# name set globally.

def configured_value(name)
key = key_for(name)
old_name = RENAMED_KEYS[self.class.key_to_s(name)]
old_key = key_for(old_name) if old_name

configs.each do |_, config|
value = config[key]
return value unless value.nil?

next if old_key.nil?

value = config[old_key]
next if value.nil?

SharedHelpers.feature_deprecated! "The `#{old_name}` setting has been renamed to `#{name}` and will be " \
"removed in Bundler 5. Use `#{name}` instead."

return value
end

nil
end

def parent_setting_for(name)
split_specific_setting_for(name)[0]
end
Expand Down
Loading