mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-16 09:20:42 -07:00
Including a module can cause Ruby's global constant cache to be busted if the included module contain constants. So that's something you don't want to happen at "runtime", otherwise it will severely degrade performance and if you are using YJIT or MJIT most of the compiled code will be invalidated. To limit the impact of this, we can pre-include the global filters, as they're generally registered during boot, that limits the problem to non-global filters.
38 lines
775 B
Ruby
38 lines
775 B
Ruby
# frozen_string_literal: true
|
|
|
|
module Liquid
|
|
# StrainerFactory is the factory for the filters system.
|
|
module StrainerFactory
|
|
extend self
|
|
|
|
def add_global_filter(filter)
|
|
strainer_class_cache.clear
|
|
GlobalCache.add_filter(filter)
|
|
end
|
|
|
|
def create(context, filters = [])
|
|
strainer_from_cache(filters).new(context)
|
|
end
|
|
|
|
GlobalCache = Class.new(StrainerTemplate)
|
|
|
|
private
|
|
|
|
def strainer_from_cache(filters)
|
|
if filters.empty?
|
|
GlobalCache
|
|
else
|
|
strainer_class_cache[filters] ||= begin
|
|
klass = Class.new(GlobalCache)
|
|
filters.each { |f| klass.add_filter(f) }
|
|
klass
|
|
end
|
|
end
|
|
end
|
|
|
|
def strainer_class_cache
|
|
@strainer_class_cache ||= {}
|
|
end
|
|
end
|
|
end
|