Commit Graph
1130 Commits
Author SHA1 Message Date
Tobi LutkeandChris Pak 50888426a1 fast-path find_variable: check top scope first before find_index 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 1a29584f96 add invoke_single fast path for no-arg filter invocation, avoids splat alloc 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 9d16eb3d05 fast-path simple if truthiness: use byte scanner before SIMPLE_CONDITION regex 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 34971c0314 replace WhitespaceOrNothing regex with byte-level blank_string? check 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak f24ca042a2 avoid array allocation in parse_tag_token: return tag_name, store markup/newlines as class ivars 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 4ea4350775 clean up filter parsing: Lexer fallback for args, no-arg fast scan stays 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 808dad6fab split filter parsing: scan no-arg filters directly, only invoke Lexer when args present 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak b994f22983 extend fast-path to handle quoted string literal variables (262 more fast-pathed) 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 62877e666c skip filter arg splat for no-arg filters, trim render loop comments 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 48a2fae5f6 hoist write score check out of render loop: skip increment_write_score when no limits active 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 27fcb3a4c9 use frozen EMPTY_ARRAY for disabled_tags in Variable 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak 6e9782c5cc return [tag_name, markup, newlines] from parse_tag_token: avoid 2 whitespace string allocs 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak da57336be9 use getbyte dispatch instead of start_with? in parse_for_document 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak 28f29433e4 avoid empty array allocation in evaluate_filter_expressions for no-arg filters 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak 4ff5523713 replace For tag Syntax regex with manual byte-level parser 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak f388c873de expose expression_cache/string_scanner via attr_reader, skip regex in filter args without colon 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak 543c1e1fe7 unified fast-path Variable parsing: handle both plain lookups and filter chains without full Lexer pass for name 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak 885c8df159 fast-path render for filter-less variables: skip render method overhead 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak 8f67d81023 skip TagAttributes scan in for tag when no colon present 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak 01f33e96e8 fast-path simple if conditions: skip ExpressionsAndOperators scan for single conditions 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak 9e6f93a494 replace SIMPLE_VARIABLE regex with byte-level scanner to avoid MatchData 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak dc6e9799e9 fast-path simple variable parsing: skip Lexer/Parser for plain dot-separated lookups 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak 98e29aa4a7 use frozen EMPTY_ARRAY for Variable filters when no filters present 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak a404cf10d0 fast-path variable_lookups: skip mutable string alloc when no dot/bracket follows 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak e73b41f3b6 fast-path String in render_obj_to_output, avoid Utils.to_s dispatch for common case 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak 9d9d094e20 short-circuit parse_number with first-byte check before regex 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak 4c96b5f682 avoid unnecessary strip allocation in Expression.parse, use byteslice for string literals 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak 0b19c0ce44 use equal? for frozen array comparison in Lexer, skip whitespace with \s+ 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak a43d970473 use getbyte instead of string indexing in whitespace_handler and create_variable 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak 6ffd0e2339 replace VariableParser regex scan with manual byte parser in VariableLookup 2026-04-04 17:33:53 -07:00
Tobi LutkeandChris Pak dc7dda2253 replace FullToken regex with manual byte parsing in parse_for_document 2026-04-04 17:33:53 -07:00
Benoit Daloze d824de701c Adapt slice filter to work on non-64 bit platforms 2026-03-25 16:46:47 +01:00
Ian Ker-SeymerandGitHub 59d8d0d22d Add cumulative resource score tracking across partial renders (#2058)
* feat: add cumulative resource score tracking across partial renders

Add cumulative_render_score and cumulative_assign_score counters to
ResourceLimits that accumulate across reset() calls, with optional
cumulative_render_score_limit and cumulative_assign_score_limit to
cap total work across all partial renders.

Also add a reached? check in BlockBody's render loop so that once a
cumulative limit triggers, the parent template stops processing
further nodes.

Bump version to 5.12.0.

* refactor: move cumulative limit enforcement into reset()

Instead of checking reached? in BlockBody's render loop, enforce
cumulative limits in reset() itself. Since reset() is called before
the begin/rescue MemoryError block in Template#render, the raise
propagates to the parent naturally — no changes to BlockBody needed.
2026-03-18 11:54:46 -04:00
Michaël Gallego d589c51697 Add squish filter 2026-02-19 10:03:52 +09:00
Tobi LutkeandClaude Opus 4.5 ccd05e869c Make blank/empty comparisons invariant to ActiveSupport
- Implement liquid_blank? and liquid_empty? methods in Condition
  to emulate ActiveSupport's behavior when it's not loaded
- This ensures templates like `{% if x == blank %}` work identically
  whether ActiveSupport is loaded or not
- Update liquid-spec adapters for new API (ctx parameter)
- Add rake spec task for running liquid-spec matrix

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
2026-01-05 14:54:43 -10:00
Tobi Lutke ef13b2dfd5 Fix empty? semantics and string first/last for empty strings
- nil is NOT empty (but IS blank) - matches Shopify production
- String first/last returns '' for empty strings, not nil - matches ActiveSupport
- Add test for nil not being empty
2026-01-01 22:06:22 -05:00
Tobi Lutke af58800c16 Update rubocop-shopify to 2.18.0 and fix new offenses 2026-01-01 20:22:19 -05:00
Tobi Lutke 361d1d52b1 Fix rubocop offenses from 1.82 upgrade 2026-01-01 20:20:50 -05:00
Tobi Lutke 0e3548d39e Remove redundant else-clause 2026-01-01 20:16:24 -05:00
Tobi Lutke 33bac87a5c Address liquid-spec issues without ActiveSupport loaded
Implement ActiveSupport-compatible behaviors internally so Liquid works
correctly without ActiveSupport being loaded:

1. String first/last via property access (name.first, name.last)
   - VariableLookup now handles string[0] and string[-1] for first/last

2. String first/last via filters (name | first, name | last)
   - StandardFilters#first and #last now handle strings

3. blank?/empty? comparisons for types without these methods
   - Condition now implements liquid_blank? and liquid_empty? internally
   - blank? matches ActiveSupport: nil, false, empty/whitespace strings,
     empty arrays/hashes are all blank
   - empty? checks length == 0 only (whitespace is NOT empty)

This fixes spec failures for templates like:
- {{ name.first }} / {{ name | first }} on strings
- {% if x == blank %} for whitespace strings, empty hashes/arrays
- {% case ' ' %}{% when blank %} matching whitespace
2026-01-01 20:14:21 -05:00
Ian Ker-SeymerandGitHub 22e979a6fa Use floating-point format for BigDecimal stringification (#2022)
## Summary

- BigDecimal values now stringify using `to_s("F")` format instead of the default `to_s`

## Why

Ruby's default `BigDecimal#to_s` produces engineering/scientific notation for certain values:

```ruby
BigDecimal("0.00001").to_s      # => "0.1E-4"
BigDecimal("12345678.9").to_s   # => "0.123456789E8"
```

This is rarely the desired output in templates. Using `to_s("F")` produces the expected floating-point format:

```ruby
BigDecimal("0.00001").to_s("F")      # => "0.00001"
BigDecimal("12345678.9").to_s("F")   # => "12345678.9"
```
2025-12-05 15:54:52 -05:00
Julia Boutin fa27bfe6e0 Preserve literal semantics in strict2 case/when
Previously, strict2 case/when used `safe_parse_expression`
to parse when expressions causing `blank`/`empty` to be
treated as string literals (Expression::LITERALS maps 'empty' => ''),
rather than method literals

This caused unexpected behavior:

```
{%- case empty_obj -%}
{%- when empty -%}
  previously: doesn't render (empty_obj == '' is false)
  now: renders (empty_obj.empty? is true)
{%- endcase -%}
```

This commit instead calls `Condition.parse_expression`
with `safe: true`, which will correctly handle `blank`
and `empty`
2025-11-28 15:51:48 -07:00
Guilherme CarreiroandGitHub 32b50ecafe Bump Liquid to 5.11.0 (#2012)
This commit reverts the Inline Snippets tag (#2001) and bumps
Liquid to 5.11. For now, the inclusion of Inline Snippets
in the latest Liquid release is being treated as a bug.

While #2001 does implement the scope contained in RFC#1916,
we need to take a step back to make sure we’re setting our
sights high enough with this feature, and that we’re truly
supporting theme developers in the ways they need.

If you have any feedback, please leave a comment on RFC#1916.

- Liquid Developer Tools
2025-11-19 18:03:23 +01:00
Gray Gilmore 9973f3399e Don't raise if no variable found when using context.key?
Previously if you set `strict_variables` to `true` on the context using
`key?('key_name')` would raise a `Liquid::UndefinedVariable` error.
Raising this error makes sense if you're trying to access the variable
directly with something like  `context['key_name']` but by using `key?`
you're safely checking if it exists first.

You should be able to enable `strict_variables` and use `key?` in
combination with each other to ensure code safety.
2025-10-30 15:33:07 -07:00
Guilherme CarreiroandGuilherme Carreiro 248f3a412f Bump to 5.10.0 2025-10-30 12:28:52 +01:00
Guilherme CarreiroandGuilherme Carreiro a16ec56a40 Update error handling for keeping backward-compatibility on error messages in the render tag 2025-10-30 12:00:44 +01:00
Julia BoutinandGuilherme Carreiro 12fd93fbe2 Missing inline snippets should display same error as filebased 2025-10-30 12:00:44 +01:00
Julia BoutinandGuilherme Carreiro 5ceb0e9cec Raise error on invalid snippet name 2025-10-30 12:00:44 +01:00
Julia BoutinandGuilherme Carreiro 98fbd985d8 Remove unneeded read method 2025-10-30 12:00:44 +01:00
Julia BoutinandGuilherme Carreiro ae05ba071c Add liquid_public_docs yard tag to snippet tag 2025-10-30 12:00:44 +01:00