mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-18 10:20:43 -07:00
Move resource limit tracking to its own class
This commit is contained in:
@@ -63,6 +63,7 @@ require 'liquid/variable'
|
||||
require 'liquid/variable_lookup'
|
||||
require 'liquid/range_lookup'
|
||||
require 'liquid/file_system'
|
||||
require 'liquid/resource_limits'
|
||||
require 'liquid/template'
|
||||
require 'liquid/standardfilters'
|
||||
require 'liquid/condition'
|
||||
|
||||
@@ -69,8 +69,8 @@ module Liquid
|
||||
|
||||
def render(context)
|
||||
output = []
|
||||
context.resource_limits[:render_length_current] = 0
|
||||
context.resource_limits[:render_score_current] += @nodelist.length
|
||||
context.resource_limits.render_length = 0
|
||||
context.resource_limits.render_score += @nodelist.length
|
||||
|
||||
@nodelist.each do |token|
|
||||
# Break out if we have any unhanded interrupts.
|
||||
@@ -104,9 +104,8 @@ module Liquid
|
||||
|
||||
def render_token(token, context)
|
||||
token_output = (token.respond_to?(:render) ? token.render(context) : token)
|
||||
context.increment_used_resources(:render_length_current, token_output)
|
||||
if context.resource_limits_reached?
|
||||
context.resource_limits[:reached] = true
|
||||
context.resource_limits.increment_render_length(token_output)
|
||||
if context.resource_limits.reached?
|
||||
raise MemoryError.new("Memory limits exceeded".freeze)
|
||||
end
|
||||
token_output
|
||||
|
||||
+6
-17
@@ -21,9 +21,12 @@ module Liquid
|
||||
@scopes = [(outer_scope || {})]
|
||||
@registers = registers
|
||||
@errors = []
|
||||
@resource_limits = resource_limits || Template.default_resource_limits.dup
|
||||
@resource_limits[:render_score_current] = 0
|
||||
@resource_limits[:assign_score_current] = 0
|
||||
|
||||
@resource_limits = if resource_limits.is_a?(ResourceLimits)
|
||||
resource_limits
|
||||
else
|
||||
ResourceLimits.new(resource_limits || Template.default_resource_limits)
|
||||
end
|
||||
squash_instance_assigns_with_environments
|
||||
|
||||
@this_stack_used = false
|
||||
@@ -36,20 +39,6 @@ module Liquid
|
||||
@filters = []
|
||||
end
|
||||
|
||||
def increment_used_resources(key, obj)
|
||||
@resource_limits[key] += if obj.kind_of?(String) || obj.kind_of?(Array) || obj.kind_of?(Hash)
|
||||
obj.length
|
||||
else
|
||||
1
|
||||
end
|
||||
end
|
||||
|
||||
def resource_limits_reached?
|
||||
(@resource_limits[:render_length_limit] && @resource_limits[:render_length_current] > @resource_limits[:render_length_limit]) ||
|
||||
(@resource_limits[:render_score_limit] && @resource_limits[:render_score_current] > @resource_limits[:render_score_limit] ) ||
|
||||
(@resource_limits[:assign_score_limit] && @resource_limits[:assign_score_current] > @resource_limits[:assign_score_limit] )
|
||||
end
|
||||
|
||||
def strainer
|
||||
@strainer ||= Strainer.create(self, @filters)
|
||||
end
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
module Liquid
|
||||
class ResourceLimits
|
||||
attr_accessor :render_length, :render_score, :assign_score,
|
||||
:render_length_limit, :render_score_limit, :assign_score_limit
|
||||
|
||||
def initialize(limits)
|
||||
@render_length_limit = limits[:render_length_limit]
|
||||
@render_score_limit = limits[:render_score_limit]
|
||||
@assign_score_limit = limits[:assign_score_limit]
|
||||
|
||||
# render_length is assigned by BlockBody
|
||||
# @render_length = 0
|
||||
@render_score = 0
|
||||
@assign_score = 0
|
||||
end
|
||||
|
||||
def reached?
|
||||
(@render_length_limit && @render_length > @render_length_limit) ||
|
||||
(@render_score_limit && @render_score > @render_score_limit ) ||
|
||||
(@assign_score_limit && @assign_score > @assign_score_limit )
|
||||
end
|
||||
|
||||
def increment_render_length(obj)
|
||||
@render_length += increment_for(obj)
|
||||
end
|
||||
|
||||
def increment_render_score(obj)
|
||||
@render_score += increment_for(obj)
|
||||
end
|
||||
|
||||
def increment_assign_score(obj)
|
||||
@assign_score += increment_for(obj)
|
||||
end
|
||||
|
||||
private
|
||||
def increment_for(obj)
|
||||
obj.instance_of?(String) || obj.instance_of?(Array) || obj.instance_of?(Hash) ? obj.length : 1
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -25,7 +25,7 @@ module Liquid
|
||||
def render(context)
|
||||
val = @from.render(context)
|
||||
context.scopes.last[@to] = val
|
||||
context.increment_used_resources(:assign_score_current, val)
|
||||
context.resource_limits.increment_assign_score(val)
|
||||
''.freeze
|
||||
end
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ module Liquid
|
||||
def render(context)
|
||||
output = super
|
||||
context.scopes.last[@to] = output
|
||||
context.increment_used_resources(:assign_score_current, output)
|
||||
context.resource_limits.increment_assign_score(output)
|
||||
''.freeze
|
||||
end
|
||||
|
||||
|
||||
@@ -18,7 +18,13 @@ module Liquid
|
||||
:locale => I18n.new
|
||||
}
|
||||
|
||||
attr_accessor :root, :resource_limits
|
||||
attr_accessor :root
|
||||
attr_reader :resource_limits
|
||||
|
||||
def resource_limits=(limits)
|
||||
@resource_limits = ResourceLimits.new(limits)
|
||||
end
|
||||
|
||||
@@file_system = BlankFileSystem.new
|
||||
|
||||
class TagRegistry
|
||||
@@ -110,7 +116,7 @@ module Liquid
|
||||
end
|
||||
|
||||
def initialize
|
||||
@resource_limits = self.class.default_resource_limits.dup
|
||||
self.resource_limits = self.class.default_resource_limits
|
||||
end
|
||||
|
||||
# Parse source code.
|
||||
|
||||
Reference in New Issue
Block a user