|
5 | 5 | * Use of this source code is governed by an MIT-style license that can be
|
6 | 6 | * found in the LICENSE file at https://angular.io/license
|
7 | 7 | */
|
| 8 | +import { Path, getSystemPath, normalize } from '@angular-devkit/core'; |
8 | 9 | import { Stats } from 'fs';
|
9 | 10 | import { WebpackCompilerHost } from './compiler_host';
|
10 | 11 | import { Callback, InputFileSystem, NodeWatchFileSystemInterface } from './webpack';
|
@@ -105,38 +106,104 @@ export class VirtualFileSystemDecorator implements InputFileSystem {
|
105 | 106 | }
|
106 | 107 |
|
107 | 108 | export class VirtualWatchFileSystemDecorator extends NodeWatchFileSystem {
|
108 |
| - constructor(private _virtualInputFileSystem: VirtualFileSystemDecorator) { |
| 109 | + constructor( |
| 110 | + private _virtualInputFileSystem: VirtualFileSystemDecorator, |
| 111 | + private _replacements?: Map<Path, Path>, |
| 112 | + ) { |
109 | 113 | super(_virtualInputFileSystem);
|
110 | 114 | }
|
111 | 115 |
|
112 | 116 | watch(
|
113 |
| - files: any, // tslint:disable-line:no-any |
114 |
| - dirs: any, // tslint:disable-line:no-any |
115 |
| - missing: any, // tslint:disable-line:no-any |
116 |
| - startTime: any, // tslint:disable-line:no-any |
117 |
| - options: any, // tslint:disable-line:no-any |
| 117 | + files: string[], |
| 118 | + dirs: string[], |
| 119 | + missing: string[], |
| 120 | + startTime: number | undefined, |
| 121 | + options: {}, |
118 | 122 | callback: any, // tslint:disable-line:no-any
|
119 |
| - callbackUndelayed: any, // tslint:disable-line:no-any |
| 123 | + callbackUndelayed: (filename: string, timestamp: number) => void, |
120 | 124 | ) {
|
| 125 | + const reverseReplacements = new Map<string, string>(); |
| 126 | + const reverseTimestamps = (map: Map<string, number>) => { |
| 127 | + for (const entry of Array.from(map.entries())) { |
| 128 | + const original = reverseReplacements.get(entry[0]); |
| 129 | + if (original) { |
| 130 | + map.set(original, entry[1]); |
| 131 | + map.delete(entry[0]); |
| 132 | + } |
| 133 | + } |
| 134 | + |
| 135 | + return map; |
| 136 | + }; |
| 137 | + |
| 138 | + const newCallbackUndelayed = (filename: string, timestamp: number) => { |
| 139 | + const original = reverseReplacements.get(filename); |
| 140 | + if (original) { |
| 141 | + this._virtualInputFileSystem.purge(original); |
| 142 | + callbackUndelayed(original, timestamp); |
| 143 | + } else { |
| 144 | + callbackUndelayed(filename, timestamp); |
| 145 | + } |
| 146 | + }; |
| 147 | + |
121 | 148 | const newCallback = (
|
122 |
| - err: any, // tslint:disable-line:no-any |
123 |
| - filesModified: any, // tslint:disable-line:no-any |
124 |
| - contextModified: any, // tslint:disable-line:no-any |
125 |
| - missingModified: any, // tslint:disable-line:no-any |
126 |
| - fileTimestamps: { [k: string]: number }, |
127 |
| - contextTimestamps: { [k: string]: number }, |
| 149 | + err: Error | null, |
| 150 | + filesModified: string[], |
| 151 | + contextModified: string[], |
| 152 | + missingModified: string[], |
| 153 | + fileTimestamps: Map<string, number>, |
| 154 | + contextTimestamps: Map<string, number>, |
128 | 155 | ) => {
|
129 | 156 | // Update fileTimestamps with timestamps from virtual files.
|
130 | 157 | const virtualFilesStats = this._virtualInputFileSystem.getVirtualFilesPaths()
|
131 | 158 | .map((fileName) => ({
|
132 | 159 | path: fileName,
|
133 | 160 | mtime: +this._virtualInputFileSystem.statSync(fileName).mtime,
|
134 | 161 | }));
|
135 |
| - virtualFilesStats.forEach(stats => fileTimestamps[stats.path] = +stats.mtime); |
136 |
| - callback(err, filesModified, contextModified, missingModified, fileTimestamps, |
137 |
| - contextTimestamps); |
| 162 | + virtualFilesStats.forEach(stats => fileTimestamps.set(stats.path, +stats.mtime)); |
| 163 | + callback( |
| 164 | + err, |
| 165 | + filesModified.map(value => reverseReplacements.get(value) || value), |
| 166 | + contextModified.map(value => reverseReplacements.get(value) || value), |
| 167 | + missingModified.map(value => reverseReplacements.get(value) || value), |
| 168 | + reverseTimestamps(fileTimestamps), |
| 169 | + reverseTimestamps(contextTimestamps), |
| 170 | + ); |
| 171 | + }; |
| 172 | + |
| 173 | + const mapReplacements = (original: string[]): string[] => { |
| 174 | + if (!this._replacements) { |
| 175 | + return original; |
| 176 | + } |
| 177 | + const replacements = this._replacements; |
| 178 | + |
| 179 | + return original.map(file => { |
| 180 | + const replacement = replacements.get(normalize(file)); |
| 181 | + if (replacement) { |
| 182 | + const fullReplacement = getSystemPath(replacement); |
| 183 | + reverseReplacements.set(fullReplacement, file); |
| 184 | + |
| 185 | + return fullReplacement; |
| 186 | + } else { |
| 187 | + return file; |
| 188 | + } |
| 189 | + }); |
138 | 190 | };
|
139 | 191 |
|
140 |
| - return super.watch(files, dirs, missing, startTime, options, newCallback, callbackUndelayed); |
| 192 | + const watcher = super.watch( |
| 193 | + mapReplacements(files), |
| 194 | + mapReplacements(dirs), |
| 195 | + mapReplacements(missing), |
| 196 | + startTime, |
| 197 | + options, |
| 198 | + newCallback, |
| 199 | + newCallbackUndelayed, |
| 200 | + ); |
| 201 | + |
| 202 | + return { |
| 203 | + close: () => watcher.close(), |
| 204 | + pause: () => watcher.pause(), |
| 205 | + getFileTimestamps: () => reverseTimestamps(watcher.getFileTimestamps()), |
| 206 | + getContextTimestamps: () => reverseTimestamps(watcher.getContextTimestamps()), |
| 207 | + }; |
141 | 208 | }
|
142 | 209 | }
|
0 commit comments