From 63903120e737b25e49b93b8870f6936b09a4922a Mon Sep 17 00:00:00 2001 From: Allison Reid Date: Fri, 14 Jan 2022 19:53:10 -0800 Subject: [PATCH] Explicitly freeze concatenated-`String` constants to unbreak on non-main `Ractor`s --- lib/addressable/uri.rb | 24 +++++++++++++++--------- spec/addressable/uri_spec.rb | 9 +++++++++ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/lib/addressable/uri.rb b/lib/addressable/uri.rb index e8d6c429..9455f81b 100644 --- a/lib/addressable/uri.rb +++ b/lib/addressable/uri.rb @@ -38,20 +38,26 @@ class InvalidURIError < StandardError ## # Container for the character classes specified in # RFC 3986. + # + # Note: Concatenated and interpolated `String`s are not affected by the + # `frozen_string_literal` directive and must be frozen explicitly. + # + # Interpolated `String`s *were* frozen this way before Ruby 3.0: + # https://bugs.ruby-lang.org/issues/17104 module CharacterClasses ALPHA = "a-zA-Z" DIGIT = "0-9" GEN_DELIMS = "\\:\\/\\?\\#\\[\\]\\@" SUB_DELIMS = "\\!\\$\\&\\'\\(\\)\\*\\+\\,\\;\\=" - RESERVED = GEN_DELIMS + SUB_DELIMS - UNRESERVED = ALPHA + DIGIT + "\\-\\.\\_\\~" - PCHAR = UNRESERVED + SUB_DELIMS + "\\:\\@" - SCHEME = ALPHA + DIGIT + "\\-\\+\\." - HOST = UNRESERVED + SUB_DELIMS + "\\[\\:\\]" - AUTHORITY = PCHAR + "\\[\\:\\]" - PATH = PCHAR + "\\/" - QUERY = PCHAR + "\\/\\?" - FRAGMENT = PCHAR + "\\/\\?" + RESERVED = (GEN_DELIMS + SUB_DELIMS).freeze + UNRESERVED = (ALPHA + DIGIT + "\\-\\.\\_\\~").freeze + PCHAR = (UNRESERVED + SUB_DELIMS + "\\:\\@").freeze + SCHEME = (ALPHA + DIGIT + "\\-\\+\\.").freeze + HOST = (UNRESERVED + SUB_DELIMS + "\\[\\:\\]").freeze + AUTHORITY = (PCHAR + "\\[\\:\\]").freeze + PATH = (PCHAR + "\\/").freeze + QUERY = (PCHAR + "\\/\\?").freeze + FRAGMENT = (PCHAR + "\\/\\?").freeze end module NormalizeCharacterClasses diff --git a/spec/addressable/uri_spec.rb b/spec/addressable/uri_spec.rb index 00baaacf..a491cd9d 100644 --- a/spec/addressable/uri_spec.rb +++ b/spec/addressable/uri_spec.rb @@ -6663,3 +6663,12 @@ def to_str expect(@uri.class).to eq(@uri.join('path').class) end end + +describe Addressable::URI, "when initialized in a non-main `Ractor`" do + it "should have the same value as if used in the main `Ractor`" do + main = Addressable::URI.parse("http://example.com") + expect( + Ractor.new { Addressable::URI.parse("http://example.com") }.take + ).to eq(main) + end +end if defined?(Ractor)