Commit Graph
100 Commits
Author SHA1 Message Date
Tobi LutkeandChris Pak 2da3ae330a Cache block_delimiter strings per tag name — avoids repeated string interpolation\n\nResult: {"status":"keep","combined_µs":4372,"parse_µs":3127,"render_µs":1245,"allocations":25605} 2026-04-04 17:42:33 -07:00
Tobi LutkeandChris Pak 1800cffd3b Lazy Context init: defer StringScanner and @interrupts array allocation until needed\n\nResult: {"status":"keep","combined_µs":4299,"parse_µs":3057,"render_µs":1242,"allocations":26015} 2026-04-04 17:42:33 -07:00
Tobi LutkeandChris Pak 02764d28f7 Cache small integer to_s (0-999): avoids 267 Integer#to_s allocations per render cycle\n\nResult: {"status":"keep","combined_µs":4158,"parse_µs":2920,"render_µs":1238,"allocations":26128} 2026-04-04 17:42:33 -07:00
Tobi LutkeandChris Pak f08fe63042 Replace split+join in truncatewords with manual word scan — avoids array + string allocations\n\nResult: {"status":"keep","combined_µs":4280,"parse_µs":3009,"render_µs":1271,"allocations":26395} 2026-04-04 17:42:33 -07:00
Tobi LutkeandChris Pak 588966fd1c Extend fast-path filter parsing to handle comma-separated multi-arg filters (e.g. pluralize: 'item', 'items')\n\nResult: {"status":"keep","combined_µs":4266,"parse_µs":3032,"render_µs":1234,"allocations":26480} 2026-04-04 17:42:33 -07:00
Tobi LutkeandChris Pak 0e5edcc9da Avoid expr_markup byteslice when name is entire markup string (no whitespace, no filters)\n\nResult: {"status":"keep","combined_µs":4277,"parse_µs":3057,"render_µs":1220,"allocations":27026} 2026-04-04 17:42:33 -07:00
Tobi LutkeandChris Pak 3f10ac702c Fast-path single-arg filter parsing: handle quoted strings, numbers, identifiers without Lexer/Parser\n\nResult: {"status":"keep","combined_µs":4427,"parse_µs":3181,"render_µs":1246,"allocations":27235} 2026-04-04 17:42:33 -07:00
Tobi LutkeandChris Pak f31930555e fix rubocop offenses: autocorrect style/layout violations 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak f0ac941ac6 update autoresearch.md with full progress log 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 19bf49c116 For tag: migrate lax_parse to Cursor with zero-alloc skip_id/expect_id 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 5204033588 Cursor: add skip_id, expect_id, skip_fragment for zero-alloc scanning 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak b0c9f576af REVERTED: Cursor for For tag adds 148 allocs from scan_id/scan_fragment string creation\n\nResult: {"status":"discard","combined_µs":5049,"parse_us":3765,"render_us":1284,"allocations":29793,"parse_µs":3765,"render_µs":1284} 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 343ae1da56 remove dead BlockBody.parse_tag_token and If SIMPLE_CONDITION - now in Cursor 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak f42593dc50 introduce Cursor class: centralize byte-level scanning for tag/variable/condition parsing 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 80edd212a0 add parse_simple to skip simple_lookup? check when caller validates 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 65d7568403 fast-path VariableLookup init: skip scan_variable for simple identifier chains 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak c2ba6b0676 avoid allocating seen={} hash in Utils.to_s/inspect when not needed 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 92ca381fb1 update autoresearch.sh: 3-run best-of, skip liquid-spec for speed 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 1032d57532 optimize Context init: avoid unnecessary array wrapping for environments 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak e1a0e7e716 use frozen EMPTY_ARRAY/EMPTY_HASH for Context @filters/@disabled_tags 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 1f309b19a7 replace INTEGER_REGEX/FLOAT_REGEX with byte-level parse_number 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak c6617accc5 replace SIMPLE_CONDITION regex with manual byte parser in if/elsif lax_parse 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak cf062e1da2 fast-path slice_collection: skip copy for full Array without offset/limit 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak 06a718cd69 add invoke_two fast path for single-arg filter invocation, avoids splat chain 2026-04-04 17:42:32 -07:00
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 f879183a23 update autoresearch.md progress log 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 aedd2dded6 autoresearch.md: add strategic direction toward single-pass scanner architecture 2026-04-04 17:42:32 -07:00
Tobi LutkeandChris Pak e1f363c72c add security constraint to autoresearch.md, fix strict mode gate 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 c82b6e58ef autoresearch: add autoresearch.md/sh, increase benchmark warmup to 20 iterations 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 3751f95da2 add auto/bench.sh: unit tests + liquid-spec + perf benchmark 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
Tobi LutkeandChris Pak 2479b26f5c add quick benchmark script for autoresearch 2026-04-04 17:33:53 -07:00
Tobi LutkeandClaude Opus 4.5 eaa9f215bf Add lax and YJIT liquid-spec adapters
- ruby_liquid_lax.rb: Tests lax parsing mode with :lax_parsing feature
- ruby_liquid_yjit.rb: Tests YJIT + strict mode + ActiveSupport

Matrix results: 4483 matched, 18 different (lax edge cases), 61 skipped

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
2026-01-05 15:11:29 -10: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
Tobias LütkeandGitHub a4a29f3e08 Merge pull request #2034 from Shopify/fix-liquid-spec-without-activesupport
Require liquid-spec to be run on commit automatically and related fixes
2026-01-01 22:32:38 -05:00
Tobi Lutke 0058e4322b Add fail-fast: false to prevent job cancellation 2026-01-01 22:30:14 -05:00
Tobi Lutke 50e1789537 Use liquid-spec feature branch until PR is merged 2026-01-01 22:29:32 -05:00
Tobi Lutke 79a2e042ff Use liquid-spec main branch 2026-01-01 22:24:00 -05:00
Tobi Lutke ddee08fb95 Add activesupport feature to with_active_support adapter
Both adapters now pass with 0 failures:
- ruby_liquid.rb: 4194 passed (skips activesupport and shopify_error_handling specs)
- ruby_liquid_with_active_support.rb: 4203 passed (skips shopify_error_handling specs)
2026-01-01 22:21:47 -05:00
Tobi Lutke 2988f1a500 Update liquid-spec to branch with per-spec required_features support 2026-01-01 22:15:38 -05: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 b0fb0ad83f Run liquid-spec for all adapters in spec/*.rb 2026-01-01 22:02:42 -05:00
Tobi Lutke ae26cb29ac Disable auto-require for activesupport gem 2026-01-01 22:00:49 -05:00
Tobi Lutke 608a877053 Add spec adapter with ActiveSupport for comparison testing 2026-01-01 22:00:38 -05:00
Tobi Lutke d321adae77 Fix spec adapter for liquid-spec API (template, assigns, options) 2026-01-01 21:59:16 -05:00
Tobi Lutke 53641e19ce Pin liquid-spec to minimum required commit 3d1b492 2026-01-01 21:57:34 -05:00
Tobi Lutke ccd10a986a Pin liquid-spec to main branch 2026-01-01 21:56:39 -05:00
Tobi Lutke f4890de9d5 hm 2026-01-01 21:54:08 -05:00
Tobi Lutke 7e3ccbc188 test 2026-01-01 21:49:33 -05:00
Tobi Lutke e0b46049af Add Ruby 3.4 yjit, 4.0 zjit, and head zjit to CI matrix 2026-01-01 21:44:28 -05:00
Tobi Lutke 19528a9b3f Update CI matrix: remove Ruby 3.0-3.2, add Ruby 4.0 2026-01-01 21:42:47 -05:00
Tobi Lutke 34c274d314 Fix rubocop: rename ruby-liquid.rb to ruby_liquid.rb and add trailing comma 2026-01-01 21:42:11 -05:00
Tobi Lutke 533d470723 Fix spec job to include :spec bundle group 2026-01-01 21:35:13 -05:00
Tobi Lutke 05f9c2a030 Add liquid-spec for conformance testing
- Add liquid-spec gem from GitHub to :spec group
- Create spec/ruby-liquid.rb adapter for the reference implementation
- Add spec job to CI workflow to run liquid-spec tests
2026-01-01 21:34:10 -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 391c0df57a Update rubocop to 1.82.0 for Ruby 4.0 support 2026-01-01 20:19:21 -05:00
Tobi Lutke 0ed29760c0 Add benchmark gem for Ruby 4.0 compatibility 2026-01-01 20:18:35 -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
Tobias LütkeandGitHub 91c54c579d Merge pull request #1477 from Watson1978/performance
Increase parsing performance
2022-02-14 12:25:19 -05:00
Tobias LütkeandGitHub 0ce8aef229 Merge pull request #1103 from ashmaroli/ci-profile-memory
Add a CI job to profile memory usage of commit
2019-08-27 15:11:55 -04:00
Tobias LütkeandGitHub 6eab595fae Merge pull request #1086 from Shopify/liquid-tag
Add {% liquid %} and {% echo %} tags
2019-08-27 15:10:20 -04:00
Tobias Lütke 3476a556dd Merge pull request #512 from Shopify/fix_tobi_name
Fix Tobi last name on gemspec
2015-01-23 21:24:04 -05:00
Tobias Lütke 101f125a69 Merge pull request #375 from Shopify/relative-link
Fixed relative link
2014-06-30 17:19:37 -04:00
Tobias Lütke 05d9976e16 fix benchmark 2012-10-29 16:47:57 -04:00
Tobias Lütke ce76dbf8d9 fixed the performance suite 2012-10-20 10:53:53 -04:00
Tobias Lütke 16c34595a4 fix mergeconflict 2012-08-07 13:21:31 -04:00
Tobias Lütke 6e091909ee Merge branch 'master' of github.com:Shopify/liquid 2012-08-07 13:20:37 -04:00
Tobias Lütke d7cb39ccb3 release 2.4.0 2012-08-07 13:20:23 -04:00
Tobias Lütke 6831eac902 Released gem 2.1.3 2010-08-05 18:07:05 -04:00