mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-16 01:10:41 -07:00
avoid array allocation in parse_tag_token: return tag_name, store markup/newlines as class ivars
This commit is contained in:
+20
-11
@@ -16,8 +16,13 @@ module Liquid
|
|||||||
# Parses "{%[-] tag_name markup [-]%}" and returns [pre_ws, tag_name, post_ws, markup] or nil
|
# Parses "{%[-] tag_name markup [-]%}" and returns [pre_ws, tag_name, post_ws, markup] or nil
|
||||||
NEWLINE_BYTE = 10 # "\n".ord
|
NEWLINE_BYTE = 10 # "\n".ord
|
||||||
|
|
||||||
|
class << self
|
||||||
|
attr_reader :_last_markup, :_last_newlines
|
||||||
|
end
|
||||||
|
|
||||||
# Fast manual tag token parser - avoids regex MatchData allocation
|
# Fast manual tag token parser - avoids regex MatchData allocation
|
||||||
# Parses "{%[-] tag_name markup [-]%}" and returns [tag_name, markup, newline_count] or nil
|
# Parses "{%[-] tag_name markup [-]%}" directly into parse_context fields
|
||||||
|
# Returns tag_name string or nil on failure. Sets @_tag_markup and @_tag_newlines.
|
||||||
def self.parse_tag_token(token)
|
def self.parse_tag_token(token)
|
||||||
# token starts with "{%"
|
# token starts with "{%"
|
||||||
pos = 2
|
pos = 2
|
||||||
@@ -47,11 +52,11 @@ module Liquid
|
|||||||
else
|
else
|
||||||
while pos < len
|
while pos < len
|
||||||
b = token.getbyte(pos)
|
b = token.getbyte(pos)
|
||||||
break unless (b >= 97 && b <= 122) || (b >= 65 && b <= 90) || (b >= 48 && b <= 57) || b == 95 # a-z, A-Z, 0-9, _
|
break unless (b >= 97 && b <= 122) || (b >= 65 && b <= 90) || (b >= 48 && b <= 57) || b == 95
|
||||||
pos += 1
|
pos += 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return nil if pos == name_start # no tag name found
|
return nil if pos == name_start
|
||||||
tag_name = token.byteslice(name_start, pos - name_start)
|
tag_name = token.byteslice(name_start, pos - name_start)
|
||||||
|
|
||||||
# skip post-whitespace, counting newlines
|
# skip post-whitespace, counting newlines
|
||||||
@@ -68,12 +73,15 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
# the rest is markup, up to optional '-' and '%}'
|
# the rest is markup, up to optional '-' and '%}'
|
||||||
# token ends with '%}' (guaranteed by tokenizer)
|
|
||||||
markup_end = len - 2
|
markup_end = len - 2
|
||||||
markup_end -= 1 if markup_end > pos && token.getbyte(markup_end - 1) == 45 # trailing '-'
|
markup_end -= 1 if markup_end > pos && token.getbyte(markup_end - 1) == 45
|
||||||
markup = pos >= markup_end ? "" : token.byteslice(pos, markup_end - pos)
|
markup = pos >= markup_end ? "" : token.byteslice(pos, markup_end - pos)
|
||||||
|
|
||||||
[tag_name, markup, newlines]
|
# Store extra results to avoid array allocation for the return value
|
||||||
|
@_last_markup = markup
|
||||||
|
@_last_newlines = newlines
|
||||||
|
|
||||||
|
tag_name
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :nodelist
|
attr_reader :nodelist
|
||||||
@@ -200,14 +208,15 @@ module Liquid
|
|||||||
second_byte = token.getbyte(1)
|
second_byte = token.getbyte(1)
|
||||||
if second_byte == PERCENT_BYTE
|
if second_byte == PERCENT_BYTE
|
||||||
whitespace_handler(token, parse_context)
|
whitespace_handler(token, parse_context)
|
||||||
parsed = BlockBody.parse_tag_token(token)
|
tag_name = BlockBody.parse_tag_token(token)
|
||||||
unless parsed
|
unless tag_name
|
||||||
return handle_invalid_tag_token(token, parse_context, &block)
|
return handle_invalid_tag_token(token, parse_context, &block)
|
||||||
end
|
end
|
||||||
tag_name, markup, newlines = parsed
|
markup = BlockBody._last_markup
|
||||||
|
|
||||||
if parse_context.line_number && newlines > 0
|
if parse_context.line_number
|
||||||
parse_context.line_number += newlines
|
newlines = BlockBody._last_newlines
|
||||||
|
parse_context.line_number += newlines if newlines > 0
|
||||||
end
|
end
|
||||||
|
|
||||||
if tag_name == 'liquid'
|
if tag_name == 'liquid'
|
||||||
|
|||||||
Reference in New Issue
Block a user