1
+ // Adapted from https://github.com/sysgears/webpack-virtual-modules
2
+ // MIT Licensed https://github.com/sysgears/webpack-virtual-modules/blob/master/LICENSE
3
+ /*
4
+ MIT License
5
+ Copyright (c) 2017 SysGears
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
21
+ */
22
+
1
23
var VirtualStats = require ( './virtual-stats' ) ;
24
+ var path = require ( "path" ) ;
2
25
3
26
var inode = 45000000 ;
4
27
5
- // Adapted from https://github.com/sysgears/webpack-virtual-modules
6
- // MIT Licensed https://github.com/sysgears/webpack-virtual-modules/blob/master/LICENSE
28
+ function createWebpackData ( result ) {
29
+ return ( function ( backendOrStorage ) {
30
+ // In Webpack v5, this variable is a "Backend", and has the data stored in a field
31
+ // _data. In V4, the `_` prefix isn't present.
32
+ if ( backendOrStorage . _data ) {
33
+ const curLevelIdx = backendOrStorage . _currentLevel ;
34
+ const curLevel = backendOrStorage . _levels [ curLevelIdx ] ;
35
+ return {
36
+ result : this . result ,
37
+ level : curLevel
38
+ } ;
39
+ }
40
+ // Webpack 4
41
+ return [ null , result ] ;
42
+ } ) . bind ( { result : result } ) ;
43
+ }
7
44
8
45
/**
9
46
* @param {Compiler } compiler - the webpack compiler
@@ -16,24 +53,64 @@ function VirtualModulesPlugin(compiler) {
16
53
17
54
compiler . inputFileSystem . purge = function ( ) {
18
55
if ( originalPurge ) {
19
- originalPurge . call ( this , arguments ) ;
56
+ originalPurge . apply ( this , arguments ) ;
20
57
}
21
58
if ( this . _virtualFiles ) {
22
- Object . keys ( this . _virtualFiles ) . forEach (
23
- function ( file ) {
24
- var data = this . _virtualFiles [ file ] ;
25
- setData ( this . _statStorage , file , [ null , data . stats ] ) ;
26
- setData ( this . _readFileStorage , file , [ null , data . contents ] ) ;
27
- } . bind ( this )
28
- ) ;
59
+ Object . keys ( this . _virtualFiles ) . forEach ( function ( file ) {
60
+ var data = this . _virtualFiles [ file ] ;
61
+ this . _writeVirtualFile ( file , data . stats , data . contents ) ;
62
+ } . bind ( this ) ) ;
29
63
}
30
64
} ;
31
65
32
66
compiler . inputFileSystem . _writeVirtualFile = function ( file , stats , contents ) {
67
+ const statStorage = getStatStorage ( this ) ;
68
+ const fileStorage = getFileStorage ( this ) ;
69
+ const readDirStorage = getReadDirBackend ( this ) ;
33
70
this . _virtualFiles = this . _virtualFiles || { } ;
34
71
this . _virtualFiles [ file ] = { stats : stats , contents : contents } ;
35
- setData ( this . _statStorage , file , [ null , stats ] ) ;
36
- setData ( this . _readFileStorage , file , [ null , contents ] ) ;
72
+ setData ( statStorage , file , createWebpackData ( stats ) ) ;
73
+ setData ( fileStorage , file , createWebpackData ( contents ) ) ;
74
+ var segments = file . split ( / [ \\ / ] / ) ;
75
+ var count = segments . length - 1 ;
76
+ var minCount = segments [ 0 ] ? 1 : 0 ;
77
+ while ( count > minCount ) {
78
+ var dir = segments . slice ( 0 , count ) . join ( path . sep ) || path . sep ;
79
+ try {
80
+ compiler . inputFileSystem . readdirSync ( dir ) ;
81
+ } catch ( e ) {
82
+ var time = Date . now ( ) ;
83
+ var dirStats = new VirtualStats ( {
84
+ dev : 8675309 ,
85
+ nlink : 0 ,
86
+ uid : 1000 ,
87
+ gid : 1000 ,
88
+ rdev : 0 ,
89
+ blksize : 4096 ,
90
+ ino : inode ++ ,
91
+ mode : 16877 ,
92
+ size : stats . size ,
93
+ blocks : Math . floor ( stats . size / 4096 ) ,
94
+ atime : time ,
95
+ mtime : time ,
96
+ ctime : time ,
97
+ birthtime : time
98
+ } ) ;
99
+ setData ( readDirStorage , dir , createWebpackData ( [ ] ) ) ;
100
+ setData ( statStorage , dir , createWebpackData ( dirStats ) ) ;
101
+ }
102
+ var dirData = getData ( getReadDirBackend ( this ) , dir ) ;
103
+ // Webpack v4 returns an array, webpack v5 returns an object
104
+ dirData = dirData [ 1 ] || dirData . result ;
105
+ var filename = segments [ count ] ;
106
+ if ( dirData . indexOf ( filename ) < 0 ) {
107
+ var files = dirData . concat ( [ filename ] ) . sort ( ) ;
108
+ setData ( getReadDirBackend ( this ) , dir , createWebpackData ( files ) ) ;
109
+ } else {
110
+ break ;
111
+ }
112
+ count -- ;
113
+ }
37
114
} ;
38
115
}
39
116
@@ -75,14 +152,81 @@ VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) {
75
152
birthtime : time
76
153
} ) ;
77
154
155
+ // When using the WatchIgnorePlugin (https://github.com/webpack/webpack/blob/52184b897f40c75560b3630e43ca642fcac7e2cf/lib/WatchIgnorePlugin.js),
156
+ // the original watchFileSystem is stored in `wfs`. The following "unwraps" the ignoring
157
+ // wrappers, giving us access to the "real" watchFileSystem.
158
+ let finalWatchFileSystem = this . _watcher && this . _watcher . watchFileSystem ;
159
+
160
+ while ( finalWatchFileSystem && finalWatchFileSystem . wfs ) {
161
+ finalWatchFileSystem = finalWatchFileSystem . wfs ;
162
+ }
78
163
this . compiler . inputFileSystem . _writeVirtualFile ( filePath , stats , contents ) ;
79
164
} ;
80
165
81
- function setData ( storage , key , value ) {
82
- if ( storage . data instanceof Map ) {
83
- storage . data . set ( key , value ) ;
166
+ function getData ( storage , key ) {
167
+ // Webpack 5
168
+ if ( storage . _data instanceof Map ) {
169
+ return storage . _data . get ( key ) ;
170
+ } else if ( storage . _data ) {
171
+ return storage . data [ key ] ;
172
+ } else if ( storage . data instanceof Map ) {
173
+ // Webpack v4
174
+ return storage . data . get ( key ) ;
175
+ } else {
176
+ return storage . data [ key ] ;
177
+ }
178
+ }
179
+
180
+ function setData ( backendOrStorage , key , valueFactory ) {
181
+ const value = valueFactory ( backendOrStorage ) ;
182
+
183
+ // Webpack v5
184
+ if ( backendOrStorage . _data instanceof Map ) {
185
+ backendOrStorage . _data . set ( key , value ) ;
186
+ } else if ( backendOrStorage . _data ) {
187
+ backendOrStorage . data [ key ] = value ;
188
+ } else if ( backendOrStorage . data instanceof Map ) {
189
+ // Webpack 4
190
+ backendOrStorage . data . set ( key , value ) ;
191
+ backendOrStorage . data . set ( key , value ) ;
192
+ } else {
193
+ backendOrStorage . data [ key ] = value ;
194
+ backendOrStorage . data [ key ] = value ;
195
+ }
196
+ }
197
+
198
+ function getStatStorage ( fileSystem ) {
199
+ if ( fileSystem . _statStorage ) {
200
+ // Webpack v4
201
+ return fileSystem . _statStorage ;
202
+ } else if ( fileSystem . _statBackend ) {
203
+ // webpack v5
204
+ return fileSystem . _statBackend ;
205
+ } else {
206
+ // Unknown version?
207
+ throw new Error ( "Couldn't find a stat storage" ) ;
208
+ }
209
+ }
210
+
211
+ function getFileStorage ( fileSystem ) {
212
+ if ( fileSystem . _readFileStorage ) {
213
+ // Webpack v4
214
+ return fileSystem . _readFileStorage ;
215
+ } else if ( fileSystem . _readFileBackend ) {
216
+ // Webpack v5
217
+ return fileSystem . _readFileBackend ;
218
+ } else {
219
+ throw new Error ( "Couldn't find a readFileStorage" ) ;
220
+ }
221
+ }
222
+
223
+ function getReadDirBackend ( fileSystem ) {
224
+ if ( fileSystem . _readdirBackend ) {
225
+ return fileSystem . _readdirBackend ;
226
+ } else if ( fileSystem . _readdirStorage ) {
227
+ return fileSystem . _readdirStorage ;
84
228
} else {
85
- storage . data [ key ] = value ;
229
+ throw new Error ( "Couldn't find a readDirStorage from Webpack Internals" ) ;
86
230
}
87
231
}
88
232
0 commit comments