mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #35201 from rails/no-leaks2
Fix memory leaks in development
This commit is contained in:
commit
ea0eaced55
8 changed files with 60 additions and 20 deletions
|
@ -58,22 +58,32 @@ module ActionView
|
|||
alias :eql? :equal?
|
||||
|
||||
@details_keys = Concurrent::Map.new
|
||||
@digest_cache = Concurrent::Map.new
|
||||
|
||||
def self.get(details)
|
||||
def self.digest_cache(details)
|
||||
@digest_cache[details_cache_key(details)] ||= Concurrent::Map.new
|
||||
end
|
||||
|
||||
def self.details_cache_key(details)
|
||||
if details[:formats]
|
||||
details = details.dup
|
||||
details[:formats] &= Template::Types.symbols
|
||||
end
|
||||
@details_keys[details] ||= Concurrent::Map.new
|
||||
@details_keys[details] ||= Object.new
|
||||
end
|
||||
|
||||
def self.clear
|
||||
ActionView::ViewPaths.all_view_paths.each do |path_set|
|
||||
path_set.each(&:clear_cache)
|
||||
end
|
||||
ActionView::LookupContext.fallbacks.each(&:clear_cache)
|
||||
@view_context_class = nil
|
||||
@details_keys.clear
|
||||
@digest_cache.clear
|
||||
end
|
||||
|
||||
def self.digest_caches
|
||||
@details_keys.values
|
||||
@digest_cache.values
|
||||
end
|
||||
|
||||
def self.view_context_class(klass)
|
||||
|
@ -88,7 +98,7 @@ module ActionView
|
|||
# Calculate the details key. Remove the handlers from calculation to improve performance
|
||||
# since the user cannot modify it explicitly.
|
||||
def details_key #:nodoc:
|
||||
@details_key ||= DetailsKey.get(@details) if @cache
|
||||
@details_key ||= DetailsKey.details_cache_key(@details) if @cache
|
||||
end
|
||||
|
||||
# Temporary skip passing the details_key forward.
|
||||
|
@ -102,7 +112,8 @@ module ActionView
|
|||
private
|
||||
|
||||
def _set_detail(key, value) # :doc:
|
||||
@details = @details.dup if @details_key
|
||||
@details = @details.dup if @digest_cache || @details_key
|
||||
@digest_cache = nil
|
||||
@details_key = nil
|
||||
@details[key] = value
|
||||
end
|
||||
|
@ -178,7 +189,7 @@ module ActionView
|
|||
user_details = @details.merge(options)
|
||||
|
||||
if @cache
|
||||
details_key = DetailsKey.get(user_details)
|
||||
details_key = DetailsKey.details_cache_key(user_details)
|
||||
else
|
||||
details_key = nil
|
||||
end
|
||||
|
@ -205,7 +216,7 @@ module ActionView
|
|||
end
|
||||
|
||||
if @cache
|
||||
[details, DetailsKey.get(details)]
|
||||
[details, DetailsKey.details_cache_key(details)]
|
||||
else
|
||||
[details, nil]
|
||||
end
|
||||
|
@ -236,6 +247,7 @@ module ActionView
|
|||
|
||||
def initialize(view_paths, details = {}, prefixes = [])
|
||||
@details_key = nil
|
||||
@digest_cache = nil
|
||||
@cache = true
|
||||
@prefixes = prefixes
|
||||
@rendered_format = nil
|
||||
|
@ -245,7 +257,7 @@ module ActionView
|
|||
end
|
||||
|
||||
def digest_cache
|
||||
details_key
|
||||
@digest_cache ||= DetailsKey.digest_cache(@details)
|
||||
end
|
||||
|
||||
def initialize_details(target, details)
|
||||
|
|
|
@ -87,6 +87,7 @@ module ActionView
|
|||
|
||||
# Returns an object that is able to render templates.
|
||||
def view_renderer # :nodoc:
|
||||
# Lifespan: Per controller
|
||||
@_view_renderer ||= ActionView::Renderer.new(lookup_context)
|
||||
end
|
||||
|
||||
|
|
|
@ -5,13 +5,21 @@ module ActionView
|
|||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
class_attribute :_view_paths, default: ActionView::PathSet.new.freeze
|
||||
ViewPaths.set_view_paths(self, ActionView::PathSet.new.freeze)
|
||||
end
|
||||
|
||||
delegate :template_exists?, :any_templates?, :view_paths, :formats, :formats=,
|
||||
:locale, :locale=, to: :lookup_context
|
||||
|
||||
module ClassMethods
|
||||
def _view_paths
|
||||
ViewPaths.get_view_paths(self)
|
||||
end
|
||||
|
||||
def _view_paths=(paths)
|
||||
ViewPaths.set_view_paths(self, paths)
|
||||
end
|
||||
|
||||
def _prefixes # :nodoc:
|
||||
@_prefixes ||= begin
|
||||
return local_prefixes if superclass.abstract?
|
||||
|
@ -29,6 +37,22 @@ module ActionView
|
|||
end
|
||||
end
|
||||
|
||||
# :stopdoc:
|
||||
@all_view_paths = {}
|
||||
|
||||
def self.get_view_paths(klass)
|
||||
@all_view_paths[klass] || get_view_paths(klass.superclass)
|
||||
end
|
||||
|
||||
def self.set_view_paths(klass, paths)
|
||||
@all_view_paths[klass] = paths
|
||||
end
|
||||
|
||||
def self.all_view_paths
|
||||
@all_view_paths.values.uniq
|
||||
end
|
||||
# :startdoc:
|
||||
|
||||
# The prefixes used in render "foo" shortcuts.
|
||||
def _prefixes # :nodoc:
|
||||
self.class._prefixes
|
||||
|
|
|
@ -11,9 +11,9 @@ class AVLogSubscriberTest < ActiveSupport::TestCase
|
|||
def setup
|
||||
super
|
||||
|
||||
ActionView::LookupContext::DetailsKey.clear
|
||||
|
||||
view_paths = ActionController::Base.view_paths
|
||||
view_paths.each(&:clear_cache)
|
||||
ActionView::LookupContext.fallbacks.each(&:clear_cache)
|
||||
|
||||
lookup_context = ActionView::LookupContext.new(view_paths, {}, ["test"])
|
||||
renderer = ActionView::Renderer.new(lookup_context)
|
||||
|
|
|
@ -631,9 +631,8 @@ class CachedViewRenderTest < ActiveSupport::TestCase
|
|||
|
||||
# Ensure view path cache is primed
|
||||
def setup
|
||||
ActionView::LookupContext::DetailsKey.clear
|
||||
view_paths = ActionController::Base.view_paths
|
||||
view_paths.each(&:clear_cache)
|
||||
ActionView::LookupContext.fallbacks.each(&:clear_cache)
|
||||
assert_equal ActionView::OptimizedFileSystemResolver, view_paths.first.class
|
||||
setup_view(view_paths)
|
||||
end
|
||||
|
@ -650,9 +649,7 @@ class LazyViewRenderTest < ActiveSupport::TestCase
|
|||
# Test the same thing as above, but make sure the view path
|
||||
# is not eager loaded
|
||||
def setup
|
||||
view_paths = ActionController::Base.view_paths
|
||||
view_paths.each(&:clear_cache)
|
||||
ActionView::LookupContext.fallbacks.each(&:clear_cache)
|
||||
ActionView::LookupContext::DetailsKey.clear
|
||||
path = ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH)
|
||||
view_paths = ActionView::PathSet.new([path])
|
||||
assert_equal ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH), view_paths.first
|
||||
|
@ -710,10 +707,10 @@ class CachedCollectionViewRenderTest < ActiveSupport::TestCase
|
|||
|
||||
# Ensure view path cache is primed
|
||||
setup do
|
||||
ActionView::LookupContext::DetailsKey.clear
|
||||
|
||||
view_paths = ActionController::Base.view_paths
|
||||
assert_equal ActionView::OptimizedFileSystemResolver, view_paths.first.class
|
||||
view_paths.each(&:clear_cache)
|
||||
ActionView::LookupContext.fallbacks.each(&:clear_cache)
|
||||
|
||||
ActionView::PartialRenderer.collection_cache = ActiveSupport::Cache::MemoryStore.new
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ require "abstract_unit"
|
|||
|
||||
class ResolverCacheTest < ActiveSupport::TestCase
|
||||
def test_inspect_shields_cache_internals
|
||||
ActionView::LookupContext::DetailsKey.clear
|
||||
assert_match %r(#<ActionView::Resolver:0x[0-9a-f]+ @cache=#<ActionView::Resolver::Cache:0x[0-9a-f]+ keys=0 queries=0>>), ActionView::Resolver.new.inspect
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,9 +7,9 @@ end
|
|||
|
||||
class SetupFiberedBase < ActiveSupport::TestCase
|
||||
def setup
|
||||
ActionView::LookupContext::DetailsKey.clear
|
||||
|
||||
view_paths = ActionController::Base.view_paths
|
||||
view_paths.each(&:clear_cache)
|
||||
ActionView::LookupContext.fallbacks.each(&:clear_cache)
|
||||
|
||||
@assigns = { secret: "in the sauce", name: nil }
|
||||
@view = ActionView::Base.with_empty_template_cache.with_view_paths(view_paths, @assigns)
|
||||
|
|
|
@ -24,6 +24,11 @@ module ActionView
|
|||
DeveloperStruct = Struct.new(:name)
|
||||
|
||||
module SharedTests
|
||||
def setup
|
||||
ActionView::LookupContext::DetailsKey.clear
|
||||
super
|
||||
end
|
||||
|
||||
def self.included(test_case)
|
||||
test_case.class_eval do
|
||||
test "helpers defined on ActionView::TestCase are available" do
|
||||
|
|
Loading…
Reference in a new issue