From 8974856cd49093d509b5b5804e6ede407838d0b6 Mon Sep 17 00:00:00 2001 From: Smitty Date: Sat, 19 Sep 2020 19:06:15 -0400 Subject: [PATCH 1/9] Update VirtualModulesPlugin from upstream This updates the internal VirtualModulesPlugin, which is copied from https://github.com/sysgears/webpack-virtual-modules. I went through all commits since this virtual.js was added, and applied them manually to the svelte-loader version where applicable. These upstream changes allow for using Webpack 5 with svelte-loader. This also adds a LICENSE file to comply with the requirements of the MIT license for the plugin files. The LICENSE file also adds in the text of MIT license that svelte-loader is licensed under (with a different copyright line, since svelte-loader wasn't written by SysGears) --- LICENSE | 42 +++++++++++ index.js | 2 +- lib/virtual-stats.js | 2 + lib/virtual.js | 170 +++++++++++++++++++++++++++++++++++++++---- 4 files changed, 199 insertions(+), 17 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..effaf658 --- /dev/null +++ b/LICENSE @@ -0,0 +1,42 @@ +svelte-loader is licensed under the MIT license: +Copyright (c) 2020 svelte-loader contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +lib/virtual.js and lib/virtual-stats.js also contain code licensed under the +MIT license: +Copyright (c) 2017 SysGears + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/index.js b/index.js index 320a12ce..85e198f3 100644 --- a/index.js +++ b/index.js @@ -178,6 +178,6 @@ module.exports = function(source, map) { }, err => callback(err)).catch(err => { // wrap error to provide correct // context when logging to console - callback(new Error(`${err.name}: ${err.toString()}`)); + callback(new Error(`${err.name || "Error"}: ${err.toString()}`)); }); }; diff --git a/lib/virtual-stats.js b/lib/virtual-stats.js index 4e1b1dee..07d6b86b 100644 --- a/lib/virtual-stats.js +++ b/lib/virtual-stats.js @@ -1,3 +1,5 @@ +// Adapted from https://github.com/sysgears/webpack-virtual-modules + /** * Used to cache a stats object for the virtual file. * Extracted from the `mock-fs` package. diff --git a/lib/virtual.js b/lib/virtual.js index 307e2c27..250226d3 100644 --- a/lib/virtual.js +++ b/lib/virtual.js @@ -1,9 +1,26 @@ +// Adapted from https://github.com/sysgears/webpack-virtual-modules + var VirtualStats = require('./virtual-stats'); +var path = require("path"); var inode = 45000000; -// Adapted from https://github.com/sysgears/webpack-virtual-modules -// MIT Licensed https://github.com/sysgears/webpack-virtual-modules/blob/master/LICENSE +function createWebpackData(result) { + return (function(backendOrStorage) { + // In Webpack v5, this variable is a "Backend", and has the data stored in a field + // _data. In V4, the `_` prefix isn't present. + if (backendOrStorage._data) { + const curLevelIdx = backendOrStorage._currentLevel; + const curLevel = backendOrStorage._levels[curLevelIdx]; + return { + result: this.result, + level: curLevel + }; + } + // Webpack 4 + return [null, result]; + }).bind({ result: result }); +} /** * @param {Compiler} compiler - the webpack compiler @@ -16,29 +33,83 @@ function VirtualModulesPlugin(compiler) { compiler.inputFileSystem.purge = function() { if (originalPurge) { - originalPurge.call(this, arguments); + originalPurge.apply(this, arguments); } if (this._virtualFiles) { - Object.keys(this._virtualFiles).forEach( - function(file) { - var data = this._virtualFiles[file]; - setData(this._statStorage, file, [null, data.stats]); - setData(this._readFileStorage, file, [null, data.contents]); - }.bind(this) - ); + Object.keys(this._virtualFiles).forEach(function(file) { + var data = this._virtualFiles[file]; + this._writeVirtualFile(file, data.stats, data.contents); + }.bind(this)); } }; compiler.inputFileSystem._writeVirtualFile = function(file, stats, contents) { + const statStorage = getStatStorage(this); + const fileStorage = getFileStorage(this); + const readDirStorage = getReadDirBackend(this); this._virtualFiles = this._virtualFiles || {}; this._virtualFiles[file] = { stats: stats, contents: contents }; - setData(this._statStorage, file, [null, stats]); - setData(this._readFileStorage, file, [null, contents]); + setData(statStorage, file, createWebpackData(stats)); + setData(fileStorage, file, createWebpackData(contents)); + compiler.fileTimestamps instanceof Map && + compiler.fileTimestamps.set(file, +stats.mtime); + var segments = file.split(/[\\/]/); + var count = segments.length - 1; + var minCount = segments[0] ? 1 : 0; + while (count > minCount) { + var dir = segments.slice(0, count).join(path.sep) || path.sep; + try { + compiler.inputFileSystem.readdirSync(dir); + } catch (e) { + var time = new Date(); + var timeMs = time.getTime(); + var dirStats = new VirtualStats({ + dev: 8675309, + nlink: 0, + uid: 1000, + gid: 1000, + rdev: 0, + blksize: 4096, + ino: inode++, + mode: 16877, + size: stats.size, + blocks: Math.floor(stats.size / 4096), + atimeMs: timeMs, + mtimeMs: timeMs, + ctimeMs: timeMs, + birthtimeMs: timeMs, + atime: time, + mtime: time, + ctime: time, + birthtime: time + }); + setData(readDirStorage, dir, createWebpackData([])); + setData(statStorage, dir, createWebpackData(dirStats)); + } + var dirData = getData(getReadDirBackend(this), dir); + // Webpack v4 returns an array, webpack v5 returns an object + dirData = dirData[1] || dirData.result; + var filename = segments[count]; + if (dirData.indexOf(filename) < 0) { + var files = dirData.concat([filename]).sort(); + setData(getReadDirBackend(this), dir, createWebpackData(files)); + } else { + break; + } + count--; + } }; } const watchRunHook = (watcher, callback) => { this._watcher = watcher.compiler || watcher; + const virtualFiles = compiler.inputFileSystem._virtualFiles; + if (virtualFiles) { + Object.keys(virtualFiles).forEach(function(file) { + compiler.fileTimestamps instanceof Map && + compiler.fileTimestamps.set(file, +virtualFiles[file].stats.mtime); + }); + } callback(); }; @@ -75,14 +146,81 @@ VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) { birthtime: time }); + // When using the WatchIgnorePlugin (https://github.com/webpack/webpack/blob/52184b897f40c75560b3630e43ca642fcac7e2cf/lib/WatchIgnorePlugin.js), + // the original watchFileSystem is stored in `wfs`. The following "unwraps" the ignoring + // wrappers, giving us access to the "real" watchFileSystem. + let finalWatchFileSystem = this._watcher && this._watcher.watchFileSystem; + + while (finalWatchFileSystem && finalWatchFileSystem.wfs) { + finalWatchFileSystem = finalWatchFileSystem.wfs; + } this.compiler.inputFileSystem._writeVirtualFile(filePath, stats, contents); }; -function setData(storage, key, value) { - if (storage.data instanceof Map) { - storage.data.set(key, value); +function getData(storage, key) { + // Webpack 5 + if (storage._data instanceof Map) { + return storage._data.get(key); + } else if (storage._data) { + return storage.data[key]; + } else if (storage.data instanceof Map) { + // Webpack v4 + return storage.data.get(key); + } else { + return storage.data[key]; + } +} + +function setData(backendOrStorage, key, valueFactory) { + const value = valueFactory(backendOrStorage); + + // Webpack v5 + if (backendOrStorage._data instanceof Map) { + backendOrStorage._data.set(key, value); + } else if (backendOrStorage._data) { + backendOrStorage.data[key] = value; + } else if (backendOrStorage.data instanceof Map) { + // Webpack 4 + backendOrStorage.data.set(key, value); + backendOrStorage.data.set(key, value); + } else { + backendOrStorage.data[key] = value; + backendOrStorage.data[key] = value; + } +} + +function getStatStorage(fileSystem) { + if (fileSystem._statStorage) { + // Webpack v4 + return fileSystem._statStorage; + } else if (fileSystem._statBackend) { + // webpack v5 + return fileSystem._statBackend; + } else { + // Unknown version? + throw new Error("Couldn't find a stat storage"); + } +} + +function getFileStorage(fileSystem) { + if (fileSystem._readFileStorage) { + // Webpack v4 + return fileSystem._readFileStorage; + } else if (fileSystem._readFileBackend) { + // Webpack v5 + return fileSystem._readFileBackend; + } else { + throw new Error("Couldn't find a readFileStorage"); + } +} + +function getReadDirBackend(fileSystem) { + if (fileSystem._readdirBackend) { + return fileSystem._readdirBackend; + } else if (fileSystem._readdirStorage) { + return fileSystem._readdirStorage; } else { - storage.data[key] = value; + throw new Error("Couldn't find a readDirStorage from Webpack Internals"); } } From 8b5ac4ff501abffded5a3d51e8e96e88eaabe194 Mon Sep 17 00:00:00 2001 From: Smitty Date: Mon, 12 Oct 2020 19:02:00 -0400 Subject: [PATCH 2/9] Use single quotes --- index.js | 2 +- lib/virtual.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 85e198f3..a70962d4 100644 --- a/index.js +++ b/index.js @@ -178,6 +178,6 @@ module.exports = function(source, map) { }, err => callback(err)).catch(err => { // wrap error to provide correct // context when logging to console - callback(new Error(`${err.name || "Error"}: ${err.toString()}`)); + callback(new Error(`${err.name || 'Error'}: ${err.toString()}`)); }); }; diff --git a/lib/virtual.js b/lib/virtual.js index 250226d3..466a7e17 100644 --- a/lib/virtual.js +++ b/lib/virtual.js @@ -1,7 +1,7 @@ // Adapted from https://github.com/sysgears/webpack-virtual-modules var VirtualStats = require('./virtual-stats'); -var path = require("path"); +var path = require('path'); var inode = 45000000; @@ -198,7 +198,7 @@ function getStatStorage(fileSystem) { return fileSystem._statBackend; } else { // Unknown version? - throw new Error("Couldn't find a stat storage"); + throw new Error('Couldn\'t find a stat storage'); } } @@ -210,7 +210,7 @@ function getFileStorage(fileSystem) { // Webpack v5 return fileSystem._readFileBackend; } else { - throw new Error("Couldn't find a readFileStorage"); + throw new Error('Couldn\'t find a readFileStorage'); } } @@ -220,7 +220,7 @@ function getReadDirBackend(fileSystem) { } else if (fileSystem._readdirStorage) { return fileSystem._readdirStorage; } else { - throw new Error("Couldn't find a readDirStorage from Webpack Internals"); + throw new Error('Couldn\'t find a readDirStorage from Webpack Internals'); } } From 6c50e32ad8bc56f8a2c1f9a16ddc8397cf2cd1fd Mon Sep 17 00:00:00 2001 From: Smitty Date: Tue, 13 Oct 2020 08:08:55 -0400 Subject: [PATCH 3/9] Use double quotes when needed to avoid escapes --- lib/virtual.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/virtual.js b/lib/virtual.js index 466a7e17..1477f19d 100644 --- a/lib/virtual.js +++ b/lib/virtual.js @@ -198,7 +198,7 @@ function getStatStorage(fileSystem) { return fileSystem._statBackend; } else { // Unknown version? - throw new Error('Couldn\'t find a stat storage'); + throw new Error("Couldn't find a stat storage"); } } @@ -210,7 +210,7 @@ function getFileStorage(fileSystem) { // Webpack v5 return fileSystem._readFileBackend; } else { - throw new Error('Couldn\'t find a readFileStorage'); + throw new Error("Couldn't find a readFileStorage"); } } @@ -220,7 +220,7 @@ function getReadDirBackend(fileSystem) { } else if (fileSystem._readdirStorage) { return fileSystem._readdirStorage; } else { - throw new Error('Couldn\'t find a readDirStorage from Webpack Internals'); + throw new Error("Couldn't find a readDirStorage from Webpack Internals"); } } From d1dc851ea5d559644dfcc85f390e8d7be491b065 Mon Sep 17 00:00:00 2001 From: Smitty Date: Wed, 21 Oct 2020 13:58:12 -0400 Subject: [PATCH 4/9] Integrate Webpack 5 watch mode from upstream Integrates the changes from: https://github.com/sysgears/webpack-virtual-modules/pull/69 --- lib/virtual.js | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/virtual.js b/lib/virtual.js index 1477f19d..7fe87cf1 100644 --- a/lib/virtual.js +++ b/lib/virtual.js @@ -22,6 +22,10 @@ function createWebpackData(result) { }).bind({ result: result }); } +function getModulePath(filePath, compiler) { + return path.isAbsolute(filePath) ? filePath : path.join(compiler.context, filePath); +} + /** * @param {Compiler} compiler - the webpack compiler */ @@ -51,8 +55,6 @@ function VirtualModulesPlugin(compiler) { this._virtualFiles[file] = { stats: stats, contents: contents }; setData(statStorage, file, createWebpackData(stats)); setData(fileStorage, file, createWebpackData(contents)); - compiler.fileTimestamps instanceof Map && - compiler.fileTimestamps.set(file, +stats.mtime); var segments = file.split(/[\\/]/); var count = segments.length - 1; var minCount = segments[0] ? 1 : 0; @@ -103,13 +105,6 @@ function VirtualModulesPlugin(compiler) { const watchRunHook = (watcher, callback) => { this._watcher = watcher.compiler || watcher; - const virtualFiles = compiler.inputFileSystem._virtualFiles; - if (virtualFiles) { - Object.keys(virtualFiles).forEach(function(file) { - compiler.fileTimestamps instanceof Map && - compiler.fileTimestamps.set(file, +virtualFiles[file].stats.mtime); - }); - } callback(); }; @@ -145,6 +140,7 @@ VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) { ctime: time, birthtime: time }); + var modulePath = getModulePath(filePath, this.compiler); // When using the WatchIgnorePlugin (https://github.com/webpack/webpack/blob/52184b897f40c75560b3630e43ca642fcac7e2cf/lib/WatchIgnorePlugin.js), // the original watchFileSystem is stored in `wfs`. The following "unwraps" the ignoring @@ -155,6 +151,27 @@ VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) { finalWatchFileSystem = finalWatchFileSystem.wfs; } this.compiler.inputFileSystem._writeVirtualFile(filePath, stats, contents); + if (finalWatchFileSystem && + (finalWatchFileSystem.watcher.fileWatchers.size || + finalWatchFileSystem.watcher.fileWatchers.length) + ) { + var fileWatchers = finalWatchFileSystem.watcher.fileWatchers instanceof Map ? + Array.from(finalWatchFileSystem.watcher.fileWatchers.values()) : + finalWatchFileSystem.watcher.fileWatchers; + fileWatchers.forEach(function(fileWatcher) { + if (fileWatcher.path === modulePath) { + delete fileWatcher.directoryWatcher._cachedTimeInfoEntries; + fileWatcher.directoryWatcher.setFileTime( + filePath, + time, + false, + false, + null + ); + fileWatcher.emit("change", time, null); + } + }); + } }; function getData(storage, key) { From 0ef2ded328b2a0fe07d77c9f900fdfbca5df8b40 Mon Sep 17 00:00:00 2001 From: Smitty Date: Wed, 21 Oct 2020 15:39:22 -0400 Subject: [PATCH 5/9] Get rid of all usage of var Replaces all usage of var with let/const --- lib/virtual-stats.js | 4 ++-- lib/virtual.js | 42 +++++++++++++++++++++--------------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/lib/virtual-stats.js b/lib/virtual-stats.js index 07d6b86b..af634711 100644 --- a/lib/virtual-stats.js +++ b/lib/virtual-stats.js @@ -14,7 +14,7 @@ 'use strict'; -var constants = require('constants'); +const constants = require('constants'); /** * Create a new stats object. @@ -22,7 +22,7 @@ var constants = require('constants'); * @constructor */ function VirtualStats(config) { - for (var key in config) { + for (const key in config) { if (!config.hasOwnProperty(key)) { continue; } diff --git a/lib/virtual.js b/lib/virtual.js index 7fe87cf1..6447c952 100644 --- a/lib/virtual.js +++ b/lib/virtual.js @@ -1,9 +1,9 @@ // Adapted from https://github.com/sysgears/webpack-virtual-modules -var VirtualStats = require('./virtual-stats'); -var path = require('path'); +const VirtualStats = require('./virtual-stats'); +const path = require('path'); -var inode = 45000000; +let inode = 45000000; function createWebpackData(result) { return (function(backendOrStorage) { @@ -33,7 +33,7 @@ function VirtualModulesPlugin(compiler) { this.compiler = compiler; if (!compiler.inputFileSystem._writeVirtualFile) { - var originalPurge = compiler.inputFileSystem.purge; + const originalPurge = compiler.inputFileSystem.purge; compiler.inputFileSystem.purge = function() { if (originalPurge) { @@ -41,7 +41,7 @@ function VirtualModulesPlugin(compiler) { } if (this._virtualFiles) { Object.keys(this._virtualFiles).forEach(function(file) { - var data = this._virtualFiles[file]; + const data = this._virtualFiles[file]; this._writeVirtualFile(file, data.stats, data.contents); }.bind(this)); } @@ -55,17 +55,17 @@ function VirtualModulesPlugin(compiler) { this._virtualFiles[file] = { stats: stats, contents: contents }; setData(statStorage, file, createWebpackData(stats)); setData(fileStorage, file, createWebpackData(contents)); - var segments = file.split(/[\\/]/); - var count = segments.length - 1; - var minCount = segments[0] ? 1 : 0; + const segments = file.split(/[\\/]/); + let count = segments.length - 1; + const minCount = segments[0] ? 1 : 0; while (count > minCount) { - var dir = segments.slice(0, count).join(path.sep) || path.sep; + const dir = segments.slice(0, count).join(path.sep) || path.sep; try { compiler.inputFileSystem.readdirSync(dir); } catch (e) { - var time = new Date(); - var timeMs = time.getTime(); - var dirStats = new VirtualStats({ + const time = new Date(); + const timeMs = time.getTime(); + const dirStats = new VirtualStats({ dev: 8675309, nlink: 0, uid: 1000, @@ -88,12 +88,12 @@ function VirtualModulesPlugin(compiler) { setData(readDirStorage, dir, createWebpackData([])); setData(statStorage, dir, createWebpackData(dirStats)); } - var dirData = getData(getReadDirBackend(this), dir); + let dirData = getData(getReadDirBackend(this), dir); // Webpack v4 returns an array, webpack v5 returns an object dirData = dirData[1] || dirData.result; - var filename = segments[count]; + const filename = segments[count]; if (dirData.indexOf(filename) < 0) { - var files = dirData.concat([filename]).sort(); + const files = dirData.concat([filename]).sort(); setData(getReadDirBackend(this), dir, createWebpackData(files)); } else { break; @@ -116,11 +116,11 @@ function VirtualModulesPlugin(compiler) { } VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) { - var len = contents ? contents.length : 0; - var time = new Date(); - var timeMs = time.getTime(); + const len = contents ? contents.length : 0; + const time = new Date(); + const timeMs = time.getTime(); - var stats = new VirtualStats({ + const stats = new VirtualStats({ dev: 8675309, ino: inode++, mode: 33188, @@ -140,7 +140,7 @@ VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) { ctime: time, birthtime: time }); - var modulePath = getModulePath(filePath, this.compiler); + const modulePath = getModulePath(filePath, this.compiler); // When using the WatchIgnorePlugin (https://github.com/webpack/webpack/blob/52184b897f40c75560b3630e43ca642fcac7e2cf/lib/WatchIgnorePlugin.js), // the original watchFileSystem is stored in `wfs`. The following "unwraps" the ignoring @@ -155,7 +155,7 @@ VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) { (finalWatchFileSystem.watcher.fileWatchers.size || finalWatchFileSystem.watcher.fileWatchers.length) ) { - var fileWatchers = finalWatchFileSystem.watcher.fileWatchers instanceof Map ? + const fileWatchers = finalWatchFileSystem.watcher.fileWatchers instanceof Map ? Array.from(finalWatchFileSystem.watcher.fileWatchers.values()) : finalWatchFileSystem.watcher.fileWatchers; fileWatchers.forEach(function(fileWatcher) { From 327bb221676ca872ed70107f4dc0ee5e5d86cf39 Mon Sep 17 00:00:00 2001 From: Smitty Date: Tue, 27 Oct 2020 16:55:03 -0400 Subject: [PATCH 6/9] Code improvements --- lib/virtual.js | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/lib/virtual.js b/lib/virtual.js index 6447c952..7462f111 100644 --- a/lib/virtual.js +++ b/lib/virtual.js @@ -58,6 +58,7 @@ function VirtualModulesPlugin(compiler) { const segments = file.split(/[\\/]/); let count = segments.length - 1; const minCount = segments[0] ? 1 : 0; + // create directories for each segment (to prevent files not being in a directory) while (count > minCount) { const dir = segments.slice(0, count).join(path.sep) || path.sep; try { @@ -123,7 +124,7 @@ VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) { const stats = new VirtualStats({ dev: 8675309, ino: inode++, - mode: 33188, + mode: 16877, nlink: 0, uid: 1000, gid: 1000, @@ -175,17 +176,11 @@ VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) { }; function getData(storage, key) { - // Webpack 5 - if (storage._data instanceof Map) { - return storage._data.get(key); - } else if (storage._data) { - return storage.data[key]; - } else if (storage.data instanceof Map) { - // Webpack v4 + const data = storage._data /* webpack 5 */ || storage.data /* webpack 4 */; + if (data instanceof Map) { return storage.data.get(key); - } else { - return storage.data[key]; } + return data.data[key]; } function setData(backendOrStorage, key, valueFactory) { From 1794d5147f4e1d6773bb3ce16b1d86f7767a4447 Mon Sep 17 00:00:00 2001 From: Smitty Date: Tue, 27 Oct 2020 17:00:18 -0400 Subject: [PATCH 7/9] extract function for creating VirtualStats --- lib/virtual.js | 77 ++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 47 deletions(-) diff --git a/lib/virtual.js b/lib/virtual.js index 7462f111..4e43fb0b 100644 --- a/lib/virtual.js +++ b/lib/virtual.js @@ -26,6 +26,32 @@ function getModulePath(filePath, compiler) { return path.isAbsolute(filePath) ? filePath : path.join(compiler.context, filePath); } +function createVirtualStats(len) { + const time = new Date(); + const timeMs = time.getTime(); + + return new VirtualStats({ + dev: 8675309, + ino: inode++, + mode: 16877, + nlink: 0, + uid: 1000, + gid: 1000, + rdev: 0, + size: len, + blksize: 4096, + blocks: Math.floor(len / 4096), + atimeMs: timeMs, + mtimeMs: timeMs, + ctimeMs: timeMs, + birthtimeMs: timeMs, + atime: time, + mtime: time, + ctime: time, + birthtime: time + }); +} + /** * @param {Compiler} compiler - the webpack compiler */ @@ -64,28 +90,7 @@ function VirtualModulesPlugin(compiler) { try { compiler.inputFileSystem.readdirSync(dir); } catch (e) { - const time = new Date(); - const timeMs = time.getTime(); - const dirStats = new VirtualStats({ - dev: 8675309, - nlink: 0, - uid: 1000, - gid: 1000, - rdev: 0, - blksize: 4096, - ino: inode++, - mode: 16877, - size: stats.size, - blocks: Math.floor(stats.size / 4096), - atimeMs: timeMs, - mtimeMs: timeMs, - ctimeMs: timeMs, - birthtimeMs: timeMs, - atime: time, - mtime: time, - ctime: time, - birthtime: time - }); + const dirStats = createVirtualStats(stats.size); setData(readDirStorage, dir, createWebpackData([])); setData(statStorage, dir, createWebpackData(dirStats)); } @@ -118,29 +123,7 @@ function VirtualModulesPlugin(compiler) { VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) { const len = contents ? contents.length : 0; - const time = new Date(); - const timeMs = time.getTime(); - - const stats = new VirtualStats({ - dev: 8675309, - ino: inode++, - mode: 16877, - nlink: 0, - uid: 1000, - gid: 1000, - rdev: 0, - size: len, - blksize: 4096, - blocks: Math.floor(len / 4096), - atimeMs: timeMs, - mtimeMs: timeMs, - ctimeMs: timeMs, - birthtimeMs: timeMs, - atime: time, - mtime: time, - ctime: time, - birthtime: time - }); + const stats = createVirtualStats(len); const modulePath = getModulePath(filePath, this.compiler); // When using the WatchIgnorePlugin (https://github.com/webpack/webpack/blob/52184b897f40c75560b3630e43ca642fcac7e2cf/lib/WatchIgnorePlugin.js), @@ -164,12 +147,12 @@ VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) { delete fileWatcher.directoryWatcher._cachedTimeInfoEntries; fileWatcher.directoryWatcher.setFileTime( filePath, - time, + stats.birthtime, false, false, null ); - fileWatcher.emit("change", time, null); + fileWatcher.emit("change", stats.birthtime, null); } }); } From 0794b959b17f54d10f049f567818b8e204d08975 Mon Sep 17 00:00:00 2001 From: Martin Oppitz Date: Wed, 11 Nov 2020 06:08:01 +0100 Subject: [PATCH 8/9] fix: optimize the implementation --- lib/virtual.js | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/lib/virtual.js b/lib/virtual.js index 4e43fb0b..201e4cd3 100644 --- a/lib/virtual.js +++ b/lib/virtual.js @@ -158,29 +158,27 @@ VirtualModulesPlugin.prototype.writeModule = function(filePath, contents) { } }; +function getStorageData(storage) { + return storage._data /* webpack 5 */ || storage.data /* webpack 4 */; +} + function getData(storage, key) { - const data = storage._data /* webpack 5 */ || storage.data /* webpack 4 */; - if (data instanceof Map) { - return storage.data.get(key); + const storageData = getStorageData(storage); + if (storageData instanceof Map) { + return storageData.get(key); + } else { + return storageData.data[key]; } - return data.data[key]; } -function setData(backendOrStorage, key, valueFactory) { +function setData(storage, key, valueFactory) { + const storageData = getStorageData(storage); const value = valueFactory(backendOrStorage); - // Webpack v5 - if (backendOrStorage._data instanceof Map) { - backendOrStorage._data.set(key, value); - } else if (backendOrStorage._data) { - backendOrStorage.data[key] = value; - } else if (backendOrStorage.data instanceof Map) { - // Webpack 4 - backendOrStorage.data.set(key, value); - backendOrStorage.data.set(key, value); + if (storageData instanceof Map) { + storageData.set(key, value); } else { - backendOrStorage.data[key] = value; - backendOrStorage.data[key] = value; + storageData.data[key] = value; } } From ac1304c688268117bc09118e9bed404fb208df58 Mon Sep 17 00:00:00 2001 From: Martin Oppitz Date: Wed, 11 Nov 2020 20:07:03 +0100 Subject: [PATCH 9/9] fix: 'backendOrStorage' is not defined no-undef --- lib/virtual.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/virtual.js b/lib/virtual.js index 201e4cd3..e9d75541 100644 --- a/lib/virtual.js +++ b/lib/virtual.js @@ -6,12 +6,12 @@ const path = require('path'); let inode = 45000000; function createWebpackData(result) { - return (function(backendOrStorage) { + return (function(storage) { // In Webpack v5, this variable is a "Backend", and has the data stored in a field // _data. In V4, the `_` prefix isn't present. - if (backendOrStorage._data) { - const curLevelIdx = backendOrStorage._currentLevel; - const curLevel = backendOrStorage._levels[curLevelIdx]; + if (storage._data) { + const curLevelIdx = storage._currentLevel; + const curLevel = storage._levels[curLevelIdx]; return { result: this.result, level: curLevel @@ -173,7 +173,7 @@ function getData(storage, key) { function setData(storage, key, valueFactory) { const storageData = getStorageData(storage); - const value = valueFactory(backendOrStorage); + const value = valueFactory(storage); if (storageData instanceof Map) { storageData.set(key, value);