Skip to content

Commit

Permalink
Showing 55 changed files with 513 additions and 213 deletions.
9 changes: 4 additions & 5 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -3275,7 +3275,7 @@ public void tearDown(boolean systemExit) {
// clear out threadlocals so they don't leak
recursive = new ThreadLocal<Map<String, RubyHash>>();

ThreadContext context = getCurrentContext();
final ThreadContext context = getCurrentContext();

// FIXME: 73df3d230b9d92c7237d581c6366df1b92ad9b2b exposed no toplevel scope existing anymore (I think the
// bogus scope I removed was playing surrogate toplevel scope and wallpapering this bug). For now, add a
@@ -3289,15 +3289,14 @@ public void tearDown(boolean systemExit) {
RubyProc proc = atExitBlocks.pop();
// IRubyObject oldExc = context.runtime.getGlobalVariables().get("$!"); // Save $!
try {
proc.call(getCurrentContext(), IRubyObject.NULL_ARRAY);
proc.call(context, IRubyObject.NULL_ARRAY);
} catch (RaiseException rj) {
RubyException raisedException = rj.getException();
if (!getSystemExit().isInstance(raisedException)) {
status = 1;
printError(raisedException);
} else {
IRubyObject statusObj = raisedException.callMethod(
getCurrentContext(), "status");
IRubyObject statusObj = raisedException.callMethod(context, "status");
if (statusObj != null && !statusObj.isNil()) {
status = RubyNumeric.fix2int(statusObj);
}
@@ -3313,7 +3312,7 @@ public void tearDown(boolean systemExit) {
IRubyObject[] trapResultEntries = ((RubyArray) trapResult).toJavaArray();
IRubyObject exitHandlerProc = trapResultEntries[0];
if (exitHandlerProc instanceof RubyProc) {
((RubyProc) exitHandlerProc).call(this.getCurrentContext(), this.getSingleNilArray());
((RubyProc) exitHandlerProc).call(context, getSingleNilArray());
}
}

8 changes: 6 additions & 2 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Original file line number Diff line number Diff line change
@@ -1208,7 +1208,7 @@ public void addFinalizer(IRubyObject f) {
// calls to undefine_finalizer, which takes an object ID, can
// locate the object properly. See JRUBY-4839.
long id = getObjectId();
RubyFixnum fixnumId = (RubyFixnum)id();
IRubyObject fixnumId = id();

getRuntime().getObjectSpace().registerObjectId(id, this);

@@ -1841,12 +1841,16 @@ public IRubyObject evalUnder(final ThreadContext context, RubyModule under, Ruby
* operation.
*/
public static class Finalizer implements Finalizable {
private final RubyFixnum id;
private final IRubyObject id;
private final AtomicBoolean finalized;
private IRubyObject firstFinalizer;
private List<IRubyObject> finalizers;

public Finalizer(RubyFixnum id) {
this((IRubyObject) id);
}

Finalizer(IRubyObject id) {
this.id = id;
this.finalized = new AtomicBoolean(false);
}
13 changes: 6 additions & 7 deletions core/src/main/java/org/jruby/RubyFloat.java
Original file line number Diff line number Diff line change
@@ -535,14 +535,13 @@ public IRubyObject op_cmp(ThreadContext context, IRubyObject other) {
IRubyObject infinite = other.callMethod(context, "infinite?");
if (infinite.isNil()) {
return value > 0.0 ? RubyFixnum.one(runtime) : RubyFixnum.minus_one(runtime);
} else {
int sign = RubyFixnum.fix2int(infinite);
}
long sign = RubyFixnum.fix2long(infinite);

if (sign > 0) {
return value > 0.0 ? RubyFixnum.zero(runtime) : RubyFixnum.minus_one(runtime);
} else {
return value < 0.0 ? RubyFixnum.zero(runtime) : RubyFixnum.one(runtime);
}
if (sign > 0) {
return value > 0.0 ? RubyFixnum.zero(runtime) : RubyFixnum.minus_one(runtime);
} else {
return value < 0.0 ? RubyFixnum.zero(runtime) : RubyFixnum.one(runtime);
}
}
return coerceCmp(context, "<=>", other);
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/RubyObjectSpace.java
Original file line number Diff line number Diff line change
@@ -82,8 +82,8 @@ public static IRubyObject define_finalizer(IRubyObject recv, IRubyObject[] args,
}

@JRubyMethod(required = 1, module = true, visibility = PRIVATE)
public static IRubyObject undefine_finalizer(IRubyObject recv, IRubyObject arg1, Block block) {
recv.getRuntime().getObjectSpace().removeFinalizers(RubyNumeric.fix2long(arg1.id()));
public static IRubyObject undefine_finalizer(IRubyObject recv, IRubyObject obj, Block block) {
recv.getRuntime().getObjectSpace().removeFinalizers(RubyNumeric.fix2long(obj.id()));
return recv;
}

12 changes: 3 additions & 9 deletions core/src/main/java/org/jruby/RubyThread.java
Original file line number Diff line number Diff line change
@@ -1511,9 +1511,9 @@ public void dieFromFinalizer() {
genericKill(getRuntime(), null);
}

private static void debug(RubyThread thread, String message) {
if (LOG.isDebugEnabled()) LOG.debug( "{} ({}): {}", Thread.currentThread(), thread.status, message );
}
//private static void debug(RubyThread thread, String message) {
// if (LOG.isDebugEnabled()) LOG.debug( "{} ({}): {}", Thread.currentThread(), thread.status, message );
//}

@JRubyMethod
public IRubyObject safe_level() {
@@ -1881,12 +1881,6 @@ public void afterBlockingCall() {
pollThreadEvents();
}

private void receivedAnException(ThreadContext context, IRubyObject exception) {
RubyModule kernelModule = getRuntime().getKernel();
debug(this, "before propagating exception");
kernelModule.callMethod(context, "raise", exception);
}

public boolean wait_timeout(IRubyObject o, Double timeout) throws InterruptedException {
if ( timeout != null ) {
long delay_ns = (long)(timeout.doubleValue() * 1000000000.0);
33 changes: 21 additions & 12 deletions spec/mspec/lib/mspec/runner/formatters/spinner.rb
Original file line number Diff line number Diff line change
@@ -27,7 +27,8 @@ def register
super

MSpec.register :start, self
MSpec.register :load, self
MSpec.register :unload, self
MSpec.unregister :before, self
end

def length=(length)
@@ -36,8 +37,8 @@ def length=(length)
@position = length / 2 - 2
end

def etr
return "00:00:00" if @percent == 0
def compute_etr
return @etr = "00:00:00" if @percent == 0
elapsed = Time.now - @start
remain = (100 * elapsed / @percent) - elapsed

@@ -46,20 +47,25 @@ def etr
min = remain >= MIN ? (remain / MIN).to_i : 0
sec = remain - min * MIN

"%02d:%02d:%02d" % [hour, min, sec]
@etr = "%02d:%02d:%02d" % [hour, min, sec]
end

def percentage
def compute_percentage
@percent = @loaded * 100 / @total
bar = ("=" * (@percent / @ratio)).ljust @length
label = "%d%%" % @percent
bar[@position, label.size] = label
bar
@bar = bar
end

def compute_progress
compute_percentage
compute_etr
end

def progress_line
@which = (@which + 1) % Spins.size
data = [Spins[@which], percentage, etr, @counter.failures, @counter.errors]
data = [Spins[@which], @bar, @etr, @counter.failures, @counter.errors]
if @color
"\r[%s | %s | %s] \e[0;#{@fail_color}m%6dF \e[0;#{@error_color}m%6dE\e[0m" % data
else
@@ -75,12 +81,16 @@ def clear_progress_line
# number of files that will be processed.
def start
@total = MSpec.retrieve(:files).size
compute_progress
print progress_line
end

# Callback for the MSpec :load event. Increments the number
# of files that have been loaded.
def load
# Callback for the MSpec :unload event. Increments the number
# of files that have been run.
def unload
@loaded += 1
compute_progress
print progress_line
end

# Callback for the MSpec :exception event. Changes the color
@@ -94,8 +104,7 @@ def exception(exception)
print_exception(exception, @count)
end

# Callback for the MSpec :after event. Updates the spinner
# and progress bar.
# Callback for the MSpec :after event. Updates the spinner.
def after(state)
print progress_line
end
21 changes: 9 additions & 12 deletions spec/mspec/spec/runner/formatters/spinner_spec.rb
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@

it "registers self with MSpec for appropriate actions" do
MSpec.should_receive(:register).with(:start, @formatter)
MSpec.should_receive(:register).with(:load, @formatter)
MSpec.should_receive(:register).with(:unload, @formatter)
MSpec.should_receive(:register).with(:after, @formatter)
MSpec.should_receive(:register).with(:finish, @formatter)
@formatter.register
@@ -55,7 +55,7 @@
describe SpinnerFormatter, "#after" do
before :each do
$stdout = IOStub.new
MSpec.stub(:retrieve).and_return(["a", "b"])
MSpec.store(:files, ["a", "b", "c", "d"])
@formatter = SpinnerFormatter.new
@formatter.register
@state = ExampleState.new("describe", "it")
@@ -67,20 +67,17 @@

it "updates the spinner" do
@formatter.start
@formatter.load
@formatter.after @state
@formatter.after @state
@formatter.unload

output = nil
if ENV["TERM"] != "dumb"
output = "\r[/ | ======== 20% | 00:00:00] " \
"\e[0;32m 0F \e[0;32m 0E\e[0m" \
"\r[- | ======== 20% | 00:00:00] " \
"\e[0;32m 0F \e[0;32m 0E\e[0m"
else
output = "\r[/ | ======== 20% | 00:00:00] 0F 0E" \
"\r[- | ======== 20% | 00:00:00] 0F 0E"
green = "\e[0;32m"
reset = "\e[0m"
end

output = "\r[/ | 0% | 00:00:00] #{green} 0F #{green} 0E#{reset}" \
"\r[- | 0% | 00:00:00] #{green} 0F #{green} 0E#{reset}" \
"\r[\\ | ========== 25% | 00:00:00] #{green} 0F #{green} 0E#{reset}"
$stdout.should == output
end
end
4 changes: 2 additions & 2 deletions spec/mspec/spec/utils/name_map_spec.rb
Original file line number Diff line number Diff line change
@@ -149,11 +149,11 @@ def n; end
end

it "prepends the module to the constant name" do
@map.namespace("SubModule", Fixnum).should == "SubModule::Fixnum"
@map.namespace("SubModule", Integer).should == "SubModule::Integer"
end

it "does not prepend Object, Class, or Module to the constant name" do
@map.namespace("Object", Fixnum).should == "Fixnum"
@map.namespace("Object", String).should == "String"
@map.namespace("Module", Integer).should == "Integer"
@map.namespace("Class", Float).should == "Float"
end
3 changes: 3 additions & 0 deletions spec/ruby/core/fiber/new_spec.rb
Original file line number Diff line number Diff line change
@@ -4,13 +4,15 @@
describe "Fiber.new" do
it "creates a fiber from the given block" do
fiber = Fiber.new {}
fiber.resume
fiber.should be_an_instance_of(Fiber)
end

it "creates a fiber from a subclass" do
class MyFiber < Fiber
end
fiber = MyFiber.new {}
fiber.resume
fiber.should be_an_instance_of(MyFiber)
end

@@ -22,6 +24,7 @@ class MyFiber < Fiber
invoked = false
fiber = Fiber.new { invoked = true }
invoked.should be_false
fiber.resume
end

it "closes over lexical environments" do
36 changes: 36 additions & 0 deletions spec/ruby/core/fiber/resume_spec.rb
Original file line number Diff line number Diff line change
@@ -12,5 +12,41 @@
fiber2 = Fiber.new { fiber1.resume; :fiber2 }
fiber2.resume.should == :fiber2
end

# Redmine #595
it "executes the ensure clause" do
rd, wr = IO.pipe

pid = Kernel::fork do
rd.close
f = Fiber.new do
begin
Fiber.yield
ensure
wr.write "executed"
end
end

# The apparent issue is that when Fiber.yield executes, control
# "leaves" the "ensure block" and so the ensure clause should run. But
# control really does NOT leave the ensure block when Fiber.yield
# executes. It merely pauses there. To require ensure to run when a
# Fiber is suspended then makes ensure-in-a-Fiber-context different
# than ensure-in-a-Thread-context and this would be very confusing.
f.resume

# When we execute the second #resume call, the ensure block DOES exit,
# the ensure clause runs. This is Ruby behavior as of 2.3.1.
f.resume

exit 0
end

wr.close
Process.waitpid pid

rd.read.should == "executed"
rd.close
end
end
end
2 changes: 2 additions & 0 deletions spec/ruby/core/fiber/yield_spec.rb
Original file line number Diff line number Diff line change
@@ -14,11 +14,13 @@
it "returns its arguments to the caller" do
fiber = Fiber.new { true; Fiber.yield :glark; true }
fiber.resume.should == :glark
fiber.resume
end

it "returns nil to the caller if given no arguments" do
fiber = Fiber.new { true; Fiber.yield; true }
fiber.resume.should be_nil
fiber.resume
end

it "returns to the Fiber the value of the #resume call that invoked it" do
31 changes: 30 additions & 1 deletion spec/ruby/core/objectspace/define_finalizer_spec.rb
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
describe "ObjectSpace.define_finalizer" do
it "raises an ArgumentError if the action does not respond to call" do
lambda {
ObjectSpace.define_finalizer("", 3)
ObjectSpace.define_finalizer("", mock("ObjectSpace.define_finalizer no #call"))
}.should raise_error(ArgumentError)
end

@@ -78,5 +78,34 @@ def handler.call(obj) end
Process.wait pid
end
end

# These specs are defined under the fork specs because there is no
# deterministic way to force finalizers to be run, except process exit, so
# we rely on that.
it "allows multiple finalizers with different 'callables' to be defined" do
rd1, wr1 = IO.pipe
rd2, wr2 = IO.pipe

pid = Kernel::fork do
rd1.close
rd2.close
obj = mock("ObjectSpace.define_finalizer multiple")

ObjectSpace.define_finalizer(obj, Proc.new { wr1.write "finalized1"; wr1.close })
ObjectSpace.define_finalizer(obj, Proc.new { wr2.write "finalized2"; wr2.close })

exit 0
end

wr1.close
wr2.close

rd1.read.should == "finalized1"
rd2.read.should == "finalized2"

rd1.close
rd2.close
Process.wait pid
end
end
end
3 changes: 2 additions & 1 deletion spec/ruby/core/objectspace/each_object_spec.rb
Original file line number Diff line number Diff line change
@@ -130,7 +130,8 @@ class ObjectSpaceSpecEachOtherObject; end
end

it "finds an object stored in a thread local" do
Thread.current.thread_variable_set(:object_space_thread_local, ObjectSpaceFixtures::ObjectToBeFound.new(:thread_local))
thread = Thread.new {}
thread.thread_variable_set(:object_space_thread_local, ObjectSpaceFixtures::ObjectToBeFound.new(:thread_local))
ObjectSpaceFixtures.to_be_found_symbols.should include(:thread_local)
end

11 changes: 7 additions & 4 deletions spec/ruby/core/process/setsid_spec.rb
Original file line number Diff line number Diff line change
@@ -20,14 +20,17 @@
}
write.close
read2.close
pgid_child = read.gets
pgid_child = Integer(read.gets)
read.close
pgid = Process.getsid(pid)
platform_is_not :aix do
# AIX does not allow Process.getsid(pid)
# if pid is in a different session.
pgid = Process.getsid(pid)
pgid_child.should == pgid
end
write2.close
Process.wait pid

pgid_child = Integer(pgid_child)
pgid_child.should == pgid
pgid_child.should_not == Process.getsid
end
end
73 changes: 5 additions & 68 deletions spec/ruby/core/range/eql_spec.rb
Original file line number Diff line number Diff line change
@@ -1,73 +1,10 @@
# Custom Range classes Xs and Ys
class Custom
include Comparable
attr :length
def initialize(n)
@length = n
end
def eql?(other)
inspect.eql? other.inspect
end
def inspect
'custom'
end
def <=>(other)
@length <=> other.length
end
def to_s
sprintf "%2d #{inspect}", @length
end
end

class Xs < Custom # represent a string of 'x's
def succ
Xs.new(@length + 1)
end
def inspect
'x' * @length
end
end

class Ys < Custom # represent a string of 'y's
def succ
Ys.new(@length + 1)
end
def inspect
'y' * @length
end
end
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/equal_value', __FILE__)

describe :range_eql, shared: true do
it "returns true if other has same begin, end, and exclude_end? values" do
(0..2).send(@method, 0..2).should == true
('G'..'M').send(@method,'G'..'M').should == true
(0.5..2.4).send(@method, 0.5..2.4).should == true
(5..10).send(@method, Range.new(5,10)).should == true
('D'..'V').send(@method, Range.new('D','V')).should == true
(0.5..2.4).send(@method, Range.new(0.5, 2.4)).should == true
(0xffff..0xfffff).send(@method, 0xffff..0xfffff).should == true
(0xffff..0xfffff).send(@method, Range.new(0xffff,0xfffff)).should == true
(Xs.new(3)..Xs.new(5)).send(@method, Range.new(Xs.new(3), Xs.new(5))).should == true
describe "Range#eql?" do
it_behaves_like(:range_eql, :eql?)

it "returns false if the endpoints are not eql?" do
(0..1).send(@method, 0..1.0).should == false
('Q'..'X').send(@method, 'A'..'C').should == false
('Q'...'X').send(@method, 'Q'..'W').should == false
('Q'..'X').send(@method, 'Q'...'X').should == false
(0.5..2.4).send(@method, 0.5...2.4).should == false
(1482..1911).send(@method, 1482...1911).should == false
(0xffff..0xfffff).send(@method, 0xffff...0xfffff).should == false
(Xs.new(3)..Xs.new(5)).send(@method, Range.new(Ys.new(3), Ys.new(5))).should == false
end

it "returns false if other is no Range" do
(1..10).send(@method, 1).should == false
(1..10).send(@method, 'a').should == false
(1..10).send(@method, mock('x')).should == false
end

it "returns true for subclasses to Range" do
class MyRange < Range ; end
Range.new(1, 2).send(@method, MyRange.new(1, 2)).should == true
Range.new(Xs.new(3), Xs.new(5)).send(@method, MyRange.new(Xs.new(3), Xs.new(5))).should == true
end
end
4 changes: 4 additions & 0 deletions spec/ruby/core/range/equal_value_spec.rb
Original file line number Diff line number Diff line change
@@ -3,4 +3,8 @@

describe "Range#==" do
it_behaves_like(:range_eql, :==)

it "returns true if the endpoints are ==" do
(0..1).send(@method, 0..1.0).should == true
end
end
46 changes: 46 additions & 0 deletions spec/ruby/core/range/fixtures/classes.rb
Original file line number Diff line number Diff line change
@@ -16,4 +16,50 @@ def succ
self.class.new(@n * 10)
end
end

# Custom Range classes Xs and Ys
class Custom
include Comparable
attr_reader :length

def initialize(n)
@length = n
end

def eql?(other)
inspect.eql? other.inspect
end
alias :== :eql?

def inspect
'custom'
end

def <=>(other)
@length <=> other.length
end
end

class Xs < Custom # represent a string of 'x's
def succ
Xs.new(@length + 1)
end

def inspect
'x' * @length
end
end

class Ys < Custom # represent a string of 'y's
def succ
Ys.new(@length + 1)
end

def inspect
'y' * @length
end
end

class MyRange < Range
end
end
2 changes: 1 addition & 1 deletion spec/ruby/core/range/range_spec.rb
Original file line number Diff line number Diff line change
@@ -3,5 +3,5 @@
describe "Range" do
it "includes Enumerable" do
Range.include?(Enumerable).should == true
end
end
end
22 changes: 18 additions & 4 deletions spec/ruby/core/range/shared/equal_value.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require File.expand_path('../../fixtures/classes', __FILE__)

describe :range_eql, shared: true do
it "returns true if other has same begin, end, and exclude_end? values" do
(0..2).send(@method, 0..2).should == true
@@ -9,23 +11,35 @@
(0xffff..0xfffff).send(@method, 0xffff..0xfffff).should == true
(0xffff..0xfffff).send(@method, Range.new(0xffff,0xfffff)).should == true

a = RangeSpecs::Xs.new(3)..RangeSpecs::Xs.new(5)
b = Range.new(RangeSpecs::Xs.new(3), RangeSpecs::Xs.new(5))
a.send(@method, b).should == true
end

it "returns false if one of the attributes differs" do
('Q'..'X').send(@method, 'A'..'C').should == false
('Q'...'X').send(@method, 'Q'..'W').should == false
('Q'..'X').send(@method, 'Q'...'X').should == false
(0.5..2.4).send(@method, 0.5...2.4).should == false
(1482..1911).send(@method, 1482...1911).should == false
(0xffff..0xfffff).send(@method, 0xffff...0xfffff).should == false

a = RangeSpecs::Xs.new(3)..RangeSpecs::Xs.new(5)
b = Range.new(RangeSpecs::Ys.new(3), RangeSpecs::Ys.new(5))
a.send(@method, b).should == false
end

it "returns false if other is no Range" do
it "returns false if other is not a Range" do
(1..10).send(@method, 1).should == false
(1..10).send(@method, 'a').should == false
(1..10).send(@method, mock('x')).should == false
end

it "returns true for subclasses to Range" do
class MyRange < Range ; end
Range.new(1, 2).send(@method, MyRange.new(1, 2)).should == true
it "returns true for subclasses of Range" do
Range.new(1, 2).send(@method, RangeSpecs::MyRange.new(1, 2)).should == true

a = Range.new(RangeSpecs::Xs.new(3), RangeSpecs::Xs.new(5))
b = RangeSpecs::MyRange.new(RangeSpecs::Xs.new(3), RangeSpecs::Xs.new(5))
a.send(@method, b).should == true
end
end
10 changes: 6 additions & 4 deletions spec/ruby/core/string/capitalize_spec.rb
Original file line number Diff line number Diff line change
@@ -17,10 +17,12 @@
"hello".taint.capitalize.tainted?.should == true
end

it "is locale insensitive (only upcases a-z and only downcases A-Z)" do
"ÄÖÜ".capitalize.should == "ÄÖÜ"
"ärger".capitalize.should == "ärger"
"BÄR".capitalize.should == "BÄr"
ruby_version_is ''...'2.4' do
it "is locale insensitive (only upcases a-z and only downcases A-Z)" do
"ÄÖÜ".capitalize.should == "ÄÖÜ"
"ärger".capitalize.should == "ärger"
"BÄR".capitalize.should == "BÄr"
end
end

it "returns subclass instances when called on a subclass" do
22 changes: 12 additions & 10 deletions spec/ruby/core/string/downcase_spec.rb
Original file line number Diff line number Diff line change
@@ -8,16 +8,18 @@
"hello".downcase.should == "hello"
end

it "is locale insensitive (only replaces A-Z)" do
"ÄÖÜ".downcase.should == "ÄÖÜ"

str = Array.new(256) { |c| c.chr }.join
expected = Array.new(256) do |i|
c = i.chr
c.between?("A", "Z") ? c.downcase : c
end.join

str.downcase.should == expected
ruby_version_is ''...'2.4' do
it "is locale insensitive (only replaces A-Z)" do
"ÄÖÜ".downcase.should == "ÄÖÜ"

str = Array.new(256) { |c| c.chr }.join
expected = Array.new(256) do |i|
c = i.chr
c.between?("A", "Z") ? c.downcase : c
end.join

str.downcase.should == expected
end
end

it "taints result when self is tainted" do
8 changes: 5 additions & 3 deletions spec/ruby/core/string/rindex_spec.rb
Original file line number Diff line number Diff line change
@@ -306,9 +306,11 @@ def obj.method_missing(*args) 5 end
"blablablax".rindex(/.x/, 7).should == nil
"blablablax".rindex(/..x/, 6).should == nil

"blablabla".rindex(/\Z/, 5).should == nil
"blablabla".rindex(/\z/, 5).should == nil
"blablabla\n".rindex(/\z/, 9).should == nil
not_supported_on :opal do
"blablabla".rindex(/\Z/, 5).should == nil
"blablabla".rindex(/\z/, 5).should == nil
"blablabla\n".rindex(/\z/, 9).should == nil
end
end

not_supported_on :opal do
10 changes: 6 additions & 4 deletions spec/ruby/core/string/swapcase_spec.rb
Original file line number Diff line number Diff line change
@@ -14,10 +14,12 @@
"hello".taint.swapcase.tainted?.should == true
end

it "is locale insensitive (only upcases a-z and only downcases A-Z)" do
"ÄÖÜ".swapcase.should == "ÄÖÜ"
"ärger".swapcase.should == "äRGER"
"BÄR".swapcase.should == "bÄr"
ruby_version_is ''...'2.4' do
it "is locale insensitive (only upcases a-z and only downcases A-Z)" do
"ÄÖÜ".swapcase.should == "ÄÖÜ"
"ärger".swapcase.should == "äRGER"
"BÄR".swapcase.should == "bÄr"
end
end

it "returns subclass instances when called on a subclass" do
22 changes: 12 additions & 10 deletions spec/ruby/core/string/upcase_spec.rb
Original file line number Diff line number Diff line change
@@ -8,16 +8,18 @@
"hello".upcase.should == "HELLO"
end

it "is locale insensitive (only replaces a-z)" do
"äöü".upcase.should == "äöü"

str = Array.new(256) { |c| c.chr }.join
expected = Array.new(256) do |i|
c = i.chr
c.between?("a", "z") ? c.upcase : c
end.join

str.upcase.should == expected
ruby_version_is ''...'2.4' do
it "is locale insensitive (only replaces a-z)" do
"äöü".upcase.should == "äöü"

str = Array.new(256) { |c| c.chr }.join
expected = Array.new(256) do |i|
c = i.chr
c.between?("a", "z") ? c.upcase : c
end.join

str.upcase.should == expected
end
end

it "taints result when self is tainted" do
19 changes: 13 additions & 6 deletions spec/ruby/core/symbol/capitalize_spec.rb
Original file line number Diff line number Diff line change
@@ -10,10 +10,15 @@
:lower.capitalize.should == :Lower
end

it "leaves the first character alone if it is not an alphabetical ASCII character" do
it "leaves the first character alone if it is not an alphabetical character" do
:"£1.20".capitalize.should == :"£1.20"
"\u{00DE}c".to_sym.capitalize.should == :"Þc"
"\u{00DF}C".to_sym.capitalize.should == :"ßc"
end

ruby_version_is ''...'2.4' do
it "leaves the first character alone if it is not an alphabetical ASCII character" do
"\u{00DE}c".to_sym.capitalize.should == :"Þc"
"\u{00DF}C".to_sym.capitalize.should == :"ßc"
end
end

it "converts subsequent uppercase ASCII characters to their lowercase equivalents" do
@@ -28,11 +33,13 @@
:mIxEd.capitalize.should == :Mixed
end

it "leaves uppercase Unicode characters as they were" do
"a\u{00DE}c".to_sym.capitalize.should == :"AÞc"
ruby_version_is ''...'2.4' do
it "leaves uppercase Unicode characters as they were" do
"a\u{00DE}c".to_sym.capitalize.should == :"AÞc"
end
end

it "leaves lowercase Unicode characters as they were" do
it "leaves lowercase Unicode characters (except in first position) as they were" do
"a\u{00DF}C".to_sym.capitalize.should == :"Aßc"
end

8 changes: 5 additions & 3 deletions spec/ruby/core/symbol/downcase_spec.rb
Original file line number Diff line number Diff line change
@@ -11,11 +11,13 @@
end

it "leaves lowercase Unicode characters as they were" do
"\u{C0}Bc".to_sym.downcase.should == :"Àbc"
"\u{E0}Bc".to_sym.downcase.should == :"àbc"
end

it "leaves uppercase Unicode characters as they were" do
"\u{DE}Bc".to_sym.downcase.should == :"Þbc"
ruby_version_is ''...'2.4' do
it "leaves uppercase Unicode characters as they were" do
"\u{DE}Bc".to_sym.downcase.should == :"Þbc"
end
end

it "leaves non-alphabetic ASCII characters as they were" do
14 changes: 8 additions & 6 deletions spec/ruby/core/symbol/swapcase_spec.rb
Original file line number Diff line number Diff line change
@@ -18,12 +18,14 @@
:mIxEd.swapcase.should == :MiXeD
end

it "leaves uppercase Unicode characters as they were" do
"\u{00DE}Bc".to_sym.swapcase.should == :"ÞbC"
end

it "leaves lowercase Unicode characters as they were" do
"\u{00DF}Bc".to_sym.swapcase.should == :"ßbC"
ruby_version_is ''...'2.4' do
it "leaves uppercase Unicode characters as they were" do
"\u{00DE}Bc".to_sym.swapcase.should == :"ÞbC"
end

it "leaves lowercase Unicode characters as they were" do
"\u{00DF}Bc".to_sym.swapcase.should == :"ßbC"
end
end

it "leaves non-alphabetic ASCII characters as they were" do
6 changes: 4 additions & 2 deletions spec/ruby/core/symbol/upcase_spec.rb
Original file line number Diff line number Diff line change
@@ -10,8 +10,10 @@
:lOwEr.upcase.should == :LOWER
end

it "leaves lowercase Unicode characters as they were" do
"\u{C0}Bc".to_sym.upcase.should == :"ÀBC"
ruby_version_is ''...'2.4' do
it "leaves lowercase Unicode characters as they were" do
"\u{E0}Bc".to_sym.upcase.should == :"àBC"
end
end

it "leaves non-alphabetic ASCII characters as they were" do
25 changes: 25 additions & 0 deletions spec/ruby/core/thread/thread_variable_get_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Thread#thread_variable_get" do
before :each do
@t = Thread.new { }
end

after :each do
@t.join
end

it "returns nil if the variable is not set" do
@t.thread_variable_get(:a).should be_nil
end

it "returns the value previously set by #[]=" do
@t.thread_variable_set :a, 49
@t.thread_variable_get(:a).should == 49
end

it "returns a value private to self" do
@t.thread_variable_set :thread_variable_get_spec, 82
Thread.current.thread_variable_get(:thread_variable_get_spec).should be_nil
end
end
26 changes: 26 additions & 0 deletions spec/ruby/core/thread/thread_variable_set_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Thread#thread_variable_set" do
before :each do
@t = Thread.new { }
end

after :each do
@t.join
end

it "returns the value set" do
(@t.thread_variable_set :a, 2).should == 2
end

it "sets a value that will be returned by #thread_variable_get" do
@t.thread_variable_set :a, 49
@t.thread_variable_get(:a).should == 49
end

it "sets a value private to self" do
@t.thread_variable_set :thread_variable_get_spec, 82
@t.thread_variable_get(:thread_variable_get_spec).should == 82
Thread.current.thread_variable_get(:thread_variable_get_spec).should be_nil
end
end
21 changes: 21 additions & 0 deletions spec/ruby/core/thread/thread_variable_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Thread#thread_variable?" do
before :each do
@t = Thread.new { }
end

after :each do
@t.join
end

it "returns false if the thread variables do not contain 'key'" do
@t.thread_variable_set :a, 2
@t.thread_variable?(:b).should be_false
end

it "returns true if the thread variables contain 'key'" do
@t.thread_variable_set :a, 2
@t.thread_variable?(:a).should be_true
end
end
24 changes: 24 additions & 0 deletions spec/ruby/core/thread/thread_variables_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Thread#thread_variables" do
before :each do
@t = Thread.new { }
end

after :each do
@t.join
end

it "returns the keys of all the values set" do
@t.thread_variable_set :a, 2
@t.thread_variable_set :b, 4
@t.thread_variable_set :c, 6
@t.thread_variables.sort.should == [:a, :b, :c]
end

it "sets a value private to self" do
@t.thread_variable_set :thread_variables_spec_a, 82
@t.thread_variable_set :thread_variables_spec_b, 82
Thread.current.thread_variables.should == []
end
end
4 changes: 3 additions & 1 deletion spec/ruby/library/etc/getgrnam_spec.rb
Original file line number Diff line number Diff line change
@@ -14,7 +14,9 @@
platform_is_not :windows do
describe "Etc.getgrnam" do
it "returns a Etc::Group struct instance for the given group" do
gr = Etc.getgrnam("daemon")
gr_name = Etc.getgrent.name
Etc.endgrent
gr = Etc.getgrnam(gr_name)
gr.is_a?(Etc::Group).should == true
end

8 changes: 8 additions & 0 deletions spec/ruby/library/fiber/transfer_spec.rb
Original file line number Diff line number Diff line change
@@ -15,6 +15,14 @@
fiber2.resume.should == :fiber1
end

it "returns to the root Fiber when finished" do
f1 = Fiber.new { :fiber_1 }
f2 = Fiber.new { f1.transfer; :fiber_2 }

f2.transfer.should == :fiber_1
f2.transfer.should == :fiber_2
end

it "can be invoked from the same Fiber it transfers control to" do
states = []
fiber = Fiber.new { states << :start; fiber.transfer; states << :end }
6 changes: 4 additions & 2 deletions spec/ruby/library/openssl/random/pseudo_bytes_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../shared/random_bytes.rb', __FILE__)

describe "OpenSSL::Random#pseudo_bytes" do
it_behaves_like :openssl_random_bytes, :pseudo_bytes
if defined?(OpenSSL::Random.pseudo_bytes)
describe "OpenSSL::Random.pseudo_bytes" do
it_behaves_like :openssl_random_bytes, :pseudo_bytes
end
end
2 changes: 1 addition & 1 deletion spec/ruby/library/openssl/random/random_bytes_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../shared/random_bytes.rb', __FILE__)

describe "OpenSSL::Random#random_bytes" do
describe "OpenSSL::Random.random_bytes" do
it_behaves_like :openssl_random_bytes, :random_bytes
end
6 changes: 3 additions & 3 deletions spec/ruby/library/openssl/random/shared/random_bytes.rb
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
describe :openssl_random_bytes, shared: true do |cmd|
it "generates a random binary string of specified length" do
(1..64).each do |idx|
bytes = OpenSSL::Random.pseudo_bytes(idx)
bytes = OpenSSL::Random.send(@method, idx)
bytes.should be_kind_of(String)
bytes.length.should == idx
end
@@ -14,7 +14,7 @@
# quick and dirty check, but good enough
values = []
256.times do
val = OpenSSL::Random.pseudo_bytes(16)
val = OpenSSL::Random.send(@method, 16)
# make sure the random bytes are not repeating
values.include?(val).should == false
values << val
@@ -23,7 +23,7 @@

it "raises ArgumentError on negative arguments" do
lambda {
OpenSSL::Random.pseudo_bytes(-1)
OpenSSL::Random.send(@method, -1)
}.should raise_error(ArgumentError)
end
end
2 changes: 2 additions & 0 deletions spec/ruby/library/readline/readline_spec.rb
Original file line number Diff line number Diff line change
@@ -19,7 +19,9 @@
after :each do
rm_r @file
STDIN.reopen(@stdin_back)
@stdin_back.close
STDOUT.reopen(@stdout_back)
@stdout_back.close
end

it "returns the input string" do
19 changes: 12 additions & 7 deletions spec/ruby/library/socket/basicsocket/getsockopt_spec.rb
Original file line number Diff line number Diff line change
@@ -11,14 +11,19 @@
@sock.close
end

it "gets a socket option Socket::SO_TYPE" do
n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE).to_s
n.should == [Socket::SOCK_STREAM].pack("i")
end
platform_is_not :aix do
# A known bug in AIX. getsockopt(2) does not properly set
# the fifth argument for SO_TYPE, SO_OOBINLINE, SO_BROADCAST, etc.

it "gets a socket option Socket::SO_TYPE" do
n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE).to_s
n.should == [Socket::SOCK_STREAM].pack("i")
end

it "gets a socket option Socket::SO_OOBINLINE" do
n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
n.should == [0].pack("i")
it "gets a socket option Socket::SO_OOBINLINE" do
n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
n.should == [0].pack("i")
end
end

it "gets a socket option Socket::SO_LINGER" do
12 changes: 8 additions & 4 deletions spec/ruby/optional/capi/constants_spec.rb
Original file line number Diff line number Diff line change
@@ -11,8 +11,10 @@
@s.rb_cArray.should == Array
end

specify "rb_cBignum references the Bignum class" do
@s.rb_cBignum.should == Bignum
ruby_version_is ""..."2.4" do
specify "rb_cBignum references the Bignum class" do
@s.rb_cBignum.should == Bignum
end
end

specify "rb_cClass references the Class class" do
@@ -39,8 +41,10 @@
@s.rb_cFile.should == File
end

specify "rb_cFixnum references the Fixnum class" do
@s.rb_cFixnum.should == Fixnum
ruby_version_is ""..."2.4" do
specify "rb_cFixnum references the Fixnum class" do
@s.rb_cFixnum.should == Fixnum
end
end

specify "rb_cFloat references the Float class" do
4 changes: 4 additions & 0 deletions spec/ruby/optional/capi/ext/rubyspec.h
Original file line number Diff line number Diff line change
@@ -123,12 +123,16 @@

/* Constants */
#define HAVE_RB_CARRAY 1
#ifndef RUBY_INTEGER_UNIFICATION
#define HAVE_RB_CBIGNUM 1
#endif
#define HAVE_RB_CCLASS 1
#define HAVE_RB_CDATA 1
#define HAVE_RB_CFALSECLASS 1
#define HAVE_RB_CFILE 1
#ifndef RUBY_INTEGER_UNIFICATION
#define HAVE_RB_CFIXNUM 1
#endif
#define HAVE_RB_CFLOAT 1
#define HAVE_RB_CHASH 1
#define HAVE_RB_CINTEGER 1
10 changes: 10 additions & 0 deletions spec/ruby/shared/fiber/resume.rb
Original file line number Diff line number Diff line change
@@ -4,6 +4,16 @@
fiber.send(@method).should == :fiber
end

it "raises a FiberError if invoked from a different Thread" do
fiber = Fiber.new { }
lambda do
Thread.new do
fiber.resume
end.join
end.should raise_error(FiberError)
fiber.resume
end

it "passes control to the beginning of the block on first invocation" do
invoked = false
fiber = Fiber.new { invoked = true }
5 changes: 3 additions & 2 deletions spec/ruby/shared/process/spawn.rb
Original file line number Diff line number Diff line change
@@ -299,9 +299,10 @@
end

it "joins the specified process group if pgroup: pgid" do
pgid = Process.getpgid(Process.pid)
lambda do
Process.wait @object.spawn(ruby_cmd("print Process.getpgid(Process.pid)"), pgroup: 123)
end.should_not output_to_fd("123")
Process.wait @object.spawn(ruby_cmd("print Process.getpgid(Process.pid)"), pgroup: pgid)
end.should output_to_fd(pgid.to_s)
end

it "raises an ArgumentError if given a negative :pgroup option" do
1 change: 1 addition & 0 deletions spec/tags/ruby/core/fiber/resume_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Fiber#resume executes the ensure clause
1 change: 1 addition & 0 deletions spec/tags/ruby/core/range/equal_value_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Range#== returns true if the endpoints are ==
1 change: 1 addition & 0 deletions spec/truffle/tags/core/fiber/resume_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Fiber#resume executes the ensure clause
1 change: 1 addition & 0 deletions spec/truffle/tags/core/range/eql_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Range#eql? returns false if the endpoints are not eql?
1 change: 1 addition & 0 deletions spec/truffle/tags/library/fiber/transfer_tags.txt
Original file line number Diff line number Diff line change
@@ -13,3 +13,4 @@ fails:Fiber#transfer transfers control from one Fiber to another when called fro
fails:Fiber#transfer can be invoked from the same Fiber it transfers control to
fails:Fiber#transfer can transfer control to a Fiber that has transfered to another Fiber
fails:Fiber#transfer raises a FiberError when transferring to a Fiber which resumes itself
fails:Fiber#transfer returns to the root Fiber when finished
15 changes: 13 additions & 2 deletions spec/truffle/truffle.mspec
Original file line number Diff line number Diff line change
@@ -10,10 +10,21 @@ class MSpecScript
RbConfig::CONFIG['host_os'] == 'linux'
end

set :target, File.expand_path("../../../bin/jruby#{windows? ? '.bat' : ''}", __FILE__)
JRUBY_DIR = File.expand_path('../../..', __FILE__)

set :target, "#{JRUBY_DIR}/bin/jruby#{windows? ? '.bat' : ''}"

if ARGV[-2..-1] != %w[-t ruby] # No flags for MRI
set :flags, %w[-X+T -J-ea -J-esa -J-Xmx2G -Xtruffle.graal.warn_unless=false]
flags = %w[
-X+T
-J-ea
-J-esa
-J-Xmx2G
-Xtruffle.graal.warn_unless=false
]
core_path = "#{JRUBY_DIR}/truffle/src/main/ruby"
flags << "-Xtruffle.core.load_path=#{core_path}" if File.directory?(core_path)
set :flags, flags
end

set :capi, [
2 changes: 2 additions & 0 deletions test/truffle/compiler/pe/pe.rb
Original file line number Diff line number Diff line change
@@ -110,6 +110,8 @@ def report(status, code, message = nil)
puts message ? format(format_str + "\n %s", status, code, message) : format('%14s: %s', status, code)
end

Truffle::Globals.permanently_invalidate :$value

EXAMPLES.each do |example|
next if example.tagged

4 changes: 4 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/core/CoreLibrary.java
Original file line number Diff line number Diff line change
@@ -107,6 +107,8 @@
import org.jruby.truffle.language.control.TruffleFatalException;
import org.jruby.truffle.language.globals.GlobalVariableStorage;
import org.jruby.truffle.language.globals.GlobalVariables;
import org.jruby.truffle.language.globals.TruffleGlobalsNodes;
import org.jruby.truffle.language.globals.TruffleGlobalsNodesFactory;
import org.jruby.truffle.language.loader.CodeLoader;
import org.jruby.truffle.language.loader.SourceLoader;
import org.jruby.truffle.language.methods.DeclarationContext;
@@ -620,6 +622,7 @@ public CoreLibrary(RubyContext context) {
defineModule(truffleModule, "Process");
defineModule(truffleModule, "Binding");
defineModule(truffleModule, "POSIX");
defineModule(truffleModule, "Globals");
psychModule = defineModule("Psych");
psychParserClass = defineClass(psychModule, objectClass, "Parser");
final DynamicObject psychHandlerClass = defineClass(psychModule, objectClass, "Handler");
@@ -842,6 +845,7 @@ public void addCoreMethods() {
coreMethodNodeManager.addCoreMethodNodes(TruffleBindingNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(TruffleArrayNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(TruffleStringNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(TruffleGlobalsNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(BCryptNodesFactory.getFactories());
return null;
}));
Original file line number Diff line number Diff line change
@@ -17,15 +17,15 @@
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.backtrace.Backtrace;
import org.jruby.truffle.language.backtrace.BacktraceFormatter;

import org.jruby.truffle.language.backtrace.BacktraceFormatter.FormattingFlags;
import java.util.EnumSet;
import java.util.List;

public abstract class ExceptionOperations {

private static final EnumSet<BacktraceFormatter.FormattingFlags> FORMAT_FLAGS = EnumSet.of(
BacktraceFormatter.FormattingFlags.OMIT_FROM_PREFIX,
BacktraceFormatter.FormattingFlags.OMIT_EXCEPTION);
FormattingFlags.OMIT_FROM_PREFIX,
FormattingFlags.OMIT_EXCEPTION);

@TruffleBoundary
public static DynamicObject backtraceAsRubyStringArray(RubyContext context, DynamicObject exception, Backtrace backtrace) {
Original file line number Diff line number Diff line change
@@ -133,16 +133,12 @@ public String formatLine(List<Activation> activations, int n, DynamicObject exce
final SourceSection reportedSourceSection;
String reportedName;

if (isCore(sourceSection) && !flags.contains(FormattingFlags.INCLUDE_CORE_FILES)) {
if (isJavaCore(sourceSection) ||
(isCore(sourceSection) && !flags.contains(FormattingFlags.INCLUDE_CORE_FILES))) {
final SourceSection nextUserSourceSection = nextUserSourceSection(activations, n);
// if there is no next source section use a core one to avoid ???
reportedSourceSection = nextUserSourceSection != null ? nextUserSourceSection : sourceSection;

try {
reportedName = activation.getMethod().getName();
} catch (Exception e) {
reportedName = "???";
}
reportedName = getMethodNameFromActivation(activation);
} else {
reportedSourceSection = sourceSection;
reportedName = sourceSection.getIdentifier();
@@ -188,6 +184,14 @@ public String formatLine(List<Activation> activations, int n, DynamicObject exce
return builder.toString();
}

private String getMethodNameFromActivation(Activation activation) {
try {
return activation.getMethod().getName();
} catch (Exception e) {
return "???";
}
}

private SourceSection nextUserSourceSection(List<Activation> activations, int n) {
while (n < activations.size()) {
final Node callNode = activations.get(n).getCallNode();
@@ -205,25 +209,26 @@ private SourceSection nextUserSourceSection(List<Activation> activations, int n)
return null;
}

public static boolean isJavaCore(SourceSection sourceSection) {
return sourceSection != null && sourceSection.getSource() == null;
}

public static boolean isCore(SourceSection sourceSection) {
if (sourceSection == null) {
return true;
}

final Source source = sourceSection.getSource();

if (source == null) {
return true;
}

final String path = source.getPath();

if (path != null) {
return path.startsWith(SourceLoader.TRUFFLE_SCHEME);
}

final String name = source.getName();

if (name != null) {
return name.startsWith(SourceLoader.TRUFFLE_SCHEME);
}
Original file line number Diff line number Diff line change
@@ -66,4 +66,9 @@ public void setValue(Object value) {
}
}

public void permanentlyInvalidate() {
changes = Integer.MAX_VALUE;
unchangedAssumption.invalidate();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.language.globals;

import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;
import org.jruby.truffle.builtins.CoreClass;
import org.jruby.truffle.builtins.CoreMethod;
import org.jruby.truffle.builtins.CoreMethodArrayArgumentsNode;

@CoreClass("Truffle::Globals")
public abstract class TruffleGlobalsNodes {

@CoreMethod(names = "permanently_invalidate", onSingleton = true, required = 1)
public abstract static class PermanentlyInvalidateNode extends CoreMethodArrayArgumentsNode {

@TruffleBoundary
@Specialization(guards = "isRubySymbol(name)")
public DynamicObject permanentlyInvalidate(DynamicObject name) {
getContext().getCoreLibrary().getGlobalVariables().getStorage(name.toString()).permanentlyInvalidate();
return nil();
}

}

}

0 comments on commit 8639587

Please sign in to comment.