activesupport 6.0.0.beta2 → 6.0.2.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +287 -3
- data/README.rdoc +2 -1
- data/lib/active_support.rb +1 -0
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +5 -1
- data/lib/active_support/cache.rb +5 -5
- data/lib/active_support/cache/memory_store.rb +2 -0
- data/lib/active_support/cache/redis_cache_store.rb +9 -6
- data/lib/active_support/concern.rb +24 -1
- data/lib/active_support/configurable.rb +3 -3
- data/lib/active_support/core_ext/array/access.rb +18 -6
- data/lib/active_support/core_ext/class/attribute.rb +10 -15
- data/lib/active_support/core_ext/date_and_time/calculations.rb +0 -30
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +24 -4
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +2 -2
- data/lib/active_support/core_ext/hash/except.rb +1 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +5 -5
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +5 -5
- data/lib/active_support/core_ext/module/delegation.rb +6 -0
- data/lib/active_support/core_ext/object/duplicable.rb +7 -117
- data/lib/active_support/core_ext/range/compare_range.rb +27 -12
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +2 -2
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +7 -2
- data/lib/active_support/core_ext/string/output_safety.rb +51 -4
- data/lib/active_support/core_ext/time/calculations.rb +31 -2
- data/lib/active_support/dependencies.rb +41 -5
- data/lib/active_support/dependencies/zeitwerk_integration.rb +44 -21
- data/lib/active_support/deprecation/method_wrappers.rb +7 -18
- data/lib/active_support/deprecation/proxy_wrappers.rb +24 -3
- data/lib/active_support/descendants_tracker.rb +52 -6
- data/lib/active_support/duration.rb +2 -3
- data/lib/active_support/evented_file_update_checker.rb +14 -2
- data/lib/active_support/gem_version.rb +2 -2
- data/lib/active_support/hash_with_indifferent_access.rb +6 -3
- data/lib/active_support/i18n_railtie.rb +6 -1
- data/lib/active_support/inflector/transliterate.rb +43 -14
- data/lib/active_support/logger_thread_safe_level.rb +2 -1
- data/lib/active_support/notifications/fanout.rb +2 -2
- data/lib/active_support/notifications/instrumenter.rb +12 -11
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +1 -1
- data/lib/active_support/parameter_filter.rb +6 -1
- data/lib/active_support/security_utils.rb +1 -1
- data/lib/active_support/subscriber.rb +55 -6
- data/lib/active_support/testing/parallelization.rb +21 -2
- metadata +13 -14
| @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            require "active_support/core_ext/array/extract_options"
         | 
| 4 | 
            +
            require "active_support/core_ext/module/redefine_method"
         | 
| 4 5 |  | 
| 5 6 | 
             
            module ActiveSupport
         | 
| 6 7 | 
             
              class Deprecation
         | 
| @@ -52,29 +53,17 @@ module ActiveSupport | |
| 52 53 | 
             
                    options = method_names.extract_options!
         | 
| 53 54 | 
             
                    deprecator = options.delete(:deprecator) || self
         | 
| 54 55 | 
             
                    method_names += options.keys
         | 
| 55 | 
            -
                    mod =  | 
| 56 | 
            +
                    mod = nil
         | 
| 56 57 |  | 
| 57 58 | 
             
                    method_names.each do |method_name|
         | 
| 58 59 | 
             
                      if target_module.method_defined?(method_name) || target_module.private_method_defined?(method_name)
         | 
| 59 | 
            -
                         | 
| 60 | 
            -
                         | 
| 61 | 
            -
                        without_method = "#{aliased_method}_without_deprecation#{punctuation}"
         | 
| 62 | 
            -
             | 
| 63 | 
            -
                        target_module.define_method(with_method) do |*args, &block|
         | 
| 60 | 
            +
                        method = target_module.instance_method(method_name)
         | 
| 61 | 
            +
                        target_module.redefine_method(method_name) do |*args, &block|
         | 
| 64 62 | 
             
                          deprecator.deprecation_warning(method_name, options[method_name])
         | 
| 65 | 
            -
                           | 
| 66 | 
            -
                        end
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                        target_module.alias_method(without_method, method_name)
         | 
| 69 | 
            -
                        target_module.alias_method(method_name, with_method)
         | 
| 70 | 
            -
             | 
| 71 | 
            -
                        case
         | 
| 72 | 
            -
                        when target_module.protected_method_defined?(without_method)
         | 
| 73 | 
            -
                          target_module.send(:protected, method_name)
         | 
| 74 | 
            -
                        when target_module.private_method_defined?(without_method)
         | 
| 75 | 
            -
                          target_module.send(:private, method_name)
         | 
| 63 | 
            +
                          method.bind(self).call(*args, &block)
         | 
| 76 64 | 
             
                        end
         | 
| 77 65 | 
             
                      else
         | 
| 66 | 
            +
                        mod ||= Module.new
         | 
| 78 67 | 
             
                        mod.define_method(method_name) do |*args, &block|
         | 
| 79 68 | 
             
                          deprecator.deprecation_warning(method_name, options[method_name])
         | 
| 80 69 | 
             
                          super(*args, &block)
         | 
| @@ -82,7 +71,7 @@ module ActiveSupport | |
| 82 71 | 
             
                      end
         | 
| 83 72 | 
             
                    end
         | 
| 84 73 |  | 
| 85 | 
            -
                    target_module.prepend(mod)  | 
| 74 | 
            +
                    target_module.prepend(mod) if mod
         | 
| 86 75 | 
             
                  end
         | 
| 87 76 | 
             
                end
         | 
| 88 77 | 
             
              end
         | 
| @@ -120,7 +120,14 @@ module ActiveSupport | |
| 120 120 | 
             
                #   # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
         | 
| 121 121 | 
             
                #        (Backtrace information…)
         | 
| 122 122 | 
             
                #        ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
         | 
| 123 | 
            -
                class DeprecatedConstantProxy <  | 
| 123 | 
            +
                class DeprecatedConstantProxy < Module
         | 
| 124 | 
            +
                  def self.new(*args, &block)
         | 
| 125 | 
            +
                    object = args.first
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                    return object unless object
         | 
| 128 | 
            +
                    super
         | 
| 129 | 
            +
                  end
         | 
| 130 | 
            +
             | 
| 124 131 | 
             
                  def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.")
         | 
| 125 132 | 
             
                    require "active_support/inflector/methods"
         | 
| 126 133 |  | 
| @@ -130,6 +137,14 @@ module ActiveSupport | |
| 130 137 | 
             
                    @message = message
         | 
| 131 138 | 
             
                  end
         | 
| 132 139 |  | 
| 140 | 
            +
                  instance_methods.each { |m| undef_method m unless /^__|^object_id$/.match?(m) }
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  # Don't give a deprecation warning on inspect since test/unit and error
         | 
| 143 | 
            +
                  # logs rely on it for diagnostics.
         | 
| 144 | 
            +
                  def inspect
         | 
| 145 | 
            +
                    target.inspect
         | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
             | 
| 133 148 | 
             
                  # Returns the class of the new constant.
         | 
| 134 149 | 
             
                  #
         | 
| 135 150 | 
             
                  #   PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
         | 
| @@ -144,8 +159,14 @@ module ActiveSupport | |
| 144 159 | 
             
                      ActiveSupport::Inflector.constantize(@new_const.to_s)
         | 
| 145 160 | 
             
                    end
         | 
| 146 161 |  | 
| 147 | 
            -
                    def  | 
| 148 | 
            -
                      @deprecator.warn(@message,  | 
| 162 | 
            +
                    def const_missing(name)
         | 
| 163 | 
            +
                      @deprecator.warn(@message, caller_locations)
         | 
| 164 | 
            +
                      target.const_get(name)
         | 
| 165 | 
            +
                    end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                    def method_missing(called, *args, &block)
         | 
| 168 | 
            +
                      @deprecator.warn(@message, caller_locations)
         | 
| 169 | 
            +
                      target.__send__(called, *args, &block)
         | 
| 149 170 | 
             
                    end
         | 
| 150 171 | 
             
                end
         | 
| 151 172 | 
             
              end
         | 
| @@ -1,5 +1,7 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            +
            require "weakref"
         | 
| 4 | 
            +
             | 
| 3 5 | 
             
            module ActiveSupport
         | 
| 4 6 | 
             
              # This module provides an internal implementation to track descendants
         | 
| 5 7 | 
             
              # which is faster than iterating through ObjectSpace.
         | 
| @@ -8,7 +10,8 @@ module ActiveSupport | |
| 8 10 |  | 
| 9 11 | 
             
                class << self
         | 
| 10 12 | 
             
                  def direct_descendants(klass)
         | 
| 11 | 
            -
                    @@direct_descendants[klass] | 
| 13 | 
            +
                    descendants = @@direct_descendants[klass]
         | 
| 14 | 
            +
                    descendants ? descendants.to_a : []
         | 
| 12 15 | 
             
                  end
         | 
| 13 16 |  | 
| 14 17 | 
             
                  def descendants(klass)
         | 
| @@ -20,10 +23,10 @@ module ActiveSupport | |
| 20 23 | 
             
                  def clear
         | 
| 21 24 | 
             
                    if defined? ActiveSupport::Dependencies
         | 
| 22 25 | 
             
                      @@direct_descendants.each do |klass, descendants|
         | 
| 23 | 
            -
                        if  | 
| 26 | 
            +
                        if Dependencies.autoloaded?(klass)
         | 
| 24 27 | 
             
                          @@direct_descendants.delete(klass)
         | 
| 25 28 | 
             
                        else
         | 
| 26 | 
            -
                          descendants.reject! { |v|  | 
| 29 | 
            +
                          descendants.reject! { |v| Dependencies.autoloaded?(v) }
         | 
| 27 30 | 
             
                        end
         | 
| 28 31 | 
             
                      end
         | 
| 29 32 | 
             
                    else
         | 
| @@ -34,15 +37,17 @@ module ActiveSupport | |
| 34 37 | 
             
                  # This is the only method that is not thread safe, but is only ever called
         | 
| 35 38 | 
             
                  # during the eager loading phase.
         | 
| 36 39 | 
             
                  def store_inherited(klass, descendant)
         | 
| 37 | 
            -
                    (@@direct_descendants[klass] ||=  | 
| 40 | 
            +
                    (@@direct_descendants[klass] ||= DescendantsArray.new) << descendant
         | 
| 38 41 | 
             
                  end
         | 
| 39 42 |  | 
| 40 43 | 
             
                  private
         | 
| 41 44 |  | 
| 42 45 | 
             
                    def accumulate_descendants(klass, acc)
         | 
| 43 46 | 
             
                      if direct_descendants = @@direct_descendants[klass]
         | 
| 44 | 
            -
                         | 
| 45 | 
            -
             | 
| 47 | 
            +
                        direct_descendants.each do |direct_descendant|
         | 
| 48 | 
            +
                          acc << direct_descendant
         | 
| 49 | 
            +
                          accumulate_descendants(direct_descendant, acc)
         | 
| 50 | 
            +
                        end
         | 
| 46 51 | 
             
                      end
         | 
| 47 52 | 
             
                    end
         | 
| 48 53 | 
             
                end
         | 
| @@ -59,5 +64,46 @@ module ActiveSupport | |
| 59 64 | 
             
                def descendants
         | 
| 60 65 | 
             
                  DescendantsTracker.descendants(self)
         | 
| 61 66 | 
             
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                # DescendantsArray is an array that contains weak references to classes.
         | 
| 69 | 
            +
                class DescendantsArray # :nodoc:
         | 
| 70 | 
            +
                  include Enumerable
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  def initialize
         | 
| 73 | 
            +
                    @refs = []
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  def initialize_copy(orig)
         | 
| 77 | 
            +
                    @refs = @refs.dup
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  def <<(klass)
         | 
| 81 | 
            +
                    cleanup!
         | 
| 82 | 
            +
                    @refs << WeakRef.new(klass)
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  def each
         | 
| 86 | 
            +
                    @refs.each do |ref|
         | 
| 87 | 
            +
                      yield ref.__getobj__
         | 
| 88 | 
            +
                    rescue WeakRef::RefError
         | 
| 89 | 
            +
                    end
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                  def refs_size
         | 
| 93 | 
            +
                    @refs.size
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                  def cleanup!
         | 
| 97 | 
            +
                    @refs.delete_if { |ref| !ref.weakref_alive? }
         | 
| 98 | 
            +
                  end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                  def reject!
         | 
| 101 | 
            +
                    @refs.reject! do |ref|
         | 
| 102 | 
            +
                      yield ref.__getobj__
         | 
| 103 | 
            +
                    rescue WeakRef::RefError
         | 
| 104 | 
            +
                      true
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
                end
         | 
| 62 108 | 
             
              end
         | 
| 63 109 | 
             
            end
         | 
| @@ -4,7 +4,6 @@ require "active_support/core_ext/array/conversions" | |
| 4 4 | 
             
            require "active_support/core_ext/module/delegation"
         | 
| 5 5 | 
             
            require "active_support/core_ext/object/acts_like"
         | 
| 6 6 | 
             
            require "active_support/core_ext/string/filters"
         | 
| 7 | 
            -
            require "active_support/deprecation"
         | 
| 8 7 |  | 
| 9 8 | 
             
            module ActiveSupport
         | 
| 10 9 | 
             
              # Provides accurate date and time measurements using Date#advance and
         | 
| @@ -339,8 +338,8 @@ module ActiveSupport | |
| 339 338 | 
             
                #   1.year.to_i     # => 31556952
         | 
| 340 339 | 
             
                #
         | 
| 341 340 | 
             
                # In such cases, Ruby's core
         | 
| 342 | 
            -
                # Date[ | 
| 343 | 
            -
                # Time[ | 
| 341 | 
            +
                # Date[https://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
         | 
| 342 | 
            +
                # Time[https://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision
         | 
| 344 343 | 
             
                # date and time arithmetic.
         | 
| 345 344 | 
             
                def to_i
         | 
| 346 345 | 
             
                  @value.to_i
         | 
| @@ -107,13 +107,23 @@ module ActiveSupport | |
| 107 107 |  | 
| 108 108 | 
             
                private
         | 
| 109 109 | 
             
                  def boot!
         | 
| 110 | 
            -
                     | 
| 110 | 
            +
                    normalize_dirs!
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                    unless @dtw.empty?
         | 
| 113 | 
            +
                      Listen.to(*@dtw, &method(:changed)).start
         | 
| 114 | 
            +
                    end
         | 
| 111 115 | 
             
                  end
         | 
| 112 116 |  | 
| 113 117 | 
             
                  def shutdown!
         | 
| 114 118 | 
             
                    Listen.stop
         | 
| 115 119 | 
             
                  end
         | 
| 116 120 |  | 
| 121 | 
            +
                  def normalize_dirs!
         | 
| 122 | 
            +
                    @dirs.transform_keys! do |dir|
         | 
| 123 | 
            +
                      dir.exist? ? dir.realpath : dir
         | 
| 124 | 
            +
                    end
         | 
| 125 | 
            +
                  end
         | 
| 126 | 
            +
             | 
| 117 127 | 
             
                  def changed(modified, added, removed)
         | 
| 118 128 | 
             
                    unless updated?
         | 
| 119 129 | 
             
                      @updated.make_true if (modified + added + removed).any? { |f| watching?(f) }
         | 
| @@ -131,7 +141,9 @@ module ActiveSupport | |
| 131 141 | 
             
                      ext = @ph.normalize_extension(file.extname)
         | 
| 132 142 |  | 
| 133 143 | 
             
                      file.dirname.ascend do |dir|
         | 
| 134 | 
            -
                         | 
| 144 | 
            +
                        matching = @dirs[dir]
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                        if matching && (matching.empty? || matching.include?(ext))
         | 
| 135 147 | 
             
                          break true
         | 
| 136 148 | 
             
                        elsif dir == @lcsp || dir.root?
         | 
| 137 149 | 
             
                          break false
         | 
| @@ -225,8 +225,8 @@ module ActiveSupport | |
| 225 225 | 
             
                #   hash[:a] = 'x'
         | 
| 226 226 | 
             
                #   hash[:b] = 'y'
         | 
| 227 227 | 
             
                #   hash.values_at('a', 'b') # => ["x", "y"]
         | 
| 228 | 
            -
                def values_at(* | 
| 229 | 
            -
                   | 
| 228 | 
            +
                def values_at(*keys)
         | 
| 229 | 
            +
                  super(*keys.map { |key| convert_key(key) })
         | 
| 230 230 | 
             
                end
         | 
| 231 231 |  | 
| 232 232 | 
             
                # Returns an array of the values at the specified indices, but also
         | 
| @@ -239,7 +239,7 @@ module ActiveSupport | |
| 239 239 | 
             
                #   hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
         | 
| 240 240 | 
             
                #   hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
         | 
| 241 241 | 
             
                def fetch_values(*indices, &block)
         | 
| 242 | 
            -
                  indices. | 
| 242 | 
            +
                  super(*indices.map { |key| convert_key(key) }, &block)
         | 
| 243 243 | 
             
                end
         | 
| 244 244 |  | 
| 245 245 | 
             
                # Returns a shallow copy of the hash.
         | 
| @@ -293,6 +293,9 @@ module ActiveSupport | |
| 293 293 | 
             
                  super(convert_key(key))
         | 
| 294 294 | 
             
                end
         | 
| 295 295 |  | 
| 296 | 
            +
                def except(*keys)
         | 
| 297 | 
            +
                  slice(*self.keys - keys.map { |key| convert_key(key) })
         | 
| 298 | 
            +
                end
         | 
| 296 299 | 
             
                alias_method :without, :except
         | 
| 297 300 |  | 
| 298 301 | 
             
                def stringify_keys!; self end
         | 
| @@ -12,6 +12,10 @@ module I18n | |
| 12 12 | 
             
                config.i18n.load_path = []
         | 
| 13 13 | 
             
                config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
         | 
| 14 14 |  | 
| 15 | 
            +
                if I18n.respond_to?(:eager_load!)
         | 
| 16 | 
            +
                  config.eager_load_namespaces << I18n
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 15 19 | 
             
                # Set the i18n configuration after initialization since a lot of
         | 
| 16 20 | 
             
                # configuration is still usually done in application initializers.
         | 
| 17 21 | 
             
                config.after_initialize do |app|
         | 
| @@ -97,7 +101,8 @@ module I18n | |
| 97 101 | 
             
                      If you desire the default locale to be included in the defaults, please
         | 
| 98 102 | 
             
                      explicitly configure it with `config.i18n.fallbacks.defaults =
         | 
| 99 103 | 
             
                      [I18n.default_locale]` or `config.i18n.fallbacks = [I18n.default_locale,
         | 
| 100 | 
            -
                      {...}] | 
| 104 | 
            +
                      {...}]`. If you want to opt-in to the new behavior, use
         | 
| 105 | 
            +
                      `config.i18n.fallbacks.defaults = [nil, {...}]`.
         | 
| 101 106 | 
             
                    MSG
         | 
| 102 107 | 
             
                    args.unshift I18n.default_locale
         | 
| 103 108 | 
             
                  end
         | 
| @@ -51,20 +51,45 @@ module ActiveSupport | |
| 51 51 | 
             
                #
         | 
| 52 52 | 
             
                # Now you can have different transliterations for each locale:
         | 
| 53 53 | 
             
                #
         | 
| 54 | 
            -
                #    | 
| 55 | 
            -
                #   transliterate('Jürgen')
         | 
| 54 | 
            +
                #   transliterate('Jürgen', locale: :en)
         | 
| 56 55 | 
             
                #   # => "Jurgen"
         | 
| 57 56 | 
             
                #
         | 
| 58 | 
            -
                #    | 
| 59 | 
            -
                #   transliterate('Jürgen')
         | 
| 57 | 
            +
                #   transliterate('Jürgen', locale: :de)
         | 
| 60 58 | 
             
                #   # => "Juergen"
         | 
| 61 | 
            -
                 | 
| 59 | 
            +
                #
         | 
| 60 | 
            +
                # Transliteration is restricted to UTF-8, US-ASCII and GB18030 strings
         | 
| 61 | 
            +
                # Other encodings will raise an ArgumentError.
         | 
| 62 | 
            +
                def transliterate(string, replacement = "?", locale: nil)
         | 
| 63 | 
            +
                  string = string.dup if string.frozen?
         | 
| 62 64 | 
             
                  raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String)
         | 
| 63 65 |  | 
| 64 | 
            -
                   | 
| 66 | 
            +
                  allowed_encodings = [Encoding::UTF_8, Encoding::US_ASCII, Encoding::GB18030]
         | 
| 67 | 
            +
                  raise ArgumentError, "Can not transliterate strings with #{string.encoding} encoding" unless allowed_encodings.include?(string.encoding)
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  input_encoding = string.encoding
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  # US-ASCII is a subset of UTF-8 so we'll force encoding as UTF-8 if
         | 
| 72 | 
            +
                  # US-ASCII is given. This way we can let tidy_bytes handle the string
         | 
| 73 | 
            +
                  # in the same way as we do for UTF-8
         | 
| 74 | 
            +
                  string.force_encoding(Encoding::UTF_8) if string.encoding == Encoding::US_ASCII
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  # GB18030 is Unicode compatible but is not a direct mapping so needs to be
         | 
| 77 | 
            +
                  # transcoded. Using invalid/undef :replace will result in loss of data in
         | 
| 78 | 
            +
                  # the event of invalid characters, but since tidy_bytes will replace
         | 
| 79 | 
            +
                  # invalid/undef with a "?" we're safe to do the same beforehand
         | 
| 80 | 
            +
                  string.encode!(Encoding::UTF_8, invalid: :replace, undef: :replace) if string.encoding == Encoding::GB18030
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                  transliterated = I18n.transliterate(
         | 
| 65 83 | 
             
                    ActiveSupport::Multibyte::Unicode.tidy_bytes(string).unicode_normalize(:nfc),
         | 
| 66 | 
            -
                    replacement: replacement
         | 
| 84 | 
            +
                    replacement: replacement,
         | 
| 85 | 
            +
                    locale: locale
         | 
| 67 86 | 
             
                  )
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                  # Restore the string encoding of the input if it was not UTF-8.
         | 
| 89 | 
            +
                  # Apply invalid/undef :replace as tidy_bytes does
         | 
| 90 | 
            +
                  transliterated.encode!(input_encoding, invalid: :replace, undef: :replace) if input_encoding != transliterated.encoding
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                  transliterated
         | 
| 68 93 | 
             
                end
         | 
| 69 94 |  | 
| 70 95 | 
             
                # Replaces special characters in a string so that it may be used as part of
         | 
| @@ -75,8 +100,8 @@ module ActiveSupport | |
| 75 100 | 
             
                #
         | 
| 76 101 | 
             
                # To use a custom separator, override the +separator+ argument.
         | 
| 77 102 | 
             
                #
         | 
| 78 | 
            -
                # | 
| 79 | 
            -
                # | 
| 103 | 
            +
                #   parameterize("Donald E. Knuth", separator: '_') # => "donald_e_knuth"
         | 
| 104 | 
            +
                #   parameterize("^très|Jolie__ ", separator: '_')  # => "tres_jolie"
         | 
| 80 105 | 
             
                #
         | 
| 81 106 | 
             
                # To preserve the case of the characters in a string, use the +preserve_case+ argument.
         | 
| 82 107 | 
             
                #
         | 
| @@ -85,13 +110,17 @@ module ActiveSupport | |
| 85 110 | 
             
                #
         | 
| 86 111 | 
             
                # It preserves dashes and underscores unless they are used as separators:
         | 
| 87 112 | 
             
                #
         | 
| 88 | 
            -
                # | 
| 89 | 
            -
                # | 
| 90 | 
            -
                # | 
| 113 | 
            +
                #   parameterize("^très|Jolie__ ")                 # => "tres-jolie__"
         | 
| 114 | 
            +
                #   parameterize("^très|Jolie-- ", separator: "_") # => "tres_jolie--"
         | 
| 115 | 
            +
                #   parameterize("^très_Jolie-- ", separator: ".") # => "tres_jolie--"
         | 
| 91 116 | 
             
                #
         | 
| 92 | 
            -
                 | 
| 117 | 
            +
                # If the optional parameter +locale+ is specified,
         | 
| 118 | 
            +
                # the word will be parameterized as a word of that language.
         | 
| 119 | 
            +
                # By default, this parameter is set to <tt>nil</tt> and it will use
         | 
| 120 | 
            +
                # the configured <tt>I18n.locale<tt>.
         | 
| 121 | 
            +
                def parameterize(string, separator: "-", preserve_case: false, locale: nil)
         | 
| 93 122 | 
             
                  # Replace accented chars with their ASCII equivalents.
         | 
| 94 | 
            -
                  parameterized_string = transliterate(string)
         | 
| 123 | 
            +
                  parameterized_string = transliterate(string, locale: locale)
         | 
| 95 124 |  | 
| 96 125 | 
             
                  # Turn unwanted chars into the separator.
         | 
| 97 126 | 
             
                  parameterized_string.gsub!(/[^a-z0-9\-_]+/i, separator)
         | 
| @@ -3,6 +3,7 @@ | |
| 3 3 | 
             
            require "active_support/concern"
         | 
| 4 4 | 
             
            require "active_support/core_ext/module/attribute_accessors"
         | 
| 5 5 | 
             
            require "concurrent"
         | 
| 6 | 
            +
            require "fiber"
         | 
| 6 7 |  | 
| 7 8 | 
             
            module ActiveSupport
         | 
| 8 9 | 
             
              module LoggerThreadSafeLevel # :nodoc:
         | 
| @@ -28,7 +29,7 @@ module ActiveSupport | |
| 28 29 | 
             
                end
         | 
| 29 30 |  | 
| 30 31 | 
             
                def local_log_id
         | 
| 31 | 
            -
                   | 
| 32 | 
            +
                  Fiber.current.__id__
         | 
| 32 33 | 
             
                end
         | 
| 33 34 |  | 
| 34 35 | 
             
                def local_level
         | 
| @@ -20,8 +20,8 @@ module ActiveSupport | |
| 20 20 | 
             
                    super
         | 
| 21 21 | 
             
                  end
         | 
| 22 22 |  | 
| 23 | 
            -
                  def subscribe(pattern = nil,  | 
| 24 | 
            -
                    subscriber = Subscribers.new | 
| 23 | 
            +
                  def subscribe(pattern = nil, callable = nil, &block)
         | 
| 24 | 
            +
                    subscriber = Subscribers.new(pattern, callable || block)
         | 
| 25 25 | 
             
                    synchronize do
         | 
| 26 26 | 
             
                      if String === pattern
         | 
| 27 27 | 
             
                        @string_subscribers[pattern] << subscriber
         | 
| @@ -13,14 +13,15 @@ module ActiveSupport | |
| 13 13 | 
             
                    @notifier = notifier
         | 
| 14 14 | 
             
                  end
         | 
| 15 15 |  | 
| 16 | 
            -
                  #  | 
| 17 | 
            -
                  # and publish it.  | 
| 18 | 
            -
                  #  | 
| 16 | 
            +
                  # Given a block, instrument it by measuring the time taken to execute
         | 
| 17 | 
            +
                  # and publish it. Without a block, simply send a message via the
         | 
| 18 | 
            +
                  # notifier. Notice that events get sent even if an error occurs in the
         | 
| 19 | 
            +
                  # passed-in block.
         | 
| 19 20 | 
             
                  def instrument(name, payload = {})
         | 
| 20 21 | 
             
                    # some of the listeners might have state
         | 
| 21 22 | 
             
                    listeners_state = start name, payload
         | 
| 22 23 | 
             
                    begin
         | 
| 23 | 
            -
                      yield payload
         | 
| 24 | 
            +
                      yield payload if block_given?
         | 
| 24 25 | 
             
                    rescue Exception => e
         | 
| 25 26 | 
             
                      payload[:exception] = [e.class.name, e.message]
         | 
| 26 27 | 
             
                      payload[:exception_object] = e
         | 
| @@ -55,8 +56,9 @@ module ActiveSupport | |
| 55 56 | 
             
                  attr_reader :name, :time, :end, :transaction_id, :payload, :children
         | 
| 56 57 |  | 
| 57 58 | 
             
                  def self.clock_gettime_supported? # :nodoc:
         | 
| 58 | 
            -
                    defined?(Process:: | 
| 59 | 
            -
                      !Gem.win_platform?
         | 
| 59 | 
            +
                    defined?(Process::CLOCK_THREAD_CPUTIME_ID) &&
         | 
| 60 | 
            +
                      !Gem.win_platform? &&
         | 
| 61 | 
            +
                      !RUBY_PLATFORM.match?(/solaris/i)
         | 
| 60 62 | 
             
                  end
         | 
| 61 63 | 
             
                  private_class_method :clock_gettime_supported?
         | 
| 62 64 |  | 
| @@ -67,9 +69,8 @@ module ActiveSupport | |
| 67 69 | 
             
                    @transaction_id = transaction_id
         | 
| 68 70 | 
             
                    @end            = ending
         | 
| 69 71 | 
             
                    @children       = []
         | 
| 70 | 
            -
                    @ | 
| 71 | 
            -
                    @ | 
| 72 | 
            -
                    @cpu_time_finish = nil
         | 
| 72 | 
            +
                    @cpu_time_start = 0
         | 
| 73 | 
            +
                    @cpu_time_finish = 0
         | 
| 73 74 | 
             
                    @allocation_count_start = 0
         | 
| 74 75 | 
             
                    @allocation_count_finish = 0
         | 
| 75 76 | 
             
                  end
         | 
| @@ -124,7 +125,7 @@ module ActiveSupport | |
| 124 125 | 
             
                  #
         | 
| 125 126 | 
             
                  #   @event.duration # => 1000.138
         | 
| 126 127 | 
             
                  def duration
         | 
| 127 | 
            -
                     | 
| 128 | 
            +
                    1000.0 * (self.end - time)
         | 
| 128 129 | 
             
                  end
         | 
| 129 130 |  | 
| 130 131 | 
             
                  def <<(event)
         | 
| @@ -142,7 +143,7 @@ module ActiveSupport | |
| 142 143 |  | 
| 143 144 | 
             
                    if clock_gettime_supported?
         | 
| 144 145 | 
             
                      def now_cpu
         | 
| 145 | 
            -
                        Process.clock_gettime(Process:: | 
| 146 | 
            +
                        Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID)
         | 
| 146 147 | 
             
                      end
         | 
| 147 148 | 
             
                    else
         | 
| 148 149 | 
             
                      def now_cpu
         |