Skip to content

Commit f556eef

Browse files
committed
[GR-9829] Fix NameError, NoMethodError, and SystemCallError dup with internal field data.
PullRequest: truffleruby/1201
2 parents ac2440e + 9441466 commit f556eef

File tree

7 files changed

+85
-4
lines changed

7 files changed

+85
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Bug fixes:
4141
* Make `String#concat` work with no or multiple arguments (#1519).
4242
* Make `Array#concat` work with no or multiple arguments (#1519).
4343
* Fixed BigDecimal coerce initial argument using `to_str` (#1826).
44+
* Fixed `NameError`, `NoMethodError`, and `SystemCallError` dup with internal field data.
4445
* Make `Enumerable#chunk` work without a block (#1518).
4546
* Fixed issue with `SystemCallError.new` setting a backtrace.
4647
* Fixed `BigDecimal#to_s` formatting issue (#1711).

spec/ruby/core/exception/name_error_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,15 @@
2222
end
2323
end
2424
end
25+
26+
describe "NameError#dup" do
27+
it "copies the name and receiver" do
28+
begin
29+
foo
30+
rescue NameError => ne
31+
name_error_dup = ne.dup
32+
name_error_dup.name.should == :foo
33+
name_error_dup.receiver.should == self
34+
end
35+
end
36+
end

spec/ruby/core/exception/no_method_error_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,17 @@ def inspect
104104
end
105105
end
106106
end
107+
108+
describe "NoMethodError#dup" do
109+
it "copies the name, arguments and receiver" do
110+
begin
111+
receiver = Object.new
112+
receiver.foo(:one, :two)
113+
rescue NoMethodError => nme
114+
no_method_error_dup = nme.dup
115+
no_method_error_dup.name.should == :foo
116+
no_method_error_dup.receiver.should == receiver
117+
no_method_error_dup.args.should == [:one, :two]
118+
end
119+
end
120+
end

spec/ruby/core/exception/system_call_error_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,10 @@ def initialize
134134
SystemCallError.new("message", 42).backtrace.should == nil
135135
end
136136
end
137+
138+
describe "SystemCallError#dup" do
139+
it "copies the errno" do
140+
dup_sce = SystemCallError.new("message", 42).dup
141+
dup_sce.errno.should == 42
142+
end
143+
end

src/main/java/org/truffleruby/core/exception/ExceptionNodes.java

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,54 @@ protected Object initializeCopySelfIsSameAsFrom(DynamicObject self, DynamicObjec
7474
return self;
7575
}
7676

77-
78-
@Specialization(guards = { "self != from", "isRubyException(from)" })
77+
@Specialization(
78+
guards = { "self != from", "isRubyException(from)", "!isNameError(from)", "!isSystemCallError(from)" })
7979
protected Object initializeCopy(DynamicObject self, DynamicObject from) {
80+
initializeExceptionCopy(self, from);
81+
return self;
82+
}
83+
84+
@Specialization(guards = { "self != from", "isSystemCallError(from)" })
85+
protected Object initializeSystemCallErrorCopy(DynamicObject self, DynamicObject from) {
86+
initializeExceptionCopy(self, from);
87+
Layouts.SYSTEM_CALL_ERROR.setErrno(self, Layouts.SYSTEM_CALL_ERROR.getErrno(from));
88+
return self;
89+
}
90+
91+
@Specialization(guards = { "self != from", "isNoMethodError(from)" })
92+
protected Object initializeCopyNoMethodError(DynamicObject self, DynamicObject from) {
93+
initializeExceptionCopy(self, from);
94+
initializeNameErrorCopy(self, from);
95+
Layouts.NO_METHOD_ERROR.setArgs(self, Layouts.NO_METHOD_ERROR.getArgs(from));
96+
return self;
97+
}
98+
99+
@Specialization(
100+
guards = { "self != from", "isNameError(from)", "!isNoMethodError(from)" })
101+
protected Object initializeCopyNameError(DynamicObject self, DynamicObject from) {
102+
initializeExceptionCopy(self, from);
103+
initializeNameErrorCopy(self, from);
104+
return self;
105+
}
106+
107+
protected boolean isNameError(DynamicObject object) {
108+
return Layouts.NAME_ERROR.isNameError(object);
109+
}
110+
111+
protected boolean isNoMethodError(DynamicObject object) {
112+
return Layouts.NO_METHOD_ERROR.isNoMethodError(object);
113+
}
114+
115+
protected boolean isSystemCallError(DynamicObject object) {
116+
return Layouts.SYSTEM_CALL_ERROR.isSystemCallError(object);
117+
}
118+
119+
private void initializeNameErrorCopy(DynamicObject self, DynamicObject from) {
120+
Layouts.NAME_ERROR.setName(self, Layouts.NAME_ERROR.getName(from));
121+
Layouts.NAME_ERROR.setReceiver(self, Layouts.NAME_ERROR.getReceiver(from));
122+
}
123+
124+
private void initializeExceptionCopy(DynamicObject self, DynamicObject from) {
80125
Backtrace backtrace = Layouts.EXCEPTION.getBacktrace(from);
81126
if (backtrace != null) {
82127
Layouts.EXCEPTION.setBacktrace(self, backtrace.copy(getContext(), self));
@@ -86,8 +131,6 @@ protected Object initializeCopy(DynamicObject self, DynamicObject from) {
86131
Layouts.EXCEPTION.setFormatter(self, Layouts.EXCEPTION.getFormatter(from));
87132
Layouts.EXCEPTION.setMessage(self, Layouts.EXCEPTION.getMessage(from));
88133
Layouts.EXCEPTION.setCause(self, Layouts.EXCEPTION.getCause(from));
89-
90-
return self;
91134
}
92135

93136
}

src/main/java/org/truffleruby/core/exception/NoMethodErrorLayout.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Object[] build(
3232
Object name,
3333
Object args);
3434

35+
boolean isNoMethodError(DynamicObject object);
36+
3537
Object getArgs(DynamicObject object);
3638

3739
void setArgs(DynamicObject object, Object value);

src/main/java/org/truffleruby/core/exception/SystemCallErrorLayout.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Object[] build(
3030
DynamicObject cause,
3131
Object errno);
3232

33+
boolean isSystemCallError(DynamicObject object);
34+
3335
Object getErrno(DynamicObject object);
3436

3537
void setErrno(DynamicObject object, Object value);

0 commit comments

Comments
 (0)