add `experiments.buildHttp`

allows to build remote resources
stores remote resources in a lockfile
This commit is contained in:
Tobias Koppers 2021-08-04 15:55:58 +02:00
parent 6d24d111f8
commit b6609a4f6b
112 changed files with 2478 additions and 260 deletions

View File

@ -25,7 +25,7 @@ module.exports = {
"no-process-exit": "warn",
"no-use-before-define": "off",
"no-unused-vars": ["error", { args: "none", ignoreRestSiblings: true }],
"no-loop-func": "warn",
"no-loop-func": "off",
"node/no-missing-require": ["error", { allowModules: ["webpack"] }],
"jsdoc/check-indentation": "error",
"jsdoc/check-param-names": "error",

1
.gitattributes vendored
View File

@ -3,3 +3,4 @@ test/statsCases/** eol=lf
examples/* eol=lf
bin/* eol=lf
*.svg eol=lf
**/*webpack.lock.data/** -text

View File

@ -186,6 +186,7 @@
"redeclaration",
"kaios",
"parallelism",
"gitattributes",
"webassemblyjs",
"fsevents",
@ -201,6 +202,7 @@
"atlaskit",
"xxhashjs",
"systemjs",
"skypack",
"sokra",
"Koppers",
@ -228,5 +230,9 @@
"pnpm"
],
"ignoreRegExpList": ["/Author.+/", "/data:.*/", "/\"mappings\":\".+\"/"],
"ignorePaths": ["**/dist/**", "examples/**/README.md"]
"ignorePaths": [
"**/dist/**",
"examples/**/README.md",
"**/webpack.lock.data/**"
]
}

View File

@ -1102,6 +1102,10 @@ export interface Experiments {
* Support WebAssembly as asynchronous EcmaScript Module.
*/
asyncWebAssembly?: boolean;
/**
* Build http(s): urls using a lockfile and resource content cache.
*/
buildHttp?: boolean | HttpUriOptions;
/**
* Enable build-time execution of modules from the module graph for plugins and loaders.
*/
@ -1159,6 +1163,27 @@ export interface Experiments {
*/
topLevelAwait?: boolean;
}
/**
* Options for building http resources.
*/
export interface HttpUriOptions {
/**
* Location where resource content is stored for lockfile entries. It's also possible to disable storing by passing false.
*/
cacheLocation?: false | string;
/**
* When set, anything that would lead to an modification of the lockfile or any resource content, will result in an error.
*/
frozen?: boolean;
/**
* Location of the lockfile.
*/
lockfileLocation?: string;
/**
* When set, resources of existing lockfile entries will be fetched and entries will be upgraded when resource content has changed.
*/
upgrade?: boolean;
}
/**
* Enable presets of externals for specific targets.
*/

View File

@ -0,0 +1,29 @@
/*
* This file was automatically generated.
* DO NOT MODIFY BY HAND.
* Run `yarn special-lint-fix` to update
*/
export type HttpUriPluginOptions = HttpUriOptions;
/**
* Options for building http resources.
*/
export interface HttpUriOptions {
/**
* Location where resource content is stored for lockfile entries. It's also possible to disable storing by passing false.
*/
cacheLocation?: false | string;
/**
* When set, anything that would lead to an modification of the lockfile or any resource content, will result in an error.
*/
frozen?: boolean;
/**
* Location of the lockfile.
*/
lockfileLocation?: string;
/**
* When set, resources of existing lockfile entries will be fetched and entries will be upgraded when resource content has changed.
*/
upgrade?: boolean;
}

View File

@ -0,0 +1,81 @@
# example.js
```javascript
import pMap1 from "https://cdn.skypack.dev/p-map";
import pMap2 from "https://cdn.esm.sh/p-map";
import pMap3 from "https://jspm.dev/p-map";
console.log(pMap1);
console.log(pMap2);
console.log(pMap3);
```
# webpack.config.js
```javascript
module.exports = {
// enable debug logging to see network requests!
// stats: {
// loggingDebug: /HttpUriPlugin/
// },
experiments: {
buildHttp: true
}
};
```
# Info
## Unoptimized
```
asset output.js 58.1 KiB [emitted] (name: main)
runtime modules 670 bytes 3 modules
modules by path https:// 20.9 KiB
modules by path https://jspm.dev/ 8.43 KiB
modules by path https://jspm.dev/*.0 6.04 KiB 5 modules
modules by path https://jspm.dev/npm:@jspm/ 1.99 KiB 2 modules
modules by path https://cdn.esm.sh/ 5.72 KiB 7 modules
modules by path https://cdn.skypack.dev/ 6.72 KiB
https://cdn.skypack.dev/p-map 2.29 KiB [built] [code generated]
[exports: default, pMapSkip]
[used exports unknown]
harmony side effect evaluation https://cdn.skypack.dev/p-map ./example.js 1:0-50
harmony import specifier https://cdn.skypack.dev/p-map ./example.js 4:12-17
https://cdn.skypack.dev/-/aggregate-error@v4.0.0-rCH8s5R9g4kQQ807o58j/dist=es2020,mode=imports/optimized/aggregate-error.js 1.99 KiB [built] [code generated]
[exports: default]
[used exports unknown]
harmony side effect evaluation /-/aggregate-error@v4.0.0-rCH8s5R9g4kQQ807o58j/dist=es2020,mode=imports/optimized/aggregate-error.js https://cdn.skypack.dev/p-map 1:0-130
harmony import specifier /-/aggregate-error@v4.0.0-rCH8s5R9g4kQQ807o58j/dist=es2020,mode=imports/optimized/aggregate-error.js https://cdn.skypack.dev/p-map 32:23-37
https://cdn.skypack.dev/-/indent-string@v5.0.0-VgKPSgi4hUX5NbF4n3aC/dist=es2020,mode=imports/optimized/indent-string.js 827 bytes [built] [code generated]
[exports: default]
[used exports unknown]
harmony side effect evaluation /-/indent-string@v5.0.0-VgKPSgi4hUX5NbF4n3aC/dist=es2020,mode=imports/optimized/indent-string.js https://cdn.skypack.dev/-/aggregate-error@v4.0.0-rCH8s5R9g4kQQ807o58j/dist=es2020,mode=imports/optimized/aggregate-error.js 23:0-124
harmony import specifier /-/indent-string@v5.0.0-VgKPSgi4hUX5NbF4n3aC/dist=es2020,mode=imports/optimized/indent-string.js https://cdn.skypack.dev/-/aggregate-error@v4.0.0-rCH8s5R9g4kQQ807o58j/dist=es2020,mode=imports/optimized/aggregate-error.js 45:21-33
https://cdn.skypack.dev/-/clean-stack@v4.1.0-DgWUKXHVzThBBZtsHXhC/dist=es2020,mode=imports/optimized/clean-stack.js 1.4 KiB [built] [code generated]
[exports: default]
[used exports unknown]
harmony side effect evaluation /-/clean-stack@v4.1.0-DgWUKXHVzThBBZtsHXhC/dist=es2020,mode=imports/optimized/clean-stack.js https://cdn.skypack.dev/-/aggregate-error@v4.0.0-rCH8s5R9g4kQQ807o58j/dist=es2020,mode=imports/optimized/aggregate-error.js 24:0-118
harmony import specifier /-/clean-stack@v4.1.0-DgWUKXHVzThBBZtsHXhC/dist=es2020,mode=imports/optimized/clean-stack.js https://cdn.skypack.dev/-/aggregate-error@v4.0.0-rCH8s5R9g4kQQ807o58j/dist=es2020,mode=imports/optimized/aggregate-error.js 43:66-76
https://cdn.skypack.dev/-/escape-string-regexp@v5.0.0-SUDdAhYOdAgXIYndxZss/dist=es2020,mode=imports/optimized/escape-string-regexp.js 240 bytes [built] [code generated]
[exports: default]
[used exports unknown]
harmony side effect evaluation /-/escape-string-regexp@v5.0.0-SUDdAhYOdAgXIYndxZss/dist=es2020,mode=imports/optimized/escape-string-regexp.js https://cdn.skypack.dev/-/clean-stack@v4.1.0-DgWUKXHVzThBBZtsHXhC/dist=es2020,mode=imports/optimized/clean-stack.js 1:0-144
harmony import specifier /-/escape-string-regexp@v5.0.0-SUDdAhYOdAgXIYndxZss/dist=es2020,mode=imports/optimized/escape-string-regexp.js https://cdn.skypack.dev/-/clean-stack@v4.1.0-DgWUKXHVzThBBZtsHXhC/dist=es2020,mode=imports/optimized/clean-stack.js 7:60-78
./example.js 201 bytes [built] [code generated]
[no exports]
[used exports unknown]
entry ./example.js main
webpack 5.48.0 compiled successfully
```
## Production mode
```
asset output.js 11.3 KiB [emitted] [minimized] (name: main)
orphan modules 20.9 KiB [orphan] 23 modules
./example.js + 22 modules 21 KiB [built] [code generated]
[no exports]
[no exports used]
entry ./example.js main
webpack 5.48.0 compiled successfully
```

View File

@ -0,0 +1,2 @@
global.NO_STATS_OPTIONS = true;
require("../build-common");

View File

@ -0,0 +1,6 @@
import pMap1 from "https://cdn.skypack.dev/p-map";
import pMap2 from "https://cdn.esm.sh/p-map";
import pMap3 from "https://jspm.dev/p-map";
console.log(pMap1);
console.log(pMap2);
console.log(pMap3);

View File

@ -0,0 +1,25 @@
# example.js
```javascript
_{{example.js}}_
```
# webpack.config.js
```javascript
_{{webpack.config.js}}_
```
# Info
## Unoptimized
```
_{{stdout}}_
```
## Production mode
```
_{{production:stdout}}_
```

View File

@ -0,0 +1,9 @@
module.exports = {
// enable debug logging to see network requests!
// stats: {
// loggingDebug: /HttpUriPlugin/
// },
experiments: {
buildHttp: true
}
};

View File

@ -0,0 +1,26 @@
{
"https://cdn.esm.sh/p-map": { "resolved": "https://cdn.esm.sh/p-map", "integrity": "sha512-Q1RsGrT9Fl5eqmmFQbaCy4PcXRx90TZQCcHDWC6sN0vfEnco9o66mi1DNjaWD2HE40qn0cNTWoZ21RIH+jmeiQ==", "contentType": "application/javascript; charset=utf-8" },
"https://cdn.esm.sh/v43/aggregate-error@4.0.0/es2015/aggregate-error.js": { "resolved": "https://cdn.esm.sh/v43/aggregate-error@4.0.0/es2015/aggregate-error.js", "integrity": "sha512-nnqEIbQNpkAb5idk+07Wbc8lNzPloQrPAs+SOjccU+va8qftYFcn0htGVwUqwvkWJHZaJn9/B5bXB2YZVzwvUg==", "contentType": "application/javascript" },
"https://cdn.esm.sh/v43/clean-stack@4.1.0/es2015/clean-stack.js": { "resolved": "https://cdn.esm.sh/v43/clean-stack@4.1.0/es2015/clean-stack.js", "integrity": "sha512-B6h1ZeTzVvZeNUbWJUvEIBPaTvyUnbNEaO+V0aREh7nR1OrFUON/xnG+jwJwEzLWACqQNKFeFiPBOlFowUZ5FQ==", "contentType": "application/javascript" },
"https://cdn.esm.sh/v43/escape-string-regexp@5.0.0/es2015/escape-string-regexp.js": { "resolved": "https://cdn.esm.sh/v43/escape-string-regexp@5.0.0/es2015/escape-string-regexp.js", "integrity": "sha512-e6uaGCpjIjNgUN5K6nm+BQ3HrIKj59Z/ySJDt86eOM1j7ri1PFvpRFq7JwyjGZ0mhNq/j4ywqNmmk7HEji1Chg==", "contentType": "application/javascript" },
"https://cdn.esm.sh/v43/indent-string@5.0.0/es2015/indent-string.js": { "resolved": "https://cdn.esm.sh/v43/indent-string@5.0.0/es2015/indent-string.js", "integrity": "sha512-yNbq6+IcXe6jW+HIM/dCPxvi1+NJRxo5msNe0Vdg4NqVVUV4DF8U2eJPehmKT0Xhv1viyaTiReidhB1BmE1f/A==", "contentType": "application/javascript" },
"https://cdn.esm.sh/v43/os-browserify@0.3.0/es2015/browser.js": { "resolved": "https://cdn.esm.sh/v43/os-browserify@0.3.0/es2015/browser.js", "integrity": "sha512-/BeiBawWpXZlWTjmXwtmrZbBeYgD0BqB9LE3EDf4yxBYqASwZ7Xj2dYNruM3/WMbJYyjP/TSRdwuKMsNLWdZbw==", "contentType": "application/javascript" },
"https://cdn.esm.sh/v43/p-map@5.1.0/es2015/p-map.js": { "resolved": "https://cdn.esm.sh/v43/p-map@5.1.0/es2015/p-map.js", "integrity": "sha512-DLSkffQJHasMXlosBDDFEIn7zgcLUW5KrTHy5/3IFsrmQO+9zlYjlWQbDJEShfvDzFEhXJc9D4ppP6zykBK/ZA==", "contentType": "application/javascript" },
"https://cdn.skypack.dev/-/aggregate-error@v4.0.0-rCH8s5R9g4kQQ807o58j/dist=es2020,mode=imports/optimized/aggregate-error.js": { "resolved": "https://cdn.skypack.dev/-/aggregate-error@v4.0.0-rCH8s5R9g4kQQ807o58j/dist=es2020,mode=imports/optimized/aggregate-error.js", "integrity": "sha512-E5rN3mgPTqyfHSovQ++ZyZWQkMUniuyjbeHHX+E4G3MStEx6TfObScB8tfHeIyuawSp86nVsFfMZjCruD61rdg==", "contentType": "application/javascript; charset=utf-8" },
"https://cdn.skypack.dev/-/clean-stack@v4.1.0-DgWUKXHVzThBBZtsHXhC/dist=es2020,mode=imports/optimized/clean-stack.js": { "resolved": "https://cdn.skypack.dev/-/clean-stack@v4.1.0-DgWUKXHVzThBBZtsHXhC/dist=es2020,mode=imports/optimized/clean-stack.js", "integrity": "sha512-1nEMT4Vc2YLu3EbeBnck7Traj0/D6G9MMSGraGpsoQIMKVuhQjq4gP76X6RxUn5GoiHv90KfrFMSWlbBn26Dhw==", "contentType": "application/javascript; charset=utf-8" },
"https://cdn.skypack.dev/-/escape-string-regexp@v5.0.0-SUDdAhYOdAgXIYndxZss/dist=es2020,mode=imports/optimized/escape-string-regexp.js": { "resolved": "https://cdn.skypack.dev/-/escape-string-regexp@v5.0.0-SUDdAhYOdAgXIYndxZss/dist=es2020,mode=imports/optimized/escape-string-regexp.js", "integrity": "sha512-54oHYow5obgsKb0twQZMNLvCH2tV5MCOY4YHB0LQH+zVonIAn7JYZseUPWhC3MMkJFK5EkeNWDAX7P2camp27g==", "contentType": "application/javascript; charset=utf-8" },
"https://cdn.skypack.dev/-/indent-string@v5.0.0-VgKPSgi4hUX5NbF4n3aC/dist=es2020,mode=imports/optimized/indent-string.js": { "resolved": "https://cdn.skypack.dev/-/indent-string@v5.0.0-VgKPSgi4hUX5NbF4n3aC/dist=es2020,mode=imports/optimized/indent-string.js", "integrity": "sha512-lSZAs06jEHkVlPMEeMtKbygGhrSmJUMVmpB6/2ChdG2F0694vRU1v6N12bUyqR5uGbbteTJ7atP5PmPtTVmlcw==", "contentType": "application/javascript; charset=utf-8" },
"https://cdn.skypack.dev/p-map": { "resolved": "https://cdn.skypack.dev/-/p-map@v5.1.0-7ixXvZxXPKKt9unR9LT0/dist=es2020,mode=imports/optimized/p-map.js", "integrity": "sha512-mZyhNJe8VlqEqafSkUGTooFrKcQPSwVjB3UxAAPqywSFD+age77uTRP6ul8uAMEQ3lllmengXX1q45igRxRcDw==", "contentType": "application/javascript; charset=utf-8" },
"https://jspm.dev/npm:@jspm/core@2.0.0-beta.8/nodelibs/os": { "resolved": "https://jspm.dev/npm:@jspm/core@2.0.0-beta.8/nodelibs/os", "integrity": "sha512-bNMLa9/IfXCZprEMIuXuHM/9s4OFAl4ZKy8r6EdXNkduLNLHQ626srFqLRdWHx6ZWGIgppc1bI9+tRJT3FzfAw==", "contentType": "application/javascript; charset=utf-8" },
"https://jspm.dev/npm:@jspm/core@2/nodelibs/os": { "resolved": "https://jspm.dev/npm:@jspm/core@2/nodelibs/os", "integrity": "sha512-rPwqsk0nq0tqTCdbeGoopnlzAVh5BsaVUsXoFKQCcb04LWJrXmOhQEwj1Yj/WHfNj2ZIPzODlZdKtWZl5bbIpA==", "contentType": "application/javascript; charset=utf-8" },
"https://jspm.dev/npm:aggregate-error@4": { "resolved": "https://jspm.dev/npm:aggregate-error@4", "integrity": "sha512-XfXd6EZ09/SKLmWFFvjPCSkqv0E08IxKc8mFm9mePyLIiEiGyAKokeFt1wql+kG8ikGmI7YqKBsDf07/I31VvA==", "contentType": "application/javascript; charset=utf-8" },
"https://jspm.dev/npm:aggregate-error@4.0.0": { "resolved": "https://jspm.dev/npm:aggregate-error@4.0.0", "integrity": "sha512-HEobsVYXVCp5H4Z+6qAlKno8XAJwHQrfF4ivR4PHrp4ttM0Yg0zDfOcsjqJOnTP5hEnKR1K6OzQdPfR2r9of4g==", "contentType": "application/javascript; charset=utf-8" },
"https://jspm.dev/npm:clean-stack@4": { "resolved": "https://jspm.dev/npm:clean-stack@4", "integrity": "sha512-3wh/QTJY4tw/GInIcn5I+0hsHSirJi8Tf3kmH85hzQsuwB5k2lghBFZyKZPO7/Ql3muvZeDgN02pYkZap59Qrw==", "contentType": "application/javascript; charset=utf-8" },
"https://jspm.dev/npm:clean-stack@4.1.0": { "resolved": "https://jspm.dev/npm:clean-stack@4.1.0", "integrity": "sha512-VgNMH/ju9thH4YuxxA5trzs0u66nzRZhMa43jkhk8q6jxlEBhd7G6ZZxswy2a0ZXiXjPQVhzXfFkAIkY/pxTOg==", "contentType": "application/javascript; charset=utf-8" },
"https://jspm.dev/npm:escape-string-regexp@5.0.0": { "resolved": "https://jspm.dev/npm:escape-string-regexp@5.0.0", "integrity": "sha512-Hz7n4npzwf0UgkdjQvLN2HxudnAzllTEM9AzJPlnzf9ktGhkwlFltPQBjEM3xyDHeTj1xI1nYpBSRVQmMCl6bw==", "contentType": "application/javascript; charset=utf-8" },
"https://jspm.dev/npm:indent-string@5": { "resolved": "https://jspm.dev/npm:indent-string@5", "integrity": "sha512-hjMQ8+LX0q8xe2sCp/DEBJW2MrVFbiDv20pK0PWwENkYCkRlyP5L4t5AUiXLEXfJLUhTVrUfZtf+hmrnGJB/zA==", "contentType": "application/javascript; charset=utf-8" },
"https://jspm.dev/npm:indent-string@5.0.0": { "resolved": "https://jspm.dev/npm:indent-string@5.0.0", "integrity": "sha512-1KRJ7I1gDWWBAXz+NpwQnlJXDiSpaxaftugln1zHywLbqhA/akcZYM6+nTdfSSuQ7wiVong69R5X9l/QKWqO7g==", "contentType": "application/javascript; charset=utf-8" },
"https://jspm.dev/npm:p-map@5.1.0": { "resolved": "https://jspm.dev/npm:p-map@5.1.0", "integrity": "sha512-Ml4ozElyzZEvq3G61nmeDVjEPVbjNzhWwIfvVcEr0OsUu58yT/ieSJWr6VSSHbNGY8B1IYjJCEO2zFrgIT9plQ==", "contentType": "application/javascript; charset=utf-8" },
"https://jspm.dev/p-map": { "resolved": "https://jspm.dev/p-map", "integrity": "sha512-Ztuu37YpSElOGm1OnAmLzhgTuTSyeDXCudBO94yRDDicb2zwUTIDEaVnHMJ6Gb7AVnKk26uubHB+Hw0XxKRnrw==", "contentType": "application/javascript; charset=utf-8" },
"version": 1
}

View File

@ -0,0 +1,3 @@
/* esm.sh - p-map@5.1.0 */
export * from "https://cdn.esm.sh/v43/p-map@5.1.0/es2015/p-map.js";
export { default } from "https://cdn.esm.sh/v43/p-map@5.1.0/es2015/p-map.js";

View File

@ -0,0 +1,3 @@
var f=Object.defineProperty;var l=(e,t,n)=>t in e?f(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var i=(e,t,n)=>(l(e,typeof t!="symbol"?t+"":t,n),n),g=(e,t,n)=>{if(!t.has(e))throw TypeError("Cannot "+n)};var c=(e,t,n)=>(g(e,t,"read from private field"),n?n.call(e):t.get(e)),o=(e,t,n)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,n)},p=(e,t,n,a)=>(g(e,t,"write to private field"),a?a.call(e,n):t.set(e,n),n);import u from"/v43/indent-string@5.0.0/es2015/indent-string.js";import m from"/v43/clean-stack@4.1.0/es2015/clean-stack.js";var d=e=>e.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g,""),r,s=class extends Error{constructor(t){o(this,r,void 0);i(this,"name","AggregateError");if(!Array.isArray(t))throw new TypeError(`Expected input to be an Array, got ${typeof t}`);t=t.map(a=>a instanceof Error?a:a!==null&&typeof a=="object"?Object.assign(new Error(a.message),a):new Error(a));let n=t.map(a=>typeof a.stack=="string"?d(m(a.stack)):String(a)).join(`
`);n=`
`+u(n,4),super(n),p(this,r,t)}get errors(){return c(this,r).slice()}};r=new WeakMap;export{s as default};

View File

@ -0,0 +1,3 @@
import s from"/v43/os-browserify@0.3.0/es2015/browser.js";import i from"/v43/escape-string-regexp@5.0.0/es2015/escape-string-regexp.js";var p=/\s+at.*[(\s](.*)\)?/,f=/^(?:(?:(?:node|node:[\w/]+|(?:(?:node:)?internal\/[\w/]*|.*node_modules\/(?:babel-polyfill|pirates)\/.*)?\w+)(?:\.js)?:\d+:\d+)|native)/,u=typeof s.homedir=="undefined"?"":s.homedir().replace(/\\/g,"/");function c(a,{pretty:l=!1,basePath:n}={}){let o=n&&new RegExp(`(at | \\()${i(n.replace(/\\/g,"/"))}`,"g");if(typeof a=="string")return a.replace(/\\/g,"/").split(`
`).filter(e=>{let r=e.match(p);if(r===null||!r[1])return!0;let t=r[1];return t.includes(".app/Contents/Resources/electron.asar")||t.includes(".app/Contents/Resources/default_app.asar")?!1:!f.test(t)}).filter(e=>e.trim()!=="").map(e=>(o&&(e=e.replace(o,"$1")),l&&(e=e.replace(p,(r,t)=>r.replace(t,t.replace(u,"~")))),e)).join(`
`)}export{c as default};

View File

@ -0,0 +1 @@
function r(e){if(typeof e!="string")throw new TypeError("Expected a string");return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}export{r as default};

View File

@ -0,0 +1 @@
function o(t,e=1,n={}){let{indent:r=" ",includeEmptyLines:p=!1}=n;if(typeof t!="string")throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof t}\``);if(typeof e!="number")throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof e}\``);if(e<0)throw new RangeError(`Expected \`count\` to be at least 0, got \`${e}\``);if(typeof r!="string")throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof r}\``);if(e===0)return t;let i=p?/^/gm:/^(?!\s*$)/gm;return t.replace(i,r.repeat(e))}export{o as default};

View File

@ -0,0 +1,2 @@
var f=Object.create;var o=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var c=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty;var d=e=>o(e,"__esModule",{value:!0});var l=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var w=(e,t,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of m(t))!p.call(e,n)&&n!=="default"&&o(e,n,{get:()=>t[n],enumerable:!(i=s(t,n))||i.enumerable});return e},a=e=>w(d(o(e!=null?f(c(e)):{},"default",e&&e.__esModule&&"default"in e?{get:()=>e.default,enumerable:!0}:{value:e,enumerable:!0})),e);var u=l(r=>{r.endianness=function(){return"LE"};r.hostname=function(){return typeof location!="undefined"?location.hostname:""};r.loadavg=function(){return[]};r.uptime=function(){return 0};r.freemem=function(){return Number.MAX_VALUE};r.totalmem=function(){return Number.MAX_VALUE};r.cpus=function(){return[]};r.type=function(){return"Browser"};r.release=function(){return typeof navigator!="undefined"?navigator.appVersion:""};r.networkInterfaces=r.getNetworkInterfaces=function(){return{}};r.arch=function(){return"javascript"};r.platform=function(){return"browser"};r.tmpdir=r.tmpDir=function(){return"/tmp"};r.EOL=`
`;r.homedir=function(){return"/"}});var b=a(u()),h=a(u()),{cpus:v,release:E,tmpDir:L,loadavg:k,uptime:A,totalmem:I,arch:N,tmpdir:_,homedir:V,endianness:x,hostname:D,type:M,freemem:O,networkInterfaces:U,getNetworkInterfaces:X,platform:j,EOL:B}=b;var export_default=h.default;export{B as EOL,N as arch,v as cpus,export_default as default,x as endianness,O as freemem,X as getNetworkInterfaces,V as homedir,D as hostname,k as loadavg,U as networkInterfaces,j as platform,E as release,L as tmpDir,_ as tmpdir,I as totalmem,M as type,A as uptime};

View File

@ -0,0 +1 @@
var m=(p,s,e)=>new Promise((f,x)=>{var h=t=>{try{o(e.next(t))}catch(r){x(r)}},l=t=>{try{o(e.throw(t))}catch(r){x(r)}},o=t=>t.done?f(t.value):Promise.resolve(t.value).then(h,l);o((e=e.apply(p,s)).next())});import S from"/v43/aggregate-error@4.0.0/es2015/aggregate-error.js";function N(x,h){return m(this,arguments,function*(p,s,{concurrency:e=Number.POSITIVE_INFINITY,stopOnError:f=!0}={}){return new Promise((l,o)=>{if(typeof s!="function")throw new TypeError("Mapper function is required");if(!((Number.isSafeInteger(e)||e===Number.POSITIVE_INFINITY)&&e>=1))throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${e}\` (${typeof e})`);let t=[],r=[],g=[],y=p[Symbol.iterator](),u=!1,c=!1,a=0,b=0,I=()=>{if(u)return;let i=y.next(),d=b;if(b++,i.done){if(c=!0,a===0)if(!f&&r.length>0)o(new S(r));else{for(let n of g)t.splice(n,1);l(t)}return}a++,(()=>m(this,null,function*(){try{let n=yield i.value;if(u)return;let w=yield s(n,d);w===T?g.push(d):t[d]=w,a--,I()}catch(n){f?(u=!0,o(n)):(r.push(n),a--,I())}}))()};for(let i=0;i<e&&(I(),!c);i++);})})}var T=Symbol("skip");export{N as default};

View File

@ -0,0 +1,54 @@
var __defProp = Object.defineProperty;
var __publicField = (obj, key, value) => {
if (typeof key !== "symbol")
key += "";
if (key in obj)
return __defProp(obj, key, {enumerable: true, configurable: true, writable: true, value});
return obj[key] = value;
};
var __accessCheck = (obj, member, msg) => {
if (!member.has(obj))
throw TypeError("Cannot " + msg);
};
var __privateGet = (obj, member, getter) => {
__accessCheck(obj, member, "read from private field");
return getter ? getter.call(obj) : member.get(obj);
};
var __privateSet = (obj, member, value, setter) => {
__accessCheck(obj, member, "write to private field");
setter ? setter.call(obj, value) : member.set(obj, value);
return value;
};
var _errors;
import indentString from "/-/indent-string@v5.0.0-VgKPSgi4hUX5NbF4n3aC/dist=es2020,mode=imports/optimized/indent-string.js";
import cleanStack from "/-/clean-stack@v4.1.0-DgWUKXHVzThBBZtsHXhC/dist=es2020,mode=imports/optimized/clean-stack.js";
const cleanInternalStack = (stack) => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, "");
class AggregateError extends Error {
constructor(errors) {
_errors.set(this, void 0);
__publicField(this, "name", "AggregateError");
if (!Array.isArray(errors)) {
throw new TypeError(`Expected input to be an Array, got ${typeof errors}`);
}
errors = errors.map((error) => {
if (error instanceof Error) {
return error;
}
if (error !== null && typeof error === "object") {
return Object.assign(new Error(error.message), error);
}
return new Error(error);
});
let message = errors.map((error) => {
return typeof error.stack === "string" ? cleanInternalStack(cleanStack(error.stack)) : String(error);
}).join("\n");
message = "\n" + indentString(message, 4);
super(message);
__privateSet(this, _errors, errors);
}
get errors() {
return __privateGet(this, _errors).slice();
}
}
_errors = new WeakMap();
export default AggregateError;

View File

@ -0,0 +1,31 @@
import escapeStringRegexp from "/-/escape-string-regexp@v5.0.0-SUDdAhYOdAgXIYndxZss/dist=es2020,mode=imports/optimized/escape-string-regexp.js";
var os = {};
const extractPathRegex = /\s+at.*[(\s](.*)\)?/;
const pathRegex = /^(?:(?:(?:node|node:[\w/]+|(?:(?:node:)?internal\/[\w/]*|.*node_modules\/(?:babel-polyfill|pirates)\/.*)?\w+)(?:\.js)?:\d+:\d+)|native)/;
const homeDir = typeof os.homedir === "undefined" ? "" : os.homedir().replace(/\\/g, "/");
function cleanStack(stack, {pretty = false, basePath} = {}) {
const basePathRegex = basePath && new RegExp(`(at | \\()${escapeStringRegexp(basePath.replace(/\\/g, "/"))}`, "g");
if (typeof stack !== "string") {
return void 0;
}
return stack.replace(/\\/g, "/").split("\n").filter((line) => {
const pathMatches = line.match(extractPathRegex);
if (pathMatches === null || !pathMatches[1]) {
return true;
}
const match = pathMatches[1];
if (match.includes(".app/Contents/Resources/electron.asar") || match.includes(".app/Contents/Resources/default_app.asar")) {
return false;
}
return !pathRegex.test(match);
}).filter((line) => line.trim() !== "").map((line) => {
if (basePathRegex) {
line = line.replace(basePathRegex, "$1");
}
if (pretty) {
line = line.replace(extractPathRegex, (m, p1) => m.replace(p1, p1.replace(homeDir, "~")));
}
return line;
}).join("\n");
}
export default cleanStack;

View File

@ -0,0 +1,7 @@
function escapeStringRegexp(string) {
if (typeof string !== "string") {
throw new TypeError("Expected a string");
}
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
}
export default escapeStringRegexp;

View File

@ -0,0 +1,24 @@
function indentString(string, count = 1, options = {}) {
const {
indent = " ",
includeEmptyLines = false
} = options;
if (typeof string !== "string") {
throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof string}\``);
}
if (typeof count !== "number") {
throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof count}\``);
}
if (count < 0) {
throw new RangeError(`Expected \`count\` to be at least 0, got \`${count}\``);
}
if (typeof indent !== "string") {
throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof indent}\``);
}
if (count === 0) {
return string;
}
const regex = includeEmptyLines ? /^/gm : /^(?!\s*$)/gm;
return string.replace(regex, indent.repeat(count));
}
export default indentString;

View File

@ -0,0 +1,79 @@
import AggregateError from "/-/aggregate-error@v4.0.0-rCH8s5R9g4kQQ807o58j/dist=es2020,mode=imports/optimized/aggregate-error.js";
async function pMap(iterable, mapper, {
concurrency = Number.POSITIVE_INFINITY,
stopOnError = true
} = {}) {
return new Promise((resolve, reject) => {
if (typeof mapper !== "function") {
throw new TypeError("Mapper function is required");
}
if (!((Number.isSafeInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency >= 1)) {
throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
}
const result = [];
const errors = [];
const skippedIndexes = [];
const iterator = iterable[Symbol.iterator]();
let isRejected = false;
let isIterableDone = false;
let resolvingCount = 0;
let currentIndex = 0;
const next = () => {
if (isRejected) {
return;
}
const nextItem = iterator.next();
const index = currentIndex;
currentIndex++;
if (nextItem.done) {
isIterableDone = true;
if (resolvingCount === 0) {
if (!stopOnError && errors.length > 0) {
reject(new AggregateError(errors));
} else {
for (const skippedIndex of skippedIndexes) {
result.splice(skippedIndex, 1);
}
resolve(result);
}
}
return;
}
resolvingCount++;
(async () => {
try {
const element = await nextItem.value;
if (isRejected) {
return;
}
const value = await mapper(element, index);
if (value === pMapSkip) {
skippedIndexes.push(index);
} else {
result[index] = value;
}
resolvingCount--;
next();
} catch (error) {
if (stopOnError) {
isRejected = true;
reject(error);
} else {
errors.push(error);
resolvingCount--;
next();
}
}
})();
};
for (let index = 0; index < concurrency; index++) {
next();
if (isIterableDone) {
break;
}
}
});
}
const pMapSkip = Symbol("skip");
export default pMap;
export {pMapSkip};

View File

@ -0,0 +1,48 @@
import indentString from './npm:indent-string@5';
import cleanStack from './npm:clean-stack@4';
const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, '');
class AggregateError extends Error {
#errors;
name = 'AggregateError';
constructor(errors) {
if (!Array.isArray(errors)) {
throw new TypeError(`Expected input to be an Array, got ${typeof errors}`);
}
errors = errors.map(error => {
if (error instanceof Error) {
return error;
}
if (error !== null && typeof error === 'object') {
// Handle plain error objects with message property and/or possibly other metadata
return Object.assign(new Error(error.message), error);
}
return new Error(error);
});
let message = errors
.map(error => {
// The `stack` property is not standardized, so we can't assume it exists
return typeof error.stack === 'string' ? cleanInternalStack(cleanStack(error.stack)) : String(error);
})
.join('\n');
message = '\n' + indentString(message, 4);
super(message);
this.#errors = errors;
}
get errors() {
return this.#errors.slice();
}
}
export default AggregateError;
//# sourceMappingURL=npm:aggregate-error@4.0.0.map

View File

@ -0,0 +1,3 @@
import "/npm:indent-string@5";
import "/npm:clean-stack@4";
export { default } from "/npm:aggregate-error@4.0.0";

View File

@ -0,0 +1,52 @@
import os from './npm:@jspm/core@2/nodelibs/os';
import escapeStringRegexp from './npm:escape-string-regexp@5.0.0';
const extractPathRegex = /\s+at.*[(\s](.*)\)?/;
const pathRegex = /^(?:(?:(?:node|node:[\w/]+|(?:(?:node:)?internal\/[\w/]*|.*node_modules\/(?:babel-polyfill|pirates)\/.*)?\w+)(?:\.js)?:\d+:\d+)|native)/;
const homeDir = typeof os.homedir === 'undefined' ? '' : os.homedir().replace(/\\/g, '/');
function cleanStack(stack, {pretty = false, basePath} = {}) {
const basePathRegex = basePath && new RegExp(`(at | \\()${escapeStringRegexp(basePath.replace(/\\/g, '/'))}`, 'g');
if (typeof stack !== 'string') {
return undefined;
}
return stack.replace(/\\/g, '/')
.split('\n')
.filter(line => {
const pathMatches = line.match(extractPathRegex);
if (pathMatches === null || !pathMatches[1]) {
return true;
}
const match = pathMatches[1];
// Electron
if (
match.includes('.app/Contents/Resources/electron.asar') ||
match.includes('.app/Contents/Resources/default_app.asar')
) {
return false;
}
return !pathRegex.test(match);
})
.filter(line => line.trim() !== '')
.map(line => {
if (basePathRegex) {
line = line.replace(basePathRegex, '$1');
}
if (pretty) {
line = line.replace(extractPathRegex, (m, p1) => m.replace(p1, p1.replace(homeDir, '~')));
}
return line;
})
.join('\n');
}
export default cleanStack;
//# sourceMappingURL=npm:clean-stack@4.1.0.map

View File

@ -0,0 +1,3 @@
import "/npm:@jspm/core@2/nodelibs/os";
import "/npm:escape-string-regexp@5.0.0";
export { default } from "/npm:clean-stack@4.1.0";

View File

@ -0,0 +1,15 @@
function escapeStringRegexp(string) {
if (typeof string !== 'string') {
throw new TypeError('Expected a string');
}
// Escape characters with special meaning either inside or outside character sets.
// Use a simple backslash escape when its always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns stricter grammar.
return string
.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
.replace(/-/g, '\\x2d');
}
export default escapeStringRegexp;
//# sourceMappingURL=npm:escape-string-regexp@5.0.0.map

View File

@ -0,0 +1,42 @@
function indentString(string, count = 1, options = {}) {
const {
indent = ' ',
includeEmptyLines = false
} = options;
if (typeof string !== 'string') {
throw new TypeError(
`Expected \`input\` to be a \`string\`, got \`${typeof string}\``
);
}
if (typeof count !== 'number') {
throw new TypeError(
`Expected \`count\` to be a \`number\`, got \`${typeof count}\``
);
}
if (count < 0) {
throw new RangeError(
`Expected \`count\` to be at least 0, got \`${count}\``
);
}
if (typeof indent !== 'string') {
throw new TypeError(
`Expected \`options.indent\` to be a \`string\`, got \`${typeof indent}\``
);
}
if (count === 0) {
return string;
}
const regex = includeEmptyLines ? /^/gm : /^(?!\s*$)/gm;
return string.replace(regex, indent.repeat(count));
}
export default indentString;
//# sourceMappingURL=npm:indent-string@5.0.0.map

View File

@ -0,0 +1 @@
export { default } from "/npm:indent-string@5.0.0";

View File

@ -0,0 +1,97 @@
var exports = {},
_dewExec = false;
function dew() {
if (_dewExec) return exports;
_dewExec = true;
exports.endianness = function () {
return "LE";
};
exports.hostname = function () {
if (typeof location !== "undefined") {
return location.hostname;
} else return "";
};
exports.loadavg = function () {
return [];
};
exports.uptime = function () {
return 0;
};
exports.freemem = function () {
return Number.MAX_VALUE;
};
exports.totalmem = function () {
return Number.MAX_VALUE;
};
exports.cpus = function () {
return [];
};
exports.type = function () {
return "Browser";
};
exports.release = function () {
if (typeof navigator !== "undefined") {
return navigator.appVersion;
}
return "";
};
exports.networkInterfaces = exports.getNetworkInterfaces = function () {
return {};
};
exports.arch = function () {
return "javascript";
};
exports.platform = function () {
return "browser";
};
exports.tmpdir = exports.tmpDir = function () {
return "/tmp";
};
exports.EOL = "\n";
exports.homedir = function () {
return "/";
};
return exports;
}
var os = dew();
var EOL = os.EOL;
var arch = os.arch;
var cpus = os.cpus;
var endianness = os.endianness;
var freemem = os.freemem;
var getNetworkInterfaces = os.getNetworkInterfaces;
var homedir = os.homedir;
var hostname = os.hostname;
var loadavg = os.loadavg;
var networkInterfaces = os.networkInterfaces;
var platform = os.platform;
var release = os.release;
var tmpDir = os.tmpDir;
var tmpdir = os.tmpdir;
var totalmem = os.totalmem;
var type = os.type;
var uptime = os.uptime;
export default os;
export { EOL, arch, cpus, endianness, freemem, getNetworkInterfaces, homedir, hostname, loadavg, networkInterfaces, platform, release, tmpDir, tmpdir, totalmem, type, uptime };
//# sourceMappingURL=os.map

View File

@ -0,0 +1,2 @@
export * from "/npm:@jspm/core@2.0.0-beta.8/nodelibs/os";
export { default } from "/npm:@jspm/core@2.0.0-beta.8/nodelibs/os";

View File

@ -0,0 +1,103 @@
import AggregateError from './npm:aggregate-error@4';
async function pMap(
iterable,
mapper,
{
concurrency = Number.POSITIVE_INFINITY,
stopOnError = true
} = {}
) {
return new Promise((resolve, reject) => {
if (typeof mapper !== 'function') {
throw new TypeError('Mapper function is required');
}
if (!((Number.isSafeInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency >= 1)) {
throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
}
const result = [];
const errors = [];
const skippedIndexes = [];
const iterator = iterable[Symbol.iterator]();
let isRejected = false;
let isIterableDone = false;
let resolvingCount = 0;
let currentIndex = 0;
const next = () => {
if (isRejected) {
return;
}
const nextItem = iterator.next();
const index = currentIndex;
currentIndex++;
if (nextItem.done) {
isIterableDone = true;
if (resolvingCount === 0) {
if (!stopOnError && errors.length > 0) {
reject(new AggregateError(errors));
} else {
for (const skippedIndex of skippedIndexes) {
result.splice(skippedIndex, 1);
}
resolve(result);
}
}
return;
}
resolvingCount++;
(async () => {
try {
const element = await nextItem.value;
if (isRejected) {
return;
}
const value = await mapper(element, index);
if (value === pMapSkip) {
skippedIndexes.push(index);
} else {
result[index] = value;
}
resolvingCount--;
next();
} catch (error) {
if (stopOnError) {
isRejected = true;
reject(error);
} else {
errors.push(error);
resolvingCount--;
next();
}
}
})();
};
for (let index = 0; index < concurrency; index++) {
next();
if (isIterableDone) {
break;
}
}
});
}
const pMapSkip = Symbol('skip');
export default pMap;
export { pMapSkip };
//# sourceMappingURL=npm:p-map@5.1.0.map

View File

@ -0,0 +1,3 @@
import "/npm:aggregate-error@4";
export * from "/npm:p-map@5.1.0";
export { default } from "/npm:p-map@5.1.0";

View File

@ -1302,6 +1302,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
module.needBuild(
{
compilation: this,
fileSystemInfo: this.fileSystemInfo,
valueCacheVersions: this.valueCacheVersions
},

View File

@ -93,6 +93,7 @@ const makeSerializable = require("./util/makeSerializable");
/**
* @typedef {Object} NeedBuildContext
* @property {Compilation} compilation
* @property {FileSystemInfo} fileSystemInfo
* @property {Map<string, string | Set<string>>} valueCacheVersions
*/

View File

@ -87,7 +87,6 @@ module.exports = class MultiCompiler {
const compiler = this.compilers[index];
const compilerIndex = index;
let compilerDone = false;
// eslint-disable-next-line no-loop-func
compiler.hooks.done.tap("MultiCompiler", stats => {
if (!compilerDone) {
compilerDone = true;
@ -98,7 +97,6 @@ module.exports = class MultiCompiler {
this.hooks.done.call(new MultiStats(compilerStats));
}
});
// eslint-disable-next-line no-loop-func
compiler.hooks.invalid.tap("MultiCompiler", () => {
if (compilerDone) {
compilerDone = false;

View File

@ -16,6 +16,7 @@ const {
SourceMapSource
} = require("webpack-sources");
const Compilation = require("./Compilation");
const HookWebpackError = require("./HookWebpackError");
const Module = require("./Module");
const ModuleBuildError = require("./ModuleBuildError");
const ModuleError = require("./ModuleError");
@ -178,6 +179,7 @@ makeSerializable(
* @property {SyncHook<[object, NormalModule]>} loader
* @property {SyncHook<[LoaderItem[], NormalModule, object]>} beforeLoaders
* @property {HookMap<AsyncSeriesBailHook<[string, NormalModule], string | Buffer>>} readResourceForScheme
* @property {AsyncSeriesBailHook<[NormalModule, NeedBuildContext], boolean>} needBuild
*/
/** @type {WeakMap<Compilation, NormalModuleCompilationHooks>} */
@ -201,7 +203,8 @@ class NormalModule extends Module {
beforeLoaders: new SyncHook(["loaders", "module", "loaderContext"]),
readResourceForScheme: new HookMap(
() => new AsyncSeriesBailHook(["resource", "module"])
)
),
needBuild: new AsyncSeriesBailHook(["module", "context"])
};
compilationHooksMap.set(compilation, hooks);
}
@ -751,6 +754,13 @@ class NormalModule extends Module {
const hooks = NormalModule.getCompilationHooks(compilation);
this.buildInfo.fileDependencies = new LazySet();
this.buildInfo.contextDependencies = new LazySet();
this.buildInfo.missingDependencies = new LazySet();
if (this.loaders.length > 0) {
this.buildInfo.buildDependencies = new LazySet();
}
this.buildInfo.cacheable = true;
try {
hooks.beforeLoaders.call(this.loaders, this, loaderContext);
} catch (err) {
@ -762,7 +772,8 @@ class NormalModule extends Module {
resource: this.resource,
loaders: this.loaders,
context: loaderContext,
processResource: (loaderContext, resource, callback) => {
processResource: (loaderContext, resourcePath, callback) => {
const resource = loaderContext.resource;
const scheme = getScheme(resource);
if (scheme) {
hooks.readResourceForScheme
@ -775,8 +786,8 @@ class NormalModule extends Module {
return callback(null, result);
});
} else {
loaderContext.addDependency(resource);
fs.readFile(resource, callback);
loaderContext.addDependency(resourcePath);
fs.readFile(resourcePath, callback);
}
}
},
@ -789,27 +800,19 @@ class NormalModule extends Module {
undefined;
if (!result) {
this.buildInfo.cacheable = false;
return processResult(
err || new Error("No result from loader-runner processing"),
null
);
}
this.buildInfo.fileDependencies = new LazySet();
this.buildInfo.fileDependencies.addAll(result.fileDependencies);
this.buildInfo.contextDependencies = new LazySet();
this.buildInfo.contextDependencies.addAll(result.contextDependencies);
this.buildInfo.missingDependencies = new LazySet();
this.buildInfo.missingDependencies.addAll(result.missingDependencies);
if (
this.loaders.length > 0 &&
this.buildInfo.buildDependencies === undefined
) {
this.buildInfo.buildDependencies = new LazySet();
}
for (const loader of this.loaders) {
this.buildInfo.buildDependencies.add(loader.loader);
}
this.buildInfo.cacheable = result.cacheable;
this.buildInfo.cacheable = this.buildInfo.cacheable && result.cacheable;
processResult(err, result.result);
}
);
@ -1178,7 +1181,8 @@ class NormalModule extends Module {
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild({ fileSystemInfo, valueCacheVersions }, callback) {
needBuild(context, callback) {
const { fileSystemInfo, compilation, valueCacheVersions } = context;
// build if enforced
if (this._forceBuild) return callback(null, true);
@ -1213,7 +1217,20 @@ class NormalModule extends Module {
// check snapshot for validity
fileSystemInfo.checkSnapshotValid(this.buildInfo.snapshot, (err, valid) => {
callback(err, !valid);
if (err) return callback(err);
if (!valid) return callback(null, true);
const hooks = NormalModule.getCompilationHooks(compilation);
hooks.needBuild.callAsync(this, context, (err, needBuild) => {
if (err) {
return callback(
HookWebpackError.makeWebpackError(
err,
"NormalModule.getCompilationHooks().needBuild"
)
);
}
callback(null, !!needBuild);
});
});
}

View File

@ -66,6 +66,7 @@ const { parseResource } = require("./util/identifier");
const EMPTY_RESOLVE_OPTIONS = {};
const EMPTY_PARSER_OPTIONS = {};
const EMPTY_GENERATOR_OPTIONS = {};
const EMPTY_ELEMENTS = [];
const MATCH_RESOURCE_REGEX = /^([^!]+)!=!/;
@ -220,6 +221,10 @@ class NormalModuleFactory extends ModuleFactory {
resolveForScheme: new HookMap(
() => new AsyncSeriesBailHook(["resourceData", "resolveData"])
),
/** @type {HookMap<AsyncSeriesBailHook<[ResourceDataWithData, ResolveData], true | void>>} */
resolveInScheme: new HookMap(
() => new AsyncSeriesBailHook(["resourceData", "resolveData"])
),
/** @type {AsyncSeriesBailHook<[ResolveData], TODO>} */
factorize: new AsyncSeriesBailHook(["resolveData"]),
/** @type {AsyncSeriesBailHook<[ResolveData], TODO>} */
@ -354,42 +359,71 @@ class NormalModuleFactory extends ModuleFactory {
/** @type {ResourceData | undefined} */
let matchResourceData = undefined;
/** @type {string} */
let requestWithoutMatchResource = request;
const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request);
if (matchResourceMatch) {
let matchResource = matchResourceMatch[1];
if (matchResource.charCodeAt(0) === 46) {
// 46 === ".", 47 === "/"
const secondChar = matchResource.charCodeAt(1);
if (
secondChar === 47 ||
(secondChar === 46 && matchResource.charCodeAt(2) === 47)
) {
// if matchResources startsWith ../ or ./
matchResource = join(this.fs, context, matchResource);
}
}
matchResourceData = {
resource: matchResource,
...cacheParseResource(matchResource)
};
requestWithoutMatchResource = request.substr(
matchResourceMatch[0].length
);
}
let unresolvedResource;
/** @type {{loader: string, options: string|undefined}[]} */
let elements;
let noPreAutoLoaders = false;
let noAutoLoaders = false;
let noPrePostAutoLoaders = false;
const firstChar = requestWithoutMatchResource.charCodeAt(0);
const secondChar = requestWithoutMatchResource.charCodeAt(1);
const noPreAutoLoaders = firstChar === 45 && secondChar === 33; // startsWith "-!"
const noAutoLoaders = noPreAutoLoaders || firstChar === 33; // startsWith "!"
const noPrePostAutoLoaders = firstChar === 33 && secondChar === 33; // startsWith "!!";
const rawElements = requestWithoutMatchResource
.slice(
noPreAutoLoaders || noPrePostAutoLoaders ? 2 : noAutoLoaders ? 1 : 0
)
.split(/!+/);
const unresolvedResource = rawElements.pop();
const elements = rawElements.map(identToLoaderRequest);
const contextScheme = getScheme(context);
/** @type {string | undefined} */
let scheme = getScheme(request);
if (!scheme) {
/** @type {string} */
let requestWithoutMatchResource = request;
const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request);
if (matchResourceMatch) {
let matchResource = matchResourceMatch[1];
if (matchResource.charCodeAt(0) === 46) {
// 46 === ".", 47 === "/"
const secondChar = matchResource.charCodeAt(1);
if (
secondChar === 47 ||
(secondChar === 46 && matchResource.charCodeAt(2) === 47)
) {
// if matchResources startsWith ../ or ./
matchResource = join(this.fs, context, matchResource);
}
}
matchResourceData = {
resource: matchResource,
...cacheParseResource(matchResource)
};
requestWithoutMatchResource = request.substr(
matchResourceMatch[0].length
);
}
scheme = getScheme(requestWithoutMatchResource);
if (!scheme && !contextScheme) {
const firstChar = requestWithoutMatchResource.charCodeAt(0);
const secondChar = requestWithoutMatchResource.charCodeAt(1);
noPreAutoLoaders = firstChar === 45 && secondChar === 33; // startsWith "-!"
noAutoLoaders = noPreAutoLoaders || firstChar === 33; // startsWith "!"
noPrePostAutoLoaders = firstChar === 33 && secondChar === 33; // startsWith "!!";
const rawElements = requestWithoutMatchResource
.slice(
noPreAutoLoaders || noPrePostAutoLoaders
? 2
: noAutoLoaders
? 1
: 0
)
.split(/!+/);
unresolvedResource = rawElements.pop();
elements = rawElements.map(identToLoaderRequest);
scheme = getScheme(unresolvedResource);
} else {
unresolvedResource = requestWithoutMatchResource;
elements = EMPTY_ELEMENTS;
}
} else {
unresolvedResource = request;
elements = EMPTY_ELEMENTS;
}
const resolveContext = {
fileDependencies,
@ -399,8 +433,6 @@ class NormalModuleFactory extends ModuleFactory {
/** @type {ResourceDataWithData} */
let resourceData;
/** @type {string | undefined} */
const scheme = getScheme(unresolvedResource);
let loaders;
@ -594,7 +626,7 @@ class NormalModuleFactory extends ModuleFactory {
this.resolveRequestArray(
contextInfo,
context,
contextScheme ? this.context : context,
elements,
loaderResolver,
resolveContext,
@ -605,6 +637,49 @@ class NormalModuleFactory extends ModuleFactory {
}
);
const defaultResolve = context => {
if (/^($|\?)/.test(unresolvedResource)) {
resourceData = {
resource: unresolvedResource,
data: {},
...cacheParseResource(unresolvedResource)
};
continueCallback();
}
// resource without scheme and with path
else {
const normalResolver = this.getResolver(
"normal",
dependencyType
? cachedSetProperty(
resolveOptions || EMPTY_RESOLVE_OPTIONS,
"dependencyType",
dependencyType
)
: resolveOptions
);
this.resolveResource(
contextInfo,
context,
unresolvedResource,
normalResolver,
resolveContext,
(err, resolvedResource, resolvedResourceResolveData) => {
if (err) return continueCallback(err);
if (resolvedResource !== false) {
resourceData = {
resource: resolvedResource,
data: resolvedResourceResolveData,
...cacheParseResource(resolvedResource)
};
}
continueCallback();
}
);
}
};
// resource with scheme
if (scheme) {
resourceData = {
@ -622,47 +697,26 @@ class NormalModuleFactory extends ModuleFactory {
});
}
// resource without scheme and without path
else if (/^($|\?)/.test(unresolvedResource)) {
// resource within scheme
else if (contextScheme) {
resourceData = {
resource: unresolvedResource,
data: {},
...cacheParseResource(unresolvedResource)
path: undefined,
query: undefined,
fragment: undefined
};
continueCallback();
this.hooks.resolveInScheme
.for(contextScheme)
.callAsync(resourceData, data, (err, handled) => {
if (err) return continueCallback(err);
if (!handled) return defaultResolve(this.context);
continueCallback();
});
}
// resource without scheme and with path
else {
const normalResolver = this.getResolver(
"normal",
dependencyType
? cachedSetProperty(
resolveOptions || EMPTY_RESOLVE_OPTIONS,
"dependencyType",
dependencyType
)
: resolveOptions
);
this.resolveResource(
contextInfo,
context,
unresolvedResource,
normalResolver,
resolveContext,
(err, resolvedResource, resolvedResourceResolveData) => {
if (err) return continueCallback(err);
if (resolvedResource !== false) {
resourceData = {
resource: resolvedResource,
data: resolvedResourceResolveData,
...cacheParseResource(resolvedResource)
};
}
continueCallback();
}
);
}
// resource without scheme and without path
else defaultResolve(context);
}
);
}

View File

@ -276,6 +276,14 @@ class WebpackOptionsApply extends OptionsApply {
}).apply(compiler);
}
if (options.experiments.buildHttp) {
const HttpUriPlugin = require("./schemes/HttpUriPlugin");
const httpOptions = options.experiments.buildHttp;
if (httpOptions === true)
throw new Error("Unexpected due to normalization");
new HttpUriPlugin(httpOptions).apply(compiler);
}
new EntryOptionPlugin().apply(compiler);
compiler.hooks.entryOption.call(options.context, options.entry);

View File

@ -120,7 +120,6 @@ class AssetModulesPlugin {
for (const type of ["asset", "asset/inline", "asset/resource"]) {
normalModuleFactory.hooks.createGenerator
.for(type)
// eslint-disable-next-line no-loop-func
.tap(plugin, generatorOptions => {
validateGeneratorOptions[type](generatorOptions);

View File

@ -171,7 +171,7 @@ const applyWebpackOptionsDefaults = options => {
applySnapshotDefaults(options.snapshot, { production });
applyExperimentsDefaults(options.experiments);
applyExperimentsDefaults(options.experiments, { production, development });
applyModuleDefaults(options.module, {
cache,
@ -193,7 +193,10 @@ const applyWebpackOptionsDefaults = options => {
module: options.module
});
applyExternalsPresetsDefaults(options.externalsPresets, { targetProperties });
applyExternalsPresetsDefaults(options.externalsPresets, {
targetProperties,
buildHttp: !!options.experiments.buildHttp
});
applyLoaderDefaults(options.loader, { targetProperties });
@ -245,13 +248,26 @@ const applyWebpackOptionsDefaults = options => {
/**
* @param {Experiments} experiments options
* @param {Object} options options
* @param {boolean} options.production is production
* @param {boolean} options.development is development mode
* @returns {void}
*/
const applyExperimentsDefaults = experiments => {
const applyExperimentsDefaults = (experiments, { production, development }) => {
D(experiments, "topLevelAwait", false);
D(experiments, "syncWebAssembly", false);
D(experiments, "asyncWebAssembly", false);
D(experiments, "outputModule", false);
D(experiments, "asset", false);
D(experiments, "executeModule", false);
D(experiments, "layers", false);
D(experiments, "lazyCompilation", false);
D(experiments, "buildHttp", false);
if (typeof experiments.buildHttp === "object") {
D(experiments.buildHttp, "frozen", production);
D(experiments.buildHttp, "upgrade", development);
}
};
/**
@ -860,13 +876,18 @@ const applyOutputDefaults = (
* @param {ExternalsPresets} externalsPresets options
* @param {Object} options options
* @param {TargetProperties | false} options.targetProperties target properties
* @param {boolean} options.buildHttp buildHttp experiment enabled
* @returns {void}
*/
const applyExternalsPresetsDefaults = (
externalsPresets,
{ targetProperties }
{ targetProperties, buildHttp }
) => {
D(externalsPresets, "web", targetProperties && targetProperties.web);
D(
externalsPresets,
"web",
!buildHttp && targetProperties && targetProperties.web
);
D(externalsPresets, "node", targetProperties && targetProperties.node);
D(externalsPresets, "nwjs", targetProperties && targetProperties.nwjs);
D(

View File

@ -171,7 +171,12 @@ const getNormalizedWebpackOptions = config => {
Promise.resolve().then(fn).then(getNormalizedEntryStatic)
)(config.entry)
: getNormalizedEntryStatic(config.entry),
experiments: cloneObject(config.experiments),
experiments: nestedConfig(config.experiments, experiments => ({
...experiments,
buildHttp: optionalNestedConfig(experiments.buildHttp, options =>
options === true ? {} : options
)
})),
externals: config.externals,
externalsPresets: cloneObject(config.externalsPresets),
externalsType: config.externalsType,

View File

@ -554,9 +554,6 @@ module.exports = mergeExports(fn, {
schemes: {
get HttpUriPlugin() {
return require("./schemes/HttpUriPlugin");
},
get HttpsUriPlugin() {
return require("./schemes/HttpsUriPlugin");
}
}
}

View File

@ -5,56 +5,963 @@
"use strict";
const { resolve, extname, dirname } = require("path");
const { URL } = require("url");
const { createGunzip, createBrotliDecompress, createInflate } = require("zlib");
const NormalModule = require("../NormalModule");
const createHash = require("../util/createHash");
const { mkdirp } = require("../util/fs");
const memoize = require("../util/memoize");
/** @typedef {import("../../declarations/plugins/schemes/HttpUriPlugin").HttpUriPluginOptions} HttpUriPluginOptions */
/** @typedef {import("../Compiler")} Compiler */
const getHttp = memoize(() => require("http"));
const getHttps = memoize(() => require("https"));
const toSafePath = str =>
str
.replace(/^[^a-zA-Z0-9]+|[^a-zA-Z0-9]+$/g, "")
.replace(/[^a-zA-Z0-9._-]+/g, "_");
const computeIntegrity = content => {
const hash = createHash("sha512");
hash.update(content);
const integrity = "sha512-" + hash.digest("base64");
return integrity;
};
const verifyIntegrity = (content, integrity) => {
if (integrity === "ignore") return true;
return computeIntegrity(content) === integrity;
};
/**
* @param {string} str input
* @returns {Record<string, string>} parsed
*/
const parseKeyValuePairs = str => {
/** @type {Record<string, string>} */
const result = {};
for (const item of str.split(",")) {
const i = item.indexOf("=");
if (i >= 0) {
const key = item.slice(0, i).trim();
const value = item.slice(i + 1).trim();
result[key] = value;
} else {
const key = item.trim();
if (!key) continue;
result[key] = key;
}
}
return result;
};
const parseCacheControl = (cacheControl, requestTime) => {
// When false resource is not stored in cache
let storeCache = true;
// When false resource is not stored in lockfile cache
let storeLock = true;
// Resource is only revalidated, after that timestamp and when upgrade is chosen
let validUntil = 0;
if (cacheControl) {
const parsed = parseKeyValuePairs(cacheControl);
if (parsed["no-cache"]) storeCache = storeLock = false;
if (parsed["max-age"] && !isNaN(+parsed["max-age"])) {
validUntil = requestTime + +parsed["max-age"] * 1000;
}
if (parsed["must-revalidate"]) validUntil = 0;
}
return {
storeLock,
storeCache,
validUntil
};
};
/**
* @typedef {Object} LockfileEntry
* @property {string} resolved
* @property {string} integrity
* @property {string} contentType
*/
const areLockfileEntriesEqual = (a, b) => {
return (
a.resolved === b.resolved &&
a.integrity === b.integrity &&
a.contentType === b.contentType
);
};
const entryToString = entry => {
return `resolved: ${entry.resolved}, integrity: ${entry.integrity}, contentType: ${entry.contentType}`;
};
class Lockfile {
constructor() {
this.version = 1;
/** @type {Map<string, LockfileEntry | "ignore" | "no-cache">} */
this.entries = new Map();
this.outdated = false;
}
static parse(content) {
// TODO handle merge conflicts
const data = JSON.parse(content);
if (data.version !== 1)
throw new Error(`Unsupported lockfile version ${data.version}`);
const lockfile = new Lockfile();
for (const key of Object.keys(data)) {
if (key === "version") continue;
const entry = data[key];
lockfile.entries.set(key, entry);
}
return lockfile;
}
toString() {
let str = "{\n";
const entries = Array.from(this.entries).sort(([a], [b]) =>
a < b ? -1 : 1
);
for (const [key, entry] of entries) {
if (typeof entry === "string") {
str += ` ${JSON.stringify(key)}: ${JSON.stringify(entry)},\n`;
} else {
str += ` ${JSON.stringify(key)}: { "resolved": ${JSON.stringify(
entry.resolved
)}, "integrity": ${JSON.stringify(
entry.integrity
)}, "contentType": ${JSON.stringify(entry.contentType)} },\n`;
}
}
str += ` "version": ${this.version}\n}\n`;
return str;
}
}
/**
* @template R
* @param {function(function(Error=, R=): void): void} fn function
* @returns {function(function(Error=, R=): void): void} cached function
*/
const cachedWithoutKey = fn => {
let inFlight = false;
/** @type {Error | undefined} */
let cachedError = undefined;
/** @type {R | undefined} */
let cachedResult = undefined;
/** @type {(function(Error=, R=): void)[] | undefined} */
let cachedCallbacks = undefined;
return callback => {
if (inFlight) {
if (cachedResult !== undefined) return callback(null, cachedResult);
if (cachedError !== undefined) return callback(cachedError);
if (cachedCallbacks === undefined) cachedCallbacks = [callback];
else cachedCallbacks.push(callback);
return;
}
inFlight = true;
fn((err, result) => {
if (err) cachedError = err;
else cachedResult = result;
const callbacks = cachedCallbacks;
cachedCallbacks = undefined;
callback(err, result);
if (callbacks !== undefined) for (const cb of callbacks) cb(err, result);
});
};
};
/**
* @template T
* @template R
* @param {function(T, function(Error=, R=): void): void} fn function
* @param {function(T, function(Error=, R=): void): void=} forceFn function for the second try
* @returns {(function(T, function(Error=, R=): void): void) & { force: function(T, function(Error=, R=): void): void }} cached function
*/
const cachedWithKey = (fn, forceFn = fn) => {
/** @typedef {{ result?: R, error?: Error, callbacks?: (function(Error=, R=): void)[], force?: true }} CacheEntry */
/** @type {Map<T, CacheEntry>} */
const cache = new Map();
const resultFn = (arg, callback) => {
const cacheEntry = cache.get(arg);
if (cacheEntry !== undefined) {
if (cacheEntry.result !== undefined)
return callback(null, cacheEntry.result);
if (cacheEntry.error !== undefined) return callback(cacheEntry.error);
if (cacheEntry.callbacks === undefined) cacheEntry.callbacks = [callback];
else cacheEntry.callbacks.push(callback);
return;
}
/** @type {CacheEntry} */
const newCacheEntry = {
result: undefined,
error: undefined,
callbacks: undefined
};
cache.set(arg, newCacheEntry);
fn(arg, (err, result) => {
if (err) newCacheEntry.error = err;
else newCacheEntry.result = result;
const callbacks = newCacheEntry.callbacks;
newCacheEntry.callbacks = undefined;
callback(err, result);
if (callbacks !== undefined) for (const cb of callbacks) cb(err, result);
});
};
resultFn.force = (arg, callback) => {
const cacheEntry = cache.get(arg);
if (cacheEntry !== undefined && cacheEntry.force) {
if (cacheEntry.result !== undefined)
return callback(null, cacheEntry.result);
if (cacheEntry.error !== undefined) return callback(cacheEntry.error);
if (cacheEntry.callbacks === undefined) cacheEntry.callbacks = [callback];
else cacheEntry.callbacks.push(callback);
return;
}
/** @type {CacheEntry} */
const newCacheEntry = {
result: undefined,
error: undefined,
callbacks: undefined,
force: true
};
cache.set(arg, newCacheEntry);
forceFn(arg, (err, result) => {
if (err) newCacheEntry.error = err;
else newCacheEntry.result = result;
const callbacks = newCacheEntry.callbacks;
newCacheEntry.callbacks = undefined;
callback(err, result);
if (callbacks !== undefined) for (const cb of callbacks) cb(err, result);
});
};
return resultFn;
};
/**
* @typedef {Object} HttpUriPluginAdvancedOptions
* @property {string | typeof import("../util/Hash")=} hashFunction
* @property {string=} hashDigest
* @property {number=} hashDigestLength
*/
class HttpUriPlugin {
/**
* @param {HttpUriPluginOptions & HttpUriPluginAdvancedOptions} options options
*/
constructor(options = {}) {
this._lockfileLocation = options.lockfileLocation;
this._cacheLocation = options.cacheLocation;
this._upgrade = options.upgrade;
this._frozen = options.frozen;
this._hashFunction = options.hashFunction;
this._hashDigest = options.hashDigest;
this._hashDigestLength = options.hashDigestLength;
}
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
const schemes = [
{
scheme: "http",
fetch: (url, options, callback) => getHttp().get(url, options, callback)
},
{
scheme: "https",
fetch: (url, options, callback) =>
getHttps().get(url, options, callback)
}
];
let lockfileCache;
compiler.hooks.compilation.tap(
"HttpUriPlugin",
(compilation, { normalModuleFactory }) => {
normalModuleFactory.hooks.resolveForScheme
.for("http")
.tap("HttpUriPlugin", resourceData => {
const url = new URL(resourceData.resource);
resourceData.path = url.origin + url.pathname;
resourceData.query = url.search;
resourceData.fragment = url.hash;
return /** @type {true} */ (true);
});
NormalModule.getCompilationHooks(compilation)
.readResourceForScheme.for("http")
.tapAsync("HttpUriPlugin", (resource, module, callback) => {
return require("http").get(new URL(resource), res => {
if (res.statusCode !== 200) {
res.destroy();
return callback(
new Error(`http request status code = ${res.statusCode}`)
);
}
const intermediateFs = compiler.intermediateFileSystem;
const fs = compilation.inputFileSystem;
const cache = compilation.getCache("webpack.HttpUriPlugin");
const logger = compilation.getLogger("webpack.HttpUriPlugin");
const lockfileLocation =
this._lockfileLocation ||
resolve(
compiler.context,
compiler.name
? `${toSafePath(compiler.name)}.webpack.lock`
: "webpack.lock"
);
const cacheLocation =
this._cacheLocation !== undefined
? this._cacheLocation
: lockfileLocation + ".data";
const upgrade = this._upgrade || false;
const frozen = this._frozen || false;
const hashFunction =
this._hashFunction || compilation.outputOptions.hashFunction;
const hashDigest =
this._hashDigest || compilation.outputOptions.hashDigest;
const hashDigestLength =
this._hashDigestLength || compilation.outputOptions.hashDigestLength;
const bufferArr = [];
let warnedAboutEol = false;
res.on("data", chunk => {
bufferArr.push(chunk);
});
const cacheKeyCache = new Map();
/**
* @param {string} url the url
* @returns {string} the key
*/
const getCacheKey = url => {
const cachedResult = cacheKeyCache.get(url);
if (cachedResult !== undefined) return cachedResult;
const result = _getCacheKey(url);
cacheKeyCache.set(url, result);
return result;
};
res.on("end", () => {
if (!res.complete) {
return callback(new Error("http request was terminated"));
/**
* @param {string} url the url
* @returns {string} the key
*/
const _getCacheKey = url => {
const parsedUrl = new URL(url);
const folder = toSafePath(parsedUrl.origin);
const name = toSafePath(parsedUrl.pathname);
const query = toSafePath(parsedUrl.search);
let ext = extname(name);
if (ext.length > 20) ext = "";
const basename = ext ? name.slice(0, -ext.length) : name;
const hash = createHash(hashFunction);
hash.update(url);
const digest = hash.digest(hashDigest).slice(0, hashDigestLength);
return `${folder.slice(-50)}/${`${basename}${
query ? `_${query}` : ""
}`.slice(0, 150)}_${digest}${ext}`;
};
const getLockfile = cachedWithoutKey(
/**
* @param {function(Error=, Lockfile=): void} callback callback
* @returns {void}
*/
callback => {
const readLockfile = () => {
intermediateFs.readFile(lockfileLocation, (err, buffer) => {
if (err && err.code !== "ENOENT") {
compilation.missingDependencies.add(lockfileLocation);
return callback(err);
}
compilation.fileDependencies.add(lockfileLocation);
compilation.fileSystemInfo.createSnapshot(
compiler.fsStartTime,
buffer ? [lockfileLocation] : [],
[],
buffer ? [] : [lockfileLocation],
{ timestamp: true },
(err, snapshot) => {
if (err) return callback(err);
const lockfile = buffer
? Lockfile.parse(buffer.toString("utf-8"))
: new Lockfile();
lockfileCache = {
lockfile,
snapshot
};
callback(null, lockfile);
}
);
});
};
if (lockfileCache) {
compilation.fileSystemInfo.checkSnapshotValid(
lockfileCache.snapshot,
(err, valid) => {
if (err) return callback(err);
if (!valid) return readLockfile();
callback(null, lockfileCache.lockfile);
}
);
} else {
readLockfile();
}
}
);
callback(null, Buffer.concat(bufferArr));
let outdatedLockfile = undefined;
const storeLockEntry = (lockfile, url, entry) => {
const oldEntry = lockfile.entries.get(url);
lockfile.entries.set(url, entry);
outdatedLockfile = lockfile;
if (!oldEntry) {
logger.log(`${url} added to lockfile`);
} else if (typeof oldEntry === "string") {
if (typeof entry === "string") {
logger.log(`${url} updated in lockfile: ${oldEntry} -> ${entry}`);
} else {
logger.log(
`${url} updated in lockfile: ${oldEntry} -> ${entry.resolved}`
);
}
} else if (typeof entry === "string") {
logger.log(
`${url} updated in lockfile: ${oldEntry.resolved} -> ${entry}`
);
} else if (oldEntry.resolved !== entry.resolved) {
logger.log(
`${url} updated in lockfile: ${oldEntry.resolved} -> ${entry.resolved}`
);
} else if (oldEntry.integrity !== entry.integrity) {
logger.log(`${url} updated in lockfile: content changed`);
} else if (oldEntry.contentType !== entry.contentType) {
logger.log(
`${url} updated in lockfile: ${oldEntry.contentType} -> ${entry.contentType}`
);
} else {
logger.log(`${url} updated in lockfile`);
}
};
const storeResult = (lockfile, url, result, callback) => {
if (result.storeLock) {
storeLockEntry(lockfile, url, result.entry);
if (!cacheLocation || !result.content)
return callback(null, result);
const key = getCacheKey(result.entry.resolved);
const filePath = resolve(cacheLocation, key);
mkdirp(intermediateFs, dirname(filePath), err => {
if (err) return callback(err);
intermediateFs.writeFile(filePath, result.content, err => {
if (err) return callback(err);
callback(null, result);
});
});
});
} else {
storeLockEntry(lockfile, url, "no-cache");
callback(null, result);
}
};
for (const { scheme, fetch } of schemes) {
/**
*
* @param {string} url URL
* @param {string} integrity integrity
* @param {function(Error=, { entry: LockfileEntry, content: Buffer, storeLock: boolean }=): void} callback callback
*/
const resolveContent = (url, integrity, callback) => {
const handleResult = (err, result) => {
if (err) return callback(err);
if ("location" in result) {
return resolveContent(
result.location,
integrity,
(err, innerResult) => {
if (err) return callback(err);
callback(null, {
entry: innerResult.entry,
content: innerResult.content,
storeLock: innerResult.storeLock && result.storeLock
});
}
);
} else {
if (
!result.fresh &&
integrity &&
result.entry.integrity !== integrity &&
!verifyIntegrity(result.content, integrity)
) {
return fetchContent.force(url, handleResult);
}
return callback(null, {
entry: result.entry,
content: result.content,
storeLock: result.storeLock
});
}
};
fetchContent(url, handleResult);
};
/** @typedef {{ storeCache: boolean, storeLock: boolean, validUntil: number, etag: string | undefined, fresh: boolean }} FetchResultMeta */
/** @typedef {FetchResultMeta & { location: string }} RedirectFetchResult */
/** @typedef {FetchResultMeta & { entry: LockfileEntry, content: Buffer }} ContentFetchResult */
/** @typedef {RedirectFetchResult | ContentFetchResult} FetchResult */
/**
* @param {string} url URL
* @param {FetchResult} cachedResult result from cache
* @param {function(Error=, FetchResult=): void} callback callback
* @returns {void}
*/
const fetchContentRaw = (url, cachedResult, callback) => {
const requestTime = Date.now();
fetch(
new URL(url),
{
headers: {
"accept-encoding": "gzip, deflate, br",
"user-agent": "webpack",
"if-none-match": cachedResult
? cachedResult.etag || null
: null
}
},
res => {
const etag = res.headers["etag"];
const location = res.headers["location"];
const cacheControl = res.headers["cache-control"];
const { storeLock, storeCache, validUntil } = parseCacheControl(
cacheControl,
requestTime
);
/**
* @param {Partial<Pick<FetchResultMeta, "fresh">> & (Pick<RedirectFetchResult, "location"> | Pick<ContentFetchResult, "content" | "entry">)} partialResult result
* @returns {void}
*/
const finishWith = partialResult => {
if ("location" in partialResult) {
logger.debug(
`GET ${url} [${res.statusCode}] -> ${partialResult.location}`
);
} else {
logger.debug(
`GET ${url} [${res.statusCode}] ${Math.ceil(
partialResult.content.length / 1024
)} kB${!storeLock ? " no-cache" : ""}`
);
}
const result = {
...partialResult,
fresh: true,
storeLock,
storeCache,
validUntil,
etag
};
if (!storeCache) {
logger.log(
`${url} can't be stored in cache, due to Cache-Control header: ${cacheControl}`
);
return callback(null, result);
}
cache.store(
url,
null,
{
...result,
fresh: false
},
err => {
if (err) {
logger.warn(
`${url} can't be stored in cache: ${err.message}`
);
logger.debug(err.stack);
}
callback(null, result);
}
);
};
if (res.statusCode === 304) {
if (
cachedResult.validUntil < validUntil ||
cachedResult.storeLock !== storeLock ||
cachedResult.storeCache !== storeCache ||
cachedResult.etag !== etag
) {
return finishWith(cachedResult);
} else {
logger.debug(`GET ${url} [${res.statusCode}] (unchanged)`);
return callback(null, {
...cachedResult,
fresh: true
});
}
}
if (
location &&
res.statusCode >= 301 &&
res.statusCode <= 308
) {
return finishWith({
location: new URL(location, url).href
});
}
// Skypack uses this header to specify the final url
const importUrl =
res.statusCode === 200 && res.headers["x-import-url"];
if (importUrl) {
return finishWith({
location: new URL(importUrl, url).href
});
}
const contentType = res.headers["content-type"] || "";
const bufferArr = [];
const contentEncoding = res.headers["content-encoding"];
let stream = res;
if (contentEncoding === "gzip") {
stream = stream.pipe(createGunzip());
} else if (contentEncoding === "br") {
stream = stream.pipe(createBrotliDecompress());
} else if (contentEncoding === "deflate") {
stream = stream.pipe(createInflate());
}
stream.on("data", chunk => {
bufferArr.push(chunk);
});
stream.on("end", () => {
if (!res.complete) {
logger.log(`GET ${url} [${res.statusCode}] (terminated)`);
return callback(new Error(`${url} request was terminated`));
}
const content = Buffer.concat(bufferArr);
if (res.statusCode !== 200) {
logger.log(`GET ${url} [${res.statusCode}]`);
return callback(
new Error(
`${url} request status code = ${
res.statusCode
}\n${content.toString("utf-8")}`
)
);
}
const integrity = computeIntegrity(content);
const entry = { resolved: url, integrity, contentType };
finishWith({
entry,
content
});
});
}
).on("error", err => {
logger.log(`GET ${url} (error)`);
err.message += `\nwhile fetching ${url}`;
callback(err);
});
};
const fetchContent = cachedWithKey(
/**
* @param {string} url URL
* @param {function(Error=, { validUntil: number, etag?: string, entry: LockfileEntry, content: Buffer, fresh: boolean } | { validUntil: number, etag?: string, location: string, fresh: boolean }=): void} callback callback
* @returns {void}
*/ (url, callback) => {
cache.get(url, null, (err, cachedResult) => {
if (err) return callback(err);
if (cachedResult) {
const isValid = cachedResult.validUntil >= Date.now();
if (isValid) return callback(null, cachedResult);
}
fetchContentRaw(url, cachedResult, callback);
});
},
(url, callback) => fetchContentRaw(url, undefined, callback)
);
const getInfo = cachedWithKey(
/**
* @param {string} url the url
* @param {function(Error=, { entry: LockfileEntry, content: Buffer }=): void} callback callback
* @returns {void}
*/
(url, callback) => {
getLockfile((err, lockfile) => {
if (err) return callback(err);
const entryOrString = lockfile.entries.get(url);
if (!entryOrString) {
if (frozen) {
return callback(
new Error(
`${url} has no lockfile entry and lockfile is frozen`
)
);
}
resolveContent(url, null, (err, result) => {
if (err) return callback(err);
storeResult(lockfile, url, result, callback);
});
return;
}
if (typeof entryOrString === "string") {
const entryTag = entryOrString;
resolveContent(url, null, (err, result) => {
if (err) return callback(err);
if (!result.storeLock || entryTag === "ignore")
return callback(null, result);
if (frozen) {
return callback(
new Error(
`${url} used to have ${entryTag} lockfile entry and has content now, but lockfile is frozen`
)
);
}
if (!upgrade) {
return callback(
new Error(
`${url} used to have ${entryTag} lockfile entry and has content now.
This should be reflected in the lockfile, so this lockfile entry must be upgraded, but upgrading is not enabled.
Remove this line from the lockfile to force upgrading.`
)
);
}
storeResult(lockfile, url, result, callback);
});
return;
}
let entry = entryOrString;
const doFetch = lockedContent => {
resolveContent(url, entry.integrity, (err, result) => {
if (err) {
if (lockedContent) {
logger.warn(
`Upgrade request to ${url} failed: ${err.message}`
);
logger.debug(err.stack);
return callback(null, {
entry,
content: lockedContent
});
}
return callback(err);
}
if (!result.storeLock) {
// When the lockfile entry should be no-cache
// we need to update the lockfile
if (frozen) {
return callback(
new Error(
`${url} has a lockfile entry and is no-cache now, but lockfile is frozen\nLockfile: ${entryToString(
entry
)}`
)
);
}
storeResult(lockfile, url, result, callback);
return;
}
if (!areLockfileEntriesEqual(result.entry, entry)) {
// When the lockfile entry is outdated
// we need to update the lockfile
if (frozen) {
return callback(
new Error(
`${url} has an outdated lockfile entry, but lockfile is frozen\nLockfile: ${entryToString(
entry
)}\nExpected: ${entryToString(result.entry)}`
)
);
}
storeResult(lockfile, url, result, callback);
return;
}
if (!lockedContent && cacheLocation) {
// When the lockfile cache content is missing
// we need to update the lockfile
if (frozen) {
return callback(
new Error(
`${url} is missing content in the lockfile cache, but lockfile is frozen\nLockfile: ${entryToString(
entry
)}`
)
);
}
storeResult(lockfile, url, result, callback);
return;
}
return callback(null, result);
});
};
if (cacheLocation) {
// When there is a lockfile cache
// we read the content from there
const key = getCacheKey(entry.resolved);
const filePath = resolve(cacheLocation, key);
fs.readFile(filePath, (err, result) => {
const content = /** @type {Buffer} */ (result);
if (err) {
if (err.code === "ENOENT") return doFetch();
return callback(err);
}
const continueWithCachedContent = result => {
if (!upgrade) {
// When not in upgrade mode, we accept the result from the lockfile cache
return callback(null, { entry, content });
}
return doFetch(content);
};
if (!verifyIntegrity(content, entry.integrity)) {
let contentWithChangedEol;
let isEolChanged = false;
try {
contentWithChangedEol = Buffer.from(
content.toString("utf-8").replace(/\r\n/g, "\n")
);
isEolChanged = verifyIntegrity(
contentWithChangedEol,
entry.integrity
);
} catch (e) {
// ignore
}
if (isEolChanged) {
if (!warnedAboutEol) {
const explainer = `Incorrect end of line sequence was detected in the lockfile cache.
The lockfile cache is protected by integrity checks, so any external modification will lead to a corrupted lockfile cache.
When using git make sure to configure .gitattributes correctly for the lockfile cache:
**/*webpack.lock.data/** -text
This will avoid that the end of line sequence is changed by git on Windows.`;
if (frozen) {
logger.error(explainer);
} else {
logger.warn(explainer);
logger.info(
"Lockfile cache will be automatically fixed now, but when lockfile is frozen this would result in an error."
);
}
warnedAboutEol = true;
}
if (!frozen) {
// "fix" the end of line sequence of the lockfile content
logger.log(
`${filePath} fixed end of line sequence (\\r\\n instead of \\n).`
);
intermediateFs.writeFile(
filePath,
contentWithChangedEol,
err => {
if (err) return callback(err);
continueWithCachedContent(contentWithChangedEol);
}
);
return;
}
}
if (frozen) {
return callback(
new Error(
`${
entry.resolved
} integrity mismatch, expected content with integrity ${
entry.integrity
} but got ${computeIntegrity(content)}.
Lockfile corrupted (${
isEolChanged
? "end of line sequence was unexpectedly changed"
: "incorrectly merged? changed by other tools?"
}).
Run build with un-frozen lockfile to automatically fix lockfile.`
)
);
} else {
// "fix" the lockfile entry to the correct integrity
// the content has priority over the integrity value
entry = {
...entry,
integrity: computeIntegrity(content)
};
storeLockEntry(lockfile, url, entry);
}
}
continueWithCachedContent(result);
});
} else {
doFetch();
}
});
}
);
normalModuleFactory.hooks.resolveForScheme
.for(scheme)
.tapAsync(
"HttpUriPlugin",
(resourceData, resolveData, callback) => {
getInfo(resourceData.resource, (err, result) => {
if (err) return callback(err);
const url = new URL(resourceData.resource);
resourceData.path = url.origin + url.pathname;
resourceData.query = url.search;
resourceData.fragment = url.hash;
resourceData.data.mimetype = result.entry.contentType;
callback(null, true);
});
}
);
normalModuleFactory.hooks.resolveInScheme
.for(scheme)
.tapAsync("HttpUriPlugin", (resourceData, data, callback) => {
// Only handle relative urls (./xxx, ../xxx, /xxx, //xxx)
if (!/^\.{0,2}\//.test(resourceData.resource)) {
return callback();
}
const url = new URL(resourceData.resource, data.context + "/");
getInfo(url.href, (err, result) => {
if (err) return callback(err);
resourceData.resource = url.href;
resourceData.path = url.origin + url.pathname;
resourceData.query = url.search;
resourceData.fragment = url.hash;
resourceData.data.mimetype = result.entry.contentType;
callback(null, true);
});
});
const hooks = NormalModule.getCompilationHooks(compilation);
hooks.readResourceForScheme
.for(scheme)
.tapAsync("HttpUriPlugin", (resource, module, callback) => {
return getInfo(resource, (err, result) => {
if (err) return callback(err);
callback(null, result.content);
});
});
hooks.needBuild.tapAsync(
"HttpUriPlugin",
(module, context, callback) => {
if (
module.resource &&
module.resource.startsWith(`${scheme}://`)
) {
getInfo(module.resource, (err, result) => {
if (err) return callback(err);
if (
result.entry.integrity !==
module.buildInfo.resourceIntegrity
) {
return callback(null, true);
}
callback();
});
} else {
return callback();
}
}
);
}
compilation.hooks.finishModules.tapAsync(
"HttpUriPlugin",
(modules, callback) => {
if (!outdatedLockfile) return callback();
intermediateFs.writeFile(
lockfileLocation,
outdatedLockfile.toString(),
callback
);
}
);
}
);
}

View File

@ -1,63 +0,0 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { URL } = require("url");
const NormalModule = require("../NormalModule");
/** @typedef {import("../Compiler")} Compiler */
class HttpsUriPlugin {
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.compilation.tap(
"HttpsUriPlugin",
(compilation, { normalModuleFactory }) => {
normalModuleFactory.hooks.resolveForScheme
.for("https")
.tap("HttpsUriPlugin", resourceData => {
const url = new URL(resourceData.resource);
resourceData.path = url.origin + url.pathname;
resourceData.query = url.search;
resourceData.fragment = url.hash;
return /** @type {true} */ (true);
});
NormalModule.getCompilationHooks(compilation)
.readResourceForScheme.for("https")
.tapAsync("HttpsUriPlugin", (resource, module, callback) => {
return require("https").get(new URL(resource), res => {
if (res.statusCode !== 200) {
res.destroy();
return callback(
new Error(`https request status code = ${res.statusCode}`)
);
}
const bufferArr = [];
res.on("data", chunk => {
bufferArr.push(chunk);
});
res.on("end", () => {
if (!res.complete) {
return callback(new Error("https request was terminated"));
}
callback(null, Buffer.concat(bufferArr));
});
});
});
}
);
}
}
module.exports = HttpsUriPlugin;

View File

@ -10,8 +10,6 @@ const SerializerMiddleware = require("./SerializerMiddleware");
/** @typedef {import("./types").BufferSerializableType} BufferSerializableType */
/** @typedef {import("./types").PrimitiveSerializableType} PrimitiveSerializableType */
/* eslint-disable no-loop-func */
/*
Format:

File diff suppressed because one or more lines are too long

View File

@ -688,6 +688,17 @@
"description": "Support WebAssembly as asynchronous EcmaScript Module.",
"type": "boolean"
},
"buildHttp": {
"description": "Build http(s): urls using a lockfile and resource content cache.",
"anyOf": [
{
"type": "boolean"
},
{
"$ref": "#/definitions/HttpUriOptions"
}
]
},
"executeModule": {
"description": "Enable build-time execution of modules from the module graph for plugins and loaders.",
"type": "boolean"
@ -1184,6 +1195,38 @@
"type": "string",
"absolutePath": false
},
"HttpUriOptions": {
"description": "Options for building http resources.",
"type": "object",
"additionalProperties": false,
"properties": {
"cacheLocation": {
"description": "Location where resource content is stored for lockfile entries. It's also possible to disable storing by passing false.",
"anyOf": [
{
"enum": [false]
},
{
"type": "string",
"absolutePath": true
}
]
},
"frozen": {
"description": "When set, anything that would lead to an modification of the lockfile or any resource content, will result in an error.",
"type": "boolean"
},
"lockfileLocation": {
"description": "Location of the lockfile.",
"type": "string",
"absolutePath": true
},
"upgrade": {
"description": "When set, resources of existing lockfile entries will be fetched and entries will be upgraded when resource content has changed.",
"type": "boolean"
}
}
},
"IgnoreWarnings": {
"description": "Ignore specific warnings.",
"type": "array",

View File

@ -0,0 +1,7 @@
/*
* This file was automatically generated.
* DO NOT MODIFY BY HAND.
* Run `yarn special-lint-fix` to update
*/
declare const check: (options: import("../../../declarations/plugins/schemes/HttpUriPlugin").HttpUriPluginOptions) => boolean;
export = check;

View File

@ -0,0 +1,6 @@
/*
* This file was automatically generated.
* DO NOT MODIFY BY HAND.
* Run `yarn special-lint-fix` to update
*/
const o=/^(?:[A-Za-z]:[\\/]|\\\\|\/)/;function t(e,{instancePath:n="",parentData:s,parentDataProperty:l,rootData:a=e}={}){let i=null,r=0;const c=r;let p=!1,u=null;const f=r;if(r==r)if(e&&"object"==typeof e&&!Array.isArray(e)){const t=r;for(const o in e)if("cacheLocation"!==o&&"frozen"!==o&&"lockfileLocation"!==o&&"upgrade"!==o){const t={params:{additionalProperty:o}};null===i?i=[t]:i.push(t),r++;break}if(t===r){if(void 0!==e.cacheLocation){let t=e.cacheLocation;const n=r,s=r;let l=!1;const a=r;if(!1!==t){const o={params:{}};null===i?i=[o]:i.push(o),r++}var h=a===r;if(l=l||h,!l){const e=r;if(r===e)if("string"==typeof t){if(t.includes("!")||!0!==o.test(t)){const o={params:{}};null===i?i=[o]:i.push(o),r++}}else{const o={params:{type:"string"}};null===i?i=[o]:i.push(o),r++}h=e===r,l=l||h}if(l)r=s,null!==i&&(s?i.length=s:i=null);else{const o={params:{}};null===i?i=[o]:i.push(o),r++}var d=n===r}else d=!0;if(d){if(void 0!==e.frozen){const o=r;if("boolean"!=typeof e.frozen){const o={params:{type:"boolean"}};null===i?i=[o]:i.push(o),r++}d=o===r}else d=!0;if(d){if(void 0!==e.lockfileLocation){let t=e.lockfileLocation;const n=r;if(r===n)if("string"==typeof t){if(t.includes("!")||!0!==o.test(t)){const o={params:{}};null===i?i=[o]:i.push(o),r++}}else{const o={params:{type:"string"}};null===i?i=[o]:i.push(o),r++}d=n===r}else d=!0;if(d)if(void 0!==e.upgrade){const o=r;if("boolean"!=typeof e.upgrade){const o={params:{type:"boolean"}};null===i?i=[o]:i.push(o),r++}d=o===r}else d=!0}}}}else{const o={params:{type:"object"}};null===i?i=[o]:i.push(o),r++}if(f===r&&(p=!0,u=0),!p){const o={params:{passingSchemas:u}};return null===i?i=[o]:i.push(o),r++,t.errors=i,!1}return r=c,null!==i&&(c?i.length=c:i=null),t.errors=i,0===r}module.exports=t,module.exports.default=t;

View File

@ -0,0 +1,42 @@
{
"definitions": {
"HttpUriOptions": {
"description": "Options for building http resources.",
"type": "object",
"additionalProperties": false,
"properties": {
"cacheLocation": {
"description": "Location where resource content is stored for lockfile entries. It's also possible to disable storing by passing false.",
"anyOf": [
{
"enum": [false]
},
{
"type": "string",
"absolutePath": true
}
]
},
"frozen": {
"description": "When set, anything that would lead to an modification of the lockfile or any resource content, will result in an error.",
"type": "boolean"
},
"lockfileLocation": {
"description": "Location of the lockfile.",
"type": "string",
"absolutePath": true
},
"upgrade": {
"description": "When set, resources of existing lockfile entries will be fetched and entries will be upgraded when resource content has changed.",
"type": "boolean"
}
}
}
},
"title": "HttpUriPluginOptions",
"oneOf": [
{
"$ref": "#/definitions/HttpUriOptions"
}
]
}

View File

@ -91,7 +91,12 @@ describe("Defaults", () => {
},
},
"experiments": Object {
"asset": false,
"asyncWebAssembly": false,
"buildHttp": false,
"executeModule": false,
"layers": false,
"lazyCompilation": false,
"outputModule": false,
"syncWebAssembly": false,
"topLevelAwait": false,

View File

@ -450,6 +450,80 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"experiments-build-http": Object {
"configs": Array [
Object {
"description": "Build http(s): urls using a lockfile and resource content cache.",
"multiple": false,
"path": "experiments.buildHttp",
"type": "boolean",
},
],
"description": "Build http(s): urls using a lockfile and resource content cache.",
"multiple": false,
"simpleType": "boolean",
},
"experiments-build-http-cache-location": Object {
"configs": Array [
Object {
"description": "Location where resource content is stored for lockfile entries. It's also possible to disable storing by passing false.",
"multiple": false,
"path": "experiments.buildHttp.cacheLocation",
"type": "enum",
"values": Array [
false,
],
},
Object {
"description": "Location where resource content is stored for lockfile entries. It's also possible to disable storing by passing false.",
"multiple": false,
"path": "experiments.buildHttp.cacheLocation",
"type": "path",
},
],
"description": "Location where resource content is stored for lockfile entries. It's also possible to disable storing by passing false.",
"multiple": false,
"simpleType": "string",
},
"experiments-build-http-frozen": Object {
"configs": Array [
Object {
"description": "When set, anything that would lead to an modification of the lockfile or any resource content, will result in an error.",
"multiple": false,
"path": "experiments.buildHttp.frozen",
"type": "boolean",
},
],
"description": "When set, anything that would lead to an modification of the lockfile or any resource content, will result in an error.",
"multiple": false,
"simpleType": "boolean",
},
"experiments-build-http-lockfile-location": Object {
"configs": Array [
Object {
"description": "Location of the lockfile.",
"multiple": false,
"path": "experiments.buildHttp.lockfileLocation",
"type": "path",
},
],
"description": "Location of the lockfile.",
"multiple": false,
"simpleType": "string",
},
"experiments-build-http-upgrade": Object {
"configs": Array [
Object {
"description": "When set, resources of existing lockfile entries will be fetched and entries will be upgraded when resource content has changed.",
"multiple": false,
"path": "experiments.buildHttp.upgrade",
"type": "boolean",
},
],
"description": "When set, resources of existing lockfile entries will be fetched and entries will be upgraded when resource content has changed.",
"multiple": false,
"simpleType": "boolean",
},
"experiments-execute-module": Object {
"configs": Array [
Object {

View File

@ -0,0 +1,16 @@
{
"http://localhost:9990/asset.txt": { "resolved": "http://localhost:9990/asset.txt", "integrity": "sha512-LHT9F+2v2A6ER7DUZ0HuJDt+t03SFJoKsbkkb7MDgvJ+hT2FhXGeDmfL2g2qj1FnEGRhXWRa4nrLFb+xRH9Fmw==", "contentType": "text/css" },
"http://localhost:9990/fallback.js": { "resolved": "http://localhost:9990/fallback.js", "integrity": "sha512-BCkBS4Wb0EreudEceuobqZZwTE7SeVUJ2vVHxDQKm8xW6dGJRcUrrSWcjd/61zijOeYAW0P+boOg7u0vxrGwYg==", "contentType": "text/javascript" },
"http://localhost:9990/folder/dependency.js": { "resolved": "http://localhost:9990/folder/dependency.js", "integrity": "sha512-N0En4W3aNPY82MPu16+50P4PqLLyPLI6l33wR2a3ue8VCRjY8RJl8erRB8ztWSEYNad7yRDPrqlYT+IBtoOA9w==", "contentType": "text/javascript" },
"http://localhost:9990/folder/sub-dependency.js": { "resolved": "http://localhost:9990/folder/sub-dependency.js", "integrity": "sha512-Jjmwazwmg67EwNPViCBwvSIxhENfS6gwufXoQLrB0B/JDA4v1p+p2S5Y6IGP4SzZqqVTsROlU8meD6ep3q6MTA==", "contentType": "text/javascript" },
"http://localhost:9990/folder/sub-dependency2.js": { "resolved": "http://localhost:9990/folder/sub-dependency2.js", "integrity": "sha512-BDZKEwlnwBabeHEwmMd02NxFEjYy+QwKAKP0S8zMMesX7dUsvh11hM7LUOPPFOS+nIEFZPtnc7kFwmnojVUw5A==", "contentType": "text/javascript" },
"http://localhost:9990/index.css?cache": { "resolved": "http://localhost:9990/index.css?cache", "integrity": "sha512-sqhF9JAEi5h3ziP48SBnzQnaeei8cf/pfYJBdKL4F7xdu3v5yr71eQ0kCL11/jWRFjLG4TKOudUnS/u6WLMqYw==", "contentType": "text/css" },
"http://localhost:9990/index.css?no-cache": "no-cache",
"http://localhost:9990/index.css?query#fragment": { "resolved": "http://localhost:9990/index.css?query#fragment", "integrity": "sha512-sqhF9JAEi5h3ziP48SBnzQnaeei8cf/pfYJBdKL4F7xdu3v5yr71eQ0kCL11/jWRFjLG4TKOudUnS/u6WLMqYw==", "contentType": "text/css" },
"http://localhost:9990/redirect": { "resolved": "http://localhost:9990/redirect.js", "integrity": "sha512-BV/MK/QTq+NHRve1XpZyQ8V6cjRP/fwbtJvENRdm5C73qNYZ4i2/fw+soj7J4qxzBXMHDbvOnA6E0ShnX2hc1w==", "contentType": "text/javascript" },
"http://localhost:9990/redirect.js": { "resolved": "http://localhost:9990/redirect.js", "integrity": "sha512-BV/MK/QTq+NHRve1XpZyQ8V6cjRP/fwbtJvENRdm5C73qNYZ4i2/fw+soj7J4qxzBXMHDbvOnA6E0ShnX2hc1w==", "contentType": "text/javascript" },
"http://localhost:9990/resolve.js": { "resolved": "http://localhost:9990/resolve.js", "integrity": "sha512-6J9zBO2hXSMTO1EtXJOxSRB2nVPHCoNmNHS8an1QeehzJFc3uoBPRWu6hqHPc54gv2/QME9RBR/BXIan68virg==", "contentType": "text/javascript" },
"https://raw.githubusercontent.com//webpack//webpack//main/CODE_OF_CONDUCT.md": { "resolved": "https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md", "integrity": "sha512-OLJ9q6iSO652hVBkTLsMLtQnFBBTzEbFqLGyWD62nPga/0DZ9bc3oOFb5OYT8RIPzmlOX4WzK2uiLgc1NSGtBA==", "contentType": "text/plain; charset=utf-8" },
"https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md": { "resolved": "https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md", "integrity": "sha512-OLJ9q6iSO652hVBkTLsMLtQnFBBTzEbFqLGyWD62nPga/0DZ9bc3oOFb5OYT8RIPzmlOX4WzK2uiLgc1NSGtBA==", "contentType": "text/plain; charset=utf-8" },
"version": 1
}

View File

@ -0,0 +1,2 @@
export * from "./sub-dependency.js";
export * from "/folder/sub-dependency2.js";

View File

@ -0,0 +1 @@
[Code of Conduct](https://github.com/openjs-foundation/code-and-learn/blob/master/CODE_OF_CONDUCT.md)

View File

@ -0,0 +1,18 @@
module.exports = [
[
/http:\/\/localhost:9990\/index\.css\?cache used to have no-cache lockfile entry and has content now, but lockfile is frozen/
],
[
/http:\/\/localhost:9990\/index\.css\?no-cache has a lockfile entry and is no-cache now, but lockfile is frozen/
],
[
/http:\/\/localhost:9990\/index\.css has an outdated lockfile entry, but lockfile is frozen/
],
[/http:\/\/localhost:9990\/resolve\.js integrity mismatch/],
[
/http:\/\/localhost:9990\/fallback\.js has no lockfile entry and lockfile is frozen/
],
[
/http:\/\/localhost:9990\/redirect has an outdated lockfile entry, but lockfile is frozen/
]
];

View File

@ -0,0 +1,13 @@
{
"http://localhost:9990/asset.txt?ignore": "ignore",
"http://localhost:9990/index.css": { "resolved": "http://localhost:9990/index.css", "integrity": "sha512-sqhF9JAEi5h3ziP48SBnzQnaeei8cf/pfYJBdKL4F7xdu3v5yr71eQ0kCL11/jWRFjLG4TKOudUnS/u6WLMqYw==", "contentType": "invalid" },
"http://localhost:9990/index.css?query#fragment": { "resolved": "http://localhost:9990/index.css?query#fragment", "integrity": "sha512-sqhF9JAEi5h3ziP48SBnzQnaeei8cf/pfYJBdKL4F7xdu3v5yr71eQ0kCL11/jWRFjLG4TKOudUnS/u6WLMqYw==", "contentType": "text/css" },
"http://localhost:9990/index.css?no-cache": { "resolved": "http://localhost:9990/index.css?no-cache", "integrity": "sha512-sqhF9JAEi5h3ziP48SBnzQnaeei8cf/pfYJBdKL4F7xdu3v5yr71eQ0kCL11/jWRFjLG4TKOudUnS/u6WLMqYw==", "contentType": "text/css" },
"http://localhost:9990/index.css?cache": "no-cache",
"http://localhost:9990/redirect": { "resolved": "http://localhost:9990/redirect", "integrity": "sha512-BV/MK/QTq+NHRve1XpZyQ8V6cjRP/fwbtJvENRdm5C73qNYZ4i2/fw+soj7J4qxzBXMHDbvOnA6E0ShnX2hc1w==", "contentType": "text/javascript" },
"http://localhost:9990/redirect.js": { "resolved": "http://localhost:9990/redirect.js", "integrity": "sha512-BV/MK/QTq+NHRve1XpZyQ8V6cjRP/fwbtJvENRdm5C73qNYZ4i2/fw+soj7J4qxzBXMHDbvOnA6E0ShnX2hc1w==", "contentType": "text/javascript" },
"http://localhost:9990/resolve.js": { "resolved": "http://localhost:9990/resolve.js", "integrity": "sha512-SHOULD_BE_INVALID", "contentType": "text/javascript" },
"https://raw.githubusercontent.com//webpack//webpack//main/CODE_OF_CONDUCT.md": { "resolved": "https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md", "integrity": "sha512-OLJ9q6iSO652hVBkTLsMLtQnFBBTzEbFqLGyWD62nPga/0DZ9bc3oOFb5OYT8RIPzmlOX4WzK2uiLgc1NSGtBA==", "contentType": "text/plain; charset=utf-8" },
"https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md": { "resolved": "https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md", "integrity": "sha512-OLJ9q6iSO652hVBkTLsMLtQnFBBTzEbFqLGyWD62nPga/0DZ9bc3oOFb5OYT8RIPzmlOX4WzK2uiLgc1NSGtBA==", "contentType": "text/plain; charset=utf-8" },
"version": 1
}

View File

@ -0,0 +1 @@
export * from "./folder/dependency.js";

View File

@ -0,0 +1 @@
[Code of Conduct](https://github.com/openjs-foundation/code-and-learn/blob/master/CODE_OF_CONDUCT.md)

View File

@ -0,0 +1,16 @@
{
"http://localhost:9990/asset.txt": { "resolved": "http://localhost:9990/asset.txt", "integrity": "sha512-LHT9F+2v2A6ER7DUZ0HuJDt+t03SFJoKsbkkb7MDgvJ+hT2FhXGeDmfL2g2qj1FnEGRhXWRa4nrLFb+xRH9Fmw==", "contentType": "text/css" },
"http://localhost:9990/fallback.js": { "resolved": "http://localhost:9990/fallback.js", "integrity": "sha512-BCkBS4Wb0EreudEceuobqZZwTE7SeVUJ2vVHxDQKm8xW6dGJRcUrrSWcjd/61zijOeYAW0P+boOg7u0vxrGwYg==", "contentType": "text/javascript" },
"http://localhost:9990/folder/dependency.js": { "resolved": "http://localhost:9990/folder/dependency.js", "integrity": "sha512-N0En4W3aNPY82MPu16+50P4PqLLyPLI6l33wR2a3ue8VCRjY8RJl8erRB8ztWSEYNad7yRDPrqlYT+IBtoOA9w==", "contentType": "text/javascript" },
"http://localhost:9990/folder/sub-dependency.js": { "resolved": "http://localhost:9990/folder/sub-dependency.js", "integrity": "sha512-Jjmwazwmg67EwNPViCBwvSIxhENfS6gwufXoQLrB0B/JDA4v1p+p2S5Y6IGP4SzZqqVTsROlU8meD6ep3q6MTA==", "contentType": "text/javascript" },
"http://localhost:9990/folder/sub-dependency2.js": { "resolved": "http://localhost:9990/folder/sub-dependency2.js", "integrity": "sha512-BDZKEwlnwBabeHEwmMd02NxFEjYy+QwKAKP0S8zMMesX7dUsvh11hM7LUOPPFOS+nIEFZPtnc7kFwmnojVUw5A==", "contentType": "text/javascript" },
"http://localhost:9990/index.css?cache": { "resolved": "http://localhost:9990/index.css?cache", "integrity": "sha512-sqhF9JAEi5h3ziP48SBnzQnaeei8cf/pfYJBdKL4F7xdu3v5yr71eQ0kCL11/jWRFjLG4TKOudUnS/u6WLMqYw==", "contentType": "text/css" },
"http://localhost:9990/index.css?no-cache": "no-cache",
"http://localhost:9990/index.css?query#fragment": { "resolved": "http://localhost:9990/index.css?query#fragment", "integrity": "sha512-sqhF9JAEi5h3ziP48SBnzQnaeei8cf/pfYJBdKL4F7xdu3v5yr71eQ0kCL11/jWRFjLG4TKOudUnS/u6WLMqYw==", "contentType": "text/css" },
"http://localhost:9990/redirect": { "resolved": "http://localhost:9990/redirect.js", "integrity": "sha512-BV/MK/QTq+NHRve1XpZyQ8V6cjRP/fwbtJvENRdm5C73qNYZ4i2/fw+soj7J4qxzBXMHDbvOnA6E0ShnX2hc1w==", "contentType": "text/javascript" },
"http://localhost:9990/redirect.js": { "resolved": "http://localhost:9990/redirect.js", "integrity": "sha512-BV/MK/QTq+NHRve1XpZyQ8V6cjRP/fwbtJvENRdm5C73qNYZ4i2/fw+soj7J4qxzBXMHDbvOnA6E0ShnX2hc1w==", "contentType": "text/javascript" },
"http://localhost:9990/resolve.js": { "resolved": "http://localhost:9990/resolve.js", "integrity": "sha512-6J9zBO2hXSMTO1EtXJOxSRB2nVPHCoNmNHS8an1QeehzJFc3uoBPRWu6hqHPc54gv2/QME9RBR/BXIan68virg==", "contentType": "text/javascript" },
"https://raw.githubusercontent.com//webpack//webpack//main/CODE_OF_CONDUCT.md": { "resolved": "https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md", "integrity": "sha512-OLJ9q6iSO652hVBkTLsMLtQnFBBTzEbFqLGyWD62nPga/0DZ9bc3oOFb5OYT8RIPzmlOX4WzK2uiLgc1NSGtBA==", "contentType": "text/plain; charset=utf-8" },
"https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md": { "resolved": "https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md", "integrity": "sha512-OLJ9q6iSO652hVBkTLsMLtQnFBBTzEbFqLGyWD62nPga/0DZ9bc3oOFb5OYT8RIPzmlOX4WzK2uiLgc1NSGtBA==", "contentType": "text/plain; charset=utf-8" },
"version": 1
}

View File

@ -0,0 +1,2 @@
export * from "./sub-dependency.js";
export * from "/folder/sub-dependency2.js";

View File

@ -0,0 +1 @@
[Code of Conduct](https://github.com/openjs-foundation/code-and-learn/blob/master/CODE_OF_CONDUCT.md)

View File

@ -0,0 +1,32 @@
it("error when lockfile is outdated/invalid", () => {
expect(() => {
require("http://localhost:9990/index.css?cache");
}).toThrowError();
expect(() => {
require("http://localhost:9990/index.css?no-cache");
}).toThrowError();
expect(() => {
require("http://localhost:9990/index.css");
}).toThrowError();
expect(() => {
require("http://localhost:9990/resolve.js");
}).toThrowError();
expect(() => {
require("http://localhost:9990/fallback.js");
}).toThrowError();
expect(() => {
require("http://localhost:9990/redirect");
}).toThrowError();
});
import text from "http://localhost:9990/asset.txt?ignore";
it("should allow to ignore lockfile entries", () => {
expect(text.trim()).toBe("Hello World");
});
import cssContent from "http://localhost:9990/index.css?query#fragment";
it("should use the entry with query and fragment", () => {
expect(cssContent).toBe("a {}.webpack{}");
});

View File

@ -1,5 +1,28 @@
import cssContent from "http://localhost:9990/index.css?query#fragment";
import noCacheCssContent from "http://localhost:9990/index.css?no-cache";
import cachedCssContent from "http://localhost:9990/index.css?cache";
import { value, value2 } from "http://localhost:9990/resolve.js";
import { fallback } from "http://localhost:9990/fallback.js";
import redirect1 from "http://localhost:9990/redirect";
import redirect2 from "http://localhost:9990/redirect.js";
import text from "http://localhost:9990/asset.txt";
import codeOfConduct1 from "https://raw.githubusercontent.com//webpack//webpack//main/CODE_OF_CONDUCT.md";
import codeOfConduct2 from "https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md";
it("http url request should be supported", () => {
expect(cssContent).toBe("a {}.webpack{}");
expect(noCacheCssContent).toBe("a {}.webpack{}");
expect(cachedCssContent).toBe("a {}.webpack{}");
expect(value).toBe(42);
expect(value2).toBe(42);
expect(fallback).toBe(42);
expect(redirect1).toEqual({ ok: true });
expect(redirect2).toEqual({ ok: true });
expect(redirect2).not.toBe(redirect1);
expect(text.trim()).toBe("Hello World");
});
it("https url request should be supported", () => {
expect(codeOfConduct1.includes("CODE_OF_CONDUCT")).toBeTruthy();
expect(codeOfConduct2.includes("CODE_OF_CONDUCT")).toBeTruthy();
});

View File

@ -0,0 +1,16 @@
{
"http://localhost:9990/asset.txt": { "resolved": "http://localhost:9990/asset.txt", "integrity": "sha512-LHT9F+2v2A6ER7DUZ0HuJDt+t03SFJoKsbkkb7MDgvJ+hT2FhXGeDmfL2g2qj1FnEGRhXWRa4nrLFb+xRH9Fmw==", "contentType": "text/css" },
"http://localhost:9990/fallback.js": { "resolved": "http://localhost:9990/fallback.js", "integrity": "sha512-BCkBS4Wb0EreudEceuobqZZwTE7SeVUJ2vVHxDQKm8xW6dGJRcUrrSWcjd/61zijOeYAW0P+boOg7u0vxrGwYg==", "contentType": "text/javascript" },
"http://localhost:9990/folder/dependency.js": { "resolved": "http://localhost:9990/folder/dependency.js", "integrity": "sha512-N0En4W3aNPY82MPu16+50P4PqLLyPLI6l33wR2a3ue8VCRjY8RJl8erRB8ztWSEYNad7yRDPrqlYT+IBtoOA9w==", "contentType": "text/javascript" },
"http://localhost:9990/folder/sub-dependency.js": { "resolved": "http://localhost:9990/folder/sub-dependency.js", "integrity": "sha512-Jjmwazwmg67EwNPViCBwvSIxhENfS6gwufXoQLrB0B/JDA4v1p+p2S5Y6IGP4SzZqqVTsROlU8meD6ep3q6MTA==", "contentType": "text/javascript" },
"http://localhost:9990/folder/sub-dependency2.js": { "resolved": "http://localhost:9990/folder/sub-dependency2.js", "integrity": "sha512-BDZKEwlnwBabeHEwmMd02NxFEjYy+QwKAKP0S8zMMesX7dUsvh11hM7LUOPPFOS+nIEFZPtnc7kFwmnojVUw5A==", "contentType": "text/javascript" },
"http://localhost:9990/index.css?cache": { "resolved": "http://localhost:9990/index.css?cache", "integrity": "sha512-sqhF9JAEi5h3ziP48SBnzQnaeei8cf/pfYJBdKL4F7xdu3v5yr71eQ0kCL11/jWRFjLG4TKOudUnS/u6WLMqYw==", "contentType": "text/css" },
"http://localhost:9990/index.css?no-cache": "no-cache",
"http://localhost:9990/index.css?query#fragment": { "resolved": "http://localhost:9990/index.css?query#fragment", "integrity": "sha512-sqhF9JAEi5h3ziP48SBnzQnaeei8cf/pfYJBdKL4F7xdu3v5yr71eQ0kCL11/jWRFjLG4TKOudUnS/u6WLMqYw==", "contentType": "text/css" },
"http://localhost:9990/redirect": { "resolved": "http://localhost:9990/redirect.js", "integrity": "sha512-BV/MK/QTq+NHRve1XpZyQ8V6cjRP/fwbtJvENRdm5C73qNYZ4i2/fw+soj7J4qxzBXMHDbvOnA6E0ShnX2hc1w==", "contentType": "text/javascript" },
"http://localhost:9990/redirect.js": { "resolved": "http://localhost:9990/redirect.js", "integrity": "sha512-BV/MK/QTq+NHRve1XpZyQ8V6cjRP/fwbtJvENRdm5C73qNYZ4i2/fw+soj7J4qxzBXMHDbvOnA6E0ShnX2hc1w==", "contentType": "text/javascript" },
"http://localhost:9990/resolve.js": { "resolved": "http://localhost:9990/resolve.js", "integrity": "sha512-6J9zBO2hXSMTO1EtXJOxSRB2nVPHCoNmNHS8an1QeehzJFc3uoBPRWu6hqHPc54gv2/QME9RBR/BXIan68virg==", "contentType": "text/javascript" },
"https://raw.githubusercontent.com//webpack//webpack//main/CODE_OF_CONDUCT.md": { "resolved": "https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md", "integrity": "sha512-OLJ9q6iSO652hVBkTLsMLtQnFBBTzEbFqLGyWD62nPga/0DZ9bc3oOFb5OYT8RIPzmlOX4WzK2uiLgc1NSGtBA==", "contentType": "text/plain; charset=utf-8" },
"https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md": { "resolved": "https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md", "integrity": "sha512-OLJ9q6iSO652hVBkTLsMLtQnFBBTzEbFqLGyWD62nPga/0DZ9bc3oOFb5OYT8RIPzmlOX4WzK2uiLgc1NSGtBA==", "contentType": "text/plain; charset=utf-8" },
"version": 1
}

View File

@ -0,0 +1 @@
export const fallback = 42;

View File

@ -0,0 +1,16 @@
{
"http://localhost:9990/asset.txt": { "resolved": "http://localhost:9990/asset.txt", "integrity": "sha512-LHT9F+2v2A6ER7DUZ0HuJDt+t03SFJoKsbkkb7MDgvJ+hT2FhXGeDmfL2g2qj1FnEGRhXWRa4nrLFb+xRH9Fmw==", "contentType": "text/css" },
"http://localhost:9990/fallback.js": { "resolved": "http://localhost:9990/fallback.js", "integrity": "sha512-BCkBS4Wb0EreudEceuobqZZwTE7SeVUJ2vVHxDQKm8xW6dGJRcUrrSWcjd/61zijOeYAW0P+boOg7u0vxrGwYg==", "contentType": "text/javascript" },
"http://localhost:9990/folder/dependency.js": { "resolved": "http://localhost:9990/folder/dependency.js", "integrity": "sha512-N0En4W3aNPY82MPu16+50P4PqLLyPLI6l33wR2a3ue8VCRjY8RJl8erRB8ztWSEYNad7yRDPrqlYT+IBtoOA9w==", "contentType": "text/javascript" },
"http://localhost:9990/folder/sub-dependency.js": { "resolved": "http://localhost:9990/folder/sub-dependency.js", "integrity": "sha512-Jjmwazwmg67EwNPViCBwvSIxhENfS6gwufXoQLrB0B/JDA4v1p+p2S5Y6IGP4SzZqqVTsROlU8meD6ep3q6MTA==", "contentType": "text/javascript" },
"http://localhost:9990/folder/sub-dependency2.js": { "resolved": "http://localhost:9990/folder/sub-dependency2.js", "integrity": "sha512-BDZKEwlnwBabeHEwmMd02NxFEjYy+QwKAKP0S8zMMesX7dUsvh11hM7LUOPPFOS+nIEFZPtnc7kFwmnojVUw5A==", "contentType": "text/javascript" },
"http://localhost:9990/index.css?cache": { "resolved": "http://localhost:9990/index.css?cache", "integrity": "sha512-sqhF9JAEi5h3ziP48SBnzQnaeei8cf/pfYJBdKL4F7xdu3v5yr71eQ0kCL11/jWRFjLG4TKOudUnS/u6WLMqYw==", "contentType": "text/css" },
"http://localhost:9990/index.css?no-cache": "no-cache",
"http://localhost:9990/index.css?query#fragment": { "resolved": "http://localhost:9990/index.css?query#fragment", "integrity": "sha512-sqhF9JAEi5h3ziP48SBnzQnaeei8cf/pfYJBdKL4F7xdu3v5yr71eQ0kCL11/jWRFjLG4TKOudUnS/u6WLMqYw==", "contentType": "text/css" },
"http://localhost:9990/redirect": { "resolved": "http://localhost:9990/redirect.js", "integrity": "sha512-BV/MK/QTq+NHRve1XpZyQ8V6cjRP/fwbtJvENRdm5C73qNYZ4i2/fw+soj7J4qxzBXMHDbvOnA6E0ShnX2hc1w==", "contentType": "text/javascript" },
"http://localhost:9990/redirect.js": { "resolved": "http://localhost:9990/redirect.js", "integrity": "sha512-BV/MK/QTq+NHRve1XpZyQ8V6cjRP/fwbtJvENRdm5C73qNYZ4i2/fw+soj7J4qxzBXMHDbvOnA6E0ShnX2hc1w==", "contentType": "text/javascript" },
"http://localhost:9990/resolve.js": { "resolved": "http://localhost:9990/resolve.js", "integrity": "sha512-6J9zBO2hXSMTO1EtXJOxSRB2nVPHCoNmNHS8an1QeehzJFc3uoBPRWu6hqHPc54gv2/QME9RBR/BXIan68virg==", "contentType": "text/javascript" },
"https://raw.githubusercontent.com//webpack//webpack//main/CODE_OF_CONDUCT.md": { "resolved": "https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md", "integrity": "sha512-OLJ9q6iSO652hVBkTLsMLtQnFBBTzEbFqLGyWD62nPga/0DZ9bc3oOFb5OYT8RIPzmlOX4WzK2uiLgc1NSGtBA==", "contentType": "text/plain; charset=utf-8" },
"https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md": { "resolved": "https://raw.githubusercontent.com/webpack/webpack/main/CODE_OF_CONDUCT.md", "integrity": "sha512-OLJ9q6iSO652hVBkTLsMLtQnFBBTzEbFqLGyWD62nPga/0DZ9bc3oOFb5OYT8RIPzmlOX4WzK2uiLgc1NSGtBA==", "contentType": "text/plain; charset=utf-8" },
"version": 1
}

View File

@ -0,0 +1,2 @@
export * from "./sub-dependency.js";
export * from "/folder/sub-dependency2.js";

View File

@ -0,0 +1 @@
[Code of Conduct](https://github.com/openjs-foundation/code-and-learn/blob/master/CODE_OF_CONDUCT.md)

Some files were not shown because too many files have changed in this diff Show More