sprockets 3.7.3 → 4.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +77 -259
- data/{LICENSE → MIT-LICENSE} +2 -2
- data/README.md +527 -320
- data/bin/sprockets +11 -7
- data/lib/rake/sprocketstask.rb +9 -4
- data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
- data/lib/sprockets/asset.rb +39 -27
- data/lib/sprockets/autoload/babel.rb +8 -0
- data/lib/sprockets/autoload/closure.rb +1 -0
- data/lib/sprockets/autoload/coffee_script.rb +1 -0
- data/lib/sprockets/autoload/eco.rb +1 -0
- data/lib/sprockets/autoload/ejs.rb +1 -0
- data/lib/sprockets/autoload/jsminc.rb +8 -0
- data/lib/sprockets/autoload/sass.rb +1 -0
- data/lib/sprockets/autoload/sassc.rb +8 -0
- data/lib/sprockets/autoload/uglifier.rb +1 -0
- data/lib/sprockets/autoload/yui.rb +1 -0
- data/lib/sprockets/autoload/zopfli.rb +7 -0
- data/lib/sprockets/autoload.rb +5 -0
- data/lib/sprockets/babel_processor.rb +66 -0
- data/lib/sprockets/base.rb +49 -12
- data/lib/sprockets/bower.rb +6 -3
- data/lib/sprockets/bundle.rb +41 -5
- data/lib/sprockets/cache/file_store.rb +25 -3
- data/lib/sprockets/cache/memory_store.rb +28 -10
- data/lib/sprockets/cache/null_store.rb +8 -0
- data/lib/sprockets/cache.rb +37 -2
- data/lib/sprockets/cached_environment.rb +15 -20
- data/lib/sprockets/closure_compressor.rb +1 -0
- data/lib/sprockets/coffee_script_processor.rb +19 -5
- data/lib/sprockets/compressing.rb +43 -3
- data/lib/sprockets/configuration.rb +5 -9
- data/lib/sprockets/context.rb +99 -25
- data/lib/sprockets/dependencies.rb +2 -1
- data/lib/sprockets/digest_utils.rb +35 -18
- data/lib/sprockets/directive_processor.rb +64 -38
- data/lib/sprockets/eco_processor.rb +2 -1
- data/lib/sprockets/ejs_processor.rb +2 -1
- data/lib/sprockets/encoding_utils.rb +2 -2
- data/lib/sprockets/environment.rb +9 -4
- data/lib/sprockets/erb_processor.rb +33 -32
- data/lib/sprockets/errors.rb +1 -0
- data/lib/sprockets/exporters/base.rb +71 -0
- data/lib/sprockets/exporters/file_exporter.rb +24 -0
- data/lib/sprockets/exporters/zlib_exporter.rb +33 -0
- data/lib/sprockets/exporters/zopfli_exporter.rb +14 -0
- data/lib/sprockets/exporting.rb +73 -0
- data/lib/sprockets/file_reader.rb +1 -0
- data/lib/sprockets/http_utils.rb +25 -7
- data/lib/sprockets/jsminc_compressor.rb +32 -0
- data/lib/sprockets/jst_processor.rb +11 -10
- data/lib/sprockets/loader.rb +91 -69
- data/lib/sprockets/manifest.rb +67 -64
- data/lib/sprockets/manifest_utils.rb +9 -6
- data/lib/sprockets/mime.rb +8 -62
- data/lib/sprockets/npm.rb +52 -0
- data/lib/sprockets/path_dependency_utils.rb +3 -11
- data/lib/sprockets/path_digest_utils.rb +2 -1
- data/lib/sprockets/path_utils.rb +88 -8
- data/lib/sprockets/paths.rb +1 -0
- data/lib/sprockets/preprocessors/default_source_map.rb +49 -0
- data/lib/sprockets/processing.rb +32 -62
- data/lib/sprockets/processor_utils.rb +28 -38
- data/lib/sprockets/resolve.rb +177 -93
- data/lib/sprockets/sass_cache_store.rb +2 -6
- data/lib/sprockets/sass_compressor.rb +13 -1
- data/lib/sprockets/sass_functions.rb +1 -0
- data/lib/sprockets/sass_importer.rb +1 -0
- data/lib/sprockets/sass_processor.rb +31 -10
- data/lib/sprockets/sassc_compressor.rb +56 -0
- data/lib/sprockets/sassc_processor.rb +297 -0
- data/lib/sprockets/server.rb +63 -40
- data/lib/sprockets/source_map_processor.rb +66 -0
- data/lib/sprockets/source_map_utils.rb +483 -0
- data/lib/sprockets/transformers.rb +63 -35
- data/lib/sprockets/uglifier_compressor.rb +21 -11
- data/lib/sprockets/unloaded_asset.rb +13 -11
- data/lib/sprockets/uri_tar.rb +1 -0
- data/lib/sprockets/uri_utils.rb +19 -16
- data/lib/sprockets/utils/gzip.rb +46 -14
- data/lib/sprockets/utils.rb +64 -90
- data/lib/sprockets/version.rb +2 -1
- data/lib/sprockets/yui_compressor.rb +1 -0
- data/lib/sprockets.rb +102 -39
- metadata +148 -45
- data/lib/sprockets/coffee_script_template.rb +0 -17
- data/lib/sprockets/deprecation.rb +0 -90
- data/lib/sprockets/eco_template.rb +0 -17
- data/lib/sprockets/ejs_template.rb +0 -17
- data/lib/sprockets/engines.rb +0 -92
- data/lib/sprockets/erb_template.rb +0 -11
- data/lib/sprockets/legacy.rb +0 -330
- data/lib/sprockets/legacy_proc_processor.rb +0 -35
- data/lib/sprockets/legacy_tilt_processor.rb +0 -29
- data/lib/sprockets/sass_template.rb +0 -19
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'sprockets/uri_utils'
|
2
3
|
require 'sprockets/uri_tar'
|
3
4
|
|
@@ -12,8 +13,8 @@ module Sprockets
|
|
12
13
|
# and full path such as
|
13
14
|
# "file:///Path/app/assets/js/app.js?type=application/javascript"
|
14
15
|
# env - The current "environment" that assets are being loaded into.
|
15
|
-
# We need it so we know where the +root+ (directory where
|
16
|
-
# is being invoked). We also need for the `file_digest` method,
|
16
|
+
# We need it so we know where the +root+ (directory where Sprockets
|
17
|
+
# is being invoked). We also need it for the `file_digest` method,
|
17
18
|
# since, for some strange reason, memoization is provided by
|
18
19
|
# overriding methods such as `stat` in the `PathUtils` module.
|
19
20
|
#
|
@@ -30,7 +31,7 @@ module Sprockets
|
|
30
31
|
# Internal: Full file path without schema
|
31
32
|
#
|
32
33
|
# This returns a string containing the full path to the asset without the schema.
|
33
|
-
# Information is loaded
|
34
|
+
# Information is loaded lazily since we want `UnloadedAsset.new(dep, self).relative_path`
|
34
35
|
# to be fast. Calling this method the first time allocates an array and a hash.
|
35
36
|
#
|
36
37
|
# Example
|
@@ -48,8 +49,8 @@ module Sprockets
|
|
48
49
|
|
49
50
|
# Internal: Hash of param values
|
50
51
|
#
|
51
|
-
# This information is generated and used internally by
|
52
|
-
# Known keys include `:type` which
|
52
|
+
# This information is generated and used internally by Sprockets.
|
53
|
+
# Known keys include `:type` which stores the asset's mime-type, `:id` which is a fully resolved
|
53
54
|
# digest for the asset (includes dependency digest as opposed to a digest of only file contents)
|
54
55
|
# and `:pipeline`. Hash may be empty.
|
55
56
|
#
|
@@ -79,12 +80,12 @@ module Sprockets
|
|
79
80
|
|
80
81
|
# Public: Dependency History key
|
81
82
|
#
|
82
|
-
# Used to retrieve an array of "histories" each of which
|
83
|
+
# Used to retrieve an array of "histories" each of which contains a set of stored dependencies
|
83
84
|
# for a given asset path and filename digest.
|
84
85
|
#
|
85
|
-
# A dependency can refer to either an asset
|
86
|
+
# A dependency can refer to either an asset e.g. index.js
|
86
87
|
# may rely on jquery.js (so jquery.js is a dependency), or other factors that may affect
|
87
|
-
# compilation, such as the VERSION of
|
88
|
+
# compilation, such as the VERSION of Sprockets (i.e. the environment) and what "processors"
|
88
89
|
# are used.
|
89
90
|
#
|
90
91
|
# For example a history array with one Set of dependencies may look like:
|
@@ -97,7 +98,7 @@ module Sprockets
|
|
97
98
|
# This method of asset lookup is used to ensure that none of the dependencies have been modified
|
98
99
|
# since last lookup. If one of them has, the key will be different and a new entry must be stored.
|
99
100
|
#
|
100
|
-
# URI
|
101
|
+
# URI dependencies are later converted to "compressed" paths
|
101
102
|
#
|
102
103
|
# Returns a String.
|
103
104
|
def dependency_history_key
|
@@ -108,8 +109,9 @@ module Sprockets
|
|
108
109
|
#
|
109
110
|
# Used to retrieve a string containing the "compressed" path to an asset based on
|
110
111
|
# a digest. The digest is generated from dependencies stored via information stored in
|
111
|
-
# the `dependency_history_key` after each of the "dependencies" is "resolved"
|
112
|
-
# "environment-version" may be resolved to "environment-1.0-3.2.0"
|
112
|
+
# the `dependency_history_key` after each of the "dependencies" is "resolved".
|
113
|
+
# For example "environment-version" may be resolved to "environment-1.0-3.2.0"
|
114
|
+
# for version "3.2.0" of Sprockets
|
113
115
|
#
|
114
116
|
# Returns a String.
|
115
117
|
def digest_key(digest)
|
data/lib/sprockets/uri_tar.rb
CHANGED
data/lib/sprockets/uri_utils.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'uri'
|
2
3
|
|
3
4
|
module Sprockets
|
@@ -20,6 +21,9 @@ module Sprockets
|
|
20
21
|
module URIUtils
|
21
22
|
extend self
|
22
23
|
|
24
|
+
URI_PARSER = defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::Generic::DEFAULT_PARSER
|
25
|
+
private_constant :URI_PARSER
|
26
|
+
|
23
27
|
# Internal: Parse URI into component parts.
|
24
28
|
#
|
25
29
|
# uri - String uri
|
@@ -44,26 +48,25 @@ module Sprockets
|
|
44
48
|
def split_file_uri(uri)
|
45
49
|
scheme, _, host, _, _, path, _, query, _ = URI.split(uri)
|
46
50
|
|
47
|
-
path =
|
51
|
+
path = URI_PARSER.unescape(path)
|
48
52
|
path.force_encoding(Encoding::UTF_8)
|
49
53
|
|
50
|
-
# Hack for parsing Windows "
|
51
|
-
path
|
52
|
-
|
53
|
-
|
54
|
-
query = nil if query && query.empty?
|
54
|
+
# Hack for parsing Windows "/C:/Users/IEUser" paths
|
55
|
+
if File::ALT_SEPARATOR && path[2] == ':'
|
56
|
+
path = path[1..-1]
|
57
|
+
end
|
55
58
|
|
56
|
-
[scheme, host, path, query]
|
59
|
+
[scheme, host || '', path, query]
|
57
60
|
end
|
58
61
|
|
59
62
|
# Internal: Join file: URI component parts into String.
|
60
63
|
#
|
61
64
|
# Returns String.
|
62
65
|
def join_file_uri(scheme, host, path, query)
|
63
|
-
str = "#{scheme}://"
|
66
|
+
str = +"#{scheme}://"
|
64
67
|
str << host if host
|
65
|
-
path = "/#{path}" unless path.start_with?("/")
|
66
|
-
str <<
|
68
|
+
path = "/#{path}" unless path.start_with?("/".freeze)
|
69
|
+
str << URI_PARSER.escape(path)
|
67
70
|
str << "?#{query}" if query
|
68
71
|
str
|
69
72
|
end
|
@@ -75,7 +78,7 @@ module Sprockets
|
|
75
78
|
# Returns true or false.
|
76
79
|
def valid_asset_uri?(str)
|
77
80
|
# Quick prefix check before attempting a full parse
|
78
|
-
str.start_with?("file://") && parse_asset_uri(str) ? true : false
|
81
|
+
str.start_with?("file://".freeze) && parse_asset_uri(str) ? true : false
|
79
82
|
rescue URI::InvalidURIError
|
80
83
|
false
|
81
84
|
end
|
@@ -162,7 +165,7 @@ module Sprockets
|
|
162
165
|
when Integer
|
163
166
|
query << "#{key}=#{value}"
|
164
167
|
when String, Symbol
|
165
|
-
query << "#{key}=#{
|
168
|
+
query << "#{key}=#{URI_PARSER.escape(value.to_s)}"
|
166
169
|
when TrueClass
|
167
170
|
query << "#{key}"
|
168
171
|
when FalseClass, NilClass
|
@@ -171,7 +174,7 @@ module Sprockets
|
|
171
174
|
end
|
172
175
|
end
|
173
176
|
|
174
|
-
"#{query.join('&')}" if query.any?
|
177
|
+
"#{query.join('&'.freeze)}" if query.any?
|
175
178
|
end
|
176
179
|
|
177
180
|
# Internal: Parse query string into hash of params
|
@@ -180,9 +183,9 @@ module Sprockets
|
|
180
183
|
#
|
181
184
|
# Return Hash of params.
|
182
185
|
def parse_uri_query_params(query)
|
183
|
-
query.to_s.split('&').reduce({}) do |h, p|
|
184
|
-
k, v = p.split('=', 2)
|
185
|
-
v =
|
186
|
+
query.to_s.split('&'.freeze).reduce({}) do |h, p|
|
187
|
+
k, v = p.split('='.freeze, 2)
|
188
|
+
v = URI_PARSER.unescape(v) if v
|
186
189
|
h[k.to_sym] = v || true
|
187
190
|
h
|
188
191
|
end
|
data/lib/sprockets/utils/gzip.rb
CHANGED
@@ -1,11 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Sprockets
|
2
3
|
module Utils
|
3
4
|
class Gzip
|
5
|
+
# Private: Generates a gzipped file based off of reference asset.
|
6
|
+
#
|
7
|
+
# ZlibArchiver.call(file, source, mtime)
|
8
|
+
#
|
9
|
+
# Compresses a given `source` using stdlib Zlib algorithm
|
10
|
+
# writes contents to the `file` passed in. Sets `mtime` of
|
11
|
+
# written file to passed in `mtime`
|
12
|
+
module ZlibArchiver
|
13
|
+
def self.call(file, source, mtime)
|
14
|
+
gz = Zlib::GzipWriter.new(file, Zlib::BEST_COMPRESSION)
|
15
|
+
gz.mtime = mtime
|
16
|
+
gz.write(source)
|
17
|
+
gz.close
|
18
|
+
|
19
|
+
File.utime(mtime, mtime, file.path)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Private: Generates a gzipped file based off of reference asset.
|
24
|
+
#
|
25
|
+
# ZopfliArchiver.call(file, source, mtime)
|
26
|
+
#
|
27
|
+
# Compresses a given `source` using the zopfli gem
|
28
|
+
# writes contents to the `file` passed in. Sets `mtime` of
|
29
|
+
# written file to passed in `mtime`
|
30
|
+
module ZopfliArchiver
|
31
|
+
def self.call(file, source, mtime)
|
32
|
+
compressed_source = Autoload::Zopfli.deflate(source, format: :gzip, mtime: mtime)
|
33
|
+
file.write(compressed_source)
|
34
|
+
file.close
|
35
|
+
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :content_type, :source, :charset, :archiver
|
41
|
+
|
4
42
|
# Private: Generates a gzipped file based off of reference file.
|
5
|
-
def initialize(asset)
|
43
|
+
def initialize(asset, archiver: ZlibArchiver)
|
6
44
|
@content_type = asset.content_type
|
7
45
|
@source = asset.source
|
8
46
|
@charset = asset.charset
|
47
|
+
@archiver = archiver
|
9
48
|
end
|
10
49
|
|
11
50
|
# What non-text mime types should we compress? This list comes from:
|
@@ -26,7 +65,7 @@ module Sprockets
|
|
26
65
|
# through a compression algorithm would make them larger.
|
27
66
|
#
|
28
67
|
# Return Boolean.
|
29
|
-
def can_compress?
|
68
|
+
def can_compress?
|
30
69
|
# The "charset" of a mime type is present if the value is
|
31
70
|
# encoded text. We can check this value to see if the asset
|
32
71
|
# can be compressed.
|
@@ -38,8 +77,8 @@ module Sprockets
|
|
38
77
|
# Private: Opposite of `can_compress?`.
|
39
78
|
#
|
40
79
|
# Returns Boolean.
|
41
|
-
def cannot_compress?
|
42
|
-
!can_compress?
|
80
|
+
def cannot_compress?
|
81
|
+
!can_compress?
|
43
82
|
end
|
44
83
|
|
45
84
|
# Private: Generates a gzipped file based off of reference asset.
|
@@ -49,16 +88,9 @@ module Sprockets
|
|
49
88
|
# Does not modify the target asset.
|
50
89
|
#
|
51
90
|
# Returns nothing.
|
52
|
-
def compress(target)
|
53
|
-
mtime = PathUtils.stat(target).mtime
|
54
|
-
|
55
|
-
gz = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
|
56
|
-
gz.mtime = mtime
|
57
|
-
gz.write(@source)
|
58
|
-
gz.close
|
59
|
-
|
60
|
-
File.utime(mtime, mtime, f.path)
|
61
|
-
end
|
91
|
+
def compress(file, target)
|
92
|
+
mtime = Sprockets::PathUtils.stat(target).mtime
|
93
|
+
archiver.call(file, source, mtime)
|
62
94
|
|
63
95
|
nil
|
64
96
|
end
|
data/lib/sprockets/utils.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'set'
|
2
3
|
|
3
4
|
module Sprockets
|
@@ -14,21 +15,17 @@ module Sprockets
|
|
14
15
|
#
|
15
16
|
# Returns false if .dup would raise a TypeError, otherwise true.
|
16
17
|
def duplicable?(obj)
|
17
|
-
|
18
|
-
|
18
|
+
case obj
|
19
|
+
when NilClass, FalseClass, TrueClass, Symbol, Numeric
|
20
|
+
false
|
19
21
|
else
|
20
|
-
|
21
|
-
when NilClass, FalseClass, TrueClass, Symbol, Numeric
|
22
|
-
false
|
23
|
-
else
|
24
|
-
true
|
25
|
-
end
|
22
|
+
true
|
26
23
|
end
|
27
24
|
end
|
28
25
|
|
29
26
|
# Internal: Duplicate and store key/value on new frozen hash.
|
30
27
|
#
|
31
|
-
#
|
28
|
+
# Separated for recursive calls, always use hash_reassoc(hash, *keys).
|
32
29
|
#
|
33
30
|
# hash - Hash
|
34
31
|
# key - Object key
|
@@ -49,7 +46,8 @@ module Sprockets
|
|
49
46
|
# Similar to Hash#store for nested frozen hashes.
|
50
47
|
#
|
51
48
|
# hash - Hash
|
52
|
-
#
|
49
|
+
# key_a - Object key. Use multiple keys for nested hashes.
|
50
|
+
# key_b - Object key. Use multiple keys for nested hashes.
|
53
51
|
# block - Receives current value at key.
|
54
52
|
#
|
55
53
|
# Examples
|
@@ -60,16 +58,19 @@ module Sprockets
|
|
60
58
|
# end
|
61
59
|
#
|
62
60
|
# Returns duplicated frozen Hash.
|
63
|
-
def hash_reassoc(hash,
|
64
|
-
if
|
65
|
-
hash_reassoc1(hash,
|
66
|
-
|
67
|
-
hash_reassoc1(hash, keys[0]) do |value|
|
68
|
-
hash_reassoc(value, *keys[1..-1], &block)
|
61
|
+
def hash_reassoc(hash, key_a, key_b = nil, &block)
|
62
|
+
if key_b
|
63
|
+
hash_reassoc1(hash, key_a) do |value|
|
64
|
+
hash_reassoc(value, key_b, &block)
|
69
65
|
end
|
66
|
+
else
|
67
|
+
hash_reassoc1(hash, key_a, &block)
|
70
68
|
end
|
71
69
|
end
|
72
70
|
|
71
|
+
WHITESPACE_ORDINALS = {0x0A => "\n", 0x20 => " ", 0x09 => "\t"}
|
72
|
+
private_constant :WHITESPACE_ORDINALS
|
73
|
+
|
73
74
|
# Internal: Check if string has a trailing semicolon.
|
74
75
|
#
|
75
76
|
# str - String
|
@@ -81,14 +82,9 @@ module Sprockets
|
|
81
82
|
c = str[i].ord
|
82
83
|
i -= 1
|
83
84
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
# 0x09 == "\t"
|
88
|
-
# 0x3B == ";"
|
89
|
-
unless c == 0x0A || c == 0x20 || c == 0x09
|
90
|
-
return c === 0x3B
|
91
|
-
end
|
85
|
+
next if WHITESPACE_ORDINALS[c]
|
86
|
+
|
87
|
+
return c === 0x3B
|
92
88
|
end
|
93
89
|
|
94
90
|
true
|
@@ -102,51 +98,28 @@ module Sprockets
|
|
102
98
|
#
|
103
99
|
# Returns buf String.
|
104
100
|
def concat_javascript_sources(buf, source)
|
105
|
-
buf
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
101
|
+
return buf if source.bytesize <= 0
|
102
|
+
|
103
|
+
buf << source
|
104
|
+
# If the source contains non-ASCII characters, indexing on it becomes O(N).
|
105
|
+
# 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)
|
106
|
+
source = source.encode(Encoding::UTF_32LE) unless source.ascii_only?
|
107
|
+
return buf if string_end_with_semicolon?(source)
|
108
|
+
|
109
|
+
# If the last character in the string was whitespace,
|
110
|
+
# such as a newline, then we want to put the semicolon
|
111
|
+
# before the whitespace. Otherwise append a semicolon.
|
112
|
+
if whitespace = WHITESPACE_ORDINALS[source[-1].ord]
|
113
|
+
buf[-1] = ";#{whitespace}"
|
114
|
+
else
|
115
|
+
buf << ";"
|
118
116
|
end
|
119
117
|
|
120
118
|
buf
|
121
119
|
end
|
122
120
|
|
123
|
-
|
124
|
-
|
125
|
-
# normalize_extension("js")
|
126
|
-
# # => ".js"
|
127
|
-
#
|
128
|
-
# normalize_extension(".css")
|
129
|
-
# # => ".css"
|
130
|
-
#
|
131
|
-
def normalize_extension(extension)
|
132
|
-
extension = extension.to_s
|
133
|
-
if extension[/^\./]
|
134
|
-
extension
|
135
|
-
else
|
136
|
-
".#{extension}"
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
# Internal: Feature detect if UnboundMethods can #bind to any Object or
|
141
|
-
# just Objects that share the same super class.
|
142
|
-
# Basically if RUBY_VERSION >= 2.
|
143
|
-
UNBOUND_METHODS_BIND_TO_ANY_OBJECT = begin
|
144
|
-
foo = Module.new { def bar; end }
|
145
|
-
foo.instance_method(:bar).bind(Object.new)
|
146
|
-
true
|
147
|
-
rescue TypeError
|
148
|
-
false
|
149
|
-
end
|
121
|
+
MODULE_INCLUDE_MUTEX = Mutex.new
|
122
|
+
private_constant :MODULE_INCLUDE_MUTEX
|
150
123
|
|
151
124
|
# Internal: Inject into target module for the duration of the block.
|
152
125
|
#
|
@@ -154,28 +127,29 @@ module Sprockets
|
|
154
127
|
#
|
155
128
|
# Returns result of block.
|
156
129
|
def module_include(base, mod)
|
157
|
-
|
130
|
+
MODULE_INCLUDE_MUTEX.synchronize do
|
131
|
+
old_methods = {}
|
158
132
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
unless UNBOUND_METHODS_BIND_TO_ANY_OBJECT
|
164
|
-
base.send(:include, mod) unless base < mod
|
165
|
-
end
|
133
|
+
mod.instance_methods.each do |sym|
|
134
|
+
old_methods[sym] = base.instance_method(sym) if base.method_defined?(sym)
|
135
|
+
end
|
166
136
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
137
|
+
mod.instance_methods.each do |sym|
|
138
|
+
method = mod.instance_method(sym)
|
139
|
+
if base.method_defined?(sym)
|
140
|
+
base.send(:alias_method, sym, sym)
|
141
|
+
end
|
142
|
+
base.send(:define_method, sym, method)
|
143
|
+
end
|
171
144
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
145
|
+
yield
|
146
|
+
ensure
|
147
|
+
mod.instance_methods.each do |sym|
|
148
|
+
base.send(:undef_method, sym) if base.method_defined?(sym)
|
149
|
+
end
|
150
|
+
old_methods.each do |sym, method|
|
151
|
+
base.send(:define_method, sym, method)
|
152
|
+
end
|
179
153
|
end
|
180
154
|
end
|
181
155
|
|
@@ -217,16 +191,16 @@ module Sprockets
|
|
217
191
|
# Returns an Array of node Arrays.
|
218
192
|
def dfs_paths(path)
|
219
193
|
paths = []
|
220
|
-
stack
|
194
|
+
stack = [path]
|
195
|
+
seen = Set.new
|
221
196
|
|
222
197
|
while path = stack.pop
|
223
|
-
|
224
|
-
|
225
|
-
paths << path if path.size > 1
|
198
|
+
seen.add(path.last)
|
199
|
+
paths << path
|
226
200
|
|
227
|
-
|
228
|
-
|
229
|
-
|
201
|
+
children = yield path.last
|
202
|
+
children.reverse_each do |node|
|
203
|
+
stack.push(path + [node]) unless seen.include?(node)
|
230
204
|
end
|
231
205
|
end
|
232
206
|
|
data/lib/sprockets/version.rb
CHANGED