sprockets 4.0.0.beta4 → 4.0.0.beta5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 52d1dd6743105d82450959d44e27538e02130e7e
4
- data.tar.gz: 02f58032703403898778cc33d6a56e0ca8bbee01
3
+ metadata.gz: 8fec40bbdd1b072ed9297eb8a8c4cace3ad4d406
4
+ data.tar.gz: 7e75410bb1fb7fce7577c5c7a270795735940d0b
5
5
  SHA512:
6
- metadata.gz: ac089336d45577a2647ba6b329c5a62862613674be5969f4312e0d7afbb0cf3a9a06cbc7d9db7dd55649fac74c234da54d4482f83d091c4d2357269502006d99
7
- data.tar.gz: 990363e0a8e9545ad6243279075cad733d7b403b45737b0c76b35d4647824e693c9f012c88b4220a431970d649dc7ad3582980311dc30c8e2b7b1871c1e5d611
6
+ metadata.gz: 41dc1ca9ad0acf4423861cc32353eb7e69f438fd01519ee2f0c5f6b543a4701b838132ebd1a55b3c2aedca5b2c2409b7221bc3199a7b094e9724c6165b9c7bbb
7
+ data.tar.gz: 2f9d9d7ca8cf7264eb99eb53b02f39d768f3f9472005d20a72655740c99eaf571977ddacd3ae07f8ada481e1390328e11cb2203bc415e29ecf496e93888d587a
@@ -4,6 +4,12 @@ Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprocket
4
4
 
5
5
  ## Master
6
6
 
7
+ ## 4.0.0.beta5
8
+
9
+ - Reduce string allocations
10
+ - Source map metadata uses compressed form specified by the [source map v3 spec](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k). [#402] **[BREAKING]**
11
+ - Generate [index maps](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt) when decoding source maps isn't necessary. [#402]
12
+ - Remove fingerprints from source map files. [#402]
7
13
 
8
14
  ## 4.0.0.beta4
9
15
 
data/README.md CHANGED
@@ -63,8 +63,8 @@ For example, if you have an `application.js` and want all the files in the `foo/
63
63
  Then create a file `foo/index.js` that requires all the files in that folder in any order you want:
64
64
 
65
65
  ```
66
- //= require foo.min.js
67
- //= require foo-ui.js
66
+ //= require ./foo.min.js
67
+ //= require ./foo-ui.js
68
68
  ```
69
69
 
70
70
  Now, your `application.js` will correctly load the `foo.min.js` before `foo-ui.js`. If you used `require_tree` it would not work correctly.
@@ -359,8 +359,8 @@ reference files relative to the location of the current file.
359
359
  #### The `require` Directive
360
360
 
361
361
  `require` *path* inserts the contents of the asset source file
362
- specified by *path*. If the file is required multiple times, it will
363
- appear in the bundle only once.
362
+ specified by *path*. If the same file is required multiple times
363
+ with different path expressions, it will appear in the bundle only once.
364
364
 
365
365
  #### The `require_directory` Directive
366
366
 
@@ -440,7 +440,7 @@ Similar to Rack, a processor is any "callable" (an object that responds to `call
440
440
 
441
441
  Also see [`Sprockets::ProcessorUtils`](https://github.com/rails/sprockets/blob/master/lib/sprockets/processor_utils.rb) for public helper methods.
442
442
 
443
- ### input Hash
443
+ ### Input Hash
444
444
 
445
445
  The `input` Hash defines the following public fields.
446
446
 
@@ -448,7 +448,6 @@ The `input` Hash defines the following public fields.
448
448
  * `:environment` - Current `Sprockets::Environment` instance.
449
449
  * `:cache` - A `Sprockets::Cache` instance. See [`Sprockets::Cache#fetch`](https://github.com/rails/sprockets/blob/master/lib/sprockets/cache.rb).
450
450
  * `:uri` - String Asset URI.
451
- * `:source_path` - String full path to original file.
452
451
  * `:load_path` - String current load path for filename.
453
452
  * `:name` - String logical path for filename.
454
453
  * `:content_type` - String content type of the output asset.
@@ -99,13 +99,7 @@ module Sprockets
99
99
  end
100
100
 
101
101
  register_pipeline :default do |env, type, file_type|
102
- # TODO: Hack for to inject source map transformer
103
- if (type == "application/js-sourcemap+json" && file_type != "application/js-sourcemap+json") ||
104
- (type == "application/css-sourcemap+json" && file_type != "application/css-sourcemap+json")
105
- [SourceMapProcessor]
106
- else
107
- env.default_processors_for(type, file_type)
108
- end
102
+ env.default_processors_for(type, file_type)
109
103
  end
110
104
 
111
105
  require 'sprockets/source_map_comment_processor'
@@ -129,7 +123,7 @@ module Sprockets
129
123
  register_bundle_metadata_reducer 'application/javascript', :data, proc { String.new("") }, Utils.method(:concat_javascript_sources)
130
124
  register_bundle_metadata_reducer '*/*', :links, :+
131
125
  register_bundle_metadata_reducer '*/*', :sources, proc { [] }, :+
132
- register_bundle_metadata_reducer '*/*', :map, SourceMapUtils.method(:concat_source_maps)
126
+ register_bundle_metadata_reducer '*/*', :map, proc { |input| { "version" => 3, "file" => PathUtils.split_subpath(input[:load_path], input[:filename]), "sections" => [] } }, SourceMapUtils.method(:concat_source_maps)
133
127
 
134
128
  require 'sprockets/closure_compressor'
135
129
  require 'sprockets/sass_compressor'
@@ -42,11 +42,11 @@ module Sprockets
42
42
 
43
43
  result = input[:cache].fetch(@cache_key + [input[:filename]] + [data]) do
44
44
  opts = {
45
- 'sourceRoot' => input[:load_path],
46
45
  'moduleRoot' => nil,
47
46
  'filename' => input[:filename],
48
47
  'filenameRelative' => PathUtils.split_subpath(input[:load_path], input[:filename]),
49
- 'sourceFileName' => input[:source_path]
48
+ 'sourceFileName' => File.basename(input[:filename]),
49
+ 'sourceMapTarget' => input[:filename]
50
50
  }.merge(@options)
51
51
 
52
52
  if opts['moduleIds'] && opts['moduleRoot']
@@ -57,8 +57,8 @@ module Sprockets
57
57
  Autoload::Babel::Transpiler.transform(data, opts)
58
58
  end
59
59
 
60
- map = SourceMapUtils.decode_json_source_map(JSON.generate(result['map']))
61
- map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map["mappings"])
60
+ map = SourceMapUtils.format_source_map(result["map"], input)
61
+ map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
62
62
 
63
63
  { data: result['code'], map: map }
64
64
  end
@@ -6,6 +6,7 @@ require 'sprockets/configuration'
6
6
  require 'sprockets/digest_utils'
7
7
  require 'sprockets/errors'
8
8
  require 'sprockets/loader'
9
+ require 'sprockets/npm'
9
10
  require 'sprockets/path_dependency_utils'
10
11
  require 'sprockets/path_digest_utils'
11
12
  require 'sprockets/path_utils'
@@ -22,6 +23,7 @@ module Sprockets
22
23
  include Server
23
24
  include Resolve, Loader
24
25
  include Bower
26
+ include Npm
25
27
 
26
28
  # Get persistent cache store
27
29
  attr_reader :cache
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require 'set'
3
3
  require 'sprockets/utils'
4
+ require 'sprockets/uri_utils'
4
5
 
5
6
  module Sprockets
6
7
  # Internal: Bundle processor takes a single file asset and prepends all the
@@ -16,15 +17,32 @@ module Sprockets
16
17
  def self.call(input)
17
18
  env = input[:environment]
18
19
  type = input[:content_type]
20
+ input[:links] ||= Set.new
19
21
  dependencies = Set.new(input[:metadata][:dependencies])
20
22
 
21
23
  processed_uri, deps = env.resolve(input[:filename], accept: type, pipeline: :self)
22
24
  dependencies.merge(deps)
23
25
 
26
+ # DirectiveProcessor (and any other transformers called here with pipeline=self)
27
+ primary_asset = env.load(processed_uri)
28
+ to_load = primary_asset.metadata.delete(:to_load) || Set.new
29
+ to_link = primary_asset.metadata.delete(:to_link) || Set.new
30
+
31
+ to_load.each do |uri|
32
+ loaded_asset = env.load(uri)
33
+ dependencies.merge(loaded_asset.metadata[:dependencies])
34
+ if to_link.include?(uri)
35
+ primary_metadata = primary_asset.metadata
36
+ input[:links] << loaded_asset.uri
37
+ primary_metadata[:links] << loaded_asset.uri
38
+ end
39
+ end
40
+
24
41
  find_required = proc { |uri| env.load(uri).metadata[:required] }
25
42
  required = Utils.dfs(processed_uri, &find_required)
26
43
  stubbed = Utils.dfs(env.load(processed_uri).metadata[:stubbed], &find_required)
27
44
  required.subtract(stubbed)
45
+ dedup(required)
28
46
  assets = required.map { |uri| env.load(uri) }
29
47
 
30
48
  (required + stubbed).each do |uri|
@@ -32,21 +50,38 @@ module Sprockets
32
50
  end
33
51
 
34
52
  reducers = Hash[env.match_mime_type_keys(env.config[:bundle_reducers], type).flat_map(&:to_a)]
35
- process_bundle_reducers(assets, reducers).merge(dependencies: dependencies, included: assets.map(&:uri))
53
+ process_bundle_reducers(input, assets, reducers).merge(dependencies: dependencies, included: assets.map(&:uri))
54
+ end
55
+
56
+ # Internal: Removes uri from required if it's already included as an alias.
57
+ #
58
+ # required - Set of required uris
59
+ #
60
+ # Returns deduped set of uris
61
+ def self.dedup(required)
62
+ dupes = required.reduce([]) do |r, uri|
63
+ path, params = URIUtils.parse_asset_uri(uri)
64
+ if (params.delete(:index_alias))
65
+ r << URIUtils.build_asset_uri(path, params)
66
+ end
67
+ r
68
+ end
69
+ required.subtract(dupes)
36
70
  end
37
71
 
38
72
  # Internal: Run bundle reducers on set of Assets producing a reduced
39
73
  # metadata Hash.
40
74
  #
75
+ # filename - String bundle filename
41
76
  # assets - Array of Assets
42
77
  # reducers - Array of [initial, reducer_proc] pairs
43
78
  #
44
79
  # Returns reduced asset metadata Hash.
45
- def self.process_bundle_reducers(assets, reducers)
80
+ def self.process_bundle_reducers(input, assets, reducers)
46
81
  initial = {}
47
82
  reducers.each do |k, (v, _)|
48
83
  if v.respond_to?(:call)
49
- initial[k] = v.call
84
+ initial[k] = v.call(input)
50
85
  elsif !v.nil?
51
86
  initial[k] = v
52
87
  end
@@ -36,6 +36,12 @@ module Sprockets
36
36
  #
37
37
  # Returns argument value.
38
38
  #
39
+ # clear(options)
40
+ #
41
+ # Clear the entire cache. Be careful with this method since it could
42
+ # affect other processes if shared cache is being used.
43
+ #
44
+ # The options hash is passed to the underlying cache implementation.
39
45
  class Cache
40
46
  # Builtin cache stores.
41
47
  autoload :FileStore, 'sprockets/cache/file_store'
@@ -144,6 +150,14 @@ module Sprockets
144
150
  "#<#{self.class} local=#{@fetch_cache.inspect} store=#{@cache_wrapper.cache.inspect}>"
145
151
  end
146
152
 
153
+ # Public: Clear cache
154
+ #
155
+ # Returns truthy on success, potentially raises exception on failure
156
+ def clear(options=nil)
157
+ @cache_wrapper.clear
158
+ @fetch_cache.clear
159
+ end
160
+
147
161
  private
148
162
  # Internal: Expand object cache key into a short String key.
149
163
  #
@@ -212,6 +226,16 @@ module Sprockets
212
226
  def set(key, value)
213
227
  cache.set(key, value)
214
228
  end
229
+
230
+ def clear(options=nil)
231
+ # dalli has a #flush method so try it
232
+ if cache.respond_to?(:flush)
233
+ cache.flush(options)
234
+ else
235
+ cache.clear(options)
236
+ end
237
+ true
238
+ end
215
239
  end
216
240
 
217
241
  class HashWrapper < Wrapper
@@ -222,6 +246,11 @@ module Sprockets
222
246
  def set(key, value)
223
247
  cache[key] = value
224
248
  end
249
+
250
+ def clear(options=nil)
251
+ cache.clear
252
+ true
253
+ end
225
254
  end
226
255
 
227
256
  class ReadWriteWrapper < Wrapper
@@ -232,6 +261,11 @@ module Sprockets
232
261
  def set(key, value)
233
262
  cache.write(key, value)
234
263
  end
264
+
265
+ def clear(options=nil)
266
+ cache.clear(options)
267
+ true
268
+ end
235
269
  end
236
270
  end
237
271
  end
@@ -20,7 +20,8 @@ module Sprockets
20
20
  class FileStore
21
21
  # Internal: Default key limit for store.
22
22
  DEFAULT_MAX_SIZE = 25 * 1024 * 1024
23
-
23
+ EXCLUDED_DIRS = ['.', '..'].freeze
24
+ GITKEEP_FILES = ['.gitkeep', '.keep'].freeze
24
25
  # Internal: Default standard error fatal logger.
25
26
  #
26
27
  # Returns a Logger.
@@ -123,6 +124,21 @@ module Sprockets
123
124
  "#<#{self.class} size=#{size}/#{@max_size}>"
124
125
  end
125
126
 
127
+ # Public: Clear the cache
128
+ #
129
+ # adapted from ActiveSupport::Cache::FileStore#clear
130
+ #
131
+ # Deletes all items from the cache. In this case it deletes all the entries in the specified
132
+ # file store directory except for .keep or .gitkeep. Be careful which directory is specified
133
+ # as @root because everything in that directory will be deleted.
134
+ #
135
+ # Returns true
136
+ def clear(options=nil)
137
+ root_dirs = Dir.entries(@root).reject { |f| (EXCLUDED_DIRS + GITKEEP_FILES).include?(f) }
138
+ FileUtils.rm_r(root_dirs.collect{ |f| File.join(@root, f) })
139
+ true
140
+ end
141
+
126
142
  private
127
143
  # Internal: Get all cache files along with stats.
128
144
  #
@@ -62,6 +62,14 @@ module Sprockets
62
62
  def inspect
63
63
  "#<#{self.class} size=#{@cache.size}/#{@max_size}>"
64
64
  end
65
+
66
+ # Public: Clear the cache
67
+ #
68
+ # Returns true
69
+ def clear(options=nil)
70
+ @cache.clear
71
+ true
72
+ end
65
73
  end
66
74
  end
67
75
  end
@@ -42,6 +42,13 @@ module Sprockets
42
42
  def inspect
43
43
  "#<#{self.class}>"
44
44
  end
45
+
46
+ # Public: Simulate clearing the cache
47
+ #
48
+ # Returns true
49
+ def clear(options=nil)
50
+ true
51
+ end
45
52
  end
46
53
  end
47
54
  end
@@ -16,12 +16,11 @@ module Sprockets
16
16
  initialize_configuration(environment)
17
17
 
18
18
  @cache = environment.cache
19
- @stats = Hash.new { |h, k| h[k] = _stat(k) }
20
- @entries = Hash.new { |h, k| h[k] = _entries(k) }
21
- @uris = Hash.new { |h, k| h[k] = _load(k) }
22
-
23
- @processor_cache_keys = Hash.new { |h, k| h[k] = _processor_cache_key(k) }
24
- @resolved_dependencies = Hash.new { |h, k| h[k] = _resolve_dependency(k) }
19
+ @stats = {}
20
+ @entries = {}
21
+ @uris = {}
22
+ @processor_cache_keys = {}
23
+ @resolved_dependencies = {}
25
24
  end
26
25
 
27
26
  # No-op return self as cached environment.
@@ -31,33 +30,28 @@ module Sprockets
31
30
  alias_method :index, :cached
32
31
 
33
32
  # Internal: Cache Environment#entries
34
- alias_method :_entries, :entries
35
33
  def entries(path)
36
- @entries[path]
34
+ @entries[path] ||= super(path)
37
35
  end
38
36
 
39
37
  # Internal: Cache Environment#stat
40
- alias_method :_stat, :stat
41
38
  def stat(path)
42
- @stats[path]
39
+ @stats[path] ||= super(path)
43
40
  end
44
41
 
45
42
  # Internal: Cache Environment#load
46
- alias_method :_load, :load
47
43
  def load(uri)
48
- @uris[uri]
44
+ @uris[uri] ||= super(uri)
49
45
  end
50
46
 
51
47
  # Internal: Cache Environment#processor_cache_key
52
- alias_method :_processor_cache_key, :processor_cache_key
53
48
  def processor_cache_key(str)
54
- @processor_cache_keys[str]
49
+ @processor_cache_keys[str] ||= super(str)
55
50
  end
56
51
 
57
52
  # Internal: Cache Environment#resolve_dependency
58
- alias_method :_resolve_dependency, :resolve_dependency
59
53
  def resolve_dependency(str)
60
- @resolved_dependencies[str]
54
+ @resolved_dependencies[str] ||= super(str)
61
55
  end
62
56
 
63
57
  private
@@ -21,11 +21,18 @@ module Sprockets
21
21
  data = input[:data]
22
22
 
23
23
  js, map = input[:cache].fetch([self.cache_key, data]) do
24
- result = Autoload::CoffeeScript.compile(data, sourceMap: true, sourceFiles: [input[:source_path]])
25
- [result['js'], SourceMapUtils.decode_json_source_map(result['v3SourceMap'])['mappings']]
24
+ result = Autoload::CoffeeScript.compile(
25
+ data,
26
+ sourceMap: "v3",
27
+ sourceFiles: [File.basename(input[:filename])],
28
+ generatedFile: input[:filename]
29
+ )
30
+ [result['js'], JSON.parse(result['v3SourceMap'])]
26
31
  end
27
32
 
33
+ map = SourceMapUtils.format_source_map(map, input)
28
34
  map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
35
+
29
36
  { data: js, map: map }
30
37
  end
31
38
  end
@@ -80,6 +80,9 @@ module Sprockets
80
80
  digest << val.to_s
81
81
  }
82
82
  end
83
+
84
+ ADD_VALUE_TO_DIGEST.compare_by_identity.rehash
85
+
83
86
  ADD_VALUE_TO_DIGEST.default_proc = ->(_, val) {
84
87
  raise TypeError, "couldn't digest #{ val }"
85
88
  }
@@ -70,20 +70,28 @@ module Sprockets
70
70
  @uri = input[:uri]
71
71
  @filename = input[:filename]
72
72
  @dirname = File.dirname(@filename)
73
- @content_type = input[:content_type]
73
+ # If loading a source map file like `application.js.map` resolve
74
+ # dependencies using `.js` instead of `.js.map`
75
+ @content_type = SourceMapProcessor.original_content_type(input[:content_type], error_when_not_found: false)
74
76
  @required = Set.new(input[:metadata][:required])
75
77
  @stubbed = Set.new(input[:metadata][:stubbed])
76
78
  @links = Set.new(input[:metadata][:links])
77
79
  @dependencies = Set.new(input[:metadata][:dependencies])
80
+ @to_link = Set.new
81
+ @to_load = Set.new
78
82
 
79
83
  data, directives = process_source(input[:data])
80
84
  process_directives(directives)
81
85
 
82
- { data: data,
83
- required: @required,
84
- stubbed: @stubbed,
85
- links: @links,
86
- dependencies: @dependencies }
86
+ {
87
+ data: data,
88
+ required: @required,
89
+ stubbed: @stubbed,
90
+ links: @links,
91
+ to_load: @to_load,
92
+ to_link: @to_link,
93
+ dependencies: @dependencies
94
+ }
87
95
  end
88
96
 
89
97
  protected
@@ -274,7 +282,7 @@ module Sprockets
274
282
  # //= depend_on_asset "bar.js"
275
283
  #
276
284
  def process_depend_on_asset_directive(path)
277
- load(resolve(path))
285
+ to_load(resolve(path))
278
286
  end
279
287
 
280
288
  # Allows dependency to be excluded from the asset bundle.
@@ -298,7 +306,8 @@ module Sprockets
298
306
  # /*= link "logo.png" */
299
307
  #
300
308
  def process_link_directive(path)
301
- @links << load(resolve(path)).uri
309
+ uri = to_load(resolve(path))
310
+ @to_link << uri
302
311
  end
303
312
 
304
313
  # `link_directory` links all the files inside a single
@@ -355,7 +364,7 @@ module Sprockets
355
364
 
356
365
  def link_paths(paths, deps, accept)
357
366
  resolve_paths(paths, deps, accept: accept) do |uri|
358
- @links << load(uri).uri
367
+ @to_link << to_load(uri)
359
368
  end
360
369
  end
361
370
 
@@ -385,10 +394,9 @@ module Sprockets
385
394
  end
386
395
  end
387
396
 
388
- def load(uri)
389
- asset = @environment.load(uri)
390
- @dependencies.merge(asset.metadata[:dependencies])
391
- asset
397
+ def to_load(uri)
398
+ @to_load << uri
399
+ uri
392
400
  end
393
401
 
394
402
  def resolve(path, **kargs)