[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]