Shopify / liquid

Liquid markup language. Safe, customer facing template language for flexible web apps.

Home Page:https://shopify.github.io/liquid/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Templates that use `assign` / `capture` tags are thread-unsafe

UlyssesZh opened this issue · comments

require 'liquid'
Liquid::Template.register_filter Module.new { def s(input) = sleep(input/10.0) && input }
template = Liquid::Template.parse '{% assign u = v %}{{ u | s }}{{ u }}'
3.times.map { |i| Thread.new { print template.render! 'v' => i } }.each &:join

Expected output: 001122; Actual output: 021222.

Why I found this: jekyll/jekyll#9485 (comment)

This actually would be super interesting to solve! +100000

I think this happens because certain state for a Liquid::Context will be re-used when a hash passed in to Liquid::Template#render. If you want to avoid that behavior, it is best to explicitly create a new Liquid::Context for each render invocation, i.e.:

template.render!(Liquid::Context.new("v" => i))