@@ -14,19 +14,37 @@ function WebIntegrityJsonpMainTemplatePlugin(sriPlugin, compilation) {
1414 this . compilation = compilation ;
1515}
1616
17- WebIntegrityJsonpMainTemplatePlugin . prototype . apply = function apply ( mainTemplate ) {
18- var self = this ;
17+ function addSriHashes ( plugin , chunk , source ) {
1918 var allDepChunkIds = { } ;
20-
21- function findDepChunks ( chunk ) {
22- chunk . chunks . forEach ( function forEachChunk ( depChunk ) {
19+ function findDepChunks ( childChunk ) {
20+ childChunk . chunks . forEach ( function forEachChunk ( depChunk ) {
2321 if ( ! allDepChunkIds [ depChunk . id ] ) {
2422 allDepChunkIds [ depChunk . id ] = true ;
2523 findDepChunks ( depChunk ) ;
2624 }
2725 } ) ;
2826 }
2927
28+ if ( chunk . chunks . length > 0 ) {
29+ findDepChunks ( chunk ) ;
30+
31+ return plugin . asString ( [
32+ source ,
33+ 'var sriHashes = ' + JSON . stringify (
34+ Object . keys ( allDepChunkIds ) . reduce ( function chunkIdReducer ( sriHashes , chunkId ) {
35+ sriHashes [ chunkId ] = makePlaceholder ( chunkId ) ; // eslint-disable-line no-param-reassign
36+ return sriHashes ;
37+ } , { } )
38+ ) + ';'
39+ ] ) ;
40+ }
41+
42+ return source ;
43+ }
44+
45+ WebIntegrityJsonpMainTemplatePlugin . prototype . apply = function apply ( mainTemplate ) {
46+ var self = this ;
47+
3048 /*
3149 * Patch jsonp-script code to add the integrity attribute.
3250 */
@@ -50,20 +68,7 @@ WebIntegrityJsonpMainTemplatePlugin.prototype.apply = function apply(mainTemplat
5068 * later.
5169 */
5270 mainTemplate . plugin ( 'local-vars' , function localVarsPlugin ( source , chunk ) {
53- if ( chunk . chunks . length > 0 ) {
54- findDepChunks ( chunk ) ;
55-
56- return this . asString ( [
57- source ,
58- 'var sriHashes = ' + JSON . stringify (
59- Object . keys ( allDepChunkIds ) . reduce ( function chunkIdReducer ( sriHashes , chunkId ) {
60- sriHashes [ chunkId ] = makePlaceholder ( chunkId ) ; // eslint-disable-line no-param-reassign
61- return sriHashes ;
62- } , { } )
63- ) + ';'
64- ] ) ;
65- }
66- return source ;
71+ return addSriHashes ( this , chunk , source ) ;
6772 } ) ;
6873} ;
6974
@@ -167,15 +172,105 @@ SubresourceIntegrityPlugin.prototype.hwpAssetPath = function hwpAssetPath(src) {
167172 return path . relative ( this . hwpPublicPath , src ) ;
168173} ;
169174
170- SubresourceIntegrityPlugin . prototype . apply = function apply ( compiler ) {
175+ function computeIntegrity ( hashFuncNames , source ) {
176+ return hashFuncNames . map ( function mapHashFuncName ( hashFuncName ) {
177+ var hash = crypto . createHash ( hashFuncName ) . update ( source , 'utf8' ) . digest ( 'base64' ) ;
178+ return hashFuncName + '-' + hash ;
179+ } ) . join ( ' ' ) ;
180+ }
181+
182+ SubresourceIntegrityPlugin . prototype . warnIfHotUpdate = function warnIfHotUpdate (
183+ compilation , source
184+ ) {
185+ if ( source . indexOf ( 'webpackHotUpdate' ) >= 0 ) {
186+ this . warnOnce (
187+ compilation ,
188+ 'webpack-subresource-integrity may interfere with hot reloading. ' +
189+ 'Consider disabling this plugin in development mode.'
190+ ) ;
191+ }
192+ } ;
193+
194+ SubresourceIntegrityPlugin . prototype . replaceAsset = function replaceAsset (
195+ assets ,
196+ depChunkIds ,
197+ hashByChunkId ,
198+ chunkFile
199+ ) {
200+ var oldSource = assets [ chunkFile ] . source ( ) ;
201+ var newAsset ;
202+ var magicMarker ;
203+ var magicMarkerPos ;
204+
205+ newAsset = new ReplaceSource ( assets [ chunkFile ] ) ;
206+
207+ depChunkIds . forEach ( function replaceMagicMarkers ( depChunkId ) {
208+ magicMarker = makePlaceholder ( depChunkId ) ;
209+ magicMarkerPos = oldSource . indexOf ( magicMarker ) ;
210+ if ( magicMarkerPos >= 0 ) {
211+ newAsset . replace (
212+ magicMarkerPos ,
213+ ( magicMarkerPos + magicMarker . length ) - 1 ,
214+ hashByChunkId [ depChunkId ] ) ;
215+ }
216+ } ) ;
217+
218+ // eslint-disable-next-line no-param-reassign
219+ assets [ chunkFile ] = newAsset ;
220+
221+ newAsset . integrity = computeIntegrity ( this . options . hashFuncNames , newAsset . source ( ) ) ;
222+ return newAsset ;
223+ } ;
224+
225+ SubresourceIntegrityPlugin . prototype . processChunk = function processChunk (
226+ chunk , compilation , assets
227+ ) {
171228 var self = this ;
229+ var newAsset ;
230+ var hashByChunkId = { } ;
231+
232+ function recurse ( childChunk ) {
233+ var depChunkIds = [ ] ;
172234
173- function computeIntegrity ( source ) {
174- return self . options . hashFuncNames . map ( function mapHashFuncName ( hashFuncName ) {
175- var hash = crypto . createHash ( hashFuncName ) . update ( source , 'utf8' ) . digest ( 'base64' ) ;
176- return hashFuncName + '-' + hash ;
177- } ) . join ( ' ' ) ;
235+ if ( hashByChunkId [ childChunk . id ] ) {
236+ return [ ] ;
237+ }
238+ hashByChunkId [ childChunk . id ] = true ;
239+
240+ childChunk . chunks . forEach ( function mapChunk ( depChunk ) {
241+ depChunkIds = depChunkIds . concat ( recurse ( depChunk ) ) ;
242+ } ) ;
243+
244+ if ( childChunk . files . length > 0 ) {
245+ self . warnIfHotUpdate ( compilation , assets [ childChunk . files [ 0 ] ] . source ( ) ) ;
246+ newAsset = self . replaceAsset (
247+ assets ,
248+ depChunkIds ,
249+ hashByChunkId ,
250+ childChunk . files [ 0 ] ) ;
251+ hashByChunkId [ childChunk . id ] = newAsset . integrity ;
252+ }
253+ return [ childChunk . id ] . concat ( depChunkIds ) ;
178254 }
255+ return recurse ( chunk ) ;
256+ } ;
257+
258+ function getTagSrc ( tag ) {
259+ // Get asset path - src from scripts and href from links
260+ return tag . attributes . href || tag . attributes . src ;
261+ }
262+
263+ function filterTag ( tag ) {
264+ // Process only script and link tags with a url
265+ return ( tag . tagName === 'script' || tag . tagName === 'link' ) && getTagSrc ( tag ) ;
266+ }
267+
268+ function normalizePath ( p ) {
269+ return p . replace ( / \? .* $ / , '' ) . split ( path . sep ) . join ( '/' ) ;
270+ }
271+
272+ SubresourceIntegrityPlugin . prototype . apply = function apply ( compiler ) {
273+ var self = this ;
179274
180275 compiler . plugin ( 'after-plugins' , function afterPlugins ( ) {
181276 compiler . plugin ( 'this-compilation' , function thisCompilation ( compilation ) {
@@ -192,94 +287,22 @@ SubresourceIntegrityPlugin.prototype.apply = function apply(compiler) {
192287 * placeholders by the actual values.
193288 */
194289 compilation . plugin ( 'after-optimize-assets' , function optimizeAssetsPlugin ( assets ) {
195- var hashByChunkId = { } ;
196- var visitedByChunkId = { } ;
197- var chunkFile ;
198- var oldSource ;
199- var magicMarker ;
200- var magicMarkerPos ;
201- var newAsset ;
202290 var asset ;
203- var newSource ;
204-
205- function processChunkRecursive ( chunk ) {
206- var depChunkIds = [ ] ;
207-
208- if ( visitedByChunkId [ chunk . id ] ) {
209- return [ ] ;
210- }
211- visitedByChunkId [ chunk . id ] = true ;
212-
213- chunk . chunks . forEach ( function mapChunk ( depChunk ) {
214- depChunkIds = depChunkIds . concat ( processChunkRecursive ( depChunk ) ) ;
215- } ) ;
216-
217- if ( chunk . files . length > 0 ) {
218- chunkFile = chunk . files [ 0 ] ;
219-
220- oldSource = assets [ chunkFile ] . source ( ) ;
221-
222- if ( oldSource . indexOf ( 'webpackHotUpdate' ) >= 0 ) {
223- self . warnOnce (
224- compilation ,
225- 'webpack-subresource-integrity may interfere with hot reloading. ' +
226- 'Consider disabling this plugin in development mode.'
227- ) ;
228- }
229-
230- newAsset = new ReplaceSource ( assets [ chunkFile ] ) ;
231-
232- depChunkIds . forEach ( function forEachChunk ( depChunkId ) {
233- magicMarker = makePlaceholder ( depChunkId ) ;
234- magicMarkerPos = oldSource . indexOf ( magicMarker ) ;
235- if ( magicMarkerPos >= 0 ) {
236- newAsset . replace (
237- magicMarkerPos ,
238- ( magicMarkerPos + magicMarker . length ) - 1 ,
239- hashByChunkId [ depChunkId ] ) ;
240- }
241- } ) ;
242-
243- // eslint-disable-next-line no-param-reassign
244- assets [ chunkFile ] = newAsset ;
245-
246- newSource = newAsset . source ( ) ;
247- newAsset . integrity = computeIntegrity ( newSource ) ;
248- hashByChunkId [ chunk . id ] = newAsset . integrity ;
249- }
250- return [ chunk . id ] . concat ( depChunkIds ) ;
251- }
252291
253292 compilation . chunks . forEach ( function forEachChunk ( chunk ) {
254- // chunk.entry was removed in Webpack 2. Use hasRuntime()
255- // for this check instead (if it exists)
256293 if ( ( 'hasRuntime' in chunk ) ? chunk . hasRuntime ( ) : chunk . entry ) {
257- processChunkRecursive ( chunk ) ;
294+ self . processChunk ( chunk , compilation , assets ) ;
258295 }
259296 } ) ;
260297
261298 Object . keys ( assets ) . forEach ( function loop ( assetKey ) {
262299 asset = assets [ assetKey ] ;
263300 if ( ! asset . integrity ) {
264- asset . integrity = computeIntegrity ( asset . source ( ) ) ;
301+ asset . integrity = computeIntegrity ( self . options . hashFuncNames , asset . source ( ) ) ;
265302 }
266303 } ) ;
267304 } ) ;
268305
269- function getTagSrc ( tag ) {
270- // Get asset path - src from scripts and href from links
271- return tag . attributes . href || tag . attributes . src ;
272- }
273-
274- function filterTag ( tag ) {
275- // Process only script and link tags with a url
276- return ( tag . tagName === 'script' || tag . tagName === 'link' ) && getTagSrc ( tag ) ;
277- }
278-
279- function normalizePath ( p ) {
280- return p . replace ( / \? .* $ / , '' ) . split ( path . sep ) . join ( '/' ) ;
281- }
282-
283306 function getIntegrityChecksumForAsset ( src ) {
284307 var normalizedSrc ;
285308 var normalizedKey ;
0 commit comments