Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ They are still available on rubygems.org and can be installed with
### The following default gems are updated.

* RubyGems 4.1.0.dev
* 4.0.3 to [v4.0.4][RubyGems-v4.0.4], [v4.0.5][RubyGems-v4.0.5], [v4.0.6][RubyGems-v4.0.6], [v4.0.7][RubyGems-v4.0.7], [v4.0.8][RubyGems-v4.0.8], [v4.0.9][RubyGems-v4.0.9], [v4.0.10][RubyGems-v4.0.10], [v4.0.11][RubyGems-v4.0.11], [v4.0.12][RubyGems-v4.0.12], [v4.0.13][RubyGems-v4.0.13], [v4.0.14][RubyGems-v4.0.14], [v4.0.15][RubyGems-v4.0.15], [v4.0.16][RubyGems-v4.0.16], [v4.0.17][RubyGems-v4.0.17], [v4.0.18][RubyGems-v4.0.18], [v4.0.19][RubyGems-v4.0.19]
* 4.0.3 to [v4.0.4][RubyGems-v4.0.4], [v4.0.5][RubyGems-v4.0.5], [v4.0.6][RubyGems-v4.0.6], [v4.0.7][RubyGems-v4.0.7], [v4.0.8][RubyGems-v4.0.8], [v4.0.9][RubyGems-v4.0.9], [v4.0.10][RubyGems-v4.0.10], [v4.0.11][RubyGems-v4.0.11], [v4.0.12][RubyGems-v4.0.12], [v4.0.13][RubyGems-v4.0.13], [v4.0.14][RubyGems-v4.0.14], [v4.0.15][RubyGems-v4.0.15], [v4.0.16][RubyGems-v4.0.16], [v4.0.17][RubyGems-v4.0.17], [v4.0.18][RubyGems-v4.0.18], [v4.0.19][RubyGems-v4.0.19], [v4.0.20][RubyGems-v4.0.20]
* bundler 4.1.0.dev
* 4.0.3 to [v4.0.4][bundler-v4.0.4], [v4.0.5][bundler-v4.0.5], [v4.0.6][bundler-v4.0.6], [v4.0.7][bundler-v4.0.7], [v4.0.8][bundler-v4.0.8], [v4.0.9][bundler-v4.0.9], [v4.0.10][bundler-v4.0.10], [v4.0.11][bundler-v4.0.11], [v4.0.12][bundler-v4.0.12], [v4.0.13][bundler-v4.0.13], [v4.0.14][bundler-v4.0.14], [v4.0.15][bundler-v4.0.15], [v4.0.16][bundler-v4.0.16], [v4.0.17][bundler-v4.0.17]
* erb 6.0.7
Expand Down Expand Up @@ -394,6 +394,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable.
[RubyGems-v4.0.17]: https://github.com/rubygems/rubygems/releases/tag/v4.0.17
[RubyGems-v4.0.18]: https://github.com/rubygems/rubygems/releases/tag/v4.0.18
[RubyGems-v4.0.19]: https://github.com/rubygems/rubygems/releases/tag/v4.0.19
[RubyGems-v4.0.20]: https://github.com/rubygems/rubygems/releases/tag/v4.0.20
[bundler-v4.0.4]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.4
[bundler-v4.0.5]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.5
[bundler-v4.0.6]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.6
Expand Down
21 changes: 21 additions & 0 deletions benchmark/string_tr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
prelude: |
# frozen_string_literal: true

require 'cgi/escape'

STR = ((("a" * 31) + "<") * 1000).freeze

ESCAPED_CHARS = {
">" => '\u003e',
"<" => '\u003c',
"&" => '\u0026',
}.freeze
ESCAPE_PATTERN = Regexp.union(ESCAPED_CHARS.keys)

benchmark:
tr_escape: |
STR.tr(ESCAPED_CHARS)
gsub_escape: |
STR.gsub(ESCAPE_PATTERN, ESCAPED_CHARS)
cgi_escape: |
CGI.escape_html(STR)
41 changes: 41 additions & 0 deletions encoding.c
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,47 @@ enc_compatible_latter(VALUE str1, VALUE str2, int idx1, int idx2)
return 0;
}

rb_encoding *
rb_enc_check_multi_str(rb_encoding *enc1, int *cr, VALUE str2)
{
RUBY_ASSERT(*cr != ENC_CODERANGE_UNKNOWN);

if (RSTRING_LEN(str2) == 0) {
return enc1;
}

int idx2 = enc_get_index_str(str2);
rb_encoding *enc2 = rb_enc_from_index(idx2);

int cr1 = *cr;

if (enc1 == enc2) {
if (cr1 == ENC_CODERANGE_7BIT) {
*cr = rb_enc_str_coderange(str2);
}
return enc1;
}

if (!rb_enc_asciicompat(enc1) || !rb_enc_asciicompat(enc2)) {
rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
rb_enc_inspect_name(enc1),
rb_enc_inspect_name(enc2));
}

if (enc2 == global_enc_us_ascii || rb_enc_str_asciionly_p(str2)) {
return enc1;
}

if (enc1 == global_enc_us_ascii || cr1 == ENC_CODERANGE_7BIT) {
*cr = rb_enc_str_coderange(str2);
return enc2;
}

rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
rb_enc_inspect_name(enc1),
rb_enc_inspect_name(enc2));
}

static rb_encoding*
enc_compatible_str(VALUE str1, VALUE str2)
{
Expand Down
26 changes: 15 additions & 11 deletions ext/json/generator/generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -1124,15 +1124,6 @@ static void generate_json_fallback(FBuffer *buffer, struct generate_json_data *d
}
}

static inline void generate_json_symbol(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
if (data->state->strict) {
generate_json_string(buffer, data, rb_sym2str(obj));
} else {
generate_json_fallback(buffer, data, obj);
}
}

static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
fbuffer_append(buffer, "null", 4);
Expand Down Expand Up @@ -1218,7 +1209,13 @@ static inline void generate_json_general(FBuffer *buffer, struct generate_json_d
} else if (RB_FLONUM_P(obj)) {
generate_json_float(buffer, data, obj);
} else if (RB_STATIC_SYM_P(obj)) {
generate_json_symbol(buffer, data, obj);
if (data->state->strict) {
obj = rb_sym2str(obj);
JSON_ASSERT(RBASIC_CLASS(obj) == rb_cString);
goto generate_string;
}

generate_json_fallback(buffer, data, obj);
} else {
goto general;
}
Expand All @@ -1239,6 +1236,7 @@ static inline void generate_json_general(FBuffer *buffer, struct generate_json_d
case T_STRING:
if (fallback && klass != rb_cString) goto general;

generate_string:
if (RB_LIKELY(valid_json_string_p(obj))) {
raw_generate_json_string(buffer, data, obj);
} else if (as_json_called) {
Expand All @@ -1250,7 +1248,13 @@ static inline void generate_json_general(FBuffer *buffer, struct generate_json_d
}
break;
case T_SYMBOL:
generate_json_symbol(buffer, data, obj);
if (data->state->strict) {
obj = rb_sym2str(obj);
JSON_ASSERT(RBASIC_CLASS(obj) == rb_cString);
goto generate_string;
}

generate_json_fallback(buffer, data, obj);
break;
case T_FLOAT:
if (fallback && klass != rb_cFloat) goto general;
Expand Down
1 change: 1 addition & 0 deletions internal/encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ void rb_enc_set_base(const char *name, const char *orig);
int rb_enc_set_dummy(int index);
void rb_enc_raw_set(VALUE obj, rb_encoding *enc);
int rb_enc_registered(const char *name);
rb_encoding *rb_enc_check_multi_str(rb_encoding *enc1, int *cr, VALUE str2);

PUREFUNC(int rb_data_is_encoding(VALUE obj));

Expand Down
2 changes: 1 addition & 1 deletion lib/bundler/bundler.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Gem::Specification.new do |s|

# These live next to the gemspec when Bundler ships as a gem, but not when
# it is synced into Ruby core, where the gemspec moves under lib/bundler.
s.files += %w[CHANGELOG-bundler.md LICENSE-bundler.md README-bundler.md].select {|f| File.file?(f) }
s.files += %w[CHANGELOG-bundler.md MIT.txt].select {|f| File.file?(f) }
s.bindir = "exe"
s.executables = %w[bundle bundler]
s.require_paths = ["lib"]
Expand Down
4 changes: 2 additions & 2 deletions lib/rubygems/util/atomic_file_writer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ def self.open(file_name)
if old_stat
# Set correct permissions on new file
begin
File.chown(old_stat.uid, old_stat.gid, tmp_path)
temp_file.chown(old_stat.uid, old_stat.gid)
# This operation will affect filesystem ACL's
File.chmod(old_stat.mode, tmp_path)
temp_file.chmod(old_stat.mode)
rescue Errno::EPERM, Errno::EACCES
# Changing file ownership failed, moving on.
end
Expand Down
2 changes: 1 addition & 1 deletion spec/bundler/support/path.rb
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ def git_ls_files(glob)
end

def tracked_files_glob
ruby_core? ? "libexec/bundle* lib/bundler lib/bundler.rb lib/rubygems/vendor/uri lib/rubygems/vendor/securerandom lib/rubygems/vendor/pub_grub lib/rubygems/yaml_serializer.rb lib/rubygems/compact_index_client* lib/rubygems/credential_store* spec/bundler man/bundle*" : "exe/bundle exe/bundler lib/bundler lib/bundler.rb lib/rubygems/vendor/uri lib/rubygems/vendor/securerandom lib/rubygems/vendor/pub_grub lib/rubygems/yaml_serializer.rb lib/rubygems/compact_index_client* lib/rubygems/credential_store* bundler.gemspec CHANGELOG-bundler.md LICENSE-bundler.md README-bundler.md"
ruby_core? ? "libexec/bundle* lib/bundler lib/bundler.rb lib/rubygems/vendor/uri lib/rubygems/vendor/securerandom lib/rubygems/vendor/pub_grub lib/rubygems/yaml_serializer.rb lib/rubygems/compact_index_client* lib/rubygems/credential_store* spec/bundler man/bundle*" : "exe/bundle exe/bundler lib/bundler lib/bundler.rb lib/rubygems/vendor/uri lib/rubygems/vendor/securerandom lib/rubygems/vendor/pub_grub lib/rubygems/yaml_serializer.rb lib/rubygems/compact_index_client* lib/rubygems/credential_store* bundler.gemspec CHANGELOG-bundler.md MIT.txt"
end

def lib_tracked_files_glob
Expand Down
88 changes: 88 additions & 0 deletions spec/ruby/core/string/tr_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,50 @@
str.tr(a, b).should == "椎名深夏"
end

it "raises Encoding::CompatibilityError when from_string or to_string parameters have an incompatible encoding" do
-> { "fée".tr("é".encode(Encoding::ISO_8859_1), "e") }.should.raise(Encoding::CompatibilityError)
-> { "fée".tr("e", "é".encode(Encoding::ISO_8859_1)) }.should.raise(Encoding::CompatibilityError)
end

ruby_version_is "4.1" do
describe "hash form" do
it "returns a new strings with characters from keys replaced by the associated strings" do
"hello".tr("e" => "EH! ", "o" => "OH!", "l" => "").should == "hEH! OH!"
"h€llø".tr("€" => "e", "ø" => "o").should == "hello"
end

it "returns a string in the combined encoding" do
str = "hello".encode(Encoding::US_ASCII).tr("e" => "é")
str.should == "héllo"
str.encoding.should == Encoding::UTF_8
end

it "works with multi-byte encodings" do
"hello".encode(Encoding::UTF_16LE).tr(
"e".encode(Encoding::UTF_16LE) => "EH! ".encode(Encoding::UTF_16LE),
"o".encode(Encoding::UTF_16LE) => "OH!".encode(Encoding::UTF_16LE),
"l".encode(Encoding::UTF_16LE) => "".encode(Encoding::UTF_16LE),
).should == "hEH! OH!".encode(Encoding::UTF_16LE)

"h€llø".encode(Encoding::UTF_16LE).tr(
"€".encode(Encoding::UTF_16LE) => "e".encode(Encoding::UTF_16LE),
"ø".encode(Encoding::UTF_16LE) => "o".encode(Encoding::UTF_16LE),
).should == "hello".encode(Encoding::UTF_16LE)
end

it "raises ArgumentError if a key is more than one codepoint" do
-> { "hello".tr("hel" => "") }.should.raise(ArgumentError)
-> { "🤦🏼‍♂️".tr("🤦🏼‍♂️" => "") }.should.raise(ArgumentError)
end

it "raises Encoding::CompatibilityError when either keys or values have an incompatible encoding" do
-> { "fée".tr("é".encode(Encoding::ISO_8859_1) => "e") }.should.raise(Encoding::CompatibilityError)
-> { "fée".tr("e" => "é".encode(Encoding::ISO_8859_1)) }.should.raise(Encoding::CompatibilityError)

-> { "ab".encode(Encoding::US_ASCII).tr("a" => "à".encode(Encoding::ISO_8859_1), "b" => "é") }.should.raise(Encoding::CompatibilityError)
end
end
end
end

describe "String#tr!" do
Expand Down Expand Up @@ -123,4 +167,48 @@
-> { s.tr!("R", "S") }.should.raise(FrozenError)
-> { s.tr!("", "") }.should.raise(FrozenError)
end

ruby_version_is "4.1" do
describe "hash form" do
it "returns a new strings with characters from keys replaced by the associated strings" do
"hello".tr!("e" => "EH! ", "o" => "OH!", "l" => "").should == "hEH! OH!"
"h€llø".tr!("€" => "e", "ø" => "o").should == "hello"
end

it "returns a string in the combined encoding" do
str = "hello".encode(Encoding::US_ASCII).tr!("e" => "é")
str.should == "héllo"
str.encoding.should == Encoding::UTF_8
end

it "works with multi-byte encodings" do
"hello".encode(Encoding::UTF_16LE).tr!(
"e".encode(Encoding::UTF_16LE) => "EH! ".encode(Encoding::UTF_16LE),
"o".encode(Encoding::UTF_16LE) => "OH!".encode(Encoding::UTF_16LE),
"l".encode(Encoding::UTF_16LE) => "".encode(Encoding::UTF_16LE),
).should == "hEH! OH!".encode(Encoding::UTF_16LE)

"h€llø".encode(Encoding::UTF_16LE).tr!(
"€".encode(Encoding::UTF_16LE) => "e".encode(Encoding::UTF_16LE),
"ø".encode(Encoding::UTF_16LE) => "o".encode(Encoding::UTF_16LE),
).should == "hello".encode(Encoding::UTF_16LE)
end

it "returns nil if the string wasn't modified" do
"hello".tr!("€" => "", "Ø" => "").should == nil
end

it "raises ArgumentError if a key is more than one codepoint" do
-> { "hello".tr!("hel" => "") }.should.raise(ArgumentError)
-> { "🤦🏼‍♂️".tr!("🤦🏼‍♂️" => "") }.should.raise(ArgumentError)
end

it "raises Encoding::CompatibilityError when either keys or values have an incompatible encoding" do
-> { "fée".tr!("é".encode(Encoding::ISO_8859_1) => "e") }.should.raise(Encoding::CompatibilityError)
-> { "fée".tr!("e" => "é".encode(Encoding::ISO_8859_1)) }.should.raise(Encoding::CompatibilityError)

-> { "ab".encode(Encoding::US_ASCII).tr!("a" => "à".encode(Encoding::ISO_8859_1), "b" => "é") }.should.raise(Encoding::CompatibilityError)
end
end
end
end
Loading