ruby-changes:66906
From: Benoit <ko1@a...>
Date: Tue, 27 Jul 2021 17:01:52 +0900 (JST)
Subject: [ruby-changes:66906] 1cf111774f (master): [ruby/uri] Add proper Ractor support to URI
https://git.ruby-lang.org/ruby.git/commit/?id=1cf111774f From 1cf111774f03c6d1ddba735cb8cc79483f16f699 Mon Sep 17 00:00:00 2001 From: Benoit Daloze <eregontp@g...> Date: Fri, 25 Jun 2021 13:38:01 +0200 Subject: [ruby/uri] Add proper Ractor support to URI * Using a module to map scheme name to scheme class, which also works with Ractor. * No constant redefinition, no ObjectSpace, still fast lookup for initial schemes. https://github.com/ruby/uri/commit/883567fd81 --- lib/uri.rb | 8 +++++++- lib/uri/common.rb | 26 ++++++++++++++++++++------ lib/uri/file.rb | 2 +- lib/uri/ftp.rb | 3 ++- lib/uri/http.rb | 3 +-- lib/uri/https.rb | 3 ++- lib/uri/ldap.rb | 2 +- lib/uri/ldaps.rb | 3 ++- lib/uri/mailto.rb | 2 +- lib/uri/ws.rb | 3 +-- lib/uri/wss.rb | 3 ++- test/uri/test_common.rb | 20 ++++++++++++++++++++ 12 files changed, 60 insertions(+), 18 deletions(-) diff --git a/lib/uri.rb b/lib/uri.rb index 5e820f4..282e82c 100644 --- a/lib/uri.rb +++ b/lib/uri.rb @@ -30,7 +30,7 @@ https://github.com/ruby/ruby/blob/trunk/lib/uri.rb#L30 # class RSYNC < Generic # DEFAULT_PORT = 873 # end -# @@schemes['RSYNC'] = RSYNC +# register_scheme 'RSYNC', RSYNC # end # #=> URI::RSYNC # @@ -100,3 +100,9 @@ require_relative 'uri/https' https://github.com/ruby/ruby/blob/trunk/lib/uri.rb#L100 require_relative 'uri/ldap' require_relative 'uri/ldaps' require_relative 'uri/mailto' + +module URI + INITIAL_SCHEMES = scheme_list + private_constant :INITIAL_SCHEMES + Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor) +end diff --git a/lib/uri/common.rb b/lib/uri/common.rb index 915c0e9..2df0536 100644 --- a/lib/uri/common.rb +++ b/lib/uri/common.rb @@ -16,6 +16,7 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/common.rb#L16 REGEXP = RFC2396_REGEXP Parser = RFC2396_Parser RFC3986_PARSER = RFC3986_Parser.new + Ractor.make_shareable(RFC3986_PARSER) if defined?(Ractor) # URI::Parser.new DEFAULT_PARSER = Parser.new @@ -27,6 +28,7 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/common.rb#L28 DEFAULT_PARSER.regexp.each_pair do |sym, str| const_set(sym, str) end + Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor) module Util # :nodoc: def make_components_hash(klass, array_hash) @@ -62,10 +64,19 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/common.rb#L64 include REGEXP - @@schemes = {} + module Schemes + end + private_constant :Schemes + + def self.register_scheme(scheme, klass) + Schemes.const_set(scheme, klass) + end + # Returns a Hash of the defined schemes. def self.scheme_list - @@schemes + Schemes.constants.map { |name| + [name.to_s.upcase, Schemes.const_get(name)] + }.to_h end # @@ -73,11 +84,13 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/common.rb#L84 # from +URI.scheme_list+. # def self.for(scheme, *arguments, default: Generic) - if scheme - uri_class = @@schemes[scheme.upcase] || default - else - uri_class = default + const_name = scheme.to_s.upcase + + uri_class = INITIAL_SCHEMES[const_name] + if !uri_class && !const_name.empty? && Schemes.const_defined?(const_name, false) + uri_class = Schemes.const_get(const_name, false) end + uri_class ||= default return uri_class.new(scheme, *arguments) end @@ -653,6 +666,7 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/common.rb#L666 "utf-16"=>"utf-16le", "utf-16le"=>"utf-16le", } # :nodoc: + Ractor.make_shareable(WEB_ENCODINGS_) if defined?(Ractor) # :nodoc: # return encoding or nil diff --git a/lib/uri/file.rb b/lib/uri/file.rb index 561ec70..7671ad6 100644 --- a/lib/uri/file.rb +++ b/lib/uri/file.rb @@ -90,5 +90,5 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/file.rb#L90 end end - @@schemes['FILE'] = File + register_scheme 'FILE', File end diff --git a/lib/uri/ftp.rb b/lib/uri/ftp.rb index fb38481..abad613 100644 --- a/lib/uri/ftp.rb +++ b/lib/uri/ftp.rb @@ -262,5 +262,6 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/ftp.rb#L262 return str end end - @@schemes['FTP'] = FTP + + register_scheme 'FTP', FTP end diff --git a/lib/uri/http.rb b/lib/uri/http.rb index 70cfb2a..6e9c963 100644 --- a/lib/uri/http.rb +++ b/lib/uri/http.rb @@ -82,6 +82,5 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/http.rb#L82 end end - @@schemes['HTTP'] = HTTP - + register_scheme 'HTTP', HTTP end diff --git a/lib/uri/https.rb b/lib/uri/https.rb index c481b1f..50a5cab 100644 --- a/lib/uri/https.rb +++ b/lib/uri/https.rb @@ -18,5 +18,6 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/https.rb#L18 # A Default port of 443 for URI::HTTPS DEFAULT_PORT = 443 end - @@schemes['HTTPS'] = HTTPS + + register_scheme 'HTTPS', HTTPS end diff --git a/lib/uri/ldap.rb b/lib/uri/ldap.rb index 14e6163..4544349 100644 --- a/lib/uri/ldap.rb +++ b/lib/uri/ldap.rb @@ -257,5 +257,5 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/ldap.rb#L257 end end - @@schemes['LDAP'] = LDAP + register_scheme 'LDAP', LDAP end diff --git a/lib/uri/ldaps.rb b/lib/uri/ldaps.rb index 227e7fa..58228f5 100644 --- a/lib/uri/ldaps.rb +++ b/lib/uri/ldaps.rb @@ -17,5 +17,6 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/ldaps.rb#L17 # A Default port of 636 for URI::LDAPS DEFAULT_PORT = 636 end - @@schemes['LDAPS'] = LDAPS + + register_scheme 'LDAPS', LDAPS end diff --git a/lib/uri/mailto.rb b/lib/uri/mailto.rb index d08c2ae..87cb996 100644 --- a/lib/uri/mailto.rb +++ b/lib/uri/mailto.rb @@ -289,5 +289,5 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/mailto.rb#L289 alias to_rfc822text to_mailtext end - @@schemes['MAILTO'] = MailTo + register_scheme 'MAILTO', MailTo end diff --git a/lib/uri/ws.rb b/lib/uri/ws.rb index 2bfee59..ff3c554 100644 --- a/lib/uri/ws.rb +++ b/lib/uri/ws.rb @@ -79,6 +79,5 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/ws.rb#L79 end end - @@schemes['WS'] = WS - + register_scheme 'WS', WS end diff --git a/lib/uri/wss.rb b/lib/uri/wss.rb index 1cfa133..7cea9d7 100644 --- a/lib/uri/wss.rb +++ b/lib/uri/wss.rb @@ -18,5 +18,6 @@ module URI https://github.com/ruby/ruby/blob/trunk/lib/uri/wss.rb#L18 # A Default port of 443 for URI::WSS DEFAULT_PORT = 443 end - @@schemes['WSS'] = WSS + + register_scheme 'WSS', WSS end diff --git a/test/uri/test_common.rb b/test/uri/test_common.rb index 1afa35f..3d28175 100644 --- a/test/uri/test_common.rb +++ b/test/uri/test_common.rb @@ -33,6 +33,26 @@ class TestCommon < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/uri/test_common.rb#L33 end end + def test_ractor + return unless defined?(Ractor) + r = Ractor.new { URI.parse("https://ruby-lang.org/").inspect } + assert_equal(URI.parse("https://ruby-lang.org/").inspect, r.take) + end + + def test_register_scheme + assert_equal(["FILE", "FTP", "HTTP", "HTTPS", "LDAP", "LDAPS", "MAILTO", "WS"].sort, URI.scheme_list.keys.sort) + + foobar = Class.new(URI::Generic) + URI.register_scheme 'FOOBAR', foobar + begin + assert_equal(["FILE", "FTP", "HTTP", "HTTPS", "LDAP", "LDAPS", "MAILTO", "WS", "FOOBAR"].sort, URI.scheme_list.keys.sort) + ensure + URI.const_get(:Schemes).send(:remove_const, :FOOBAR) + end + + assert_equal(["FILE", "FTP", "HTTP", "HTTPS", "LDAP", "LDAPS", "MAILTO", "WS"].sort, URI.scheme_list.keys.sort) + end + def test_regexp EnvUtil.suppress_warning do assert_instance_of Regexp, URI.regexp -- cgit v1.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/