sprockets 3.6.0 → 3.6.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sprockets might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a1eef394792f4af6343438fcc3666a88ca893348
4
- data.tar.gz: 464e323e318b96534f12621a3f1a5dfc9a024425
3
+ metadata.gz: 60bd74a92e432ab26a1c9ff6a5f3a1ced8ccc1c8
4
+ data.tar.gz: 8708f6433b0ab2438bea014db7783388d2c0d493
5
5
  SHA512:
6
- metadata.gz: 446a6718c9ae7f0e94e57672680c7bbb2233855000dd813d3dc1867d0d3c6f12f3dcb43abe21f9a72bfcc05bff7524b9030eb771c342d4ea65fdde1169887f21
7
- data.tar.gz: e49c3925afb5988848f46439b1e9c3b5334932e599c13398f0a7a6a312dde2f228c0e679bd8fc898e80dd1861bc4fcfedfd807a9872b91b2af14be210870ab7d
6
+ metadata.gz: 41f481255492f56a331de0a8b5df114a9f60681b048a79cba5cf90f44b08622fb08f6cf23fa108fb2a448890c1808d685ba785934db949ac47911d6f1aebee98
7
+ data.tar.gz: 45204e3291b8427570c24e75a245039a02a8cb10ceda060984a904c7c9abea4d1f19e4ce50133fc83e2980da93ce1485f0d38b3c6188d075ab985b026d018971
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ **3.6.3** (July 1, 2016)
2
+
3
+ * Faster asset lookup in large directories #336
4
+ * Faster PathUtils.match_path_extname https://github.com/rails/sprockets/commit/697269cf81e5261fdd7072e32bd489403027fd7e
5
+ * Fixed uglifier comment stripping #326
6
+ * Error messages now show load path info #313
7
+
8
+ **3.6.2** (June 21, 2016)
9
+
10
+ * More performance improvements.
11
+
12
+ **3.6.1** (June 17, 2016)
13
+
14
+ * Some performance improvements.
15
+
1
16
  **3.6.0** (April 6, 2016)
2
17
 
3
18
  * Add `Manifest#find_sources` to return the source of the compiled assets.
@@ -36,7 +36,6 @@ module Sprockets
36
36
  # (default: 1000).
37
37
  def initialize(root, max_size = DEFAULT_MAX_SIZE, logger = self.class.default_logger)
38
38
  @root = root
39
- @size = find_caches.inject(0) { |n, (_, stat)| n + stat.size }
40
39
  @max_size = max_size
41
40
  @gc_size = max_size * 0.75
42
41
  @logger = logger
@@ -107,11 +106,11 @@ module Sprockets
107
106
  # Write data
108
107
  PathUtils.atomic_write(path) do |f|
109
108
  f.write(raw)
110
- @size += f.size unless exists
109
+ @size = size + f.size unless exists
111
110
  end
112
111
 
113
112
  # GC if necessary
114
- gc! if @size > @max_size
113
+ gc! if size > @max_size
115
114
 
116
115
  value
117
116
  end
@@ -120,7 +119,7 @@ module Sprockets
120
119
  #
121
120
  # Returns String.
122
121
  def inspect
123
- "#<#{self.class} size=#{@size}/#{@max_size}>"
122
+ "#<#{self.class} size=#{size}/#{@max_size}>"
124
123
  end
125
124
 
126
125
  private
@@ -138,6 +137,10 @@ module Sprockets
138
137
  }.sort_by { |_, stat| stat.mtime.to_i }
139
138
  end
140
139
 
140
+ def size
141
+ @size ||= compute_size(find_caches)
142
+ end
143
+
141
144
  def compute_size(caches)
142
145
  caches.inject(0) { |sum, (_, stat)| sum + stat.size }
143
146
  end
@@ -34,6 +34,50 @@ module Sprockets
34
34
  DIGEST_SIZES[bytes.bytesize]
35
35
  end
36
36
 
37
+ ADD_VALUE_TO_DIGEST = {
38
+ String => ->(val, digest) { digest << val },
39
+ FalseClass => ->(val, digest) { digest << 'FalseClass'.freeze },
40
+ TrueClass => ->(val, digest) { digest << 'TrueClass'.freeze },
41
+ NilClass => ->(val, digest) { digest << 'NilClass'.freeze },
42
+
43
+ Symbol => ->(val, digest) {
44
+ digest << 'Symbol'.freeze
45
+ digest << val.to_s
46
+ },
47
+ Fixnum => ->(val, digest) {
48
+ digest << 'Fixnum'.freeze
49
+ digest << val.to_s
50
+ },
51
+ Bignum => ->(val, digest) {
52
+ digest << 'Bignum'.freeze
53
+ digest << val.to_s
54
+ },
55
+ Array => ->(val, digest) {
56
+ digest << 'Array'.freeze
57
+ val.each do |element|
58
+ ADD_VALUE_TO_DIGEST[element.class].call(element, digest)
59
+ end
60
+ },
61
+ Hash => ->(val, digest) {
62
+ digest << 'Hash'.freeze
63
+ val.sort.each do |array|
64
+ ADD_VALUE_TO_DIGEST[Array].call(array, digest)
65
+ end
66
+ },
67
+ Set => ->(val, digest) {
68
+ digest << 'Set'.freeze
69
+ ADD_VALUE_TO_DIGEST[Array].call(val.to_a, digest)
70
+ },
71
+ Encoding => ->(val, digest) {
72
+ digest << 'Encoding'.freeze
73
+ digest << val.name
74
+ },
75
+ }
76
+ ADD_VALUE_TO_DIGEST.default_proc = ->(_, val) {
77
+ raise TypeError, "couldn't digest #{ val }"
78
+ }
79
+ private_constant :ADD_VALUE_TO_DIGEST
80
+
37
81
  # Internal: Generate a hexdigest for a nested JSON serializable object.
38
82
  #
39
83
  # This is used for generating cache keys, so its pretty important its
@@ -44,46 +88,8 @@ module Sprockets
44
88
  # Returns a String digest of the object.
45
89
  def digest(obj)
46
90
  digest = digest_class.new
47
- queue = [obj]
48
-
49
- while queue.length > 0
50
- obj = queue.shift
51
- klass = obj.class
52
-
53
- if klass == String
54
- digest << obj
55
- elsif klass == Symbol
56
- digest << 'Symbol'
57
- digest << obj.to_s
58
- elsif klass == Fixnum
59
- digest << 'Fixnum'
60
- digest << obj.to_s
61
- elsif klass == Bignum
62
- digest << 'Bignum'
63
- digest << obj.to_s
64
- elsif klass == TrueClass
65
- digest << 'TrueClass'
66
- elsif klass == FalseClass
67
- digest << 'FalseClass'
68
- elsif klass == NilClass
69
- digest << 'NilClass'.freeze
70
- elsif klass == Array
71
- digest << 'Array'
72
- queue.concat(obj)
73
- elsif klass == Hash
74
- digest << 'Hash'
75
- queue.concat(obj.sort)
76
- elsif klass == Set
77
- digest << 'Set'
78
- queue.concat(obj.to_a)
79
- elsif klass == Encoding
80
- digest << 'Encoding'
81
- digest << obj.name
82
- else
83
- raise TypeError, "couldn't digest #{klass}"
84
- end
85
- end
86
91
 
92
+ ADD_VALUE_TO_DIGEST[obj.class].call(obj, digest)
87
93
  digest.digest
88
94
  end
89
95
 
@@ -55,7 +55,9 @@ module Sprockets
55
55
  if File.directory?(path)
56
56
  entries = Dir.entries(path, :encoding => Encoding.default_internal)
57
57
  entries.reject! { |entry|
58
- entry =~ /^\.|~$|^\#.*\#$/
58
+ entry.start_with?(".".freeze) ||
59
+ (entry.start_with?("#".freeze) && entry.end_with?("#".freeze)) ||
60
+ entry.end_with?("~".freeze)
59
61
  }
60
62
  entries.sort!
61
63
  else
@@ -146,16 +148,19 @@ module Sprockets
146
148
  #
147
149
  # Returns [String extname, Object value] or nil nothing matched.
148
150
  def match_path_extname(path, extensions)
149
- match, key = nil, ""
150
- path_extnames(path).reverse_each do |extname|
151
- key.prepend(extname)
152
- if value = extensions[key]
153
- match = [key.dup, value]
154
- elsif match
155
- break
151
+ basename = File.basename(path)
152
+
153
+ i = basename.index('.'.freeze)
154
+ while i && i < basename.length - 1
155
+ extname = basename[i..-1]
156
+ if value = extensions[extname]
157
+ return extname, value
156
158
  end
159
+
160
+ i = basename.index('.'.freeze, i+1)
157
161
  end
158
- match
162
+
163
+ nil
159
164
  end
160
165
 
161
166
  # Internal: Returns all parents for path
@@ -121,6 +121,17 @@ module Sprockets
121
121
  Set
122
122
  ]).freeze
123
123
 
124
+ # Internal: Hash of all "simple" value types allowed to be returned in
125
+ # processor metadata.
126
+ VALID_METADATA_VALUE_TYPES_HASH = VALID_METADATA_VALUE_TYPES.each_with_object({}) do |type, hash|
127
+ hash[type] = true
128
+ end.freeze
129
+
130
+ # Internal: Hash of all nested compound metadata types that can nest values.
131
+ VALID_METADATA_COMPOUND_TYPES_HASH = VALID_METADATA_COMPOUND_TYPES.each_with_object({}) do |type, hash|
132
+ hash[type] = true
133
+ end.freeze
134
+
124
135
  # Internal: Set of all allowed metadata types.
125
136
  VALID_METADATA_TYPES = (VALID_METADATA_VALUE_TYPES + VALID_METADATA_COMPOUND_TYPES).freeze
126
137
 
@@ -159,9 +170,9 @@ module Sprockets
159
170
  #
160
171
  # Returns true if class is in whitelist otherwise false.
161
172
  def valid_processor_metadata_value?(value)
162
- if VALID_METADATA_VALUE_TYPES.include?(value.class)
173
+ if VALID_METADATA_VALUE_TYPES_HASH[value.class]
163
174
  true
164
- elsif VALID_METADATA_COMPOUND_TYPES.include?(value.class)
175
+ elsif VALID_METADATA_COMPOUND_TYPES_HASH[value.class]
165
176
  value.all? { |v| valid_processor_metadata_value?(v) }
166
177
  else
167
178
  false
@@ -60,6 +60,7 @@ module Sprockets
60
60
  end
61
61
 
62
62
  message << " with type '#{options[:accept]}'" if options[:accept]
63
+ message << "\nChecked in these paths: \n #{ config[:paths].join("\n ") }"
63
64
 
64
65
  raise FileNotFound, message
65
66
  end
@@ -177,6 +178,7 @@ module Sprockets
177
178
  candidates = []
178
179
  entries = self.entries(dirname)
179
180
  entries.each do |entry|
181
+ next unless File.basename(entry).start_with?(basename)
180
182
  name, type, _, _ = parse_path_extnames(entry)
181
183
  if basename == name
182
184
  candidates << [File.join(dirname, entry), type]
@@ -41,7 +41,7 @@ module Sprockets
41
41
  options[:copyright] ||= false
42
42
  else
43
43
  # Uglifier >= 2.x
44
- options[:copyright] ||= :none
44
+ options[:comments] ||= :none
45
45
  end
46
46
 
47
47
  @uglifier = Autoload::Uglifier.new(options)
@@ -14,10 +14,8 @@ module Sprockets
14
14
  @env = env
15
15
  uri = uri.to_s
16
16
  if uri.include?("://".freeze)
17
- uri_array = uri.split("://".freeze)
18
- @scheme = uri_array.shift
19
- @scheme << "://".freeze
20
- @path = uri_array.join("".freeze)
17
+ @scheme, _, @path = uri.partition("://".freeze)
18
+ @scheme << "://".freeze
21
19
  else
22
20
  @scheme = "".freeze
23
21
  @path = uri
@@ -74,16 +74,19 @@ module Sprockets
74
74
  def string_end_with_semicolon?(str)
75
75
  i = str.size - 1
76
76
  while i >= 0
77
- c = str[i]
77
+ c = str[i].ord
78
78
  i -= 1
79
- if c == "\n" || c == " " || c == "\t"
80
- next
81
- elsif c != ";"
82
- return false
83
- else
84
- return true
79
+
80
+ # Need to compare against the ordinals because the string can be UTF_8 or UTF_32LE encoded
81
+ # 0x0A == "\n"
82
+ # 0x20 == " "
83
+ # 0x09 == "\t"
84
+ # 0x3B == ";"
85
+ unless c == 0x0A || c == 0x20 || c == 0x09
86
+ return c === 0x3B
85
87
  end
86
88
  end
89
+
87
90
  true
88
91
  end
89
92
 
@@ -95,11 +98,21 @@ module Sprockets
95
98
  #
96
99
  # Returns buf String.
97
100
  def concat_javascript_sources(buf, source)
98
- if buf.bytesize > 0
99
- buf << ";" unless string_end_with_semicolon?(buf)
100
- buf << "\n" unless buf.end_with?("\n")
101
+ if source.bytesize > 0
102
+ buf << source
103
+
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
+
108
+ if !string_end_with_semicolon?(source)
109
+ buf << ";\n"
110
+ elsif source[source.size - 1].ord != 0x0A
111
+ buf << "\n"
112
+ end
101
113
  end
102
- buf << source
114
+
115
+ buf
103
116
  end
104
117
 
105
118
  # Internal: Prepends a leading "." to an extension if its missing.
@@ -1,3 +1,3 @@
1
1
  module Sprockets
2
- VERSION = "3.6.0"
2
+ VERSION = "3.6.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sprockets
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.0
4
+ version: 3.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Stephenson
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-04-06 00:00:00.000000000 Z
12
+ date: 2016-07-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack