diff --git a/lib/liquid.rb b/lib/liquid.rb index 18566f6b2..0a970005d 100644 --- a/lib/liquid.rb +++ b/lib/liquid.rb @@ -68,7 +68,6 @@ module Liquid require 'liquid/errors' require 'liquid/interrupts' require 'liquid/strainer_template' -require 'liquid/strainer_factory' require 'liquid/expression' require 'liquid/context' require 'liquid/tag' diff --git a/lib/liquid/strainer_factory.rb b/lib/liquid/strainer_factory.rb deleted file mode 100644 index 869b09ad3..000000000 --- a/lib/liquid/strainer_factory.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module Liquid - # StrainerFactory is the factory for the filters system. - module StrainerFactory - extend self - - def add_global_filter(filter, environment = Environment.default) - Deprecations.warn("StrainerFactory.add_global_filter", "Environment#register_filter") - environment.register_filter(filter) - end - - def create(context, filters = Const::EMPTY_ARRAY, environment = Environment.default) - Deprecations.warn("StrainerFactory.create", "StrainerFactory.create_strainer") - environment.create_strainer(context, filters) - end - - def global_filter_names(environment = Environment.default) - Deprecations.warn("StrainerFactory.global_filter_names", "Environment#filter_method_names") - Environment.strainer_template.filter_method_names - end - end -end diff --git a/performance/benchmark.rb b/performance/benchmark.rb index da31aa0c6..f897c5113 100644 --- a/performance/benchmark.rb +++ b/performance/benchmark.rb @@ -4,7 +4,8 @@ require_relative 'theme_runner' RubyVM::YJIT.enable if defined?(RubyVM::YJIT) -Liquid::Template.error_mode = ARGV.first.to_sym if ARGV.first +Liquid::Environment.default.error_mode = ARGV.first.to_sym if ARGV.first + profiler = ThemeRunner.new Benchmark.ips do |x| diff --git a/performance/shopify/liquid.rb b/performance/shopify/liquid.rb index 40444c3c6..d30e67b04 100644 --- a/performance/shopify/liquid.rb +++ b/performance/shopify/liquid.rb @@ -11,11 +11,12 @@ require_relative 'tag_filter' require_relative 'weight_filter' -Liquid::Template.register_tag('paginate', Paginate) -Liquid::Template.register_tag('form', CommentForm) +default_environment = Liquid::Environment.default +default_environment.register_tag('paginate', Paginate) +default_environment.register_tag('form', CommentForm) -Liquid::Template.register_filter(JsonFilter) -Liquid::Template.register_filter(MoneyFilter) -Liquid::Template.register_filter(WeightFilter) -Liquid::Template.register_filter(ShopFilter) -Liquid::Template.register_filter(TagFilter) +default_environment.register_filter(JsonFilter) +default_environment.register_filter(MoneyFilter) +default_environment.register_filter(WeightFilter) +default_environment.register_filter(ShopFilter) +default_environment.register_filter(TagFilter) diff --git a/test/integration/error_handling_test.rb b/test/integration/error_handling_test.rb index c19e75243..26b0e5f95 100644 --- a/test/integration/error_handling_test.rb +++ b/test/integration/error_handling_test.rb @@ -203,20 +203,19 @@ def test_default_exception_renderer_with_internal_error end def test_setting_default_exception_renderer - old_exception_renderer = Liquid::Template.default_exception_renderer exceptions = [] - Liquid::Template.default_exception_renderer = ->(e) { + default_exception_renderer = ->(e) { exceptions << e '' } - template = Liquid::Template.parse('This is a runtime error: {{ errors.argument_error }}') + + env = Liquid::Environment.build(exception_renderer: default_exception_renderer) + template = Liquid::Template.parse('This is a runtime error: {{ errors.argument_error }}', environment: env) output = template.render('errors' => ErrorDrop.new) assert_equal('This is a runtime error: ', output) assert_equal([Liquid::ArgumentError], template.errors.map(&:class)) - ensure - Liquid::Template.default_exception_renderer = old_exception_renderer if old_exception_renderer end def test_setting_exception_renderer_on_environment diff --git a/test/integration/profiler_test.rb b/test/integration/profiler_test.rb index 1a610c56a..70a22fc06 100644 --- a/test/integration/profiler_test.rb +++ b/test/integration/profiler_test.rb @@ -33,7 +33,7 @@ def read_template_file(template_path) end def setup - Liquid::Template.file_system = ProfilingFileSystem.new + Liquid::Environment.default.file_system = ProfilingFileSystem.new end def test_template_allows_flagging_profiling diff --git a/test/integration/tags/include_tag_test.rb b/test/integration/tags/include_tag_test.rb index ad801f69a..6e1649663 100644 --- a/test/integration/tags/include_tag_test.rb +++ b/test/integration/tags/include_tag_test.rb @@ -174,10 +174,10 @@ def read_template_file(_template_path) end end - Liquid::Template.file_system = infinite_file_system.new + env = Liquid::Environment.build(file_system: infinite_file_system.new) assert_raises(Liquid::StackLevelError) do - Template.parse("{% include 'loop' %}").render! + Template.parse("{% include 'loop' %}", environment: env).render! end end @@ -264,26 +264,27 @@ def test_custom_include_tag_within_if_statement end def test_does_not_add_error_in_strict_mode_for_missing_variable - Liquid::Template.file_system = TestFileSystem.new + env = Liquid::Environment.build(file_system: TestFileSystem.new) - a = Liquid::Template.parse(' {% include "nested_template" %}') + a = Liquid::Template.parse(' {% include "nested_template" %}', environment: env) a.render! assert_empty(a.errors) end def test_passing_options_to_included_templates - Liquid::Template.file_system = TestFileSystem.new + env = Liquid::Environment.build(file_system: TestFileSystem.new) + assert_raises(Liquid::SyntaxError) do - Template.parse("{% include template %}", error_mode: :strict).render!("template" => '{{ "X" || downcase }}') + Template.parse("{% include template %}", error_mode: :strict, environment: env).render!("template" => '{{ "X" || downcase }}') end with_error_mode(:lax) do - assert_equal('x', Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: true).render!("template" => '{{ "X" || downcase }}')) + assert_equal('x', Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: true, environment: env).render!("template" => '{{ "X" || downcase }}')) end assert_raises(Liquid::SyntaxError) do - Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: [:locale]).render!("template" => '{{ "X" || downcase }}') + Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: [:locale], environment: env).render!("template" => '{{ "X" || downcase }}') end with_error_mode(:lax) do - assert_equal('x', Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: [:error_mode]).render!("template" => '{{ "X" || downcase }}')) + assert_equal('x', Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: [:error_mode], environment: env).render!("template" => '{{ "X" || downcase }}')) end end @@ -334,8 +335,11 @@ def test_including_via_variable_value end def test_including_with_strict_variables - Liquid::Template.file_system = StubFileSystem.new({ "simple" => "simple" }) - template = Liquid::Template.parse("{% include 'simple' %}", error_mode: :warn) + env = Liquid::Environment.build( + file_system: StubFileSystem.new('simple' => 'simple'), + ) + + template = Liquid::Template.parse("{% include 'simple' %}", error_mode: :warn, environment: env) template.render(nil, strict_variables: true) assert_equal([], template.errors) diff --git a/test/integration/tags/render_tag_test.rb b/test/integration/tags/render_tag_test.rb index 01485cfa2..eda80a040 100644 --- a/test/integration/tags/render_tag_test.rb +++ b/test/integration/tags/render_tag_test.rb @@ -82,19 +82,22 @@ def test_nested_render_tag end def test_recursively_rendered_template_does_not_produce_endless_loop - Liquid::Template.file_system = StubFileSystem.new('loop' => '{% render "loop" %}') + env = Liquid::Environment.build( + file_system: StubFileSystem.new('loop' => '{% render "loop" %}'), + ) assert_raises(Liquid::StackLevelError) do - Template.parse('{% render "loop" %}').render! + Template.parse('{% render "loop" %}', environment: env).render! end end def test_sub_contexts_count_towards_the_same_recursion_limit - Liquid::Template.file_system = StubFileSystem.new( - 'loop_render' => '{% render "loop_render" %}', + env = Liquid::Environment.build( + file_system: StubFileSystem.new('loop_render' => '{% render "loop_render" %}'), ) + assert_raises(Liquid::StackLevelError) do - Template.parse('{% render "loop_render" %}').render! + Template.parse('{% render "loop_render" %}', environment: env).render! end end diff --git a/test/test_helper.rb b/test/test_helper.rb index e5c88fb29..1ecfce3f5 100755 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -13,7 +13,7 @@ puts "-- #{env_mode.upcase} ERROR MODE" mode = env_mode.to_sym end -Liquid::Template.error_mode = mode +Liquid::Environment.default.error_mode = mode if ENV['LIQUID_C'] == '1' puts "-- LIQUID C" @@ -88,11 +88,11 @@ def with_global_filter(*globals, &blk) end def with_error_mode(mode) - old_mode = Liquid::Template.error_mode - Liquid::Template.error_mode = mode + old_mode = Liquid::Environment.default.error_mode + Liquid::Environment.default.error_mode = mode yield ensure - Liquid::Template.error_mode = old_mode + Liquid::Environment.default.error_mode = old_mode end def with_custom_tag(tag_name, tag_class, &block) diff --git a/test/unit/strainer_factory_unit_test.rb b/test/unit/environment_filter_test.rb similarity index 72% rename from test/unit/strainer_factory_unit_test.rb rename to test/unit/environment_filter_test.rb index c78d422b6..942f6a3c7 100644 --- a/test/unit/strainer_factory_unit_test.rb +++ b/test/unit/environment_filter_test.rb @@ -2,7 +2,7 @@ require 'test_helper' -class StrainerFactoryUnitTest < Minitest::Test +class EnvironmentFilterTest < Minitest::Test include Liquid module AccessScopeFilters @@ -16,8 +16,6 @@ def private_filter private :private_filter end - StrainerFactory.add_global_filter(AccessScopeFilters) - module LateAddedFilter def late_added_filter(_input) "filtered" @@ -25,24 +23,28 @@ def late_added_filter(_input) end def setup - @context = Context.build + @environment = Liquid::Environment.build do |env| + env.register_filter(AccessScopeFilters) + end + + @context = Context.build(environment: @environment) end def test_strainer - strainer = StrainerFactory.create(@context) + strainer = @environment.create_strainer(@context) assert_equal(5, strainer.invoke('size', 'input')) assert_equal("public", strainer.invoke("public_filter")) end def test_stainer_raises_argument_error - strainer = StrainerFactory.create(@context) + strainer = @environment.create_strainer(@context) assert_raises(Liquid::ArgumentError) do strainer.invoke("public_filter", 1) end end def test_stainer_argument_error_contains_backtrace - strainer = StrainerFactory.create(@context) + strainer = @environment.create_strainer(@context) exception = assert_raises(Liquid::ArgumentError) do strainer.invoke("public_filter", 1) @@ -57,7 +59,7 @@ def test_stainer_argument_error_contains_backtrace end def test_strainer_only_invokes_public_filter_methods - strainer = StrainerFactory.create(@context) + strainer = @environment.create_strainer(@context) assert_equal(false, strainer.class.invokable?('__test__')) assert_equal(false, strainer.class.invokable?('test')) assert_equal(false, strainer.class.invokable?('instance_eval')) @@ -66,18 +68,18 @@ def test_strainer_only_invokes_public_filter_methods end def test_strainer_returns_nil_if_no_filter_method_found - strainer = StrainerFactory.create(@context) + strainer = @environment.create_strainer(@context) assert_nil(strainer.invoke("private_filter")) assert_nil(strainer.invoke("undef_the_filter")) end def test_strainer_returns_first_argument_if_no_method_and_arguments_given - strainer = StrainerFactory.create(@context) + strainer = @environment.create_strainer(@context) assert_equal("password", strainer.invoke("undef_the_method", "password")) end def test_strainer_only_allows_methods_defined_in_filters - strainer = StrainerFactory.create(@context) + strainer = @environment.create_strainer(@context) assert_equal("1 + 1", strainer.invoke("instance_eval", "1 + 1")) assert_equal("puts", strainer.invoke("__send__", "puts", "Hi Mom")) assert_equal("has_method?", strainer.invoke("invoke", "has_method?", "invoke")) @@ -86,7 +88,9 @@ def test_strainer_only_allows_methods_defined_in_filters def test_strainer_uses_a_class_cache_to_avoid_method_cache_invalidation a = Module.new b = Module.new - strainer = StrainerFactory.create(@context, [a, b]) + + strainer = @environment.create_strainer(@context, [a, b]) + assert_kind_of(StrainerTemplate, strainer) assert_kind_of(a, strainer) assert_kind_of(b, strainer) @@ -94,8 +98,10 @@ def test_strainer_uses_a_class_cache_to_avoid_method_cache_invalidation end def test_add_global_filter_clears_cache - assert_equal('input', StrainerFactory.create(@context).invoke('late_added_filter', 'input')) - StrainerFactory.add_global_filter(LateAddedFilter) - assert_equal('filtered', StrainerFactory.create(nil).invoke('late_added_filter', 'input')) + assert_equal('input', @environment.create_strainer(@context).invoke('late_added_filter', 'input')) + + @environment.register_filter(LateAddedFilter) + + assert_equal('filtered', @environment.create_strainer(nil).invoke('late_added_filter', 'input')) end end diff --git a/test/unit/strainer_template_unit_test.rb b/test/unit/strainer_template_unit_test.rb index 18b9f499b..a04107084 100644 --- a/test/unit/strainer_template_unit_test.rb +++ b/test/unit/strainer_template_unit_test.rb @@ -25,11 +25,13 @@ def public_filter end def test_add_filter_raises_when_module_privately_overrides_registered_public_methods - strainer = Context.new.strainer - error = assert_raises(Liquid::MethodOverrideError) do - strainer.class.add_filter(PrivateMethodOverrideFilter) + Liquid::Environment.build do |env| + env.register_filter(PublicMethodOverrideFilter) + env.register_filter(PrivateMethodOverrideFilter) + end end + assert_equal('Liquid error: Filter overrides registered public methods as non public: public_filter', error.message) end @@ -42,11 +44,13 @@ def public_filter end def test_add_filter_raises_when_module_overrides_registered_public_method_as_protected - strainer = Context.new.strainer - error = assert_raises(Liquid::MethodOverrideError) do - strainer.class.add_filter(ProtectedMethodOverrideFilter) + Liquid::Environment.build do |env| + env.register_filter(PublicMethodOverrideFilter) + env.register_filter(ProtectedMethodOverrideFilter) + end end + assert_equal('Liquid error: Filter overrides registered public methods as non public: public_filter', error.message) end