mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
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:
@@ -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, ["-r", crb.path, drb.path])
|
||||||
assert_mruby("[1, -2, 3]\n5\n6\n", "", true, ["-b", "-r", cmrb.path, dmrb.path])
|
assert_mruby("[1, -2, 3]\n5\n6\n", "", true, ["-b", "-r", cmrb.path, dmrb.path])
|
||||||
end
|
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
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
class String
|
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)
|
def match(re, pos = 0)
|
||||||
re = Regexp.new(re) if re.is_a?(String)
|
re = Regexp.new(re) if re.is_a?(String)
|
||||||
re.match(self, pos)
|
re.match(self, pos)
|
||||||
@@ -59,10 +64,14 @@ class String
|
|||||||
end
|
end
|
||||||
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)
|
def split(pattern = nil, limit = -1)
|
||||||
return super if pattern.nil?
|
return __split(pattern, limit) if pattern.nil?
|
||||||
if pattern.is_a?(String)
|
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))
|
pattern = Regexp.new(Regexp.escape(pattern))
|
||||||
end
|
end
|
||||||
result = []
|
result = []
|
||||||
|
|||||||
Reference in New Issue
Block a user