From 0adc82997a5be0ed828dc41115add0dcda5485c9 Mon Sep 17 00:00:00 2001 From: James Prior Date: Wed, 6 May 2026 07:37:11 +0100 Subject: [PATCH] Move `self` handling to variable lookup --- lib/liquid.rb | 1 - lib/liquid/context.rb | 4 ---- lib/liquid/expression.rb | 2 -- lib/liquid/self_drop.rb | 38 ----------------------------------- lib/liquid/variable_lookup.rb | 17 ++++++++++------ 5 files changed, 11 insertions(+), 51 deletions(-) delete mode 100644 lib/liquid/self_drop.rb diff --git a/lib/liquid.rb b/lib/liquid.rb index dce089772..4d0a71a64 100644 --- a/lib/liquid.rb +++ b/lib/liquid.rb @@ -65,7 +65,6 @@ module Liquid require 'liquid/parser' require 'liquid/i18n' require 'liquid/drop' -require 'liquid/self_drop' require 'liquid/tablerowloop_drop' require 'liquid/forloop_drop' require 'liquid/extensions' diff --git a/lib/liquid/context.rb b/lib/liquid/context.rb index 7902ebcff..516556615 100644 --- a/lib/liquid/context.rb +++ b/lib/liquid/context.rb @@ -206,10 +206,6 @@ def find_variable(key, raise_on_not_found: true) # path and find_index() is optimized in MRI to reduce object allocation index = @scopes.find_index { |s| s.key?(key) } - # `self` resolves to a SelfDrop (enabling `self['var']` lookups), - # but only when it hasn't been explicitly assigned as a local variable. - return SelfDrop.new(self) if key == Expression::SELF && !index - variable = if index lookup_and_evaluate(@scopes[index], key, raise_on_not_found: raise_on_not_found) else diff --git a/lib/liquid/expression.rb b/lib/liquid/expression.rb index 7e15f85b0..00c40a4c3 100644 --- a/lib/liquid/expression.rb +++ b/lib/liquid/expression.rb @@ -2,8 +2,6 @@ module Liquid class Expression - SELF = 'self' - LITERALS = { nil => nil, 'nil' => nil, diff --git a/lib/liquid/self_drop.rb b/lib/liquid/self_drop.rb deleted file mode 100644 index 357814653..000000000 --- a/lib/liquid/self_drop.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: true - -module Liquid - # @liquid_public_docs - # @liquid_type object - # @liquid_name self - # @liquid_summary - # Provides access to variables through the current scope chain. - # @liquid_description - # The `self` object resolves variables through the normal lookup hierarchy - # (local > file > global) without exposing filters, interrupts, errors, - # or other context internals. It's used when bare bracket notation - # (`['variable']`) needs to be replaced with an explicit variable lookup. - # - # If `self` is explicitly assigned as a local variable (e.g. `{% assign self = 'value' %}`), - # then the local value takes precedence over the `self` object. - # @liquid_access global - class SelfDrop < Drop - def initialize(context) - super() - @context = context - end - - def [](key) - @context.find_variable(key) - rescue UndefinedVariable - nil - end - - def key?(key) - @context.variable_defined?(key) - end - - def to_liquid - self - end - end -end diff --git a/lib/liquid/variable_lookup.rb b/lib/liquid/variable_lookup.rb index 4fba2a658..ac6a5a8a0 100644 --- a/lib/liquid/variable_lookup.rb +++ b/lib/liquid/variable_lookup.rb @@ -64,9 +64,14 @@ def evaluate(context) res = context.lookup_and_evaluate(object, key) object = res.to_liquid - # Some special cases. If the part wasn't in square brackets and - # no key with the same name was found we interpret following calls - # as commands and call them on the current object + # If "self" is not in scope or `self[key]` does not exist, try to + # resolve `key` in the current scope. + elsif i == 0 && name == "self" && key.is_a?(String) && context.variable_defined?(key) + object = context.find_variable(key) + + # Some special cases. If the part wasn't in square brackets and + # no key with the same name was found we interpret following calls + # as commands and call them on the current object elsif lookup_command?(i) && object.respond_to?(key) object = object.send(key).to_liquid @@ -75,9 +80,9 @@ def evaluate(context) elsif lookup_command?(i) && object.is_a?(String) && (key == "first" || key == "last") object = key == "first" ? (object[0] || "") : (object[-1] || "") - # No key was present with the desired value and it wasn't one of the directly supported - # keywords either. The only thing we got left is to return nil or - # raise an exception if `strict_variables` option is set to true + # No key was present with the desired value and it wasn't one of the directly supported + # keywords either. The only thing we got left is to return nil or + # raise an exception if `strict_variables` option is set to true else return nil unless context.strict_variables raise Liquid::UndefinedVariable, "undefined variable #{key}"