Merge pull request #1289 from Shopify/refactor-for-c-block-body

Avoid direct coupling to BlockBody instances for liquid-c replacement
This commit is contained in:
Dylan Thacker-Smith
2020-09-11 09:15:58 -04:00
committed by GitHub
7 changed files with 75 additions and 23 deletions
+8 -2
View File
@@ -10,7 +10,7 @@ module Liquid
end end
def parse(tokens) def parse(tokens)
@body = BlockBody.new @body = new_body
while parse_body(@body, tokens) while parse_body(@body, tokens)
end end
end end
@@ -55,8 +55,14 @@ module Liquid
@block_delimiter ||= "end#{block_name}" @block_delimiter ||= "end#{block_name}"
end end
protected private
# @api public
def new_body
parse_context.new_block_body
end
# @api public
def parse_body(body, tokens) def parse_body(body, tokens)
if parse_context.depth >= MAX_DEPTH if parse_context.depth >= MAX_DEPTH
raise StackLevelError, "Nesting too deep" raise StackLevelError, "Nesting too deep"
+29 -12
View File
@@ -58,6 +58,28 @@ module Liquid
Block.raise_unknown_tag(tag, 'liquid', '%}', parse_context) Block.raise_unknown_tag(tag, 'liquid', '%}', parse_context)
end end
# @api private
def self.raise_missing_tag_terminator(token, parse_context)
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_termination", token: token, tag_end: TagEnd.inspect)
end
# @api private
def self.raise_missing_variable_terminator(token, parse_context)
raise SyntaxError, parse_context.locale.t("errors.syntax.variable_termination", token: token, tag_end: VariableEnd.inspect)
end
# @api private
def self.render_node(context, output, node)
node.render_to_output_buffer(context, output)
rescue UndefinedVariable, UndefinedDropMethod, UndefinedFilter => e
context.handle_error(e, node.line_number)
rescue MemoryError
raise
rescue ::StandardError => e
line_number = node.is_a?(String) ? nil : node.line_number
output << context.handle_error(e, line_number)
end
private def parse_liquid_tag(markup, parse_context) private def parse_liquid_tag(markup, parse_context)
liquid_tag_tokenizer = Tokenizer.new(markup, line_number: parse_context.line_number, for_liquid_tag: true) liquid_tag_tokenizer = Tokenizer.new(markup, line_number: parse_context.line_number, for_liquid_tag: true)
parse_for_liquid_tag(liquid_tag_tokenizer, parse_context) do |end_tag_name, _end_tag_markup| parse_for_liquid_tag(liquid_tag_tokenizer, parse_context) do |end_tag_name, _end_tag_markup|
@@ -74,7 +96,7 @@ module Liquid
when token.start_with?(TAGSTART) when token.start_with?(TAGSTART)
whitespace_handler(token, parse_context) whitespace_handler(token, parse_context)
unless token =~ FullToken unless token =~ FullToken
raise_missing_tag_terminator(token, parse_context) BlockBody.raise_missing_tag_terminator(token, parse_context)
end end
tag_name = Regexp.last_match(2) tag_name = Regexp.last_match(2)
markup = Regexp.last_match(4) markup = Regexp.last_match(4)
@@ -179,14 +201,7 @@ module Liquid
private private
def render_node(context, output, node) def render_node(context, output, node)
node.render_to_output_buffer(context, output) BlockBody.render_node(context, output, node)
rescue UndefinedVariable, UndefinedDropMethod, UndefinedFilter => e
context.handle_error(e, node.line_number)
rescue MemoryError
raise
rescue ::StandardError => e
line_number = node.is_a?(String) ? nil : node.line_number
output << context.handle_error(e, line_number)
end end
def create_variable(token, parse_context) def create_variable(token, parse_context)
@@ -194,15 +209,17 @@ module Liquid
markup = content.first markup = content.first
return Variable.new(markup, parse_context) return Variable.new(markup, parse_context)
end end
raise_missing_variable_terminator(token, parse_context) BlockBody.raise_missing_variable_terminator(token, parse_context)
end end
# @deprecated Use {.raise_missing_tag_terminator} instead
def raise_missing_tag_terminator(token, parse_context) def raise_missing_tag_terminator(token, parse_context)
raise SyntaxError, parse_context.locale.t("errors.syntax.tag_termination", token: token, tag_end: TagEnd.inspect) BlockBody.raise_missing_tag_terminator(token, parse_context)
end end
# @deprecated Use {.raise_missing_variable_terminator} instead
def raise_missing_variable_terminator(token, parse_context) def raise_missing_variable_terminator(token, parse_context)
raise SyntaxError, parse_context.locale.t("errors.syntax.variable_termination", token: token, tag_end: VariableEnd.inspect) BlockBody.raise_missing_variable_terminator(token, parse_context)
end end
def registered_tags def registered_tags
+28 -3
View File
@@ -1,15 +1,26 @@
# frozen_string_literal: true # frozen_string_literal: true
module Liquid module Liquid
class Document < BlockBody class Document
def self.parse(tokens, parse_context) def self.parse(tokens, parse_context)
doc = new doc = new(parse_context)
doc.parse(tokens, parse_context) doc.parse(tokens, parse_context)
doc doc
end end
attr_reader :parse_context, :body
def initialize(parse_context)
@parse_context = parse_context
@body = new_body
end
def nodelist
@body.nodelist
end
def parse(tokens, parse_context) def parse(tokens, parse_context)
super do |end_tag_name, _end_tag_params| @body.parse(tokens, parse_context) do |end_tag_name, _end_tag_params|
unknown_tag(end_tag_name, parse_context) if end_tag_name unknown_tag(end_tag_name, parse_context) if end_tag_name
end end
rescue SyntaxError => e rescue SyntaxError => e
@@ -25,5 +36,19 @@ module Liquid
raise SyntaxError, parse_context.locale.t("errors.syntax.unknown_tag", tag: tag) raise SyntaxError, parse_context.locale.t("errors.syntax.unknown_tag", tag: tag)
end end
end end
def render_to_output_buffer(context, output)
@body.render_to_output_buffer(context, output)
end
def render(context)
@body.render(context)
end
private
def new_body
parse_context.new_block_body
end
end end
end end
+4
View File
@@ -19,6 +19,10 @@ module Liquid
@options[option_key] @options[option_key]
end end
def new_block_body
Liquid::BlockBody.new
end
def partial=(value) def partial=(value)
@partial = value @partial = value
@options = value ? partial_options : @template_options @options = value ? partial_options : @template_options
+3 -3
View File
@@ -19,7 +19,7 @@ module Liquid
end end
def parse(tokens) def parse(tokens)
body = BlockBody.new body = new_body
body = @blocks.last.attachment while parse_body(body, tokens) body = @blocks.last.attachment while parse_body(body, tokens)
if blank? if blank?
@blocks.each { |condition| condition.attachment.remove_blank_strings } @blocks.each { |condition| condition.attachment.remove_blank_strings }
@@ -59,7 +59,7 @@ module Liquid
private private
def record_when_condition(markup) def record_when_condition(markup)
body = BlockBody.new body = new_body
while markup while markup
unless markup =~ WhenSyntax unless markup =~ WhenSyntax
@@ -80,7 +80,7 @@ module Liquid
end end
block = ElseCondition.new block = ElseCondition.new
block.attach(BlockBody.new) block.attach(new_body)
@blocks << block @blocks << block
end end
+2 -2
View File
@@ -54,7 +54,7 @@ module Liquid
super super
@from = @limit = nil @from = @limit = nil
parse_with_selected_parser(markup) parse_with_selected_parser(markup)
@for_block = BlockBody.new @for_block = new_body
@else_block = nil @else_block = nil
end end
@@ -74,7 +74,7 @@ module Liquid
def unknown_tag(tag, markup, tokens) def unknown_tag(tag, markup, tokens)
return super unless tag == 'else' return super unless tag == 'else'
@else_block = BlockBody.new @else_block = new_body
end end
def render_to_output_buffer(context, output) def render_to_output_buffer(context, output)
+1 -1
View File
@@ -64,7 +64,7 @@ module Liquid
end end
@blocks.push(block) @blocks.push(block)
block.attach(BlockBody.new) block.attach(new_body)
end end
def lax_parse(markup) def lax_parse(markup)