Shopify / Shopify/liquid

Hash registers leaking into subcontexts as static registers

Open
#1,564 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Ruby
Stars
11.9k
Forks
1.5k
Avg merge
17h 55m
Merged PRs (30d)
3

Description

Here is an example that shows the problem:

require 'liquid'

template_code = <<~LIQUID
  {% render 'snippet' %}
LIQUID

module FakeFS
  def self.read_template_file(template_path)
    case template_path
    when 'snippet'
      <<~LIQUID
        In snippet:
        {% cycle "colors": 'red', 'green', 'blue' %}
        {% render 'subsnippet' %}
      LIQUID
    when 'subsnippet'
      <<~LIQUID
        In subsnippet:
        {% cycle "colors": 'red', 'green', 'blue' %}
      LIQUID
    end
  end
end

Liquid::Template.file_system = FakeFS

puts Liquid::Template.parse(<<~LIQUID).render.strip
  template 1:
  {% render 'snippet' %}
LIQUID
puts
puts Liquid::Template.parse(<<~LIQUID).render.strip
  template 2:
  {% cycle "colors": 'red', 'green', 'blue' %}
  {% render 'snippet' %}
LIQUID

which outputs

template 1:
In snippet:
red
In subsnippet:
red

template 2:
red
In snippet:
green
In subsnippet:
blue

where for template 1 you can see that the :cycle register isn't shared for the nested render, as expected, but this isn't the case for template 2. For template 2, the :cycle register gets set by the cycle tag in the template, then the snippets are inheriting that register as a static register.

The output I would expect would be

template 1:
In snippet:
red
In subsnippet:
red

template 2:
red
In snippet:
red
In subsnippet:
red

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the issue through Liquid::Template.parse and render, using the cycle and render tags shown in the example. Trace how cycle registers are created for the outer template and inherited by nested renders. Done means template 2 produces red for both nested cycles, while template 1 retains its existing output; add regression coverage for both cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.