Module: Sprockets::Utils
Relationships & Source Files | |
Namespace Children | |
Classes:
| |
Extension / Inclusion / Inheritance Descendants | |
Extended In:
| |
Included In:
| |
Defined in: | lib/sprockets/utils.rb, lib/sprockets/utils/gzip.rb |
Overview
Internal: Utils
, we didn’t know where else to put it! Functions may eventually be shuffled into more specific drawers.
Constant Summary
-
MODULE_INCLUDE_MUTEX =
private
# File 'lib/sprockets/utils.rb', line 121Mutex.new
-
WHITESPACE_ORDINALS =
private
# File 'lib/sprockets/utils.rb', line 71{0x0A => "\n", 0x20 => " ", 0x09 => "\t"}
Instance Method Summary
-
#concat_javascript_sources(buf, source)
Internal: Accumulate asset source to buffer and append a trailing semicolon if necessary.
-
#dfs(initial)
Internal: Post-order Depth-First search algorithm.
-
#dfs_paths(path)
Internal: Post-order Depth-First search algorithm that gathers all paths along the way.
-
#duplicable?(obj) ⇒ Boolean
Internal: Check if object can safely be .dup’d.
-
#hash_reassoc(hash, key_a, key_b = nil, &block)
Internal: Duplicate and store key/value on new frozen hash.
-
#hash_reassoc1(hash, key)
Internal: Duplicate and store key/value on new frozen hash.
-
#module_include(base, mod)
Internal: Inject into target module for the duration of the block.
-
#string_end_with_semicolon?(str) ⇒ Boolean
Internal: Check if string has a trailing semicolon.
Instance Method Details
#concat_javascript_sources(buf, source)
Internal: Accumulate asset source to buffer and append a trailing semicolon if necessary.
buf - String buffer to append to source - String source to append
Returns buf String.
# File 'lib/sprockets/utils.rb', line 100
def concat_javascript_sources(buf, source) return buf if source.bytesize <= 0 buf << source # If the source contains non-ASCII characters, indexing on it becomes O(N). # This will lead to O(N^2) performance in string_end_with_semicolon?, so we should use 32 bit encoding to make sure indexing stays O(1) source = source.encode(Encoding::UTF_32LE) unless source.ascii_only? return buf if string_end_with_semicolon?(source) # If the last character in the string was whitespace, # such as a newline, then we want to put the semicolon # before the whitespace. Otherwise append a semicolon. if whitespace = WHITESPACE_ORDINALS[source[-1].ord] buf[-1] = ";#{whitespace}" else buf << ";" end buf end
#dfs(initial)
Internal: Post-order Depth-First search algorithm.
Used for resolving asset dependencies.
initial - Initial Array of nodes to traverse. block -
node - Current node to get children of
Returns a Set of nodes.
# File 'lib/sprockets/utils.rb', line 165
def dfs(initial) nodes, seen = Set.new, Set.new stack = Array(initial).reverse while node = stack.pop if seen.include?(node) nodes.add(node) else seen.add(node) stack.push(node) stack.concat(Array(yield node).reverse) end end nodes end
#dfs_paths(path)
Internal: Post-order Depth-First search algorithm that gathers all paths along the way.
TODO: Rename function.
path - Initial Array node path block -
node - Current node to get children of
Returns an Array of node Arrays.
# File 'lib/sprockets/utils.rb', line 192
def dfs_paths(path) paths = [] stack = [path] seen = Set.new while path = stack.pop seen.add(path.last) paths << path children = yield path.last children.reverse_each do |node| stack.push(path + [node]) unless seen.include?(node) end end paths end
#duplicable?(obj) ⇒ Boolean
Internal: Check if object can safely be .dup’d.
Similar to ActiveSupport #duplicable?
check.
obj - Any Object
Returns false if .dup
would raise a TypeError, otherwise true.
# File 'lib/sprockets/utils.rb', line 17
def duplicable?(obj) case obj when NilClass, FalseClass, TrueClass, Symbol, Numeric false else true end end
#hash_reassoc(hash, key_a, key_b = nil, &block)
Internal: Duplicate and store key/value on new frozen hash.
Similar to Hash#store
for nested frozen hashes.
hash - Hash key_a - Object key. Use multiple keys for nested hashes. key_b - Object key. Use multiple keys for nested hashes. block - Receives current value at key.
Examples
config = {paths: ["/bin", "/sbin"]}.freeze
new_config = hash_reassoc(config, :paths) do |paths|
paths << "/usr/local/bin"
end
Returns duplicated frozen Hash.
# File 'lib/sprockets/utils.rb', line 61
def hash_reassoc(hash, key_a, key_b = nil, &block) if key_b hash_reassoc1(hash, key_a) do |value| hash_reassoc(value, key_b, &block) end else hash_reassoc1(hash, key_a, &block) end end
#hash_reassoc1(hash, key)
Internal: Duplicate and store key/value on new frozen hash.
Separated for recursive calls, always use hash_reassoc(hash, *keys).
hash - Hash key - Object key
Returns Hash.
# File 'lib/sprockets/utils.rb', line 34
def hash_reassoc1(hash, key) hash = hash.dup if hash.frozen? old_value = hash[key] old_value = old_value.dup if duplicable?(old_value) new_value = yield old_value new_value.freeze if duplicable?(new_value) hash.store(key, new_value) hash.freeze end
#module_include(base, mod)
Internal: Inject into target module for the duration of the block.
mod - Module
Returns result of block.
# File 'lib/sprockets/utils.rb', line 129
def module_include(base, mod) MODULE_INCLUDE_MUTEX.synchronize do old_methods = {} mod.instance_methods.each do |sym| old_methods[sym] = base.instance_method(sym) if base.method_defined?(sym) end mod.instance_methods.each do |sym| method = mod.instance_method(sym) if base.method_defined?(sym) base.send(:alias_method, sym, sym) end base.send(:define_method, sym, method) end yield ensure mod.instance_methods.each do |sym| base.send(:undef_method, sym) if base.method_defined?(sym) end old_methods.each do |sym, method| base.send(:define_method, sym, method) end end end
#string_end_with_semicolon?(str) ⇒ Boolean
Internal: Check if string has a trailing semicolon.
str - String
Returns true or false.
# File 'lib/sprockets/utils.rb', line 79
def string_end_with_semicolon?(str) i = str.size - 1 while i >= 0 c = str[i].ord i -= 1 next if WHITESPACE_ORDINALS[c] return c === 0x3B end true end