Remove mutable render state from Liquid::Template

Use Liquid::Context to access this mutable state after rendering or to have
state that is persisted between mutations
This commit is contained in:
Dylan Thacker-Smith
2020-08-18 10:04:41 -04:00
parent a1d982ca76
commit 219168e89f
6 changed files with 169 additions and 212 deletions
+28 -51
View File
@@ -16,7 +16,7 @@ module Liquid
#
class Template
attr_accessor :root
attr_reader :resource_limits, :warnings
attr_reader :warnings
class TagRegistry
include Enumerable
@@ -106,11 +106,6 @@ module Liquid
end
end
def initialize
@rethrow_errors = false
@resource_limits = ResourceLimits.new(Template.default_resource_limits)
end
# Parse source code.
# Returns self for easy chaining
def parse(source, options = {})
@@ -123,22 +118,6 @@ module Liquid
self
end
def registers
@registers ||= {}
end
def assigns
@assigns ||= {}
end
def instance_assigns
@instance_assigns ||= {}
end
def errors
@errors ||= []
end
# Render takes a hash with local variables.
#
# if you use the same filters over and over again consider registering them globally
@@ -153,37 +132,18 @@ module Liquid
# * <tt>registers</tt> : hash with register variables. Those can be accessed from
# filters and tags and might be useful to integrate liquid more with its host application
#
def render(*args)
def render(assigns_or_context = nil, options = nil)
return '' if @root.nil?
context = case args.first
when Liquid::Context
c = args.shift
if @rethrow_errors
c.exception_renderer = ->(_e) { raise }
end
c
when Liquid::Drop
drop = args.shift
drop.context = Context.new([drop, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits)
when Hash
Context.new([args.shift, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits)
when nil
Context.new(assigns, instance_assigns, registers, @rethrow_errors, @resource_limits)
else
raise ArgumentError, "Expected Hash or Liquid::Context as parameter"
end
context = coerce_context(assigns_or_context)
output = nil
context_register = context.registers.is_a?(StaticRegisters) ? context.registers.static : context.registers
case args.last
case options
when Hash
options = args.pop
output = options[:output] if options[:output]
output = options[:output] if options[:output]
options[:registers]&.each do |key, register|
context_register[key] = register
@@ -191,7 +151,7 @@ module Liquid
apply_options_to_context(context, options)
when Module, Array
context.add_filters(args.pop)
context.add_filters(options)
end
Template.registers.each do |key, register|
@@ -209,14 +169,15 @@ module Liquid
end
rescue Liquid::MemoryError => e
context.handle_error(e)
ensure
@errors = context.errors
end
end
def render!(*args)
@rethrow_errors = true
render(*args)
def render!(assigns_or_context = nil, options = nil)
context = coerce_context(assigns_or_context)
# rethrow errors
context.exception_renderer = ->(_e) { raise }
render(context, options)
end
def render_to_output_buffer(context, output)
@@ -225,6 +186,22 @@ module Liquid
private
def coerce_context(assigns_or_context)
case assigns_or_context
when Liquid::Context
assigns_or_context
when Liquid::Drop
drop = assigns_or_context
drop.context = Context.build(environments: [drop])
when Hash
Context.build(environments: [assigns_or_context])
when nil
Context.build
else
raise ArgumentError, "Expected Hash or Liquid::Context as parameter"
end
end
def tokenize(source)
Tokenizer.new(source, @line_numbers)
end