Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: opal/opal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 7990dbea53cc
Choose a base ref
...
head repository: opal/opal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f87d14a738da
Choose a head ref
  • 2 commits
  • 5 files changed
  • 2 contributors

Commits on Apr 27, 2015

  1. Copy the full SHA
    d95e59a View commit details
  2. Merge pull request #813 from vais/string-scan

    Fix String#scan, make #gsub, #rindex, #rpartition multiline by default
    elia committed Apr 27, 2015

    Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    f87d14a View commit details
Showing with 38 additions and 18 deletions.
  1. +20 −16 opal/corelib/string.rb
  2. +6 −0 spec/filters/bugs/string.rb
  3. +2 −0 spec/filters/unsupported/regular_expressions.rb
  4. +9 −1 spec/filters/unsupported/tainted.rb
  5. +1 −1 spec/rubyspecs
36 changes: 20 additions & 16 deletions opal/corelib/string.rb
Original file line number Diff line number Diff line change
@@ -430,10 +430,10 @@ def gsub(pattern, replacement = undefined, &block)
var result = '', match_data = nil, index = 0, match, _replacement;
if (pattern.$$is_regexp) {
pattern = new RegExp(pattern.source, 'g' + (pattern.multiline ? 'm' : '') + (pattern.ignoreCase ? 'i' : ''));
pattern = new RegExp(pattern.source, 'gm' + (pattern.ignoreCase ? 'i' : ''));
} else {
pattern = #{Opal.coerce_to(`pattern`, String, :to_str)};
pattern = new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
pattern = new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gm');
}
while (true) {
@@ -821,7 +821,7 @@ def rindex(search, offset = undefined)
if (search.$$is_regexp) {
m = null;
r = new RegExp(search.source, 'g' + (search.multiline ? 'm' : '') + (search.ignoreCase ? 'i' : ''));
r = new RegExp(search.source, 'gm' + (search.ignoreCase ? 'i' : ''));
while (true) {
_m = r.exec(self);
if (_m === null || _m.index > offset) {
@@ -872,7 +872,7 @@ def rpartition(sep)
if (sep.$$is_regexp) {
m = null;
r = new RegExp(sep.source, 'g' + (sep.multiline ? 'm' : '') + (sep.ignoreCase ? 'i' : ''));
r = new RegExp(sep.source, 'gm' + (sep.ignoreCase ? 'i' : ''));
while (true) {
_m = r.exec(self);
@@ -914,27 +914,31 @@ def rstrip

def scan(pattern, &block)
%x{
if (pattern.global) {
// should we clear it afterwards too?
pattern.lastIndex = 0;
}
else {
// rewrite regular expression to add the global flag to capture pre/post match
pattern = new RegExp(pattern.source, 'g' + (pattern.multiline ? 'm' : '') + (pattern.ignoreCase ? 'i' : ''));
}
var result = [],
match_data = nil,
match;
var result = [];
var match;
if (pattern.$$is_regexp) {
pattern = new RegExp(pattern.source, 'gm' + (pattern.ignoreCase ? 'i' : ''));
} else {
pattern = #{Opal.coerce_to(`pattern`, String, :to_str)};
pattern = new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gm');
}
while ((match = pattern.exec(self)) != null) {
var match_data = #{MatchData.new `pattern`, `match`};
match_data = #{MatchData.new `pattern`, `match`};
if (block === nil) {
match.length == 1 ? result.push(match[0]) : result.push(#{`match_data`.captures});
} else {
match.length == 1 ? block(match[0]) : block.apply(self, #{`match_data`.captures});
match.length == 1 ? block(match[0]) : block.call(self, #{`match_data`.captures});
}
if (pattern.lastIndex === match.index) {
pattern.lastIndex += 1;
}
}
#{$~ = `match_data`}
return (block !== nil ? self : result);
}
end
6 changes: 6 additions & 0 deletions spec/filters/bugs/string.rb
Original file line number Diff line number Diff line change
@@ -9,6 +9,12 @@
fails "String#lines uses $/ as the separator when none is given"
fails "String#lines yields subclass instances for subclasses"

#The following failure is a side-effect of a symbol being used in one of the assertions:
fails "String#scan raises a TypeError if pattern isn't a Regexp and can't be converted to a String"

#The following failure is a side-effect of the currently broken MatchData#offset implementation:
fails "String#scan with pattern and block sets $~ for access from the block"

fails "String#slice with Range calls to_int on range arguments"

fails "String#split with String returns subclass instances based on self"
2 changes: 2 additions & 0 deletions spec/filters/unsupported/regular_expressions.rb
Original file line number Diff line number Diff line change
@@ -7,4 +7,6 @@
fails "String#gsub with pattern and replacement doesn't freak out when replacing ^" #Only fails "Text\nFoo".gsub(/^/, ' ').should == " Text\n Foo"
fails "String#gsub with pattern and replacement supports \\G which matches at the beginning of the remaining (non-matched) string"
fails "String#gsub with pattern and replacement returns a copy of self with all occurrences of pattern replaced with replacement" #Only fails str.gsub(/\Ah\S+\s*/, "huh? ").should == "huh? homely world. hah!"

fails "String#scan supports \\G which matches the end of the previous match / string start for first match"
end
10 changes: 9 additions & 1 deletion spec/filters/unsupported/tainted.rb
Original file line number Diff line number Diff line change
@@ -120,9 +120,17 @@
fails "String#rjust with length, padding taints result when self or padstr is tainted"
fails "String#rjust with length, padding when padding is tainted and self is untainted returns a tainted string if and only if length is longer than self"


fails "String#rstrip taints the result when self is tainted"

fails "String#scan taints the results if the String argument is tainted"
fails "String#scan taints the results when passed a String argument if self is tainted"
fails "String#scan taints the results if the Regexp argument is tainted"
fails "String#scan taints the results when passed a Regexp argument if self is tainted"
fails "String#scan with pattern and block taints the results if the String argument is tainted"
fails "String#scan with pattern and block taints the results when passed a String argument if self is tainted"
fails "String#scan with pattern and block taints the results if the Regexp argument is tainted"
fails "String#scan with pattern and block taints the results when passed a Regexp argument if self is tainted"

fails "String#slice with index, length always taints resulting strings when self is tainted"
fails "String#slice with Range always taints resulting strings when self is tainted"
fails "String#slice with Regexp always taints resulting strings when self or regexp is tainted"
2 changes: 1 addition & 1 deletion spec/rubyspecs
Original file line number Diff line number Diff line change
@@ -154,7 +154,7 @@ corelib/core/string/rindex_spec
corelib/core/string/rjust_spec
corelib/core/string/rpartition_spec
corelib/core/string/rstrip_spec
# corelib/core/string/scan_spec - infinite loop on parsing
corelib/core/string/scan_spec
corelib/core/string/setbyte_spec
corelib/core/string/size_spec
corelib/core/string/slice_spec