1
+ // Adapted from https://github.com/sysgears/webpack-virtual-modules
2
+
1
3
var VirtualStats = require ( './virtual-stats' ) ;
4
+ var path = require ( "path" ) ;
2
5
3
6
var inode = 45000000 ;
4
7
5
- // Adapted from https://github.com/sysgears/webpack-virtual-modules
6
- // MIT Licensed https://github.com/sysgears/webpack-virtual-modules/blob/master/LICENSE
8
+ function createWebpackData ( result ) {
9
+ return ( function ( backendOrStorage ) {
10
+ // In Webpack v5, this variable is a "Backend", and has the data stored in a field
11
+ // _data. In V4, the `_` prefix isn't present.
12
+ if ( backendOrStorage . _data ) {
13
+ const curLevelIdx = backendOrStorage . _currentLevel ;
14
+ const curLevel = backendOrStorage . _levels [ curLevelIdx ] ;
15
+ return {
16
+ result : this . result ,
17
+ level : curLevel
18
+ } ;
19
+ }
20
+ // Webpack 4
21
+ return [ null , result ] ;
22
+ } ) . bind ( { result : result } ) ;
23
+ }
7
24
8
25
/**
9
26
* @param {Compiler } compiler - the webpack compiler
@@ -16,24 +33,69 @@ function VirtualModulesPlugin(compiler) {
16
33
17
34
compiler . inputFileSystem . purge = function ( ) {
18
35
if ( originalPurge ) {
19
- originalPurge . call ( this , arguments ) ;
36
+ originalPurge . apply ( this , arguments ) ;
20
37
}
21
38
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
- ) ;
39
+ Object . keys ( this . _virtualFiles ) . forEach ( function ( file ) {
40
+ var data = this . _virtualFiles [ file ] ;
41
+ this . _writeVirtualFile ( file , data . stats , data . contents ) ;
42
+ } . bind ( this ) ) ;
29
43
}
30
44
} ;
31
45
32
46
compiler . inputFileSystem . _writeVirtualFile = function ( file , stats , contents ) {
47
+ const statStorage = getStatStorage ( this ) ;
48
+ const fileStorage = getFileStorage ( this ) ;
49
+ const readDirStorage = getReadDirBackend ( this ) ;
33
50
this . _virtualFiles = this . _virtualFiles || { } ;
34
51
this . _virtualFiles [ file ] = { stats : stats , contents : contents } ;
35
- setData ( this . _statStorage , file , [ null , stats ] ) ;
36
- setData ( this . _readFileStorage , file , [ null , contents ] ) ;
52
+ setData ( statStorage , file , createWebpackData ( stats ) ) ;
53
+ setData ( fileStorage , file , createWebpackData ( contents ) ) ;
54
+ var segments = file . split ( / [ \\ / ] / ) ;
55
+ var count = segments . length - 1 ;
56
+ var minCount = segments [ 0 ] ? 1 : 0 ;
57
+ while ( count > minCount ) {
58
+ var dir = segments . slice ( 0 , count ) . join ( path . sep ) || path . sep ;
59
+ try {
60
+ compiler . inputFileSystem . readdirSync ( dir ) ;
61
+ } catch ( e ) {
62
+ var time = new Date ( ) ;
63
+ var timeMs = time . getTime ( ) ;
64
+ var dirStats = new VirtualStats ( {
65
+ dev : 8675309 ,
66
+ nlink : 0 ,
67
+ uid : 1000 ,
68
+ gid : 1000 ,
69
+ rdev : 0 ,
70
+ blksize : 4096 ,
71
+ ino : inode ++ ,
72
+ mode : 16877 ,
73
+ size : stats . size ,
74
+ blocks : Math . floor ( stats . size / 4096 ) ,
75
+ atimeMs : timeMs ,
76
+ mtimeMs : timeMs ,
77
+ ctimeMs : timeMs ,
78
+ birthtimeMs : timeMs ,
79
+ atime : time ,
80
+ mtime : time ,
81
+ ctime : time ,
82
+ birthtime : time
83
+ } ) ;
84
+ setData ( readDirStorage , dir , createWebpackData ( [ ] ) ) ;
85
+ setData ( statStorage , dir , createWebpackData ( dirStats ) ) ;
86
+ }
87
+ var dirData = getData ( getReadDirBackend ( this ) , dir ) ;
88
+ // Webpack v4 returns an array, webpack v5 returns an object
89
+ dirData = dirData [ 1 ] || dirData . result ;
90
+ var filename = segments [ count ] ;
91
+ if ( dirData . indexOf ( filename ) < 0 ) {
92
+ var files = dirData . concat ( [ filename ] ) . sort ( ) ;
93
+ setData ( getReadDirBackend ( this ) , dir , createWebpackData ( files ) ) ;
94
+ } else {
95
+ break ;
96
+ }
97
+ count -- ;
98
+ }
37
99
} ;
38
100
}
39
101
@@ -75,14 +137,81 @@ VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) {
75
137
birthtime : time
76
138
} ) ;
77
139
140
+ // When using the WatchIgnorePlugin (https://github.com/webpack/webpack/blob/52184b897f40c75560b3630e43ca642fcac7e2cf/lib/WatchIgnorePlugin.js),
141
+ // the original watchFileSystem is stored in `wfs`. The following "unwraps" the ignoring
142
+ // wrappers, giving us access to the "real" watchFileSystem.
143
+ let finalWatchFileSystem = this . _watcher && this . _watcher . watchFileSystem ;
144
+
145
+ while ( finalWatchFileSystem && finalWatchFileSystem . wfs ) {
146
+ finalWatchFileSystem = finalWatchFileSystem . wfs ;
147
+ }
78
148
this . compiler . inputFileSystem . _writeVirtualFile ( filePath , stats , contents ) ;
79
149
} ;
80
150
81
- function setData ( storage , key , value ) {
82
- if ( storage . data instanceof Map ) {
83
- storage . data . set ( key , value ) ;
151
+ function getData ( storage , key ) {
152
+ // Webpack 5
153
+ if ( storage . _data instanceof Map ) {
154
+ return storage . _data . get ( key ) ;
155
+ } else if ( storage . _data ) {
156
+ return storage . data [ key ] ;
157
+ } else if ( storage . data instanceof Map ) {
158
+ // Webpack v4
159
+ return storage . data . get ( key ) ;
160
+ } else {
161
+ return storage . data [ key ] ;
162
+ }
163
+ }
164
+
165
+ function setData ( backendOrStorage , key , valueFactory ) {
166
+ const value = valueFactory ( backendOrStorage ) ;
167
+
168
+ // Webpack v5
169
+ if ( backendOrStorage . _data instanceof Map ) {
170
+ backendOrStorage . _data . set ( key , value ) ;
171
+ } else if ( backendOrStorage . _data ) {
172
+ backendOrStorage . data [ key ] = value ;
173
+ } else if ( backendOrStorage . data instanceof Map ) {
174
+ // Webpack 4
175
+ backendOrStorage . data . set ( key , value ) ;
176
+ backendOrStorage . data . set ( key , value ) ;
177
+ } else {
178
+ backendOrStorage . data [ key ] = value ;
179
+ backendOrStorage . data [ key ] = value ;
180
+ }
181
+ }
182
+
183
+ function getStatStorage ( fileSystem ) {
184
+ if ( fileSystem . _statStorage ) {
185
+ // Webpack v4
186
+ return fileSystem . _statStorage ;
187
+ } else if ( fileSystem . _statBackend ) {
188
+ // webpack v5
189
+ return fileSystem . _statBackend ;
190
+ } else {
191
+ // Unknown version?
192
+ throw new Error ( "Couldn't find a stat storage" ) ;
193
+ }
194
+ }
195
+
196
+ function getFileStorage ( fileSystem ) {
197
+ if ( fileSystem . _readFileStorage ) {
198
+ // Webpack v4
199
+ return fileSystem . _readFileStorage ;
200
+ } else if ( fileSystem . _readFileBackend ) {
201
+ // Webpack v5
202
+ return fileSystem . _readFileBackend ;
203
+ } else {
204
+ throw new Error ( "Couldn't find a readFileStorage" ) ;
205
+ }
206
+ }
207
+
208
+ function getReadDirBackend ( fileSystem ) {
209
+ if ( fileSystem . _readdirBackend ) {
210
+ return fileSystem . _readdirBackend ;
211
+ } else if ( fileSystem . _readdirStorage ) {
212
+ return fileSystem . _readdirStorage ;
84
213
} else {
85
- storage . data [ key ] = value ;
214
+ throw new Error ( "Couldn't find a readDirStorage from Webpack Internals" ) ;
86
215
}
87
216
}
88
217
0 commit comments