Merge pull request #1524 from Shopify/global-constant-cache

Eagerly cache global filters
This commit is contained in:
Jean byroot Boussier
2022-03-01 16:14:31 +01:00
committed by GitHub
6 changed files with 30 additions and 23 deletions
+1 -1
View File
@@ -59,8 +59,8 @@ require 'liquid/forloop_drop'
require 'liquid/extensions' require 'liquid/extensions'
require 'liquid/errors' require 'liquid/errors'
require 'liquid/interrupts' require 'liquid/interrupts'
require 'liquid/strainer_factory'
require 'liquid/strainer_template' require 'liquid/strainer_template'
require 'liquid/strainer_factory'
require 'liquid/expression' require 'liquid/expression'
require 'liquid/context' require 'liquid/context'
require 'liquid/parser_switching' require 'liquid/parser_switching'
+11 -10
View File
@@ -7,25 +7,26 @@ module Liquid
def add_global_filter(filter) def add_global_filter(filter)
strainer_class_cache.clear strainer_class_cache.clear
global_filters << filter GlobalCache.add_filter(filter)
end end
def create(context, filters = []) def create(context, filters = [])
strainer_from_cache(filters).new(context) strainer_from_cache(filters).new(context)
end end
GlobalCache = Class.new(StrainerTemplate)
private private
def global_filters
@global_filters ||= []
end
def strainer_from_cache(filters) def strainer_from_cache(filters)
strainer_class_cache[filters] ||= begin if filters.empty?
klass = Class.new(StrainerTemplate) GlobalCache
global_filters.each { |f| klass.add_filter(f) } else
filters.each { |f| klass.add_filter(f) } strainer_class_cache[filters] ||= begin
klass klass = Class.new(GlobalCache)
filters.each { |f| klass.add_filter(f) }
klass
end
end end
end end
+5
View File
@@ -31,6 +31,11 @@ module Liquid
filter_methods.include?(method.to_s) filter_methods.include?(method.to_s)
end end
def inherited(subclass)
super
subclass.instance_variable_set(:@filter_methods, @filter_methods.dup)
end
private private
def filter_methods def filter_methods
+10 -10
View File
@@ -72,21 +72,21 @@ module Minitest
end end
def with_global_filter(*globals) def with_global_filter(*globals)
original_global_filters = Liquid::StrainerFactory.instance_variable_get(:@global_filters) original_global_cache = Liquid::StrainerFactory::GlobalCache
Liquid::StrainerFactory.instance_variable_set(:@global_filters, []) Liquid::StrainerFactory.send(:remove_const, :GlobalCache)
globals.each do |global| Liquid::StrainerFactory.const_set(:GlobalCache, Class.new(Liquid::StrainerTemplate))
Liquid::StrainerFactory.add_global_filter(global)
end
Liquid::StrainerFactory.send(:strainer_class_cache).clear
globals.each do |global| globals.each do |global|
Liquid::Template.register_filter(global) Liquid::Template.register_filter(global)
end end
yield
ensure
Liquid::StrainerFactory.send(:strainer_class_cache).clear Liquid::StrainerFactory.send(:strainer_class_cache).clear
Liquid::StrainerFactory.instance_variable_set(:@global_filters, original_global_filters) begin
yield
ensure
Liquid::StrainerFactory.send(:remove_const, :GlobalCache)
Liquid::StrainerFactory.const_set(:GlobalCache, original_global_cache)
Liquid::StrainerFactory.send(:strainer_class_cache).clear
end
end end
def with_error_mode(mode) def with_error_mode(mode)
+2 -1
View File
@@ -52,7 +52,8 @@ class StrainerFactoryUnitTest < Minitest::Test
/\ALiquid error: wrong number of arguments \((1 for 0|given 1, expected 0)\)\z/, /\ALiquid error: wrong number of arguments \((1 for 0|given 1, expected 0)\)\z/,
exception.message exception.message
) )
assert_equal(exception.backtrace[0].split(':')[0], __FILE__) source = AccessScopeFilters.instance_method(:public_filter).source_location
assert_equal(source.map(&:to_s), exception.backtrace[0].split(':')[0..1])
end end
def test_strainer_only_invokes_public_filter_methods def test_strainer_only_invokes_public_filter_methods
+1 -1
View File
@@ -57,8 +57,8 @@ class StrainerTemplateUnitTest < Minitest::Test
end end
def test_add_filter_does_not_raise_when_module_overrides_previously_registered_method def test_add_filter_does_not_raise_when_module_overrides_previously_registered_method
strainer = Context.new.strainer
with_global_filter do with_global_filter do
strainer = Context.new.strainer
strainer.class.add_filter(PublicMethodOverrideFilter) strainer.class.add_filter(PublicMethodOverrideFilter)
assert(strainer.class.send(:filter_methods).include?('public_filter')) assert(strainer.class.send(:filter_methods).include?('public_filter'))
end end