拿掉 build files

This commit is contained in:
2022-07-18 16:33:23 +08:00
parent 41e2287bcb
commit 3707f158a3
31953 changed files with 0 additions and 4411796 deletions
-518
View File
@@ -1,518 +0,0 @@
# Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="0.13.1"></a>
## [0.13.1](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.13.0...v0.13.1) (2018-12-10)
### Bug Fixes
* optimize contextNormalPath mzgoddard/hard-source-webpack-plugin[#469](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/469) ([cb03413](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/cb03413))
* replace native fs with graceful-fs ([93143ca](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/93143ca))
<a name="0.13.0"></a>
# [0.13.0](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.12.0...v0.13.0) (2018-12-09)
### Bug Fixes
* add prefix member to HarmonyExportExpression schema ([#443](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/443)) ([fef1488](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/fef1488))
* remove ExcludeMiniCssModulePlugin ([f15bd9f](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/f15bd9f))
* support new dll plugin schema changes ([a250247](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/a250247))
<a name="0.12.0"></a>
# [0.12.0](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.11.2...v0.12.0) (2018-07-30)
### Bug Fixes
* memory leak in TransformNormalModuleFactoryPlugin ([#414](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/414)) ([33b306b](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/33b306b))
### Features
* add ParallelModulePlugin ([#415](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/415)) ([9585d47](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/9585d47))
<a name="0.11.2"></a>
## [0.11.2](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.11.0...v0.11.2) (2018-07-22)
### Bug Fixes
* performance regression due to false position md5 ([#413](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/413)) ([c670f73](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/c670f73))
* serialize path query params without change ([#408](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/408)) ([734e5b0](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/734e5b0))
* webpack 3 RuleSet creation ([#407](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/407)) ([6551c8e](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/6551c8e))
<a name="0.11.1"></a>
## [0.11.1](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.10.1...v0.11.1) (2018-07-12)
### Bug Fixes
* plus sign missing ([#398](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/398)) ([8885f10](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/8885f10))
* serialize path query params without change ([#408](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/408)) ([734e5b0](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/734e5b0))
* use Buffer.alloc ([#402](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/402)) ([e327108](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/e327108))
* webpack 3 RuleSet creation ([#407](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/407)) ([6551c8e](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/6551c8e))
### Features
* support resource data sideEffects: false ([#403](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/403)) ([a5c5d33](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/a5c5d33))
<a name="0.11.0"></a>
# [0.11.0](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.10.2...v0.11.0) (2018-07-07)
### Features
* support resource data sideEffects: false ([#403](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/403)) ([a5c5d33](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/a5c5d33))
<a name="0.10.2"></a>
## [0.10.2](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.10.0...v0.10.2) (2018-07-07)
### Bug Fixes
* plus sign missing ([#398](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/398)) ([8885f10](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/8885f10))
* support unresolved loader resolve calls ([#396](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/396)) ([66086aa](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/66086aa))
* use Buffer.alloc ([#402](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/402)) ([e327108](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/e327108))
<a name="0.10.1"></a>
## [0.10.1](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.10.0...v0.10.1) (2018-07-02)
### Bug Fixes
* support unresolved loader resolve calls ([#396](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/396)) ([66086aa](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/66086aa))
<a name="0.10.0"></a>
# [0.10.0](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.9.0...v0.10.0) (2018-07-02)
### Features
* store low level resolutions from built module ([#392](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/392)) ([2d0df51](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/2d0df51))
<a name="0.9.0"></a>
# [0.9.0](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.8.1...v0.9.0) (2018-06-23)
### Bug Fixes
* **package:** update find-cache-dir to version 2.0.0 ([#385](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/385)) ([d871c8a](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/d871c8a))
* **package:** update pkg-dir to version 3.0.0 ([#384](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/384)) ([d97566d](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/d97566d))
### Features
* add cache pruning ([#386](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/386)) ([c685a61](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/c685a61))
<a name="0.8.1"></a>
## [0.8.1](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.8.0...v0.8.1) (2018-06-14)
### Bug Fixes
* exclude mini-css loader modules ([#382](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/382)) ([1c8eb1f](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/1c8eb1f))
<a name="0.8.0"></a>
# [0.8.0](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.7.6...v0.8.0) (2018-06-14)
### Features
* add ExcludeModulePlugin ([#381](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/381)) ([074b5d9](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/074b5d9))
<a name="0.7.6"></a>
## [0.7.6](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.7.5...v0.7.6) (2018-06-12)
### Bug Fixes
* **cache:** reset corrupted caches ([#375](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/375)) ([33cc986](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/33cc986))
* thaw SystemImportDeprecationWarning ([#379](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/379)) ([5603da0](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/5603da0))
* **package:** add engine to define minimum node version ([#377](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/377)) ([d1f9c5f](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/d1f9c5f))
<a name="0.7.5"></a>
## [0.7.5](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.7.2...v0.7.5) (2018-06-04)
### Bug Fixes
* add missing commitlint configuration file ([#363](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/363)) ([c878f4b](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/c878f4b))
* check that normalId is on missingCache ([#364](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/364)) ([79aa0bc](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/79aa0bc))
* parse and stringify data in serializers ([#358](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/358)) ([c40fd30](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/c40fd30))
<a name="0.7.4"></a>
## [0.7.4](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.7.3...v0.7.4) (2018-05-30)
### Bug Fixes
* add missing commitlint configuration file ([#363](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/363)) ([c878f4b](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/c878f4b))
* check that normalId is on missingCache ([#364](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/364)) ([79aa0bc](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/79aa0bc))
<a name="0.7.3"></a>
## [0.7.3](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.7.2...v0.7.3) (2018-05-30)
### Bug Fixes
* parse and stringify data in serializers ([#358](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/358)) ([c40fd30](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/c40fd30))
<a name="0.7.2"></a>
## [0.7.2](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.7.0...v0.7.2) (2018-05-28)
### Bug Fixes
* missing logMessages import in ParitySystem ([#354](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/354)) ([59ec7cf](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/59ec7cf))
* use find-cache-dir for default cache directory ([#237](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/237)) ([#355](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/355)) ([0212475](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/0212475))
<a name="0.7.1"></a>
## [0.7.1](https://github.com/mzgoddard/hard-source-webpack-plugin/compare/v0.7.0...v0.7.1) (2018-05-28)
### Bug Fixes
* missing logMessages import in ParitySystem ([#354](https://github.com/mzgoddard/hard-source-webpack-plugin/issues/354)) ([59ec7cf](https://github.com/mzgoddard/hard-source-webpack-plugin/commit/59ec7cf))
# 0.7.0
- Internal reworking splitting out multiple caches and making them less dependent on each other
- Use webpack 4's new tapable plugin interface to avoid the deprecation message on .plugin
- Replace default data serializer, append, with append-2 for performance and stability
- Use brief (chalk) colored log messages
## 0.7.X Patches
- `0.7.0-beta.4` Replace debug process exit with unfrozen error in source transform (#293)
- `0.7.0-beta.3` Monkey patch mini-css CssDependency to update its module's hash (#339)
- `0.7.0-beta.2` Fix import context block chunk name support (#327), Add parity compilation cache check
- `0.7.0-beta.1` Ensure file and context dependencies are absolute paths (#330), better json error messaging (#307), always chalk log to stderr
- `0.7.0-beta.0` Update README
- `0.7.0-alpha.4` Add chalk logging with shorter messages, iterate fix on data deleted from md5 cache (#330)
- `0.7.0-alpha.3` Update file path naming standards, fix watchRun compiler misnover (#320)
- `0.7.0-alpha.2` Fix Source freezing with typescript (#291) (@kristenmills)
- `0.7.0-alpha.1` Remove deprecated recordsPath support, more narrow dependency transform generation, add cacache serializer and append-2 serializer as the new default.
## Support
- webpack 3 and 4
- node 8 and later
## Release Features
### Cleaner Separation of Concerns
Separate different parts of the cache into subcaches.
- AssetCache: stores the collection of Assets for the compiler
- EnhancedResolverCache: cached results from enhanced-resolver
- Md5Cache: performs file and context hashing together as well as store values
- ModuleCache: stores the modules as frozen and thawed by other plugins
- ModuleResolverCache: stores resolver data collected from enhanced-resolver for a module
Each Cache handles a set of singles to: reset their cache, read from an existing cache, verify the cache is correct, and write out changes to the cache.
### Stability
The current 'data' serializer, `append`, is being replaced by `append-2`. This second version "appends" at the folder level instead of the file level. This make the source easier to understand and write and more likely to hold less bugs. It also happens to be faster than `append` thanks to being easier to write, it's easier to write optimizations for.
# 0.6.0
- Thaw dependency instances to their original type
- Naturally thaw NormalModule and ContextModule
- Relate the config hash to the cache directory and frozen items to the compiler context path
- Write items immediately adjacent to each other in AppendSerializer, without filler
## 0.6.X Patches
- `0.6.7` Add MiniCssExtract support, add graceful failure when module does not freeze all dependencies
- `0.6.6` Add local module support and fix webpack 4 json, wasm, and module build hash support
- `0.6.5` Fix dynamic import (@faceyspacey, @matthewborden) (#300), fix .split issue (@toriningen) (#289), fix README typo (@Zakjholt, @koningskristof)
- `0.6.4` Use general dependency -> block cycle test to avoid max call stack (#283)
- `0.6.3` Add safety net to module dependency freezing
- `0.6.2` Rebuild activeExports when thawing instead of serializing it
- `0.6.1` Fix freezing sourceless modules (#270), fix freezing json and wasm parsers and generators (#276)
- `0.6.0` Additional protection against source path being locked when copied
- `0.6.0-alpha.8` Protect append serializer from rename and unlink errors on Windows
- `0.6.0-alpha.7` Move babel dependencies to development
- `0.6.0-alpha.6` Fix unneeded rebuilding performance regressions
- `0.6.0-alpha.5` Naturally thaw NormalModule and ContextModule
- `0.6.0-alpha.4` Add webpack 4 beta support
- `0.6.0-alpha.3` Fix dependency thawing performance regression
- `0.6.0-alpha.2` Fix missed preload path relation thawing
## Release Features
### The original debt, hybrid dependencies
Remove the need to depend on webpack record ids feature and to manually invalidate frozen modules due to module id or used harmony export changes.
From hard-source's beginning it froze dependencies as hybrid or abstract dependencies. Thawed they represented the other modules the a frozen module depended on. They made the frozen module's representation of the output brittle. A change in id, used harmony exports, and some other dependency elements meant the frozen module had to thrown away so a new webpack NormalModule could be built and its source rendered. Fixing this debt, the frozen module can re-render as how NormalModule does when a module id or used harmony exports changed.
This improves rebuild time when used exports of a harmony dependency change or webpack assigns a different id to a built module. As well this improves hard-source relability in relation to webpack as it removes the need for the special case logic in hard-source that would invalidates modules in these cases.
### The derived debt, non-core modules
Thaw cached NormalModule and ContextModule data into webpack's NormalModule and ContextModule types.
With hybrid dependencies custom module types were needed to be able to use the hybrid dependencies and custom source type. The hybrid modules let webpack trace dependencies through them but left HardSource to pick a lot of work to make sure the custom modules were not returned from webpack hooks if they were out of date. In many cases with webpack 2 and later, to make this work they'd need an additional build in webpack so they the normal process of creating a module would replace a module HardSource returned incorrectly because it could not check that the module was out of date until a later stage in the build.
With this new thawing HardSource is making iterative webpack builds look internally in its data more like the first build that was cached.
### Relative Cache
Relate cached items to the cache directory and compiler contxt path. A relative cache is a portable cache. The cache built on one computer can be used on another system or in a cloned copy of the project with a different root directory on the same system.
Relate paths in the config hash to the cache directory as the config contains the context path that becomes the compiler context. Two versions of a config may only differ by the context path. Using a different context relative to the root of the project or the cacheDirectory will not be able to use the cached items in the matching config hash's build because the items when their paths are made absolute during the build will be not correct.
Relate frozen items to the compiler context. When thawed the items will have their paths made absolute again so their internal state matches their previous state where paths are absolute during webpack's runtime.
Make resolver request fields relative to the context if they are absolute paths. Most path fields in frozen items can be known ahead of time to be absolute paths. So making the paths relative and absolute while freezing and thawing is straight forward. The request part of resolutions is not straight forward. Sometimes the request path is relative, and sometimes it is absolute. An absolute path cannot be frozen so the absolute path must be made relative. But an original relative request must not be made absolute when thawed. To answer this, make only absolute paths relative and leave the request path as is when thawed. To use these thawed resolutions two checks may be made into the cache. First an unmodified lookup and second a modified lookup with the input made relative as if it was being frozen. This way enhanced-resolve cached items and NormalModule and ContextModule resolver items can be frozen and thawed reliably.
### No wasted space in AppendSerializer
Log new values to byte positions instead of block positions. Removing the filler space in incomplete blocks, this decreases the space AppendSerializer uses and can have a small improvement to write and read performance.
# 0.5.0
- Internal plugins for freezing and thawing modules, dependencies, and assets
- Use AppendSerializer by default
- Improved ES2015 support
- Environment hash defaults to package-lock.json and yarn.lock if they exist
## 0.5.X Patches
- `0.5.16` Fix baseMap redundancy logic (#246), fix options passing for cheap-eval devtool (#241)
- `0.5.15` Safety check that `sourceMap.map` is in cache before use (@abogaart)
- `0.5.14` Improve AppendSerializer performance reading and writing
- `0.5.13` Improve AppendSerializer performance on lots of writes
- `0.5.12` Fix sourcesContext is undefined (@piecyk)
- `0.5.11` Fix relative context module's identifier and id assignment
- `0.5.10` Fix contextTimstamp typo and hash regression, fix bad compilerContext when logging freezing errors (#230)
- `0.5.9` Fix context dependency validation (#182) and worker-loader cache prefix search (#201)
- `0.5.8`
- Fix memory usage related to HarmonyExportImportedSpecifierDependency
- Reduce memory usage in frozen modules and source maps
- Reduce memory usage writing to and reading from disk
- Fix using preloaded modules in the memory cache
- `0.5.7` Fix a large memory usage related to HarmonyExportImportedSpecifierDependency (#205)
- `0.5.6` Add module freeze error logging
- `0.5.5` Fix contextStampm, return context object in synchronous branch
- `0.5.4` Improve cache read and write performance related to promises, fix AppendSerializer compacting
- `0.5.3` Improve AppendSerializer performance
- `0.5.2` Fix nested AsyncDependenciesBlock origins for Stats support
## Release Features
The first step to providing meaningful third party hard-source plugins for deeper integration with advanced webpack plugins, this version adds internally used plugins for freezing and thawing modules, etc. These plugins are accessible externally but are prefixed with `--` to help indicate that you should avoid using them in the meantime. You are welcome to make plugins that use these hooks but the interface may change. Internal and external plugin interface changes will only occur during minor version releases before version 1.
As an important example of the utility of the plugin interface modules that are put into a ConcatenatedModule are now cached, helping decreasing build times using that plugin.
# 0.4.0
- Low level resolution cache
- Missing resolution attempt check
- Expose a 'hard-source-cache-factory' plugin hook on the compiler
- Cache module resolutions in a cache serializer
- Expose a 'hard-source-log' plugin hook on the compiler
- Default options
## 0.4.X Patches
- `0.4.15` Deserialize objects from their caches before use (@ettavolt)
- `0.4.14` Publish index.js and lib, omitting tests
- `0.4.13` Add AppendSerializer
- `0.4.12` Fix harmony module export * from ... (@filipesilva)
- `0.4.11` Fix ContextDependency non-regexp use and fix child compiler cache prefix search
- `0.4.10` Bump webpack version to help with nested dependency issues (@rowan)
- `0.4.9` Fetch loader options for rule based options in webpack > 2
- `0.4.8` Fix error in loader rule optimization use during watch mode
- `0.4.7` Support webpack 3's loader rules optimization
- `0.4.6` Support direct use of SourceMapDevToolPlugin
- `0.4.5` Add webpack 3 support. Add initial ModuleConcatenationPlugin support
- `0.4.4` Fix configHash default value
- `0.4.3` Fix #105. Cache assets in memory as well as disk
- `0.4.2` Tune default options
- `0.4.1` Add Appveyor CI
## Release Features
### Low level resolution cache
Prior versions of hard-source cache resolution values the NormalModuleFactory creates and a similar data for the ContextModuleFactory. These higher level resolutions provide a lot of hard-sources performance gain by reusing those values when resolving modules as long as an assumption holds. The file or context the resolution points at must still exist. The low level resolution cache takes this further caching the work resolving files, loaders, and contexts. These cached resolutions can be reused between multiple module resolutions as they may share files or loaders. Two modules with the same file but different loaders go through separate NormalModuleFactory resolutions meaning they hit the lower level resolvers. This new cache provides some performance gains in regards to the reused values.
### Missing resolution attempt check
Highly related to the low level resolution cache is the missing resolution attempt check that can be made. When the low level resolvers try to find the resource for a request it can optionally build an array of missing paths that it tried. Caching that information hard-source now provides a stronger assurance that what should have been built is. Seeing any of those missing attempts now existing means the old resolution is invalid and any related NormalModuleFactory resolution is also invalid. During the new build, hard-source will let the normal resolutions occur and store the new information.
### `'hard-source-cache-factory'` plugin
Leading up to changing the default cache serializer (#53), hard-source has its first plugin hook to make it more flexible. The `'hard-source-cache-factory'` plugin hook on the webpack compiler lets a users determine how the cache is write to and read from disk. Documentation on this is in the `lib/cache-serializer-factory.js` module.
With this hook a working additional serializer and plugin is available to replace the leveldb default serializer with a json serializer. This serializer is primarily available for debugging the contents of the cache as they're directly human readable.
To use this plugin you can add it to your config
```js
plugins: [
// other plugins
new HardSourceWebpackPlugin.HardSourceJsonSerializerPlugin(),
```
As a step to #53 a patch version with a replacement to the leveldb will come out during `v0.4.x` that will become the default in `v0.5.0`.
### Cache module resolutions in a cache serializer
Up until this version the NormalModuleFactory resolutions were using some old code to write and read its cache. That has been replaced with a cache serializer like the other caches. This has little effect on reading but provides a small performance gain when writing changes to the cache from the build. The cache serializers are able to write out changes instead of needing to write out the whole cache. This may a small measurable impact on large project where they were writing out the whole module resolution cache.
### `'hard-source-log'` plugin
A second plugin hook in this release, `'hard-source-log'` presents a way to control the logging output from hard-source. Two obvious uses is a plugin to silence its output or another to write the output to disk. Documentation on this plugin hook can be found in `lib/logger-factory.js`.
With a plugin approach to logging, more logging of lower levels (debug, log) will be added that a plugin will optionally enable for writting out. This additional logging will cover when and why modules are invalidated, timing and other information to help debug hard-source.
### Default options
Past versions required at least the `cacheDirectory` and `recordsPath` options, along with recommending the `configHash` option. This release sets defaults for these making hard-source easier to use.
- `cacheDirectory` defaults to `'node_modules/.cache/hard-source/[confighash]'`
- `recordsPath` defaults to `'node_modules/.cache/hard-source/[confighash]/records.json'`
- `configHash` defaults to `require('node-object-hash')({sort: false}).hash`
# 0.3.0
- Internal env-hash implementation relying on file hashes
- Support context dependencies and ContextModule
- Preload the memory cache for faster builds
The `env-hash` implementation is more generalized than the npm env-hash implementation that was previously used. That one focused on hashing modified time values of folders and files to be as fast as possible. This new one is a little slower hashing files and files of folders but supports use cases like reusing a cache from a prior build on a CI environment. While the CI environment would have all new modified times, if the files' content didn't change the hash of those files will be the same letting the old cache be used.
Context dependencies and ContextModules are now supported. This information is stored in the cache and deserialized like file dependencies and NormalModules. This will allow projects with ContextModules and NormalModules with context dependencies to gain the caching benefit they were previously missing.
Webpack's memory cache allows webpack to make assumptions about previously built modules and skip build steps it would otherwise perform on those modules. That cache is now filled with up to date modules from the HardSource cache letting builds with webpack or the first build with a webpack server to gain the performance those assumptions support.
## 0.3.X Patches
- `0.3.13` Support change to error rendering in webpack 2
- `0.3.12` Support different resolutions in different child compilations
- `0.3.11` Support optional dependencies
- `0.3.10` Fix webpack typo'd dependency (HarmonyCompatiblilityDependency)
- `0.3.9` Support webpack.IgnorePlugin
- `0.3.8` Support webpack 2.2.0 stable release
- `0.3.7` Support webpack 2.2.0-rc.4 (by @swernerx)
- `0.3.6` Allow webpack 2 rc versions in package peer dependencies
- `0.3.5` Support out of order harmony import specifiers
- `0.3.4` Support webpack 2.2.0-rc.0
- `0.3.3` Support webpack 2.1.0-beta.28
- `0.3.1` Fix false positive invalidation against modules like Delegated and External
# 0.2.0
Builds and stores checksums of files built by webpack to better determine when to rebuild modules. This helps HardSource rebuild less in CI environments.
Code contributed by:
- @nikhilmat
## 0.2.X Patches
- `0.2.7` Fix resolve cache invalidation, use resource instead of userRequest
- `0.2.6` Don't log version mismatch message on first build without a cache
- `0.2.5` Stamp cache with library version and fix serializing `loc` strings
- `0.2.4` Fix out of date harmony module tree shaking keys
- `0.2.3` Fix context depending modules rebuild check
- `0.2.2` Flatten dependency loc data for HarmonyImportSpecifier
- `0.2.1` Support functions as option to environmentHash
# 0.1.0
HardSource grew through its `0.0.X` versions up to this point. It currently supports:
- Webpack 1 AMD and CommonJS modules
- Webpack 2 Harmony modules with tree shaking
- Module warnings and errors
- Child Compiler use with plugins like ExtractTextWebpackPlugin and HtmlWebpackPlugin
- Webpack builtin plugins like DllPlugin and UglifyJSPlugin
- Module cache busting when dependencies move
- Multiple caches through the configHash option
- Full cache invalidation through dependency hash comparison
## 0.1.X Patches
- `0.1.4` Consider AMDDefineDependencies as a HardNullDependency like ConstDependency
- `0.1.3` Fix normal module resolver plugin that didn't pass on resolve errors
- `0.1.2` Ignore ExtractText root modules so that child compilers always run and output assets
# 0.0.X
- `0.0.44` Prefix module cache identifier by child compiler subcache name
- `0.0.43` Flatten dependency `loc` field (HMR fix for 0.0.41)
- `0.0.42` Support out of order harmony module export specifier dependencies
- `0.0.41` Freeze and thaw module warnings and errors (by @Strate)
- `0.0.40` Support latest webpack 2 beta (2.1.0-beta.25)
- `0.0.38` Add `configHash` option
- `0.0.37` Add a little logic to avoid re-serializing already serialized modules
- `0.0.36` Freeze and thaw some common fields that weren't before
- `0.0.35` Use additional pass in compilation instead of pre-emptive pass. Fixes use with HMR
- `0.0.34` Correctly thaw harmony specifier dependencies
- `0.0.33` Add HardModule.libIdent to support DllPlugin
- `0.0.32` Fix webpack 2 dependency warnings
- `0.0.30` Fix asset thawing and unnecessary dependency invalidation
- `0.0.28` Help ensure cacheDirectory is used as users expect
- `0.0.27` Use pre-emptive compile when supporting isUsed (webpack 2)
- `0.0.26` Invalidate modules based on webpack 2 tree shaking
- `0.0.23` Fix to error in resolve invalidation
- `0.0.19` Store separate non-devtool related base map for Uglify support
- `0.0.18` Invalidate modules depending on a now invalid resolve value
- `0.0.17` Support webpack-isomorphic-tools
- `0.0.16` Incomplete resolve invalidation
- `0.0.15` Invalidate whole cache when environment (node_modules, etc) change
- `0.0.13` Freeze and thaw module's `_source` used by Stats
- `0.0.11` Store modules in a leveldb store
- `0.0.10` Store assets separate for performance
- `0.0.9` Support ExtractText and Uglify
- `0.0.8` relative `cacheDirectory` support
- `0.0.7` Support Harmony modules by disabling tree shaking
- `0.0.5` First ReadME, travis badge, cacheDirectory change
- `0.0.4` Add source map tests, improve source map thawing
- `0.0.3` Add tests
-7
View File
@@ -1,7 +0,0 @@
## ISC License
Copyright (c) 2016, Michael "Z" Goddard <mzgoddard@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-225
View File
@@ -1,225 +0,0 @@
# HardSourceWebpackPlugin
[![Build Status](https://travis-ci.org/mzgoddard/hard-source-webpack-plugin.svg?branch=master)](https://travis-ci.org/mzgoddard/hard-source-webpack-plugin) [![Build status](https://ci.appveyor.com/api/projects/status/761saaelxem01xo5/branch/master?svg=true)](https://ci.appveyor.com/project/mzgoddard/hard-source-webpack-plugin/branch/master)
`HardSourceWebpackPlugin` is a plugin for webpack to provide an intermediate caching step for modules. In order to see results, you'll need to run webpack twice with this plugin: the first build will take the normal amount of time. The second build will be signficantly faster.
Install with `npm install --save-dev hard-source-webpack-plugin` or `yarn add --dev hard-source-webpack-plugin`. And include the plugin in your webpack's plugins configuration.
```js
// webpack.config.js
var HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
module.exports = {
context: // ...
entry: // ...
output: // ...
plugins: [
new HardSourceWebpackPlugin()
]
}
```
You can optionally set where HardSource writes and reads its cache to and from, and the hash values that determine when it creates new caches.
```js
new HardSourceWebpackPlugin({
// Either an absolute path or relative to webpack's options.context.
cacheDirectory: 'node_modules/.cache/hard-source/[confighash]',
// Either a string of object hash function given a webpack config.
configHash: function(webpackConfig) {
// node-object-hash on npm can be used to build this.
return require('node-object-hash')({sort: false}).hash(webpackConfig);
},
// Either false, a string, an object, or a project hashing function.
environmentHash: {
root: process.cwd(),
directories: [],
files: ['package-lock.json', 'yarn.lock'],
},
// An object.
info: {
// 'none' or 'test'.
mode: 'none',
// 'debug', 'log', 'info', 'warn', or 'error'.
level: 'debug',
},
// Clean up large, old caches automatically.
cachePrune: {
// Caches younger than `maxAge` are not considered for deletion. They must
// be at least this (default: 2 days) old in milliseconds.
maxAge: 2 * 24 * 60 * 60 * 1000,
// All caches together must be larger than `sizeThreshold` before any
// caches will be deleted. Together they must be at least this
// (default: 50 MB) big in bytes.
sizeThreshold: 50 * 1024 * 1024
},
}),
```
Some further configuration is possible through provided plugins.
```js
plugins: [
new HardSourceWebpackPlugin(),
```
### ExcludeModulePlugin
```js
// You can optionally exclude items that may not be working with HardSource
// or items with custom loaders while you are actively developing the
// loader.
new HardSourceWebpackPlugin.ExcludeModulePlugin([
{
// HardSource works with mini-css-extract-plugin but due to how
// mini-css emits assets, assets are not emitted on repeated builds with
// mini-css and hard-source together. Ignoring the mini-css loader
// modules, but not the other css loader modules, excludes the modules
// that mini-css needs rebuilt to output assets every time.
test: /mini-css-extract-plugin[\\/]dist[\\/]loader/,
},
{
test: /my-loader/,
include: path.join(__dirname, 'vendor'),
},
]),
```
### ParallelModulePlugin
```js
// HardSource includes an experimental plugin for parallelizing webpack
// across multiple processes. It requires that the extra processes have the
// same configuration. `mode` must be set in the config. Making standard
// use with webpack-dev-server or webpack-serve is difficult. Using it with
// webpack-dev-server or webpack-serve means disabling any automatic
// configuration and configuring hot module replacement support manually.
new HardSourceWebpackPlugin.ParallelModulePlugin({
// How to launch the extra processes. Default:
fork: (fork, compiler, webpackBin) => fork(
webpackBin(),
['--config', __filename], {
silent: true,
}
),
// Number of workers to spawn. Default:
numWorkers: () => require('os').cpus().length,
// Number of modules built before launching parallel building. Default:
minModules: 10,
}),
]
```
## Options
### `cacheDirectory`
The `cacheDirectory` is where the cache is written to. The default stores the cache in a directory under node_modules so if node_modules is cleared so is the cache.
The `cacheDirectory` has a field in it `[confighash]` that is replaced by the `configHash` option when webpack is started. The `[confighash]` field is here to help with changes to the configuration by the developer or by a script. For example if the same webpack configuration is used for the `webpack` cli tool and then the `webpack-dev-server` cli tool, they will generate different configuration hashes. `webpack-dev-server` adds plugins for its reloading features, and the default hash function produces a different value with those plugins added.
### `configHash`
<a name="using-confighash-in-the-cachedirectory"></a>
<a name="why-hash-the-config"></a>
`configHash` turns a webpack configuration when a webpack instance is started and is used by `cacheDirectory` to build different caches for different webpack configurations.
Configurations may change how modules are rendered and so change how they appear in the disk cache `hard-source` writes. It is important to use a different cache per webpack configuration or webpack cli tool. `webpack` and `webpack-dev-server` for example needed separate caches, `configHash` and `[confighash]` in the `cacheDirectory` will create separate caches due to the plugins and configuration changes `webpack-dev-server` makes.
The default value for `configHash` is
```js
configHash: function(webpackConfig) {
return require('node-object-hash')({sort: false}).hash(webpackConfig);
}
```
This uses the npm `node-object-hash` module with sort set to false to hash the object. `node-object-hash` hashes as much as it can but may have issue with some plugins or plugins and loaders that load an additional configuration file like a babel rc file or postcss config. In those cases you can depend on `node-object-hash` and extend what it hashes to best cover those changes.
`configHash` can also be set to a string or it can be a function that generates a value based on other parts of the environment.
```js
configHash: function() {
return process.env.NODE_ENV + '-' + process.env.BABEL_ENV;
}
```
### `environmentHash`
When loaders, plugins, other build time scripts, or other dynamic dependencies change, `hard-source` needs to replace the cache to make sure the output is correct. The `environmentHash` is used to determine this. If the hash is different than a previous build, a fresh cache will be used.
The default object
```js
environmentHash: {
root: process.cwd(),
directories: [],
files: ['package-lock.json', 'yarn.lock']
}
```
hashes the lock files for `npm` and `yarn`. They will both be used if they both exist, or just one if only one exists. If neither file is found, the default will hash `package.json` and the `package.json` under `node_modules`.
<a name="environmenthash-as-a-function"></a>
<a name="environmenthash-as-an-object"></a>
<a name="environmenthash-disabled-with-false"></a>
You can disable the environmentHash by setting it to `false`. By doing this you will manually need to delete the cache when there is any dependency environment change.
### `info`
Control the amount of messages from hard-source.
#### `mode`
Sets other defaults for info. Defaults to 'test' when NODE_ENV==='test'.
#### `level`
The level of log messages to report down to. Defaults to 'debug' when mode is 'none'. Defaults to 'warn' when mode is 'test'.
For example 'debug' reports all messages while 'warn' reports warn and error level messages.
### `cachePrune`
`hard-source` caches are by default created when the webpack configuration changes. Each cache holds a copy of all the data to create a build so they can become quite large. Once a cache is considered "old enough" that it is unlikely to be reused `hard-source` will delete it to free up space automatically.
#### `maxAge`
Caches older than `maxAge` in milliseconds are considered for automatic deletion.
#### `sizeThreshold`
For caches to be deleted, all of them together must total more than this threshold.
## Troubleshooting
### Configuration changes are not being detected
`hard-source` needs a different cache for each different webpack configuration. The default `configHash` may not detect all of your options to plugins or other configuration files like `.babelrc` or `postcss.config.js`. In those cases a custom `configHash` is needed hashing the webpack config and those other values that it cannot normally reach.
### Hot reloading is not working
`webpack-dev-server` needs a different cache than `webpack` or other webpack cli tools. Make sure your `cacheDirectory` and `configHash` options are hashing the changes `webpack-dev-server` makes to your webpack config. The default `hard-source` values should do this.
### Multiple webpack processes at the same time are getting bad results
If you are using multiple webpack instances in separate processes make sure each has its own cache by changing `cacheDirectory` or `configHash`.
### Rebuilds are slower than the first build during dev-server
This is can be due to module context dependencies. `require.context` or loaders that watch folders use this webpack feature so webpack rebuilds when files or folders are added or removed from these watched directories. Be careful about using `require.context` or context aware loaders on folders that contain a lot of items. Both `require.context` and context loaders depend on those folders recursively. `hard-source` hashes every file under a `require.context` or context loader folder to detect when the context has changed and dependent modules are rebuilt.
### `webpack-dev-server` build loops continuously
Make sure you don't have a `require.context` or context loader on the root of your project. Such a context module means webpack is watching the hard source cache and when the cache is written after a build, webpack will start a new build for that module. This normally does not happen with `webpack-dev-server` because it writes the built files into memory instead of the disk. `hard-source` cannot do that since that would defeat its purpose as a disk caching plugin.
## Please contribute!
If you encounter any issues or have an idea for hard-source-webpack-plugin could be better, please let us know.
# [Change Log](CHANGELOG.md)
-582
View File
@@ -1,582 +0,0 @@
const crypto = require('crypto');
const fs = require('graceful-fs');
const path = require('path');
const lodash = require('lodash');
const _mkdirp = require('mkdirp');
const _rimraf = require('rimraf');
const nodeObjectHash = require('node-object-hash');
const findCacheDir = require('find-cache-dir');
const envHash = require('./lib/envHash');
const defaultConfigHash = require('./lib/defaultConfigHash');
const promisify = require('./lib/util/promisify');
const relateContext = require('./lib/util/relate-context');
const pluginCompat = require('./lib/util/plugin-compat');
const logMessages = require('./lib/util/log-messages');
const LoggerFactory = require('./lib/loggerFactory');
const cachePrefix = require('./lib/util').cachePrefix;
const CacheSerializerFactory = require('./lib/CacheSerializerFactory');
const ExcludeModulePlugin = require('./lib/ExcludeModulePlugin');
const HardSourceLevelDbSerializerPlugin = require('./lib/SerializerLeveldbPlugin');
const SerializerAppend2Plugin = require('./lib/SerializerAppend2Plugin');
const SerializerAppendPlugin = require('./lib/SerializerAppendPlugin');
const SerializerCacachePlugin = require('./lib/SerializerCacachePlugin');
const SerializerJsonPlugin = require('./lib/SerializerJsonPlugin');
const hardSourceVersion = require('./package.json').version;
function requestHash(request) {
return crypto
.createHash('sha1')
.update(request)
.digest()
.hexSlice();
}
const mkdirp = promisify(_mkdirp, { context: _mkdirp });
mkdirp.sync = _mkdirp.sync.bind(_mkdirp);
const rimraf = promisify(_rimraf);
rimraf.sync = _rimraf.sync.bind(_rimraf);
const fsReadFile = promisify(fs.readFile, { context: fs });
const fsWriteFile = promisify(fs.writeFile, { context: fs });
const bulkFsTask = (array, each) =>
new Promise((resolve, reject) => {
let ops = 0;
const out = [];
array.forEach((item, i) => {
out[i] = each(item, (back, callback) => {
ops++;
return (err, value) => {
try {
out[i] = back(err, value, out[i]);
} catch (e) {
return reject(e);
}
ops--;
if (ops === 0) {
resolve(out);
}
};
});
});
if (ops === 0) {
resolve(out);
}
});
const compilerContext = relateContext.compilerContext;
const relateNormalPath = relateContext.relateNormalPath;
const contextNormalPath = relateContext.contextNormalPath;
const contextNormalPathSet = relateContext.contextNormalPathSet;
function relateNormalRequest(compiler, key) {
return key
.split('!')
.map(subkey => relateNormalPath(compiler, subkey))
.join('!');
}
function relateNormalModuleId(compiler, id) {
return id.substring(0, 24) + relateNormalRequest(compiler, id.substring(24));
}
function contextNormalRequest(compiler, key) {
return key
.split('!')
.map(subkey => contextNormalPath(compiler, subkey))
.join('!');
}
function contextNormalModuleId(compiler, id) {
return id.substring(0, 24) + contextNormalRequest(compiler, id.substring(24));
}
function contextNormalLoaders(compiler, loaders) {
return loaders.map(loader =>
Object.assign({}, loader, {
loader: contextNormalPath(compiler, loader.loader),
}),
);
}
function contextNormalPathArray(compiler, paths) {
return paths.map(subpath => contextNormalPath(compiler, subpath));
}
class HardSourceWebpackPlugin {
constructor(options) {
this.options = options || {};
}
getPath(dirName, suffix) {
const confighashIndex = dirName.search(/\[confighash\]/);
if (confighashIndex !== -1) {
dirName = dirName.replace(/\[confighash\]/, this.configHash);
}
let cachePath = path.resolve(
process.cwd(),
this.compilerOutputOptions.path,
dirName,
);
if (suffix) {
cachePath = path.join(cachePath, suffix);
}
return cachePath;
}
getCachePath(suffix) {
return this.getPath(this.options.cacheDirectory, suffix);
}
apply(compiler) {
const options = this.options;
let active = true;
const logger = new LoggerFactory(compiler).create();
const loggerCore = logger.from('core');
logger.lock();
const compilerHooks = pluginCompat.hooks(compiler);
if (!compiler.options.cache) {
compiler.options.cache = true;
}
if (!options.cacheDirectory) {
options.cacheDirectory = path.resolve(
findCacheDir({
name: 'hard-source',
cwd: compiler.options.context || process.cwd(),
}),
'[confighash]',
);
}
this.compilerOutputOptions = compiler.options.output;
if (!options.configHash) {
options.configHash = defaultConfigHash;
}
if (options.configHash) {
if (typeof options.configHash === 'string') {
this.configHash = options.configHash;
} else if (typeof options.configHash === 'function') {
this.configHash = options.configHash(compiler.options);
}
compiler.__hardSource_configHash = this.configHash;
compiler.__hardSource_shortConfigHash = this.configHash.substring(0, 8);
}
const configHashInDirectory =
options.cacheDirectory.search(/\[confighash\]/) !== -1;
if (configHashInDirectory && !this.configHash) {
logMessages.configHashSetButNotUsed(compiler, {
cacheDirectory: options.cacheDirectory,
});
active = false;
function unlockLogger() {
logger.unlock();
}
compilerHooks.watchRun.tap('HardSource - index', unlockLogger);
compilerHooks.run.tap('HardSource - index', unlockLogger);
return;
}
let environmentHasher = null;
if (typeof options.environmentHash !== 'undefined') {
if (options.environmentHash === false) {
environmentHasher = () => Promise.resolve('');
} else if (typeof options.environmentHash === 'string') {
environmentHasher = () => Promise.resolve(options.environmentHash);
} else if (typeof options.environmentHash === 'object') {
environmentHasher = () => envHash(options.environmentHash);
environmentHasher.inputs = () =>
envHash.inputs(options.environmentHash);
} else if (typeof options.environmentHash === 'function') {
environmentHasher = () => Promise.resolve(options.environmentHash());
if (options.environmentHash.inputs) {
environmentHasher.inputs = () =>
Promise.resolve(options.environmentHasher.inputs());
}
}
}
if (!environmentHasher) {
environmentHasher = envHash;
}
const cacheDirPath = this.getCachePath();
const cacheAssetDirPath = path.join(cacheDirPath, 'assets');
const resolveCachePath = path.join(cacheDirPath, 'resolve.json');
let currentStamp = '';
const cacheSerializerFactory = new CacheSerializerFactory(compiler);
let createSerializers = true;
let cacheRead = false;
const _this = this;
pluginCompat.register(compiler, '_hardSourceCreateSerializer', 'sync', [
'cacheSerializerFactory',
'cacheDirPath',
]);
pluginCompat.register(compiler, '_hardSourceResetCache', 'sync', []);
pluginCompat.register(compiler, '_hardSourceReadCache', 'asyncParallel', [
'relativeHelpers',
]);
pluginCompat.register(
compiler,
'_hardSourceVerifyCache',
'asyncParallel',
[],
);
pluginCompat.register(compiler, '_hardSourceWriteCache', 'asyncParallel', [
'compilation',
'relativeHelpers',
]);
if (configHashInDirectory) {
const PruneCachesSystem = require('./lib/SystemPruneCaches');
new PruneCachesSystem(
path.dirname(cacheDirPath),
options.cachePrune,
).apply(compiler);
}
function runReadOrReset(_compiler) {
logger.unlock();
if (!active) {
return Promise.resolve();
}
try {
fs.statSync(cacheAssetDirPath);
} catch (_) {
mkdirp.sync(cacheAssetDirPath);
logMessages.configHashFirstBuild(compiler, {
cacheDirPath,
configHash: compiler.__hardSource_configHash,
});
}
const start = Date.now();
if (createSerializers) {
createSerializers = false;
try {
compilerHooks._hardSourceCreateSerializer.call(
cacheSerializerFactory,
cacheDirPath,
);
} catch (err) {
return Promise.reject(err);
}
}
return Promise.all([
fsReadFile(path.join(cacheDirPath, 'stamp'), 'utf8').catch(() => ''),
environmentHasher(),
fsReadFile(path.join(cacheDirPath, 'version'), 'utf8').catch(() => ''),
environmentHasher.inputs ? environmentHasher.inputs() : null,
]).then(([stamp, hash, versionStamp, hashInputs]) => {
if (!configHashInDirectory && options.configHash) {
hash += `_${_this.configHash}`;
}
if (hashInputs && !cacheRead) {
logMessages.environmentInputs(compiler, { inputs: hashInputs });
}
currentStamp = hash;
if (!hash || hash !== stamp || hardSourceVersion !== versionStamp) {
if (hash && stamp) {
if (configHashInDirectory) {
logMessages.environmentHashChanged(compiler);
} else {
logMessages.configHashChanged(compiler);
}
} else if (versionStamp && hardSourceVersion !== versionStamp) {
logMessages.hardSourceVersionChanged(compiler);
}
// Reset the cache, we can't use it do to an environment change.
pluginCompat.call(compiler, '_hardSourceResetCache', []);
return rimraf(cacheDirPath);
}
if (cacheRead) {
return Promise.resolve();
}
cacheRead = true;
logMessages.configHashBuildWith(compiler, {
cacheDirPath,
configHash: compiler.__hardSource_configHash,
});
function contextKeys(compiler, fn) {
return source => {
const dest = {};
Object.keys(source).forEach(key => {
dest[fn(compiler, key)] = source[key];
});
return dest;
};
}
function contextValues(compiler, fn) {
return source => {
const dest = {};
Object.keys(source).forEach(key => {
const value = fn(compiler, source[key], key);
if (value) {
dest[key] = value;
} else {
delete dest[key];
}
});
return dest;
};
}
function copyWithDeser(dest, source) {
Object.keys(source).forEach(key => {
const item = source[key];
dest[key] = typeof item === 'string' ? JSON.parse(item) : item;
});
}
return Promise.all([
compilerHooks._hardSourceReadCache.promise({
contextKeys,
contextValues,
contextNormalPath,
contextNormalRequest,
contextNormalModuleId,
copyWithDeser,
}),
])
.catch(error => {
logMessages.serialBadCache(compiler, error);
return rimraf(cacheDirPath);
})
.then(() => {
// console.log('cache in', Date.now() - start);
});
});
}
compilerHooks.watchRun.tapPromise(
'HardSource - index - readOrReset',
runReadOrReset,
);
compilerHooks.run.tapPromise(
'HardSource - index - readOrReset',
runReadOrReset,
);
const detectModule = path => {
try {
require(path);
return true;
} catch (_) {
return false;
}
};
const webpackFeatures = {
concatenatedModule: detectModule(
'webpack/lib/optimize/ConcatenatedModule',
),
generator: detectModule('webpack/lib/JavascriptGenerator'),
};
let schemasVersion = 2;
if (webpackFeatures.concatenatedModule) {
schemasVersion = 3;
}
if (webpackFeatures.generator) {
schemasVersion = 4;
}
const ArchetypeSystem = require('./lib/SystemArchetype');
const ParitySystem = require('./lib/SystemParity');
const AssetCache = require('./lib/CacheAsset');
const ModuleCache = require('./lib/CacheModule');
const EnhancedResolveCache = require('./lib/CacheEnhancedResolve');
const Md5Cache = require('./lib/CacheMd5');
const ModuleResolverCache = require('./lib/CacheModuleResolver');
const TransformCompilationPlugin = require('./lib/TransformCompilationPlugin');
const TransformAssetPlugin = require('./lib/TransformAssetPlugin');
let TransformConcatenationModulePlugin;
if (webpackFeatures.concatenatedModule) {
TransformConcatenationModulePlugin = require('./lib/TransformConcatenationModulePlugin');
}
const TransformNormalModulePlugin = require('./lib/TransformNormalModulePlugin');
const TransformNormalModuleFactoryPlugin = require('./lib/TransformNormalModuleFactoryPlugin');
const TransformModuleAssetsPlugin = require('./lib/TransformModuleAssetsPlugin');
const TransformModuleErrorsPlugin = require('./lib/TransformModuleErrorsPlugin');
const SupportExtractTextPlugin = require('./lib/SupportExtractTextPlugin');
let SupportMiniCssExtractPlugin;
if (webpackFeatures.generator) {
SupportMiniCssExtractPlugin = require('./lib/SupportMiniCssExtractPlugin');
}
const TransformDependencyBlockPlugin = require('./lib/TransformDependencyBlockPlugin');
const TransformBasicDependencyPlugin = require('./lib/TransformBasicDependencyPlugin');
let HardHarmonyDependencyPlugin;
const TransformSourcePlugin = require('./lib/TransformSourcePlugin');
const TransformParserPlugin = require('./lib/TransformParserPlugin');
let TransformGeneratorPlugin;
if (webpackFeatures.generator) {
TransformGeneratorPlugin = require('./lib/TransformGeneratorPlugin');
}
const ChalkLoggerPlugin = require('./lib/ChalkLoggerPlugin');
new ArchetypeSystem().apply(compiler);
new ParitySystem().apply(compiler);
new AssetCache().apply(compiler);
new ModuleCache().apply(compiler);
new EnhancedResolveCache().apply(compiler);
new Md5Cache().apply(compiler);
new ModuleResolverCache().apply(compiler);
new TransformCompilationPlugin().apply(compiler);
new TransformAssetPlugin().apply(compiler);
new TransformNormalModulePlugin({
schema: schemasVersion,
}).apply(compiler);
new TransformNormalModuleFactoryPlugin().apply(compiler);
if (TransformConcatenationModulePlugin) {
new TransformConcatenationModulePlugin().apply(compiler);
}
new TransformModuleAssetsPlugin().apply(compiler);
new TransformModuleErrorsPlugin().apply(compiler);
new SupportExtractTextPlugin().apply(compiler);
if (SupportMiniCssExtractPlugin) {
new SupportMiniCssExtractPlugin().apply(compiler);
}
new TransformDependencyBlockPlugin({
schema: schemasVersion,
}).apply(compiler);
new TransformBasicDependencyPlugin({
schema: schemasVersion,
}).apply(compiler);
new TransformSourcePlugin({
schema: schemasVersion,
}).apply(compiler);
new TransformParserPlugin({
schema: schemasVersion,
}).apply(compiler);
if (TransformGeneratorPlugin) {
new TransformGeneratorPlugin({
schema: schemasVersion,
}).apply(compiler);
}
new ChalkLoggerPlugin(this.options.info).apply(compiler);
function runVerify(_compiler) {
if (!active) {
return Promise.resolve();
}
const stats = {};
return pluginCompat.promise(compiler, '_hardSourceVerifyCache', []);
}
compilerHooks.watchRun.tapPromise('HardSource - index - verify', runVerify);
compilerHooks.run.tapPromise('HardSource - index - verify', runVerify);
let freeze;
compilerHooks._hardSourceMethods.tap('HardSource - index', methods => {
freeze = methods.freeze;
});
compilerHooks.afterCompile.tapPromise('HardSource - index', compilation => {
if (!active) {
return Promise.resolve();
}
const startCacheTime = Date.now();
const identifierPrefix = cachePrefix(compilation);
if (identifierPrefix !== null) {
freeze('Compilation', null, compilation, {
compilation,
});
}
return Promise.all([
mkdirp(cacheDirPath).then(() =>
Promise.all([
fsWriteFile(path.join(cacheDirPath, 'stamp'), currentStamp, 'utf8'),
fsWriteFile(
path.join(cacheDirPath, 'version'),
hardSourceVersion,
'utf8',
),
]),
),
pluginCompat.promise(compiler, '_hardSourceWriteCache', [
compilation,
{
relateNormalPath,
relateNormalRequest,
relateNormalModuleId,
contextNormalPath,
contextNormalRequest,
contextNormalModuleId,
},
]),
]).then(() => {
// console.log('cache out', Date.now() - startCacheTime);
});
});
}
}
module.exports = HardSourceWebpackPlugin;
HardSourceWebpackPlugin.ExcludeModulePlugin = ExcludeModulePlugin;
HardSourceWebpackPlugin.HardSourceLevelDbSerializerPlugin = HardSourceLevelDbSerializerPlugin;
HardSourceWebpackPlugin.LevelDbSerializerPlugin = HardSourceLevelDbSerializerPlugin;
HardSourceWebpackPlugin.SerializerAppend2Plugin = SerializerAppend2Plugin;
HardSourceWebpackPlugin.SerializerAppendPlugin = SerializerAppendPlugin;
HardSourceWebpackPlugin.SerializerCacachePlugin = SerializerCacachePlugin;
HardSourceWebpackPlugin.SerializerJsonPlugin = SerializerJsonPlugin;
Object.defineProperty(HardSourceWebpackPlugin, 'ParallelModulePlugin', {
get() {
return require('./lib/ParallelModulePlugin');
},
});
-127
View File
@@ -1,127 +0,0 @@
const crypto = require('crypto');
const pluginCompat = require('./util/plugin-compat');
const relateContext = require('./util/relate-context');
const { parityCacheFromCache, pushParityWriteOps } = require('./util/parity');
function requestHash(request) {
return crypto
.createHash('sha1')
.update(request)
.digest()
.hexSlice();
}
const relateNormalRequest = relateContext.relateNormalRequest;
class AssetCache {
apply(compiler) {
const compilerHooks = pluginCompat.hooks(compiler);
let assetCache = {};
let parityCache = {};
const assetArchetypeCache = {
_ops: [],
get(id) {
const hashId = requestHash(relateNormalRequest(compiler, id));
if (assetCache[hashId]) {
if (typeof assetCache[hashId] === 'string') {
assetCache[hashId] = JSON.parse(assetCache[hashId]);
}
return assetCache[hashId];
}
},
set(id, item) {
const hashId = requestHash(relateNormalRequest(compiler, id));
if (item) {
assetCache[hashId] = item;
this._ops.push({
key: hashId,
value: item,
});
} else {
assetCache[hashId] = null;
this._ops.push({
key: hashId,
value: null,
});
}
},
operations() {
const ops = this._ops.slice();
this._ops.length = 0;
return ops;
},
};
compilerHooks._hardSourceArchetypeRegister.call(
'Asset',
assetArchetypeCache,
);
let assetCacheSerializer;
let assetParityCacheSerializer;
compilerHooks._hardSourceCreateSerializer.tap(
'HardSource - AssetCache',
(cacheSerializerFactory, cacheDirPath) => {
assetCacheSerializer = cacheSerializerFactory.create({
name: 'assets',
type: 'file',
cacheDirPath,
});
assetParityCacheSerializer = cacheSerializerFactory.create({
name: 'assets-parity',
type: 'data',
cacheDirPath,
});
},
);
compilerHooks._hardSourceResetCache.tap('HardSource - AssetCache', () => {
assetCache = {};
parityCache = {};
});
compilerHooks._hardSourceReadCache.tapPromise(
'HardSource - AssetCache',
() =>
Promise.all([
assetCacheSerializer.read().then(_assetCache => {
assetCache = _assetCache;
}),
assetParityCacheSerializer.read().then(_parityCache => {
parityCache = _parityCache;
}),
]),
);
compilerHooks._hardSourceParityCache.tap(
'HardSource - AssetCache',
parityRoot => {
parityCacheFromCache('Asset', parityRoot, parityCache);
},
);
compilerHooks._hardSourceWriteCache.tapPromise(
'HardSource - AssetCache',
compilation => {
const assetOps = assetArchetypeCache.operations();
const parityOps = [];
pushParityWriteOps(compilation, parityOps);
return Promise.all([
assetCacheSerializer.write(assetOps),
assetParityCacheSerializer.write(parityOps),
]);
},
);
}
}
module.exports = AssetCache;
-517
View File
@@ -1,517 +0,0 @@
const path = require('path');
const lodash = require('lodash');
const nodeObjectHash = require('node-object-hash');
const parseJson = require('parse-json');
const pluginCompat = require('./util/plugin-compat');
const promisify = require('./util/promisify');
const relateContext = require('./util/relate-context');
const serial = require('./util/serial');
const values = require('./util/Object.values');
const bulkFsTask = require('./util/bulk-fs-task');
const { parityCacheFromCache, pushParityWriteOps } = require('./util/parity');
const serialNormalResolved = serial.created({
result: serial.path,
resourceResolveData: serial.objectAssign({
context: serial.created({
issuer: serial.request,
resolveOptions: serial.identity,
}),
path: serial.path,
descriptionFilePath: serial.path,
descriptionFileRoot: serial.path,
}),
});
class EnhancedResolveCache {
apply(compiler) {
let missingCacheSerializer;
let resolverCacheSerializer;
let missingCache = { normal: {}, loader: {}, context: {} };
let resolverCache = { normal: {}, loader: {}, context: {} };
let parityCache = {};
const compilerHooks = pluginCompat.hooks(compiler);
compilerHooks._hardSourceCreateSerializer.tap(
'HardSource - EnhancedResolveCache',
(cacheSerializerFactory, cacheDirPath) => {
missingCacheSerializer = cacheSerializerFactory.create({
name: 'missing-resolve',
type: 'data',
autoParse: true,
cacheDirPath,
});
resolverCacheSerializer = cacheSerializerFactory.create({
name: 'resolver',
type: 'data',
autoParse: true,
cacheDirPath,
});
},
);
compilerHooks._hardSourceResetCache.tap(
'HardSource - EnhancedResolveCache',
() => {
missingCache = { normal: {}, loader: {}, context: {} };
resolverCache = { normal: {}, loader: {}, context: {} };
parityCache = {};
compiler.__hardSource_missingCache = missingCache;
},
);
compilerHooks._hardSourceReadCache.tapPromise(
'HardSource - EnhancedResolveCache',
({ contextNormalPath, contextNormalRequest }) => {
return Promise.all([
missingCacheSerializer.read().then(_missingCache => {
missingCache = { normal: {}, loader: {}, context: {} };
compiler.__hardSource_missingCache = missingCache;
function contextNormalMissingKey(compiler, key) {
const parsed = parseJson(key);
return JSON.stringify([
contextNormalPath(compiler, parsed[0]),
contextNormalPath(compiler, parsed[1]),
]);
}
function contextNormalMissing(compiler, missing) {
return missing.map(missed =>
contextNormalRequest(compiler, missed),
);
}
Object.keys(_missingCache).forEach(key => {
let item = _missingCache[key];
if (typeof item === 'string') {
item = parseJson(item);
}
const splitIndex = key.indexOf('/');
const group = key.substring(0, splitIndex);
const keyName = contextNormalMissingKey(
compiler,
key.substring(splitIndex + 1),
);
missingCache[group] = missingCache[group] || {};
missingCache[group][keyName] = contextNormalMissing(
compiler,
item,
);
});
}),
resolverCacheSerializer.read().then(_resolverCache => {
resolverCache = { normal: {}, loader: {}, context: {} };
parityCache = {};
function contextNormalResolvedKey(compiler, key) {
const parsed = parseJson(key);
return JSON.stringify([
contextNormalPath(compiler, parsed[0]),
parsed[1],
]);
}
function contextNormalResolved(compiler, resolved) {
return serialNormalResolved.thaw(resolved, resolved, {
compiler,
});
}
Object.keys(_resolverCache).forEach(key => {
let item = _resolverCache[key];
if (typeof item === 'string') {
item = parseJson(item);
}
if (key.startsWith('__hardSource_parityToken')) {
parityCache[key] = item;
return;
}
const splitIndex = key.indexOf('/');
const group = key.substring(0, splitIndex);
const keyName = contextNormalResolvedKey(
compiler,
key.substring(splitIndex + 1),
);
resolverCache[group] = resolverCache[group] || {};
resolverCache[group][keyName] = contextNormalResolved(
compiler,
item,
);
});
}),
]);
},
);
compilerHooks._hardSourceParityCache.tap(
'HardSource - EnhancedResolveCache',
parityRoot => {
parityCacheFromCache('EnhancedResolve', parityRoot, parityCache);
},
);
let missingVerifyResolve;
compiler.__hardSource_missingVerify = new Promise(resolve => {
missingVerifyResolve = resolve;
});
compilerHooks._hardSourceVerifyCache.tapPromise(
'HardSource - EnhancedResolveCache',
() =>
(() => {
compiler.__hardSource_missingVerify = new Promise(resolve => {
missingVerifyResolve = resolve;
});
const bulk = lodash.flatten(
Object.keys(missingCache).map(group =>
lodash.flatten(
Object.keys(missingCache[group])
.map(key => {
const missingItem = missingCache[group][key];
if (!missingItem) {
return;
}
return missingItem.map((missed, index) => [
group,
key,
missed,
index,
]);
})
.filter(Boolean),
),
),
);
return bulkFsTask(bulk, (item, task) => {
const group = item[0];
const key = item[1];
const missingItem = missingCache[group][key];
const missed = item[2];
const missedPath = missed.split('?')[0];
const missedIndex = item[3];
// The missed index is the resolved item. Invalidate if it does not
// exist.
if (missedIndex === missingItem.length - 1) {
compiler.inputFileSystem.stat(
missed,
task((err, stat) => {
if (err) {
missingItem.invalid = true;
missingItem.invalidReason = 'resolved now missing';
}
}),
);
} else {
compiler.inputFileSystem.stat(
missed,
task((err, stat) => {
if (err) {
return;
}
if (stat.isDirectory()) {
if (group === 'context') {
missingItem.invalid = true;
}
}
if (stat.isFile()) {
if (group === 'loader' || group.startsWith('normal')) {
missingItem.invalid = true;
missingItem.invalidReason = 'missing now found';
}
}
}),
);
}
});
})().then(missingVerifyResolve),
);
function bindResolvers() {
function configureMissing(key, resolver) {
// missingCache[key] = missingCache[key] || {};
// resolverCache[key] = resolverCache[key] || {};
const _resolve = resolver.resolve;
resolver.resolve = function(info, context, request, cb, cb2) {
let numArgs = 4;
if (!cb) {
numArgs = 3;
cb = request;
request = context;
context = info;
}
let resolveContext;
if (cb2) {
numArgs = 5;
resolveContext = cb;
cb = cb2;
}
if (info && info.resolveOptions) {
key = `normal-${new nodeObjectHash({ sort: false }).hash(
info.resolveOptions,
)}`;
resolverCache[key] = resolverCache[key] || {};
missingCache[key] = missingCache[key] || {};
}
const resolveId = JSON.stringify([context, request]);
const absResolveId = JSON.stringify([
context,
relateContext.relateAbsolutePath(context, request),
]);
const resolve =
resolverCache[key][resolveId] || resolverCache[key][absResolveId];
if (resolve && !resolve.invalid) {
const missingId = JSON.stringify([context, resolve.result]);
const missing = missingCache[key][missingId];
if (missing && !missing.invalid) {
return cb(
null,
[resolve.result].concat(request.split('?').slice(1)).join('?'),
resolve.resourceResolveData,
);
} else {
resolve.invalid = true;
resolve.invalidReason = 'out of date';
}
}
let localMissing = [];
const callback = (err, result, result2) => {
if (result) {
const inverseId = JSON.stringify([context, result.split('?')[0]]);
const resolveId = JSON.stringify([context, request]);
// Skip recording missing for any dependency in node_modules.
// Changes to them will be handled by the environment hash. If we
// tracked the stuff in node_modules too, we'd be adding a whole
// bunch of reduntant work.
if (result.includes('node_modules')) {
localMissing = localMissing.filter(
missed => !missed.includes('node_modules'),
);
}
// In case of other cache layers, if we already have missing
// recorded and we get a new empty array of missing, keep the old
// value.
if (localMissing.length === 0 && missingCache[key][inverseId]) {
return cb(err, result, result2);
}
missingCache[key][inverseId] = localMissing
.filter((missed, missedIndex) => {
const index = localMissing.indexOf(missed);
if (index === -1 || index < missedIndex) {
return false;
}
if (missed === result) {
return false;
}
return true;
})
.concat(result.split('?')[0]);
missingCache[key][inverseId].new = true;
resolverCache[key][resolveId] = {
result: result.split('?')[0],
resourceResolveData: result2,
new: true,
};
}
cb(err, result, result2);
};
const _missing =
cb.missing || (resolveContext && resolveContext.missing);
if (_missing) {
callback.missing = {
push(path) {
localMissing.push(path);
_missing.push(path);
},
add(path) {
localMissing.push(path);
_missing.add(path);
},
};
if (resolveContext) {
resolveContext.missing = callback.missing;
}
} else {
callback.missing = Object.assign(localMissing, {
add(path) {
localMissing.push(path);
},
});
if (resolveContext) {
resolveContext.missing = callback.missing;
}
}
if (numArgs === 3) {
_resolve.call(this, context, request, callback);
} else if (numArgs === 5) {
_resolve.call(
this,
info,
context,
request,
resolveContext,
callback,
);
} else {
_resolve.call(this, info, context, request, callback);
}
};
}
if (compiler.resolverFactory) {
compiler.resolverFactory.hooks.resolver
.for('normal')
.tap('HardSource resolve cache', (resolver, options) => {
const normalCacheId = `normal-${new nodeObjectHash({
sort: false,
}).hash(Object.assign({}, options, { fileSystem: null }))}`;
resolverCache[normalCacheId] = resolverCache[normalCacheId] || {};
missingCache[normalCacheId] = missingCache[normalCacheId] || {};
configureMissing(normalCacheId, resolver);
return resolver;
});
compiler.resolverFactory.hooks.resolver
.for('loader')
.tap('HardSource resolve cache', resolver => {
configureMissing('loader', resolver);
return resolver;
});
compiler.resolverFactory.hooks.resolver
.for('context')
.tap('HardSource resolve cache', resolver => {
configureMissing('context', resolver);
return resolver;
});
} else {
configureMissing('normal', compiler.resolvers.normal);
configureMissing('loader', compiler.resolvers.loader);
configureMissing('context', compiler.resolvers.context);
}
}
compilerHooks.afterPlugins.tap('HardSource - EnhancedResolveCache', () => {
if (compiler.resolvers.normal) {
bindResolvers();
} else {
compilerHooks.afterResolvers.tap(
'HardSource - EnhancedResolveCache',
bindResolvers,
);
}
});
compilerHooks._hardSourceWriteCache.tapPromise(
'HardSource - EnhancedResolveCache',
(compilation, { relateNormalPath, relateNormalRequest }) => {
if (compilation.compiler.parentCompilation) {
const resolverOps = [];
pushParityWriteOps(compilation, resolverOps);
return resolverCacheSerializer.write(resolverOps);
}
const missingOps = [];
const resolverOps = [];
function relateNormalMissingKey(compiler, key) {
const parsed = parseJson(key);
return JSON.stringify([
relateNormalPath(compiler, parsed[0]),
relateNormalPath(compiler, parsed[1]),
]);
}
function relateNormalMissing(compiler, missing) {
return missing.map(missed => relateNormalRequest(compiler, missed));
}
Object.keys(missingCache).forEach(group => {
Object.keys(missingCache[group]).forEach(key => {
if (!missingCache[group][key]) {
return;
}
if (missingCache[group][key].new) {
missingCache[group][key].new = false;
missingOps.push({
key: `${group}/${relateNormalMissingKey(compiler, key)}`,
value: JSON.stringify(
relateNormalMissing(compiler, missingCache[group][key]),
),
});
} else if (missingCache[group][key].invalid) {
missingCache[group][key] = null;
missingOps.push({
key: `${group}/${relateNormalMissingKey(compiler, key)}`,
value: null,
});
}
});
});
function relateNormalResolvedKey(compiler, key) {
const parsed = parseJson(key);
return JSON.stringify([
relateNormalPath(compiler, parsed[0]),
relateContext.relateAbsolutePath(parsed[0], parsed[1]),
]);
}
function relateNormalResolved(compiler, resolved) {
return serialNormalResolved.freeze(resolved, resolved, {
compiler,
});
}
Object.keys(resolverCache).forEach(group => {
Object.keys(resolverCache[group]).forEach(key => {
if (!resolverCache[group][key]) {
return;
}
if (resolverCache[group][key].new) {
resolverCache[group][key].new = false;
resolverOps.push({
key: `${group}/${relateNormalResolvedKey(compiler, key)}`,
value: JSON.stringify(
relateNormalResolved(compiler, resolverCache[group][key]),
),
});
} else if (resolverCache[group][key].invalid) {
resolverCache[group][key] = null;
resolverOps.push({
key: `${group}/${relateNormalResolvedKey(compiler, key)}`,
value: null,
});
}
});
});
pushParityWriteOps(compilation, resolverOps);
return Promise.all([
missingCacheSerializer.write(missingOps),
resolverCacheSerializer.write(resolverOps),
]);
},
);
}
}
module.exports = EnhancedResolveCache;
-481
View File
@@ -1,481 +0,0 @@
const crypto = require('crypto');
const path = require('path');
const lodash = require('lodash');
const bulkFsTask = require('./util/bulk-fs-task');
const pluginCompat = require('./util/plugin-compat');
const promisify = require('./util/promisify');
const values = require('./util/Object.values');
const { parityCacheFromCache, pushParityWriteOps } = require('./util/parity');
class Md5Cache {
apply(compiler) {
let md5Cache = {};
let parityCache = {};
const fileMd5s = {};
const cachedMd5s = {};
let fileTimestamps = {};
const contextMd5s = {};
let contextTimestamps = {};
let md5CacheSerializer;
let latestStats = {};
let latestMd5s = {};
let unbuildMd5s = {};
let fileDependencies = [];
let contextDependencies = [];
let stat;
let readdir;
let readFile;
let mtime;
let md5;
let fileStamp;
let contextStamp;
let contextStamps;
function bindFS() {
stat = promisify(compiler.inputFileSystem.stat, {
context: compiler.inputFileSystem,
});
// stat = promisify(fs.stat, {context: fs});
readdir = promisify(compiler.inputFileSystem.readdir, {
context: compiler.inputFileSystem,
});
readFile = promisify(compiler.inputFileSystem.readFile, {
context: compiler.inputFileSystem,
});
mtime = file =>
stat(file)
.then(stat => +stat.mtime)
.catch(() => 0);
md5 = file =>
readFile(file)
.then(contents =>
crypto
.createHash('md5')
.update(contents, 'utf8')
.digest('hex'),
)
.catch(() => '');
fileStamp = (file, stats) => {
if (compiler.__hardSource_fileTimestamps[file]) {
return compiler.__hardSource_fileTimestamps[file];
} else {
if (!stats[file]) {
stats[file] = stat(file);
}
return stats[file].then(stat => {
const mtime = +stat.mtime;
compiler.__hardSource_fileTimestamps[file] = mtime;
return mtime;
});
}
};
contextStamp = (dir, stats) => {
const context = {};
let selfTime = 0;
function walk(dir) {
return readdir(dir)
.then(items =>
Promise.all(
items.map(item => {
const file = path.join(dir, item);
if (!stats[file]) {
stats[file] = stat(file);
}
return stats[file].then(
stat => {
if (stat.isDirectory()) {
return walk(path.join(dir, item)).then(items2 =>
items2.map(item2 => path.join(item, item2)),
);
}
if (+stat.mtime > selfTime) {
selfTime = +stat.mtime;
}
return item;
},
() => {
return;
},
);
}),
),
)
.catch(() => [])
.then(items =>
items
.reduce((carry, item) => carry.concat(item), [])
.filter(Boolean),
);
}
return walk(dir).then(items => {
items.sort();
const selfHash = crypto.createHash('md5');
items.forEach(item => {
selfHash.update(item);
});
context.mtime = selfTime;
context.hash = selfHash.digest('hex');
return context;
});
};
contextStamps = (contextDependencies, stats) => {
stats = stats || {};
const contexts = {};
contextDependencies.forEach(context => {
contexts[context] = { files: [], mtime: 0, hash: '' };
});
const compilerContextTs = compiler.contextTimestamps;
contextDependencies.forEach(contextPath => {
const _context = contextStamp(contextPath, stats);
if (!_context.then) {
contexts[contextPath] = _context;
} else {
contexts[contextPath] = _context.then(context => {
contexts[contextPath] = context;
return context;
});
}
});
return contexts;
};
}
if (compiler.inputFileSystem) {
bindFS();
} else {
pluginCompat.tap(
compiler,
'afterEnvironment',
'HardSource - Md5Cache',
bindFS,
);
}
pluginCompat.tap(
compiler,
'_hardSourceCreateSerializer',
'HardSource - Md5Cache',
(cacheSerializerFactory, cacheDirPath) => {
md5CacheSerializer = cacheSerializerFactory.create({
name: 'md5',
type: 'data',
autoParse: true,
cacheDirPath,
});
},
);
pluginCompat.tap(
compiler,
'_hardSourceResetCache',
'HardSource - Md5Cache',
() => {
md5Cache = {};
parityCache = {};
fileTimestamps = {};
contextTimestamps = {};
},
);
pluginCompat.tapPromise(
compiler,
'_hardSourceReadCache',
'HardSource - Md5Cache',
({ contextKeys, contextNormalPath }) =>
md5CacheSerializer
.read()
.then(_md5Cache => {
Object.keys(_md5Cache).forEach(key => {
if (key.startsWith('__hardSource_parityToken')) {
parityCache[key] = _md5Cache[key];
delete _md5Cache[key];
}
});
return _md5Cache;
})
.then(contextKeys(compiler, contextNormalPath))
.then(_md5Cache => {
Object.keys(_md5Cache).forEach(key => {
if (typeof _md5Cache[key] === 'string') {
_md5Cache[key] = JSON.parse(_md5Cache[key]);
}
if (_md5Cache[key] && _md5Cache[key].hash) {
cachedMd5s[key] = _md5Cache[key].hash;
}
});
md5Cache = _md5Cache;
})
.then(() => {
const dependencies = Object.keys(md5Cache);
fileDependencies = dependencies.filter(
file => md5Cache[file].isFile,
);
contextDependencies = dependencies.filter(
file => md5Cache[file].isDirectory,
);
}),
);
pluginCompat.tap(
compiler,
'_hardSourceParityCache',
'HardSource - Md5Cache',
parityRoot => {
parityCacheFromCache('Md5', parityRoot, parityCache);
},
);
pluginCompat.tapPromise(
compiler,
'_hardSourceVerifyCache',
'HardSource - Md5Cache',
() => {
latestStats = {};
latestMd5s = {};
unbuildMd5s = {};
const stats = {};
// var md5s = latestMd5s;
// Prepare objects to mark md5s to delete if they are not used.
for (const key in cachedMd5s) {
unbuildMd5s[key] = null;
}
return Promise.all([
(() => {
const compilerFileTs = (compiler.__hardSource_fileTimestamps = {});
const fileTs = (fileTimestamps = {});
return bulkFsTask(fileDependencies, (file, task) => {
if (compiler.__hardSource_fileTimestamps[file]) {
return compiler.__hardSource_fileTimestamps[file];
} else {
compiler.inputFileSystem.stat(
file,
task((err, value) => {
if (err) {
return 0;
}
const mtime = +value.mtime;
compiler.__hardSource_fileTimestamps[file] = mtime;
return mtime;
}),
);
}
}).then(mtimes => {
const bulk = lodash.zip(fileDependencies, mtimes);
return bulkFsTask(bulk, (item, task) => {
const file = item[0];
const mtime = item[1];
fileTs[file] = mtime || 0;
if (!compiler.__hardSource_fileTimestamps[file]) {
compiler.__hardSource_fileTimestamps[file] = mtime;
}
compiler.inputFileSystem.readFile(
file,
task(function(err, body) {
if (err) {
fileMd5s[file] = '';
return;
}
const hash = crypto
.createHash('md5')
.update(body, 'utf8')
.digest('hex');
fileMd5s[file] = hash;
}),
);
});
});
})(),
(() => {
compiler.contextTimestamps = compiler.contextTimestamps || {};
const contextTs = (contextTimestamps = {});
const contexts = contextStamps(contextDependencies, stats);
return Promise.all(values(contexts)).then(function() {
for (var contextPath in contexts) {
var context = contexts[contextPath];
if (!compiler.contextTimestamps[contextPath]) {
compiler.contextTimestamps[contextPath] = context.mtime;
}
contextTimestamps[contextPath] = context.mtime;
fileMd5s[contextPath] = context.hash;
}
});
})(),
]);
},
);
pluginCompat.tap(
compiler,
'compilation',
'HardSource - Md5Cache',
compilation => {
compilation.__hardSourceFileMd5s = fileMd5s;
compilation.__hardSourceCachedMd5s = cachedMd5s;
compilation.__hardSourceFileTimestamps = fileTimestamps;
},
);
pluginCompat.tapPromise(
compiler,
'_hardSourceWriteCache',
'HardSource - Md5Cache',
(compilation, { relateNormalPath, contextNormalPath }) => {
const moduleOps = [];
const dataOps = [];
const md5Ops = [];
const assetOps = [];
const moduleResolveOps = [];
const missingOps = [];
const resolverOps = [];
let buildingMd5s = {};
function buildMd5Ops(dependencies) {
dependencies.forEach(file => {
function updateMd5CacheItem(value) {
if (
!md5Cache[file] ||
(md5Cache[file] && md5Cache[file].hash !== value.hash)
) {
md5Cache[file] = value;
cachedMd5s[file] = value.hash;
md5Ops.push({
key: relateNormalPath(compiler, file),
value: value,
});
} else if (
!value.mtime &&
md5Cache[file] &&
md5Cache[file].mtime !== value.mtime
) {
md5Cache[file] = value;
cachedMd5s[file] = value.hash;
}
}
const building = buildingMd5s[file];
if (!building.then) {
updateMd5CacheItem(building);
} else {
buildingMd5s[file] = building.then(updateMd5CacheItem);
}
});
}
const fileDependencies = Array.from(compilation.fileDependencies).map(
file => contextNormalPath(compiler, file),
);
const MD5_TIME_PRECISION_BUFFER = 2000;
fileDependencies.forEach(file => {
if (buildingMd5s[file]) {
return;
}
delete unbuildMd5s[file];
if (fileMd5s[file]) {
buildingMd5s[file] = {
// Subtract a small buffer from now for file systems that record
// lower precision mtimes.
mtime: Date.now() - MD5_TIME_PRECISION_BUFFER,
hash: fileMd5s[file],
isFile: true,
isDirectory: false,
};
} else {
buildingMd5s[file] = md5(file).then(hash => ({
mtime: Date.now() - MD5_TIME_PRECISION_BUFFER,
hash,
isFile: true,
isDirectory: false,
}));
}
});
buildMd5Ops(fileDependencies);
const contextDependencies = Array.from(
compilation.contextDependencies,
).map(file => contextNormalPath(compiler, file));
const contexts = contextStamps(contextDependencies);
contextDependencies.forEach(file => {
if (buildingMd5s[file]) {
return;
}
delete unbuildMd5s[file];
let context = contexts[file];
if (!context.then) {
// Subtract a small buffer from now for file systems that record lower
// precision mtimes.
context.mtime = Date.now() - MD5_TIME_PRECISION_BUFFER;
context.isFile = false;
context.isDirectory = true;
} else {
context = context.then(context => {
context.mtime = Date.now() - MD5_TIME_PRECISION_BUFFER;
context.isFile = false;
context.isDirectory = true;
return context;
});
}
buildingMd5s[file] = context;
});
buildMd5Ops(contextDependencies);
const writeMd5Ops = Promise.all(
Object.keys(buildingMd5s).map(key => buildingMd5s[key]),
).then(() => {
if (!compilation.compiler.parentCompilation) {
for (const key in unbuildMd5s) {
md5Ops.push({
key: relateNormalPath(compiler, key),
value: unbuildMd5s[key],
});
}
}
pushParityWriteOps(compilation, md5Ops);
});
return writeMd5Ops.then(() => md5CacheSerializer.write(md5Ops));
},
);
}
}
module.exports = Md5Cache;
-145
View File
@@ -1,145 +0,0 @@
const pluginCompat = require('./util/plugin-compat');
const relateContext = require('./util/relate-context');
const { parityCacheFromCache, pushParityWriteOps } = require('./util/parity');
const relateNormalPath = relateContext.relateNormalPath;
function relateNormalRequest(compiler, key) {
return key
.split('!')
.map(subkey => relateNormalPath(compiler, subkey))
.join('!');
}
function relateNormalModuleId(compiler, id) {
return id.substring(0, 24) + relateNormalRequest(compiler, id.substring(24));
}
class ModuleCache {
apply(compiler) {
const compilerHooks = pluginCompat.hooks(compiler);
let moduleCache = {};
let parityCache = {};
const moduleArchetypeCache = {
_ops: [],
get(id) {
if (moduleCache[id] && !moduleCache[id].invalid) {
if (typeof moduleCache[id] === 'string') {
moduleCache[id] = JSON.parse(moduleCache[id]);
}
return moduleCache[id];
}
},
set(id, item) {
moduleCache[id] = item;
if (item) {
this._ops.push(id);
} else if (moduleCache[id]) {
if (typeof moduleCache[id] === 'string') {
moduleCache[id] = JSON.parse(moduleCache[id]);
}
moduleCache[id].invalid = true;
moduleCache[id].invalidReason = 'overwritten';
this._ops.push(id);
}
},
operations() {
const _this = this;
const ops = this._ops.map(id => ({
key: relateNormalModuleId(compiler, id),
value: _this.get(id) || null,
}));
this._ops.length = 0;
return ops;
},
};
compilerHooks._hardSourceArchetypeRegister.call(
'Module',
moduleArchetypeCache,
);
let moduleCacheSerializer;
compilerHooks._hardSourceCreateSerializer.tap(
'HardSource - ModuleCache',
(cacheSerializerFactory, cacheDirPath) => {
moduleCacheSerializer = cacheSerializerFactory.create({
name: 'module',
type: 'data',
cacheDirPath,
autoParse: true,
});
},
);
compilerHooks._hardSourceResetCache.tap('HardSource - ModuleCache', () => {
moduleCache = {};
});
compilerHooks._hardSourceReadCache.tapPromise(
'HardSource - ModuleCache',
({ contextKeys, contextNormalModuleId, copyWithDeser }) =>
moduleCacheSerializer
.read()
.then(_moduleCache => {
Object.keys(_moduleCache).forEach(key => {
if (key.startsWith('__hardSource_parityToken')) {
parityCache[key] = _moduleCache[key];
delete _moduleCache[key];
}
});
return _moduleCache;
})
.then(contextKeys(compiler, contextNormalModuleId))
.then(copyWithDeser.bind(null, moduleCache)),
);
compilerHooks._hardSourceParityCache.tap(
'HardSource - ModuleCache',
parityRoot => {
parityCacheFromCache('Module', parityRoot, parityCache);
},
);
compilerHooks.compilation.tap('HardSource - ModuleCache', compilation => {
compilation.__hardSourceModuleCache = moduleCache;
});
compilerHooks._hardSourceWriteCache.tapPromise(
'HardSource - ModuleCache',
compilation => {
const moduleOps = moduleArchetypeCache.operations();
if (!compilation.compiler.parentCompilation) {
// Add ops to remove no longer valid modules. If they were replaced with a
// up to date module, they will already have replaced this item so we
// won't accidentally delete up to date modules.
Object.keys(moduleCache).forEach(key => {
const cacheItem = moduleCache[key];
if (cacheItem && cacheItem.invalid) {
// console.log('invalid', cacheItem.invalidReason);
moduleCache[key] = null;
moduleOps.push({
key,
value: null,
});
}
});
}
pushParityWriteOps(compilation, moduleOps);
return moduleCacheSerializer.write(moduleOps);
},
);
}
}
module.exports = ModuleCache;
-408
View File
@@ -1,408 +0,0 @@
const nodeObjectHash = require('node-object-hash');
const parseJson = require('parse-json');
const serial = require('./util/serial');
const pluginCompat = require('./util/plugin-compat');
const relateContext = require('./util/relate-context');
const { parityCacheFromCache, pushParityWriteOps } = require('./util/parity');
const serialJsonKey = {
freeze(arg, value, extra) {
return JSON.parse(arg);
},
thaw(arg, frozen, extra) {
return JSON.stringify(arg);
},
};
const serialJson = {
freeze(arg, value, extra) {
return JSON.stringify(arg);
},
thaw(arg, frozen, extra) {
return JSON.parse(arg);
},
};
const serialObjectAssign = serial.objectAssign;
const serialResolveOptionsKey = serialObjectAssign({
context: serial.path,
userRequest: serial.request,
options: serialObjectAssign({
request: serial.request,
}),
});
const serialResolveKey = serialObjectAssign({
context: serial.path,
request: serial.request,
});
const serialNormalModuleResolveKey = serial.pipe(
serialJsonKey,
{
freeze(arg, key, extra) {
if (Array.isArray(arg)) {
return [
arg[0],
serial.path.freeze(arg[1], arg[1], extra),
serial.request.freeze(arg[2], arg[2], extra),
];
} else if (!arg.request) {
return serialResolveOptionsKey.freeze(arg, arg, extra);
} else {
return serialResolveKey.freeze(arg, arg, extra);
}
},
thaw(arg, frozen, extra) {
if (Array.isArray(arg)) {
return [
arg[0],
serial.path.thaw(arg[1], arg[1], extra),
serial.request.thaw(arg[2], arg[2], extra),
];
} else if (!arg.request) {
return serialResolveOptionsKey.thaw(arg, arg, extra);
} else {
return serialResolveKey.thaw(arg, arg, extra);
}
},
},
serialJson,
);
const serialNormalModuleId = {
freeze(arg, module, extra) {
return (
id.substring(0, 24) + serial.request.freeze(id.substring(24), id, extra)
);
},
thaw(arg, frozen, extra) {
return (
id.substring(0, 24) + serial.request.thaw(id.substring(24), id, extra)
);
},
};
const serialResolveContext = serialObjectAssign({
identifier: serialNormalModuleId,
resource: serialNormalModuleId,
});
const serialResolveNormal = serialObjectAssign({
context: serial.path,
request: serial.request,
userRequest: serial.request,
rawRequest: serial.request,
resource: serial.request,
loaders: serial.loaders,
resourceResolveData: serial.objectAssign({
context: serial.created({
issuer: serial.request,
resolveOptions: serial.identity,
}),
path: serial.path,
request: serial.request,
descriptionFilePath: serial.path,
descriptionFileRoot: serial.path,
}),
});
const serialResolve = {
freeze(arg, module, extra) {
if (arg.type === 'context') {
return serialResolveContext.freeze(arg, arg, extra);
}
return serialResolveNormal.freeze(arg, arg, extra);
},
thaw(arg, frozen, extra) {
if (arg.type === 'context') {
return serialResolveContext.thaw(arg, arg, extra);
}
return serialResolveNormal.thaw(arg, arg, extra);
},
};
class ModuleResolverCache {
apply(compiler) {
let moduleResolveCache = {};
let parityCache = {};
let moduleResolveCacheChange = [];
let moduleResolveCacheSerializer;
const compilerHooks = pluginCompat.hooks(compiler);
compilerHooks._hardSourceCreateSerializer.tap(
'HardSource - ModuleResolverCache',
(cacheSerializerFactory, cacheDirPath) => {
moduleResolveCacheSerializer = cacheSerializerFactory.create({
name: 'module-resolve',
type: 'data',
autoParse: true,
cacheDirPath,
});
},
);
compilerHooks._hardSourceResetCache.tap(
'HardSource - ModuleResolverCache',
() => {
moduleResolveCache = {};
parityCache = {};
},
);
compilerHooks._hardSourceReadCache.tapPromise(
'HardSource - ModuleResolverCache',
({
contextKeys,
contextValues,
contextNormalPath,
contextNormalRequest,
contextNormalModuleId,
copyWithDeser,
}) => {
function contextNormalModuleResolveKey(compiler, key) {
if (key.startsWith('__hardSource_parityToken')) {
return key;
}
const parsed = parseJson(key);
if (Array.isArray(parsed)) {
return JSON.stringify([
parsed[0],
contextNormalPath(compiler, parsed[1]),
parsed[2],
]);
} else {
return JSON.stringify(
Object.assign({}, parsed, {
context: contextNormalPath(compiler, parsed.context),
}),
);
}
}
function contextNormalModuleResolve(compiler, resolved, key) {
if (key.startsWith('__hardSource_parityToken')) {
parityCache[key] = resolved;
return;
}
if (typeof resolved === 'string') {
resolved = parseJson(resolved);
}
if (resolved.type === 'context') {
return Object.assign({}, resolved, {
identifier: contextNormalModuleId(compiler, resolved.identifier),
resource: contextNormalRequest(compiler, resolved.resource),
});
}
return serialResolveNormal.thaw(resolved, resolved, {
compiler,
});
}
return moduleResolveCacheSerializer
.read()
.then(contextKeys(compiler, contextNormalModuleResolveKey))
.then(contextValues(compiler, contextNormalModuleResolve))
.then(copyWithDeser.bind(null, moduleResolveCache));
},
);
compilerHooks._hardSourceParityCache.tap(
'HardSource - ModuleResolverCache',
parityRoot => {
parityCacheFromCache('ModuleResolver', parityRoot, parityCache);
},
);
compilerHooks._hardSourceVerifyCache.tapPromise(
'HardSource - ModuleResolverCache',
() =>
compiler.__hardSource_missingVerify.then(() => {
const missingCache = compiler.__hardSource_missingCache;
// Invalidate resolve cache items.
Object.keys(moduleResolveCache).forEach(key => {
const resolveKey = parseJson(key);
const resolveItem = moduleResolveCache[key];
let normalId = 'normal';
if (resolveItem.resolveOptions) {
normalId = `normal-${new nodeObjectHash({ sort: false }).hash(
resolveItem.resolveOptions,
)}`;
}
if (resolveItem.type === 'context') {
const contextMissing =
missingCache.context[
JSON.stringify([
resolveKey.context,
resolveItem.resource.split('?')[0],
])
];
if (!contextMissing || contextMissing.invalid) {
resolveItem.invalid = true;
resolveItem.invalidReason = 'resolved context invalid';
}
} else {
const normalMissing =
missingCache[normalId] &&
missingCache[normalId][
JSON.stringify([
resolveKey[1],
resolveItem.resource.split('?')[0],
])
];
if (!normalMissing || normalMissing.invalid) {
resolveItem.invalid = true;
resolveItem.invalidReason = `resolved normal invalid${
normalMissing
? ` ${normalMissing.invalidReason}`
: ': resolve entry not in cache'
}`;
}
resolveItem.loaders.forEach(loader => {
if (typeof loader === 'object') {
if (loader.loader != null) {
loader = loader.loader;
} else {
// Convert { "0": "b", "1": "a", "2": "r" } into "bar"
loader = Object.assign([], loader).join('');
}
}
// Loaders specified in a dependency are searched for from the
// context of the module containing that dependency.
let loaderMissing =
missingCache.loader[
JSON.stringify([resolveKey[1], loader.split('?')[0]])
];
if (!loaderMissing) {
// webpack searches for rule based loaders from the project
// context.
loaderMissing =
missingCache.loader[
JSON.stringify([
// compiler may be a Watching instance, which refers to the
// compiler
(compiler.options || compiler.compiler.options).context,
loader.split('?')[0],
])
];
}
if (!loaderMissing || loaderMissing.invalid) {
resolveItem.invalid = true;
resolveItem.invalidReason = 'resolved loader invalid';
}
});
}
});
}),
);
compilerHooks.compilation.tap(
'HardSource - ModuleResolverCache',
compilation => {
compilation.__hardSourceModuleResolveCache = moduleResolveCache;
compilation.__hardSourceModuleResolveCacheChange = moduleResolveCacheChange;
},
);
compilerHooks._hardSourceWriteCache.tapPromise(
'HardSource - ModuleResolverCache',
(
compilation,
{ relateNormalPath, relateNormalModuleId, relateNormalRequest },
) => {
if (compilation.compiler.parentCompilation) {
const moduleResolveOps = [];
pushParityWriteOps(compilation, moduleResolveOps);
return moduleResolveCacheSerializer.write(moduleResolveOps);
}
const moduleResolveOps = [];
function relateNormalModuleResolveKey(compiler, key) {
const parsed = parseJson(key);
if (Array.isArray(parsed)) {
return JSON.stringify([
parsed[0],
relateNormalPath(compiler, parsed[1]),
relateContext.relateAbsoluteRequest(parsed[1], parsed[2]),
]);
} else {
if (!parsed.request) {
return JSON.stringify(
Object.assign({}, parsed, {
context: relateNormalPath(compiler, parsed.context),
userRequest: relateContext.relateAbsoluteRequest(
parsed.context,
parsed.userRequest,
),
options: Object.assign({}, parsed.options, {
request: relateContext.relateAbsoluteRequest(
parsed.context,
parsed.options.request,
),
}),
}),
);
} else {
return JSON.stringify(
Object.assign({}, parsed, {
context: relateNormalPath(compiler, parsed.context),
request: relateContext.relateAbsoluteRequest(
parsed.context,
parsed.request,
),
}),
);
}
}
}
function relateNormalModuleResolve(compiler, resolved) {
if (resolved.type === 'context') {
return Object.assign({}, resolved, {
identifier: relateNormalModuleId(compiler, resolved.identifier),
resource: relateNormalRequest(compiler, resolved.resource),
});
}
return serialResolveNormal.freeze(resolved, resolved, {
compiler,
});
}
moduleResolveCacheChange
.reduce((carry, value) => {
if (!carry.includes(value)) {
carry.push(value);
}
return carry;
}, [])
.forEach(key => {
// console.log(key, moduleResolveCache[key]);
// moduleResolveCache[key] && console.log(relateNormalModuleResolveKey(compiler, key));
// moduleResolveCache[key] && console.log(relateNormalModuleResolve(compiler, moduleResolveCache[key]));
moduleResolveOps.push({
key: relateNormalModuleResolveKey(compiler, key),
value: moduleResolveCache[key]
? relateNormalModuleResolve(compiler, moduleResolveCache[key])
: null,
});
});
moduleResolveCacheChange = [];
pushParityWriteOps(compilation, moduleResolveOps);
return moduleResolveCacheSerializer.write(moduleResolveOps);
},
);
}
}
module.exports = ModuleResolverCache;
-157
View File
@@ -1,157 +0,0 @@
/**
* A factory wrapper around a webpack compiler plugin to create a serializer
* object that caches a various data hard-source turns into json data without
* circular references.
*
* The wrapper uses a plugin hook on the webpack Compiler called
* `'hard-source-cache-factory'`. It is a waterfall plugin, the returned value
* of one plugin handle is passed to the next as the first argument. This
* plugin is expected to return a factory function that takes one argument. The
* argument passed to the factory function is the info about what kind of cache
* serializer hard-source wants.
*
* The info object contains three fields, `name`, `type`, and `cacheDirPath`.
*
* One example of info might be
*
* ```js
* {
* name: 'asset',
* type: 'file',
* cacheDirPath: '/absolute/path/to/my-project/path/configured/in/hard-source'
* }
* ```
*
* - `name` is the general name of the cache in hard-source.
* - `type` is the type of data contained. The `file` type means it'll be file
* data like large buffers and strings. The `data` type means its generally
* smaller info and serializable with JSON.stringify.
* - `cacheDirPath` is the root of the hard-source disk cache. A serializer
* should add some further element to the path for where it will store its
* info.
*
* So an example plugin handle should take the `factory` argument and return
* its own wrapping factory function. That function will take the `info` data
* and if it wants to returns a serializer. Otherwise its best to call the
* factory passed into the plugin handle.
*
* ```js
* compiler.plugin('hard-source-cache-factory', function(factory) {
* return function(info) {
* if (info.type === 'data') {
* return new MySerializer({
* cacheDirPath: join(info.cacheDirPath, info.name)
* });
* }
* return factory(info);
* };
* });
* ```
*
* @module hard-source-webpack-plugin/cache-serializer-factory
* @author Michael "Z" Goddard <mzgoddard@gmail.com>
*/
/**
* @constructor Serializer
* @memberof module:hard-source-webpack-plugin/cache-serializer-factory
*/
/**
* @method read
* @memberof module:hard-source-webpack-plugin/cache-serializer-factory~Serializer#
* @returns {Promise} promise that resolves the disk cache's contents
* @resolves {Object} a map of keys to current values stored on disk that has
* previously been cached
*/
/**
* @method write
* @memberof module:hard-source-webpack-plugin/cache-serializer-factory~Serializer#
* @param {Array.Object} ops difference of values to be stored in the disk cache
* @param {string} ops.key
* @param ops.value
* @returns {Promise} promise that resolves when writing completes
*/
const FileSerializerPlugin = require('./SerializerFilePlugin');
const Append2SerializerPlugin = require('./SerializerAppend2Plugin');
const pluginCompat = require('./util/plugin-compat');
/**
* @constructor CacheSerializerFactory
* @memberof module:hard-source-webpack-plugin/cache-serializer-factory
*/
class CacheSerializerFactory {
constructor(compiler) {
this.compiler = compiler;
pluginCompat.register(compiler, 'hardSourceCacheFactory', 'syncWaterfall', [
'factory',
]);
pluginCompat.tap(
compiler,
'hardSourceCacheFactory',
'default factory',
factory => info => {
// It's best to have plugins to hard-source listed in the config after it
// but to make hard-source easier to use we can call the factory of a
// plugin passed into this default factory.
if (factory) {
serializer = factory(info);
if (serializer) {
return serializer;
}
}
// Otherwise lets return the default serializers.
switch (info.type) {
case 'data':
return CacheSerializerFactory.dataSerializer.createSerializer(info);
break;
case 'file':
return CacheSerializerFactory.fileSerializer.createSerializer(info);
break;
default:
throw new Error(
`Unknown hard-source cache serializer type: ${info.type}`,
);
break;
}
},
);
}
/**
* @method create
* @memberof module:hard-source-webpack-plugin/cache-serializer-factory~CacheSerializerFactory#
* @param {Object} info
* @param {String} info.name
* @param {String} info.type
* @param {String} info.cacheDirPath
* @returns {Serializer}
*/
create(info) {
const factory = pluginCompat.call(this.compiler, 'hardSourceCacheFactory', [
null,
]);
const serializer = factory(info);
return serializer;
}
}
/**
* The default data serializer factory.
*/
CacheSerializerFactory.dataSerializer = Append2SerializerPlugin;
/**
* The default file serializer factory.
*/
CacheSerializerFactory.fileSerializer = FileSerializerPlugin;
module.exports = CacheSerializerFactory;
-133
View File
@@ -1,133 +0,0 @@
const chalk = require('chalk');
const pluginCompat = require('./util/plugin-compat');
const LOGGER_SEPARATOR = ':';
const DEFAULT_LOGGER_PREFIX = 'hardsource';
const messages = {
'serialization--error-freezing-module': {
short: value =>
`Could not freeze ${value.data.moduleReadable}: ${
value.data.errorMessage
}`,
},
'serialzation--cache-incomplete': {
short: value =>
`Last compilation did not finish saving. Building new cache.`,
},
'confighash--directory-no-confighash': {
short: value => `Config hash skipped in cache directory.`,
},
'confighash--new': {
short: value =>
`Writing new cache ${value.data.configHash.substring(0, 8)}...`,
},
'confighash--reused': {
short: value =>
`Reading from cache ${value.data.configHash.substring(0, 8)}...`,
},
'caches--delete-old': {
short: value =>
`Deleted ${value.data.deletedSizeMB} MB. Using ${
value.data.sizeMB
} MB of disk space.`,
},
'caches--keep': {
short: value => `Using ${value.data.sizeMB} MB of disk space.`,
},
'environment--inputs': {
short: value =>
`Tracking node dependencies with: ${value.data.inputs.join(', ')}.`,
},
'environment--config-changed': {
short: value => 'Configuration changed. Building new cache.',
},
'environment--changed': {
short: value => `Node dependencies changed. Building new cache.`,
},
'environment--hardsource-changed': {
short: value => `hard-source version changed. Building new cache.`,
},
'childcompiler--no-cache': {
once: value =>
`A child compiler has its cache disabled. Skipping child in hard-source.`,
},
'childcompiler--unnamed-cache': {
once: value =>
`A child compiler has unnamed cache. Skipping child in hard-source.`,
},
unrecognized: {
short: value => value.message,
},
};
const logLevels = ['error', 'warn', 'info', 'log', 'debug'];
const levelId = level => logLevels.indexOf(level.toLowerCase());
const compareLevel = (a, b) => levelId(a) - levelId(b);
class ChalkLoggerPlugin {
constructor(options = {}) {
this.options = options;
this.once = {};
// mode: 'test' or 'none'
this.options.mode =
this.options.mode || (process.env.NODE_ENV === 'test' ? 'test' : 'none');
// level: 'error', 'warn', 'info', 'log', 'debug'
this.options.level =
this.options.level || (this.options.mode === 'test' ? 'warn' : 'debug');
}
apply(compiler) {
const compilerHooks = pluginCompat.hooks(compiler);
compilerHooks.hardSourceLog.tap('HardSource - ChalkLoggerPlugin', value => {
if (compareLevel(this.options.level, value.level) < 0) {
return;
}
let headerColor = chalk.white;
let color = chalk.white;
if (value.level === 'error') {
headerColor = chalk.red;
} else if (value.level === 'warn') {
headerColor = chalk.yellow;
} else if (value.level === 'info') {
headerColor = chalk.white;
} else {
headerColor = color = chalk.gray;
}
const header = headerColor(
`[${DEFAULT_LOGGER_PREFIX}${LOGGER_SEPARATOR}${compiler.__hardSource_shortConfigHash ||
value.from}]`,
);
// Always use warn or error so that output goes to stderr.
const consoleFn = value.level === 'error' ? console.error : console.warn;
let handle = messages[value.data.id];
if (!handle) {
handle = messages.unrecognized;
}
if (handle) {
if (handle.once) {
if (!this.once[value.data.id]) {
this.once[value.data.id] = true;
consoleFn.call(console, header, color(handle.once(value)));
}
} else if (handle.short) {
consoleFn.call(console, header, color(handle.short(value)));
}
} else {
consoleFn.call(console, header, color(value.message));
}
});
}
}
module.exports = ChalkLoggerPlugin;
-53
View File
@@ -1,53 +0,0 @@
const pluginCompat = require('./util/plugin-compat');
const matchTest = (test, source) => {
if (Array.isArray(test)) {
return test.some(subtest => matchTest(subtest, source));
} else if (test instanceof RegExp) {
return test.test(source);
} else if (typeof test === 'string') {
return source.startsWith(test);
} else if (typeof test === 'function') {
return test(source);
}
return false;
};
const matchOne = ({ test, include, exclude }, source) => {
return (
(test ? matchTest(test, source) : true) &&
(include ? matchTest(include, source) : true) &&
(exclude ? !matchTest(exclude, source) : true)
);
};
const matchAny = (test, source) => {
if (Array.isArray(test)) {
return test.some(subtest => matchOne(subtest, source));
}
return matchOne(test, source);
};
class ExcludeModulePlugin {
constructor(match) {
this.match = match;
}
apply(compiler) {
const compilerHooks = pluginCompat.hooks(compiler);
compilerHooks.afterPlugins.tap('HardSource - ExcludeModulePlugin', () => {
compilerHooks._hardSourceAfterFreezeModule.tap(
'HardSource - ExcludeModulePlugin',
(frozen, module, extra) => {
if (matchAny(this.match, module.identifier())) {
return null;
}
return frozen;
},
);
});
}
}
module.exports = ExcludeModulePlugin;
-306
View File
@@ -1,306 +0,0 @@
const { fork: cpFork } = require('child_process');
const { cpus } = require('os');
const { resolve } = require('path');
const logMessages = require('./util/log-messages');
const pluginCompat = require('./util/plugin-compat');
const webpackBin = () => {
try {
return require.resolve('webpack-cli');
} catch (e) {}
try {
return require.resolve('webpack-command');
} catch (e) {}
throw new Error('webpack cli tool not installed or discoverable');
};
const configPath = compiler => {
try {
return require.resolve(
resolve(compiler.options.context || process.cwd(), 'webpack.config'),
);
} catch (e) {}
try {
return require.resolve(resolve(process.cwd(), 'webpack.config'));
} catch (e) {}
throw new Error('config not in obvious location');
};
class ParallelModulePlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
try {
require('webpack/lib/JavascriptGenerator');
} catch (e) {
logMessages.parallelRequireWebpack4(compiler);
return;
}
const options = this.options || {};
const fork =
options.fork ||
((fork, compiler, webpackBin) =>
fork(webpackBin(compiler), ['--config', configPath(compiler)], {
silent: true,
}));
const numWorkers = options.numWorkers
? typeof options.numWorkers === 'function'
? options.numWorkers
: () => options.numWorkers
: () => cpus().length;
const minModules =
typeof options.minModules === 'number' ? options.minModules : 10;
const compilerHooks = pluginCompat.hooks(compiler);
let freeze, thaw;
compilerHooks._hardSourceMethods.tap('ParallelModulePlugin', methods => {
freeze = methods.freeze;
thaw = methods.thaw;
});
compilerHooks.thisCompilation.tap(
'ParallelModulePlugin',
(compilation, params) => {
const compilationHooks = pluginCompat.hooks(compilation);
const nmfHooks = pluginCompat.hooks(params.normalModuleFactory);
const doMaster = () => {
const jobs = {};
const readyJobs = {};
const workers = [];
let nextWorkerIndex = 0;
let start = 0;
let started = false;
let configMismatch = false;
let modules = 0;
const startWorkers = () => {
const _numWorkers = numWorkers();
logMessages.parallelStartWorkers(compiler, {
numWorkers: _numWorkers,
});
for (let i = 0; i < _numWorkers; i++) {
const worker = fork(cpFork, compiler, webpackBin);
workers.push(worker);
worker.on('message', _result => {
if (configMismatch) {
return;
}
if (_result.startsWith('ready:')) {
const configHash = _result.split(':')[1];
if (configHash !== compiler.__hardSource_configHash) {
logMessages.parallelConfigMismatch(compiler, {
outHash: compiler.__hardSource_configHash,
theirHash: configHash,
});
configMismatch = true;
killWorkers();
for (const id in jobs) {
jobs[id].cb({ error: true });
delete readyJobs[id];
delete jobs[id];
}
return;
}
}
if (Object.values(readyJobs).length) {
const id = Object.keys(readyJobs)[0];
worker.send(
JSON.stringify({
id,
data: readyJobs[id].data,
}),
);
delete readyJobs[id];
} else {
worker.ready = true;
}
if (_result.startsWith('ready:')) {
start = Date.now();
return;
}
const result = JSON.parse(_result);
jobs[result.id].cb(result);
delete [result.id];
});
}
};
const killWorkers = () => {
Object.values(workers).forEach(worker => worker.kill());
};
const doJob = (module, cb) => {
if (configMismatch) {
cb({ error: new Error('config mismatch') });
return;
}
const id = 'xxxxxxxx-xxxxxxxx'.replace(/x/g, () =>
Math.random()
.toString(16)
.substring(2, 3),
);
jobs[id] = {
id,
data: freeze('Module', null, module, {
id: module.identifier(),
compilation,
}),
cb,
};
const worker = Object.values(workers).find(worker => worker.ready);
if (worker) {
worker.ready = false;
worker.send(
JSON.stringify({
id,
data: jobs[id].data,
}),
);
} else {
readyJobs[id] = jobs[id];
}
if (!started) {
started = true;
startWorkers();
}
};
const _create = params.normalModuleFactory.create;
params.normalModuleFactory.create = (data, cb) => {
_create.call(params.normalModuleFactory, data, (err, module) => {
if (err) {
return cb(err);
}
if (module.constructor.name === 'NormalModule') {
const build = module.build;
module.build = (
options,
compilation,
resolver,
fs,
callback,
) => {
if (modules < minModules) {
build.call(
module,
options,
compilation,
resolver,
fs,
callback,
);
modules += 1;
return;
}
try {
doJob(module, result => {
if (result.error) {
build.call(
module,
options,
compilation,
resolver,
fs,
callback,
);
} else {
thaw('Module', module, result.module, {
compilation,
normalModuleFactory: params.normalModuleFactory,
contextModuleFactory: params.contextModuleFactory,
});
callback();
}
});
} catch (e) {
logMessages.parallelErrorSendingJob(compiler, e);
build.call(
module,
options,
compilation,
resolver,
fs,
callback,
);
}
};
cb(null, module);
} else {
cb(err, module);
}
});
};
compilationHooks.seal.tap('ParallelModulePlugin', () => {
killWorkers();
});
};
const doChild = () => {
const _create = params.normalModuleFactory.create;
params.normalModuleFactory.create = (data, cb) => {};
process.send('ready:' + compiler.__hardSource_configHash);
process.on('message', _job => {
const job = JSON.parse(_job);
const module = thaw('Module', null, job.data, {
compilation,
normalModuleFactory: params.normalModuleFactory,
contextModuleFactory: params.contextModuleFactory,
});
module.build(
compilation.options,
compilation,
compilation.resolverFactory.get('normal', module.resolveOptions),
compilation.inputFileSystem,
error => {
process.send(
JSON.stringify({
id: job.id,
error: error,
module:
module &&
freeze('Module', null, module, {
id: module.identifier(),
compilation,
}),
}),
);
},
);
});
};
if (!process.send) {
doMaster();
} else {
doChild();
}
},
);
}
}
module.exports = ParallelModulePlugin;
-602
View File
@@ -1,602 +0,0 @@
const fs = require('graceful-fs');
const join = require('path').join;
const Readable = require('stream').Readable;
const _mkdirp = require('mkdirp');
const _rimraf = require('rimraf');
const writeJsonFile = require('write-json-file');
const entries = require('./util/Object.entries');
const values = require('./util/Object.values');
const promisify = require('./util/promisify');
const rimraf = promisify(_rimraf);
const open = promisify(fs.open);
const close = promisify(fs.close);
const read = promisify(fs.read);
const readFile = promisify(fs.readFile);
const write = promisify(fs.write);
const rename = promisify(fs.rename);
const unlink = promisify(fs.unlink);
const stat = promisify(fs.stat);
const mkdirp = promisify(_mkdirp);
const APPEND_VERSION = 1;
const _blockSize = 4 * 1024;
const _logSize = 2 * 1024 * 1024;
const _minCompactSize = 512 * 1024;
const _compactMultiplierThreshold = 1.5;
const value = (key, size, start) => ({
key,
size: size || 0,
start: start || 0,
});
const objFrom = map => {
if (map instanceof Map) {
const obj = {};
map.forEach((value, key) => {
obj[key] = value;
});
return obj;
}
return map;
};
const table = ({ nextByte, blockSize, logSize, map }) => ({
version: APPEND_VERSION,
nextByte: nextByte,
blockSize: blockSize,
logSize: logSize,
map: objFrom(map),
});
const modTable = ({ nextByte, blockSize, logSize, map }) => ({
version: APPEND_VERSION,
nextByte: nextByte,
blockSize: blockSize,
logSize: logSize,
map: new Map(entries(map)),
});
function putKey(_table, key, size) {
// _table.map[key] = value(key, size, _table.nextByte, Math.ceil(size / _table.blockSize));
_table.map.set(key, value(key, size, _table.nextByte));
_table.nextByte = _table.nextByte + size;
return _table;
}
function delKey(_table, key) {
// if (_table.map[key]) {
// delete _table.map[key];
if (_table.map.get(key)) {
_table.map.delete(key);
}
return _table;
}
const _tablepath = ({ path }) => join(path, 'table.json');
const _defaultTable = ({ blockSize, logSize }) =>
table({
nextByte: 0,
blockSize: blockSize || _blockSize,
logSize: logSize || _logSize,
map: {},
});
const timeout100 = () => new Promise(resolve => setTimeout(resolve, 100));
const _retry = (fn, n) => {
n = n || 5;
const _retryFn = value => {
if (n) {
n--;
return fn(value).catch(_retryFn);
}
return fn(value);
};
return _retryFn;
};
const _readTable = _this =>
readFile(_tablepath(_this), 'utf8')
.catch(e => JSON.stringify(_defaultTable(_this)))
.then(JSON.parse)
.then(_table => {
if (_table.version !== APPEND_VERSION) {
return _defaultTable(_this);
}
return _table;
});
const _writeTable = (_this, _table) => writeJsonFile(_tablepath(_this), _table);
const _logFilepath = ({ path }, { logSize }, index) => {
let logId = ((index / logSize) | 0).toString();
while (logId.length < 4) {
logId = `0${logId}`;
}
return join(path, `log${logId}`);
};
const _openLog = (_this, mode, _table, index) => {
if (_this._fd !== null) {
return Promise.resolve();
} else {
// If mode is 'a', stat the log to write to, if it should be empty and
// isn't, unlink before opening.
return Promise.resolve()
.then(() => {
if (mode === 'a' && index % _table.logSize === 0) {
return stat(_logFilepath(_this, _table, index))
.then(({ size }) => {
if (size > 0) {
return unlink(_logFilepath(_this, _table, index)).then(
timeout100,
);
}
})
.catch(() => {});
}
})
.then(() => open(_logFilepath(_this, _table, index), mode))
.then(fd => {
_this._fd = fd;
if (mode === 'a') {
_this._writeBuffer = new Buffer(_table.logSize);
_this._writeOffset = 0;
}
})
.catch(e => {
throw e;
});
}
};
const _closeLog = _this => {
if (_this._fd === null) {
return Promise.resolve();
} else {
return Promise.resolve()
.then(() => {
if (_this._writeBuffer) {
return write(_this._fd, _this._writeBuffer, 0, _this._writeOffset);
}
})
.then(() => close(_this._fd))
.then(() => {
_this._fd = null;
_this._writeBuffer = null;
_this._writeOffset = 0;
});
}
};
const _readBufferSize = (_this, { blockSize, logSize }) =>
Math.min(32 * blockSize, logSize);
const _readLog = (_this, _table) => {
let index = 0;
const out = new Readable({
read() {},
});
const rbSize = _table.logSize;
const _readBuffer = new Buffer(rbSize);
function _log() {
if (index >= _table.nextByte) {
out.push(null);
return _closeLog(_this);
}
const offset = 0;
function step() {
if (!_this._fd) {
index = _table.nextByte;
return _log();
}
return read(_this._fd, _readBuffer, 0, rbSize, 0).then(read => {
index += _table.logSize;
out.push(_readBuffer);
return _log();
});
}
return _closeLog(_this)
.then(() => _openLog(_this, 'r', _table, index))
.then(step);
}
Promise.resolve().then(_log);
return out;
};
const _appendBlock = (_this, _table, blockContent, index, next) => {
let prep;
if (_this._fd !== null && index % _table.logSize === 0) {
prep = _closeLog(_this).then(() => _openLog(_this, 'a', _table, index));
} else if (_this._fd === null) {
prep = _openLog(_this, 'a', _table, index);
}
function work() {
if (!_this._fd) {
return next(new Error());
}
if (blockContent.length > _table.logSize) {
return next(new Error('block longer than max size'));
}
const writeSlice = _this._writeBuffer.slice(
_this._writeOffset,
_this._writeOffset + blockContent.length,
);
// if (blockContent.length < _table.blockSize) {
// writeSlice.fill(0);
// }
blockContent.copy(writeSlice);
_this._writeOffset += blockContent.length;
if (_this._writeOffset > _this._writeBuffer.length) {
return next(
new Error(
`writeOffset ${_this._writeOffset} past writeBuffer length ${
_this._writeBuffer.length
}`,
),
);
}
if (_this._writeOffset > _table.logSize) {
return next(
new Error(
`writeOffset ${_this._writeOffset} past logSize ${_table.logSize}`,
),
);
}
next();
// return fs.write(_this._fd, blockContent, 0, _table.blockSize, next);
}
if (prep) {
prep.then(work);
} else {
work();
}
// return Promise.resolve()
// .then(function() {
// if (index % (_table.logSize / _table.blockSize) === 0) {
// return _closeLog(_this);
// }
// })
// .then(function() {
// return _openLog(_this, 'a', _table, index);
// })
// .then(function() {
// if (!_this._fd) {
// throw new Error();
// }
// if (blockContent.length > _table.blockSize) {
// throw new Error('block longer than max size');
// }
// if (blockContent.length < _table.blockSize) {
// var _blockContent = new Buffer(_table.blockSize);
// blockContent.copy(_blockContent);
// blockContent = _blockContent;
// }
// return write(_this._fd, blockContent, 0, _table.blockSize);
// });
};
const _sizeNeeded = (_this, { map }) =>
values(map).reduce((carry, { size }) => carry + size, 0);
const _sizeUsed = (_this, { nextByte }) => nextByte;
const _compactSize = (_this, _table) =>
Math.max(
_this.compactSizeThreshold,
_sizeNeeded(_this, _table) * _this.compactMultiplierThreshold,
);
const _lock = (_this, mustLock, promiseFn) => {
if (mustLock !== false) {
return (_this.lock = promiseFn(_this.lock));
}
return promiseFn(Promise.resolve());
};
const serialFsTask = (array, each) =>
new Promise((resolve, reject) => {
let queue = 0;
let index = 0;
let inNext = false;
function next(err) {
if (err) {
return reject(err);
}
if (index === array.length) {
return resolve();
}
queue++;
if (inNext) {
return;
}
inNext = true;
while (queue > index && index < array.length) {
try {
each(array[index++], next);
} catch (e) {
return next(e);
}
}
inNext = false;
}
next();
});
class AppendSerializer {
constructor(options) {
this.path = options.cacheDirPath;
this.autoParse = options.autoParse;
this.blockSize = options.blockSize || _blockSize;
this.logSize = options.logSize || _logSize;
this.compactSizeThreshold = options.compactSizeThreshold || _minCompactSize;
this.compactMultiplierThreshold =
options.compactMultiplierThreshold || _compactMultiplierThreshold;
this.lock = Promise.resolve();
this._fd = null;
}
read(mustLock) {
const start = Date.now();
const _this = this;
function _read() {
let activeTable;
return Promise.resolve()
.then(_retry(() => _readTable(_this)))
.then(_table => {
activeTable = _table;
})
.then(() => {
const map = new Map();
const valueStarts = [];
values(activeTable.map).forEach(value => {
valueStarts.push({
start: value.start,
end: value.start + value.size,
value,
});
});
valueStarts.sort((a, b) => a.start - b.start);
return new Promise((resolve, reject) => {
let valueIndex = 0;
let destBuffer = new Buffer(2 * 1024 * 1024);
let offset = 0;
let logOffset = 0;
const log = _readLog(_this, activeTable);
log.on('data', data => {
if (valueIndex >= valueStarts.length) {
return;
}
for (let bufferIndex = 0; bufferIndex < data.length; ) {
if (bufferIndex + logOffset >= valueStarts[valueIndex].end) {
valueIndex++;
}
if (valueIndex >= valueStarts.length) {
return;
}
const value = valueStarts[valueIndex].value;
if (bufferIndex + logOffset >= value.start) {
if (value.size > destBuffer.length) {
const newLength = Math.pow(
2,
Math.ceil(Math.log(value.size) / Math.log(2)),
);
destBuffer = new Buffer(newLength);
}
const readAmount = Math.min(
value.start + value.size - logOffset - bufferIndex,
activeTable.logSize - bufferIndex,
);
data
.slice(bufferIndex, bufferIndex + readAmount)
.copy(destBuffer.slice(offset, offset + readAmount));
bufferIndex += readAmount;
offset += readAmount;
if (offset >= value.size) {
offset = 0;
if (_this.autoParse) {
// console.log(value.size, destBuffer.utf8Slice(0, value.size))
map.set(
value.key,
JSON.parse(destBuffer.utf8Slice(0, value.size)),
);
} else {
map.set(value.key, destBuffer.utf8Slice(0, value.size));
}
}
} else if (bufferIndex + logOffset < value.start) {
bufferIndex += value.start - (bufferIndex + logOffset);
}
}
logOffset += activeTable.logSize;
});
log.on('end', resolve);
log.on('error', reject);
}).then(() => objFrom(map));
});
}
return _lock(_this, mustLock, promise =>
promise
.then(() => _read())
.catch(e =>
_closeLog(_this).then(() => {
throw e;
}),
),
);
}
write(ops, mustLock) {
if (ops.length === 0) {
return Promise.resolve();
}
const steps = 0;
const _this = this;
let activeTable;
let contentBuffer;
let contentLength;
function _write() {
return Promise.resolve()
.then(_retry(() => mkdirp(_this.path)))
.then(_retry(() => _readTable(_this)))
.then(_table => {
activeTable = modTable(_table);
const _ops = ops.slice();
function step(op, next) {
// steps++;
// var op = _ops.shift();
// if (!op) {
// return;
// }
let content = op.value;
if (content !== null) {
if (typeof content !== 'string') {
content = JSON.stringify(content);
}
if (
Buffer.byteLength &&
contentBuffer &&
Buffer.byteLength(content) <= contentBuffer.length
) {
contentLength = contentBuffer.utf8Write(content);
} else {
contentBuffer = new Buffer(content);
contentLength = contentBuffer.length;
}
const blockCount = Math.ceil(
((activeTable.nextByte % activeTable.logSize) + contentLength) /
activeTable.logSize,
);
let nextByte = activeTable.nextByte;
activeTable = putKey(activeTable, op.key, contentLength);
let bufferIndex = 0;
const bulk = Array.from(new Array(blockCount)).map((_, i) => i);
return serialFsTask(bulk, (_, next) => {
const blockSlice = contentBuffer.slice(
bufferIndex,
Math.min(
bufferIndex +
(activeTable.logSize - (nextByte % activeTable.logSize)),
contentLength,
),
);
_appendBlock(_this, activeTable, blockSlice, nextByte, next);
bufferIndex += blockSlice.length;
nextByte += blockSlice.length;
}).then(next);
// function append() {
// if (bufferIndex < contentBuffer.length) {
// var blockSlice = contentBuffer.slice(bufferIndex, bufferIndex + activeTable.blockSize);
// bufferIndex += activeTable.blockSize;
// return _appendBlock(_this, activeTable, blockSlice, nextByte++)
// .then(append);
// }
// }
// return append()
// .then(step);
} else {
activeTable = delKey(activeTable, op.key);
next();
}
}
return serialFsTask(_ops, step);
// return step();
})
.then(() => _closeLog(_this))
.then(
_retry(() => {
activeTable = table(activeTable);
return _writeTable(_this, activeTable);
}),
);
}
return _lock(_this, mustLock, promise =>
promise
.then(() => _write())
.catch(e =>
_closeLog(_this).then(() => {
throw e;
}),
)
.then(() => {
if (
_sizeUsed(_this, activeTable) > _compactSize(_this, activeTable)
) {
return _this.compact(false);
}
}),
);
}
compact(mustLock) {
const _this = this;
return _this
.read(mustLock)
.then(map => {
const ops = [];
Object.keys(map).forEach(key => {
ops.push({
key,
value: map[key],
});
});
return ops;
})
.then(ops =>
rimraf(`${_this.path}~`)
.then(timeout100)
.then(() => ops),
)
.then(ops => {
const copy = new AppendSerializer({
cacheDirPath: `${_this.path}~`,
blockSize: _this.blockSize,
logSize: _this.logSize,
compactSizeThreshold: _this.compactSizeThreshold,
compactMultiplierThreshold: _this.compactMultiplierThreshold,
});
return _lock(_this, mustLock, promise =>
promise
.then(() => copy.write(ops))
.then(() => rimraf(_this.path))
.then(timeout100)
.then(_retry(() => rename(copy.path, _this.path), 10)),
);
});
}
}
module.exports = AppendSerializer;
-425
View File
@@ -1,425 +0,0 @@
const fs = require('graceful-fs');
const { join, resolve } = require('path');
const _mkdirp = require('mkdirp');
const parseJson = require('parse-json');
const _rimraf = require('rimraf');
const promisify = require('./util/promisify');
const close = promisify(fs.close);
const mkdirp = promisify(_mkdirp);
const open = promisify(fs.open);
const read = promisify(fs.readFile);
const readdir = promisify(fs.readdir);
const readfd = promisify(fs.read);
const rename = promisify(fs.rename);
const rimraf = promisify(_rimraf);
const write = promisify(fs.writeFile);
const nextPow2 = n => {
const exponent = Math.log(n) / Math.log(2);
const nextExponent = Math.floor(exponent) + 1;
return Math.pow(2, nextExponent);
};
const resizePow2 = (buffer, n) => {
const tmpBuffer = Buffer.allocUnsafe(nextPow2(n));
buffer.copy(tmpBuffer.slice(0, buffer.length));
return tmpBuffer;
};
const MAX_CHUNK = 2 * 1024 * 1024;
const TMP_CHUNK = 0.5 * 1024 * 1024;
const MAX_CHUNK_PLUS = 2.5 * 1024 * 1024;
const LARGE_CONTENT = 64 * 1024;
let tmpBuffer = Buffer.allocUnsafe(TMP_CHUNK);
let outBuffer = Buffer.allocUnsafe(MAX_CHUNK_PLUS);
const _buffers = [];
const alloc = size => {
const buffer = _buffers.pop();
if (buffer && buffer.length >= size) {
return buffer;
}
return Buffer.allocUnsafe(size);
};
const drop = buffer => _buffers.push(buffer);
class WriteOutput {
constructor(length = 0, table = [], buffer = alloc(MAX_CHUNK_PLUS)) {
this.length = length;
this.table = table;
this.buffer = buffer;
}
static clone(other) {
return new WriteOutput(other.length, other.table, other.buffer);
}
take() {
const output = WriteOutput.clone(this);
this.length = 0;
this.table = [];
this.buffer = alloc(MAX_CHUNK_PLUS);
return output;
}
add(key, content) {
if (content !== null) {
// Write content to a temporary buffer
let length = tmpBuffer.utf8Write(content);
while (length === tmpBuffer.length) {
tmpBuffer = Buffer.allocUnsafe(tmpBuffer.length * 2);
length = tmpBuffer.utf8Write(content);
}
const start = this.length;
const end = start + length;
// Ensure output buffer is long enough to add the new content
if (end > this.buffer.length) {
this.buffer = resizePow2(this.buffer, end);
}
// Copy temporary buffer to the end of the current output buffer
tmpBuffer.copy(this.buffer.slice(start, end));
this.table.push({
name: key,
start,
end,
});
this.length = end;
} else {
this.table.push({
name: key,
start: -1,
end: -1,
});
}
}
}
class Semaphore {
constructor(max) {
this.max = max;
this.count = 0;
this.next = [];
}
async guard() {
if (this.count < this.max) {
this.count++;
return new SemaphoreGuard(this);
} else {
return new Promise(resolve => {
this.next.push(resolve);
}).then(() => new SemaphoreGuard(this));
}
}
}
class SemaphoreGuard {
constructor(parent) {
this.parent = parent;
}
done() {
const next = this.parent.next.shift();
if (next) {
next();
} else {
this.parent.count--;
}
}
}
class Append2 {
constructor({ cacheDirPath: path, autoParse }) {
this.path = path;
this.autoParse = autoParse;
this.inBuffer = Buffer.alloc(0);
this._buffers = [];
this.outBuffer = Buffer.alloc(0);
}
async _readFile(file) {
const fd = await open(file, 'r+');
let body = alloc(MAX_CHUNK_PLUS);
await readfd(fd, body, 0, 4, null);
const fullLength = body.readUInt32LE(0);
if (fullLength > body.length) {
drop(body);
body = alloc(nextPow2(fullLength));
}
await readfd(fd, body, 0, fullLength, null);
close(fd);
const tableLength = body.readUInt32LE(0);
const tableBody = body.utf8Slice(4, 4 + tableLength);
const table = parseJson(tableBody);
const content = body.slice(4 + tableLength);
return [table, content, body];
}
async read() {
const out = {};
const size = { used: 0, total: 0 };
const table = {};
const order = {};
await mkdirp(this.path);
const items = await readdir(this.path);
const logs = items.filter(item => /^log\d+$/.test(item));
logs.sort();
const reverseLogs = logs.reverse();
const sema = new Semaphore(8);
return Promise.all(
reverseLogs.map(async (_file, index) => {
const file = join(this.path, _file);
const guard = await sema.guard();
const [table, content, body] = await this._readFile(file);
const keys = Object.keys(table);
if (keys.length > 0) {
size.total += table[keys.length - 1].end;
}
for (const entry of table) {
if (
typeof order[entry.name] === 'undefined' ||
order[entry.name] > index
) {
if (typeof order[entry.name] !== 'undefined') {
size.used -= table[entry.name];
}
table[entry.name] = entry.end - entry.start;
size.used += entry.end - entry.start;
order[entry.name] = index;
// Negative start positions are not set on the output. They are
// treated as if they were deleted in a prior write. A future
// compact will remove all instances of any old entries.
if (entry.start >= 0) {
await new Promise(process.nextTick);
const data = content.utf8Slice(entry.start, entry.end);
if (this.autoParse) {
out[entry.name] = parseJson(data);
} else {
out[entry.name] = data;
}
} else {
delete out[entry.name];
}
}
}
drop(body);
guard.done();
}),
)
.then(async () => {
if (size.used / size.total < 0.6) {
await this.compact(out);
}
})
.then(() => out);
}
async _markLog() {
const count = (await readdir(this.path)).filter(item =>
/log\d+$/.test(item),
).length;
const marker = Math.random()
.toString(16)
.substring(2)
.padStart(13, '0');
const logName = `log${count.toString().padStart(4, '0')}`;
const file = resolve(this.path, logName);
await write(file, marker);
const writtenMarker = await read(file, 'utf8');
if (marker === writtenMarker) {
return file;
}
return null;
}
async _write(file, output) {
// 4 bytes - full length
// 4 bytes - length of table
// x bytes - table
// y bytes - content
// Write table into a temporary buffer at position 8
const content = JSON.stringify(output.table);
let length = tmpBuffer.utf8Write(content, 8);
// Make the temporary buffer longer if the space used is the same as the
// length
while (8 + length === tmpBuffer.length) {
tmpBuffer = Buffer.allocUnsafe(nextPow2(8 + length));
// Write again to see if the length is more due to the last buffer being
// too short.
length = tmpBuffer.utf8Write(content, 8);
}
// Ensure the buffer is long enough to fit the table and content.
const end = 8 + length + output.length;
if (end > tmpBuffer.length) {
tmpBuffer = resizePow2(tmpBuffer, end);
}
// Copy the output after the table.
output.buffer.copy(tmpBuffer.slice(8 + length, end));
// Full length after this uint.
tmpBuffer.writeUInt32LE(end - 4, 0);
// Length of table after this uint.
tmpBuffer.writeUInt32LE(length, 4);
if (end > output.buffer.length) {
output.buffer = alloc(nextPow2(end));
}
tmpBuffer.copy(output.buffer.slice(0, end));
await write(file, output.buffer.slice(0, end));
drop(output.buffer);
}
async _markAndWrite(output) {
const file = await this._markLog();
if (file !== null) {
await this._write(file, output.take());
}
}
// Write out a log chunk once the file reaches the maximum chunk size.
async _writeAtMax(output) {
while (output.length >= MAX_CHUNK) {
await this._markAndWrite(output);
}
}
// Write out a log chunk if their is any entries in the table.
async _writeAtAny(output) {
while (output.table.length > 0) {
await this._markAndWrite(output);
}
}
async write(ops) {
let smallOutput = new WriteOutput();
let largeOutput = new WriteOutput();
const outputPromises = [];
await mkdirp(this.path);
for (const op of ops) {
if (op.value !== null) {
let content = op.value;
if (typeof content !== 'string') {
content = JSON.stringify(content);
}
if (content.length < LARGE_CONTENT) {
smallOutput.add(op.key, content);
await this._writeAtMax(smallOutput);
} else {
largeOutput.add(op.key, content);
await this._writeAtMax(largeOutput);
}
} else {
smallOutput.add(op.key, null);
await this._writeAtMax(smallOutput);
}
}
await this._writeAtAny(smallOutput);
await this._writeAtAny(largeOutput);
await Promise.all(outputPromises);
}
async sizes() {
const size = {
used: 0,
total: 0,
};
const table = {};
const order = {};
await mkdirp(this.path);
const items = await readdir(this.path);
const logs = items.filter(item => /^log\d+$/.test(item));
logs.sort();
const reverseLogs = logs.reverse();
const sema = new Semaphore(8);
return Promise.all(
reverseLogs.map(async (_file, index) => {
const file = join(this.path, _file);
const guard = await sema.guard();
const [table, content, body] = await this._readFile(file);
size.total += content.length;
for (const entry of table) {
if (
typeof order[entry.name] === 'undefined' ||
order[entry.name] > index
) {
if (typeof order[entry.name] !== 'undefined') {
size.used -= table[entry.name];
}
table[entry.name] = entry.end - entry.start;
size.used += entry.end - entry.start;
order[entry.name] = index;
}
}
drop(body);
guard.done();
}),
).then(() => size);
}
async compact(_obj = this.read()) {
const obj = await _obj;
const ops = [];
for (const key in obj) {
ops.push({
key,
value: obj[key],
});
}
const truePath = this.path;
this.path += '~';
await this.write(ops);
this.path = truePath;
await rimraf(this.path);
await rename(`${this.path}~`, this.path);
}
}
module.exports = Append2;
-48
View File
@@ -1,48 +0,0 @@
const join = require('path').join;
const pluginCompat = require('./util/plugin-compat');
let Append2Serializer;
const _blockSizeByName = {
data: 4 * 1024,
md5: 128,
'missing-resolve': 256,
module: 4 * 1024,
'module-resolve': 1024,
resolver: 256,
};
class SerializerAppend2Plugin {
apply(compiler) {
pluginCompat.tap(
compiler,
'hardSourceCacheFactory',
'Append2Serializer',
factory => info => {
if (info.type === 'data') {
return SerializerAppend2Plugin.createSerializer(info);
}
return factory(info);
},
);
}
}
SerializerAppend2Plugin.createSerializer = ({
cacheDirPath,
name,
autoParse,
}) => {
if (!Append2Serializer) {
Append2Serializer = require('./SerializerAppend2');
}
return new Append2Serializer({
cacheDirPath: join(cacheDirPath, name),
blockSize: _blockSizeByName[name],
autoParse: autoParse,
});
};
module.exports = SerializerAppend2Plugin;
-48
View File
@@ -1,48 +0,0 @@
const join = require('path').join;
const pluginCompat = require('./util/plugin-compat');
let AppendSerializer;
const _blockSizeByName = {
data: 4 * 1024,
md5: 128,
'missing-resolve': 256,
module: 4 * 1024,
'module-resolve': 1024,
resolver: 256,
};
class SerializerAppendPlugin {
apply(compiler) {
pluginCompat.tap(
compiler,
'hardSourceCacheFactory',
'AppendSerializer',
factory => info => {
if (info.type === 'data') {
return SerializerAppendPlugin.createSerializer(info);
}
return factory(info);
},
);
}
}
SerializerAppendPlugin.createSerializer = ({
cacheDirPath,
name,
autoParse,
}) => {
if (!AppendSerializer) {
AppendSerializer = require('./SerializerAppend');
}
return new AppendSerializer({
cacheDirPath: join(cacheDirPath, name),
blockSize: _blockSizeByName[name],
autoParse: autoParse,
});
};
module.exports = SerializerAppendPlugin;
-43
View File
@@ -1,43 +0,0 @@
const cacache = require('cacache');
class CacacheSerializer {
constructor({ cacheDirPath }) {
this.path = cacheDirPath;
}
read() {
const cache = {};
const promises = [];
return new Promise((resolve, reject) => {
cacache.ls
.stream(this.path)
.on('data', ({ key }) => {
promises.push(
cacache.get(this.path, key).then(({ data }) => {
cache[key] = JSON.parse(data);
}),
);
})
.on('error', reject)
.on('end', () => {
resolve();
});
})
.then(() => Promise.all(promises))
.then(() => cache);
}
write(ops) {
return Promise.all(
ops.map(op => {
if (op.value) {
return cacache.put(this.path, op.key, JSON.stringify(op.value));
} else {
return cacache.rm.entry(this.path, op.key);
}
}),
);
}
}
module.exports = CacacheSerializer;
-33
View File
@@ -1,33 +0,0 @@
const join = require('path').join;
const pluginCompat = require('./util/plugin-compat');
let CacacheSerializer;
class SerializerCacachePlugin {
apply(compiler) {
pluginCompat.tap(
compiler,
'hardSourceCacheFactory',
'CacacheSerializer',
factory => info => {
if (info.type === 'data') {
return SerializerCacachePlugin.createSerializer(info);
}
return factory(info);
},
);
}
}
SerializerCacachePlugin.createSerializer = ({ cacheDirPath, name }) => {
if (!CacacheSerializer) {
CacacheSerializer = require('./SerializerCacache');
}
return new CacacheSerializer({
cacheDirPath: join(cacheDirPath, name),
});
};
module.exports = SerializerCacachePlugin;
-50
View File
@@ -1,50 +0,0 @@
const fs = require('graceful-fs');
const join = require('path').join;
const _mkdirp = require('mkdirp');
const promisify = require('./util/promisify');
const mkdirp = promisify(_mkdirp);
const fsReadFile = promisify(fs.readFile, { context: fs });
const fsReaddir = promisify(fs.readdir, { context: fs });
const fsWriteFile = promisify(fs.writeFile, { context: fs });
class FileSerializer {
constructor({ cacheDirPath }) {
this.path = cacheDirPath;
}
read() {
const assets = {};
const cacheAssetDirPath = this.path;
return mkdirp(cacheAssetDirPath)
.then(() => fsReaddir(cacheAssetDirPath))
.then(dir =>
dir.map(name =>
Promise.all([name, fsReadFile(join(cacheAssetDirPath, name))]),
),
)
.then(a => Promise.all(a))
.then(_assets => {
for (let i = 0; i < _assets.length; i++) {
assets[_assets[i][0]] = _assets[i][1];
}
})
.then(() => assets);
}
write(assetOps) {
const cacheAssetDirPath = this.path;
return mkdirp(cacheAssetDirPath)
.then(() =>
assetOps.map(({ key, value }) => {
const assetPath = join(cacheAssetDirPath, key);
return fsWriteFile(assetPath, value);
}),
)
.then(a => Promise.all(a));
}
}
module.exports = FileSerializer;
-33
View File
@@ -1,33 +0,0 @@
const join = require('path').join;
const pluginCompat = require('./util/plugin-compat');
let FileSerializer;
class SerializerFilePlugin {
apply(compiler) {
pluginCompat.tap(
compiler,
'hardSourceCacheFactory',
'FileSerializer',
factory => info => {
if (info.type === 'file') {
return SerializerFilePlugin.createSerializer(info);
}
return factory(info);
},
);
}
}
SerializerFilePlugin.createSerializer = ({ cacheDirPath, name }) => {
if (!FileSerializer) {
FileSerializer = require('./SerializerFile');
}
return new FileSerializer({
cacheDirPath: join(cacheDirPath, name),
});
};
module.exports = SerializerFilePlugin;
-38
View File
@@ -1,38 +0,0 @@
const fs = require('graceful-fs');
const promisify = require('./util/promisify');
const fsReadFile = promisify(fs.readFile, { context: fs });
const fsWriteFile = promisify(fs.writeFile, { context: fs });
class JsonSerializer {
constructor({ cacheDirPath }) {
this.path = cacheDirPath;
if (!/\.json$/.test(this.path)) {
this.path += '.json';
}
}
read() {
const cacheDirPath = this.path;
return fsReadFile(cacheDirPath, 'utf8')
.catch(() => '{}')
.then(JSON.parse);
}
write(moduleOps) {
const cacheDirPath = this.path;
return this.read()
.then(cache => {
for (let i = 0; i < moduleOps.length; i++) {
const op = moduleOps[i];
cache[op.key] = op.value;
}
return cache;
})
.then(JSON.stringify)
.then(cache => fsWriteFile(cacheDirPath, cache));
}
}
module.exports = JsonSerializer;
-33
View File
@@ -1,33 +0,0 @@
const join = require('path').join;
const pluginCompat = require('./util/plugin-compat');
let JsonSerializer;
class SerializerJsonPlugin {
apply(compiler) {
pluginCompat.tap(
compiler,
'hardSourceCacheFactory',
'JsonSerializer',
factory => info => {
if (info.type === 'data') {
return SerializerJsonPlugin.createSerializer(info);
}
return factory(info);
},
);
}
}
SerializerJsonPlugin.createSerializer = ({ cacheDirPath, name }) => {
if (!JsonSerializer) {
JsonSerializer = require('./SerializerJson');
}
return new JsonSerializer({
cacheDirPath: join(cacheDirPath, name),
});
};
module.exports = SerializerJsonPlugin;
-63
View File
@@ -1,63 +0,0 @@
const _level = require('level');
const promisify = require('./util/promisify');
const level = promisify(_level);
class LevelDbSerializer {
constructor({ cacheDirPath }) {
this.path = cacheDirPath;
this.leveldbLock = Promise.resolve();
}
read() {
const start = Date.now();
const moduleCache = {};
return level(this.path)
.then(
db =>
new Promise((resolve, reject) => {
const dbClose = promisify(db.close, { context: db });
db.createReadStream()
.on('data', data => {
const value = data.value;
if (!moduleCache[data.key]) {
moduleCache[data.key] = value;
}
})
.on('end', () => {
dbClose().then(resolve, reject);
});
}),
)
.then(() => moduleCache);
}
write(moduleOps) {
const ops = moduleOps;
if (ops.length === 0) {
return Promise.resolve();
}
for (let i = 0; i < ops.length; i++) {
if (ops[i].value === null) {
ops[i].type = 'delete';
} else {
if (typeof ops[i].value !== 'string') {
ops[i].value = JSON.stringify(ops[i].value);
}
ops[i].type = 'put';
}
}
const cachePath = this.path;
return (this.leveldbLock = this.leveldbLock
.then(() => level(cachePath))
.then(db => promisify(db.batch, { context: db })(ops).then(() => db))
.then(db => promisify(db.close, { context: db })()));
}
}
module.exports = LevelDbSerializer;
-44
View File
@@ -1,44 +0,0 @@
const join = require('path').join;
const pluginCompat = require('./util/plugin-compat');
let LevelDbSerializer;
let AppendSerializerPlugin;
class HardSourceLevelDbSerializerPlugin {
apply(compiler) {
pluginCompat.tap(
compiler,
'hardSourceCacheFactory',
'LevelDbSerializer',
factory => info => {
if (info.type === 'data') {
return HardSourceLevelDbSerializerPlugin.createSerializer(info);
}
return factory(info);
},
);
}
}
HardSourceLevelDbSerializerPlugin.createSerializer = info => {
if (!LevelDbSerializer) {
try {
LevelDbSerializer = require('./SerializerLeveldb');
} catch (e) {}
}
if (LevelDbSerializer) {
return new LevelDbSerializer({
cacheDirPath: join(info.cacheDirPath, info.name),
});
} else {
if (!AppendSerializerPlugin) {
AppendSerializerPlugin = require('./SerializerAppendPlugin');
}
return AppendSerializerPlugin.createSerializer(info);
}
};
module.exports = HardSourceLevelDbSerializerPlugin;
@@ -1,34 +0,0 @@
const path = require('path');
let extractTextNS;
let extractTextNS2;
try {
extractTextNS = path.dirname(require.resolve('extract-text-webpack-plugin'));
} catch (_) {}
const pluginCompat = require('./util/plugin-compat');
class SupportExtractTextPlugin {
apply(compiler) {
pluginCompat.tap(
compiler,
'_hardSourceAfterFreezeModule',
'SupportExtractTextPlugin',
(frozen, module, extra) => {
// Ignore the modules that kick off child compilers in extract text.
// These modules must always be built so the child compilers run so
// that assets get built.
if (
module[extractTextNS] ||
(!module.factoryMeta && module.meta && module.meta[extractTextNS])
) {
return null;
}
return frozen;
},
);
}
}
module.exports = SupportExtractTextPlugin;
@@ -1,67 +0,0 @@
const pluginCompat = require('./util/plugin-compat');
const mixinCssDependency = function(CssDependency) {
const Dependency = Object.getPrototypeOf(CssDependency.prototype).constructor;
CssDependency.prototype.updateHash = function(hash) {
Dependency.prototype.updateHash.call(this, hash);
hash.update(this.content);
};
};
class SupportMiniCssExtractPlugin {
apply(compiler) {
let CssDependency;
pluginCompat.tap(
compiler,
'make',
'SupportMiniCssExtractPlugin',
({ dependencyFactories }) => {
const Dependencies = dependencyFactories.keys();
for (const Dep of Dependencies) {
if (Dep.name === 'CssDependency') {
CssDependency = Dep;
mixinCssDependency(CssDependency);
break;
}
}
},
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeDependency',
'HardMiniCssExtractPlugin freeze',
(frozen, dependency, extra) => {
if (dependency.constructor === CssDependency) {
return {
type: 'CssDependency',
line: {
identifier: dependency.identifier,
content: dependency.content,
media: dependency.media,
sourceMap: dependency.sourceMap,
},
context: dependency.context,
identifierIndex: dependency.identifierIndex,
};
}
return frozen;
},
);
pluginCompat.tap(
compiler,
'_hardSourceThawDependency',
'HardMiniCssExtractPlugin',
(dependency, { type, line, context, identifierIndex }, extra) => {
if (type === 'CssDependency') {
return new CssDependency(line, context, identifierIndex);
}
return dependency;
},
);
}
}
module.exports = SupportMiniCssExtractPlugin;
-206
View File
@@ -1,206 +0,0 @@
const pluginCompat = require('./util/plugin-compat');
class ArchetypeSystem {
apply(compiler) {
const compilerHooks = pluginCompat.hooks(compiler);
const archetypeCaches = {
// asset: assetArchetypeCache,
// Asset: assetArchetypeCache,
// module: moduleArchetypeCache,
// Module: moduleArchetypeCache,
};
pluginCompat.register(compiler, '_hardSourceArchetypeRegister', 'sync', [
'name',
'archetypeCache',
]);
compilerHooks._hardSourceArchetypeRegister.tap(
'HardSource - ArchetypeSystem',
(name, cache) => {
archetypeCaches[name] = cache;
archetypeCaches[name.toLowerCase()] = cache;
},
);
let freeze;
let thaw;
let mapMap;
let mapFreeze;
let mapThaw;
let store;
let fetch;
pluginCompat.register(compiler, '_hardSourceMethods', 'sync', ['methods']);
[
'Asset',
'Compilation',
'Dependency',
'DependencyBlock',
'DependencyVariable',
'Module',
'ModuleAssets',
'ModuleError',
'ModuleWarning',
'Source',
].forEach(archetype => {
pluginCompat.register(
compiler,
`_hardSourceBeforeFreeze${archetype}`,
'syncWaterfall',
['frozen', 'item', 'extra'],
);
pluginCompat.register(
compiler,
`_hardSourceFreeze${archetype}`,
'syncWaterfall',
['frozen', 'item', 'extra'],
);
pluginCompat.register(
compiler,
`_hardSourceAfterFreeze${archetype}`,
'syncWaterfall',
['frozen', 'item', 'extra'],
);
pluginCompat.register(
compiler,
`_hardSourceBeforeThaw${archetype}`,
'syncWaterfall',
['item', 'frozen', 'extra'],
);
pluginCompat.register(
compiler,
`_hardSourceThaw${archetype}`,
'syncWaterfall',
['item', 'frozen', 'extra'],
);
pluginCompat.register(
compiler,
`_hardSourceAfterThaw${archetype}`,
'syncWaterfall',
['item', 'frozen', 'extra'],
);
});
function run(_compiler) {
let compiler = _compiler;
if (_compiler.compiler) {
compiler = _compiler.compiler;
}
freeze = (archetype, frozen, item, extra) => {
if (!item) {
return item;
}
frozen = pluginCompat.call(
compiler,
`_hardSourceBeforeFreeze${archetype}`,
[frozen, item, extra],
);
frozen = pluginCompat.call(compiler, `_hardSourceFreeze${archetype}`, [
frozen,
item,
extra,
]);
frozen = pluginCompat.call(
compiler,
`_hardSourceAfterFreeze${archetype}`,
[frozen, item, extra],
);
return frozen;
};
thaw = (archetype, item, frozen, extra) => {
if (!frozen) {
return frozen;
}
item = pluginCompat.call(
compiler,
`_hardSourceBeforeThaw${archetype}`,
[item, frozen, extra],
);
item = pluginCompat.call(compiler, `_hardSourceThaw${archetype}`, [
item,
frozen,
extra,
]);
item = pluginCompat.call(compiler, `_hardSourceAfterThaw${archetype}`, [
item,
frozen,
extra,
]);
return item;
};
mapMap = (fn, name, output, input, extra) => {
if (output) {
return input
.map((item, index) => fn(name, output[index], item, extra))
.filter(Boolean);
} else {
return input.map(item => fn(name, null, item, extra)).filter(Boolean);
}
};
mapFreeze = (name, frozen, items, extra) =>
mapMap(freeze, name, frozen, items, extra);
mapThaw = (name, items, frozen, extra) =>
mapMap(thaw, name, items, frozen, extra);
store = (archetype, id, item, extra) => {
const cache = archetypeCaches[archetype];
if (item) {
const frozen = cache.get(id);
const newFrozen = freeze(archetype, frozen, item, extra);
if (
(frozen && newFrozen && newFrozen !== frozen) ||
(!frozen && newFrozen)
) {
cache.set(id, newFrozen);
return newFrozen;
} else if (frozen) {
return frozen;
}
} else {
cache.set(id, null);
}
};
fetch = (archetype, id, extra) => {
const cache = archetypeCaches[archetype];
const frozen = cache.get(id);
return thaw(archetype, null, frozen, extra);
};
const methods = {
freeze,
thaw,
mapFreeze,
mapThaw,
store,
fetch,
};
pluginCompat.call(compiler, '_hardSourceMethods', [methods]);
}
compilerHooks.watchRun.tap('HardSource - ArchetypeSystem', run);
compilerHooks.run.tap('HardSource - ArchetypeSystem', run);
compilerHooks.compilation.tap(
'HardSource - ArchetypeSystem',
compilation => {
compilation.__hardSourceMethods = {
freeze,
thaw,
mapFreeze,
mapThaw,
store,
fetch,
};
},
);
}
}
module.exports = ArchetypeSystem;
-38
View File
@@ -1,38 +0,0 @@
const pluginCompat = require('./util/plugin-compat');
const logMessages = require('./util/log-messages');
const { ParityRoot } = require('./util/parity');
class ParitySystem {
apply(compiler) {
pluginCompat.register(compiler, '_hardSourceParityCache', 'sync', [
'parityRoot',
]);
const compilerHooks = pluginCompat.hooks(compiler);
function runParityOrReset(_compiler) {
const parityRoot = new ParityRoot();
compilerHooks._hardSourceParityCache.call(parityRoot);
if (!parityRoot.verify()) {
logMessages.cacheNoParity(compiler, { parityRoot });
// Reset the cache, some part of it is incomplete and using it will lead
// to errors.
compilerHooks._hardSourceResetCache.call();
}
return Promise.resolve();
}
compilerHooks.watchRun.tapPromise(
'HardSource - index - parityOrReset',
runParityOrReset,
);
compilerHooks.run.tapPromise(
'HardSource - index - parityOrReset',
runParityOrReset,
);
}
}
module.exports = ParitySystem;
-163
View File
@@ -1,163 +0,0 @@
const { readdir: _readdir, stat: _stat } = require('graceful-fs');
const { basename, join } = require('path');
const _rimraf = require('rimraf');
const logMessages = require('./util/log-messages');
const pluginCompat = require('./util/plugin-compat');
const promisify = require('./util/promisify');
const readdir = promisify(_readdir);
const rimraf = promisify(_rimraf);
const stat = promisify(_stat);
const directorySize = async dir => {
const _stat = await stat(dir);
if (_stat.isFile()) {
return _stat.size;
}
if (_stat.isDirectory()) {
const names = await readdir(dir);
let size = 0;
for (const name of names) {
size += await directorySize(join(dir, name));
}
return size;
}
return 0;
};
class CacheInfo {
constructor(id = '') {
this.id = id;
this.lastModified = 0;
this.size = 0;
}
static async fromDirectory(dir) {
const info = new CacheInfo(basename(dir));
info.lastModified = new Date(
(await stat(join(dir, 'stamp'))).mtime,
).getTime();
info.size = await directorySize(dir);
return info;
}
static async fromDirectoryChildren(dir) {
const children = [];
const names = await readdir(dir);
for (const name of names) {
children.push(await CacheInfo.fromDirectory(join(dir, name)));
}
return children;
}
}
// Compilers for webpack with multiple parallel configurations might try to
// delete caches at the same time. Mutex lock the process of pruning to keep
// from multiple pruning runs from colliding with each other.
let deleteLock = null;
class PruneCachesSystem {
constructor(cacheRoot, options = {}) {
this.cacheRoot = cacheRoot;
this.options = Object.assign(
{
// Caches younger than `maxAge` are not considered for deletion. They
// must be at least this (default: 2 days) old in milliseconds.
maxAge: 2 * 24 * 60 * 60 * 1000,
// All caches together must be larger than `sizeThreshold` before any
// caches will be deleted. Together they must be at least this
// (default: 50 MB) big in bytes.
sizeThreshold: 50 * 1024 * 1024,
},
options,
);
}
apply(compiler) {
const compilerHooks = pluginCompat.hooks(compiler);
const deleteOldCaches = async () => {
while (deleteLock !== null) {
await deleteLock;
}
let resolveLock;
let infos;
try {
deleteLock = new Promise(resolve => {
resolveLock = resolve;
});
infos = await CacheInfo.fromDirectoryChildren(this.cacheRoot);
// Sort lastModified in descending order. More recently modified at the
// beginning of the array.
infos.sort((a, b) => b.lastModified - a.lastModified);
const totalSize = infos.reduce((carry, info) => carry + info.size, 0);
const oldInfos = infos.filter(
info => info.lastModified < Date.now() - this.options.maxAge,
);
const oldTotalSize = oldInfos.reduce(
(carry, info) => carry + info.size,
0,
);
if (oldInfos.length > 0 && totalSize > this.options.sizeThreshold) {
const newInfos = infos.filter(
info => info.lastModified >= Date.now() - this.options.maxAge,
);
for (const info of oldInfos) {
rimraf(join(this.cacheRoot, info.id));
}
const newTotalSize = newInfos.reduce(
(carry, info) => carry + info.size,
0,
);
logMessages.deleteOldCaches(compiler, {
infos,
totalSize,
newInfos,
newTotalSize,
oldInfos,
oldTotalSize,
});
} else {
logMessages.keepCaches(compiler, {
infos,
totalSize,
});
}
} catch (error) {
if (error.code !== 'ENOENT') {
throw error;
}
} finally {
if (typeof resolveLock === 'function') {
deleteLock = null;
resolveLock();
}
}
};
compilerHooks.watchRun.tapPromise(
'HardSource - PruneCachesSystem',
deleteOldCaches,
);
compilerHooks.run.tapPromise(
'HardSource - PruneCachesSystem',
deleteOldCaches,
);
}
}
module.exports = PruneCachesSystem;
-35
View File
@@ -1,35 +0,0 @@
const RawSource = require('webpack-sources').RawSource;
const pluginCompat = require('./util/plugin-compat');
class TransformAssetPlugin {
apply(compiler) {
pluginCompat.tap(
compiler,
'_hardSourceFreezeAsset',
'TransformAssetPlugin freeze',
(frozen, asset, extra) => asset.source(),
);
pluginCompat.tap(
compiler,
'_hardSourceThawAsset',
'TransformAssetPlugin thaw',
(thawed, asset, extra) => {
if (!thawed) {
thawed = asset;
if (thawed.type === 'buffer') {
thawed = new Buffer(thawed);
}
if (!(thawed instanceof RawSource)) {
thawed = new RawSource(thawed);
}
}
return thawed;
},
);
}
}
module.exports = TransformAssetPlugin;
@@ -1,79 +0,0 @@
const pluginCompat = require('./util/plugin-compat');
function freezeDependency(dependency, extra, methods) {
if (extra.schemas.map.has(dependency.constructor)) {
return extra.schemas.map
.get(dependency.constructor)
.freeze(dependency, dependency, extra, methods);
}
if (extra.schemas[dependency.constructor.name]) {
return extra.schemas[dependency.constructor.name].freeze(
dependency,
dependency,
extra,
methods,
);
}
}
function thawDependency(frozen, extra, methods) {
if (extra.schemas[frozen.type]) {
return extra.schemas[frozen.type].thaw(null, frozen, extra, methods);
}
}
class TransformBasicDependencyPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
if (this.options.schema < 4) {
const TransformBasicDependencyPluginLegacy = require('./TransformBasicDependencyPluginLegacy');
new TransformBasicDependencyPluginLegacy(this.options).apply(compiler);
} else {
const schemas = require('./schema-4');
let methods;
pluginCompat.tap(
compiler,
'_hardSourceMethods',
'TransformBasicDependencyPlugin methods',
_methods => {
methods = _methods;
},
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeDependency',
'TransformBasicDependencyPlugin freeze',
(frozen, dependency, extra) => {
extra.schemas = schemas;
const _frozen = freezeDependency(dependency, extra, methods);
if (_frozen) {
return _frozen;
}
return frozen;
},
);
pluginCompat.tap(
compiler,
'_hardSourceThawDependency',
'TransformBasicDependencyPlugin',
(dependency, frozen, extra) => {
extra.schemas = schemas;
const _thawed = thawDependency(frozen, extra, methods);
if (_thawed) {
return _thawed;
}
return dependency;
},
);
}
}
}
module.exports = TransformBasicDependencyPlugin;
@@ -1,822 +0,0 @@
const cachePrefix = require('./util').cachePrefix;
const LoggerFactory = require('./loggerFactory');
const pluginCompat = require('./util/plugin-compat');
const relateContext = require('./util/relate-context');
let LocalModule;
try {
LocalModule = require('webpack/lib/dependencies/LocalModule');
} catch (_) {}
function flattenPrototype(obj) {
if (typeof obj === 'string') {
return obj;
}
const copy = {};
for (const key in obj) {
copy[key] = obj[key];
}
return copy;
}
let AMDDefineDependency;
let AMDRequireArrayDependency;
let AMDRequireContextDependency;
let AMDRequireDependency;
let AMDRequireItemDependency;
let CommonJsRequireContextDependency;
let CommonJsRequireDependency;
let ConstDependency;
let ContextDependency;
let ContextElementDependency;
let CriticalDependencyWarning;
let DelegatedExportsDependency;
let DelegatedSourceDependency;
let DllEntryDependency;
let HarmonyAcceptDependency;
let HarmonyAcceptImportDependency;
let HarmonyCompatibilityDependency;
let HarmonyExportExpressionDependency;
let HarmonyExportHeaderDependency;
let HarmonyExportImportedSpecifierDependency;
let HarmonyExportSpecifierDependency;
let HarmonyImportDependency;
let HarmonyImportSpecifierDependency;
let ImportContextDependency;
let ImportDependency;
let ImportEagerContextDependency;
let ImportEagerDependency;
let ImportLazyContextDependency;
let ImportLazyOnceContextDependency;
let ImportWeakContextDependency;
let ImportWeakDependency;
let LoaderDependency;
let LocalModuleDependency;
let ModuleDependency;
let ModuleHotAcceptDependency;
let ModuleHotDeclineDependency;
let MultiEntryDependency;
let NullDependency;
let PrefetchDependency;
let RequireContextDependency;
let RequireEnsureDependency;
let RequireEnsureItemDependency;
let RequireHeaderDependency;
let RequireIncludeDependency;
let RequireResolveContextDependency;
let RequireResolveDependency;
let RequireResolveHeaderDependency;
let SingleEntryDependency;
let UnsupportedDependency;
const DependencySchemas2 = [
[
'AMDDefineDependency',
'range',
'arrayRange',
'functionRange',
'objectRange',
'namedModule',
],
['AMDRequireArrayDependency', 'depsArray', 'range'],
[
'AMDRequireContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
],
['AMDRequireDependency', 'block'],
['AMDRequireItemDependency', 'request', 'range'],
[
'CommonJsRequireContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
],
['CommonJsRequireDependency', 'request', 'range'],
['ConstDependency', 'expression', 'range'],
['ContextDependency', 'request', 'recursive', 'regExp'],
['ContextElementDependency', 'request', 'userRequest'],
['DelegatedSourceDependency', 'request'],
['DllEntryDependency', 'dependencies', 'name'],
['HarmonyAcceptDependency', 'range', 'dependencies', 'hasCallback'],
['HarmonyAcceptImportDependency', 'request', 'importedVar', 'range'],
['HarmonyCompatibilityDependency', 'originModule'],
[
'HarmonyExportExpressionDependency',
'originModule',
'range',
'rangeStatement',
'prefix',
],
['HarmonyExportHeaderDependency', 'range', 'rangeStatement'],
[
'HarmonyExportImportedSpecifierDependency',
'originModule',
'importDependency',
'importedVar',
'id',
'name',
],
[
'HarmonyExportSpecifierDependency',
'originModule',
'id',
'name',
'position',
'immutable',
],
['HarmonyImportDependency', 'request', 'importedVar', 'range'],
[
'HarmonyImportSpecifierDependency',
'importDependency',
'importedVar',
'id',
'name',
'range',
'strictExportPresence',
],
[
'ImportContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
'chunkName',
],
['ImportDependency', 'request', 'block'],
[
'ImportEagerContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
'chunkName',
],
['ImportEagerDependency', 'request', 'range'],
[
'ImportLazyContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
'chunkName',
],
[
'ImportLazyOnceContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
'chunkName',
],
['LoaderDependency', 'request'],
['LocalModuleDependency', 'localModule', 'range'],
['ModuleDependency', 'request'],
['ModuleHotAcceptDependency', 'request', 'range'],
['ModuleHotDeclineDependency', 'request', 'range'],
['MultiEntryDependency', 'dependencies', 'name'],
['NullDependency'],
['PrefetchDependency', 'request'],
['RequireContextDependency', 'request', 'recursive', 'regExp', 'range'],
['RequireEnsureDependency', 'block'],
['RequireEnsureItemDependency', 'request'],
['RequireHeaderDependency', 'range'],
['RequireIncludeDependency', 'request', 'range'],
[
'RequireResolveContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
],
['RequireResolveDependency', 'request', 'range'],
['RequireResolveHeaderDependency', 'range'],
['SingleEntryDependency', 'request'],
['UnsupportedDependency', 'request', 'range'],
];
const DependencySchemas3 = [
[
'AMDDefineDependency',
'range',
'arrayRange',
'functionRange',
'objectRange',
'namedModule',
],
['AMDRequireArrayDependency', 'depsArray', 'range'],
[
'AMDRequireContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
],
['AMDRequireDependency', 'block'],
['AMDRequireItemDependency', 'request', 'range'],
[
'CommonJsRequireContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
],
['CommonJsRequireDependency', 'request', 'range'],
['ConstDependency', 'expression', 'range'],
['ContextDependency', 'request', 'recursive', 'regExp'],
['ContextElementDependency', 'request', 'userRequest'],
['CriticalDependencyWarning', 'message'],
['DelegatedExportsDependency', 'originModule', 'exports'],
['DelegatedSourceDependency', 'request'],
['DllEntryDependency', 'dependencies', 'name'],
['HarmonyAcceptDependency', 'range', 'dependencies', 'hasCallback'],
['HarmonyAcceptImportDependency', 'request', 'importedVar', 'range'],
['HarmonyCompatibilityDependency', 'originModule'],
[
'HarmonyExportExpressionDependency',
'originModule',
'range',
'rangeStatement',
'prefix',
],
['HarmonyExportHeaderDependency', 'range', 'rangeStatement'],
[
'HarmonyExportImportedSpecifierDependency',
'originModule',
'importDependency',
'importedVar',
'id',
'name',
'activeExports',
'otherStarExports',
],
[
'HarmonyExportSpecifierDependency',
'originModule',
'id',
'name',
'position',
'immutable',
],
['HarmonyImportDependency', 'request', 'importedVar', 'range'],
[
'HarmonyImportSpecifierDependency',
'importDependency',
'importedVar',
'id',
'name',
'range',
'strictExportPresence',
],
[
'ImportContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
'chunkName',
],
['ImportDependency', 'request', 'block'],
[
'ImportEagerContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
'chunkName',
],
['ImportEagerDependency', 'request', 'range'],
[
'ImportLazyContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
'chunkName',
],
[
'ImportLazyOnceContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
'chunkName',
],
[
'ImportWeakContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
'chunkName',
],
['ImportWeakDependency', 'request', 'range'],
['LoaderDependency', 'request'],
['LocalModuleDependency', 'localModule', 'range'],
['ModuleDependency', 'request'],
['ModuleHotAcceptDependency', 'request', 'range'],
['ModuleHotDeclineDependency', 'request', 'range'],
['MultiEntryDependency', 'dependencies', 'name'],
['NullDependency'],
['PrefetchDependency', 'request'],
[
'RequireContextDependency',
'request',
'recursive',
'regExp',
'asyncMode',
'range',
],
['RequireEnsureDependency', 'block'],
['RequireEnsureItemDependency', 'request'],
['RequireHeaderDependency', 'range'],
['RequireIncludeDependency', 'request', 'range'],
[
'RequireResolveContextDependency',
'request',
'recursive',
'regExp',
'range',
'valueRange',
],
['RequireResolveDependency', 'request', 'range'],
['RequireResolveHeaderDependency', 'range'],
['SingleEntryDependency', 'request'],
['UnsupportedDependency', 'request', 'range'],
];
const freezeArgument = {
dependencies(arg, dependency, extra, methods) {
return methods.mapFreeze('Dependency', null, arg, extra);
},
depsArray(arg, dependency, extra, methods) {
return methods.mapFreeze('Dependency', null, arg, extra);
},
localModule({ name, idx }, dependency, extra, methods) {
return {
name: name,
idx: idx,
};
},
regExp(arg, dependency, extra, methods) {
return arg ? arg.source : false;
},
request(arg, dependency, extra, methods) {
return relateContext.relateAbsoluteRequest(extra.module.context, arg);
},
userRequest(arg, dependency, extra, methods) {
return relateContext.relateAbsoluteRequest(extra.module.context, arg);
},
block(arg, dependency, extra, methods) {
// Dependency nested in a parent. Freezing the block is a loop.
if (arg.dependencies.includes(dependency)) {
return;
}
return methods.freeze('DependencyBlock', null, arg, extra);
},
importDependency(arg, dependency, extra, methods) {
return methods.freeze('Dependency', null, arg, extra);
},
originModule(arg, dependency, extra, methods) {
// This will be in extra, generated or found during the process of thawing.
},
activeExports(arg, dependency, extra, methods) {
return null;
},
otherStarExports(arg, dependency, extra, methods) {
if (arg) {
// This will be in extra, generated during the process of thawing.
return 'star';
}
return null;
},
options(arg, dependency, extra, methods) {
if (arg.regExp) {
return Object.assign({}, arg, {
regExp: arg.regExp.source,
});
}
return arg;
},
parserScope(arg, dependencies, extra, methods) {
return;
},
};
const thawArgument = {
dependencies(arg, frozen, extra, methods) {
return methods.mapThaw('Dependency', null, arg, extra);
},
depsArray(arg, frozen, extra, methods) {
return methods.mapThaw('Dependency', null, arg, extra);
},
localModule({ idx, name, used }, frozen, extra, methods) {
const state = extra.state;
if (!state.localModules) {
state.localModules = [];
}
if (!state.localModules[idx]) {
state.localModules[idx] = new LocalModule(extra.module, name, idx);
state.localModules[idx].used = used;
}
return state.localModules[idx];
},
regExp(arg, frozen, extra, methods) {
return arg ? new RegExp(arg) : arg;
},
// request: function(arg, dependency, extra, methods) {
// return relateContext.contextNormalRequest(extra.compilation.compiler, arg);
// },
block(arg, frozen, extra, methods) {
// Not having a block, means it needs to create a cycle and refer to its
// parent.
if (!arg) {
return extra.parent;
}
return methods.thaw('DependencyBlock', null, arg, extra);
},
importDependency(arg, frozen, extra, methods) {
return methods.thaw('Dependency', null, arg, extra);
},
originModule(arg, frozen, extra, methods) {
return extra.module;
},
activeExports(arg, { name }, { state }, methods) {
state.activeExports = state.activeExports || new Set();
if (name) {
state.activeExports.add(name);
}
return state.activeExports;
},
otherStarExports(arg, frozen, { state }, methods) {
if (arg === 'star') {
return state.otherStarExports || [];
}
return null;
},
options(arg, frozen, extra, methods) {
if (arg.regExp) {
return Object.assign({}, arg, {
regExp: new RegExp(arg.regExp),
});
}
return arg;
},
parserScope(arg, frozen, { state }, methods) {
state.harmonyParserScope = state.harmonyParserScope || {};
return state.harmonyParserScope;
},
};
function freezeDependency(dependency, extra, methods) {
const schemas = extra.schemas;
for (let i = 0; i < schemas.length; i++) {
if (dependency.constructor === schemas[i].Dependency) {
const frozen = {
type: schemas[i][0],
};
for (let j = 1; j < schemas[i].length; j++) {
let arg = dependency[schemas[i][j]];
if (freezeArgument[schemas[i][j]]) {
arg = freezeArgument[schemas[i][j]](arg, dependency, extra, methods);
}
frozen[schemas[i][j]] = arg;
}
return frozen;
}
}
}
function thawDependency(frozen, extra, methods) {
const schemas = extra.schemas;
schemas.map = schemas.map || {};
if (schemas.map[frozen.type]) {
const depSchema = schemas.map[frozen.type];
const Dependency = depSchema.Dependency;
try {
return new Dependency(...depSchema.args(frozen, extra, methods));
} catch (_) {
return new (Function.prototype.bind.apply(
Dependency,
[null].concat(depSchema.args(frozen, extra, methods)),
))();
}
}
for (const depSchema of schemas) {
if (frozen.type === depSchema[0]) {
schemas.map[frozen.type] = depSchema;
const Dependency = depSchema.Dependency;
const lines = [];
for (let j = 1; j < depSchema.length; j++) {
const argName = depSchema[j];
if (thawArgument[argName]) {
lines.push(
` thawArgument.${argName}(frozen.${argName}, frozen, extra, methods)`,
);
} else {
lines.push(` frozen.${argName}`);
}
}
depSchema.args = new Function(
'thawArgument',
`
return function(frozen, extra, methods) {
return [
${lines.join(',\n')}
];
};
`,
)(thawArgument);
try {
return new Dependency(...depSchema.args(frozen, extra, methods));
} catch (_) {
return new (Function.prototype.bind.apply(
Dependency,
[null].concat(depSchema.args(frozen, extra, methods)),
))();
}
}
}
}
class TransformBasicDependencyPluginLegacy {
constructor(options) {
this.options = options;
}
apply(compiler) {
let schemas = DependencySchemas3;
if (this.options.schema < 3) {
schemas = DependencySchemas2;
}
pluginCompat.tap(
compiler,
'afterPlugins',
'TransformBasicDependencyPlugin scan Dependency types',
() => {
pluginCompat.tap(
compiler,
'compilation',
'TransformBasicDependencyPlugin scan Dependencies types',
({ dependencyFactories }) => {
const Dependencies = dependencyFactories.keys();
for (const Dep of Dependencies) {
for (let i = 0; i < schemas.length; i++) {
if (Dep.name === schemas[i][0]) {
schemas[i].Dependency = Dep;
}
}
}
for (let i = 0; i < schemas.length; i++) {
if (!schemas[i].Dependency) {
if (this.options.schema < 4) {
} else {
if (schemas[i][0] === 'JsonExportsDependency') {
try {
schemas[
i
].Dependency = require('webpack/lib/dependencies/JsonExportsDependency');
} catch (_) {}
} else if (schemas[i][0] === 'DelegatedExportsDependency') {
try {
schemas[
i
].Dependency = require('webpack/lib/dependencies/DelegatedExportsDependency');
} catch (_) {}
} else if (schemas[i][0] === 'DelegatedSourceDependency') {
try {
schemas[
i
].Dependency = require('webpack/lib/dependencies/DelegatedSourceDependency');
} catch (_) {}
}
}
}
}
},
);
},
);
let methods;
pluginCompat.tap(
compiler,
'_hardSourceMethods',
'TransformBasicDependencyPlugin methods',
_methods => {
methods = _methods;
},
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeDependency',
'TransformBasicDependencyPlugin freeze',
(frozen, dependency, extra) => {
extra.schemas = schemas;
const _frozen = freezeDependency(dependency, extra, methods);
if (_frozen) {
if (dependency.prepend) {
_frozen.prepend = dependency.prepend;
}
if (dependency.replaces) {
_frozen.replaces = dependency.replaces;
}
if (dependency.critical) {
_frozen.critical = dependency.critical;
}
if (typeof dependency.namespaceObjectAsContext !== 'undefined') {
_frozen.namespaceObjectAsContext =
dependency.namespaceObjectAsContext;
}
if (typeof dependency.callArgs !== 'undefined') {
_frozen.callArgs = dependency.callArgs;
}
if (typeof dependency.call !== 'undefined') {
_frozen.call = dependency.call;
}
if (typeof dependency.directImport !== 'undefined') {
_frozen.directImport = dependency.directImport;
}
if (typeof dependency.shorthand !== 'undefined') {
_frozen.shorthand = dependency.shorthand;
}
if (
typeof dependency.localModule === 'object' &&
dependency.localModule !== null
) {
_frozen.localModule = {
name: dependency.localModule.name,
idx: dependency.localModule.idx,
used: dependency.localModule.used,
};
}
return _frozen;
}
return frozen;
},
);
pluginCompat.tap(
compiler,
'_hardSourceAfterFreezeDependency',
'TransformBasicDependencyPlugin after freeze',
(frozen, dependency, extra) => {
if (frozen && dependency.loc) {
frozen.loc = flattenPrototype(dependency.loc);
}
if (frozen && dependency.optional) {
frozen.optional = dependency.optional;
}
if (frozen && dependency.getWarnings) {
const warnings = dependency.getWarnings();
if (warnings && warnings.length) {
frozen.warnings = warnings.map(({ stack }) =>
stack.includes('\n at pluginCompat.tap')
? stack.split('\n at pluginCompat.tap')[0]
: stack.split('\n at Compiler.pluginCompat.tap')[0],
);
}
}
return frozen;
},
);
pluginCompat.tap(
compiler,
'_hardSourceThawDependency',
'TransformBasicDependencyPlugin',
(dependency, frozen, extra) => {
extra.schemas = schemas;
const _thawed = thawDependency(frozen, extra, methods);
if (_thawed) {
const state = extra.state;
// console.log('Thawed', frozen.type);
if (frozen.prepend) {
_thawed.prepend = frozen.prepend;
}
if (frozen.replaces) {
_thawed.replaces = frozen.replaced;
}
if (frozen.critical) {
_thawed.critical = frozen.critical;
}
if (typeof frozen.namespaceObjectAsContext !== 'undefined') {
_thawed.namespaceObjectAsContext = frozen.namespaceObjectAsContext;
}
if (typeof frozen.callArgs !== 'undefined') {
_thawed.callArgs = frozen.callArgs;
}
if (typeof frozen.call !== 'undefined') {
_thawed.call = frozen.call;
}
if (typeof frozen.directImport !== 'undefined') {
_thawed.directImport = frozen.directImport;
}
if (typeof frozen.shorthand !== 'undefined') {
_thawed.shorthand = frozen.shorthand;
}
if (
typeof frozen.localModule === 'object' &&
frozen.localModule !== null
) {
if (!state.localModules) {
state.localModules = [];
}
if (!state.localModules[frozen.localModule.idx]) {
state.localModules[frozen.localModule.idx] = new LocalModule(
extra.module,
frozen.localModule.name,
frozen.localModule.idx,
);
state.localModules[frozen.localModule.idx].used =
frozen.localModule.used;
}
_thawed.localModule = state.localModules[frozen.localModule.idx];
}
if (frozen.type === 'HarmonyImportDependency') {
const ref = frozen.range.toString();
if (state.imports[ref]) {
return state.imports[ref];
}
state.imports[ref] = _thawed;
} else if (
frozen.type === 'HarmonyExportImportedSpecifierDependency'
) {
if (_thawed.otherStarExports) {
extra.state.otherStarExports = (
extra.state.otherStarExports || []
).concat(_thawed);
}
}
return _thawed;
}
return dependency;
},
);
pluginCompat.tap(
compiler,
'_hardSourceAfterThawDependency',
'TransformBasicDependencyPlugin',
(dependency, { loc, optional, warnings }, extra) => {
if (dependency && loc) {
dependency.loc = loc;
}
if (dependency && optional) {
dependency.optional = true;
}
if (dependency && warnings && dependency.getWarnings) {
const frozenWarnings = warnings;
const _getWarnings = dependency.getWarnings;
dependency.getWarnings = function() {
const warnings = _getWarnings.call(this);
if (warnings && warnings.length) {
return warnings.map((warning, i) => {
const stack = warning.stack.split(
'\n at Compilation.reportDependencyErrorsAndWarnings',
)[1];
warning.stack = `${
frozenWarnings[i]
}\n at Compilation.reportDependencyErrorsAndWarnings${stack}`;
return warning;
});
}
return warnings;
};
}
return dependency;
},
);
}
}
module.exports = TransformBasicDependencyPluginLegacy;
@@ -1,47 +0,0 @@
const cachePrefix = require('./util').cachePrefix;
const logMessages = require('./util/log-messages');
const pluginCompat = require('./util/plugin-compat');
class TransformCompilationPlugin {
apply(compiler) {
let store;
pluginCompat.tap(
compiler,
'_hardSourceMethods',
'TransformCompilationPlugin copy methods',
methods => {
store = methods.store;
// fetch = methods.fetch;
// freeze = methods.freeze;
// thaw = methods.thaw;
},
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeCompilation',
'TransformCompilationPlugin freeze',
(_, compilation) => {
compilation.modules.forEach(module => {
const identifierPrefix = cachePrefix(compilation);
if (identifierPrefix === null) {
return;
}
const identifier = identifierPrefix + module.identifier();
try {
store('Module', identifier, module, {
id: identifier,
compilation,
});
} catch (e) {
logMessages.moduleFreezeError(compilation, module, e);
}
});
},
);
}
}
module.exports = TransformCompilationPlugin;
@@ -1,107 +0,0 @@
const NormalModule = require('webpack/lib/NormalModule');
const cachePrefix = require('./util').cachePrefix;
const pluginCompat = require('./util/plugin-compat');
function wrapSource(source, methods) {
Object.keys(methods).forEach(key => {
const _method = source[key];
source[key] = function(...args) {
methods[key].apply(this, args);
_method && _method.apply(this, args);
};
});
return source;
}
function spyMethod(name, mods) {
return function(...args) {
mods.push([name].concat([].slice.call(args)));
};
}
function isEqual(a, b) {
if (Array.isArray(a) && Array.isArray(b) && a.length === b.length) {
return a.reduce(
(carry, value, index) => carry && isEqual(value, b[index]),
true,
);
} else if (a === b) {
return true;
}
return false;
}
class HardModuleConcatenationPlugin {
apply(compiler) {
let store;
let freeze;
pluginCompat.tap(
compiler,
'_hardSourceMethods',
'HardModuleConcatenationPlugin',
methods => {
store = methods.store;
// fetch = methods.fetch;
freeze = methods.freeze;
// thaw = methods.thaw;
// mapFreeze = methods.mapFreeze;
// mapThaw = methods.mapThaw;
},
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeModule',
'HardModuleConcatenationPlugin',
(frozen, { modules }, extra) => {
if (modules) {
const compilation = extra.compilation;
modules.forEach(module => {
if (
(module.cacheable ||
(module.buildInfo && module.buildInfo.cacheable)) &&
module instanceof NormalModule
) {
const identifierPrefix = cachePrefix(compilation);
if (identifierPrefix === null) {
return;
}
const identifier = identifierPrefix + module.identifier();
store('Module', identifier, module, {
id: identifier,
compilation,
});
}
});
}
return frozen;
},
);
pluginCompat.tap(
compiler,
'_hardSourceAfterFreezeModule',
'HardModuleConcatenationPlugin',
(frozen, module, { compilation }) => {
return frozen;
if (frozen && module.__hardSource_concatedSource) {
const source = module.__hardSource_concatedSource;
frozen.source = source.source();
frozen.sourceMap = freeze('SourceMap', null, source, {
module,
compilation: compilation,
});
frozen.concatenatedSourceMods = module.__hardSource_sourceMods;
}
return frozen;
},
);
}
}
module.exports = HardModuleConcatenationPlugin;
@@ -1,389 +0,0 @@
const DependenciesBlockVariable = require('webpack/lib/DependenciesBlockVariable');
const pluginCompat = require('./util/plugin-compat');
const BlockSchemas3 = [
[
'AMDRequireDependenciesBlock',
'expr',
'arrayRange',
'functionRange',
'errorCallbackRange',
'module',
'loc',
],
['ImportDependenciesBlock', 'request', 'range', 'chunkName', 'module', 'loc'],
[
'RequireEnsureDependenciesBlock',
'expr',
'successExpression',
'errorExpression',
'chunkName',
'chunkNameRange',
'module',
'loc',
],
['AsyncDependenciesBlock', 'name', 'module'],
];
const BlockSchemas4 = [
[
'AMDRequireDependenciesBlock',
'expr',
'arrayRange',
'functionRange',
'errorCallbackRange',
'module',
'loc',
'request',
],
[
'ImportDependenciesBlock',
'request',
'range',
'groupOptions',
'module',
'loc',
'originModule',
],
[
'RequireEnsureDependenciesBlock',
'expr',
'successExpression',
'errorExpression',
'chunkName',
'chunkNameRange',
'module',
'loc',
],
['AsyncDependenciesBlock', 'groupOptions', 'module', 'loc', 'request'],
];
try {
BlockSchemas3[0].DependencyBlock = require('webpack/lib/dependencies/AMDRequireDependenciesBlock');
BlockSchemas4[0].DependencyBlock = require('webpack/lib/dependencies/AMDRequireDependenciesBlock');
} catch (_) {}
try {
BlockSchemas3[1].DependencyBlock = require('webpack/lib/dependencies/ImportDependenciesBlock');
BlockSchemas4[1].DependencyBlock = require('webpack/lib/dependencies/ImportDependenciesBlock');
} catch (_) {}
try {
BlockSchemas3[2].DependencyBlock = require('webpack/lib/dependencies/RequireEnsureDependenciesBlock');
BlockSchemas4[2].DependencyBlock = require('webpack/lib/dependencies/RequireEnsureDependenciesBlock');
} catch (_) {}
try {
BlockSchemas3[3].DependencyBlock = require('webpack/lib/AsyncDependenciesBlock');
BlockSchemas4[3].DependencyBlock = require('webpack/lib/AsyncDependenciesBlock');
} catch (_) {}
const freezeArgument = {
chunkName(arg, { chunkName }, extra, methods) {
return chunkName;
},
name(arg, { name }, extra, methods) {
return name;
},
groupOptions(arg, { groupOptions }) {
return groupOptions;
},
module(arg, block, extra, methods) {},
originModule(arg, block, extra, methods) {},
};
const thawArgument = {
module(arg, frozen, extra, methods) {
return extra.module;
},
originModule(arg, block, extra, methods) {
return extra.module;
},
};
function freezeDependencyBlock(dependencyBlock, extra, methods) {
const schemas = extra.schemas;
for (let i = 0; i < schemas.length; i++) {
if (dependencyBlock.constructor === schemas[i].DependencyBlock) {
const frozen = {
type: schemas[i][0],
};
for (let j = 1; j < schemas[i].length; j++) {
let arg = dependencyBlock[schemas[i][j]];
if (freezeArgument[schemas[i][j]]) {
arg = freezeArgument[schemas[i][j]](
arg,
dependencyBlock,
extra,
methods,
);
}
frozen[schemas[i][j]] = arg;
}
return frozen;
}
}
}
function thawDependencyBlock(frozen, extra, methods) {
const schemas = extra.schemas;
for (let i = 0; i < schemas.length; i++) {
if (frozen.type === schemas[i][0]) {
const DependencyBlock = schemas[i].DependencyBlock;
const args = [];
for (let j = 1; j < schemas[i].length; j++) {
let arg = frozen[schemas[i][j]];
if (thawArgument[schemas[i][j]]) {
arg = thawArgument[schemas[i][j]](arg, frozen, extra, methods);
}
args.push(arg);
}
try {
return new DependencyBlock(...args);
} catch (_) {
return new (Function.prototype.bind.apply(
DependencyBlock,
[null].concat(args),
))();
}
}
}
}
function assertFrozen({ length }, original, typeName, freeze) {
if (length !== original.length) {
const didNotFreeze = original.filter(item => !freeze(item));
if (didNotFreeze.length > 0) {
throw new Error(
`Unfrozen ${typeName} (${didNotFreeze.length} / ${
original.length
}): ${didNotFreeze
.map(({ constructor }) => constructor.name)
.filter((name, i, names) => !names.slice(0, i).includes(name))
.join(', ')}`,
);
}
}
}
class TransformDependencyBlockPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
let schemas = BlockSchemas4;
if (this.options.schema < 4) {
schemas = BlockSchemas3;
}
let methods;
pluginCompat.tap(
compiler,
'_hardSourceMethods',
'TransformDependencyBlockPlugin',
_methods => {
methods = _methods;
},
);
let freeze;
let mapFreeze;
let mapThaw;
pluginCompat.tap(
compiler,
'_hardSourceMethods',
'TransformDependencyBlockPlugin',
methods => {
// store = methods.store;
// fetch = methods.fetch;
freeze = methods.freeze;
// thaw = methods.thaw;
mapFreeze = methods.mapFreeze;
mapThaw = methods.mapThaw;
},
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeDependencyVariable',
'TransformDependencyBlockPlugin',
(frozen, { name, expression, dependencies }, extra) => ({
type: 'DependenciesBlockVariable',
name: name,
expression: expression,
dependencies: mapFreeze('Dependency', null, dependencies, extra),
}),
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeDependencyBlock',
'TransformDependencyBlockPlugin',
(frozen, block, extra) => {
extra.schemas = schemas;
const _frozen = freezeDependencyBlock(block, extra, methods);
if (_frozen) {
if (
(block.dependencies && block.dependencies.length > 0) ||
(block.variables && block.variables.length > 0) ||
(block.blocks && block.blocks.length > 0)
) {
_frozen.dependencies = mapFreeze(
'Dependency',
null,
block.dependencies,
extra,
);
assertFrozen(
_frozen.dependencies,
block.dependencies,
'dependencies',
item => freeze('Dependency', null, item, extra),
);
_frozen.variables = mapFreeze(
'DependencyVariable',
null,
block.variables,
extra,
);
assertFrozen(
_frozen.variables,
block.variables,
'dependency variables',
item => freeze('DependencyVariable', null, item, extra),
);
_frozen.blocks = mapFreeze(
'DependencyBlock',
null,
block.blocks,
extra,
);
assertFrozen(_frozen.blocks, block.blocks, 'blocks', item =>
freeze('DependencyBlock', null, item, extra),
);
}
if (block.parent) {
_frozen.parent = true;
}
return _frozen;
}
const _frozenBlock = {
type: 'DependenciesBlock',
dependencies: mapFreeze(
'Dependency',
null,
block.dependencies,
extra,
),
variables: mapFreeze(
'DependencyVariable',
null,
block.variables,
extra,
),
blocks: mapFreeze('DependencyBlock', null, block.blocks, extra),
};
assertFrozen(
_frozenBlock.dependencies,
block.dependencies,
'dependencies',
item => freeze('Dependency', null, item, extra),
);
assertFrozen(
_frozenBlock.variables,
block.variables,
'dependency variables',
item => freeze('DependencyVariable', null, item, extra),
);
assertFrozen(_frozenBlock.blocks, block.blocks, 'blocks', item =>
freeze('DependencyBlock', null, item, extra),
);
return _frozenBlock;
},
);
pluginCompat.tap(
compiler,
'_hardSourceThawDependencyVariable',
'TransformDependencyBlockPlugin',
(variable, { name, expression, dependencies }, extra) =>
new DependenciesBlockVariable(
name,
expression,
mapThaw('Dependency', null, dependencies, extra),
),
);
pluginCompat.tap(
compiler,
'_hardSourceThawDependencyBlock',
'TransformDependencyBlockPlugin',
(block, frozen, extra) => {
extra.schemas = schemas;
const _thawed = thawDependencyBlock(frozen, extra, methods);
if (_thawed) {
if (_thawed.dependencies) {
var blockExtra = {
state: extra.state,
module: extra.module,
parent: _thawed,
compilation: extra.compilation,
};
_thawed.dependencies = mapThaw(
'Dependency',
null,
frozen.dependencies,
blockExtra,
);
_thawed.variables = mapThaw(
'DependencyVariable',
null,
frozen.variables,
blockExtra,
);
mapThaw('DependencyBlock', null, frozen.blocks, blockExtra);
}
if (frozen.parent) {
extra.parent.addBlock(_thawed);
}
return _thawed;
}
if (block) {
var blockExtra = {
state: extra.state,
module: extra.module,
parent: block,
compilation: extra.compilation,
};
block.dependencies = mapThaw(
'Dependency',
null,
frozen.dependencies,
blockExtra,
);
block.variables = mapThaw(
'DependencyVariable',
null,
frozen.variables,
blockExtra,
);
block.blocks = mapThaw(
'DependencyBlock',
null,
frozen.blocks,
blockExtra,
);
}
return block;
},
);
}
}
module.exports = TransformDependencyBlockPlugin;
-169
View File
@@ -1,169 +0,0 @@
const relateContext = require('./util/relate-context');
const pluginCompat = require('./util/plugin-compat');
const GeneratorSchemas4 = [
['ByTypeGenerator', 'map'],
['JavascriptGenerator'],
['JsonGenerator'],
['WebAssemblyGenerator'],
['WebAssemblyJavascriptGenerator'],
];
try {
try {
GeneratorSchemas4[0].Generator = require('webpack/lib/Generator').byType(
{},
).constructor;
} catch (_) {}
GeneratorSchemas4[1].Generator = require('webpack/lib/JavascriptGenerator');
GeneratorSchemas4[2].Generator = require('webpack/lib/JsonGenerator');
try {
GeneratorSchemas4[3].Generator = require('webpack/lib/WebAssemblyGenerator');
} catch (_) {
GeneratorSchemas4[3].Generator = require('webpack/lib/wasm/WebAssemblyGenerator');
}
try {
GeneratorSchemas4[4].Generator = require('webpack/lib/wasm/WebAssemblyJavascriptGenerator');
} catch (_) {}
} catch (_) {}
const freezeArgument = {
map(arg, generator, extra, methods) {
const map = {};
for (const key in arg) {
map[key] = methods.freeze('Generator', null, arg[key], extra);
}
return map;
},
};
const thawArgument = {
map(arg, generator, extra, methods) {
const map = {};
for (const key in arg) {
map[key] = methods.thaw('Generator', null, arg[key], extra);
}
return map;
},
};
function freezeGenerator(generator, extra, methods) {
const schemas = extra.schemas;
for (let i = 0; i < schemas.length; i++) {
if (generator.constructor === schemas[i].Generator) {
const frozen = {
type: schemas[i][0],
};
for (let j = 1; j < schemas[i].length; j++) {
let arg = generator[schemas[i][j]];
if (freezeArgument[schemas[i][j]]) {
arg = freezeArgument[schemas[i][j]](arg, generator, extra, methods);
}
frozen[schemas[i][j]] = arg;
}
return frozen;
}
}
}
function thawGenerator(frozen, extra, methods) {
const schemas = extra.schemas;
for (let i = 0; i < schemas.length; i++) {
if (frozen.type === schemas[i][0]) {
const Generator = schemas[i].Generator;
const args = [];
for (let j = 1; j < schemas[i].length; j++) {
let arg = frozen[schemas[i][j]];
if (thawArgument[schemas[i][j]]) {
arg = thawArgument[schemas[i][j]](arg, frozen, extra, methods);
}
args.push(arg);
}
try {
return new Generator(...args);
} catch (_) {
return new (Function.prototype.bind.apply(
Generator,
[null].concat(args),
))();
}
}
}
}
class TransformGeneratorPlugin {
apply(compiler) {
pluginCompat.register(
compiler,
'_hardSourceBeforeFreezeGenerator',
'syncWaterfall',
['frozen', 'item', 'extra'],
);
pluginCompat.register(
compiler,
'_hardSourceFreezeGenerator',
'syncWaterfall',
['frozen', 'item', 'extra'],
);
pluginCompat.register(
compiler,
'_hardSourceAfterFreezeGenerator',
'syncWaterfall',
['frozen', 'item', 'extra'],
);
pluginCompat.register(
compiler,
'_hardSourceBeforeThawGenerator',
'syncWaterfall',
['item', 'frozen', 'extra'],
);
pluginCompat.register(
compiler,
'_hardSourceThawGenerator',
'syncWaterfall',
['item', 'frozen', 'extra'],
);
pluginCompat.register(
compiler,
'_hardSourceAfterThawGenerator',
'syncWaterfall',
['item', 'frozen', 'extra'],
);
let methods;
pluginCompat.tap(
compiler,
'_hardSourceMethods',
'TransformGeneratorPlugin',
_methods => {
methods = _methods;
},
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeGenerator',
'TransformGeneratorPlugin freeze',
(frozen, generator, extra) => {
extra.schemas = GeneratorSchemas4;
frozen = freezeGenerator(generator, extra, methods);
frozen.moduleType = extra.module.type;
frozen.options = {};
return frozen;
},
);
pluginCompat.tap(
compiler,
'_hardSourceThawGenerator',
'TransformGeneratorPlugin thaw',
(generator, { moduleType, options }, { normalModuleFactory }) => {
return normalModuleFactory.getGenerator(moduleType, options);
},
);
}
}
module.exports = TransformGeneratorPlugin;
@@ -1,56 +0,0 @@
const pluginCompat = require('./util/plugin-compat');
class TransformModuleAssetsPlugin {
apply(compiler) {
let store;
let fetch;
pluginCompat.tap(
compiler,
'_hardSourceMethods',
'TransformModuleAssetsPlugin copy methods',
methods => {
store = methods.store;
fetch = methods.fetch;
// freeze = methods.freeze;
// thaw = methods.thaw;
// mapFreeze = methods.mapFreeze;
// mapThaw = methods.mapThaw;
},
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeModuleAssets',
'TransformModuleAssetsPlugin freeze',
(frozen, assets, extra) => {
if (!frozen && assets) {
Object.keys(assets).forEach(key => {
store('Asset', key, assets[key], extra);
});
frozen = Object.keys(assets);
}
return frozen;
},
);
pluginCompat.tap(
compiler,
'_hardSourceThawModuleAssets',
'TransformModuleAssetsPlugin thaw',
(assets, frozen, extra) => {
if (!assets && frozen) {
assets = {};
frozen.forEach(key => {
assets[key] = fetch('Asset', key, extra);
});
}
return assets;
},
);
}
}
module.exports = TransformModuleAssetsPlugin;
@@ -1,109 +0,0 @@
const WebpackError = require('webpack/lib/WebpackError');
const ModuleError = require('webpack/lib/ModuleError');
const ModuleWarning = require('webpack/lib/ModuleWarning');
const pluginCompat = require('./util/plugin-compat');
class TransformModuleErrorsPlugin {
apply(compiler) {
let freeze;
let thaw;
let mapFreeze;
let mapThaw;
pluginCompat.tap(
compiler,
'_hardSourceMethods',
'TransformModuleErrorsPlugin',
methods => {
// store = methods.store;
// fetch = methods.fetch;
freeze = methods.freeze;
thaw = methods.thaw;
mapFreeze = methods.mapFreeze;
mapThaw = methods.mapThaw;
},
);
function freezeErrorWarning(
frozen,
{ message, details, originLoc, dependencies, name, loc, constructor },
extra,
) {
return {
constructor: constructor.name,
message: message,
details: details,
originLoc: originLoc,
dependencies:
dependencies && mapFreeze('Dependency', null, dependencies, extra),
name: name,
loc: loc,
};
}
pluginCompat.tap(
compiler,
'_hardSourceFreezeModuleError',
'TransformModuleErrorsPlugin',
freezeErrorWarning,
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeModuleWarning',
'TransformModuleErrorsPlugin',
freezeErrorWarning,
);
function thawError(
ErrorClass,
error,
{ constructor, message, details, originLoc, dependencies, name, loc },
extra,
) {
const module = extra.module;
error = new ErrorClass(module, message);
if (constructor === 'SystemImportDeprecationWarning') {
error = new WebpackError(message);
error.module = module;
}
if (details) {
error.details = details;
}
if (extra.origin) {
error.origin = extra.origin;
}
if (originLoc) {
error.originLoc = originLoc;
}
if (dependencies) {
error.dependencies = mapThaw('Dependency', null, dependencies, extra);
}
if (name) {
error.name = name;
}
if (loc) {
error.loc = loc;
}
return error;
}
pluginCompat.tap(
compiler,
'_hardSourceThawModuleError',
'TransformModuleErrorsPlugin',
(error, frozen, extra) => thawError(ModuleError, error, frozen, extra),
);
pluginCompat.tap(
compiler,
'_hardSourceThawModuleWarning',
'TransformModuleErrorsPlugin',
(warning, frozen, extra) =>
thawError(ModuleWarning, warning, frozen, extra),
);
}
}
module.exports = TransformModuleErrorsPlugin;
@@ -1,229 +0,0 @@
const fs = require('graceful-fs');
const path = require('path');
const cachePrefix = require('./util').cachePrefix;
const pluginCompat = require('./util/plugin-compat');
const relateContext = require('./util/relate-context');
let NS;
NS = path.dirname(fs.realpathSync(__dirname));
class NormalModuleFactoryPlugin {
apply(compiler) {
const compilerHooks = pluginCompat.hooks(compiler);
let fetch;
compilerHooks._hardSourceMethods.tap(
'HardSource - TransformNormalModuleFactoryPlugin',
methods => {
fetch = methods.fetch;
},
);
compilerHooks.compilation.tap(
'HardSource - TransformNormalModuleFactoryPlugin',
(compilation, { normalModuleFactory, contextModuleFactory }) => {
// if (!active) {return;}
// compilation.fileTimestamps = fileTimestamps;
// compilation.contextTimestamps = contextTimestamps;
// compilation.__hardSourceFileMd5s = fileMd5s;
// compilation.__hardSourceCachedMd5s = cachedMd5s;
const compilationHooks = pluginCompat.hooks(compilation);
compilationHooks.buildModule.tap(
'HardSource - TransformNormalModuleFactoryPlugin',
module => {
if (module.constructor.name === 'NormalModule') {
module.__originalCreateLoaderContext =
module.__originalCreateLoaderContext ||
module.createLoaderContext;
module.__hardSource_resolved = {};
module.createLoaderContext = (...args) => {
const loaderContext = module.__originalCreateLoaderContext(
...args,
);
const _resolve = loaderContext.resolve;
loaderContext.resolve = (context, request, callback) => {
_resolve.call(
loaderContext,
context,
request,
(err, result) => {
if (err) {
callback(err, result);
} else {
module.__hardSource_resolved[
JSON.stringify({ context, request })
] = {
resource: result,
resolveOptions: module.resolveOptions,
};
callback(err, result);
}
},
);
};
return loaderContext;
};
}
},
);
const normalModuleFactoryHooks = pluginCompat.hooks(
normalModuleFactory,
);
// Webpack 2 can use different parsers based on config rule sets.
normalModuleFactoryHooks.parser
.for('javascript/auto')
.tap(
'HardSource - TransformNormalModuleFactoryPlugin',
(parser, options) => {
// Store the options somewhere that can not conflict with another plugin
// on the parser so we can look it up and store those options with a
// cached module resolution.
parser[`${NS}/parser-options`] = options;
},
);
normalModuleFactoryHooks.resolver.tap(
'HardSource - TransformNormalModuleFactoryPlugin',
fn => (request, cb) => {
const identifierPrefix = cachePrefix(compilation);
if (identifierPrefix === null) {
return fn.call(null, request, cb);
}
const cacheId = JSON.stringify([
identifierPrefix,
request.context,
request.request,
]);
const absCacheId = JSON.stringify([
identifierPrefix,
request.context,
relateContext.relateAbsoluteRequest(
request.context,
request.request,
),
]);
request.contextInfo.resolveOptions = request.resolveOptions;
const next = () => {
const originalRequest = request;
return fn.call(null, request, function(err, request) {
if (err) {
return cb(err);
}
if (!request.source) {
compilation.__hardSourceModuleResolveCacheChange.push(
cacheId,
);
compilation.__hardSourceModuleResolveCache[
cacheId
] = Object.assign({}, request, {
parser: null,
generator: null,
parserOptions: request.parser[`${NS}/parser-options`],
type: request.settings && request.settings.type,
settings: request.settings,
resourceResolveData: request.resourceResolveData,
dependencies: null,
});
}
cb(...arguments);
});
};
const fromCache = () => {
const result = Object.assign(
{},
compilation.__hardSourceModuleResolveCache[cacheId] ||
compilation.__hardSourceModuleResolveCache[absCacheId],
);
result.dependencies = request.dependencies;
if (!result.parser || !result.parser.parse) {
result.parser = result.settings
? normalModuleFactory.getParser(
result.type,
result.settings.parser,
)
: normalModuleFactory.getParser(result.parserOptions);
}
if (!result.generator && normalModuleFactory.getGenerator) {
result.generator = normalModuleFactory.getGenerator(
result.type,
result.settings.generator,
);
}
result.loaders = result.loaders.map(loader => {
if (typeof loader === 'object' && loader.ident) {
const ruleSet = normalModuleFactory.ruleSet;
return {
loader: loader.loader,
ident: loader.ident,
options: ruleSet.references[loader.ident],
};
}
return loader;
});
return cb(null, result);
};
if (
(compilation.__hardSourceModuleResolveCache[cacheId] &&
!compilation.__hardSourceModuleResolveCache[cacheId].invalid) ||
(compilation.__hardSourceModuleResolveCache[absCacheId] &&
!compilation.__hardSourceModuleResolveCache[absCacheId].invalid)
) {
return fromCache();
}
next();
},
);
normalModuleFactoryHooks.createModule.tap(
'HardSourceWebpackPlugin',
({ request }) => {
if (
compilation.cache &&
compilation.cache[`m${request}`] &&
compilation.cache[`m${request}`].cacheItem &&
!compilation.cache[`m${request}`].cacheItem.invalid
) {
return compilation.cache[`m${request}`];
}
const identifierPrefix = cachePrefix(compilation);
if (identifierPrefix === null) {
return;
}
const identifier = identifierPrefix + request;
const module = fetch('Module', identifier, {
compilation,
normalModuleFactory: normalModuleFactory,
contextModuleFactory: contextModuleFactory,
});
if (module) {
return module;
}
},
);
},
);
}
}
module.exports = NormalModuleFactoryPlugin;
@@ -1,706 +0,0 @@
const NormalModule = require('webpack/lib/NormalModule');
const Module = require('webpack/lib/Module');
const nodeObjectHash = require('node-object-hash');
const logMessages = require('./util/log-messages');
const {
relateNormalPath,
relateNormalRequest,
relateNormalPathSet,
relateNormalLoaders,
} = require('./util/relate-context');
const pluginCompat = require('./util/plugin-compat');
const serial = require('./util/serial');
const serialResolveRequest = serial.created({
context: serial.path,
request: serial.request,
});
const serialResolved = serial.created({
// context: serial.path,
// request: serial.request,
// userRequest: serial.request,
// rawRequest: serial.request,
resource: serial.request,
resolveOptions: serial.identity,
// loaders: serial.loaders,
});
const serialJson = {
freeze(arg, value, extra) {
return JSON.parse(arg);
},
thaw(arg, frozen, extra) {
return JSON.stringify(arg);
},
};
const serialMap = serial.map;
const serialResolvedMap = serial.map(
serial.pipe(
{ freeze: serialJson.freeze, thaw: serial.identity.thaw },
serialResolveRequest,
{ freeze: serial.identity.freeze, thaw: serialJson.thaw },
),
serialResolved,
);
const serialResourceHashMap = serial.map(serial.request, serial.identity);
const serialNormalConstructor4 = serial.constructed(NormalModule, {
data: serial.pipe(
{ freeze: (arg, module) => module, thaw: arg => arg },
serial.created({
type: serial.identity,
request: serial.request,
userRequest: serial.request,
rawRequest: serial.request,
loaders: serial.loaders,
resource: serial.path,
parser: serial.parser,
generator: serial.generator,
resolveOptions: serial.identity,
}),
),
});
const serialNormalModuleExtra4 = {
freeze() {},
thaw(arg, frozen, extra, methods) {
extra.module = arg;
return arg;
},
};
const serialNormalIdentifier4 = {
freeze(arg, module, extra, methods) {
return serial.request.freeze(module.identifier(), null, extra, methods);
},
thaw(arg) {
return arg;
},
};
const serialNormalAssigned4 = serial.assigned({
factoryMeta: serial.identity,
issuer: serial.pipe(
{
freeze(arg, { issuer }) {
return issuer && typeof issuer === 'object'
? issuer.identifier()
: issuer;
},
thaw(arg, frozen, extra) {
return arg;
},
},
serial.request,
{
freeze(arg) {
return arg;
},
thaw(arg, frozen, { compilation }) {
if (compilation.modules) {
for (const module of compilation.modules) {
if (
module &&
typeof module.identifier === 'function' &&
module.identifier() === arg
) {
return module;
}
}
for (const cacheId in compilation.cache) {
const module = compilation.cache[cacheId];
if (
module &&
typeof module.identifier === 'function' &&
module.identifier() === arg
) {
return module;
}
}
}
return arg;
},
},
),
useSourceMap: serial.identity,
lineToLine: serial.identity,
});
const serialNormalOriginExtra4 = {
freeze() {},
thaw(arg, frozen, extra) {
if (typeof arg.issuer === 'object') {
extra.origin = arg.issuer;
}
return arg;
},
};
const serialNormalBuild4 = serial.assigned({
built: serial.identity,
buildTimestamp: serial.identity,
buildMeta: serial.identity,
buildInfo: serial.created({
assets: serial.moduleAssets,
cacheable: serial.identity,
contextDependencies: serial.pathSet,
exportsArgument: serial.identity,
fileDependencies: serial.pathSet,
harmonyModule: serial.identity,
jsonData: serial.identity,
strict: serial.identity,
}),
warnings: serial.moduleWarning,
errors: serial.moduleError,
_source: serial.source,
_buildHash: serial.identity,
hash: serial.identity,
_lastSuccessfulBuildMeta: serial.identity,
__hardSource_resolved: serialResolvedMap,
__hardSource_oldHashes: serial.pipe(
{
freeze(arg, module, extra) {
const obj = {};
const cachedMd5s = extra.compilation.__hardSourceFileMd5s;
for (const file of module.buildInfo.fileDependencies) {
obj[file] = cachedMd5s[file];
}
for (const dir of module.buildInfo.contextDependencies) {
obj[dir] = cachedMd5s[dir];
}
return obj;
},
thaw: serial.identity.thaw,
},
serialResourceHashMap,
),
});
const serialNormalError4 = {
freeze() {},
thaw(arg, module, extra) {
arg.error = arg.errors[0] || null;
return arg;
},
};
const serialNormalSourceExtra4 = {
freeze() {},
thaw(arg, module, extra) {
extra.source = arg._source;
return arg;
},
};
const serialNormalSource4 = serial.assigned({
_cachedSource: serial.source,
_cachedSourceHash: serial.identity,
renderedHash: serial.identity,
});
const serialNormalModule4PreBuild = serial.serial('NormalModule', {
constructor: serialNormalConstructor4,
setModuleExtra: serialNormalModuleExtra4,
identifier: serialNormalIdentifier4,
assigned: serialNormalAssigned4,
setOriginExtra: serialNormalOriginExtra4,
});
const serialNormalModule4PostBuild = serial.serial('NormalModule', {
build: serialNormalBuild4,
dependencyBlock: serial.dependencyBlock,
setError: serialNormalError4,
setSourceExtra: serialNormalSourceExtra4,
source: serialNormalSource4,
});
const serialNormalModule4 = serial.serial('NormalModule', {
constructor: serialNormalConstructor4,
setModuleExtra: serialNormalModuleExtra4,
identifier: serialNormalIdentifier4,
assigned: serialNormalAssigned4,
setOriginExtra: serialNormalOriginExtra4,
build: serialNormalBuild4,
dependencyBlock: serial.dependencyBlock,
setError: serialNormalError4,
setSourceExtra: serialNormalSourceExtra4,
source: serialNormalSource4,
});
const needRebuild4 = function() {
if (this.error) {
this.cacheItem.invalid = true;
this.cacheItem.invalidReason = 'error building';
return true;
}
const fileHashes = this.__hardSourceFileMd5s;
const cachedHashes = this.__hardSourceCachedMd5s;
const resolvedLast = this.__hardSource_resolved;
const missingCache = this.__hardSource_missingCache;
for (const file of this.buildInfo.fileDependencies) {
if (!cachedHashes[file] || fileHashes[file] !== cachedHashes[file]) {
this.cacheItem.invalid = true;
this.cacheItem.invalidReason = 'md5 mismatch';
return true;
}
}
for (const dir of this.buildInfo.contextDependencies) {
if (!cachedHashes[dir] || fileHashes[dir] !== cachedHashes[dir]) {
this.cacheItem.invalid = true;
this.cacheItem.invalidReason = 'md5 mismatch';
return true;
}
}
let resolvedNeedRebuild = false;
for (const _resolveKey in resolvedLast) {
const resolveKey = JSON.parse(_resolveKey);
const resolved = resolvedLast[_resolveKey];
let normalId = 'normal';
if (resolved.resolveOptions) {
normalId = `normal-${new nodeObjectHash({ sort: false }).hash(
resolved.resolveOptions,
)}`;
}
const resolvedMissing =
missingCache[normalId] &&
missingCache[normalId][
JSON.stringify([resolveKey.context, resolved.resource.split('?')[0]])
];
if (!resolvedMissing || resolvedMissing.invalid) {
resolved.invalid = true;
resolved.invalidReason = `resolved normal invalid${
resolvedMissing
? ` ${resolvedMissing.invalidReason}`
: ': resolve entry not in cache'
}`;
resolvedNeedRebuild = true;
}
}
return resolvedNeedRebuild;
};
const serialNormalModule3 = serial.serial('NormalModule', {
constructor: serial.constructed(NormalModule, {
request: serial.request,
userRequest: serial.request,
rawRequest: serial.request,
loaders: serial.loaders,
resource: serial.path,
parser: serial.parser,
}),
setModuleExtra: serialNormalModuleExtra4,
// Used internally by HardSource
identifier: serialNormalIdentifier4,
assigned: serial.assigned({
issuer: serial.pipe(
{
freeze(arg, { issuer }) {
return issuer && typeof issuer === 'object'
? issuer.identifier()
: issuer;
},
thaw(arg, frozen, extra) {
return arg;
},
},
serial.request,
{
freeze(arg) {
return arg;
},
thaw(arg, frozen, { compilation }) {
if (compilation.modules) {
for (const module of compilation.modules) {
if (
module &&
typeof module.identifier === 'function' &&
module.identifier() === arg
) {
return module;
}
}
for (const cacheId in compilation.cache) {
const module = compilation.cache[cacheId];
if (
module &&
typeof module.identifier === 'function' &&
module.identifier() === arg
) {
return module;
}
}
}
return arg;
},
},
),
useSourceMap: serial.identity,
lineToLine: serial.identity,
}),
setOriginExtra: {
freeze() {},
thaw(arg, frozen, extra) {
if (typeof arg.issuer === 'object') {
extra.origin = arg.issuer;
}
return arg;
},
},
build: serial.assigned({
built: serial.identity,
buildTimestamp: serial.identity,
cacheable: serial.identity,
meta: serial.identity,
assets: serial.moduleAssets,
fileDependencies: serial.pathArray,
contextDependencies: serial.pathArray,
harmonyModule: serial.identity,
strict: serial.identity,
exportsArgument: serial.identity,
warnings: serial.moduleWarning,
errors: serial.moduleError,
_source: serial.source,
__hardSource_resolved: serialResolvedMap,
__hardSource_oldHashes: serial.pipe(
{
freeze(arg, module, extra) {
const obj = {};
const cachedMd5s = extra.compilation.__hardSourceCachedMd5s;
for (const file of module.fileDependencies) {
obj[file] = cachedMd5s[file];
}
for (const dir of module.contextDependencies) {
obj[dir] = cachedMd5s[dir];
}
return obj;
},
thaw: serial.identity.thaw,
},
serialResourceHashMap,
),
}),
hash: {
freeze(arg, module, { compilation }, methods) {
return module.getHashDigest(compilation.dependencyTemplates);
},
thaw(arg) {
return arg;
},
},
dependencyBlock: serial.dependencyBlock,
setError: {
freeze() {},
thaw(arg, module, extra) {
arg.error = arg.errors[0] || null;
return arg;
},
},
setSourceExtra: {
freeze() {},
thaw(arg, module, extra) {
extra.source = arg._source;
return arg;
},
},
source: serial.assigned({
_cachedSource: serial.created({
source: serial.source,
hash: serial.identity,
}),
}),
});
const needRebuild3 = function() {
if (this.error) {
this.cacheItem.invalid = true;
this.cacheItem.invalidReason = 'error building';
return true;
}
const fileHashes = this.__hardSourceFileMd5s;
const cachedHashes = this.__hardSourceCachedMd5s;
const resolvedLast = this.__hardSource_resolved;
const missingCache = this.__hardSource_missingCache;
for (const file of this.fileDependencies) {
if (!cachedHashes[file] || fileHashes[file] !== cachedHashes[file]) {
this.cacheItem.invalid = true;
this.cacheItem.invalidReason = 'md5 mismatch';
return true;
}
}
for (const dir of this.contextDependencies) {
if (!cachedHashes[dir] || fileHashes[dir] !== cachedHashes[dir]) {
this.cacheItem.invalid = true;
this.cacheItem.invalidReason = 'md5 mismatch';
return true;
}
}
let resolvedNeedRebuild = false;
for (const _resolveKey in resolvedLast) {
const resolveKey = JSON.parse(_resolveKey);
const resolved = resolvedLast[_resolveKey];
let normalId = 'normal';
if (resolved.resolveOptions) {
normalId = `normal-${new nodeObjectHash({ sort: false }).hash(
resolved.resolveOptions,
)}`;
}
const resolvedMissing =
missingCache[normalId] &&
missingCache[normalId][
JSON.stringify([resolveKey.context, resolved.resource.split('?')[0]])
];
if (!resolvedMissing || resolvedMissing.invalid) {
resolved.invalid = true;
resolved.invalidReason = `resolved normal invalid${
resolvedMissing
? ` ${resolvedMissing.invalidReason}`
: ': resolve entry not in cache'
}`;
resolvedNeedRebuild = true;
}
}
return resolvedNeedRebuild;
};
const cacheable = module =>
module.buildInfo ? module.buildInfo.cacheable : module.cacheable;
class TransformNormalModulePlugin {
constructor(options) {
this.options = options || {};
}
apply(compiler) {
const schema = this.options.schema;
let serialNormalModule = serialNormalModule4;
let needRebuild = needRebuild4;
if (schema < 4) {
serialNormalModule = serialNormalModule3;
needRebuild = needRebuild3;
}
let createHash;
if (schema >= 4) {
createHash = require('webpack/lib/util/createHash');
}
let freeze;
let mapFreeze;
let _methods;
pluginCompat.tap(
compiler,
'_hardSourceMethods',
'TransformNormalModulePlugin',
methods => {
_methods = methods;
// store = methods.store;
// fetch = methods.fetch;
freeze = methods.freeze;
// thaw = methods.thaw;
mapFreeze = methods.mapFreeze;
// mapThaw = methods.mapThaw;
},
);
pluginCompat.tap(
compiler,
'compilation',
'TransformNormalModulePlugin',
compilation => {
pluginCompat.tap(
compilation,
'succeedModule',
'TransformNormalModulePlugin',
module => {
if (module instanceof NormalModule) {
try {
module._dependencyBlock = freeze(
'DependencyBlock',
null,
module,
{
module,
parent: module,
compilation,
},
);
} catch (e) {
logMessages.moduleFreezeError(compilation, module, e);
}
}
},
);
},
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeModule',
'TransformNormalModulePlugin',
(frozen, module, extra) => {
// Set hash if it was not set.
if (
schema === 4 &&
module instanceof NormalModule &&
module.buildTimestamp &&
!module.hash
) {
const outputOptions = extra.compilation.outputOptions;
const hashFunction = outputOptions.hashFunction;
const hashDigest = outputOptions.hashDigest;
const hashDigestLength = outputOptions.hashDigestLength;
if (module.buildInfo && module._initBuildHash) {
module._initBuildHash(extra.compilation);
}
const moduleHash = createHash(hashFunction);
module.updateHash(moduleHash);
module.hash = moduleHash.digest(hashDigest);
module.renderedHash = module.hash.substr(0, hashDigestLength);
if (module._cachedSource) {
module._cachedSourceHash = module.getHashDigest(
extra.compilation.dependencyTemplates,
);
}
}
if (
module.request &&
(cacheable(module) || !module.built) &&
module instanceof NormalModule &&
(!frozen ||
(schema >= 4 && module.hash !== frozen.build.hash) ||
(schema < 4 &&
module.getHashDigest(extra.compilation.dependencyTemplates) !==
frozen.hash))
) {
const compilation = extra.compilation;
if (module.cacheItem) {
module.cacheItem.invalid = false;
module.cacheItem.invalidReason = null;
}
let serialModule = serialNormalModule;
if (!module.built) {
serialModule = serialNormalModule4PreBuild;
}
const f = serialModule.freeze(
null,
module,
{
module,
compilation,
},
_methods,
);
// The saved dependencies may not be the ones derived in the hash. This is
// alright, in such a case the dependencies were altered before the source
// was rendered. The dependencies should be modified a second time, if
// they are in the same way they'll match. If they are not modified in the
// same way, then it'll correctly rerender.
if (module._dependencyBlock) {
f.dependencyBlock = module._dependencyBlock;
}
return f;
}
return frozen;
},
);
pluginCompat.tap(
compiler,
'_hardSourceThawModule',
'TransformNormalModulePlugin thaw',
(module, frozen, { compilation, normalModuleFactory }) => {
if (frozen.type === 'NormalModule') {
let m;
if (module === null) {
let serialModule = serialNormalModule;
if (!frozen.build || !frozen.build.built) {
serialModule = serialNormalModule4PreBuild;
}
m = serialModule.thaw(
null,
frozen,
{
state: { imports: {} },
compilation: compilation,
normalModuleFactory: normalModuleFactory,
},
_methods,
);
} else {
m = serialNormalModule4PostBuild.thaw(
module,
frozen,
{
state: { imports: {} },
compilation: compilation,
normalModuleFactory: normalModuleFactory,
},
_methods,
);
}
m.cacheItem = frozen;
m.__hardSourceFileMd5s = compilation.__hardSourceFileMd5s;
m.__hardSourceCachedMd5s = compilation.__hardSourceCachedMd5s;
m.__hardSource_missingCache = compiler.__hardSource_missingCache;
m.needRebuild = needRebuild;
// Unbuild if there is no cache. The module will be rebuilt. Not
// unbuilding will lead to double dependencies.
if (m.built && schema === 4 && !compilation.cache) {
m.unbuild();
}
// Side load into the cache if something for this identifier isn't already
// there.
else if (
m.built &&
compilation.cache &&
!compilation.cache[`m${m.identifier()}`]
) {
compilation.cache[`m${m.identifier()}`] = m;
}
return m;
}
return module;
},
);
}
}
module.exports = TransformNormalModulePlugin;
-162
View File
@@ -1,162 +0,0 @@
const relateContext = require('./util/relate-context');
const pluginCompat = require('./util/plugin-compat');
const ParserSchemas3 = [['Parser', 'options']];
const ParserSchemas4 = [
['JsonParser', 'options'],
['Parser', 'options', 'sourceType'],
['WebAssemblyParser', 'options'],
];
try {
ParserSchemas3[0].Parser = require('webpack/lib/Parser');
} catch (_) {}
try {
ParserSchemas4[0].Parser = require('webpack/lib/JsonParser');
ParserSchemas4[1].Parser = require('webpack/lib/Parser');
try {
ParserSchemas4[2].Parser = require('webpack/lib/WebAssemblyParser');
} catch (_) {
ParserSchemas4[2].Parser = require('webpack/lib/wasm/WebAssemblyParser');
}
} catch (_) {}
const freezeArgument = {};
const thawArgument = {};
function freezeParser(parser, extra, methods) {
const schemas = extra.schemas;
for (let i = 0; i < schemas.length; i++) {
if (parser.constructor === schemas[i].Parser) {
const frozen = {
type: schemas[i][0],
};
for (let j = 1; j < schemas[i].length; j++) {
let arg = parser[schemas[i][j]];
if (freezeArgument[schemas[i][j]]) {
arg = freezeArgument[schemas[i][j]](arg, parser, extra, methods);
}
frozen[schemas[i][j]] = arg;
}
return frozen;
}
}
}
function thawParser(frozen, extra, methods) {
const schemas = extra.schemas;
for (let i = 0; i < schemas.length; i++) {
if (frozen.type === schemas[i][0]) {
const Parser = schemas[i].Parser;
const args = [];
for (let j = 1; j < schemas[i].length; j++) {
let arg = frozen[schemas[i][j]];
if (thawArgument[schemas[i][j]]) {
arg = thawArgument[schemas[i][j]](arg, frozen, extra, methods);
}
args.push(arg);
}
try {
return new Parser(...args);
} catch (_) {
return new (Function.prototype.bind.apply(
Parser,
[null].concat(args),
))();
}
}
}
}
class TransformParserPlugin {
constructor(options) {
this.options = options || {};
}
apply(compiler) {
const schema = this.options.schema;
let schemas = ParserSchemas4;
if (schema < 4) {
schemas = ParserSchemas3;
}
pluginCompat.register(
compiler,
'_hardSourceBeforeFreezeParser',
'syncWaterfall',
['frozen', 'item', 'extra'],
);
pluginCompat.register(
compiler,
'_hardSourceFreezeParser',
'syncWaterfall',
['frozen', 'item', 'extra'],
);
pluginCompat.register(
compiler,
'_hardSourceAfterFreezeParser',
'syncWaterfall',
['frozen', 'item', 'extra'],
);
pluginCompat.register(
compiler,
'_hardSourceBeforeThawParser',
'syncWaterfall',
['item', 'frozen', 'extra'],
);
pluginCompat.register(compiler, '_hardSourceThawParser', 'syncWaterfall', [
'item',
'frozen',
'extra',
]);
pluginCompat.register(
compiler,
'_hardSourceAfterThawParser',
'syncWaterfall',
['item', 'frozen', 'extra'],
);
let methods;
pluginCompat.tap(
compiler,
'_hardSourceMethods',
'TransformParserPlugin',
_methods => {
methods = _methods;
},
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeParser',
'TransformParserPlugin freeze',
(frozen, parser, extra) => {
extra.schemas = schemas;
frozen = freezeParser(parser, extra, methods);
if (schema === 4) {
frozen.moduleType = extra.module.type;
}
return frozen;
},
);
pluginCompat.tap(
compiler,
'_hardSourceThawParser',
'TransformParserPlugin thaw',
(parser, { options, moduleType }, { normalModuleFactory }) => {
if (schema < 4) {
return normalModuleFactory.getParser(options);
} else {
return normalModuleFactory.getParser(moduleType, options);
}
},
);
}
}
module.exports = TransformParserPlugin;
-225
View File
@@ -1,225 +0,0 @@
const relateContext = require('./util/relate-context');
const pluginCompat = require('./util/plugin-compat');
const SourceSchemas3 = [
['CachedSource', 'source'],
['ConcatSource'],
['LineToLineMappedSource', 'value', 'name', 'originalSource'],
['OriginalSource', 'value', 'name'],
['RawSource', 'value'],
['ReplaceSource', 'source', 'name'],
[
'SourceMapSource',
'value',
'name',
'sourceMap',
'originalSource',
'innerSourceMap',
],
];
try {
SourceSchemas3[0].Source = require('webpack-sources/lib/CachedSource');
} catch (_) {}
try {
SourceSchemas3[1].Source = require('webpack-sources/lib/ConcatSource');
} catch (_) {}
try {
SourceSchemas3[2].Source = require('webpack-sources/lib/LineToLineMappedSource');
} catch (_) {}
try {
SourceSchemas3[3].Source = require('webpack-sources/lib/OriginalSource');
} catch (_) {}
try {
SourceSchemas3[4].Source = require('webpack-sources/lib/RawSource');
} catch (_) {}
try {
SourceSchemas3[5].Source = require('webpack-sources/lib/ReplaceSource');
} catch (_) {}
try {
SourceSchemas3[6].Source = require('webpack-sources/lib/SourceMapSource');
} catch (_) {}
const freezeArgument = {
value(arg, { _value }, extra, methods) {
return _value;
},
name(arg, { _name }, { compilation }, methods) {
try {
return relateContext.relateNormalPath(compilation.compiler, _name);
} catch (e) {
console.error(e.stack);
process.exit();
}
},
sourceMap(arg, { _sourceMap }, extra, methods) {
return _sourceMap;
},
originalSource(arg, { _originalSource }, extra, methods) {
return _originalSource;
},
innerSourceMap(arg, { _innerSourceMap }, extra, methods) {
return _innerSourceMap;
},
source(arg, { constructor, _source }, extra, methods) {
if (constructor.name === 'ReplaceSource') {
return;
}
return methods.freeze('Source', null, _source, extra);
},
};
const thawArgument = {
name(arg, source, { compilation }, methods) {
try {
return relateContext.contextNormalPath(compilation.compiler, arg);
} catch (e) {
console.error(e.stack);
process.exit();
}
},
source(arg, { type }, extra, methods) {
if (type === 'ReplaceSource') {
return extra.source;
}
return methods.thaw('Source', null, arg, extra);
},
value(arg, frozen, extra, methods) {
if (arg && arg.type === 'Buffer') {
return new Buffer(arg.data);
}
return arg;
},
};
function freezeSource(source, extra, methods) {
const schemas = extra.schemas;
for (let i = 0; i < schemas.length; i++) {
if (source.constructor.name === schemas[i].Source.name) {
const frozen = {
type: schemas[i][0],
};
for (let j = 1; j < schemas[i].length; j++) {
let arg = source[schemas[i][j]];
if (freezeArgument[schemas[i][j]]) {
arg = freezeArgument[schemas[i][j]](arg, source, extra, methods);
}
frozen[schemas[i][j]] = arg;
}
return frozen;
}
}
throw new Error(`Unfrozen ${source.constructor.name}.`);
}
function thawSource(frozen, extra, methods) {
const schemas = extra.schemas;
for (let i = 0; i < schemas.length; i++) {
if (frozen.type === schemas[i][0]) {
const Source = schemas[i].Source;
const args = [];
for (let j = 1; j < schemas[i].length; j++) {
let arg = frozen[schemas[i][j]];
if (thawArgument[schemas[i][j]]) {
arg = thawArgument[schemas[i][j]](arg, frozen, extra, methods);
}
args.push(arg);
}
try {
return new Source(...args);
} catch (_) {
return new (Function.prototype.bind.apply(
Source,
[null].concat(args),
))();
}
}
}
}
class TransformSourcePlugin {
apply(compiler) {
let methods;
pluginCompat.tap(
compiler,
'_hardSourceMethods',
'TransformSourcePlugin',
_methods => {
methods = _methods;
},
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeSource',
'TransformSourcePlugin freeze',
(frozen, source, extra) => {
if (typeof source === 'string') {
return {
type: 'String',
value: source,
};
} else if (Buffer.isBuffer && Buffer.isBuffer(source)) {
// Serialization layer might transform it into JSON or handle it as binary
// data
return source;
}
extra.schemas = SourceSchemas3;
frozen = freezeSource(source, extra, methods);
if (frozen.type === 'ReplaceSource') {
frozen.replacements = source.replacements;
} else if (frozen.type === 'CachedSource') {
frozen.cachedSource = source._cachedSource;
frozen.cachedSize = source._cachedSize;
frozen.cachedMaps = source._cachedMaps;
} else if (frozen.type === 'ConcatSource') {
frozen.children = methods.mapFreeze(
'Source',
null,
source.children,
extra,
);
}
return frozen;
},
);
pluginCompat.tap(
compiler,
'_hardSourceThawSource',
'TransformSourcePlugin thaw',
(source, frozen, extra) => {
if (frozen.type === 'String') {
return frozen.value;
} else if (frozen.type === 'Buffer') {
return new Buffer(frozen.data);
} else if (Buffer.isBuffer && Buffer.isBuffer(frozen)) {
return frozen;
}
extra.schemas = SourceSchemas3;
source = thawSource(frozen, extra, methods);
if (frozen.type === 'ReplaceSource') {
source.replacements = frozen.replacements;
} else if (frozen.type === 'CachedSource') {
source._cachedSource = frozen.cachedSource;
source._cachedSize = frozen.cachedSize;
source._cachedMaps = frozen.cachedMaps;
} else if (frozen.type === 'ConcatSource') {
source.children = methods.mapThaw(
'Source',
null,
frozen.children,
extra,
);
}
return source;
},
);
}
}
module.exports = TransformSourcePlugin;
-30
View File
@@ -1,30 +0,0 @@
const crypto = require('crypto');
const path = require('path');
const nodeObjectHash = require('node-object-hash');
const sort = nodeObjectHash({
sort: false,
}).sort;
function relateContextToCacheDir(config) {
const hardSourcePlugin = config.plugins.find(
({ constructor }) => constructor.name === 'HardSourceWebpackPlugin',
);
const cacheDir = hardSourcePlugin.getCachePath();
const context = path.resolve(process.cwd(), config.context);
const clone = Object.assign({}, config, {
context: path.relative(cacheDir, context),
});
const sorted = sort(clone)
.replace(new RegExp(`${context}[^,\\]}]*`, 'g'), match =>
path.relative(cacheDir, match),
)
.replace(/\\/g, '/');
return crypto
.createHash('sha256')
.update(sorted)
.digest('hex');
}
module.exports = relateContextToCacheDir;
-149
View File
@@ -1,149 +0,0 @@
// - scan dirs
// - stat items
// - hash files
// - stat dir items under
// - hash files
// - hash files
const crypto = require('crypto');
const fs = require('graceful-fs');
const path = require('path');
const pkgDir = require('pkg-dir');
const promisify = require('./util/promisify');
const readFile = promisify(fs.readFile);
const readdir = promisify(fs.readdir);
const stat = promisify(fs.stat);
function hashFile(file) {
return readFile(file)
.then(src => [
file,
crypto
.createHash('md5')
.update(src)
.digest('hex'),
])
.catch(() => {});
}
function hashObject(obj) {
const hash = crypto.createHash('md5');
obj.forEach(item => {
hash.update(item[0]);
hash.update(item[1]);
});
return hash.digest('hex');
}
function hashFiles(root, files) {
return Promise.all(files.map(file => hashFile(path.join(root, file)))).then(
hashes => hashes.filter(Boolean),
);
}
function flatten(items) {
return (items || []).reduce(
(carry, item) => (item ? carry.concat(item) : carry),
[],
);
}
const inputs = async ({ files, directories, root = process.cwd() } = {}) => {
let defaults;
if (!files && !directories) {
const lockFiles = (await Promise.all(
['package-lock.json', 'yarn.lock'].map(f =>
stat(path.join(root, f)).then(() => f, () => null),
),
)).filter(Boolean);
if (lockFiles.length) {
return lockFiles;
}
}
if (!files) {
files = ['package.json'];
}
if (!directories) {
directories = ['node_modules'];
}
directories = directories.map(d => `${d}/*`);
return flatten([files, directories]);
};
module.exports = options => {
options = options || {};
const root = options.root || pkgDir.sync(process.cwd());
let files = options.files;
let directories = options.directories;
let hashDefaults = Promise.resolve();
if (!files && !directories) {
hashDefaults = hashFiles(root, ['package-lock.json', 'yarn.lock']);
}
return hashDefaults
.then(_defaults => {
if (_defaults && _defaults.length > 0) {
return [_defaults];
} else {
if (!files) {
files = ['package.json'];
}
if (!directories) {
directories = ['node_modules'];
}
}
return Promise.all([
hashFiles(root, files),
Promise.all(
directories.map(dir =>
readdir(path.join(root, dir))
.then(items =>
Promise.all(
items.map(item =>
stat(path.join(root, dir, item))
.then(stat => {
if (stat.isDirectory()) {
return hashFiles(path.join(root, dir, item), files);
}
if (stat.isFile()) {
return hashFile(path.join(root, dir, item)).then(
hash => (hash ? [hash] : hash),
);
}
})
.catch(function(...args) {
console.error(args);
}),
),
).then(hashes => hashes.filter(Boolean)),
)
.catch(() => {})
.then(flatten),
),
).then(flatten),
]);
})
.then(flatten)
.then(items => {
items.forEach(item => {
item[0] = path.relative(root, item[0]);
});
// console.log(items);
items.sort((a, b) => {
if (a[0] < b[0]) {
return -1;
} else if (a[0] > b[0]) {
return 1;
}
return 0;
});
return hashObject(items);
});
};
module.exports.inputs = inputs;
-219
View File
@@ -1,219 +0,0 @@
/**
* The LoggerFactory wraps a hard source plugin exposed on the webpack Compiler.
*
* The plugin handle, `'hard-source-log'` takes one object as input and should
* log it to the console, disk, or somewhere. Or not if it the message should
* be ignored. The object has a few arguments that generally follows this
* structure. The `data` key will generally have an `id` value.
*
* ```js
* {
* from: 'core',
* level: 'error',
* message: 'HardSourceWebpackPlugin requires a cacheDirectory setting.',
* data: {
* id: 'need-cache-directory-option'
* }
* }
* ```
*
* So a simple plugin handle may be
*
* ```js
* compiler.plugin('hard-source-log', function(message) {
* console[message.level].call(
* console,
* 'hard-source:' + message.from, message.message
* );
* });
* ```
*
* @module hard-source-webpack-plugin/logger-factory
* @author Michael "Z" Goddard <mzgoddard@gmail.com>
*/
const pluginCompat = require('./util/plugin-compat');
const LOGGER_SEPARATOR = ':';
const DEFAULT_LOGGER_PREFIX = 'hard-source';
const LOGGER_FACTORY_COMPILER_KEY = `${__dirname}/hard-source-logger-factory-compiler-key`;
/**
* @constructor Logger
* @memberof module:hard-source-webpack-plugin/logger-factory
*/
class Logger {
constructor(compiler) {
this.compiler = compiler;
this._lock = null;
}
/**
* @method lock
* @memberof module:hard-source-webpack-plugin/logger-factory~Logger#
*/
lock() {
this._lock = [];
}
/**
* @method unlock
* @memberof module:hard-source-webpack-plugin/logger-factory~Logger#
*/
unlock() {
const _this = this;
if (_this._lock) {
const lock = _this._lock;
_this._lock = null;
lock.forEach(value => {
_this.write(value);
});
}
}
/**
* @method write
* @memberof module:hard-source-webpack-plugin/logger-factory~Logger#
*/
write(value) {
if (this._lock) {
return this._lock.push(value);
}
if (this.compiler.hooks && this.compiler.hooks.hardSourceLog.taps.length) {
this.compiler.hooks.hardSourceLog.call(value);
} else if (
this.compiler._plugins &&
this.compiler._plugins['hard-source-log'] &&
this.compiler._plugins['hard-source-log'].length
) {
(this.compiler.applyPlugins1 || this.compiler.applyPlugins).call(
this.compiler,
'hard-source-log',
value,
);
} else {
console.error(
`[${DEFAULT_LOGGER_PREFIX}${LOGGER_SEPARATOR}${value.from}]`,
value.message,
);
}
}
/**
* @method from
* @memberof module:hard-source-webpack-plugin/logger-factory~Logger#
*/
from(name) {
return new LoggerFrom(this, name);
}
}
/**
* @constructor LoggerFrom
* @memberof module:hard-source-webpack-plugin/logger-factory
*/
class LoggerFrom {
constructor(logger, from) {
this._logger = logger;
this._from = from;
}
/**
* @method from
* @memberof module:hard-source-webpack-plugin/logger-factory~LoggerFrom#
*/
from(name) {
return new LoggerFrom(this._logger, this._from + LOGGER_SEPARATOR + name);
}
/**
* @method _write
* @memberof module:hard-source-webpack-plugin/logger-factory~LoggerFrom#
*/
_write(level, data, message) {
this._logger.write({
from: this._from,
level,
message,
data,
});
}
/**
* @method error
* @memberof module:hard-source-webpack-plugin/logger-factory~LoggerFrom#
*/
error(data, message) {
this._write('error', data, message);
}
/**
* @method warn
* @memberof module:hard-source-webpack-plugin/logger-factory~LoggerFrom#
*/
warn(data, message) {
this._write('warn', data, message);
}
/**
* @method info
* @memberof module:hard-source-webpack-plugin/logger-factory~LoggerFrom#
*/
info(data, message) {
this._write('info', data, message);
}
/**
* @method log
* @memberof module:hard-source-webpack-plugin/logger-factory~LoggerFrom#
*/
log(data, message) {
this._write('log', data, message);
}
/**
* @method debug
* @memberof module:hard-source-webpack-plugin/logger-factory~LoggerFrom#
*/
debug(data, message) {
this._write('debug', data, message);
}
}
/**
* @constructor LoggerFactory
* @memberof module:hard-source-webpack-plugin/logger-factory
*/
class LoggerFactory {
constructor(compiler) {
this.compiler = compiler;
pluginCompat.register(compiler, 'hardSourceLog', 'sync', ['data']);
}
/**
* @method create
* @memberof module:hard-source-webpack-plugin/logger-factory~LoggerFactory#
*/
create() {
const compiler = this.compiler;
if (!compiler[LOGGER_FACTORY_COMPILER_KEY]) {
compiler[LOGGER_FACTORY_COMPILER_KEY] = new Logger(this.compiler);
}
return compiler[LOGGER_FACTORY_COMPILER_KEY];
}
}
/**
* @function getLogger
* @memberof module:hard-source-webpack-plugin/logger-factory~LoggerFactory.
*/
LoggerFactory.getLogger = compilation => {
while (compilation.compiler.parentCompilation) {
compilation = compilation.compiler.parentCompilation;
}
return new LoggerFactory(compilation.compiler).create();
};
module.exports = LoggerFactory;
-561
View File
@@ -1,561 +0,0 @@
/** prelude
const serial = require('../util/serial');
const relateContext = require('../util/relate-context');
const LocalModule = require('webpack/lib/dependencies/LocalModule');
function flattenPrototype(obj) {
if (typeof obj === 'string') {
return obj;
}
const copy = {};
for (const key in obj) {
copy[key] = obj[key];
}
return copy;
}
const assignTruthful = {
freeze(arg, dependency) {
return arg;
},
thaw(arg, frozen) {
return arg;
},
};
const assignDefined = {
freeze(arg, dependency) {
if (typeof arg !== 'undefined') {
return arg;
}
},
thaw(arg, frozen) {
if (typeof arg !== 'undefined') {
return arg;
}
},
}
const optional = serial.assigned({
prepend: assignTruthful,
replaces: assignTruthful,
critical: assignTruthful,
namespaceObjectAsContext: assignDefined,
callArgs: assignDefined,
call: assignDefined,
directImport: assignDefined,
shorthand: assignDefined,
optional: assignTruthful,
loc: {
freeze(arg, dependency) {
return flattenPrototype(dependency.loc);
},
thaw(arg, frozen) {
return arg;
},
},
});
const localModuleAssigned = {
freeze(_, dependency) {
if (
typeof dependency.localModule === 'object' &&
dependency.localModule !== null
) {
return {
name: dependency.localModule.name,
idx: dependency.localModule.idx,
used: dependency.localModule.used,
};
}
},
thaw(thawed, localModule, extra) {
const state = extra.state;
if (
typeof localModule === 'object' &&
localModule !== null
) {
if (!state.localModules) {
state.localModules = [];
}
if (!state.localModules[localModule.idx]) {
state.localModules[localModule.idx] = new LocalModule(
extra.module,
localModule.name,
localModule.idx,
);
state.localModules[localModule.idx].used =
localModule.used;
}
thawed.localModule = state.localModules[localModule.idx];
}
return thawed;
},
};
const warnings = {
freeze(frozen, dependency) {
if (frozen && dependency.getWarnings) {
const warnings = dependency.getWarnings();
if (warnings && warnings.length) {
return warnings.map(
({ stack }) =>
stack.includes('\n at Object.freeze')
? stack.split('\n at Object.freeze')[0]
: stack.includes('\n at pluginCompat.tap')
? stack.split('\n at pluginCompat.tap')[0]
: stack.split('\n at Compiler.pluginCompat.tap')[0],
);
}
}
},
thaw(dependency, warnings) {
if (dependency && warnings && dependency.getWarnings) {
const frozenWarnings = warnings;
const _getWarnings = dependency.getWarnings;
dependency.getWarnings = function() {
const warnings = _getWarnings.call(this);
if (warnings && warnings.length) {
return warnings.map((warning, i) => {
const stack = warning.stack.split(
'\n at Compilation.reportDependencyErrorsAndWarnings',
)[1];
warning.stack = `${
frozenWarnings[i]
}\n at Compilation.reportDependencyErrorsAndWarnings${stack}`;
return warning;
});
}
return warnings;
};
}
return dependency;
},
};
**/
const constructorArguments = {
/** dependencies
dependencies: {
freeze(arg, dependency, extra, methods) {
return methods.mapFreeze('Dependency', null, arg, extra);
},
thaw(arg, frozen, extra, methods) {
return methods.mapThaw('Dependency', null, arg, extra);
},
},
**/
/** freeze dependencies
dependencies: methods.mapFreeze('Dependency', null, dependency.dependencies, extra),
**/
/** thaw dependencies
methods.mapThaw('Dependency', null, frozen.dependencies, extra),
**/
/** depsArray
depsArray: {
freeze(arg, dependency, extra, methods) {
return methods.mapFreeze('Dependency', null, arg, extra);
},
thaw(arg, frozen, extra, methods) {
return methods.mapThaw('Dependency', null, arg, extra);
},
},
**/
/** freeze depsArray
depsArray: methods.mapFreeze('Dependency', null, dependency.depsArray, extra),
**/
/** thaw depsArray
methods.mapThaw('Dependency', null, frozen.depsArray, extra),
**/
/** localModule
localModule: {
freeze({ name, idx }, dependency, extra, methods) {
return {
name: name,
idx: idx,
};
},
thaw({ idx, name, used }, frozen, extra, methods) {
const state = extra.state;
if (!state.localModules) {
state.localModules = [];
}
if (!state.localModules[idx]) {
state.localModules[idx] = new LocalModule(extra.module, name, idx);
state.localModules[idx].used = used;
}
return state.localModules[idx];
},
},
**/
/** freeze localModule
localModule: {
name: dependency.localModule.name,
name: dependency.localModule.idx,
},
**/
/** thaw prep localModule
if (!extra.state.localModules) {
extra.state.localModules = [];
}
if (!extra.state.localModules[frozen.localModule.idx]) {
extra.state.localModules[frozen.localModule.idx] = new LocalModule(extra.module, frozen.localModule.name, frozen.localModule.idx);
extra.state.localModules[frozen.localModule.idx].used = frozen.localModule.used;
}
**/
/** thaw localModule
extra.state.localModules[frozen.localModule.idx],
**/
/** regExp
regExp: {
freeze(arg, dependency, extra, methods) {
return arg ? arg.source : false;
},
thaw(arg, frozen, extra, methods) {
return arg ? new RegExp(arg) : arg;
},
},
**/
/** freeze regExp
regExp: dependency.regExp ? dependency.regExp.source : false,
**/
/** thaw regExp
frozen.regExp ? new RegExp(frozen.regExp) : frozen.regExp,
**/
/** request
request: {
freeze(arg, dependency, extra, methods) {
return relateContext.relateAbsoluteRequest(extra.module.context, arg);
},
thaw(arg, dependency, extra, methods) {
return arg;
// return relateContext.contextNormalRequest(extra.compilation.compiler, arg);
},
},
**/
/** freeze request
request: relateContext.relateAbsoluteRequest(extra.module.context, dependency.request),
**/
/** thaw request
frozen.request,
**/
/** userRequest
userRequest: {
freeze(arg, dependency, extra, methods) {
return relateContext.relateAbsoluteRequest(extra.module.context, arg);
},
thaw(arg, dependency, extra, methods) {
return arg;
// return relateContext.contextNormalRequest(extra.compilation.compiler, arg);
},
},
**/
/** freeze userRequest
userRequest: relateContext.relateAbsoluteRequest(extra.module.context, dependency.userRequest),
**/
/** thaw userRequest
frozen.userRequest,
**/
/** block
block: {
freeze(arg, dependency, extra, methods) {
// Dependency nested in a parent. Freezing the block is a loop.
if (arg.dependencies.includes(dependency)) {
return;
}
return methods.freeze('DependencyBlock', null, arg, extra);
},
thaw(arg, frozen, extra, methods) {
// Not having a block, means it needs to create a cycle and refer to its
// parent.
if (!arg) {
return extra.parent;
}
return methods.thaw('DependencyBlock', null, arg, extra);
},
},
**/
/** freeze block
block: !dependency.block.dependencies.includes(dependency) ?
methods.freeze('DependencyBlock', null, dependency.block, extra) :
undefined,
**/
/** thaw block
!frozen.block ? extra.parent : methods.thaw('DependencyBlock', null, frozen.block, extra),
**/
/** importDependency
importDependency: {
freeze(arg, dependency, extra, methods) {
return methods.freeze('Dependency', null, arg, extra);
},
thaw(arg, frozen, extra, methods) {
return methods.thaw('Dependency', null, arg, extra);
},
},
**/
/** freeze importDependency
importDependency: methods.freeze('Dependency', null, dependency.importDependency, extra),
**/
/** thaw importDependency
methods.thaw('Dependency', null, frozen.importDependency, extra),
**/
/** originModule
originModule: {
freeze(arg, dependency, extra, methods) {
// This will be in extra, generated or found during the process of thawing.
},
thaw(arg, frozen, extra, methods) {
return extra.module;
},
},
**/
/** freeze originModule
originModule: null,
**/
/** thaw originModule
extra.module,
**/
/** activeExports
activeExports: {
freeze(arg, dependency, extra, methods) {
return null;
},
thaw(arg, { name }, { state }, methods) {
state.activeExports = state.activeExports || new Set();
if (name) {
state.activeExports.add(name);
}
return state.activeExports;
},
},
**/
/** freeze activeExports
activeExports: null,
**/
/** thaw prep activeExports
extra.state.activeExports = extra.state.activeExports || new Set();
if (frozen.name) {
extra.state.activeExports.add(frozen.name);
}
**/
/** thaw activeExports
extra.state.activeExports,
**/
/** otherStarExports
otherStarExports: {
freeze(arg, dependency, extra, methods) {
if (arg) {
// This will be in extra, generated during the process of thawing.
return 'star';
}
return null;
},
thaw(arg, frozen, { state }, methods) {
if (arg === 'star') {
return state.otherStarExports || [];
}
return null;
},
},
**/
/** freeze otherStarExports
otherStarExports: dependency.otherStarExports ? 'star' : null,
**/
/** thaw otherStarExports
frozen.otherStarExports === 'star' ?
(extra.state.otherStarExports || []) :
null,
**/
/** options
options: {
freeze(arg, dependency, extra, methods) {
if (arg.regExp) {
return Object.assign({}, arg, {
regExp: arg.regExp.source,
});
}
return arg;
},
thaw(arg, frozen, extra, methods) {
if (arg.regExp) {
return Object.assign({}, arg, {
regExp: new RegExp(arg.regExp),
});
}
return arg;
},
},
**/
/** freeze options
options: dependency.options.regExp ?
Object.assign({}, dependency.options, {
regExp: dependency.options.regExp.source,
}) :
dependency.options,
**/
/** thaw options
frozen.options.regExp ?
Object.assign({}, frozen.options, {
regExp: new RegExp(frozen.options.regExp),
}) :
frozen.options,
**/
/** parserScope
parserScope: {
freeze(arg, dependencies, extra, methods) {
return;
},
thaw(arg, frozen, { state }, methods) {
state.harmonyParserScope = state.harmonyParserScope || {};
return state.harmonyParserScope;
},
},
**/
/** freeze parserScope
parserScope: null,
**/
/** thaw prep parserScope
extra.state.harmonyParserScope = extra.state.harmonyParserScope || {};
**/
/** thaw parserScope
extra.state.harmonyParserScope,
**/
};
/** importDependencyState
importDependency: {
freeze(frozen) {
return frozen;
},
thaw(thawed, frozen, extra) {
const state = extra.state;
const ref = frozen.range.toString();
if (state.imports[ref]) {
return state.imports[ref];
}
state.imports[ref] = thawed;
return thawed;
},
},
**/
/** exportImportedDependencyState
exportImportedDependency: {
freeze(frozen) {},
thaw(thawed, frozen, extra) {
if (thawed.otherStarExports) {
extra.state.otherStarExports = (
extra.state.otherStarExports || []
).concat(thawed);
}
return thawed;
},
},
**/
const fs = require('graceful-fs');
const path = require('path');
const generateRaw = fs.readFileSync(path.join(__dirname, '_generate.js'), 'utf8');
const generateBlocks = generateRaw
.split(/((?:\/\*\*)((?!\*\*\/)[^\r\n]*\r?\n)+)/g)
.filter(Boolean)
.filter(str => !str.startsWith('**/'))
.reduce((carry, item, index) => index % 2 === 0 ? [...carry, item] : carry, []);
const getBlock = name => {
let lines = generateBlocks
.find(block => block.startsWith(`/** ${name}`));
if (lines) {
lines = lines.split('\n');
lines = lines.slice(1, lines.length - 1);
}
return lines || [];
};
const dependencyInfo = require('./basic-dependency.json');
let output = getBlock('prelude');
for (const dependency of dependencyInfo) {
const DepName = dependency[0];
const depName = DepName[0].toLowerCase() + DepName.slice(1);
const DepNameSerial = `${DepName}Serial`;
output.push(`const ${dependency[0]} = require('webpack/lib/dependencies/${dependency[0]}');`);
output.push(`const ${DepNameSerial} = serial.serial('${DepName}', {`);
// output.push(` constructor: serial.constructed(${DepName}, {`);
// for (const argument of dependency.slice(1)) {
// let block = getBlock(argument);
// if (!block.length) {
// block = [` ${argument}: serial.identity,`];
// }
// output.push(...block);
// }
// output.push(` }),`);
output.push(` constructor: {`);
output.push(` freeze(_, dependency, extra, methods) {`);
output.push(` return {`);
for (const argument of dependency.slice(1)) {
let block = getBlock(`freeze ${argument}`);
if (!block.length) {
block = [` ${argument}: dependency.${argument},`];
}
output.push(...block);
}
output.push(` };`);
output.push(` },`);
output.push(` thaw(thawed, frozen, extra, methods) {`);
for (const argument of dependency.slice(1)) {
let block = getBlock(`thaw prep ${argument}`);
output.push(...block);
}
output.push(` return new ${DepName}(`);
for (const argument of dependency.slice(1)) {
let block = getBlock(`thaw ${argument}`);
if (!block.length) {
block = [` frozen.${argument},`];
}
output.push(...block);
}
output.push(` );`);
output.push(` },`);
output.push(` },`);
output.push(``);
output.push(` optional,`);
if (DepName === 'AMDDefineDependency' || DepName === 'LocalModuleDependency') {
output.push(``);
output.push(` localModuleAssigned,`);
}
output.push(``);
output.push(` warnings,`);
if (DepName === 'HarmonyImportDependency') {
output.push(``);
output.push(...getBlock('importDependencyState'));
}
if (DepName === 'HarmonyExportImportedSpecifierDependency') {
output.push(``);
output.push(...getBlock('exportImportedDependencyState'));
}
output.push(`});`);
output.push(``);
}
output.push(`exports.map = new Map();`);
for (const dependency of dependencyInfo) {
const DepName = dependency[0];
const DepNameSerial = `${DepName}Serial`;
output.push(`exports.${DepName} = ${DepNameSerial};`);
output.push(`exports.map.set(${DepName}, ${DepNameSerial});`);
}
output.push(``);
require('graceful-fs').writeFileSync(require('path').join(__dirname, 'index.js'), output.join('\n'), 'utf8');
@@ -1,103 +0,0 @@
[
[
"AMDDefineDependency",
"range",
"arrayRange",
"functionRange",
"objectRange",
"namedModule"
],
["AMDRequireArrayDependency", "depsArray", "range"],
["AMDRequireContextDependency", "options", "range", "valueRange"],
["AMDRequireDependency", "block"],
["AMDRequireItemDependency", "request", "range"],
["CommonJsRequireContextDependency", "options", "range", "valueRange"],
["CommonJsRequireDependency", "request", "range"],
["ConstDependency", "expression", "range", "requireWebpackRequire"],
["ContextDependency", "options"],
["ContextElementDependency", "request", "userRequest"],
["CriticalDependencyWarning", "message"],
["DelegatedExportsDependency", "originModule", "exports"],
["DelegatedSourceDependency", "request"],
["DllEntryDependency", "dependencies", "name"],
["HarmonyAcceptDependency", "range", "dependencies", "hasCallback"],
["HarmonyAcceptImportDependency", "request", "originModule", "parserScope"],
["HarmonyCompatibilityDependency", "originModule"],
[
"HarmonyExportExpressionDependency",
"originModule",
"range",
"rangeStatement",
"prefix"
],
["HarmonyExportHeaderDependency", "range", "rangeStatement"],
[
"HarmonyExportImportedSpecifierDependency",
"request",
"originModule",
"sourceOrder",
"parserScope",
"id",
"name",
"activeExports",
"otherStarExports",
"strictExportPresence"
],
["HarmonyExportSpecifierDependency", "originModule", "id", "name"],
[
"HarmonyImportDependency",
"request",
"originModule",
"sourceOrder",
"parserScope"
],
[
"HarmonyImportSideEffectDependency",
"request",
"originModule",
"sourceOrder",
"parserScope"
],
[
"HarmonyImportSpecifierDependency",
"request",
"originModule",
"sourceOrder",
"parserScope",
"id",
"name",
"range",
"strictExportPresence"
],
["HarmonyInitDependency", "originModule"],
["ImportContextDependency", "options", "range", "valueRange"],
["ImportDependency", "request", "originModule", "block"],
["ImportEagerDependency", "request", "originModule", "range"],
["ImportWeakDependency", "request", "originModule", "range"],
["JsonExportsDependency", "exports"],
["LoaderDependency", "request"],
["LocalModuleDependency", "localModule", "range", "callNew"],
["ModuleDependency", "request"],
["ModuleHotAcceptDependency", "request", "range"],
["ModuleHotDeclineDependency", "request", "range"],
["MultiEntryDependency", "dependencies", "name"],
["NullDependency"],
["PrefetchDependency", "request"],
["RequireContextDependency", "options", "range"],
["RequireEnsureDependency", "block"],
["RequireEnsureItemDependency", "request"],
["RequireHeaderDependency", "range"],
["RequireIncludeDependency", "request", "range"],
["RequireResolveContextDependency", "options", "range", "valueRange"],
["RequireResolveDependency", "request", "range"],
["RequireResolveHeaderDependency", "range"],
["SingleEntryDependency", "request"],
["UnsupportedDependency", "request", "range"],
[
"WebAssemblyImportDependency",
"request",
"name",
"description",
"onlyDirectImport"
]
]
File diff suppressed because it is too large Load Diff
-3
View File
@@ -1,3 +0,0 @@
module.exports = function Object_values(obj) {
return Object.keys(obj).map(key => [key, obj[key]]);
};
-3
View File
@@ -1,3 +0,0 @@
module.exports = function Object_values(obj) {
return Object.keys(obj).map(key => obj[key]);
};
-29
View File
@@ -1,29 +0,0 @@
// Perform a set of tasks in array quickly. Sometimes testing much better for
// large sets of work instead of individual promises.
const bulkFsTask = (array, each) =>
new Promise((resolve, reject) => {
let ops = 0;
const out = [];
array.forEach((item, i) => {
out[i] = each(item, (back, callback) => {
ops++;
return (err, value) => {
try {
out[i] = back(err, value, out[i]);
} catch (e) {
return reject(e);
}
ops--;
if (ops === 0) {
resolve(out);
}
};
});
});
if (ops === 0) {
resolve(out);
}
});
module.exports = bulkFsTask;
-89
View File
@@ -1,89 +0,0 @@
const fs = require('graceful-fs');
const path = require('path');
const logMessages = require('./log-messages');
exports.cachePrefix = cachePrefix;
const NS = fs.realpathSync(path.dirname(__dirname));
const cachePrefixNS = `${NS}/cachePrefix`;
function cachePrefix(compilation) {
if (typeof compilation[cachePrefixNS] === 'undefined') {
let prefix = '';
let nextCompilation = compilation;
while (nextCompilation.compiler.parentCompilation) {
const parentCompilation = nextCompilation.compiler.parentCompilation;
if (!nextCompilation.cache) {
logMessages.childCompilerWithoutCache(compilation);
prefix = null;
break;
}
const cache = nextCompilation.cache;
let parentCache = parentCompilation.cache;
if (cache === parentCache) {
nextCompilation = parentCompilation;
continue;
}
let cacheKey;
for (var key in parentCache) {
if (key && parentCache[key] === cache) {
cacheKey = key;
break;
}
}
// webpack 3 adds the children member containing compiler names paired
// with arrays of compilation caches, one for each compilation sharing the
// same name.
if (!cacheKey && parentCache.children) {
parentCache = parentCache.children;
for (var key in parentCache) {
if (key && parentCache[key]) {
for (const index in parentCache[key]) {
if (parentCache[key][index] === cache) {
cacheKey = `${key}.${index}`;
break;
}
if (
parentCache[key][index] &&
typeof parentCache[key][index] === 'object'
) {
for (const subkey in parentCache[key][index]) {
if (parentCache[key][index][subkey] === cache) {
cacheKey = `${key}.${index}.${subkey}`;
break;
}
}
}
}
}
}
}
if (!cacheKey) {
logMessages.childCompilerUnnamedCache(compilation);
prefix = null;
break;
} else {
prefix = cacheKey + prefix;
}
nextCompilation = parentCompilation;
}
compilation[cachePrefixNS] =
prefix !== null
? require('crypto')
.createHash('md5')
.update(prefix)
.digest('base64')
: null;
}
return compilation[cachePrefixNS];
}
-248
View File
@@ -1,248 +0,0 @@
const cachePrefix = require('.').cachePrefix;
const LoggerFactory = require('../loggerFactory');
exports.moduleFreezeError = (compilation, module, e) => {
const loggerSerial = LoggerFactory.getLogger(compilation).from('serial');
const compilerName = compilation.compiler.name;
const compilerContext = compilation.compiler.options.context;
const identifierPrefix = cachePrefix(compilation);
const moduleIdentifier = module.identifier();
const shortener = new (require('webpack/lib/RequestShortener'))(
compilerContext,
);
const moduleReadable = module.readableIdentifier(shortener);
loggerSerial.error(
{
id: 'serialization--error-freezing-module',
identifierPrefix,
compilerName,
moduleIdentifier,
moduleReadable,
error: e,
errorMessage: e.message,
errorStack: e.stack,
},
`Unable to freeze module "${moduleReadable}${
compilerName ? `" in compilation "${compilerName}` : ''
}". An error occured serializing it into a string: ${e.message}`,
);
};
exports.cacheNoParity = (compiler, { parityRoot }) => {
const loggerSerial = new LoggerFactory(compiler).create().from('serial');
loggerSerial.error(
{
id: 'serialzation--cache-incomplete',
parityRoot,
},
[
`Previous cache did not complete parity check. ${parityRoot.reason}`,
'Resetting cache.',
].join('\n'),
);
};
exports.serialBadCache = (compiler, error) => {
const loggerSerial = new LoggerFactory(compiler).create().from('serial');
loggerSerial.error(
{
id: 'serialzation--bad-cache',
},
['Cache is corrupted.', error.stack || error.message || error].join('\n'),
);
};
const logCore = compiler => new LoggerFactory(compiler).create().from('core');
exports.configHashSetButNotUsed = (compiler, { cacheDirectory }) => {
const loggerCore = logCore(compiler);
loggerCore.error(
{
id: 'confighash--directory-no-confighash',
cacheDirectory: cacheDirectory,
},
'HardSourceWebpackPlugin cannot use [confighash] in cacheDirectory ' +
'without configHash option being set and returning a non-falsy value.',
);
};
exports.configHashFirstBuild = (compiler, { cacheDirPath, configHash }) => {
const loggerCore = logCore(compiler);
loggerCore.log(
{
id: 'confighash--new',
cacheDirPath,
configHash,
},
`HardSourceWebpackPlugin is writing to a new confighash path for the first time: ${cacheDirPath}`,
);
};
exports.configHashBuildWith = (compiler, { cacheDirPath, configHash }) => {
const loggerCore = logCore(compiler);
loggerCore.log(
{
id: 'confighash--reused',
cacheDirPath,
configHash,
},
`HardSourceWebpackPlugin is reading from and writing to a confighash path: ${cacheDirPath}`,
);
};
exports.deleteOldCaches = (compiler, { newTotalSize, oldTotalSize }) => {
const loggerCore = logCore(compiler);
const sizeMB = Math.ceil(newTotalSize / 1024 / 1024);
const deletedSizeMB = Math.ceil(oldTotalSize / 1024 / 1024);
loggerCore.log(
{
id: 'caches--delete-old',
size: newTotalSize,
sizeMB,
deletedSize: oldTotalSize,
deletedSizeMB,
},
`HardSourceWebpackPlugin is using ${sizeMB} MB of disk space after deleting ${deletedSizeMB} MB.`,
);
};
exports.keepCaches = (compiler, { totalSize }) => {
const loggerCore = logCore(compiler);
const sizeMB = Math.ceil(totalSize / 1024 / 1024);
loggerCore.log(
{
id: 'caches--keep',
size: totalSize,
sizeMB,
},
`HardSourceWebpackPlugin is using ${sizeMB} MB of disk space.`,
);
};
exports.environmentInputs = (compiler, { inputs }) => {
const loggerCore = logCore(compiler);
loggerCore.log(
{
id: 'environment--inputs',
inputs,
},
`Tracking environment changes with ${inputs.join(', ')}.`,
);
};
exports.configHashChanged = compiler => {
const loggerCore = logCore(compiler);
loggerCore.warn(
{
id: 'environment--config-changed',
},
'Environment has changed (configuration was changed).\n' +
'HardSourceWebpackPlugin will reset the cache and store a fresh one.',
);
};
exports.environmentHashChanged = compiler => {
const loggerCore = logCore(compiler);
loggerCore.warn(
{
id: 'environment--changed',
},
'Environment has changed (node_modules was updated).\n' +
'HardSourceWebpackPlugin will reset the cache and store a fresh one.',
);
};
exports.hardSourceVersionChanged = compiler => {
const loggerCore = logCore(compiler);
loggerCore.warn(
{
id: 'environment--hardsource-changed',
},
'Installed HardSource version does not match the saved ' +
'cache.\nHardSourceWebpackPlugin will reset the cache and store ' +
'a fresh one.',
);
};
exports.childCompilerWithoutCache = compilation => {
var loggerUtil = LoggerFactory.getLogger(compilation).from('util');
loggerUtil.error(
{
id: 'childcompiler--no-cache',
compilerName: compilation.compiler.name,
},
[
`A child compiler (${compilation.compiler.name}) does not`,
"have a memory cache. Enable a memory cache with webpack's",
'`cache` configuration option. HardSourceWebpackPlugin will be',
'disabled for this child compiler until then.',
].join('\n'),
);
};
exports.childCompilerUnnamedCache = compilation => {
var loggerUtil = LoggerFactory.getLogger(compilation).from('util');
loggerUtil.error(
{
id: 'childcompiler--unnamed-cache',
compilerName: compilation.compiler.name,
},
[
`A child compiler (${compilation.compiler.name}) has a`,
'memory cache but its cache name is unknown.',
'HardSourceWebpackPlugin will be disabled for this child',
'compiler.',
].join('\n'),
);
};
const logParallel = compiler =>
new LoggerFactory(compiler).create().from('parallel');
exports.parallelStartWorkers = (compiler, options) => {
const loggerParallel = logParallel(compiler);
loggerParallel.log(
{
id: 'parallel--start-workers',
numWorkers: options.numWorkers,
},
[`Start ${options.numWorkers} module workers.`].join('\n'),
);
};
exports.parallelConfigMismatch = (compiler, options) => {
const loggerParallel = logParallel(compiler);
loggerParallel.error(
{
id: 'parallel--config-mismatch',
ourHash: options.ourHash,
theirHash: options.theirHash,
},
[
`Child process's configuration does not match parent `,
`configuration. Unable to parallelize webpack.`,
].join('\n'),
);
};
exports.parallelErrorSendingJob = (compiler, error) => {
const loggerParallel = logParallel(compiler);
loggerParallel.error(
{
id: 'parallel--error-sending-job',
error,
},
`Failed to send parallel module work. ${error.stack}`,
);
};
exports.parallelRequireWebpack4 = compiler => {
const loggerParallel = logParallel(compiler);
loggerParallel.error(
{
id: 'parallel--webpack-4',
},
`Parallel Module Plugin requires webpack 4.`,
);
};
-194
View File
@@ -1,194 +0,0 @@
const parseJson = require('parse-json');
const { cachePrefix } = require('.');
class ParityRoot {
constructor() {
this.children = [];
}
add(name) {
const bits = new ParityCache(name);
this.children.push(bits);
return bits;
}
verify() {
const firstChild = this.children[0];
if (!this.children.some(child => child.root)) {
return true;
}
for (const child of this.children) {
if (!child.verify()) {
this.reason = {
cache: child,
cacheName: child.name,
cacheReason: child.reason,
message: `Cache ${child.name} is not complete. ${
child.reason.message
}`,
};
return false;
}
if (child !== firstChild && child.root.token !== firstChild.root.token) {
this.reason = {
firstCache: firstChild,
firstCacheName: firstChild.name,
firstCacheReason: firstChild.reason,
secondCache: child,
secondCacheName: child.name,
secondCacheReason: child.reason,
message: `Cache ${firstChild.name} and ${child.name} disagree.`,
};
return false;
}
}
return true;
}
}
class ParityCache {
constructor(name) {
this.name = name;
this.root = null;
this.bits = {};
this.reason = null;
}
add(_token) {
const token = ParityToken.fromJson(_token);
if (token.isRoot) {
this.root = token;
}
this.bits[token.id] = token;
}
verify() {
if (this.root === null) {
this.reason = {
message: 'Root compilation not found.',
};
return false;
}
for (const id of this.root.ids) {
if (typeof this.bits[id] === 'undefined') {
this.reason = {
message: `Compilation '${id}' not found.`,
};
return false;
} else if (this.root.token !== this.bits[id].token) {
this.reason = {
message: `Root and '${id}' compilation disagree.`,
};
return false;
}
}
return true;
}
}
const createParityToken = (id, ids = null) => {
const token = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c =>
c === 'x'
? ((Math.random() * 16) | 0).toString(16)
: (((Math.random() * 4) | 0) + 8).toString(16),
);
return new ParityToken(id, token, ids);
};
class ParityToken {
constructor(id, token, ids = null) {
this.id = id;
this.token = token;
this.isRoot = ids !== null;
this.ids = ids;
}
static fromCompilation(compilation) {
let parentCompilation = compilation;
while (parentCompilation.compiler.parentCompilation) {
parentCompilation = parentCompilation.compiler.parentCompilation;
}
if (!parentCompilation.__hardSource_parityToken) {
parentCompilation.__hardSource_parityToken = createParityToken(
cachePrefix(parentCompilation),
[],
);
}
if (compilation !== parentCompilation) {
return parentCompilation.__hardSource_parityToken.createChild(
cachePrefix(compilation),
);
}
return parentCompilation.__hardSource_parityToken;
}
static fromJson(json) {
return new ParityToken(json.id, json.token, json.ids);
}
createChild(id) {
this.ids.push(id);
return new ParityToken(id, this.token);
}
toJSON() {
return {
type: 'CacheParityToken',
id: this.id,
ids: this.ids,
token: this.token,
};
}
}
const parseIfString = item => {
if (typeof item === 'string') {
return parseJson(item);
}
return item;
};
const parityCacheFromCache = (name, parityRoot, cache) => {
const parityCache = parityRoot.add(name);
if (cache.__hardSource_parityToken_root) {
const rootCompilation = parseIfString(cache.__hardSource_parityToken_root);
parityCache.add(rootCompilation);
rootCompilation.ids.forEach(id => {
if (cache[`__hardSource_parityToken_${id}`]) {
parityCache.add(parseIfString(cache[`__hardSource_parityToken_${id}`]));
}
});
}
};
const pushParityWriteOps = (compilation, ops) => {
if (compilation.compiler.parentCompilation) {
ops.push({
key: `__hardSource_parityToken_${cachePrefix(compilation)}`,
value: JSON.stringify(ParityToken.fromCompilation(compilation)),
});
} else {
ops.push({
key: `__hardSource_parityToken_root`,
value: JSON.stringify(ParityToken.fromCompilation(compilation)),
});
}
};
module.exports = {
ParityRoot,
ParityCache,
ParityToken,
parityCacheFromCache,
pushParityWriteOps,
};
-247
View File
@@ -1,247 +0,0 @@
let hookTypes;
const callStyles = {
sync: 'applyPlugins',
syncWaterfall: 'applyPluginsWaterfall',
syncBail: 'applyPluginsBailResult',
sync_map: 'applyPlugins',
asyncWaterfall: 'applyPluginsAsyncWaterfall',
asyncParallel: 'applyPluginsParallel',
asyncSerial: 'applyPluginsAsync',
};
const camelToDash = camel =>
camel.replace(/_/g, '--').replace(/[A-Z]/g, c => `-${c.toLowerCase()}`);
const knownPluginRegistrations = {
Compilation: {
needAdditionalPass: ['sync', []],
succeedModule: ['sync', ['module']],
buildModule: ['sync', ['module']],
seal: ['sync', []],
},
Compiler: {
afterCompile: ['asyncSerial', ['compilation']],
afterEnvironment: ['sync', []],
afterPlugins: ['sync', []],
afterResolvers: ['sync', []],
compilation: ['sync', ['compilation', 'params']],
emit: ['asyncSerial', ['compilation']],
make: ['asyncParallel', ['compilation']],
watchRun: ['asyncSerial', ['watcher']],
run: ['asyncSerial', ['compiler']],
},
NormalModuleFactory: {
createModule: ['syncBail', ['data']],
parser: ['sync_map', ['parser', 'parserOptions']],
resolver: ['syncWaterfall', ['nextResolver']],
},
ContextModuleFactory: {
afterResolve: ['asyncWaterfall', ['data']],
},
};
exports.register = (tapable, name, style, args) => {
if (tapable.hooks) {
if (!hookTypes) {
const Tapable = require('tapable');
hookTypes = {
sync: Tapable.SyncHook,
syncWaterfall: Tapable.SyncWaterfallHook,
syncBail: Tapable.SyncBailHook,
asyncWaterfall: Tapable.AsyncWaterfallHook,
asyncParallel: Tapable.AsyncParallelHook,
asyncSerial: Tapable.AsyncSeriesHook,
asyncSeries: Tapable.AsyncSeriesHook,
};
}
if (!tapable.hooks[name]) {
tapable.hooks[name] = new hookTypes[style](args);
}
} else {
if (!tapable.__hardSource_hooks) {
tapable.__hardSource_hooks = {};
}
if (!tapable.__hardSource_hooks[name]) {
tapable.__hardSource_hooks[name] = {
name,
dashName: camelToDash(name),
style,
args,
async: style.startsWith('async'),
map: style.endsWith('_map'),
};
}
if (!tapable.__hardSource_proxy) {
tapable.__hardSource_proxy = {};
}
if (!tapable.__hardSource_proxy[name]) {
if (tapable.__hardSource_hooks[name].map) {
const _forCache = {};
tapable.__hardSource_proxy[name] = {
_forCache,
for: key => {
let hook = _forCache[key];
if (hook) {
return hook;
}
_forCache[key] = {
tap: (...args) => exports.tapFor(tapable, name, key, ...args),
tapPromise: (...args) =>
exports.tapPromiseFor(tapable, name, key, ...args),
call: (...args) => exports.callFor(tapable, name, key, ...args),
promise: (...args) =>
exports.promiseFor(tapable, name, key, ...args),
};
return _forCache[key];
},
tap: (...args) => exports.tapFor(tapable, name, ...args),
tapPromise: (...args) =>
exports.tapPromiseFor(tapable, name, ...args),
call: (...args) => exports.callFor(tapable, name, ...args),
promise: (...args) => exports.promiseFor(tapable, name, ...args),
};
} else {
tapable.__hardSource_proxy[name] = {
tap: (...args) => exports.tap(tapable, name, ...args),
tapPromise: (...args) => exports.tapPromise(tapable, name, ...args),
call: (...args) => exports.call(tapable, name, args),
promise: (...args) => exports.promise(tapable, name, args),
};
}
}
}
};
exports.tap = (tapable, name, reason, callback) => {
if (tapable.hooks) {
tapable.hooks[name].tap(reason, callback);
} else {
if (!tapable.__hardSource_hooks || !tapable.__hardSource_hooks[name]) {
const registration =
knownPluginRegistrations[tapable.constructor.name][name];
exports.register(tapable, name, registration[0], registration[1]);
}
const dashName = tapable.__hardSource_hooks[name].dashName;
if (tapable.__hardSource_hooks[name].async) {
tapable.plugin(dashName, (...args) => {
const cb = args.pop();
cb(null, callback(...args));
});
} else {
tapable.plugin(dashName, callback);
}
}
};
exports.tapPromise = (tapable, name, reason, callback) => {
if (tapable.hooks) {
tapable.hooks[name].tapPromise(reason, callback);
} else {
if (!tapable.__hardSource_hooks || !tapable.__hardSource_hooks[name]) {
const registration =
knownPluginRegistrations[tapable.constructor.name][name];
exports.register(tapable, name, registration[0], registration[1]);
}
const dashName = tapable.__hardSource_hooks[name].dashName;
tapable.plugin(dashName, (...args) => {
const cb = args.pop();
return callback(...args).then(value => cb(null, value), cb);
});
}
};
exports.tapAsync = (tapable, name, reason, callback) => {
if (tapable.hooks) {
tapable.hooks[name].tapAsync(reason, callback);
} else {
if (!tapable.__hardSource_hooks || !tapable.__hardSource_hooks[name]) {
const registration =
knownPluginRegistrations[tapable.constructor.name][name];
exports.register(tapable, name, registration[0], registration[1]);
}
const dashName = tapable.__hardSource_hooks[name].dashName;
tapable.plugin(dashName, callback);
}
};
exports.call = (tapable, name, args) => {
if (tapable.hooks) {
const hook = tapable.hooks[name];
return hook.call(...args);
} else {
const dashName = tapable.__hardSource_hooks[name].dashName;
const style = tapable.__hardSource_hooks[name].style;
return tapable[callStyles[style]](...[dashName].concat(args));
}
};
exports.promise = (tapable, name, args) => {
if (tapable.hooks) {
const hook = tapable.hooks[name];
return hook.promise(...args);
} else {
const dashName = tapable.__hardSource_hooks[name].dashName;
const style = tapable.__hardSource_hooks[name].style;
return new Promise((resolve, reject) => {
tapable[callStyles[style]](
...[dashName].concat(args, (err, value) => {
if (err) {
reject(err);
} else {
resolve(value);
}
}),
);
});
}
};
exports.tapFor = (tapable, name, key, reason, callback) => {
if (tapable.hooks) {
tapable.hooks[name].for(key).tap(reason, callback);
} else {
exports.tap(tapable, name, reason, callback);
}
};
exports.tapPromiseFor = (tapable, name, key, reason, callback) => {
if (tapable.hooks) {
tapable.hooks[name].for(key).tapPromise(reason, callback);
} else {
exports.tapPromise(tapable, name, reason, callback);
}
};
exports.callFor = (tapable, name, key, args) => {
if (tapable.hooks) {
tapable.hooks[name].for(key).call(...args);
} else {
exports.call(tapable, name, args);
}
};
exports.promiseFor = (tapable, name, key, args) => {
if (tapable.hooks) {
tapable.hooks[name].for(key).promise(...args);
} else {
exports.promise(tapable, name, args);
}
};
exports.hooks = tapable => {
if (tapable.hooks) {
return tapable.hooks;
}
if (!tapable.__hardSource_proxy) {
tapable.__hardSource_proxy = {};
}
const registrations = knownPluginRegistrations[tapable.constructor.name];
if (registrations) {
for (const name in registrations) {
const registration = registrations[name];
exports.register(tapable, name, registration[0], registration[1]);
}
}
return tapable.__hardSource_proxy;
};
-15
View File
@@ -1,15 +0,0 @@
module.exports = function promisify(f, o) {
const ctx = (o && o.context) || null;
return function promisify_wrap() {
const args = Array.from(arguments);
return new Promise(function promisify_resolver(resolve, reject) {
args.push(function promisify_callback(err, value) {
if (err) {
return reject(err);
}
return resolve(value);
});
f.apply(ctx, args);
});
};
};
-195
View File
@@ -1,195 +0,0 @@
const path = require('path');
const rootCompiler = compiler => {
while (compiler.parentCompilation) {
compiler = compiler.parentCompilation.compiler;
}
return compiler;
};
const compilerContext = (exports.compilerContext = function compilerContext(
compiler,
) {
return rootCompiler(compiler.compiler ? compiler.compiler : compiler).context;
});
const relateNormalPath = (exports.relateNormalPath = function relateNormalPath(
compiler,
key,
) {
if (typeof key !== 'string') {
return key;
}
if (compilerContext(compiler) === key) {
return '.';
}
if (key === '') {
return key;
}
const rel = path.relative(compilerContext(compiler), key.split('?')[0]);
return [rel.replace(/\\/g, '/')].concat(key.split('?').slice(1)).join('?');
});
const relateNormalRequest = (exports.relateNormalRequest = function relateNormalRequest(
compiler,
key,
) {
return key
.split('!')
.map(subkey => relateNormalPath(compiler, subkey))
.join('!');
});
const relateNormalModuleId = (exports.relateNormalModuleId = function relateNormalModuleId(
compiler,
id,
) {
return id.substring(0, 24) + relateNormalRequest(compiler, id.substring(24));
});
const relateNormalLoaders = (exports.relateNormalLoaders = function relateNormalLoaders(
compiler,
loaders,
) {
return loaders.map(loader =>
Object.assign({}, loader, {
loader: relateNormalPath(compiler, loader.loader),
}),
);
});
const relateNormalPathArray = (exports.relateNormalPathArray = function relateNormalPathArray(
compiler,
paths,
) {
return paths.map(subpath => relateNormalPath(compiler, subpath));
});
const relateNormalPathSet = (exports.relateNormalPathSet = function relateNormalPathSet(
compiler,
paths,
) {
return relateNormalPathArray(compiler, Array.from(paths));
});
/**
*
*/
// Cache whether we need to replace path.sep because contextNormalPath is called _very_ frequently
const resolveRelativeCompilerContext =
'/' === path.sep
? function(context, key) {
return path.resolve(context, key);
}
: function(context, key) {
return path.resolve(context, key).replace(/\//g, path.sep);
};
const contextNormalPath = (exports.contextNormalPath = function contextNormalPath(
compiler,
key,
) {
if (typeof key !== 'string' || key === '') {
return key;
}
const context = compilerContext(compiler);
if (key === '.') {
return context;
}
const markIndex = key.indexOf('?');
if (markIndex === -1) {
return resolveRelativeCompilerContext(context, key);
}
const abs = resolveRelativeCompilerContext(
context,
key.substring(0, markIndex),
);
return abs + '?' + key.substring(markIndex + 1);
});
const contextNormalRequest = (exports.contextNormalRequest = function contextNormalRequest(
compiler,
key,
) {
// return key
// .split('!')
// .map(subkey => contextNormalPath(compiler, subkey))
// .join('!');
let i = -1;
let j = -1;
let _newkey = '';
while ((i = key.indexOf('!', i + 1)) !== -1) {
_newkey += contextNormalPath(compiler, key.substring(j + 1, i));
_newkey += '!';
j = i;
}
_newkey += contextNormalPath(compiler, key.substring(j + 1));
return _newkey;
});
const contextNormalModuleId = (exports.contextNormalModuleId = function contextNormalModuleId(
compiler,
id,
) {
return id.substring(0, 24) + contextNormalRequest(compiler, id.substring(24));
});
const contextNormalLoaders = (exports.contextNormalLoaders = function contextNormalLoaders(
compiler,
loaders,
) {
return loaders.map(loader =>
Object.assign({}, loader, {
loader: contextNormalPath(compiler, loader.loader),
}),
);
});
const contextNormalPathArray = (exports.contextNormalPathArray = function contextNormalPathArray(
compiler,
paths,
) {
return paths.map(subpath => contextNormalPath(compiler, subpath));
});
const contextNormalPathSet = (exports.contextNormalPathSet = function contextNormalPathSet(
compiler,
paths,
) {
return new Set(contextNormalPathArray(compiler, paths));
});
/**
*
*/
const maybeAbsolutePath = (exports.maybeAbsolutePath = function maybeAbsolutePath(
path,
) {
return /^([a-zA-Z]:\\\\|\/)/.test(path);
});
const relateAbsolutePath = (exports.relateAbsolutePath = function relateAbsolutePath(
context,
absPath,
) {
if (maybeAbsolutePath(absPath)) {
return path.relative(context, absPath);
}
return absPath;
});
const relateAbsoluteRequest = (exports.relateAbsoluteRequest = function relateAbsoluteRequest(
context,
absReq,
) {
return absReq
.split(/!/g)
.map(path => relateAbsolutePath(context, path))
.join('!');
});
-220
View File
@@ -1,220 +0,0 @@
const relateContext = require('./relate-context');
const pipe = (exports.pipe = (...fns) => ({
freeze(arg, module, extra, methods) {
for (const fn of fns) {
arg = fn.freeze(arg, module, extra, methods);
}
return arg;
},
thaw(arg, frozen, extra, methods) {
for (const fn of fns) {
arg = fn.thaw(arg, frozen, extra, methods);
}
return arg;
},
}));
const serialMap = (exports.map = (keyOp, valueOp) => ({
freeze(arg, module, extra) {
const resolved = [];
for (const key in arg) {
resolved.push([
keyOp.freeze(key, key, extra),
valueOp.freeze(arg[key], arg[key], extra),
]);
}
return resolved;
},
thaw(arg, frozen, extra) {
const resolved = {};
for (const item of arg) {
const key = keyOp.thaw(item[0], item[0], extra);
const value = valueOp.thaw(item[1], item[1], extra);
resolved[key] = value;
}
return resolved;
},
}));
const contextual = (exports.contextual = fnname => {
const relate = relateContext[`relateNormal${fnname}`];
const context = relateContext[`contextNormal${fnname}`];
return {
freeze: (arg, module, { compiler, compilation }, methods) =>
arg ? relate(compiler || compilation.compiler, arg) : arg,
thaw: (arg, module, { compiler, compilation }, methods) =>
arg ? context(compiler || compilation.compiler, arg) : arg,
};
});
const archetype = (exports.archetype = type => ({
freeze: (arg, module, extra, { freeze }) => freeze(type, null, arg, extra),
thaw: (arg, module, extra, { thaw }) => thaw(type, null, arg, extra),
}));
const mapArchetype = (exports.mapArchetype = type => ({
freeze: (arg, module, extra, { mapFreeze }) =>
mapFreeze(type, null, arg, extra),
thaw: (arg, module, extra, { mapThaw }) => mapThaw(type, null, arg, extra),
}));
const path = (exports.path = contextual('Path'));
const pathArray = (exports.pathArray = contextual('PathArray'));
const pathSet = (exports.pathSet = contextual('PathSet'));
const request = (exports.request = contextual('Request'));
const _loaders = (exports._loaders = contextual('Loaders'));
const loaders = (exports.loaders = {
freeze: _loaders.freeze,
thaw(arg, frozen, extra, methods) {
return _loaders.thaw(arg, frozen, extra, methods).map(loader => {
if (loader.ident) {
let ruleSet =
extra.normalModuleFactory && extra.normalModuleFactory.ruleSet;
if (!ruleSet) {
ruleSet = extra.compiler.__hardSource_ruleSet;
if (!ruleSet) {
const RuleSet = require('webpack/lib/RuleSet');
if (extra.compiler.options.module.defaultRules) {
// webpack 4
ruleSet = extra.compiler.__hardSource_ruleSet = new RuleSet(
extra.compiler.options.module.defaultRules.concat(
extra.compiler.options.module.rules,
),
);
} else {
// webpack <4
ruleSet = extra.compiler.__hardSource_ruleSet = new RuleSet(
extra.compiler.options.module.rules ||
extra.compiler.options.module.loaders,
);
}
}
}
return {
loader: loader.loader,
ident: loader.ident,
options: ruleSet.findOptionsByIdent(loader.ident),
};
}
return loader;
});
},
});
const regExp = (exports.regExp = {
freeze: arg => (arg ? arg.source : false),
thaw: arg => (arg ? new RegExp(arg) : false),
});
const parser = (exports.parser = archetype('Parser'));
const generator = (exports.generator = archetype('Generator'));
const source = (exports.source = archetype('Source'));
const moduleAssets = (exports.moduleAssets = archetype('ModuleAssets'));
const moduleError = (exports.moduleError = mapArchetype('ModuleError'));
const moduleWarning = (exports.moduleWarning = mapArchetype('ModuleWarning'));
const dependencyBlock = (exports.dependencyBlock = {
freeze: (arg, module, extra, { freeze }) =>
freeze('DependencyBlock', null, arg, extra),
thaw: (arg, module, extra, { thaw }) =>
thaw('DependencyBlock', arg, module, extra),
});
const _null = (exports.null = {
freeze: () => null,
thaw: () => null,
});
const identity = (exports.identity = {
freeze: (arg, module, extra, methods) => arg,
thaw: (arg, module, extra, methods) => arg,
});
const assigned = (exports.assigned = members => ({
freeze(arg, module, extra, methods) {
const out = {};
for (const key in members) {
out[key] = members[key].freeze(arg[key], module, extra, methods);
}
return out;
},
thaw(arg, frozen, extra, methods) {
for (const key in members) {
arg[key] = members[key].thaw(frozen[key], frozen, extra, methods);
}
return arg;
},
}));
const created = (exports.created = members => ({
freeze(arg, module, extra, methods) {
if (!arg) {
return null;
}
const out = {};
for (const key in members) {
out[key] = members[key].freeze(arg[key], module, extra, methods);
}
return out;
},
thaw(arg, frozen, extra, methods) {
if (!arg) {
return null;
}
const out = {};
for (const key in members) {
out[key] = members[key].thaw(arg[key], frozen, extra, methods);
}
return out;
},
}));
const objectAssign = (exports.objectAssign = opts => ({
freeze(arg, module, extra) {
const out = Object.assign({}, arg);
for (const key in opts) {
out[key] = opts[key].freeze(arg[key], arg, extra);
}
return out;
},
thaw(arg, frozen, extra) {
const out = Object.assign({}, arg);
for (const key in opts) {
out[key] = opts[key].thaw(arg[key], arg, extra);
}
return out;
},
}));
const constructed = (exports.constructed = (Type, args) => ({
freeze(arg, module, extra, methods) {
const out = {};
for (const key in args) {
out[key] = args[key].freeze(arg[key], module, extra, methods);
}
return out;
},
thaw(arg, frozen, extra, methods) {
const newArgs = [];
for (const key in args) {
newArgs.push(args[key].thaw(frozen[key], frozen, extra, methods));
}
return new Type(...newArgs);
},
}));
const serial = (exports.serial = (name, stages) => ({
freeze(arg, module, extra, methods) {
const out = {
type: name,
};
for (const key in stages) {
out[key] = stages[key].freeze(module, module, extra, methods);
}
return out;
},
thaw(arg, frozen, extra, methods) {
let out = arg;
for (const key in stages) {
out = stages[key].thaw(out, frozen[key], extra, methods);
}
return out;
},
}));
-1
View File
@@ -1 +0,0 @@
../semver/bin/semver
@@ -1,39 +0,0 @@
# changes log
## 5.7
* Add `minVersion` method
## 5.6
* Move boolean `loose` param to an options object, with
backwards-compatibility protection.
* Add ability to opt out of special prerelease version handling with
the `includePrerelease` option flag.
## 5.5
* Add version coercion capabilities
## 5.4
* Add intersection checking
## 5.3
* Add `minSatisfying` method
## 5.2
* Add `prerelease(v)` that returns prerelease components
## 5.1
* Add Backus-Naur for ranges
* Remove excessively cute inspection methods
## 5.0
* Remove AMD/Browserified build artifacts
* Fix ltr and gtr when using the `*` range
* Fix for range `*` with a prerelease identifier
-15
View File
@@ -1,15 +0,0 @@
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-412
View File
@@ -1,412 +0,0 @@
semver(1) -- The semantic versioner for npm
===========================================
## Install
```bash
npm install --save semver
````
## Usage
As a node module:
```js
const semver = require('semver')
semver.valid('1.2.3') // '1.2.3'
semver.valid('a.b.c') // null
semver.clean(' =v1.2.3 ') // '1.2.3'
semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
semver.gt('1.2.3', '9.8.7') // false
semver.lt('1.2.3', '9.8.7') // true
semver.minVersion('>=1.0.0') // '1.0.0'
semver.valid(semver.coerce('v2')) // '2.0.0'
semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7'
```
As a command-line utility:
```
$ semver -h
A JavaScript implementation of the https://semver.org/ specification
Copyright Isaac Z. Schlueter
Usage: semver [options] <version> [<version> [...]]
Prints valid versions sorted by SemVer precedence
Options:
-r --range <range>
Print versions that match the specified range.
-i --increment [<level>]
Increment a version by the specified level. Level can
be one of: major, minor, patch, premajor, preminor,
prepatch, or prerelease. Default level is 'patch'.
Only one version may be specified.
--preid <identifier>
Identifier to be used to prefix premajor, preminor,
prepatch or prerelease version increments.
-l --loose
Interpret versions and ranges loosely
-p --include-prerelease
Always include prerelease versions in range matching
-c --coerce
Coerce a string into SemVer if possible
(does not imply --loose)
Program exits successfully if any valid version satisfies
all supplied ranges, and prints all satisfying versions.
If no satisfying versions are found, then exits failure.
Versions are printed in ascending order, so supplying
multiple versions to the utility will just sort them.
```
## Versions
A "version" is described by the `v2.0.0` specification found at
<https://semver.org/>.
A leading `"="` or `"v"` character is stripped off and ignored.
## Ranges
A `version range` is a set of `comparators` which specify versions
that satisfy the range.
A `comparator` is composed of an `operator` and a `version`. The set
of primitive `operators` is:
* `<` Less than
* `<=` Less than or equal to
* `>` Greater than
* `>=` Greater than or equal to
* `=` Equal. If no operator is specified, then equality is assumed,
so this operator is optional, but MAY be included.
For example, the comparator `>=1.2.7` would match the versions
`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6`
or `1.1.0`.
Comparators can be joined by whitespace to form a `comparator set`,
which is satisfied by the **intersection** of all of the comparators
it includes.
A range is composed of one or more comparator sets, joined by `||`. A
version matches a range if and only if every comparator in at least
one of the `||`-separated comparator sets is satisfied by the version.
For example, the range `>=1.2.7 <1.3.0` would match the versions
`1.2.7`, `1.2.8`, and `1.2.99`, but not the versions `1.2.6`, `1.3.0`,
or `1.1.0`.
The range `1.2.7 || >=1.2.9 <2.0.0` would match the versions `1.2.7`,
`1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0`.
### Prerelease Tags
If a version has a prerelease tag (for example, `1.2.3-alpha.3`) then
it will only be allowed to satisfy comparator sets if at least one
comparator with the same `[major, minor, patch]` tuple also has a
prerelease tag.
For example, the range `>1.2.3-alpha.3` would be allowed to match the
version `1.2.3-alpha.7`, but it would *not* be satisfied by
`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater
than" `1.2.3-alpha.3` according to the SemVer sort rules. The version
range only accepts prerelease tags on the `1.2.3` version. The
version `3.4.5` *would* satisfy the range, because it does not have a
prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`.
The purpose for this behavior is twofold. First, prerelease versions
frequently are updated very quickly, and contain many breaking changes
that are (by the author's design) not yet fit for public consumption.
Therefore, by default, they are excluded from range matching
semantics.
Second, a user who has opted into using a prerelease version has
clearly indicated the intent to use *that specific* set of
alpha/beta/rc versions. By including a prerelease tag in the range,
the user is indicating that they are aware of the risk. However, it
is still not appropriate to assume that they have opted into taking a
similar risk on the *next* set of prerelease versions.
Note that this behavior can be suppressed (treating all prerelease
versions as if they were normal versions, for the purpose of range
matching) by setting the `includePrerelease` flag on the options
object to any
[functions](https://github.com/npm/node-semver#functions) that do
range matching.
#### Prerelease Identifiers
The method `.inc` takes an additional `identifier` string argument that
will append the value of the string as a prerelease identifier:
```javascript
semver.inc('1.2.3', 'prerelease', 'beta')
// '1.2.4-beta.0'
```
command-line example:
```bash
$ semver 1.2.3 -i prerelease --preid beta
1.2.4-beta.0
```
Which then can be used to increment further:
```bash
$ semver 1.2.4-beta.0 -i prerelease
1.2.4-beta.1
```
### Advanced Range Syntax
Advanced range syntax desugars to primitive comparators in
deterministic ways.
Advanced ranges may be combined in the same way as primitive
comparators using white space or `||`.
#### Hyphen Ranges `X.Y.Z - A.B.C`
Specifies an inclusive set.
* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`
If a partial version is provided as the first version in the inclusive
range, then the missing pieces are replaced with zeroes.
* `1.2 - 2.3.4` := `>=1.2.0 <=2.3.4`
If a partial version is provided as the second version in the
inclusive range, then all versions that start with the supplied parts
of the tuple are accepted, but nothing that would be greater than the
provided tuple parts.
* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0`
* `1.2.3 - 2` := `>=1.2.3 <3.0.0`
#### X-Ranges `1.2.x` `1.X` `1.2.*` `*`
Any of `X`, `x`, or `*` may be used to "stand in" for one of the
numeric values in the `[major, minor, patch]` tuple.
* `*` := `>=0.0.0` (Any version satisfies)
* `1.x` := `>=1.0.0 <2.0.0` (Matching major version)
* `1.2.x` := `>=1.2.0 <1.3.0` (Matching major and minor versions)
A partial version range is treated as an X-Range, so the special
character is in fact optional.
* `""` (empty string) := `*` := `>=0.0.0`
* `1` := `1.x.x` := `>=1.0.0 <2.0.0`
* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0`
#### Tilde Ranges `~1.2.3` `~1.2` `~1`
Allows patch-level changes if a minor version is specified on the
comparator. Allows minor-level changes if not.
* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0`
* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0` (Same as `1.2.x`)
* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0` (Same as `1.x`)
* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0`
* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0` (Same as `0.2.x`)
* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0` (Same as `0.x`)
* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0` Note that prereleases in
the `1.2.3` version will be allowed, if they are greater than or
equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but
`1.2.4-beta.2` would not, because it is a prerelease of a
different `[major, minor, patch]` tuple.
#### Caret Ranges `^1.2.3` `^0.2.5` `^0.0.4`
Allows changes that do not modify the left-most non-zero digit in the
`[major, minor, patch]` tuple. In other words, this allows patch and
minor updates for versions `1.0.0` and above, patch updates for
versions `0.X >=0.1.0`, and *no* updates for versions `0.0.X`.
Many authors treat a `0.x` version as if the `x` were the major
"breaking-change" indicator.
Caret ranges are ideal when an author may make breaking changes
between `0.2.4` and `0.3.0` releases, which is a common practice.
However, it presumes that there will *not* be breaking changes between
`0.2.4` and `0.2.5`. It allows for changes that are presumed to be
additive (but non-breaking), according to commonly observed practices.
* `^1.2.3` := `>=1.2.3 <2.0.0`
* `^0.2.3` := `>=0.2.3 <0.3.0`
* `^0.0.3` := `>=0.0.3 <0.0.4`
* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0` Note that prereleases in
the `1.2.3` version will be allowed, if they are greater than or
equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but
`1.2.4-beta.2` would not, because it is a prerelease of a
different `[major, minor, patch]` tuple.
* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4` Note that prereleases in the
`0.0.3` version *only* will be allowed, if they are greater than or
equal to `beta`. So, `0.0.3-pr.2` would be allowed.
When parsing caret ranges, a missing `patch` value desugars to the
number `0`, but will allow flexibility within that value, even if the
major and minor versions are both `0`.
* `^1.2.x` := `>=1.2.0 <2.0.0`
* `^0.0.x` := `>=0.0.0 <0.1.0`
* `^0.0` := `>=0.0.0 <0.1.0`
A missing `minor` and `patch` values will desugar to zero, but also
allow flexibility within those values, even if the major version is
zero.
* `^1.x` := `>=1.0.0 <2.0.0`
* `^0.x` := `>=0.0.0 <1.0.0`
### Range Grammar
Putting all this together, here is a Backus-Naur grammar for ranges,
for the benefit of parser authors:
```bnf
range-set ::= range ( logical-or range ) *
logical-or ::= ( ' ' ) * '||' ( ' ' ) *
range ::= hyphen | simple ( ' ' simple ) * | ''
hyphen ::= partial ' - ' partial
simple ::= primitive | partial | tilde | caret
primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial
partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )?
xr ::= 'x' | 'X' | '*' | nr
nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) *
tilde ::= '~' partial
caret ::= '^' partial
qualifier ::= ( '-' pre )? ( '+' build )?
pre ::= parts
build ::= parts
parts ::= part ( '.' part ) *
part ::= nr | [-0-9A-Za-z]+
```
## Functions
All methods and classes take a final `options` object argument. All
options in this object are `false` by default. The options supported
are:
- `loose` Be more forgiving about not-quite-valid semver strings.
(Any resulting output will always be 100% strict compliant, of
course.) For backwards compatibility reasons, if the `options`
argument is a boolean value instead of an object, it is interpreted
to be the `loose` param.
- `includePrerelease` Set to suppress the [default
behavior](https://github.com/npm/node-semver#prerelease-tags) of
excluding prerelease tagged versions from ranges unless they are
explicitly opted into.
Strict-mode Comparators and Ranges will be strict about the SemVer
strings that they parse.
* `valid(v)`: Return the parsed version, or null if it's not valid.
* `inc(v, release)`: Return the version incremented by the release
type (`major`, `premajor`, `minor`, `preminor`, `patch`,
`prepatch`, or `prerelease`), or null if it's not valid
* `premajor` in one call will bump the version up to the next major
version and down to a prerelease of that major version.
`preminor`, and `prepatch` work the same way.
* If called from a non-prerelease version, the `prerelease` will work the
same as `prepatch`. It increments the patch version, then makes a
prerelease. If the input version is already a prerelease it simply
increments it.
* `prerelease(v)`: Returns an array of prerelease components, or null
if none exist. Example: `prerelease('1.2.3-alpha.1') -> ['alpha', 1]`
* `major(v)`: Return the major version number.
* `minor(v)`: Return the minor version number.
* `patch(v)`: Return the patch version number.
* `intersects(r1, r2, loose)`: Return true if the two supplied ranges
or comparators intersect.
* `parse(v)`: Attempt to parse a string as a semantic version, returning either
a `SemVer` object or `null`.
### Comparison
* `gt(v1, v2)`: `v1 > v2`
* `gte(v1, v2)`: `v1 >= v2`
* `lt(v1, v2)`: `v1 < v2`
* `lte(v1, v2)`: `v1 <= v2`
* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent,
even if they're not the exact same string. You already know how to
compare strings.
* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`.
* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call
the corresponding function above. `"==="` and `"!=="` do simple
string comparison, but are included for completeness. Throws if an
invalid comparison string is provided.
* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if
`v2` is greater. Sorts in ascending order if passed to `Array.sort()`.
* `rcompare(v1, v2)`: The reverse of compare. Sorts an array of versions
in descending order when passed to `Array.sort()`.
* `diff(v1, v2)`: Returns difference between two versions by the release type
(`major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, or `prerelease`),
or null if the versions are the same.
### Comparators
* `intersects(comparator)`: Return true if the comparators intersect
### Ranges
* `validRange(range)`: Return the valid range or null if it's not valid
* `satisfies(version, range)`: Return true if the version satisfies the
range.
* `maxSatisfying(versions, range)`: Return the highest version in the list
that satisfies the range, or `null` if none of them do.
* `minSatisfying(versions, range)`: Return the lowest version in the list
that satisfies the range, or `null` if none of them do.
* `minVersion(range)`: Return the lowest version that can possibly match
the given range.
* `gtr(version, range)`: Return `true` if version is greater than all the
versions possible in the range.
* `ltr(version, range)`: Return `true` if version is less than all the
versions possible in the range.
* `outside(version, range, hilo)`: Return true if the version is outside
the bounds of the range in either the high or low direction. The
`hilo` argument must be either the string `'>'` or `'<'`. (This is
the function called by `gtr` and `ltr`.)
* `intersects(range)`: Return true if any of the ranges comparators intersect
Note that, since ranges may be non-contiguous, a version might not be
greater than a range, less than a range, *or* satisfy a range! For
example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9`
until `2.0.0`, so the version `1.2.10` would not be greater than the
range (because `2.0.1` satisfies, which is higher), nor less than the
range (since `1.2.8` satisfies, which is lower), and it also does not
satisfy the range.
If you want to know if a version satisfies or does not satisfy a
range, use the `satisfies(version, range)` function.
### Coercion
* `coerce(version)`: Coerces a string to semver if possible
This aims to provide a very forgiving translation of a non-semver string to
semver. It looks for the first digit in a string, and consumes all
remaining characters which satisfy at least a partial semver (e.g., `1`,
`1.2`, `1.2.3`) up to the max permitted length (256 characters). Longer
versions are simply truncated (`4.6.3.9.2-alpha2` becomes `4.6.3`). All
surrounding text is simply ignored (`v3.4 replaces v3.3.1` becomes
`3.4.0`). Only text which lacks digits will fail coercion (`version one`
is not valid). The maximum length for any semver component considered for
coercion is 16 characters; longer components will be ignored
(`10000000000000000.4.7.4` becomes `4.7.4`). The maximum value for any
semver component is `Number.MAX_SAFE_INTEGER || (2**53 - 1)`; higher value
components are invalid (`9999999999999999.4.7.4` is likely invalid).
-160
View File
@@ -1,160 +0,0 @@
#!/usr/bin/env node
// Standalone semver comparison program.
// Exits successfully and prints matching version(s) if
// any supplied version is valid and passes all tests.
var argv = process.argv.slice(2)
var versions = []
var range = []
var inc = null
var version = require('../package.json').version
var loose = false
var includePrerelease = false
var coerce = false
var identifier
var semver = require('../semver')
var reverse = false
var options = {}
main()
function main () {
if (!argv.length) return help()
while (argv.length) {
var a = argv.shift()
var indexOfEqualSign = a.indexOf('=')
if (indexOfEqualSign !== -1) {
a = a.slice(0, indexOfEqualSign)
argv.unshift(a.slice(indexOfEqualSign + 1))
}
switch (a) {
case '-rv': case '-rev': case '--rev': case '--reverse':
reverse = true
break
case '-l': case '--loose':
loose = true
break
case '-p': case '--include-prerelease':
includePrerelease = true
break
case '-v': case '--version':
versions.push(argv.shift())
break
case '-i': case '--inc': case '--increment':
switch (argv[0]) {
case 'major': case 'minor': case 'patch': case 'prerelease':
case 'premajor': case 'preminor': case 'prepatch':
inc = argv.shift()
break
default:
inc = 'patch'
break
}
break
case '--preid':
identifier = argv.shift()
break
case '-r': case '--range':
range.push(argv.shift())
break
case '-c': case '--coerce':
coerce = true
break
case '-h': case '--help': case '-?':
return help()
default:
versions.push(a)
break
}
}
var options = { loose: loose, includePrerelease: includePrerelease }
versions = versions.map(function (v) {
return coerce ? (semver.coerce(v) || { version: v }).version : v
}).filter(function (v) {
return semver.valid(v)
})
if (!versions.length) return fail()
if (inc && (versions.length !== 1 || range.length)) { return failInc() }
for (var i = 0, l = range.length; i < l; i++) {
versions = versions.filter(function (v) {
return semver.satisfies(v, range[i], options)
})
if (!versions.length) return fail()
}
return success(versions)
}
function failInc () {
console.error('--inc can only be used on a single version with no range')
fail()
}
function fail () { process.exit(1) }
function success () {
var compare = reverse ? 'rcompare' : 'compare'
versions.sort(function (a, b) {
return semver[compare](a, b, options)
}).map(function (v) {
return semver.clean(v, options)
}).map(function (v) {
return inc ? semver.inc(v, inc, options, identifier) : v
}).forEach(function (v, i, _) { console.log(v) })
}
function help () {
console.log(['SemVer ' + version,
'',
'A JavaScript implementation of the https://semver.org/ specification',
'Copyright Isaac Z. Schlueter',
'',
'Usage: semver [options] <version> [<version> [...]]',
'Prints valid versions sorted by SemVer precedence',
'',
'Options:',
'-r --range <range>',
' Print versions that match the specified range.',
'',
'-i --increment [<level>]',
' Increment a version by the specified level. Level can',
' be one of: major, minor, patch, premajor, preminor,',
" prepatch, or prerelease. Default level is 'patch'.",
' Only one version may be specified.',
'',
'--preid <identifier>',
' Identifier to be used to prefix premajor, preminor,',
' prepatch or prerelease version increments.',
'',
'-l --loose',
' Interpret versions and ranges loosely',
'',
'-p --include-prerelease',
' Always include prerelease versions in range matching',
'',
'-c --coerce',
' Coerce a string into SemVer if possible',
' (does not imply --loose)',
'',
'Program exits successfully if any valid version satisfies',
'all supplied ranges, and prints all satisfying versions.',
'',
'If no satisfying versions are found, then exits failure.',
'',
'Versions are printed in ascending order, so supplying',
'multiple versions to the utility will just sort them.'
].join('\n'))
}
@@ -1,63 +0,0 @@
{
"_args": [
[
"semver@5.7.1",
"/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series"
]
],
"_from": "semver@5.7.1",
"_id": "semver@5.7.1",
"_inBundle": false,
"_integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"_location": "/hard-source-webpack-plugin/semver",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "semver@5.7.1",
"name": "semver",
"escapedName": "semver",
"rawSpec": "5.7.1",
"saveSpec": null,
"fetchSpec": "5.7.1"
},
"_requiredBy": [
"/hard-source-webpack-plugin"
],
"_resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"_spec": "5.7.1",
"_where": "/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series",
"bin": {
"semver": "bin/semver"
},
"bugs": {
"url": "https://github.com/npm/node-semver/issues"
},
"description": "The semantic version parser used by npm.",
"devDependencies": {
"tap": "^13.0.0-rc.18"
},
"files": [
"bin",
"range.bnf",
"semver.js"
],
"homepage": "https://github.com/npm/node-semver#readme",
"license": "ISC",
"main": "semver.js",
"name": "semver",
"repository": {
"type": "git",
"url": "git+https://github.com/npm/node-semver.git"
},
"scripts": {
"postpublish": "git push origin --all; git push origin --tags",
"postversion": "npm publish",
"preversion": "npm test",
"test": "tap"
},
"tap": {
"check-coverage": true
},
"version": "5.7.1"
}
-16
View File
@@ -1,16 +0,0 @@
range-set ::= range ( logical-or range ) *
logical-or ::= ( ' ' ) * '||' ( ' ' ) *
range ::= hyphen | simple ( ' ' simple ) * | ''
hyphen ::= partial ' - ' partial
simple ::= primitive | partial | tilde | caret
primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial
partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )?
xr ::= 'x' | 'X' | '*' | nr
nr ::= '0' | [1-9] ( [0-9] ) *
tilde ::= '~' partial
caret ::= '^' partial
qualifier ::= ( '-' pre )? ( '+' build )?
pre ::= parts
build ::= parts
parts ::= part ( '.' part ) *
part ::= nr | [-0-9A-Za-z]+
File diff suppressed because it is too large Load Diff
-115
View File
@@ -1,115 +0,0 @@
{
"_args": [
[
"hard-source-webpack-plugin@0.13.1",
"/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series"
]
],
"_from": "hard-source-webpack-plugin@0.13.1",
"_id": "hard-source-webpack-plugin@0.13.1",
"_inBundle": false,
"_integrity": "sha512-r9zf5Wq7IqJHdVAQsZ4OP+dcUSvoHqDMxJlIzaE2J0TZWn3UjMMrHqwDHR8Jr/pzPfG7XxSe36E7Y8QGNdtuAw==",
"_location": "/hard-source-webpack-plugin",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "hard-source-webpack-plugin@0.13.1",
"name": "hard-source-webpack-plugin",
"escapedName": "hard-source-webpack-plugin",
"rawSpec": "0.13.1",
"saveSpec": null,
"fetchSpec": "0.13.1"
},
"_requiredBy": [
"/@nuxt/webpack"
],
"_resolved": "https://registry.npmjs.org/hard-source-webpack-plugin/-/hard-source-webpack-plugin-0.13.1.tgz",
"_spec": "0.13.1",
"_where": "/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series",
"author": {
"name": "Michael \"Z\" Goddard",
"email": "mzgoddard@gmail.com"
},
"bugs": {
"url": "https://github.com/mzgoddard/hard-source-webpack-plugin/issues"
},
"dependencies": {
"chalk": "^2.4.1",
"find-cache-dir": "^2.0.0",
"graceful-fs": "^4.1.11",
"lodash": "^4.15.0",
"mkdirp": "^0.5.1",
"node-object-hash": "^1.2.0",
"parse-json": "^4.0.0",
"pkg-dir": "^3.0.0",
"rimraf": "^2.6.2",
"semver": "^5.6.0",
"tapable": "^1.0.0-beta.5",
"webpack-sources": "^1.0.1",
"write-json-file": "^2.3.0"
},
"description": "Hard cache the source of modules in webpack.",
"devDependencies": {
"@commitlint/cli": "^7.0.0",
"@commitlint/config-conventional": "^7.0.0",
"@commitlint/travis-cli": "^7.0.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.6.1",
"cacache": "^11.0.2",
"chai": "^3.5.0",
"copy-webpack-plugin": "^4.5.1",
"css-loader": "^1.0.0",
"extract-text-webpack-plugin": "^3.0.0 || ^2.0.0 || ^1.0.1",
"file-loader": "^1.0.0 || ^0.11.0 || ^0.10.1",
"html-webpack-plugin": "^3.2.0 || ^2.22.0",
"husky": "^0.14.3",
"level": "^4.0.0",
"memory-fs": "^0.4.1",
"mini-css-extract-plugin": "^0.4.0",
"mocha": "^3.0.2",
"prettier": "^1.12.1",
"source-map": "^0.5.6",
"standard-version": "^4.4.0",
"style-loader": "^0.14.0",
"webpack": "^4.0.0 || ^4.0.0-beta.* || ^3.8.1 || ^3.0.0 || ^3.0.0-rc.0 || ^2.1.0 || ^1.13.1",
"webpack-cli": "^3.0.0",
"webpack-isomorphic-tools": "^3.0.0",
"worker-loader": "^2.0.0"
},
"engines": {
"node": ">=8.0.0"
},
"files": [
"index.js",
"lib"
],
"homepage": "https://github.com/mzgoddard/hard-source-webpack-plugin#readme",
"keywords": [
"webpack",
"disk",
"iterative",
"build",
"cache",
"plugin"
],
"license": "ISC",
"main": "index.js",
"name": "hard-source-webpack-plugin",
"peerDependencies": {
"webpack": "*"
},
"repository": {
"type": "git",
"url": "git+https://github.com/mzgoddard/hard-source-webpack-plugin.git"
},
"scripts": {
"commitlint-travis": "commitlint-travis",
"commitmsg": "commitlint -e $GIT_PARAMS",
"lint": "prettier --list-different --single-quote --trailing-comma all {index.js,lib/*.js,lib/util/*.js,test/*.js,test/*/*.js,bin/*.js}",
"lint:fix": "prettier --write --single-quote --trailing-comma all {index.js,lib/*.js,lib/util/*.js,test/*.js,test/*/*.js,bin/*.js}",
"test": "NODE_ENV=test mocha tests/*.js"
},
"version": "0.13.1"
}