Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
192 commits
Select commit Hold shift + click to select a range
b3fb286
Update compat version to 3.5.0
headius Nov 11, 2025
bef058a
Update most gems for 3.5
headius Nov 11, 2025
7af7ec5
Ruby 3.5 is officially 4.0 now
headius Nov 11, 2025
b1295a7
Ignore missing exts on JRuby
headius Nov 11, 2025
8f6173c
Ignore win32/registry.rb now provided by win32-registry gem
headius Nov 12, 2025
aee7394
Remove test of automatic jar extension loading
headius Nov 12, 2025
123a357
Replace loaded features rather than clear if it is frozen
headius Nov 12, 2025
227f405
Bump up size of jruby-jars
headius Nov 12, 2025
aa4642e
Split these specs to test each feature separately
headius Nov 12, 2025
ff383da
Remove defunct spec description
headius Nov 12, 2025
e15f051
First pass moving Set to core and passing all tests
headius Nov 5, 2025
85541f7
Add CRuby's test_set.rb
headius Nov 12, 2025
7019118
Update JRuby's test_set for core set move
headius Nov 12, 2025
7eed27f
Remove @hash instance variable and all references to it
headius Nov 15, 2025
c411a9d
Remove defunct library/set spec tags
headius Nov 17, 2025
235d23b
Align Hash#== behavior with CRuby
headius Nov 17, 2025
2d5e1f7
Align Set#compare_by_identity with CRuby
headius Nov 17, 2025
ddee6f5
Align Set#disjoint? and Set#intersect? with CRuby
headius Nov 17, 2025
c57e610
Implement union-find with path compression
headius Nov 17, 2025
18cb385
Propagate wrapped block's signature
headius Nov 17, 2025
b3e8a0b
Align Set#initialize enum logic with CRuby
headius Nov 17, 2025
2e946dd
Update Set#^ behavior to match CRuby
headius Nov 17, 2025
1cd5684
Update prelude from CRuby
headius Nov 17, 2025
0b82e3b
Update Set spec tags
headius Nov 17, 2025
3ea2f65
Simulate old Set marshaling for compat
headius Nov 17, 2025
c258550
Remove passing excludes for Set
headius Nov 17, 2025
55d295c
Prealloc Set's Hash along default paths
headius Nov 17, 2025
0cbc9eb
Remove defunct Set tests from JRuby suite
headius Nov 17, 2025
641afcf
Merge pull request #9066 from headius/core_set
headius Nov 17, 2025
270c0a7
Avoid array allocation for *nil, by not calling nil.to_a
headius Nov 18, 2025
becb750
Merge pull request #9074 from headius/nil_splat
headius Nov 18, 2025
1c48b59
No numbered parameters in Binding#local_variables
headius Nov 18, 2025
dc7c280
Selective inspect of instance variables
headius Nov 18, 2025
5f3dc14
Merge pull request #9075 from headius/inspect_variables
headius Nov 18, 2025
ccf3020
Merge pull request #9077 from headius/no_implicits_in_local_vars
headius Nov 18, 2025
3eb70db
Another gem update for Ruby 4.0
headius Nov 18, 2025
337a420
Deprecate ObjectSpace._id2ref
headius Nov 18, 2025
fd9f761
Add Math.{expm1,log1p}
headius Nov 18, 2025
cc0c818
Merge pull request #9078 from headius/math_expm1_log1p
headius Nov 18, 2025
5ec0f80
Remove deprecated open with pipe
headius Nov 18, 2025
c7b5639
Align IO.select timeout logic with CRuby
headius Nov 18, 2025
58b44ea
Merge pull request #9079 from headius/io_select_infinity
headius Nov 18, 2025
6252ebd
Merge branch 'master' into ruby-4.0
headius Nov 19, 2025
51c0e4b
Mild refactoring of RubyKernel.raise
headius Nov 18, 2025
0fe5c55
Implement cause: for Thread#raise and Fiber#raise
headius Nov 19, 2025
d949109
Merge pull request #9083 from headius/raise_updates
headius Dec 30, 2025
961f027
Merge branch '10.1-dev' into ruby-4.0
headius Dec 30, 2025
8bbc0d5
Add backward compat for Set subclasses
headius Dec 30, 2025
f3a4525
Update tests from CRuby 4.0.0 release
headius Dec 30, 2025
79cf0d4
Exclude hanging Fiber test
headius Dec 30, 2025
2ce8be1
Add Array#find and Array#rfind
headius Dec 31, 2025
a5ed3cf
Implement 128-bit ints and range checks for IO::Buffer
headius Dec 31, 2025
d3b8895
Infinite Range#to_set should raise RangeError
headius Dec 31, 2025
0f9727e
Implement Range#max with beginless and size
headius Dec 31, 2025
fbb7fbb
Exclude some MRI-specific tests
headius Dec 31, 2025
acecdae
Exclude hanging Fiber scheduler unblock test
headius Dec 31, 2025
c89e110
Update gems to 4.0.0 release versions
headius Dec 31, 2025
b996789
Exclude test that uses RubyVM
headius Dec 31, 2025
76cd35c
Implement Enumerator.produce size keyword
headius Dec 31, 2025
8a9bf26
Define top-level Ruby module
headius Dec 31, 2025
4cb30db
Add to_set to Enumerable and deprecate passing args
headius Dec 31, 2025
ef3d5d0
Update warning for ruby2_keywords
headius Jan 2, 2026
9eae064
Mask internal Ruby backtrace elements like native masking
headius Jan 6, 2026
7a732e2
Merge pull request #9154 from headius/mask_internal_frames
headius Jan 7, 2026
33c4ae2
Exclude two more tests that depend on CRuby GC APIs
headius Jan 13, 2026
b8880cf
Update deprecation for $, and $\
headius Jan 13, 2026
8534401
Use strict coercion logic to reject non-Proc
headius Jan 13, 2026
4f7d71d
Partially fix deprecation for $/ and $; variables
headius Jan 13, 2026
bf93b26
Tag in-place dedup test not implementable on JRuby
headius Jan 13, 2026
4e313a7
Exclude test for use-after-free not possible in JRuby
headius Jan 13, 2026
b351ad8
Verify encoding of path for File.path
headius Jan 13, 2026
74f3afe
Avoid calling #size for to_set on Enumerable and Range
headius Jan 13, 2026
dce6134
Ensure Module#name is frozen
headius Jan 13, 2026
8ca9ae0
Check frozen status setting Module temp name
headius Jan 13, 2026
de7a508
Delegate to Array#fetch from Array#fetch_values
headius Jan 13, 2026
e9dff45
Specification#has_rdoc was finally removed
headius Jan 13, 2026
eedab81
Remove CGI gem and commit remaining pieces
headius Jan 13, 2026
1bc93aa
Implement implicit param logic for Binding
headius Jan 14, 2026
80252f4
Merge pull request #9180 from headius/binding_implicits
headius Jan 14, 2026
2719a90
Update reline tests
headius Jan 14, 2026
abd6cec
Fix Data subclasses with ivars
headius Jan 15, 2026
1559cda
Update stdlib tests again from CRuby 4.0
headius Jan 22, 2026
29400f8
Merge branch '10.1-dev' into ruby-4.0
headius Jan 22, 2026
ca2f450
Exclude more ObjSpace tests specific to CRuby
headius Jan 22, 2026
40ccf3f
Add TracePoint.stat
headius Jan 22, 2026
a14ab67
Update test/tool/lib from CRuby tool/lib
headius Jan 22, 2026
ddcd049
Add utility methods from CRuby rbconfig.rb
headius Jan 22, 2026
0a19eeb
Add dummy Sanitizers for CRuby tests
headius Jan 22, 2026
6cf9fcb
Remove win32ole tests already deleted
headius Jan 22, 2026
883925b
Implement remaining 4.0 predefined var changes
headius Jan 23, 2026
f20b324
Separate configurable separator from default
headius Jan 23, 2026
a5894a2
Update error message to match CRuby
headius Jan 23, 2026
f091520
Also skip ruby2_keywords when there's post args
headius Jan 23, 2026
aec59cb
Only error for endless set
headius Jan 23, 2026
35547a8
Need to actually scan for dest code range here
headius Jan 23, 2026
8992389
Tweak Kernel#inspect when requested ivars is nil or non-ary
headius Jan 23, 2026
e2afba1
Don't double-coerce in fetch_values
headius Jan 23, 2026
9937e85
Add doco about the fail return value
headius Jan 23, 2026
e49fff2
Merge branch '10.1-dev' into ruby-4.0
headius Jan 23, 2026
ce62ffe
Rework double conversion to match CRuby
headius Jan 23, 2026
b34cfb2
Correct immediate flag for core types
headius Jan 23, 2026
b49556e
Remove another test previously deleted
headius Jan 23, 2026
efcd1a2
Fix formatting of some MathDomainError messages
headius Jan 23, 2026
97d9efa
Restore immediate status to False
headius Jan 23, 2026
e7ff21e
A Data object should be frozen even if it has no members
evaniainbrooks Jan 30, 2026
321113a
Merge pull request #9202 from evaniainbrooks/9179-data-frozen
enebo Jan 30, 2026
0d0c1eb
Add ruby_bug for spec of Data with no members being frozen
herwinw Feb 3, 2026
b491f33
Rewrite spec for Data with no members being frozen
herwinw Feb 3, 2026
506f5d4
Remove Process::Status#& and Process::Status#>>
herwinw Feb 3, 2026
75962da
Merge pull request #9210 from herwinw/ruby_4_remove_process_status_me…
headius Feb 3, 2026
e3be698
Merge pull request #9209 from herwinw/spec_data_initialize
headius Feb 3, 2026
b117b9d
Merge remote-tracking branch 'origin/ruby-4.0' into data_ivar_fixes
headius Feb 3, 2026
75b6d59
Merge pull request #9181 from headius/data_ivar_fixes
headius Feb 3, 2026
ff66485
Merge remote-tracking branch 'origin/10.1-dev' into ruby-4.0
headius Feb 11, 2026
ed58f10
Update Exception#cause behavior to match 4.0
headius Feb 11, 2026
078bb4d
Modify our exception test to match CRuby 4 behavior
headius Feb 11, 2026
1b25b39
Use capitalized Class and Module for frozen errors
headius Feb 12, 2026
e1e02cf
Merge pull request #9235 from headius/frozen_module_message
headius Feb 12, 2026
4743855
Properly handle keywords in {Kernel|Thread|Fiber}#raise
headius Feb 12, 2026
2616578
Guard against Ruby::Box accesses
headius Feb 13, 2026
3732a82
Implement CRuby 4.0 Bignum slicing
headius Feb 14, 2026
31b2971
Allow instance variable names for Data
headius Feb 14, 2026
8c367c5
Don't mutate either set while doing xor
headius Feb 14, 2026
88331a6
Exclude aliased global variable deprecation tests
headius Feb 14, 2026
5d72958
Fix another error capitalization change
headius Feb 14, 2026
e03966e
Eagerly init copied module/class
headius Feb 14, 2026
163629e
Fix inspect recursion logic to match CRuby
headius Feb 14, 2026
f81eb73
Fix for cloned class singleton class has too many ancestors
evaniainbrooks Feb 15, 2026
0823d6e
Merge pull request #9239 from evaniainbrooks/9238-singleton-ancestors
headius Feb 18, 2026
0e8bc23
Remove commented code
headius Feb 14, 2026
b42564d
Restore overridden to_s call
headius Feb 18, 2026
9fd233f
Merge pull request #9236 from headius/kernel_thread_fiber_raise
headius Feb 18, 2026
8d1fd29
Fix bad merge of require_spec
headius Feb 18, 2026
9f30e68
Pass block through Range#to_set
headius Feb 18, 2026
50dd6ff
Clean up last failure in imported cgi/escape
headius Feb 18, 2026
dd809d4
Native files can't be mapped by IO::Buffer yet
headius Feb 18, 2026
ffcd2b8
Still need work to include class name in backtrace
headius Feb 18, 2026
bf2f0db
Defer updating unicode for now
headius Feb 18, 2026
5022765
Match CRuby CGI::Escape module setup
headius Feb 18, 2026
39b1834
Exclude pure-Ruby tests with problematic alias trick
headius Feb 18, 2026
4dcdcac
Exclude tests that want class on backtrace frames
headius Feb 18, 2026
ef9a131
Exclude tests of IO::Buffer file mapping
headius Feb 18, 2026
8c5d04a
Exclude tests of unicode level
headius Feb 18, 2026
424a7d6
Add pathname to provided libraries
headius Feb 18, 2026
18bc039
Remove JRuby internals before testing
headius Feb 18, 2026
6db771b
Upgrade jcodings to 1.0.64 for Unicode 17
headius Feb 20, 2026
c81f39d
Merge branch 'master' into ruby-4.0
headius Feb 24, 2026
eb3751f
Internalize pathname for now
headius Feb 24, 2026
17dc4a9
Update joni to 2.2.7
headius Feb 25, 2026
1faa4d4
Merge branch 'master' into ruby-4.0
headius Feb 25, 2026
2afcfff
Don't set @hash ivar on Set anymore
headius Feb 26, 2026
7533940
Don't map pathname to pathname.so on JRuby
headius Feb 26, 2026
f2cddaf
Tag last file-mapping fail in IO::Buffer.map specs
headius Feb 26, 2026
4ad7618
Implement Array#fetch_vaues in terms of fetch
headius Feb 26, 2026
e49f1a4
Exclud negative lines from coverage
headius Feb 26, 2026
ec11fd9
Unwrap Java exceptions for Thread#raise enqueueing
headius Feb 26, 2026
1fe490a
Remove extra whitespace
headius Feb 26, 2026
58ad113
Mark implicit arg nodes for handling in #parameters
headius Feb 26, 2026
8f7bfda
Implicits are -2 so filter all < 0
headius Feb 26, 2026
73630b2
Separate logic for implicit params and local variables
headius Feb 26, 2026
326063d
Exclude last weird "it" case from MRI tests
headius Feb 26, 2026
8bfae83
Exclude modified endless def syntax test
headius Feb 26, 2026
a889511
Exclude String#split/rsplit with selectors tests
headius Feb 26, 2026
83c17e8
Exclude rehash-during-update Hash tests
headius Feb 26, 2026
2822e7c
Exclude deadlock output test
headius Feb 26, 2026
b4068f1
Exclude tests for alternative pattern with local vars
headius Feb 26, 2026
8fc6e9d
These complex block+call forms do not parse
headius Feb 26, 2026
ccf6291
Disallow recursive userdef dumps
headius Feb 27, 2026
a797c55
Exclude new Ruby 4.0 OpenSSL failures
headius Feb 28, 2026
be519a6
Exclude another HTTP proxy test that appears to hang
headius Feb 28, 2026
d52a9ed
Update socket.rb from CRuby
headius Feb 28, 2026
801abb9
Accept :open_timeout keyword but ignore for now
headius Feb 28, 2026
0ffed86
Fix recursion check for Kernel#inspect
headius Feb 28, 2026
f6318a9
Implement Pathname#initialze as in CRuby
headius Feb 28, 2026
91ba2e3
Implement Pathname#lutime, arity split File.lutime/utime
headius Feb 28, 2026
90c8785
Exclude some Fiber scheduler tests that aren't hooked up
headius Feb 28, 2026
8cf0a7e
Exclude some OpenURI tests that fail in util code
headius Mar 1, 2026
32129d9
Implement state management for IO#timeout
headius Mar 1, 2026
22f3658
Unexclude IO#timeout-related tests
headius Mar 1, 2026
57551bb
Exclude a few more OpenURI tests failing in util code
headius Mar 1, 2026
38ff55f
Define Encoding::UNICODE_VERSION
headius Feb 28, 2026
6021669
Update unicode_normalize sources from CRuby
headius Feb 28, 2026
9875b61
Tag SSL test for timeout
headius Mar 1, 2026
b070109
Exclude a few more OpenURI tests failing in util code
headius Mar 1, 2026
a8b344a
Accept fast_fallback and test_mode_settings kwargs
headius Mar 1, 2026
bbdeaca
Coerce path argument to UNIXServer.open
headius Mar 1, 2026
ba9c568
Match CRuby frozen error for class/module
headius Mar 1, 2026
249506f
Exclude test failing on GHA Linux
headius Mar 1, 2026
e597aab
Exclude remaining open-uri test failures
headius Mar 1, 2026
c58da66
Additional failure due to new callable form
headius Mar 1, 2026
2520273
Exclude remaining IO and socket failures
headius Mar 1, 2026
6a826d6
Exclude remaining unfinished Ruby 4.0 tests
headius Mar 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ lib/ruby/stdlib/*.jar
lib/ruby/stdlib/ant*
lib/ruby/stdlib/benchmark*
lib/ruby/stdlib/bundler*
lib/ruby/stdlib/cgi*
lib/ruby/stdlib/debug*
lib/ruby/stdlib/delegate*
lib/ruby/stdlib/did_you_mean*
Expand Down Expand Up @@ -125,6 +124,7 @@ lib/ruby/stdlib/un*
lib/ruby/stdlib/uri*
lib/ruby/stdlib/yaml*
lib/ruby/stdlib/weakref*
lib/ruby/stdlib/win32/registry.rb

release.properties
share
Expand Down
4 changes: 2 additions & 2 deletions core/pom.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@
jar 'com.github.jnr:jffi:${jffi.version}'
jar 'com.github.jnr:jffi:${jffi.version}:native'

jar 'org.jruby.joni:joni:2.2.6'
jar 'org.jruby.jcodings:jcodings:1.0.63'
jar 'org.jruby.joni:joni:2.2.7'
jar 'org.jruby.jcodings:jcodings:1.0.64'
jar 'org.jruby:dirgra:0.5'

jar 'com.headius:invokebinder:1.14'
Expand Down
10 changes: 5 additions & 5 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ DO NOT MODIFY - GENERATED CODE
<test.results.dir>${build.dir}/test-results</test.results.dir>
<tzdata.scope>provided</tzdata.scope>
<tzdata.version>2019c</tzdata.version>
<version.ruby>3.4.5</version.ruby>
<version.ruby.major>3.4</version.ruby.major>
<version.ruby.minor>5</version.ruby.minor>
<version.ruby>4.0.0</version.ruby>
<version.ruby.major>4.0</version.ruby.major>
<version.ruby.minor>0</version.ruby.minor>
</properties>
<dependencies>
<dependency>
Expand Down Expand Up @@ -149,12 +149,12 @@ DO NOT MODIFY - GENERATED CODE
<dependency>
<groupId>org.jruby.joni</groupId>
<artifactId>joni</artifactId>
<version>2.2.6</version>
<version>2.2.7</version>
</dependency>
<dependency>
<groupId>org.jruby.jcodings</groupId>
<artifactId>jcodings</artifactId>
<version>1.0.63</version>
<version>1.0.64</version>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
Expand Down
18 changes: 14 additions & 4 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import org.jruby.exceptions.LocalJumpError;
import org.jruby.exceptions.SystemExit;
import org.jruby.ext.jruby.JRubyUtilLibrary;
import org.jruby.ext.set.RubySet;
import org.jruby.ext.thread.ConditionVariable;
import org.jruby.ext.thread.Mutex;
import org.jruby.ext.thread.Queue;
Expand Down Expand Up @@ -518,6 +519,8 @@ private Ruby(RubyInstanceConfig config) {

dataClass = RubyData.createDataClass(context, objectClass);

setClass = RubySet.createSetClass(context, objectClass, enumerableModule);

// everything booted, so SizedQueue should be available; set up root fiber
ThreadFiber.initRootFiber(context, context.getThread());

Expand Down Expand Up @@ -602,6 +605,8 @@ private void initBootLibraries(ThreadContext context) {
loadService.provide("thread.rb");
loadService.provide("fiber.rb");
loadService.provide("ruby2_keywords.rb");
loadService.provide("set.rb");
loadService.provide("pathname.rb");

// Load preludes
initRubyPreludes();
Expand Down Expand Up @@ -2508,6 +2513,10 @@ public RubyClass getData() {
return dataClass;
}

public RubyClass getSet() {
return setClass;
}

/** The default Ruby Random object for this runtime */
private RubyRandom defaultRandom;

Expand Down Expand Up @@ -4391,7 +4400,7 @@ public RaiseException newFloatDomainError(String message){
}

public RaiseException newMathDomainError(String message) {
return newRaiseException(getMathDomainError(), "Numerical argument is out of domain - \"" + message + "\"");
return newRaiseException(getMathDomainError(), "Numerical argument is out of domain - " + message);
}

public RaiseException newEncodingError(String message){
Expand Down Expand Up @@ -4452,12 +4461,13 @@ public RaiseException newBufferMaskError(String message) {
* @return a new RaiseException wrapping a new Ruby exception
*/
public RaiseException newRaiseException(RubyClass exceptionClass, String message) {
IRubyObject cause = getCurrentContext().getErrorInfo();
ThreadContext context = getCurrentContext();
IRubyObject cause = context.getErrorInfo();

RaiseException exception = RaiseException.from(this, exceptionClass, message);

if (cause != null && !cause.isNil()) {
exception.getException().setCause(cause);
exception.getException().setCause(context, cause);
}

return exception;
Expand Down Expand Up @@ -5076,7 +5086,6 @@ public void setChdirThread(RubyThread thread) {
public RubyThread getChdirThread() { return this.chdirCurrentThread; }

public RubyStackTraceElement getChdirLocation() { return this.chdirLocation; }

/**
* Because RubyString.equals does not consider encoding, and MRI's logic for deduplication does need to consider
* encoding, we use a wrapper object as the key. These wrappers need to be used on all get operations, so if we
Expand Down Expand Up @@ -5316,6 +5325,7 @@ public interface RecursiveFunctionEx<T> extends ThreadContext.RecursiveFunctionE
private final RubyClass closedQueueError;
private final RubyClass sizedQueueClass;
private final RubyClass dataClass;
private final RubyClass setClass;

private RubyClass tmsStruct;
private RubyClass passwdStruct;
Expand Down
7 changes: 7 additions & 0 deletions core/src/main/java/org/jruby/RubyArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.callsite.CachingCallSite;
import org.jruby.runtime.marshal.MarshalDumper;
import org.jruby.runtime.marshal.MarshalLoader;
import org.jruby.specialized.RubyArrayOneObject;
Expand Down Expand Up @@ -1357,6 +1358,12 @@ public void copyInto(IRubyObject[] target, int start, int len) {
@Override
public abstract boolean equals(Object other);

@JRubyMethod
public abstract IRubyObject rfind(ThreadContext context, Block block);

@JRubyMethod
public abstract IRubyObject rfind(ThreadContext context, IRubyObject ifnone, Block block);

@Deprecated(since = "10.0.0.0", forRemoval = true)
@SuppressWarnings("removal")
public static void marshalTo(RubyArray array, org.jruby.runtime.marshal.MarshalStream output) throws IOException {
Expand Down
37 changes: 23 additions & 14 deletions core/src/main/java/org/jruby/RubyArrayNative.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
package org.jruby;

import org.jcodings.specific.USASCIIEncoding;
import org.jruby.anno.JRubyMethod;
import org.jruby.api.Create;
import org.jruby.api.JRubyAPI;
import org.jruby.ast.util.ArgsUtil;
Expand Down Expand Up @@ -922,21 +923,10 @@ public T eltInternalSet(int offset, T item) {

public IRubyObject fetch_values(ThreadContext context, IRubyObject[] args, Block block) {
int length = args.length;
if (length == 0) return Create.newEmptyArray(context);

int arraySize = size();
var result = Create.allocArray(context, length);
for (int i = 0; i < length; i++) {
int index = toInt(context, args[i]);
// FIXME: lookup the bounds part of this in error message??
if (index >= arraySize) {
if (!block.isGiven()) throw indexError(context, "index " + index + " outside of array bounds: 0...0");
result.append(context, block.yield(context, asFixnum(context, index)));
} else {
result.append(context, eltOk(index));
}
RubyArray result = RubyArrayNative.newBlankArrayInternal(context.runtime, length);
for (int i = 0; i < args.length; i++) {
result.storeInternal(context, i, fetch(context, args[i], block));
}

return result;
}

Expand Down Expand Up @@ -5205,6 +5195,25 @@ public boolean equals(Object other) {
return false;
}

@JRubyMethod
public IRubyObject rfind(ThreadContext context, Block block) {
return rfind(context, context.nil, block);
}

@JRubyMethod
public IRubyObject rfind(ThreadContext context, IRubyObject ifnone, Block block) {
CachingCallSite self_each = sites(context).self_each;
if (!self_each.isBuiltin(this)) return RubyEnumerable.detectCommon(context, self_each, this, block);

for (int i = realLength - 1; i >= 0; i--) {
IRubyObject value = eltOk(i);

if (block.yield(context, value).isTrue()) return value;
}

return ifnone != null && !ifnone.isNil() ? sites(context).call.call(context, ifnone, ifnone) : context.nil;
}

private static IRubyObject safeArrayRef(ThreadContext context, IRubyObject[] values, int i) {
try {
return values[i];
Expand Down
109 changes: 75 additions & 34 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ protected final void testFrozen(String message) {
protected final void testFrozen() {
if (isFrozen()) {
var context = getRuntime().getCurrentContext();
throw context.runtime.newFrozenError((isClass() ? "Class: " : (isModule() ? "Module: " : "object: ")) + inspect(context), this);
throw context.runtime.newFrozenError((isClass() ? "Class: " : (isModule() ? "Module: " : "Object: ")) + inspect(context), this);
}
}

Expand Down Expand Up @@ -905,6 +905,7 @@ private static void initCopy(ThreadContext context, IRubyObject clone, IRubyObje
RubyModule cloneMod = (RubyModule)clone;
cloneMod.syncConstants((RubyModule)original);
cloneMod.syncClassVariables((RubyModule)original);
cloneMod.initializeCopiedModule(context, original);
}
}

Expand Down Expand Up @@ -1028,16 +1029,20 @@ protected RubyClass getSingletonClassCloneAndAttach(ThreadContext context, RubyB
MetaClass clone = new MetaClass(context.runtime, klass.getSuperClass(), attach);
clone.flags = klass.flags;

clone.setMetaClass(this instanceof RubyClass ? clone : klass.getSingletonClassCloneAndAttach(context, null));
if (this instanceof RubyClass) {
clone.setMetaClass(clone);
} else {
MetaClass metaClone = (MetaClass) klass.getSingletonClassCloneAndAttach(context, null);
clone.setMetaClass(metaClone);
metaClone.setAttached(clone);
}

if (klass.hasVariables()) clone.syncVariables(klass);

clone.syncConstants(klass);

klass.cloneMethods(context, clone);

((MetaClass) clone.getMetaClass()).setAttached(clone);

return clone;
}

Expand Down Expand Up @@ -1132,24 +1137,26 @@ public IRubyObject inspect() {
// MRI: rb_obj_inspect
public IRubyObject inspect(ThreadContext context) {
return !isImmediate() && !(this instanceof RubyModule) && hasVariables() ?
hashyInspect() : to_s(context);
hashyInspect(context) : to_s(context);
}

@Deprecated(since = "10.1.0.0")
public final IRubyObject hashyInspect() {
final Ruby runtime = getRuntime();
return hashyInspect(getRuntime().getCurrentContext());
}

RubyString part = inspectPrefix(runtime.getCurrentContext(), metaClass.getRealClass(), inspectHashCode());
public final IRubyObject hashyInspect(ThreadContext context) {
IRubyObject ivars = Helpers.invokeChecked(context, this, sites(context).instance_variables_to_inspect_checked);

if (runtime.isInspecting(this)) {
encStrBufCat(runtime, part, SPACE_DOT_DOT_DOT_GT);
return part;
}
try {
runtime.registerInspecting(this);
return inspectObj(runtime, part);
} finally {
runtime.unregisterInspecting(this);
if (ivars != null && !ivars.isNil() && !(ivars instanceof RubyArray)) {
throw typeError(context, "Expected #instance_variables_to_inspect to return an Array or nil, but it returned " + ivars.getMetaClass());
}

RubyString part = inspectPrefix(context, metaClass.getRealClass(), inspectHashCode());

return context.execRecursive(
(ctx, p, obj, recur) -> inspectObj(ctx, p, ivars, recur),
part, this, "inspect");
}

// MRI: rb_inspect, which does dispatch
Expand Down Expand Up @@ -1187,31 +1194,63 @@ protected int inspectHashCode() {
* The internal helper method that takes care of the part of the
* inspection that inspects instance variables.
*/
private RubyString inspectObj(final Ruby runtime, RubyString part) {
final ThreadContext context = runtime.getCurrentContext();
private RubyString inspectObj(final ThreadContext context, RubyString part, IRubyObject ivars, boolean recur) {
Ruby runtime = context.runtime;

if (recur) {
encStrBufCat(runtime, part, SPACE_DOT_DOT_DOT_GT);
return part;
}

if (ivars == null || ivars.isNil()) {
// no ivars specified, do all of them
boolean first = true;
for (Map.Entry<String, VariableAccessor> entry : metaClass.getVariableTableManager().getVariableAccessorsForRead().entrySet()) {
VariableAccessor accessor = entry.getValue();
String name = entry.getKey();

boolean first = true;
for (Map.Entry<String, VariableAccessor> entry : metaClass.getVariableTableManager().getVariableAccessorsForRead().entrySet()) {
Object value = entry.getValue().get(this);
if (!(value instanceof IRubyObject)) continue;
RubySymbol symbol = asSymbol(context, entry.getKey());
if (!symbol.validInstanceVariableName()) continue;
if (appendInstanceVariable(context, part, accessor, name, first, runtime)) continue;

first = false;
}
} else {
// ivars specified, do only those
RubyArray ivarsAry = Convert.castAsArray(context, ivars);

IRubyObject obj = (IRubyObject) value;
boolean first = true;
Map<String, VariableAccessor> accessors = metaClass.getVariableTableManager().getVariableAccessorsForRead();
for (int i = 0; i < ivarsAry.size(); i++) {
String name = ivarsAry.eltOk(i).toString();
VariableAccessor accessor = accessors.get(name);
if (accessor == null) continue;

if (!first) encStrBufCat(runtime, part, COMMA);
encStrBufCat(runtime, part, SPACE);
// FIXME: bytelist_love: EPICLY wrong but something in MRI gets around identifiers of arbitrary encoding.
encStrBufCat(runtime, part, symbol.asString().encode(context, encodingService(context).convertEncodingToRubyEncoding(part.getEncoding())).asString().getByteList());
encStrBufCat(runtime, part, EQUALS);
encStrBufCat(runtime, part, sites(context).inspect.call(context, obj, obj).convertToString().getByteList());
if (appendInstanceVariable(context, part, accessor, name, first, runtime)) continue;

first = false;
first = false;
}
}

encStrBufCat(runtime, part, GT);
return part;
}

private boolean appendInstanceVariable(ThreadContext context, RubyString part, VariableAccessor accessor, String name, boolean first, Ruby runtime) {
Object value = accessor.get(this);
if (!(value instanceof IRubyObject)) return true;
RubySymbol symbol = asSymbol(context, name);
if (!symbol.validInstanceVariableName()) return true;

IRubyObject obj = (IRubyObject) value;

if (!first) encStrBufCat(runtime, part, COMMA);
encStrBufCat(runtime, part, SPACE);
// FIXME: bytelist_love: EPICLY wrong but something in MRI gets around identifiers of arbitrary encoding.
encStrBufCat(runtime, part, symbol.asString().encode(context, encodingService(context).convertEncodingToRubyEncoding(part.getEncoding())).asString().getByteList());
encStrBufCat(runtime, part, EQUALS);
encStrBufCat(runtime, part, sites(context).inspect.call(context, obj, obj).convertToString().getByteList());
return false;
}

// Methods of the Object class (rb_obj_*):


Expand Down Expand Up @@ -1695,8 +1734,10 @@ public void forEachInstanceVariable(BiConsumer<String, IRubyObject> accessor) {
}

private void raiseFrozenError() throws RaiseException {
if (this instanceof RubyModule) {
throw getRuntime().newFrozenError("class/module ", this);
if (this instanceof RubyClass) {
throw getRuntime().newFrozenError("Class", this);
} else if (this instanceof RubyModule) {
throw getRuntime().newFrozenError("Module", this);
} else {
throw getRuntime().newFrozenError(this);
}
Expand Down
Loading
Loading