aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib/active_support')
-rw-r--r--activesupport/lib/active_support/cache.rb9
-rw-r--r--activesupport/lib/active_support/cache/strategy/local_cache.rb6
-rw-r--r--activesupport/lib/active_support/callbacks.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/module/delegation.rb18
-rw-r--r--activesupport/lib/active_support/core_ext/object/duplicable.rb124
-rw-r--r--activesupport/lib/active_support/dependencies.rb26
-rw-r--r--activesupport/lib/active_support/deprecation/proxy_wrappers.rb29
-rw-r--r--activesupport/lib/active_support/inflector/inflections.rb1
-rw-r--r--activesupport/lib/active_support/log_subscriber.rb3
-rw-r--r--activesupport/lib/active_support/message_verifier.rb4
-rw-r--r--activesupport/lib/active_support/number_helper.rb2
-rw-r--r--activesupport/lib/active_support/parameter_filter.rb7
-rw-r--r--activesupport/lib/active_support/rails.rb3
-rw-r--r--activesupport/lib/active_support/secure_compare_rotator.rb52
-rw-r--r--activesupport/lib/active_support/testing/parallelization.rb11
15 files changed, 148 insertions, 148 deletions
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index e055135bb4..a5063d0784 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -678,18 +678,15 @@ module ActiveSupport
end
def instrument(operation, key, options = nil)
- log { "Cache #{operation}: #{normalize_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}" }
+ if logger && logger.debug? && !silence?
+ logger.debug "Cache #{operation}: #{normalize_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}"
+ end
payload = { key: key }
payload.merge!(options) if options.is_a?(Hash)
ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload) { yield(payload) }
end
- def log
- return unless logger && logger.debug? && !silence?
- logger.debug(yield)
- end
-
def handle_expired_entry(entry, key, options)
if entry && entry.expired?
race_ttl = options[:race_condition_ttl].to_i
diff --git a/activesupport/lib/active_support/cache/strategy/local_cache.rb b/activesupport/lib/active_support/cache/strategy/local_cache.rb
index 39b32fc7f6..8e80946fbb 100644
--- a/activesupport/lib/active_support/cache/strategy/local_cache.rb
+++ b/activesupport/lib/active_support/cache/strategy/local_cache.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require "active_support/core_ext/object/duplicable"
require "active_support/core_ext/string/inflections"
require "active_support/per_thread_registry"
@@ -75,7 +74,10 @@ module ActiveSupport
end
def fetch_entry(key, options = nil) # :nodoc:
- @data.fetch(key) { @data[key] = yield }
+ entry = @data.fetch(key) { @data[key] = yield }
+ dup_entry = entry.dup
+ dup_entry&.dup_value!
+ dup_entry
end
end
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 11746e0537..daf98c9528 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -7,7 +7,6 @@ require "active_support/core_ext/class/attribute"
require "active_support/core_ext/kernel/reporting"
require "active_support/core_ext/kernel/singleton_class"
require "active_support/core_ext/string/filters"
-require "active_support/deprecation"
require "thread"
module ActiveSupport
diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb
index b8996ecb10..14d7f0c484 100644
--- a/activesupport/lib/active_support/core_ext/module/delegation.rb
+++ b/activesupport/lib/active_support/core_ext/module/delegation.rb
@@ -205,18 +205,18 @@ class Module
if allow_nil
method_def = [
"def #{method_prefix}#{method}(#{definition})",
- "_ = #{to}",
- "if !_.nil? || nil.respond_to?(:#{method})",
- " _.#{method}(#{definition})",
- "end",
- "end"
+ " _ = #{to}",
+ " if !_.nil? || nil.respond_to?(:#{method})",
+ " _.#{method}(#{definition})",
+ " end",
+ "end"
].join ";"
else
exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
method_def = [
"def #{method_prefix}#{method}(#{definition})",
- " _ = #{to}",
+ " _ = #{to}",
" _.#{method}(#{definition})",
"rescue NoMethodError => e",
" if _.nil? && e.name == :#{method}",
@@ -276,6 +276,11 @@ class Module
# The delegated method must be public on the target, otherwise it will
# raise +DelegationError+. If you wish to instead return +nil+,
# use the <tt>:allow_nil</tt> option.
+ #
+ # The <tt>marshal_dump</tt> and <tt>_dump</tt> methods are exempt from
+ # delegation due to possible interference when calling
+ # <tt>Marshal.dump(object)</tt>, should the delegation target method
+ # of <tt>object</tt> add or remove instance variables.
def delegate_missing_to(target, allow_nil: nil)
target = target.to_s
target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target)
@@ -285,6 +290,7 @@ class Module
# It may look like an oversight, but we deliberately do not pass
# +include_private+, because they do not get delegated.
+ return false if name == :marshal_dump || name == :_dump
#{target}.respond_to?(name) || super
end
diff --git a/activesupport/lib/active_support/core_ext/object/duplicable.rb b/activesupport/lib/active_support/core_ext/object/duplicable.rb
index c78ee6bbfc..3ebcdca02b 100644
--- a/activesupport/lib/active_support/core_ext/object/duplicable.rb
+++ b/activesupport/lib/active_support/core_ext/object/duplicable.rb
@@ -28,96 +28,6 @@ class Object
end
end
-class NilClass
- begin
- nil.dup
- rescue TypeError
-
- # +nil+ is not duplicable:
- #
- # nil.duplicable? # => false
- # nil.dup # => TypeError: can't dup NilClass
- def duplicable?
- false
- end
- end
-end
-
-class FalseClass
- begin
- false.dup
- rescue TypeError
-
- # +false+ is not duplicable:
- #
- # false.duplicable? # => false
- # false.dup # => TypeError: can't dup FalseClass
- def duplicable?
- false
- end
- end
-end
-
-class TrueClass
- begin
- true.dup
- rescue TypeError
-
- # +true+ is not duplicable:
- #
- # true.duplicable? # => false
- # true.dup # => TypeError: can't dup TrueClass
- def duplicable?
- false
- end
- end
-end
-
-class Symbol
- begin
- :symbol.dup
-
- # Some symbols couldn't be duped in Ruby 2.4.0 only, due to a bug.
- # This feature check catches any regression.
- "symbol_from_string".to_sym.dup
- rescue TypeError
-
- # Symbols are not duplicable:
- #
- # :my_symbol.duplicable? # => false
- # :my_symbol.dup # => TypeError: can't dup Symbol
- def duplicable?
- false
- end
- end
-end
-
-class Numeric
- begin
- 1.dup
- rescue TypeError
-
- # Numbers are not duplicable:
- #
- # 3.duplicable? # => false
- # 3.dup # => TypeError: can't dup Integer
- def duplicable?
- false
- end
- end
-end
-
-require "bigdecimal"
-class BigDecimal
- # BigDecimals are duplicable:
- #
- # BigDecimal("1.2").duplicable? # => true
- # BigDecimal("1.2").dup # => #<BigDecimal:...,'0.12E1',18(18)>
- def duplicable?
- true
- end
-end
-
class Method
# Methods are not duplicable:
#
@@ -128,32 +38,12 @@ class Method
end
end
-class Complex
- begin
- Complex(1).dup
- rescue TypeError
-
- # Complexes are not duplicable:
- #
- # Complex(1).duplicable? # => false
- # Complex(1).dup # => TypeError: can't copy Complex
- def duplicable?
- false
- end
- end
-end
-
-class Rational
- begin
- Rational(1).dup
- rescue TypeError
-
- # Rationals are not duplicable:
- #
- # Rational(1).duplicable? # => false
- # Rational(1).dup # => TypeError: can't copy Rational
- def duplicable?
- false
- end
+class UnboundMethod
+ # Unbound methods are not duplicable:
+ #
+ # method(:puts).unbind.duplicable? # => false
+ # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
+ def duplicable?
+ false
end
end
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 5dc47b20c6..32cb3a53f4 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -201,6 +201,11 @@ module ActiveSupport #:nodoc:
end
end
+ def self.include_into(base)
+ base.include(self)
+ append_features(base)
+ end
+
def const_missing(const_name)
from_mod = anonymous? ? guess_for_anonymous(const_name) : self
Dependencies.load_missing_constant(from_mod, const_name)
@@ -230,6 +235,21 @@ module ActiveSupport #:nodoc:
base.class_eval do
define_method(:load, Kernel.instance_method(:load))
private :load
+
+ define_method(:require, Kernel.instance_method(:require))
+ private :require
+ end
+ end
+
+ def self.include_into(base)
+ base.include(self)
+
+ if base.instance_method(:load).owner == base
+ base.remove_method(:load)
+ end
+
+ if base.instance_method(:require).owner == base
+ base.remove_method(:require)
end
end
@@ -325,9 +345,9 @@ module ActiveSupport #:nodoc:
end
def hook!
- Object.class_eval { include Loadable }
- Module.class_eval { include ModuleConstMissing }
- Exception.class_eval { include Blamable }
+ Loadable.include_into(Object)
+ ModuleConstMissing.include_into(Module)
+ Exception.include(Blamable)
end
def unhook!
diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
index 56f1e23136..d7d3c30b97 100644
--- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
+++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
@@ -120,9 +120,16 @@ module ActiveSupport
# # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
# (Backtrace information…)
# ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
- class DeprecatedConstantProxy < DeprecationProxy
+ class DeprecatedConstantProxy < Module
+ def self.new(*args, &block)
+ object = args.first
+
+ return object unless object
+ super
+ end
+
def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.")
- require "active_support/inflector/methods"
+ Kernel.require "active_support/inflector/methods"
@old_const = old_const
@new_const = new_const
@@ -130,6 +137,14 @@ module ActiveSupport
@message = message
end
+ instance_methods.each { |m| undef_method m unless /^__|^object_id$/.match?(m) }
+
+ # Don't give a deprecation warning on inspect since test/unit and error
+ # logs rely on it for diagnostics.
+ def inspect
+ target.inspect
+ end
+
# Returns the class of the new constant.
#
# PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
@@ -144,8 +159,14 @@ module ActiveSupport
ActiveSupport::Inflector.constantize(@new_const.to_s)
end
- def warn(callstack, called, args)
- @deprecator.warn(@message, callstack)
+ def const_missing(name)
+ @deprecator.warn(@message, caller_locations)
+ target.const_get(name)
+ end
+
+ def method_missing(called, *args, &block)
+ @deprecator.warn(@message, caller_locations)
+ target.__send__(called, *args, &block)
end
end
end
diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb
index 5b29a13894..efee74a1df 100644
--- a/activesupport/lib/active_support/inflector/inflections.rb
+++ b/activesupport/lib/active_support/inflector/inflections.rb
@@ -2,7 +2,6 @@
require "concurrent/map"
require "active_support/i18n"
-require "active_support/deprecation"
module ActiveSupport
module Inflector
diff --git a/activesupport/lib/active_support/log_subscriber.rb b/activesupport/lib/active_support/log_subscriber.rb
index db991c7a32..8b9dd1fffe 100644
--- a/activesupport/lib/active_support/log_subscriber.rb
+++ b/activesupport/lib/active_support/log_subscriber.rb
@@ -29,6 +29,9 @@ module ActiveSupport
# subscriber, the line above should be called after your
# <tt>ActiveRecord::LogSubscriber</tt> definition.
#
+ # A logger also needs to be set with <tt>ActiveRecord::LogSubscriber.logger=</tt>.
+ # This is assigned automatically in a Rails environment.
+ #
# After configured, whenever a <tt>"sql.active_record"</tt> notification is published,
# it will properly dispatch the event
# (<tt>ActiveSupport::Notifications::Event</tt>) to the sql method.
diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb
index c4a4afe95f..a5dc1181d8 100644
--- a/activesupport/lib/active_support/message_verifier.rb
+++ b/activesupport/lib/active_support/message_verifier.rb
@@ -178,8 +178,8 @@ module ActiveSupport
# Generates a signed message for the provided value.
#
- # The message is signed with the +MessageVerifier+'s secret. Without knowing
- # the secret, the original value cannot be extracted from the message.
+ # The message is signed with the +MessageVerifier+'s secret.
+ # Returns Base64-encoded message joined with the generated signature.
#
# verifier = ActiveSupport::MessageVerifier.new 's3Krit'
# verifier.generate 'a private message' # => "BAhJIhRwcml2YXRlLW1lc3NhZ2UGOgZFVA==--e2d724331ebdee96a10fb99b089508d1c72bd772"
diff --git a/activesupport/lib/active_support/number_helper.rb b/activesupport/lib/active_support/number_helper.rb
index 8f3d04aa5c..0c87114c0d 100644
--- a/activesupport/lib/active_support/number_helper.rb
+++ b/activesupport/lib/active_support/number_helper.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require "active_support/dependencies/autoload"
-
module ActiveSupport
module NumberHelper
extend ActiveSupport::Autoload
diff --git a/activesupport/lib/active_support/parameter_filter.rb b/activesupport/lib/active_support/parameter_filter.rb
index 8e5595babf..e1cd7c46c1 100644
--- a/activesupport/lib/active_support/parameter_filter.rb
+++ b/activesupport/lib/active_support/parameter_filter.rb
@@ -109,7 +109,12 @@ module ActiveSupport
elsif value.is_a?(Hash)
value = call(value, parents, original_params)
elsif value.is_a?(Array)
- value = value.map { |v| v.is_a?(Hash) ? call(v, parents, original_params) : v }
+ # If we don't pop the current parent it will be duplicated as we
+ # process each array value.
+ parents.pop if deep_regexps
+ value = value.map { |v| value_for_key(key, v, parents, original_params) }
+ # Restore the parent stack after processing the array.
+ parents.push(key) if deep_regexps
elsif blocks.any?
key = key.dup if key.duplicable?
value = value.dup if value.duplicable?
diff --git a/activesupport/lib/active_support/rails.rb b/activesupport/lib/active_support/rails.rb
index 8b727a69ec..30857f04d8 100644
--- a/activesupport/lib/active_support/rails.rb
+++ b/activesupport/lib/active_support/rails.rb
@@ -13,9 +13,6 @@
# Defines Object#blank? and Object#present?.
require "active_support/core_ext/object/blank"
-# Rails own autoload, eager_load, etc.
-require "active_support/dependencies/autoload"
-
# Support for ClassMethods and the included macro.
require "active_support/concern"
diff --git a/activesupport/lib/active_support/secure_compare_rotator.rb b/activesupport/lib/active_support/secure_compare_rotator.rb
new file mode 100644
index 0000000000..14a0aee947
--- /dev/null
+++ b/activesupport/lib/active_support/secure_compare_rotator.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require "active_support/security_utils"
+require "active_support/messages/rotator"
+
+module ActiveSupport
+ # The ActiveSupport::SecureCompareRotator is a wrapper around +ActiveSupport::SecurityUtils.secure_compare+
+ # and allows you to rotate a previously defined value to a new one.
+ #
+ # It can be used as follow:
+ #
+ # rotator = ActiveSupport::SecureCompareRotator.new('new_production_value')
+ # rotator.rotate('previous_production_value')
+ # rotator.secure_compare!('previous_production_value')
+ #
+ # One real use case example would be to rotate a basic auth credentials:
+ #
+ # class MyController < ApplicationController
+ # def authenticate_request
+ # rotator = ActiveSupport::SecureComparerotator.new('new_password')
+ # rotator.rotate('old_password')
+ #
+ # authenticate_or_request_with_http_basic do |username, password|
+ # rotator.secure_compare!(password)
+ # rescue ActiveSupport::SecureCompareRotator::InvalidMatch
+ # false
+ # end
+ # end
+ # end
+ class SecureCompareRotator
+ include SecurityUtils
+ prepend Messages::Rotator
+
+ InvalidMatch = Class.new(StandardError)
+
+ def initialize(value, **_options)
+ @value = value
+ end
+
+ def secure_compare!(other_value, on_rotation: @rotation)
+ secure_compare(@value, other_value) ||
+ run_rotations(on_rotation) { |wrapper| wrapper.secure_compare!(other_value) } ||
+ raise(InvalidMatch)
+ end
+
+ private
+
+ def build_rotation(previous_value, _options)
+ self.class.new(previous_value)
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/testing/parallelization.rb b/activesupport/lib/active_support/testing/parallelization.rb
index f50a5e0554..96518a4a58 100644
--- a/activesupport/lib/active_support/testing/parallelization.rb
+++ b/activesupport/lib/active_support/testing/parallelization.rb
@@ -72,7 +72,11 @@ module ActiveSupport
def start
@pool = @queue_size.times.map do |worker|
+ title = "Rails test worker #{worker}"
+
fork do
+ Process.setproctitle("#{title} - (starting)")
+
DRb.stop_service
begin
@@ -85,6 +89,9 @@ module ActiveSupport
klass = job[0]
method = job[1]
reporter = job[2]
+
+ Process.setproctitle("#{title} - #{klass}##{method}")
+
result = klass.with_info_handler reporter do
Minitest.run_one_method(klass, method)
end
@@ -99,8 +106,12 @@ module ActiveSupport
end
queue.record(reporter, result)
end
+
+ Process.setproctitle("#{title} - (idle)")
end
ensure
+ Process.setproctitle("#{title} - (stopping)")
+
run_cleanup(worker)
end
end