summaryrefslogtreecommitdiff
path: root/spec/ruby/core
diff options
context:
space:
mode:
authorJean Boussier <byroot@ruby-lang.org>2024-02-12 12:03:36 +0100
committerJean Boussier <jean.boussier@gmail.com>2024-02-12 18:31:48 +0100
commitde1a586ecc2ee7f465f0c0a69291054136a3a819 (patch)
treed6825acfea6f796b5f5dbb2746fe7fcb1c07d580 /spec/ruby/core
parentc04782c2cb56c512e1d1b34630cb942da3aeb366 (diff)
proc.c: get rid of `CLONESETUP`
[Bug #20253] All the way down to Ruby 1.9, `Proc`, `Method`, `UnboundMethod` and `Binding` always had their own specific clone and dup routine. This caused various discrepancies with how other objects behave on `dup` and `clone. [Bug #20250], [Bug #20253]. This commit get rid of `CLONESETUP` and use the the same codepath as all other types, so ensure consistency. NB: It's still not accepting the `freeze` keyword argument on `clone`. Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
Diffstat (limited to 'spec/ruby/core')
-rw-r--r--spec/ruby/core/binding/clone_spec.rb6
-rw-r--r--spec/ruby/core/binding/dup_spec.rb6
-rw-r--r--spec/ruby/core/binding/shared/clone.rb22
-rw-r--r--spec/ruby/core/method/clone_spec.rb15
-rw-r--r--spec/ruby/core/method/dup_spec.rb15
-rw-r--r--spec/ruby/core/method/shared/dup.rb32
-rw-r--r--spec/ruby/core/proc/clone_spec.rb9
-rw-r--r--spec/ruby/core/proc/dup_spec.rb7
-rw-r--r--spec/ruby/core/proc/shared/dup.rb23
-rw-r--r--spec/ruby/core/unboundmethod/clone_spec.rb13
-rw-r--r--spec/ruby/core/unboundmethod/dup_spec.rb15
-rw-r--r--spec/ruby/core/unboundmethod/shared/dup.rb32
12 files changed, 181 insertions, 14 deletions
diff --git a/spec/ruby/core/binding/clone_spec.rb b/spec/ruby/core/binding/clone_spec.rb
index ebd40f5377..f1769ac6de 100644
--- a/spec/ruby/core/binding/clone_spec.rb
+++ b/spec/ruby/core/binding/clone_spec.rb
@@ -4,4 +4,10 @@ require_relative 'shared/clone'
describe "Binding#clone" do
it_behaves_like :binding_clone, :clone
+
+ it "preserves frozen status" do
+ bind = binding.freeze
+ bind.frozen?.should == true
+ bind.clone.frozen?.should == true
+ end
end
diff --git a/spec/ruby/core/binding/dup_spec.rb b/spec/ruby/core/binding/dup_spec.rb
index 43968213c8..55fac6e333 100644
--- a/spec/ruby/core/binding/dup_spec.rb
+++ b/spec/ruby/core/binding/dup_spec.rb
@@ -4,4 +4,10 @@ require_relative 'shared/clone'
describe "Binding#dup" do
it_behaves_like :binding_clone, :dup
+
+ it "resets frozen status" do
+ bind = binding.freeze
+ bind.frozen?.should == true
+ bind.dup.frozen?.should == false
+ end
end
diff --git a/spec/ruby/core/binding/shared/clone.rb b/spec/ruby/core/binding/shared/clone.rb
index 0e934ac1b5..1224b8ec7d 100644
--- a/spec/ruby/core/binding/shared/clone.rb
+++ b/spec/ruby/core/binding/shared/clone.rb
@@ -31,4 +31,26 @@ describe :binding_clone, shared: true do
b2.local_variable_defined?(:x).should == false
end
end
+
+ ruby_version_is "3.4" do
+ it "copies instance variables" do
+ @b1.instance_variable_set(:@ivar, 1)
+ cl = @b1.send(@method)
+ cl.instance_variables.should == [:@ivar]
+ end
+
+ it "copies the finalizer" do
+ code = <<-RUBY
+ obj = binding
+
+ ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" })
+
+ obj.clone
+
+ exit 0
+ RUBY
+
+ ruby_exe(code).lines.sort.should == ["finalized\n", "finalized\n"]
+ end
+ end
end
diff --git a/spec/ruby/core/method/clone_spec.rb b/spec/ruby/core/method/clone_spec.rb
index 3fe4000fb7..b0eb5751a9 100644
--- a/spec/ruby/core/method/clone_spec.rb
+++ b/spec/ruby/core/method/clone_spec.rb
@@ -1,14 +1,13 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
+require_relative 'shared/dup'
describe "Method#clone" do
- it "returns a copy of the method" do
- m1 = MethodSpecs::Methods.new.method(:foo)
- m2 = m1.clone
+ it_behaves_like :method_dup, :clone
- m1.should == m2
- m1.should_not equal(m2)
-
- m1.call.should == m2.call
+ it "preserves frozen status" do
+ method = Object.new.method(:method)
+ method.freeze
+ method.frozen?.should == true
+ method.clone.frozen?.should == true
end
end
diff --git a/spec/ruby/core/method/dup_spec.rb b/spec/ruby/core/method/dup_spec.rb
new file mode 100644
index 0000000000..e3e29d8a68
--- /dev/null
+++ b/spec/ruby/core/method/dup_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+require_relative 'shared/dup'
+
+describe "Method#dup" do
+ ruby_version_is "3.4" do
+ it_behaves_like :method_dup, :dup
+
+ it "resets frozen status" do
+ method = Object.new.method(:method)
+ method.freeze
+ method.frozen?.should == true
+ method.dup.frozen?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/method/shared/dup.rb b/spec/ruby/core/method/shared/dup.rb
new file mode 100644
index 0000000000..1a10b90689
--- /dev/null
+++ b/spec/ruby/core/method/shared/dup.rb
@@ -0,0 +1,32 @@
+describe :method_dup, shared: true do
+ it "returns a copy of self" do
+ a = Object.new.method(:method)
+ b = a.send(@method)
+
+ a.should == b
+ a.should_not equal(b)
+ end
+
+ ruby_version_is "3.4" do
+ it "copies instance variables" do
+ method = Object.new.method(:method)
+ method.instance_variable_set(:@ivar, 1)
+ cl = method.send(@method)
+ cl.instance_variables.should == [:@ivar]
+ end
+
+ it "copies the finalizer" do
+ code = <<-RUBY
+ obj = Object.new.method(:method)
+
+ ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" })
+
+ obj.clone
+
+ exit 0
+ RUBY
+
+ ruby_exe(code).lines.sort.should == ["finalized\n", "finalized\n"]
+ end
+ end
+end
diff --git a/spec/ruby/core/proc/clone_spec.rb b/spec/ruby/core/proc/clone_spec.rb
index a1a1292654..7eca9c561e 100644
--- a/spec/ruby/core/proc/clone_spec.rb
+++ b/spec/ruby/core/proc/clone_spec.rb
@@ -3,4 +3,13 @@ require_relative 'shared/dup'
describe "Proc#clone" do
it_behaves_like :proc_dup, :clone
+
+ ruby_bug "cloning a frozen proc is broken on Ruby 3.3", "3.3"..."3.4" do
+ it "preserves frozen status" do
+ proc = Proc.new { }
+ proc.freeze
+ proc.frozen?.should == true
+ proc.clone.frozen?.should == true
+ end
+ end
end
diff --git a/spec/ruby/core/proc/dup_spec.rb b/spec/ruby/core/proc/dup_spec.rb
index 6da2f3080c..dd19b3c1e9 100644
--- a/spec/ruby/core/proc/dup_spec.rb
+++ b/spec/ruby/core/proc/dup_spec.rb
@@ -3,4 +3,11 @@ require_relative 'shared/dup'
describe "Proc#dup" do
it_behaves_like :proc_dup, :dup
+
+ it "resets frozen status" do
+ proc = Proc.new { }
+ proc.freeze
+ proc.frozen?.should == true
+ proc.dup.frozen?.should == false
+ end
end
diff --git a/spec/ruby/core/proc/shared/dup.rb b/spec/ruby/core/proc/shared/dup.rb
index 4480f3d0c9..c419a4078a 100644
--- a/spec/ruby/core/proc/shared/dup.rb
+++ b/spec/ruby/core/proc/shared/dup.rb
@@ -15,4 +15,27 @@ describe :proc_dup, shared: true do
cl.new{}.send(@method).class.should == cl
end
end
+
+ ruby_version_is "3.4" do
+ it "copies instance variables" do
+ proc = -> { "hello" }
+ proc.instance_variable_set(:@ivar, 1)
+ cl = proc.send(@method)
+ cl.instance_variables.should == [:@ivar]
+ end
+
+ it "copies the finalizer" do
+ code = <<-RUBY
+ obj = Proc.new { }
+
+ ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" })
+
+ obj.clone
+
+ exit 0
+ RUBY
+
+ ruby_exe(code).lines.sort.should == ["finalized\n", "finalized\n"]
+ end
+ end
end
diff --git a/spec/ruby/core/unboundmethod/clone_spec.rb b/spec/ruby/core/unboundmethod/clone_spec.rb
index 098ee61476..1e7fb18744 100644
--- a/spec/ruby/core/unboundmethod/clone_spec.rb
+++ b/spec/ruby/core/unboundmethod/clone_spec.rb
@@ -1,12 +1,13 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
+require_relative 'shared/dup'
describe "UnboundMethod#clone" do
- it "returns a copy of the UnboundMethod" do
- um1 = UnboundMethodSpecs::Methods.instance_method(:foo)
- um2 = um1.clone
+ it_behaves_like :unboundmethod_dup, :clone
- (um1 == um2).should == true
- um1.bind(UnboundMethodSpecs::Methods.new).call.should == um2.bind(UnboundMethodSpecs::Methods.new).call
+ it "preserves frozen status" do
+ method = Class.instance_method(:instance_method)
+ method.freeze
+ method.frozen?.should == true
+ method.clone.frozen?.should == true
end
end
diff --git a/spec/ruby/core/unboundmethod/dup_spec.rb b/spec/ruby/core/unboundmethod/dup_spec.rb
new file mode 100644
index 0000000000..5a78dd8e36
--- /dev/null
+++ b/spec/ruby/core/unboundmethod/dup_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+require_relative 'shared/dup'
+
+describe "UnboundMethod#dup" do
+ ruby_version_is "3.4" do
+ it_behaves_like :unboundmethod_dup, :dup
+
+ it "resets frozen status" do
+ method = Class.instance_method(:instance_method)
+ method.freeze
+ method.frozen?.should == true
+ method.dup.frozen?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/unboundmethod/shared/dup.rb b/spec/ruby/core/unboundmethod/shared/dup.rb
new file mode 100644
index 0000000000..943a7faaa3
--- /dev/null
+++ b/spec/ruby/core/unboundmethod/shared/dup.rb
@@ -0,0 +1,32 @@
+describe :unboundmethod_dup, shared: true do
+ it "returns a copy of self" do
+ a = Class.instance_method(:instance_method)
+ b = a.send(@method)
+
+ a.should == b
+ a.should_not equal(b)
+ end
+
+ ruby_version_is "3.4" do
+ it "copies instance variables" do
+ method = Class.instance_method(:instance_method)
+ method.instance_variable_set(:@ivar, 1)
+ cl = method.send(@method)
+ cl.instance_variables.should == [:@ivar]
+ end
+
+ it "copies the finalizer" do
+ code = <<-RUBY
+ obj = Class.instance_method(:instance_method)
+
+ ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" })
+
+ obj.clone
+
+ exit 0
+ RUBY
+
+ ruby_exe(code).lines.sort.should == ["finalized\n", "finalized\n"]
+ end
+ end
+end