/usr/lib/ruby/vendor_ruby/sass/environment.rb is in ruby-sass 3.1.15-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | require 'set'
module Sass
# The lexical environment for SassScript.
# This keeps track of variable, mixin, and function definitions.
#
# A new environment is created for each level of Sass nesting.
# This allows variables to be lexically scoped.
# The new environment refers to the environment in the upper scope,
# so it has access to variables defined in enclosing scopes,
# but new variables are defined locally.
#
# Environment also keeps track of the {Engine} options
# so that they can be made available to {Sass::Script::Functions}.
class Environment
# The enclosing environment,
# or nil if this is the global environment.
#
# @return [Environment]
attr_reader :parent
attr_writer :options
# @param parent [Environment] See \{#parent}
def initialize(parent = nil)
@parent = parent
unless parent
@stack = []
@mixins_in_use = Set.new
@files_in_use = Set.new
end
end
# The options hash.
# See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
#
# @return [{Symbol => Object}]
def options
@options || parent_options || {}
end
# Push a new stack frame onto the mixin/include stack.
#
# @param frame_info [{Symbol => Object}]
# Frame information has the following keys:
#
# `:filename`
# : The name of the file in which the lexical scope changed.
#
# `:mixin`
# : The name of the mixin in which the lexical scope changed,
# or `nil` if it wasn't within in a mixin.
#
# `:line`
# : The line of the file on which the lexical scope changed. Never nil.
def push_frame(frame_info)
top_of_stack = stack.last
if top_of_stack && top_of_stack.delete(:prepared)
top_of_stack.merge!(frame_info)
else
stack.push(top_of_stack = frame_info)
end
mixins_in_use << top_of_stack[:mixin] if top_of_stack[:mixin]
files_in_use << top_of_stack[:filename] if top_of_stack[:filename]
end
# Like \{#push\_frame}, but next time a stack frame is pushed,
# it will be merged with this frame.
#
# @param frame_info [{Symbol => Object}] Same as for \{#push\_frame}.
def prepare_frame(frame_info)
push_frame(frame_info.merge(:prepared => true))
end
# Pop a stack frame from the mixin/include stack.
def pop_frame
pop_and_unuse if stack.last && stack.last[:prepared]
pop_and_unuse
end
# A list of stack frames in the mixin/include stack.
# The last element in the list is the most deeply-nested frame.
#
# @return [Array<{Symbol => Object}>] The stack frames,
# of the form passed to \{#push\_frame}.
def stack
@stack ||= @parent.stack
end
# A set of names of mixins currently present in the stack.
#
# @return [Set<String>] The mixin names.
def mixins_in_use
@mixins_in_use ||= @parent.mixins_in_use
end
# A set of names of files currently present in the stack.
#
# @return [Set<String>] The filenames.
def files_in_use
@files_in_use ||= @parent.files_in_use
end
def stack_trace
trace = []
stack.reverse.each_with_index do |entry, i|
msg = "#{i == 0 ? "on" : "from"} line #{entry[:line]}"
msg << " of #{entry[:filename] || "an unknown file"}"
msg << ", in `#{entry[:mixin]}'" if entry[:mixin]
trace << msg
end
trace
end
private
def pop_and_unuse
popped = stack.pop
mixins_in_use.delete(popped[:mixin]) if popped && popped[:mixin]
files_in_use.delete(popped[:filename]) if popped && popped[:filename]
popped
end
def parent_options
@parent_options ||= @parent && @parent.options
end
class << self
private
UNDERSCORE, DASH = '_', '-'
# Note: when updating this,
# update sass/yard/inherited_hash.rb as well.
def inherited_hash(name)
class_eval <<RUBY, __FILE__, __LINE__ + 1
def #{name}(name)
_#{name}(name.tr(UNDERSCORE, DASH))
end
def _#{name}(name)
(@#{name}s && @#{name}s[name]) || @parent && @parent._#{name}(name)
end
protected :_#{name}
def set_#{name}(name, value)
name = name.tr(UNDERSCORE, DASH)
@#{name}s[name] = value unless try_set_#{name}(name, value)
end
def try_set_#{name}(name, value)
@#{name}s ||= {}
if @#{name}s.include?(name)
@#{name}s[name] = value
true
elsif @parent
@parent.try_set_#{name}(name, value)
else
false
end
end
protected :try_set_#{name}
def set_local_#{name}(name, value)
@#{name}s ||= {}
@#{name}s[name.tr(UNDERSCORE, DASH)] = value
end
RUBY
end
end
# variable
# Script::Literal
inherited_hash :var
# mixin
# Sass::Callable
inherited_hash :mixin
# function
# Sass::Callable
inherited_hash :function
end
end
|