mruby-regexp: alias original String#split before overriding it

`class String; def split` in mruby-regexp/mrblib/string_regexp.rb
replaced the C-defined String#split rather than overriding it, so
the in-Ruby `return super if pattern.nil?` paths raised
NoMethodError for any `"x".split(...)` call once mruby-regexp was
loaded (the default full-core production binary).

The regression wasn't caught by the test suite because per-gem
tests run under mrb_open_core() with only the gem's dep_list, so
the broken override is never visible from test/t/string.rb
(mruby-test, not mruby-regexp).

Add `alias __split split` at the top of the override class body,
which captures the C-defined method, and change the Ruby override
to delegate via `__split(pattern, limit)` for non-regexp fallback
paths. Add a bintest under mruby-bin-mruby that runs through
bin/mruby (full gem load) to catch this regression class.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2026-05-11 12:45:43 +09:00
parent 0a78ab986d
commit 9d8d41006b
2 changed files with 25 additions and 2 deletions
+14
View File
@@ -176,3 +176,17 @@ assert('top level local variables are in file scope') do
assert_mruby("[1, -2, 3]\n5\n6\n", "", true, ["-r", crb.path, drb.path])
assert_mruby("[1, -2, 3]\n5\n6\n", "", true, ["-b", "-r", cmrb.path, dmrb.path])
end
assert('String#split still works when mruby-regexp is loaded') do
# The regexp-aware override in mruby-regexp/mrblib/string_regexp.rb used to
# replace the C-defined String#split, leaving its `return super if ...`
# fast paths with no method to delegate to (NoMethodError). Now the
# override delegates via `__split`, an alias of the original C method
# installed in mrb_mruby_regexp_gem_init before mrblib runs.
assert_mruby(%Q(["a", "b", "c"]\n), "", true,
["-e", 'p "a,b,c".split(",")'])
assert_mruby(%Q(["abc", "abc", "abc"]\n), "", true,
["-e", 'p "abc abc abc".split'])
assert_mruby(%Q(["hello", "world"]\n), "", true,
["-e", 'p "hello world".split(/\s+/)'])
end
+11 -2
View File
@@ -1,4 +1,9 @@
class String
# Capture the C-defined String#split under `__split` before the override
# below replaces it, so the override can delegate non-regexp patterns
# back to the core implementation.
alias __split split
def match(re, pos = 0)
re = Regexp.new(re) if re.is_a?(String)
re.match(self, pos)
@@ -59,10 +64,14 @@ class String
end
end
# Regexp-aware split. Falls back to the C-defined split (aliased as
# `__split` in mrb_mruby_regexp_gem_init before this override loads) for
# nil or simple-string patterns; converts string-with-backslash to a
# Regexp and handles regexp patterns in Ruby.
def split(pattern = nil, limit = -1)
return super if pattern.nil?
return __split(pattern, limit) if pattern.nil?
if pattern.is_a?(String)
return super if pattern.length == 1 || !pattern.include?('\\')
return __split(pattern, limit) if pattern.length == 1 || !pattern.include?('\\')
pattern = Regexp.new(Regexp.escape(pattern))
end
result = []