Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 8 additions & 9 deletions gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,8 @@ rb_gc_shutdown_call_finalizer_p(VALUE obj)
{
switch (BUILTIN_TYPE(obj)) {
case T_DATA:
if (!ruby_free_at_exit_p() && (!DATA_PTR(obj) || !RDATA(obj)->dfree)) return false;
if (!ruby_free_at_exit_p() && !DATA_PTR(obj)) return false;
if (!ruby_free_at_exit_p() && !RTYPEDDATA_P(obj) && !RDATA(obj)->dfree) return false;
if (rb_obj_is_thread(obj)) return false;
if (rb_obj_is_mutex(obj)) return false;
if (rb_obj_is_fiber(obj)) return false;
Expand Down Expand Up @@ -1142,14 +1143,16 @@ rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FU
{
RUBY_ASSERT_ALWAYS(dfree != (RUBY_DATA_FUNC)1);
if (klass) rb_data_object_check(klass);
VALUE obj = rb_newobj(GET_EC(), klass, T_DATA, ROOT_SHAPE_ID, !dmark, sizeof(struct RTypedData));
VALUE obj = rb_newobj(GET_EC(), klass, T_DATA, ROOT_SHAPE_ID, !dmark, sizeof(struct RData));

rb_gc_register_pinning_obj(obj);

struct RData *data = (struct RData *)obj;
data->fields_obj = 0;
data->_reserved = 0;
data->data = datap;
data->dmark = dmark;
data->dfree = dfree;
data->data = datap;

return obj;
}
Expand Down Expand Up @@ -3512,9 +3515,7 @@ rb_gc_mark_children(void *objspace, VALUE obj)
bool typed_data = RTYPEDDATA_P(obj);
void *const ptr = typed_data ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj);

if (typed_data) {
gc_mark_internal(RTYPEDDATA(obj)->fields_obj);
}
gc_mark_internal(RTYPEDDATA(obj)->fields_obj);

if (ptr) {
if (typed_data && gc_declarative_marking_p(RTYPEDDATA_TYPE(obj))) {
Expand Down Expand Up @@ -4462,9 +4463,7 @@ rb_gc_update_object_references(void *objspace, VALUE obj)
bool typed_data = RTYPEDDATA_P(obj);
void *const ptr = typed_data ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj);

if (typed_data) {
UPDATE_IF_MOVED(objspace, RTYPEDDATA(obj)->fields_obj);
}
UPDATE_IF_MOVED(objspace, RTYPEDDATA(obj)->fields_obj);

if (ptr) {
if (typed_data && gc_declarative_marking_p(RTYPEDDATA_TYPE(obj))) {
Expand Down
2 changes: 1 addition & 1 deletion include/ruby/internal/abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* In released versions of Ruby, this number is not defined since teeny
* versions of Ruby should guarantee ABI compatibility.
*/
#define RUBY_ABI_VERSION 1
#define RUBY_ABI_VERSION 2

/* Windows does not support weak symbols so ruby_abi_version will not exist
* in the shared library. */
Expand Down
18 changes: 12 additions & 6 deletions include/ruby/internal/core/rdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,24 @@ typedef void (*RUBY_DATA_FUNC)(void*);
* @shyouhei tried to add RBIMPL_ATTR_DEPRECATED for this type but that yielded
* too many warnings in the core. Maybe we want to retry later... Just add
* deprecated document for now.
*
* RData shares its initial fields with struct ::RTypedData so the VM can handle
* per-object fields without checking whether a T_DATA object is typed or legacy.
*/
struct RData {

/** Basic part, including flags and class. */
struct RBasic basic;

/** @internal Direct reference to the slots that hold instance variables, if any. */
VALUE fields_obj;

/** @internal Padding where ::RTypedData stores its type, so both structs place data at the same offset. */
VALUE _reserved;

/** Pointer to the actual C level struct that you want to wrap. */
void *data;

/**
* This function is called when the object is experiencing GC marks. If it
* contains references to other Ruby objects, you need to mark them also.
Expand All @@ -141,12 +153,6 @@ struct RData {
* impossible at that moment (that is why GC runs).
*/
RUBY_DATA_FUNC dfree;

/** Pointer to the actual C level struct that you want to wrap.
* This is after dmark and dfree to allow DATA_PTR to continue to work for
* both RData and non-embedded RTypedData.
*/
void *data;
};

RBIMPL_SYMBOL_EXPORT_BEGIN()
Expand Down
1 change: 1 addition & 0 deletions include/ruby/internal/core/rtypeddata.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ struct RTypedData {
};

#if !defined(__cplusplus) || __cplusplus >= 201103L
RBIMPL_STATIC_ASSERT(fields_obj_in_rdata, offsetof(struct RData, fields_obj) == offsetof(struct RTypedData, fields_obj));
RBIMPL_STATIC_ASSERT(data_in_rtypeddata, offsetof(struct RData, data) == offsetof(struct RTypedData, data));
#endif

Expand Down
6 changes: 3 additions & 3 deletions jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ enum jit_bindgen_constants {
// Field offset for prime classext's fields_obj from a class pointer
RCLASS_OFFSET_PRIME_FIELDS_OBJ = offsetof(struct RClass_and_rb_classext_t, classext.fields_obj),

// Field offset for fields_obj in RTypedData
RTYPEDDATA_OFFSET_FIELDS_OBJ = offsetof(struct RTypedData, fields_obj),
// Field offset for fields_obj in T_DATA
TDATA_OFFSET_FIELDS_OBJ = offsetof(struct RTypedData, fields_obj),

// Field offsets for the RString struct
RUBY_OFFSET_RSTRING_LEN = offsetof(struct RString, len),
Expand Down Expand Up @@ -568,7 +568,7 @@ rb_jit_class_fields_embedded_p(VALUE klass)
}

bool
rb_jit_typed_data_fields_embedded_p(VALUE obj)
rb_jit_data_fields_embedded_p(VALUE obj)
{
VALUE fields_obj = RTYPEDDATA(obj)->fields_obj;
return !fields_obj || !FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP);
Expand Down
4 changes: 3 additions & 1 deletion lib/rubygems/package.rb
Original file line number Diff line number Diff line change
Expand Up @@ -743,9 +743,11 @@ def limit_read(io, name, limit)
if Gem.win_platform?
# Create a symlink and fallback to copy the file or directory on Windows,
# where symlink creation needs special privileges in form of the Developer Mode.
# JRuby on Windows raises TypeError from the wincode path-conversion helper
# when it cannot create the symlink, so fall back to copy in that case too.
def create_symlink(old_name, new_name)
File.symlink(old_name, new_name)
rescue Errno::EACCES
rescue Errno::EACCES, TypeError
from = File.expand_path(old_name, File.dirname(new_name))
FileUtils.cp_r(from, new_name)
end
Expand Down
3 changes: 1 addition & 2 deletions shape.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,8 +428,7 @@ rb_obj_using_gen_fields_table_p(VALUE obj)
{
switch (BUILTIN_TYPE(obj)) {
case T_DATA:
if (RTYPEDDATA_P(obj)) return false;
break;
return false;

case T_STRUCT:
if (!FL_TEST_RAW(obj, RSTRUCT_GEN_FIELDS)) return false;
Expand Down
2 changes: 1 addition & 1 deletion spec/bundler/realworld/fixtures/warbler/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ source "https://rubygems.org"

gem "demo", path: "./demo"
gem "jruby-jars", "~> 10.0"
gem "warbler", github: "https://github.com/jruby/warbler/pull/557"
gem "warbler", "~> 2.1"
26 changes: 11 additions & 15 deletions spec/bundler/realworld/fixtures/warbler/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
GIT
remote: https://github.com/jruby/warbler.git
revision: 3a3a89e9a055ab1badb4e6fee860e8617b4acfe1
ref: refs/pull/557/head
specs:
warbler (2.0.5)
jruby-jars (>= 9.0.0)
jruby-rack (>= 1.1.1, < 1.3)
rake (>= 13.0.3)
rexml (~> 3.0)
rubyzip (>= 1.0.0)

PATH
remote: demo
specs:
Expand All @@ -19,10 +7,18 @@ GEM
remote: https://rubygems.org/
specs:
jruby-jars (10.0.0.1)
jruby-rack (1.2.2)
jruby-rack (1.2.7)
ostruct (0.6.3)
rake (13.3.0)
rexml (3.4.2)
rubyzip (2.4.1)
rubyzip (3.3.0)
warbler (2.1.0)
jruby-jars (>= 9.4, < 10.1)
jruby-rack (>= 1.2.3, < 1.3)
ostruct (~> 0.6.2)
rake (~> 13.0, >= 13.0.3)
rexml (~> 3.0)
rubyzip (>= 3.0.0)

PLATFORMS
arm64-darwin
Expand All @@ -33,7 +29,7 @@ PLATFORMS
DEPENDENCIES
demo!
jruby-jars (~> 10.0)
warbler!
warbler (~> 2.1)

BUNDLED WITH
4.1.0.dev
23 changes: 22 additions & 1 deletion test/rubygems/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,32 @@
require "fileutils"
require "pathname"
require "pp"
require "rubygems/installer"
require "rubygems/package"
require "shellwords"
require "tmpdir"
require "rubygems/vendor/uri/lib/uri"
require "zlib"
require_relative "mock_gem_ui"

# JRuby on Windows raises TypeError inside File.symlink (the wincode helper
# trips on a nil path), so any test that exercises Gem::Installer's symlink
# branch fails to even install the gem. Real users hit the wrapper branch via
# `gem install` (DependencyInstaller passes wrappers: true), so mirror that
# default for direct Gem::Installer.at callers in the test suite.
if Gem.win_platform? && Gem.java_platform?
module Gem::InstallerDefaultWrappersOnJRubyWindows
def at(path, options = {})
super(path, { wrappers: true }.merge(options))
end

def for_spec(spec, options = {})
super(spec, { wrappers: true }.merge(options))
end
end
Gem::Installer.singleton_class.prepend(Gem::InstallerDefaultWrappersOnJRubyWindows)
end

module Gem
##
# Allows setting the gem path searcher.
Expand Down Expand Up @@ -1268,11 +1287,13 @@ def symlink_supported?
if @@symlink_supported.nil?
begin
File.symlink(File.join(@tempdir, "a"), File.join(@tempdir, "b"))
File.readlink(File.join(@tempdir, "b"))
rescue NotImplementedError, SystemCallError
@@symlink_supported = false
else
File.unlink(File.join(@tempdir, "b"))
@@symlink_supported = true
ensure
File.unlink(File.join(@tempdir, "b")) if File.symlink?(File.join(@tempdir, "b"))
end
end
@@symlink_supported
Expand Down
5 changes: 4 additions & 1 deletion test/rubygems/test_gem.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ def test_self_install_permissions_with_format_executable_and_non_standard_ruby_i
end

def assert_self_install_permissions(format_executable: false, data_mode: 0o640)
omit "FileUtils.install signature differs on JRuby/Windows" if Gem.win_platform? && Gem.java_platform?

mask = Gem.win_platform? ? 0o700 : 0o777
options = {
dir_mode: 0o500,
Expand Down Expand Up @@ -199,7 +201,8 @@ def assert_self_install_permissions(format_executable: false, data_mode: 0o640)
end
assert_equal(expected, result)
ensure
File.chmod(0o755, *Dir.glob(@gemhome + "/gems/**/"))
files = Dir.glob(@gemhome + "/gems/**/")
File.chmod(0o755, *files) unless files.empty?
end

def test_require_missing
Expand Down
2 changes: 2 additions & 0 deletions test/rubygems/test_gem_commands_open_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ def gem(name, version = "1.0")
end

def test_execute
omit "JRuby on Windows spawns the editor with a different cwd" if Gem.win_platform? && Gem.java_platform?

@cmd.options[:args] = %w[foo]
@cmd.options[:editor] = (ruby_with_rubygems_in_load_path + ["-e", "puts(ARGV,Dir.pwd)", "--"]).join(" ")

Expand Down
7 changes: 6 additions & 1 deletion test/rubygems/test_gem_installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -689,8 +689,11 @@ def test_generate_bin_symlink_update_remove_wrapper

def test_generate_bin_symlink_win32
old_win_platform = Gem.win_platform?
Gem.win_platform = true
old_alt_separator = File::ALT_SEPARATOR

omit "JRuby on Windows still creates the symlink so the wrapper branch is not exercised" if Gem.win_platform? && Gem.java_platform?

Gem.win_platform = true
File.__send__(:remove_const, :ALT_SEPARATOR)
File.const_set(:ALT_SEPARATOR, "\\")

Expand Down Expand Up @@ -743,6 +746,8 @@ def test_generate_bin_uses_default_shebang
end

def test_generate_bin_with_dangling_symlink
omit "JRuby on Windows still creates the symlink so the wrapper branch is not exercised" if Gem.win_platform? && Gem.java_platform?

gem_with_dangling_symlink = File.expand_path("packages/ascii_binder-0.1.10.1.gem", __dir__)

installer = Gem::Installer.at(
Expand Down
8 changes: 3 additions & 5 deletions test/rubygems/test_gem_path_support.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,12 @@ def test_initialize_spec
end

def test_gem_paths_do_not_contain_symlinks
pend "symlinks not supported" unless symlink_supported?

dir = "#{@tempdir}/realgemdir"
symlink = "#{@tempdir}/symdir"
Dir.mkdir dir
begin
File.symlink(dir, symlink)
rescue NotImplementedError, SystemCallError
pend "symlinks not supported"
end
File.symlink(dir, symlink)
not_existing = "#{@tempdir}/does_not_exist"
path = "#{symlink}#{File::PATH_SEPARATOR}#{not_existing}"

Expand Down
2 changes: 2 additions & 0 deletions test/rubygems/test_gem_safe_marshal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ def test_hash_with_default_value
end

def test_hash_with_compare_by_identity
pend "Marshal.dump of a compare_by_identity Hash emits an unexpected ivar on jruby" if RUBY_ENGINE == "jruby"

with_const(Gem::SafeMarshal, :PERMITTED_CLASSES, %w[Hash]) do
assert_safe_load_as Hash.new.compare_by_identity.tap {|h|
h[+"a"] = 1
Expand Down
2 changes: 2 additions & 0 deletions test/rubygems/test_gem_source_git.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ def test_checkout_local_cached
end

def test_checkout_submodules
omit "JRuby on Windows hits git submodule path differences" if Gem.win_platform? && Gem.java_platform?

# We need to allow to checkout submodules with file:// protocol
# CVE-2022-39253
# https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
Expand Down
6 changes: 3 additions & 3 deletions test/rubygems/test_gem_specification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ def test_self_load_escape_curly
write_file full_path do |io|
io.write @a2.to_ruby_for_cache
end
rescue Errno::EINVAL
rescue Errno::EINVAL, Errno::EACCES
pend "cannot create '#{full_path}' on this platform"
end

Expand All @@ -836,7 +836,7 @@ def test_self_load_escape_interpolation
write_file full_path do |io|
io.write @a2.to_ruby_for_cache
end
rescue Errno::EINVAL
rescue Errno::EINVAL, Errno::EACCES
pend "cannot create '#{full_path}' on this platform"
end

Expand All @@ -855,7 +855,7 @@ def test_self_load_escape_quote
write_file full_path do |io|
io.write @a2.to_ruby_for_cache
end
rescue Errno::EINVAL
rescue Errno::EINVAL, Errno::EACCES
pend "cannot create '#{full_path}' on this platform"
end

Expand Down
3 changes: 3 additions & 0 deletions test/rubygems/test_project_sanity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def teardown

def test_manifest_is_up_to_date
pend unless File.exist?("#{root}/Rakefile")
omit "JRuby on Windows cannot exec the bin/rake shebang" if Gem.win_platform? && Gem.java_platform?
rake = "#{root}/bin/rake"

_, status = Open3.capture2e(rake, "check_manifest")
Expand All @@ -37,6 +38,8 @@ def test_manifest_is_up_to_date
end

def test_require_rubygems_package
omit "JRuby on Windows fails to spawn ruby --disable-gems here" if Gem.win_platform? && Gem.java_platform?

err, status = Open3.capture2e(*ruby_with_rubygems_in_load_path, "--disable-gems", "-e", "require \"rubygems/package\"")

assert status.success?, err
Expand Down
3 changes: 3 additions & 0 deletions test/rubygems/test_require.rb
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ def test_second_gem_require_does_not_resolve_path_manually_before_going_through_

def test_realworld_default_gem
omit "this test can't work under ruby-core setup" if ruby_repo?
omit "JRuby on Windows does not register json as a default gem the same way" if Gem.win_platform? && Gem.java_platform?

cmd = <<-RUBY
$stderr = $stdout
Expand Down Expand Up @@ -786,6 +787,8 @@ def deprecated
end

def test_require_does_not_crash_when_utilizing_bundler_version_finder
omit "JRuby on Windows hits a different require path" if Gem.win_platform? && Gem.java_platform?

a1 = util_spec "a", "1.1", { "bundler" => ">= 0" }
a2 = util_spec "a", "1.2", { "bundler" => ">= 0" }
b1 = util_spec "bundler", "2.3.7"
Expand Down
Loading