Merge pull request #10080 from webpack/feature/cjs-tree-shaking
CommonJs Tree Shaking
This commit is contained in:
commit
964160a97f
|
@ -0,0 +1,282 @@
|
||||||
|
# example.js
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const inc = require("./increment").increment;
|
||||||
|
var a = 1;
|
||||||
|
inc(a); // 2
|
||||||
|
```
|
||||||
|
|
||||||
|
# increment.js
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const add = require("./math").add;
|
||||||
|
exports.increment = function increment(val) {
|
||||||
|
return add(val, 1);
|
||||||
|
};
|
||||||
|
exports.incrementBy2 = function incrementBy2(val) {
|
||||||
|
return add(val, 2);
|
||||||
|
};
|
||||||
|
exports.decrement = function decrement(val) {
|
||||||
|
return add(val, 1);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
# math.js
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
exports.add = function add() {
|
||||||
|
var sum = 0,
|
||||||
|
i = 0,
|
||||||
|
args = arguments,
|
||||||
|
l = args.length;
|
||||||
|
while (i < l) {
|
||||||
|
sum += args[i++];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.multiply = function multiply() {
|
||||||
|
var product = 0,
|
||||||
|
i = 0,
|
||||||
|
args = arguments,
|
||||||
|
l = args.length;
|
||||||
|
while (i < l) {
|
||||||
|
sum *= args[i++];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
# dist/output.js
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
/******/ (() => { // webpackBootstrap
|
||||||
|
/******/ var __webpack_modules__ = ([
|
||||||
|
/* 0 */,
|
||||||
|
/* 1 */
|
||||||
|
/*!**********************!*\
|
||||||
|
!*** ./increment.js ***!
|
||||||
|
\**********************/
|
||||||
|
/*! exports type: default defaultObject: redirect */
|
||||||
|
/*! export decrement [provided] [unused] [renamed to C] */
|
||||||
|
/*! export default [provided] [unused] [no name, virtual] */
|
||||||
|
/*! export decrement [provided] [unused] [renamed to C] */
|
||||||
|
/*! export increment [provided] [used] [renamed to pD] */
|
||||||
|
/*! export incrementBy2 [provided] [unused] [renamed to ju] */
|
||||||
|
/*! other exports [not provided] [unused] */
|
||||||
|
/*! export increment [provided] [used] [renamed to pD] */
|
||||||
|
/*! export incrementBy2 [provided] [unused] [renamed to ju] */
|
||||||
|
/*! other exports [not provided] [unused] */
|
||||||
|
/*! runtime requirements: __webpack_require__, __webpack_exports__ */
|
||||||
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||||
|
|
||||||
|
var __webpack_unused_export__;
|
||||||
|
const add = __webpack_require__(/*! ./math */ 2)/* .add */ .K;
|
||||||
|
exports.pD = function increment(val) {
|
||||||
|
return add(val, 1);
|
||||||
|
};
|
||||||
|
__webpack_unused_export__ = function incrementBy2(val) {
|
||||||
|
return add(val, 2);
|
||||||
|
};
|
||||||
|
__webpack_unused_export__ = function decrement(val) {
|
||||||
|
return add(val, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
/* 2 */
|
||||||
|
/*!*****************!*\
|
||||||
|
!*** ./math.js ***!
|
||||||
|
\*****************/
|
||||||
|
/*! exports type: default defaultObject: redirect */
|
||||||
|
/*! export add [provided] [used] [renamed to K] */
|
||||||
|
/*! export default [provided] [unused] [no name, virtual] */
|
||||||
|
/*! export add [provided] [used] [renamed to K] */
|
||||||
|
/*! export multiply [provided] [unused] [renamed to j] */
|
||||||
|
/*! other exports [not provided] [unused] */
|
||||||
|
/*! export multiply [provided] [unused] [renamed to j] */
|
||||||
|
/*! other exports [not provided] [unused] */
|
||||||
|
/*! runtime requirements: __webpack_exports__ */
|
||||||
|
/***/ ((__unused_webpack_module, exports) => {
|
||||||
|
|
||||||
|
var __webpack_unused_export__;
|
||||||
|
exports.K = function add() {
|
||||||
|
var sum = 0,
|
||||||
|
i = 0,
|
||||||
|
args = arguments,
|
||||||
|
l = args.length;
|
||||||
|
while (i < l) {
|
||||||
|
sum += args[i++];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
__webpack_unused_export__ = function multiply() {
|
||||||
|
var product = 0,
|
||||||
|
i = 0,
|
||||||
|
args = arguments,
|
||||||
|
l = args.length;
|
||||||
|
while (i < l) {
|
||||||
|
sum *= args[i++];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
/******/ ]);
|
||||||
|
```
|
||||||
|
|
||||||
|
<details><summary><code>/* webpack runtime code */</code></summary>
|
||||||
|
|
||||||
|
``` js
|
||||||
|
/************************************************************************/
|
||||||
|
/******/ // The module cache
|
||||||
|
/******/ var __webpack_module_cache__ = {};
|
||||||
|
/******/
|
||||||
|
/******/ // The require function
|
||||||
|
/******/ function __webpack_require__(moduleId) {
|
||||||
|
/******/ // Check if module is in cache
|
||||||
|
/******/ if(__webpack_module_cache__[moduleId]) {
|
||||||
|
/******/ return __webpack_module_cache__[moduleId].exports;
|
||||||
|
/******/ }
|
||||||
|
/******/ // Create a new module (and put it into the cache)
|
||||||
|
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||||
|
/******/ // no module.id needed
|
||||||
|
/******/ // no module.loaded needed
|
||||||
|
/******/ exports: {}
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // Execute the module function
|
||||||
|
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||||
|
/******/
|
||||||
|
/******/ // Return the exports of the module
|
||||||
|
/******/ return module.exports;
|
||||||
|
/******/ }
|
||||||
|
/******/
|
||||||
|
/************************************************************************/
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
``` js
|
||||||
|
(() => {
|
||||||
|
/*!********************!*\
|
||||||
|
!*** ./example.js ***!
|
||||||
|
\********************/
|
||||||
|
/*! dynamic exports type */
|
||||||
|
/*! exports [maybe provided (runtime-defined)] [unused] */
|
||||||
|
/*! runtime requirements: __webpack_require__ */
|
||||||
|
const inc = __webpack_require__(/*! ./increment */ 1)/* .increment */ .pD;
|
||||||
|
var a = 1;
|
||||||
|
inc(a); // 2
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
/******/ })()
|
||||||
|
;
|
||||||
|
```
|
||||||
|
|
||||||
|
# dist/output.js (production)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
/*! For license information please see output.js.LICENSE */
|
||||||
|
(()=>{var r=[,(r,t,n)=>{const e=n(2).K;t.pD=function(r){return e(r,1)}},(r,t)=>{t.K=function(){for(var r=0,t=0,n=arguments,e=n.length;t<e;)r+=n[t++];return r}}],t={};function n(e){if(t[e])return t[e].exports;var o=t[e]={exports:{}};return r[e](o,o.exports,n),o.exports}(0,n(1).pD)(1)})();
|
||||||
|
```
|
||||||
|
|
||||||
|
# dist/without.js (same without tree shaking)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
/*! For license information please see without.js.LICENSE */
|
||||||
|
(()=>{var n=[,(n,r,t)=>{const e=t(2).add;r.increment=function(n){return e(n,1)},r.incrementBy2=function(n){return e(n,2)},r.decrement=function(n){return e(n,1)}},(n,r)=>{r.add=function(){for(var n=0,r=0,t=arguments,e=t.length;r<e;)n+=t[r++];return n},r.multiply=function(){for(var n=0,r=arguments,t=r.length;n<t;)sum*=r[n++];return sum}}],r={};function t(e){if(r[e])return r[e].exports;var u=r[e]={exports:{}};return n[e](u,u.exports,t),u.exports}(0,t(1).increment)(1)})();
|
||||||
|
```
|
||||||
|
|
||||||
|
# Info
|
||||||
|
|
||||||
|
## Unoptimized
|
||||||
|
|
||||||
|
```
|
||||||
|
Hash: 0a1b2c3d4e5f6a7b8c9d
|
||||||
|
Version: webpack 5.0.0-beta.7
|
||||||
|
Child
|
||||||
|
Hash: 0a1b2c3d4e5f6a7b8c9d
|
||||||
|
Asset Size
|
||||||
|
output.js 3.44 KiB [emitted] [name: main]
|
||||||
|
Entrypoint main = output.js
|
||||||
|
chunk output.js (main) 634 bytes [entry] [rendered]
|
||||||
|
> ./example.js main
|
||||||
|
./example.js 70 bytes [built]
|
||||||
|
[no exports used]
|
||||||
|
entry ./example.js main
|
||||||
|
./increment.js 251 bytes [built]
|
||||||
|
[exports: default, decrement, increment, incrementBy2]
|
||||||
|
[only some exports used: increment]
|
||||||
|
cjs full require ./increment ./example.js 1:12-44
|
||||||
|
./math.js 313 bytes [built]
|
||||||
|
[exports: default, add, multiply]
|
||||||
|
[only some exports used: add]
|
||||||
|
cjs full require ./math ./increment.js 1:12-33
|
||||||
|
Child
|
||||||
|
Hash: 0a1b2c3d4e5f6a7b8c9d
|
||||||
|
Asset Size
|
||||||
|
without.js 3.7 KiB [emitted] [name: main]
|
||||||
|
Entrypoint main = without.js
|
||||||
|
chunk without.js (main) 634 bytes [entry] [rendered]
|
||||||
|
> ./example.js main
|
||||||
|
./example.js 70 bytes [built]
|
||||||
|
[used exports unknown]
|
||||||
|
entry ./example.js main
|
||||||
|
./increment.js 251 bytes [built]
|
||||||
|
[exports: default, decrement, increment, incrementBy2]
|
||||||
|
[used exports unknown]
|
||||||
|
cjs full require ./increment ./example.js 1:12-44
|
||||||
|
./math.js 313 bytes [built]
|
||||||
|
[exports: default, add, multiply]
|
||||||
|
[used exports unknown]
|
||||||
|
cjs full require ./math ./increment.js 1:12-33
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production mode
|
||||||
|
|
||||||
|
```
|
||||||
|
Hash: 0a1b2c3d4e5f6a7b8c9d
|
||||||
|
Version: webpack 5.0.0-beta.7
|
||||||
|
Child
|
||||||
|
Hash: 0a1b2c3d4e5f6a7b8c9d
|
||||||
|
Asset Size
|
||||||
|
output.js 348 bytes [emitted] [name: main]
|
||||||
|
output.js.LICENSE 1.16 KiB [emitted]
|
||||||
|
Entrypoint main = output.js
|
||||||
|
chunk output.js (main) 634 bytes [entry] [rendered]
|
||||||
|
> ./example.js main
|
||||||
|
./example.js 70 bytes [built]
|
||||||
|
[no exports used]
|
||||||
|
entry ./example.js main
|
||||||
|
./increment.js 251 bytes [built]
|
||||||
|
[exports: default, decrement, increment, incrementBy2]
|
||||||
|
[only some exports used: increment]
|
||||||
|
cjs full require ./increment ./example.js 1:12-44
|
||||||
|
./math.js 313 bytes [built]
|
||||||
|
[exports: default, add, multiply]
|
||||||
|
[only some exports used: add]
|
||||||
|
cjs full require ./math ./increment.js 1:12-33
|
||||||
|
Child
|
||||||
|
Hash: 0a1b2c3d4e5f6a7b8c9d
|
||||||
|
Asset Size
|
||||||
|
without.js 534 bytes [emitted] [name: main]
|
||||||
|
without.js.LICENSE 1.49 KiB [emitted]
|
||||||
|
Entrypoint main = without.js
|
||||||
|
chunk without.js (main) 634 bytes [entry] [rendered]
|
||||||
|
> ./example.js main
|
||||||
|
./example.js 70 bytes [built]
|
||||||
|
[used exports unknown]
|
||||||
|
entry ./example.js main
|
||||||
|
./increment.js 251 bytes [built]
|
||||||
|
[exports: default, decrement, increment, incrementBy2]
|
||||||
|
[used exports unknown]
|
||||||
|
cjs full require ./increment ./example.js 1:12-44
|
||||||
|
./math.js 313 bytes [built]
|
||||||
|
[exports: default, add, multiply]
|
||||||
|
[used exports unknown]
|
||||||
|
cjs full require ./math ./increment.js 1:12-33
|
||||||
|
```
|
|
@ -0,0 +1,2 @@
|
||||||
|
global.NO_TARGET_ARGS = true;
|
||||||
|
require("../build-common");
|
|
@ -0,0 +1,58 @@
|
||||||
|
BAD:
|
||||||
|
|
||||||
|
module.exports = abc; module.exports.xxx = abc; abc.xxx;
|
||||||
|
exports = abc;
|
||||||
|
module.exports
|
||||||
|
exports
|
||||||
|
this
|
||||||
|
function f() { return this; } module.exports = { f }; module.exports.xxx = abc;
|
||||||
|
|
||||||
|
|
||||||
|
EXPORTS:
|
||||||
|
|
||||||
|
exports.xxx = abc;
|
||||||
|
|
||||||
|
module.exports.xxx = abc;
|
||||||
|
this.xxx = abc
|
||||||
|
Object.defineProperty(exports, "xxx", { ... })
|
||||||
|
Object.defineProperty(module.exports, "xxx", { ... })
|
||||||
|
Object.defineProperty(this, "xxx", { ... })
|
||||||
|
module.exports.xxx
|
||||||
|
exports.xxx
|
||||||
|
this.xxx
|
||||||
|
module.exports = function() {}; module.exports.xxx = abc;
|
||||||
|
module.exports = { ... }; module.exports.xxx = abc;
|
||||||
|
|
||||||
|
OBJECTS:
|
||||||
|
|
||||||
|
module.exports = { xxx: abc };
|
||||||
|
|
||||||
|
IMPORT:
|
||||||
|
|
||||||
|
require(x).xxx
|
||||||
|
var { xxx } = require(x);
|
||||||
|
var x = require(x); x.xxx;
|
||||||
|
|
||||||
|
REEXPORT:
|
||||||
|
|
||||||
|
module.exports.xxx = require(x);
|
||||||
|
module.exports.xxx = require(x).xxx;
|
||||||
|
exports.xxx = require(x);
|
||||||
|
exports.xxx = require(x).xxx;
|
||||||
|
module.exports = { xxx2: require(x) };
|
||||||
|
module.exports = { xxx2: require(x).xxx };
|
||||||
|
var xxx = require(x); exports.xxx = xxx;
|
||||||
|
var xxx = require(x); exports.xxx = xxx.xxx;
|
||||||
|
var xxx = require(x); module.exports = { xxx };
|
||||||
|
var xxx = require(x); module.exports = { xxx: xxx.xxx };
|
||||||
|
|
||||||
|
TRANSPILED:
|
||||||
|
|
||||||
|
TypeScript:
|
||||||
|
function __export(m) { for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; }
|
||||||
|
__export(require(x));
|
||||||
|
|
||||||
|
Babel:
|
||||||
|
var xxx = _interopRequireDefault(require(x));
|
||||||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||||
|
xxx.xxx;
|
|
@ -0,0 +1,3 @@
|
||||||
|
const inc = require("./increment").increment;
|
||||||
|
var a = 1;
|
||||||
|
inc(a); // 2
|
|
@ -0,0 +1,10 @@
|
||||||
|
const add = require("./math").add;
|
||||||
|
exports.increment = function increment(val) {
|
||||||
|
return add(val, 1);
|
||||||
|
};
|
||||||
|
exports.incrementBy2 = function incrementBy2(val) {
|
||||||
|
return add(val, 2);
|
||||||
|
};
|
||||||
|
exports.decrement = function decrement(val) {
|
||||||
|
return add(val, 1);
|
||||||
|
};
|
|
@ -0,0 +1,21 @@
|
||||||
|
exports.add = function add() {
|
||||||
|
var sum = 0,
|
||||||
|
i = 0,
|
||||||
|
args = arguments,
|
||||||
|
l = args.length;
|
||||||
|
while (i < l) {
|
||||||
|
sum += args[i++];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.multiply = function multiply() {
|
||||||
|
var product = 0,
|
||||||
|
i = 0,
|
||||||
|
args = arguments,
|
||||||
|
l = args.length;
|
||||||
|
while (i < l) {
|
||||||
|
sum *= args[i++];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
};
|
|
@ -0,0 +1,49 @@
|
||||||
|
# example.js
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
_{{example.js}}_
|
||||||
|
```
|
||||||
|
|
||||||
|
# increment.js
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
_{{increment.js}}_
|
||||||
|
```
|
||||||
|
|
||||||
|
# math.js
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
_{{math.js}}_
|
||||||
|
```
|
||||||
|
|
||||||
|
# dist/output.js
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
_{{dist/output.js}}_
|
||||||
|
```
|
||||||
|
|
||||||
|
# dist/output.js (production)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
_{{production:dist/output.js}}_
|
||||||
|
```
|
||||||
|
|
||||||
|
# dist/without.js (same without tree shaking)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
_{{production:dist/without.js}}_
|
||||||
|
```
|
||||||
|
|
||||||
|
# Info
|
||||||
|
|
||||||
|
## Unoptimized
|
||||||
|
|
||||||
|
```
|
||||||
|
_{{stdout}}_
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production mode
|
||||||
|
|
||||||
|
```
|
||||||
|
_{{production:stdout}}_
|
||||||
|
```
|
|
@ -0,0 +1,26 @@
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
entry: "./example.js",
|
||||||
|
output: {
|
||||||
|
pathinfo: true,
|
||||||
|
filename: "output.js"
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
moduleIds: "size",
|
||||||
|
usedExports: true,
|
||||||
|
mangleExports: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
entry: "./example.js",
|
||||||
|
output: {
|
||||||
|
pathinfo: true,
|
||||||
|
filename: "without.js"
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
moduleIds: "size",
|
||||||
|
usedExports: false,
|
||||||
|
mangleExports: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
|
@ -1,260 +0,0 @@
|
||||||
/*
|
|
||||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
|
||||||
Author Tobias Koppers @sokra
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const RuntimeGlobals = require("./RuntimeGlobals");
|
|
||||||
const RuntimeModule = require("./RuntimeModule");
|
|
||||||
const Template = require("./Template");
|
|
||||||
const ModuleDecoratorDependency = require("./dependencies/ModuleDecoratorDependency");
|
|
||||||
const RuntimeRequirementsDependency = require("./dependencies/RuntimeRequirementsDependency");
|
|
||||||
const {
|
|
||||||
evaluateToIdentifier,
|
|
||||||
expressionIsUnsupported,
|
|
||||||
toConstantDependency
|
|
||||||
} = require("./javascript/JavascriptParserHelpers");
|
|
||||||
|
|
||||||
class CommonJsStuffPlugin {
|
|
||||||
apply(compiler) {
|
|
||||||
compiler.hooks.compilation.tap(
|
|
||||||
"CommonJsStuffPlugin",
|
|
||||||
(compilation, { normalModuleFactory }) => {
|
|
||||||
compilation.dependencyFactories.set(
|
|
||||||
ModuleDecoratorDependency,
|
|
||||||
normalModuleFactory
|
|
||||||
);
|
|
||||||
compilation.dependencyTemplates.set(
|
|
||||||
ModuleDecoratorDependency,
|
|
||||||
new ModuleDecoratorDependency.Template()
|
|
||||||
);
|
|
||||||
|
|
||||||
compilation.hooks.runtimeRequirementInModule
|
|
||||||
.for(RuntimeGlobals.harmonyModuleDecorator)
|
|
||||||
.tap("CommonJsStuffPlugin", (module, set) => {
|
|
||||||
set.add(RuntimeGlobals.module);
|
|
||||||
set.add(RuntimeGlobals.requireScope);
|
|
||||||
});
|
|
||||||
|
|
||||||
compilation.hooks.runtimeRequirementInModule
|
|
||||||
.for(RuntimeGlobals.nodeModuleDecorator)
|
|
||||||
.tap("CommonJsStuffPlugin", (module, set) => {
|
|
||||||
set.add(RuntimeGlobals.module);
|
|
||||||
set.add(RuntimeGlobals.requireScope);
|
|
||||||
});
|
|
||||||
|
|
||||||
compilation.hooks.runtimeRequirementInTree
|
|
||||||
.for(RuntimeGlobals.harmonyModuleDecorator)
|
|
||||||
.tap("CommonJsStuffPlugin", (chunk, set) => {
|
|
||||||
compilation.addRuntimeModule(
|
|
||||||
chunk,
|
|
||||||
new HarmonyModuleDecoratorRuntimeModule()
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
compilation.hooks.runtimeRequirementInTree
|
|
||||||
.for(RuntimeGlobals.nodeModuleDecorator)
|
|
||||||
.tap("CommonJsStuffPlugin", (chunk, set) => {
|
|
||||||
compilation.addRuntimeModule(
|
|
||||||
chunk,
|
|
||||||
new NodeModuleDecoratorRuntimeModule()
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const handler = (parser, parserOptions) => {
|
|
||||||
parser.hooks.expression
|
|
||||||
.for("require.main.require")
|
|
||||||
.tap(
|
|
||||||
"CommonJsStuffPlugin",
|
|
||||||
expressionIsUnsupported(
|
|
||||||
parser,
|
|
||||||
"require.main.require is not supported by webpack."
|
|
||||||
)
|
|
||||||
);
|
|
||||||
parser.hooks.expression
|
|
||||||
.for("module.parent.require")
|
|
||||||
.tap(
|
|
||||||
"CommonJsStuffPlugin",
|
|
||||||
expressionIsUnsupported(
|
|
||||||
parser,
|
|
||||||
"module.parent.require is not supported by webpack."
|
|
||||||
)
|
|
||||||
);
|
|
||||||
parser.hooks.expression
|
|
||||||
.for("require.main")
|
|
||||||
.tap(
|
|
||||||
"CommonJsStuffPlugin",
|
|
||||||
toConstantDependency(
|
|
||||||
parser,
|
|
||||||
`${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}]`,
|
|
||||||
[RuntimeGlobals.moduleCache, RuntimeGlobals.entryModuleId]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
parser.hooks.expression
|
|
||||||
.for("module.loaded")
|
|
||||||
.tap("CommonJsStuffPlugin", expr => {
|
|
||||||
parser.state.module.buildMeta.moduleConcatenationBailout =
|
|
||||||
"module.loaded";
|
|
||||||
return toConstantDependency(
|
|
||||||
parser,
|
|
||||||
`${RuntimeGlobals.module}.l`,
|
|
||||||
[RuntimeGlobals.module]
|
|
||||||
)(expr);
|
|
||||||
});
|
|
||||||
parser.hooks.expression
|
|
||||||
.for("module.id")
|
|
||||||
.tap("CommonJsStuffPlugin", expr => {
|
|
||||||
parser.state.module.buildMeta.moduleConcatenationBailout =
|
|
||||||
"module.id";
|
|
||||||
return toConstantDependency(
|
|
||||||
parser,
|
|
||||||
`${RuntimeGlobals.module}.i`,
|
|
||||||
[RuntimeGlobals.module]
|
|
||||||
)(expr);
|
|
||||||
});
|
|
||||||
parser.hooks.expression
|
|
||||||
.for("module.exports")
|
|
||||||
.tap("CommonJsStuffPlugin", expr => {
|
|
||||||
const module = parser.state.module;
|
|
||||||
const isHarmony =
|
|
||||||
module.buildMeta && module.buildMeta.exportsType;
|
|
||||||
if (!isHarmony) {
|
|
||||||
if (module.moduleArgument === "module") {
|
|
||||||
// avoid rewriting module.exports for backward-compat
|
|
||||||
const dep = new RuntimeRequirementsDependency([
|
|
||||||
RuntimeGlobals.module
|
|
||||||
]);
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
module.addPresentationalDependency(dep);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return toConstantDependency(
|
|
||||||
parser,
|
|
||||||
`${module.moduleArgument}.exports`,
|
|
||||||
[RuntimeGlobals.module]
|
|
||||||
)(expr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
parser.hooks.expression
|
|
||||||
.for("this")
|
|
||||||
.tap("CommonJsStuffPlugin", expr => {
|
|
||||||
if (!parser.scope.topLevelScope) return;
|
|
||||||
const module = parser.state.module;
|
|
||||||
const isHarmony =
|
|
||||||
module.buildMeta && module.buildMeta.exportsType;
|
|
||||||
if (!isHarmony) {
|
|
||||||
return toConstantDependency(parser, "this", [
|
|
||||||
RuntimeGlobals.thisAsExports
|
|
||||||
])(expr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
parser.hooks.evaluateIdentifier.for("module.hot").tap(
|
|
||||||
"CommonJsStuffPlugin",
|
|
||||||
evaluateToIdentifier("module.hot", "module", () => ["hot"], false)
|
|
||||||
);
|
|
||||||
parser.hooks.expression
|
|
||||||
.for("module")
|
|
||||||
.tap("CommonJsStuffPlugin", expr => {
|
|
||||||
const isHarmony =
|
|
||||||
parser.state.module.buildMeta &&
|
|
||||||
parser.state.module.buildMeta.exportsType;
|
|
||||||
const dep = new ModuleDecoratorDependency(
|
|
||||||
isHarmony
|
|
||||||
? RuntimeGlobals.harmonyModuleDecorator
|
|
||||||
: RuntimeGlobals.nodeModuleDecorator
|
|
||||||
);
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
parser.state.module.addPresentationalDependency(dep);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
normalModuleFactory.hooks.parser
|
|
||||||
.for("javascript/auto")
|
|
||||||
.tap("CommonJsStuffPlugin", handler);
|
|
||||||
normalModuleFactory.hooks.parser
|
|
||||||
.for("javascript/dynamic")
|
|
||||||
.tap("CommonJsStuffPlugin", handler);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class HarmonyModuleDecoratorRuntimeModule extends RuntimeModule {
|
|
||||||
constructor() {
|
|
||||||
super("harmony module decorator");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {string} runtime code
|
|
||||||
*/
|
|
||||||
generate() {
|
|
||||||
const { runtimeTemplate } = this.compilation;
|
|
||||||
return Template.asString([
|
|
||||||
`${
|
|
||||||
RuntimeGlobals.harmonyModuleDecorator
|
|
||||||
} = ${runtimeTemplate.basicFunction("module", [
|
|
||||||
"module = Object.create(module);",
|
|
||||||
"if (!module.children) module.children = [];",
|
|
||||||
"Object.defineProperty(module, 'loaded', {",
|
|
||||||
Template.indent([
|
|
||||||
"enumerable: true,",
|
|
||||||
`get: ${runtimeTemplate.returningFunction("module.l")}`
|
|
||||||
]),
|
|
||||||
"});",
|
|
||||||
"Object.defineProperty(module, 'id', {",
|
|
||||||
Template.indent([
|
|
||||||
"enumerable: true,",
|
|
||||||
`get: ${runtimeTemplate.returningFunction("module.i")}`
|
|
||||||
]),
|
|
||||||
"});",
|
|
||||||
"Object.defineProperty(module, 'exports', {",
|
|
||||||
Template.indent([
|
|
||||||
"enumerable: true,",
|
|
||||||
`set: ${runtimeTemplate.basicFunction("", [
|
|
||||||
"throw new Error('ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: ' + module.id);"
|
|
||||||
])}`
|
|
||||||
]),
|
|
||||||
"});",
|
|
||||||
"return module;"
|
|
||||||
])};`
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NodeModuleDecoratorRuntimeModule extends RuntimeModule {
|
|
||||||
constructor() {
|
|
||||||
super("node module decorator");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {string} runtime code
|
|
||||||
*/
|
|
||||||
generate() {
|
|
||||||
const { runtimeTemplate } = this.compilation;
|
|
||||||
return Template.asString([
|
|
||||||
`${
|
|
||||||
RuntimeGlobals.nodeModuleDecorator
|
|
||||||
} = ${runtimeTemplate.basicFunction("module", [
|
|
||||||
"module.paths = [];",
|
|
||||||
"if (!module.children) module.children = [];",
|
|
||||||
"Object.defineProperty(module, 'loaded', {",
|
|
||||||
Template.indent([
|
|
||||||
"enumerable: true,",
|
|
||||||
`get: ${runtimeTemplate.returningFunction("module.l")}`
|
|
||||||
]),
|
|
||||||
"});",
|
|
||||||
"Object.defineProperty(module, 'id', {",
|
|
||||||
Template.indent([
|
|
||||||
"enumerable: true,",
|
|
||||||
`get: ${runtimeTemplate.returningFunction("module.i")}`
|
|
||||||
]),
|
|
||||||
"});",
|
|
||||||
"return module;"
|
|
||||||
])};`
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = CommonJsStuffPlugin;
|
|
|
@ -462,13 +462,12 @@ class ContextModule extends Module {
|
||||||
return 9;
|
return 9;
|
||||||
}
|
}
|
||||||
const moduleGraph = chunkGraph.moduleGraph;
|
const moduleGraph = chunkGraph.moduleGraph;
|
||||||
|
// bitfield
|
||||||
|
let hasType = 0;
|
||||||
|
const comparator = compareModulesById(chunkGraph);
|
||||||
// if we filter first we get a new array
|
// if we filter first we get a new array
|
||||||
// therefor we dont need to create a clone of dependencies explicitly
|
// therefor we dont need to create a clone of dependencies explicitly
|
||||||
// therefore the order of this is !important!
|
// therefore the order of this is !important!
|
||||||
let hasNonHarmony = false;
|
|
||||||
let hasNamespace = false;
|
|
||||||
let hasNamed = false;
|
|
||||||
const comparator = compareModulesById(chunkGraph);
|
|
||||||
const fakeMap = dependencies
|
const fakeMap = dependencies
|
||||||
.map(dependency => ({
|
.map(dependency => ({
|
||||||
module: moduleGraph.getModule(dependency),
|
module: moduleGraph.getModule(dependency),
|
||||||
|
@ -477,30 +476,46 @@ class ContextModule extends Module {
|
||||||
.filter(item => item.module)
|
.filter(item => item.module)
|
||||||
.sort((a, b) => comparator(a.module, b.module))
|
.sort((a, b) => comparator(a.module, b.module))
|
||||||
.reduce((map, { dependency: dep, module }) => {
|
.reduce((map, { dependency: dep, module }) => {
|
||||||
const exportsType = module.buildMeta && module.buildMeta.exportsType;
|
const exportsType = module.getExportsType(
|
||||||
|
this.options.namespaceObject === "strict"
|
||||||
|
);
|
||||||
const id = chunkGraph.getModuleId(module);
|
const id = chunkGraph.getModuleId(module);
|
||||||
if (!exportsType) {
|
switch (exportsType) {
|
||||||
map[id] = this.options.namespaceObject === "strict" ? 1 : 7;
|
case "namespace":
|
||||||
hasNonHarmony = true;
|
map[id] = 9;
|
||||||
} else if (exportsType === "namespace") {
|
hasType |= 1;
|
||||||
map[id] = 9;
|
break;
|
||||||
hasNamespace = true;
|
case "dynamic":
|
||||||
} else if (exportsType === "default") {
|
map[id] = 7;
|
||||||
map[id] = this.options.namespaceObject === "strict" ? 1 : 3;
|
hasType |= 2;
|
||||||
hasNamed = true;
|
break;
|
||||||
|
case "dynamic-default":
|
||||||
|
case "default-only":
|
||||||
|
map[id] = 1;
|
||||||
|
hasType |= 4;
|
||||||
|
break;
|
||||||
|
case "default-with-named":
|
||||||
|
map[id] = 3;
|
||||||
|
hasType |= 8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unexpected exports type ${exportsType}`);
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}, Object.create(null));
|
}, Object.create(null));
|
||||||
if (!hasNamespace && hasNonHarmony && !hasNamed) {
|
if (hasType === 1) {
|
||||||
return this.options.namespaceObject === "strict" ? 1 : 7;
|
|
||||||
}
|
|
||||||
if (hasNamespace && !hasNonHarmony && !hasNamed) {
|
|
||||||
return 9;
|
return 9;
|
||||||
}
|
}
|
||||||
if (!hasNamespace && !hasNonHarmony && hasNamed) {
|
if (hasType === 2) {
|
||||||
return this.options.namespaceObject === "strict" ? 1 : 3;
|
return 7;
|
||||||
}
|
}
|
||||||
if (!hasNamespace && !hasNonHarmony && !hasNamed) {
|
if (hasType === 4) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (hasType === 8) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if (hasType === 0) {
|
||||||
return 9;
|
return 9;
|
||||||
}
|
}
|
||||||
return fakeMap;
|
return fakeMap;
|
||||||
|
|
|
@ -65,7 +65,8 @@ const makeSerializable = require("./util/makeSerializable");
|
||||||
* @property {string=} exportsArgument
|
* @property {string=} exportsArgument
|
||||||
* @property {boolean=} strict
|
* @property {boolean=} strict
|
||||||
* @property {string=} moduleConcatenationBailout
|
* @property {string=} moduleConcatenationBailout
|
||||||
* @property {("default" | "namespace")=} exportsType
|
* @property {("default" | "namespace" | "flagged")=} exportsType
|
||||||
|
* @property {(boolean | "redirect" | "redirect-warn")=} defaultObject
|
||||||
* @property {boolean=} strictHarmonyModule
|
* @property {boolean=} strictHarmonyModule
|
||||||
* @property {boolean=} async
|
* @property {boolean=} async
|
||||||
*/
|
*/
|
||||||
|
@ -364,6 +365,29 @@ class Module extends DependenciesBlock {
|
||||||
return (this.buildInfo && this.buildInfo.moduleArgument) || "module";
|
return (this.buildInfo && this.buildInfo.moduleArgument) || "module";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {boolean} strict the importing module is strict
|
||||||
|
* @returns {"dynamic" | "dynamic-default" | "namespace" | "default-only" | "default-with-named"} export type
|
||||||
|
*/
|
||||||
|
getExportsType(strict) {
|
||||||
|
switch (this.buildMeta && this.buildMeta.exportsType) {
|
||||||
|
case "flagged":
|
||||||
|
return strict ? "dynamic-default" : "namespace";
|
||||||
|
case "namespace":
|
||||||
|
return "namespace";
|
||||||
|
case "default":
|
||||||
|
switch (this.buildMeta.defaultObject) {
|
||||||
|
case "redirect":
|
||||||
|
case "redirect-warn":
|
||||||
|
return strict ? "default-only" : "default-with-named";
|
||||||
|
default:
|
||||||
|
return "default-only";
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return strict ? "dynamic-default" : "dynamic";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Dependency} presentationalDependency dependency being tied to module.
|
* @param {Dependency} presentationalDependency dependency being tied to module.
|
||||||
* This is a Dependency without edge in the module graph. It's only for presentation.
|
* This is a Dependency without edge in the module graph. It's only for presentation.
|
||||||
|
@ -602,7 +626,11 @@ class Module extends DependenciesBlock {
|
||||||
for (const exportInfo of exportsInfo.orderedExports) {
|
for (const exportInfo of exportsInfo.orderedExports) {
|
||||||
hash.update(exportInfo.name);
|
hash.update(exportInfo.name);
|
||||||
hash.update(exportInfo.used + "");
|
hash.update(exportInfo.used + "");
|
||||||
hash.update(exportInfo.usedName + "");
|
hash.update(
|
||||||
|
exportInfo.usedName === ModuleGraph.SKIP_OVER_NAME
|
||||||
|
? "<skip-over-name>"
|
||||||
|
: exportInfo.usedName + ""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (this.presentationalDependencies !== undefined) {
|
if (this.presentationalDependencies !== undefined) {
|
||||||
for (const dep of this.presentationalDependencies) {
|
for (const dep of this.presentationalDependencies) {
|
||||||
|
|
|
@ -24,6 +24,8 @@ const makeSerializable = require("./util/makeSerializable");
|
||||||
|
|
||||||
const EMPTY_ARRAY = [];
|
const EMPTY_ARRAY = [];
|
||||||
|
|
||||||
|
const SKIP_OVER_NAME = Symbol("skip over name");
|
||||||
|
|
||||||
/** @typedef {0|1|2|3|4} UsageStateType */
|
/** @typedef {0|1|2|3|4} UsageStateType */
|
||||||
|
|
||||||
const UsageState = Object.freeze({
|
const UsageState = Object.freeze({
|
||||||
|
@ -130,12 +132,8 @@ class ExportsInfo {
|
||||||
this._exportsAreOrdered = true;
|
this._exportsAreOrdered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
setRedirectToDefaultObject() {
|
setRedirectNamedTo(exportsInfo) {
|
||||||
const defaultInfo = this.getExportInfo("default");
|
this._redirectTo = exportsInfo;
|
||||||
defaultInfo.canMangleProvide = false;
|
|
||||||
defaultInfo.usedName = "";
|
|
||||||
const inner = defaultInfo.createNestedExportsInfo();
|
|
||||||
this._redirectTo = inner;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setHasProvideInfo() {
|
setHasProvideInfo() {
|
||||||
|
@ -190,8 +188,6 @@ class ExportsInfo {
|
||||||
const info = this._exports.get(name);
|
const info = this._exports.get(name);
|
||||||
if (info !== undefined) return info;
|
if (info !== undefined) return info;
|
||||||
if (this._redirectTo) return this._redirectTo.getExportInfo(name);
|
if (this._redirectTo) return this._redirectTo.getExportInfo(name);
|
||||||
if (!name)
|
|
||||||
throw new Error("ModuleGraph.getExportInfo name must be a valid string");
|
|
||||||
const newInfo = new ExportInfo(name, this._otherExportsInfo);
|
const newInfo = new ExportInfo(name, this._otherExportsInfo);
|
||||||
this._exports.set(name, newInfo);
|
this._exports.set(name, newInfo);
|
||||||
this._exportsAreOrdered = false;
|
this._exportsAreOrdered = false;
|
||||||
|
@ -456,11 +452,16 @@ class ExportsInfo {
|
||||||
let info = this.getReadOnlyExportInfo(name[0]);
|
let info = this.getReadOnlyExportInfo(name[0]);
|
||||||
const x = info.getUsedName(name[0]);
|
const x = info.getUsedName(name[0]);
|
||||||
if (x === false) return false;
|
if (x === false) return false;
|
||||||
const arr = x === name[0] && name.length === 1 ? name : x ? [x] : [];
|
const arr =
|
||||||
|
x === name[0] && name.length === 1
|
||||||
|
? name
|
||||||
|
: x !== SKIP_OVER_NAME
|
||||||
|
? [x]
|
||||||
|
: EMPTY_ARRAY;
|
||||||
if (name.length === 1) {
|
if (name.length === 1) {
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
if (info.exportsInfo) {
|
if (info.exportsInfo && info.used === UsageState.OnlyPropertiesUsed) {
|
||||||
const nested = info.exportsInfo.getUsedName(name.slice(1));
|
const nested = info.exportsInfo.getUsedName(name.slice(1));
|
||||||
if (!nested) return false;
|
if (!nested) return false;
|
||||||
return arr.concat(nested);
|
return arr.concat(nested);
|
||||||
|
@ -527,7 +528,7 @@ class ExportInfo {
|
||||||
constructor(name, initFrom) {
|
constructor(name, initFrom) {
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
this.name = name;
|
this.name = name;
|
||||||
/** @type {string | null} */
|
/** @type {string | null | SKIP_OVER_NAME} */
|
||||||
this.usedName = initFrom ? initFrom.usedName : null;
|
this.usedName = initFrom ? initFrom.usedName : null;
|
||||||
/** @type {UsageStateType} */
|
/** @type {UsageStateType} */
|
||||||
this.used = initFrom ? initFrom.used : UsageState.NoInfo;
|
this.used = initFrom ? initFrom.used : UsageState.NoInfo;
|
||||||
|
@ -628,7 +629,9 @@ class ExportInfo {
|
||||||
|
|
||||||
getRenameInfo() {
|
getRenameInfo() {
|
||||||
if (this.usedName !== null && this.usedName !== this.name) {
|
if (this.usedName !== null && this.usedName !== this.name) {
|
||||||
return this.usedName ? `renamed to ${this.usedName}` : "no name, virtual";
|
return this.usedName !== SKIP_OVER_NAME
|
||||||
|
? `renamed to ${JSON.stringify(this.usedName).slice(1, -1)}`
|
||||||
|
: "no name, virtual";
|
||||||
}
|
}
|
||||||
switch (this.canMangleProvide) {
|
switch (this.canMangleProvide) {
|
||||||
case undefined:
|
case undefined:
|
||||||
|
@ -958,7 +961,20 @@ class ModuleGraph {
|
||||||
*/
|
*/
|
||||||
finishModule(module) {
|
finishModule(module) {
|
||||||
if (module.buildMeta.exportsType === "default") {
|
if (module.buildMeta.exportsType === "default") {
|
||||||
this.getExportsInfo(module).setRedirectToDefaultObject();
|
const exportsInfo = this.getExportsInfo(module);
|
||||||
|
const defaultInfo = exportsInfo.getExportInfo("default");
|
||||||
|
defaultInfo.canMangleProvide = false;
|
||||||
|
defaultInfo.provided = true;
|
||||||
|
defaultInfo.usedName = SKIP_OVER_NAME;
|
||||||
|
if (module.buildMeta.defaultObject) {
|
||||||
|
const innerObject = defaultInfo.createNestedExportsInfo();
|
||||||
|
if (
|
||||||
|
module.buildMeta.defaultObject === "redirect" ||
|
||||||
|
module.buildMeta.defaultObject === "redirect-warn"
|
||||||
|
) {
|
||||||
|
exportsInfo.setRedirectNamedTo(innerObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1322,4 +1338,5 @@ module.exports = ModuleGraph;
|
||||||
module.exports.ModuleGraphConnection = ModuleGraphConnection;
|
module.exports.ModuleGraphConnection = ModuleGraphConnection;
|
||||||
module.exports.ExportsInfo = ExportsInfo;
|
module.exports.ExportsInfo = ExportsInfo;
|
||||||
module.exports.ExportInfo = ExportInfo;
|
module.exports.ExportInfo = ExportInfo;
|
||||||
|
module.exports.SKIP_OVER_NAME = SKIP_OVER_NAME;
|
||||||
module.exports.UsageState = UsageState;
|
module.exports.UsageState = UsageState;
|
||||||
|
|
|
@ -33,9 +33,10 @@ const printExportsInfoToSource = (source, indent, exportsInfo) => {
|
||||||
for (const exportInfo of exportsInfo.orderedExports) {
|
for (const exportInfo of exportsInfo.orderedExports) {
|
||||||
source.add(
|
source.add(
|
||||||
Template.toComment(
|
Template.toComment(
|
||||||
`${indent}export ${
|
`${indent}export ${JSON.stringify(exportInfo.name).slice(
|
||||||
exportInfo.name
|
1,
|
||||||
} [${exportInfo.getProvidedInfo()}] [${exportInfo.getUsedInfo()}] [${exportInfo.getRenameInfo()}]`
|
-1
|
||||||
|
)} [${exportInfo.getProvidedInfo()}] [${exportInfo.getUsedInfo()}] [${exportInfo.getRenameInfo()}]`
|
||||||
) + "\n"
|
) + "\n"
|
||||||
);
|
);
|
||||||
if (exportInfo.exportsInfo) {
|
if (exportInfo.exportsInfo) {
|
||||||
|
@ -79,6 +80,14 @@ class ModuleInfoHeaderPlugin {
|
||||||
source.add("/*!****" + reqStrStar + "****!*\\\n");
|
source.add("/*!****" + reqStrStar + "****!*\\\n");
|
||||||
source.add(" !*** " + reqStr + " ***!\n");
|
source.add(" !*** " + reqStr + " ***!\n");
|
||||||
source.add(" \\****" + reqStrStar + "****/\n");
|
source.add(" \\****" + reqStrStar + "****/\n");
|
||||||
|
const exportsType = module.buildMeta.exportsType;
|
||||||
|
source.add(
|
||||||
|
Template.toComment(
|
||||||
|
exportsType
|
||||||
|
? `${exportsType} exports`
|
||||||
|
: "unknown exports (runtime-defined)"
|
||||||
|
) + "\n"
|
||||||
|
);
|
||||||
const exportsInfo = moduleGraph.getExportsInfo(module);
|
const exportsInfo = moduleGraph.getExportsInfo(module);
|
||||||
printExportsInfoToSource(source, "", exportsInfo);
|
printExportsInfoToSource(source, "", exportsInfo);
|
||||||
source.add(
|
source.add(
|
||||||
|
|
|
@ -13,13 +13,15 @@ const AbstractMethodError = require("./AbstractMethodError");
|
||||||
/** @typedef {Record<string, any>} PreparsedAst */
|
/** @typedef {Record<string, any>} PreparsedAst */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} ParserState
|
* @typedef {Object} ParserStateBase
|
||||||
* @property {NormalModule} current
|
* @property {NormalModule} current
|
||||||
* @property {NormalModule} module
|
* @property {NormalModule} module
|
||||||
* @property {Compilation} compilation
|
* @property {Compilation} compilation
|
||||||
* @property {TODO} options
|
* @property {TODO} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** @typedef {Record<string, any> & ParserStateBase} ParserState */
|
||||||
|
|
||||||
class Parser {
|
class Parser {
|
||||||
/**
|
/**
|
||||||
* @param {string | Buffer | PreparsedAst} source the source to parse
|
* @param {string | Buffer | PreparsedAst} source the source to parse
|
||||||
|
|
|
@ -35,6 +35,16 @@ exports.returnExportsFromRuntime = "return-exports-from-runtime";
|
||||||
*/
|
*/
|
||||||
exports.module = "module";
|
exports.module = "module";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the internal module object
|
||||||
|
*/
|
||||||
|
exports.moduleId = "module.id";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the internal module object
|
||||||
|
*/
|
||||||
|
exports.moduleLoaded = "module.loaded";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the bundle public path
|
* the bundle public path
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -45,6 +45,11 @@ const GLOBALS_ON_REQUIRE = [
|
||||||
RuntimeGlobals.instantiateWasm
|
RuntimeGlobals.instantiateWasm
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const MODULE_DEPENDENCIES = {
|
||||||
|
[RuntimeGlobals.moduleLoaded]: [RuntimeGlobals.module],
|
||||||
|
[RuntimeGlobals.moduleId]: [RuntimeGlobals.module]
|
||||||
|
};
|
||||||
|
|
||||||
const TREE_DEPENDENCIES = {
|
const TREE_DEPENDENCIES = {
|
||||||
[RuntimeGlobals.definePropertyGetters]: [RuntimeGlobals.hasOwnProperty],
|
[RuntimeGlobals.definePropertyGetters]: [RuntimeGlobals.hasOwnProperty],
|
||||||
[RuntimeGlobals.compatGetDefaultExport]: [
|
[RuntimeGlobals.compatGetDefaultExport]: [
|
||||||
|
@ -88,6 +93,14 @@ class RuntimePlugin {
|
||||||
for (const dep of deps) set.add(dep);
|
for (const dep of deps) set.add(dep);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
for (const req of Object.keys(MODULE_DEPENDENCIES)) {
|
||||||
|
const deps = MODULE_DEPENDENCIES[req];
|
||||||
|
compilation.hooks.runtimeRequirementInModule
|
||||||
|
.for(req)
|
||||||
|
.tap("RuntimePlugin", (chunk, set) => {
|
||||||
|
for (const dep of deps) set.add(dep);
|
||||||
|
});
|
||||||
|
}
|
||||||
compilation.hooks.runtimeRequirementInTree
|
compilation.hooks.runtimeRequirementInTree
|
||||||
.for(RuntimeGlobals.definePropertyGetters)
|
.for(RuntimeGlobals.definePropertyGetters)
|
||||||
.tap("RuntimePlugin", chunk => {
|
.tap("RuntimePlugin", chunk => {
|
||||||
|
|
|
@ -326,25 +326,26 @@ class RuntimeTemplate {
|
||||||
request,
|
request,
|
||||||
weak
|
weak
|
||||||
});
|
});
|
||||||
const exportsType = module.buildMeta && module.buildMeta.exportsType;
|
const exportsType = module.getExportsType(strict);
|
||||||
if (exportsType === "namespace") {
|
switch (exportsType) {
|
||||||
const rawModule = this.moduleRaw({
|
case "namespace":
|
||||||
module,
|
return this.moduleRaw({
|
||||||
chunkGraph,
|
module,
|
||||||
request,
|
chunkGraph,
|
||||||
weak,
|
request,
|
||||||
runtimeRequirements
|
weak,
|
||||||
});
|
runtimeRequirements
|
||||||
return rawModule;
|
});
|
||||||
} else if (strict) {
|
case "default-with-named":
|
||||||
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
||||||
return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 1)`;
|
return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 3)`;
|
||||||
} else if (exportsType === "default") {
|
case "default-only":
|
||||||
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
case "dynamic-default":
|
||||||
return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 3)`;
|
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
||||||
} else {
|
return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 1)`;
|
||||||
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
case "dynamic":
|
||||||
return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 7)`;
|
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
||||||
|
return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 7)`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,54 +428,46 @@ class RuntimeTemplate {
|
||||||
request,
|
request,
|
||||||
weak
|
weak
|
||||||
});
|
});
|
||||||
const exportsType = module.buildMeta && module.buildMeta.exportsType;
|
const exportsType = module.getExportsType(strict);
|
||||||
if (exportsType === "namespace") {
|
let fakeType = 0;
|
||||||
if (header) {
|
switch (exportsType) {
|
||||||
const rawModule = this.moduleRaw({
|
case "namespace":
|
||||||
module,
|
if (header) {
|
||||||
chunkGraph,
|
const rawModule = this.moduleRaw({
|
||||||
request,
|
module,
|
||||||
weak,
|
chunkGraph,
|
||||||
runtimeRequirements
|
request,
|
||||||
});
|
weak,
|
||||||
getModuleFunction = this.basicFunction(
|
runtimeRequirements
|
||||||
"",
|
});
|
||||||
`${header}return ${rawModule};`
|
getModuleFunction = this.basicFunction(
|
||||||
);
|
"",
|
||||||
} else {
|
`${header}return ${rawModule};`
|
||||||
runtimeRequirements.add(RuntimeGlobals.require);
|
);
|
||||||
getModuleFunction = `__webpack_require__.bind(null, ${comment}${idExpr})`;
|
} else {
|
||||||
}
|
runtimeRequirements.add(RuntimeGlobals.require);
|
||||||
} else if (strict) {
|
getModuleFunction = `__webpack_require__.bind(__webpack_require__, ${comment}${idExpr})`;
|
||||||
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
}
|
||||||
if (header) {
|
break;
|
||||||
const returnExpression = `${RuntimeGlobals.createFakeNamespaceObject}(${moduleIdExpr}, 1)`;
|
case "dynamic":
|
||||||
getModuleFunction = header
|
fakeType |= 7;
|
||||||
? this.basicFunction("", `${header}return ${returnExpression};`)
|
/* fall through */
|
||||||
: this.returningFunction(returnExpression);
|
case "default-with-named":
|
||||||
} else {
|
fakeType |= 3;
|
||||||
getModuleFunction = `${RuntimeGlobals.createFakeNamespaceObject}.bind(__webpack_require__, ${comment}${idExpr}, 1)`;
|
/* fall through */
|
||||||
}
|
case "default-only":
|
||||||
} else if (exportsType === "default") {
|
case "dynamic-default":
|
||||||
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
fakeType |= 1;
|
||||||
if (header) {
|
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
||||||
const returnExpression = `${RuntimeGlobals.createFakeNamespaceObject}(${moduleIdExpr}, 3)`;
|
if (header) {
|
||||||
getModuleFunction = header
|
const returnExpression = `${RuntimeGlobals.createFakeNamespaceObject}(${moduleIdExpr}, ${fakeType})`;
|
||||||
? this.basicFunction("", `${header}return ${returnExpression};`)
|
getModuleFunction = header
|
||||||
: this.returningFunction(returnExpression);
|
? this.basicFunction("", `${header}return ${returnExpression};`)
|
||||||
} else {
|
: this.returningFunction(returnExpression);
|
||||||
getModuleFunction = `${RuntimeGlobals.createFakeNamespaceObject}.bind(__webpack_require__, ${comment}${idExpr}, 3)`;
|
} else {
|
||||||
}
|
getModuleFunction = `${RuntimeGlobals.createFakeNamespaceObject}.bind(__webpack_require__, ${comment}${idExpr}, ${fakeType})`;
|
||||||
} else {
|
}
|
||||||
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
break;
|
||||||
if (header) {
|
|
||||||
const returnExpression = `${RuntimeGlobals.createFakeNamespaceObject}(${moduleIdExpr}, 7)`;
|
|
||||||
getModuleFunction = header
|
|
||||||
? this.basicFunction("", `${header}return ${returnExpression};`)
|
|
||||||
: this.returningFunction(returnExpression);
|
|
||||||
} else {
|
|
||||||
getModuleFunction = `${RuntimeGlobals.createFakeNamespaceObject}.bind(__webpack_require__, ${comment}${idExpr}, 7)`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${promise || "Promise.resolve()"}.then(${getModuleFunction})`;
|
return `${promise || "Promise.resolve()"}.then(${getModuleFunction})`;
|
||||||
|
@ -552,6 +545,7 @@ class RuntimeTemplate {
|
||||||
* @param {boolean} options.asiSafe true, if location is safe for ASI, a bracket can be emitted
|
* @param {boolean} options.asiSafe true, if location is safe for ASI, a bracket can be emitted
|
||||||
* @param {boolean} options.isCall true, if expression will be called
|
* @param {boolean} options.isCall true, if expression will be called
|
||||||
* @param {boolean} options.callContext when false, call context will not be preserved
|
* @param {boolean} options.callContext when false, call context will not be preserved
|
||||||
|
* @param {boolean} options.defaultInterop when true and accessing the default exports, interop code will be generated
|
||||||
* @param {string} options.importVar the identifier name of the import variable
|
* @param {string} options.importVar the identifier name of the import variable
|
||||||
* @param {InitFragment[]} options.initFragments init fragments will be added here
|
* @param {InitFragment[]} options.initFragments init fragments will be added here
|
||||||
* @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
|
* @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
|
||||||
|
@ -566,6 +560,7 @@ class RuntimeTemplate {
|
||||||
asiSafe,
|
asiSafe,
|
||||||
isCall,
|
isCall,
|
||||||
callContext,
|
callContext,
|
||||||
|
defaultInterop,
|
||||||
importVar,
|
importVar,
|
||||||
initFragments,
|
initFragments,
|
||||||
runtimeRequirements
|
runtimeRequirements
|
||||||
|
@ -580,26 +575,43 @@ class RuntimeTemplate {
|
||||||
}
|
}
|
||||||
const exportsType = module.buildMeta && module.buildMeta.exportsType;
|
const exportsType = module.buildMeta && module.buildMeta.exportsType;
|
||||||
|
|
||||||
if (!exportsType) {
|
if (defaultInterop) {
|
||||||
if (exportName.length > 0 && exportName[0] === "default") {
|
if (!exportsType) {
|
||||||
if (!originModule.buildMeta.strictHarmonyModule) {
|
if (exportName.length > 0 && exportName[0] === "default") {
|
||||||
if (isCall) {
|
if (!originModule.buildMeta.strictHarmonyModule) {
|
||||||
return `${importVar}_default()${propertyAccess(exportName, 1)}`;
|
if (isCall) {
|
||||||
} else if (asiSafe) {
|
return `${importVar}_default()${propertyAccess(exportName, 1)}`;
|
||||||
return `(${importVar}_default()${propertyAccess(exportName, 1)})`;
|
} else if (asiSafe) {
|
||||||
|
return `(${importVar}_default()${propertyAccess(exportName, 1)})`;
|
||||||
|
} else {
|
||||||
|
return `${importVar}_default.a${propertyAccess(exportName, 1)}`;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return `${importVar}_default.a${propertyAccess(exportName, 1)}`;
|
return `${importVar}${propertyAccess(exportName, 1)}`;
|
||||||
|
}
|
||||||
|
} else if (originModule.buildMeta.strictHarmonyModule) {
|
||||||
|
if (exportName.length > 0) {
|
||||||
|
return (
|
||||||
|
"/* non-default import from non-esm module */undefined" +
|
||||||
|
propertyAccess(exportName, 1)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
||||||
|
initFragments.push(
|
||||||
|
new InitFragment(
|
||||||
|
`var ${importVar}_namespace_cache;\n`,
|
||||||
|
InitFragment.STAGE_CONSTANTS,
|
||||||
|
-1,
|
||||||
|
`${importVar}_namespace_cache`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return `/*#__PURE__*/ (${importVar}_namespace_cache || (${importVar}_namespace_cache = ${RuntimeGlobals.createFakeNamespaceObject}(${importVar})))`;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return `${importVar}${propertyAccess(exportName, 1)}`;
|
|
||||||
}
|
}
|
||||||
} else if (originModule.buildMeta.strictHarmonyModule) {
|
}
|
||||||
if (exportName.length > 0) {
|
|
||||||
return (
|
if (exportsType === "default") {
|
||||||
"/* non-default import from non-esm module */undefined" +
|
if (exportName.length === 0) {
|
||||||
propertyAccess(exportName, 1)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
||||||
initFragments.push(
|
initFragments.push(
|
||||||
new InitFragment(
|
new InitFragment(
|
||||||
|
@ -609,30 +621,20 @@ class RuntimeTemplate {
|
||||||
`${importVar}_namespace_cache`
|
`${importVar}_namespace_cache`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return `/*#__PURE__*/ (${importVar}_namespace_cache || (${importVar}_namespace_cache = ${RuntimeGlobals.createFakeNamespaceObject}(${importVar})))`;
|
const content = `${importVar}_namespace_cache || (${importVar}_namespace_cache = ${
|
||||||
|
RuntimeGlobals.createFakeNamespaceObject
|
||||||
|
}(${importVar}, ${
|
||||||
|
originModule.buildMeta.strictHarmonyModule ? 0 : 2
|
||||||
|
}))`;
|
||||||
|
if (asiSafe) {
|
||||||
|
return `/*#__PURE__*/ (${content})`;
|
||||||
|
} else {
|
||||||
|
return `/*#__PURE__*/ Object(${content})`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exportsType === "default") {
|
|
||||||
if (exportName.length === 0) {
|
|
||||||
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
|
||||||
initFragments.push(
|
|
||||||
new InitFragment(
|
|
||||||
`var ${importVar}_namespace_cache;\n`,
|
|
||||||
InitFragment.STAGE_CONSTANTS,
|
|
||||||
-1,
|
|
||||||
`${importVar}_namespace_cache`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return `/*#__PURE__*/ (${importVar}_namespace_cache || (${importVar}_namespace_cache = ${
|
|
||||||
RuntimeGlobals.createFakeNamespaceObject
|
|
||||||
}(${importVar}, ${
|
|
||||||
originModule.buildMeta.strictHarmonyModule ? 0 : 2
|
|
||||||
})))`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exportName.length > 0) {
|
if (exportName.length > 0) {
|
||||||
const exportsInfo = moduleGraph.getExportsInfo(module);
|
const exportsInfo = moduleGraph.getExportsInfo(module);
|
||||||
const used = exportsInfo.getUsedName(exportName);
|
const used = exportsInfo.getUsedName(exportName);
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||||
|
Author Tobias Koppers @sokra
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
class SelfModuleFactory {
|
||||||
|
constructor(moduleGraph) {
|
||||||
|
this.moduleGraph = moduleGraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
create(data, callback) {
|
||||||
|
const module = this.moduleGraph.getParentModule(data.dependencies[0]);
|
||||||
|
callback(null, {
|
||||||
|
module
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = SelfModuleFactory;
|
|
@ -27,6 +27,9 @@ const { compareIds } = require("./util/comparators");
|
||||||
const START_LOWERCASE_ALPHABET_CODE = "a".charCodeAt(0);
|
const START_LOWERCASE_ALPHABET_CODE = "a".charCodeAt(0);
|
||||||
const START_UPPERCASE_ALPHABET_CODE = "A".charCodeAt(0);
|
const START_UPPERCASE_ALPHABET_CODE = "A".charCodeAt(0);
|
||||||
const DELTA_A_TO_Z = "z".charCodeAt(0) - START_LOWERCASE_ALPHABET_CODE + 1;
|
const DELTA_A_TO_Z = "z".charCodeAt(0) - START_LOWERCASE_ALPHABET_CODE + 1;
|
||||||
|
const NUMBER_OF_IDENTIFIER_START_CHARS = DELTA_A_TO_Z * 2 + 2; // a-z A-Z _ $
|
||||||
|
const NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS =
|
||||||
|
NUMBER_OF_IDENTIFIER_START_CHARS + 10; // a-z A-Z _ $ 0-9
|
||||||
const FUNCTION_CONTENT_REGEX = /^function\s?\(\)\s?\{\r?\n?|\r?\n?\}$/g;
|
const FUNCTION_CONTENT_REGEX = /^function\s?\(\)\s?\{\r?\n?|\r?\n?\}$/g;
|
||||||
const INDENT_MULTILINE_REGEX = /^\t/gm;
|
const INDENT_MULTILINE_REGEX = /^\t/gm;
|
||||||
const LINE_SEPARATOR_REGEX = /\r?\n/g;
|
const LINE_SEPARATOR_REGEX = /\r?\n/g;
|
||||||
|
@ -124,30 +127,73 @@ class Template {
|
||||||
.replace(MATCH_PADDED_HYPHENS_REPLACE_REGEX, "");
|
.replace(MATCH_PADDED_HYPHENS_REPLACE_REGEX, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// map number to a single character a-z, A-Z or <_ + number> if number is too big
|
// map number to a single character a-z, A-Z or mulitple characters if number is too big
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param {number} n number to convert to ident
|
* @param {number} n number to convert to ident
|
||||||
* @returns {string} returns single character ident
|
* @returns {string} returns single character ident
|
||||||
*/
|
*/
|
||||||
static numberToIdentifier(n) {
|
static numberToIdentifier(n) {
|
||||||
|
if (n >= NUMBER_OF_IDENTIFIER_START_CHARS) {
|
||||||
|
// use multiple letters
|
||||||
|
return (
|
||||||
|
Template.numberToIdentifier(n % NUMBER_OF_IDENTIFIER_START_CHARS) +
|
||||||
|
Template.numberToIdentifierContinuation(
|
||||||
|
Math.floor(n / NUMBER_OF_IDENTIFIER_START_CHARS)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// lower case
|
// lower case
|
||||||
if (n < DELTA_A_TO_Z) {
|
if (n < DELTA_A_TO_Z) {
|
||||||
return String.fromCharCode(START_LOWERCASE_ALPHABET_CODE + n);
|
return String.fromCharCode(START_LOWERCASE_ALPHABET_CODE + n);
|
||||||
}
|
}
|
||||||
|
n -= DELTA_A_TO_Z;
|
||||||
|
|
||||||
// upper case
|
// upper case
|
||||||
if (n < DELTA_A_TO_Z * 2) {
|
if (n < DELTA_A_TO_Z) {
|
||||||
return String.fromCharCode(
|
return String.fromCharCode(START_UPPERCASE_ALPHABET_CODE + n);
|
||||||
START_UPPERCASE_ALPHABET_CODE + n - DELTA_A_TO_Z
|
}
|
||||||
|
|
||||||
|
if (n === DELTA_A_TO_Z) return "_";
|
||||||
|
return "$";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} n number to convert to ident
|
||||||
|
* @returns {string} returns single character ident
|
||||||
|
*/
|
||||||
|
static numberToIdentifierContinuation(n) {
|
||||||
|
if (n >= NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS) {
|
||||||
|
// use multiple letters
|
||||||
|
return (
|
||||||
|
Template.numberToIdentifierContinuation(
|
||||||
|
n % NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS
|
||||||
|
) +
|
||||||
|
Template.numberToIdentifierContinuation(
|
||||||
|
Math.floor(n / NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// use multiple letters
|
// lower case
|
||||||
return (
|
if (n < DELTA_A_TO_Z) {
|
||||||
Template.numberToIdentifier(n % (2 * DELTA_A_TO_Z)) +
|
return String.fromCharCode(START_LOWERCASE_ALPHABET_CODE + n);
|
||||||
Template.numberToIdentifier(Math.floor(n / (2 * DELTA_A_TO_Z)))
|
}
|
||||||
);
|
n -= DELTA_A_TO_Z;
|
||||||
|
|
||||||
|
// upper case
|
||||||
|
if (n < DELTA_A_TO_Z) {
|
||||||
|
return String.fromCharCode(START_UPPERCASE_ALPHABET_CODE + n);
|
||||||
|
}
|
||||||
|
n -= DELTA_A_TO_Z;
|
||||||
|
|
||||||
|
// numbers
|
||||||
|
if (n < 10) {
|
||||||
|
return `${n}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n === 10) return "_";
|
||||||
|
return "$";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -358,3 +404,5 @@ class Template {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Template;
|
module.exports = Template;
|
||||||
|
module.exports.NUMBER_OF_IDENTIFIER_START_CHARS = NUMBER_OF_IDENTIFIER_START_CHARS;
|
||||||
|
module.exports.NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS = NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS;
|
||||||
|
|
|
@ -18,7 +18,6 @@ const RecordIdsPlugin = require("./RecordIdsPlugin");
|
||||||
const RuntimePlugin = require("./RuntimePlugin");
|
const RuntimePlugin = require("./RuntimePlugin");
|
||||||
|
|
||||||
const APIPlugin = require("./APIPlugin");
|
const APIPlugin = require("./APIPlugin");
|
||||||
const CommonJsStuffPlugin = require("./CommonJsStuffPlugin");
|
|
||||||
const CompatibilityPlugin = require("./CompatibilityPlugin");
|
const CompatibilityPlugin = require("./CompatibilityPlugin");
|
||||||
const ConstPlugin = require("./ConstPlugin");
|
const ConstPlugin = require("./ConstPlugin");
|
||||||
const ExportsInfoApiPlugin = require("./ExportsInfoApiPlugin");
|
const ExportsInfoApiPlugin = require("./ExportsInfoApiPlugin");
|
||||||
|
@ -341,7 +340,6 @@ class WebpackOptionsApply extends OptionsApply {
|
||||||
const NodeStuffPlugin = require("./NodeStuffPlugin");
|
const NodeStuffPlugin = require("./NodeStuffPlugin");
|
||||||
new NodeStuffPlugin(options.node).apply(compiler);
|
new NodeStuffPlugin(options.node).apply(compiler);
|
||||||
}
|
}
|
||||||
new CommonJsStuffPlugin().apply(compiler);
|
|
||||||
new APIPlugin().apply(compiler);
|
new APIPlugin().apply(compiler);
|
||||||
new ExportsInfoApiPlugin().apply(compiler);
|
new ExportsInfoApiPlugin().apply(compiler);
|
||||||
new ConstPlugin().apply(compiler);
|
new ConstPlugin().apply(compiler);
|
||||||
|
|
|
@ -12,6 +12,7 @@ const AMDRequireContextDependency = require("./AMDRequireContextDependency");
|
||||||
const AMDRequireItemDependency = require("./AMDRequireItemDependency");
|
const AMDRequireItemDependency = require("./AMDRequireItemDependency");
|
||||||
const ConstDependency = require("./ConstDependency");
|
const ConstDependency = require("./ConstDependency");
|
||||||
const ContextDependencyHelpers = require("./ContextDependencyHelpers");
|
const ContextDependencyHelpers = require("./ContextDependencyHelpers");
|
||||||
|
const DynamicExports = require("./DynamicExports");
|
||||||
const LocalModuleDependency = require("./LocalModuleDependency");
|
const LocalModuleDependency = require("./LocalModuleDependency");
|
||||||
const { addLocalModule, getLocalModule } = require("./LocalModulesHelpers");
|
const { addLocalModule, getLocalModule } = require("./LocalModulesHelpers");
|
||||||
|
|
||||||
|
@ -217,6 +218,7 @@ class AMDDefineDependencyParserPlugin {
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
DynamicExports.bailout(parser.state);
|
||||||
let fnParams = null;
|
let fnParams = null;
|
||||||
let fnParamsOffset = 0;
|
let fnParamsOffset = 0;
|
||||||
if (fn) {
|
if (fn) {
|
||||||
|
|
|
@ -0,0 +1,182 @@
|
||||||
|
/*
|
||||||
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||||
|
Author Tobias Koppers @sokra
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const InitFragment = require("../InitFragment");
|
||||||
|
const { UsageState } = require("../ModuleGraph");
|
||||||
|
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||||
|
const makeSerializable = require("../util/makeSerializable");
|
||||||
|
const propertyAccess = require("../util/propertyAccess");
|
||||||
|
const NullDependency = require("./NullDependency");
|
||||||
|
|
||||||
|
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
|
||||||
|
/** @typedef {import("../Dependency")} Dependency */
|
||||||
|
/** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
|
||||||
|
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
|
||||||
|
/** @typedef {import("../ModuleGraph")} ModuleGraph */
|
||||||
|
|
||||||
|
class CommonJsExportsDependency extends NullDependency {
|
||||||
|
constructor(range, base, names) {
|
||||||
|
super();
|
||||||
|
this.range = range;
|
||||||
|
this.base = base;
|
||||||
|
this.names = names;
|
||||||
|
}
|
||||||
|
|
||||||
|
get type() {
|
||||||
|
return "cjs exports";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the exported names
|
||||||
|
* @param {ModuleGraph} moduleGraph module graph
|
||||||
|
* @returns {ExportsSpec | undefined} export names
|
||||||
|
*/
|
||||||
|
getExports(moduleGraph) {
|
||||||
|
return {
|
||||||
|
exports: [this.names[0]],
|
||||||
|
dependencies: undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
serialize(context) {
|
||||||
|
const { write } = context;
|
||||||
|
write(this.range);
|
||||||
|
write(this.base);
|
||||||
|
write(this.names);
|
||||||
|
super.serialize(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
deserialize(context) {
|
||||||
|
const { read } = context;
|
||||||
|
this.range = read();
|
||||||
|
this.base = read();
|
||||||
|
this.names = read();
|
||||||
|
super.deserialize(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
makeSerializable(
|
||||||
|
CommonJsExportsDependency,
|
||||||
|
"webpack/lib/dependencies/CommonJsExportsDependency"
|
||||||
|
);
|
||||||
|
|
||||||
|
CommonJsExportsDependency.Template = class CommonJsExportsDependencyTemplate extends NullDependency.Template {
|
||||||
|
/**
|
||||||
|
* @param {Dependency} dependency the dependency for which the template should be applied
|
||||||
|
* @param {ReplaceSource} source the current replace source which can be modified
|
||||||
|
* @param {DependencyTemplateContext} templateContext the context object
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
apply(
|
||||||
|
dependency,
|
||||||
|
source,
|
||||||
|
{ module, moduleGraph, initFragments, runtimeRequirements }
|
||||||
|
) {
|
||||||
|
const dep = /** @type {CommonJsExportsDependency} */ (dependency);
|
||||||
|
let used;
|
||||||
|
if (module.buildMeta.exportsType === "default") {
|
||||||
|
const defaultInfo = moduleGraph.getExportInfo(module, "default");
|
||||||
|
if (defaultInfo.used === UsageState.Used) {
|
||||||
|
used = dep.names;
|
||||||
|
} else {
|
||||||
|
used = defaultInfo.exportsInfo.getUsedName(dep.names);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
used = moduleGraph.getExportsInfo(module).getUsedName(dep.names);
|
||||||
|
}
|
||||||
|
|
||||||
|
let base = undefined;
|
||||||
|
let type;
|
||||||
|
switch (dep.base) {
|
||||||
|
case "exports":
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.exports);
|
||||||
|
base = module.exportsArgument;
|
||||||
|
type = "expression";
|
||||||
|
break;
|
||||||
|
case "module.exports":
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.module);
|
||||||
|
base = `${module.moduleArgument}.exports`;
|
||||||
|
type = "expression";
|
||||||
|
break;
|
||||||
|
case "this":
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.thisAsExports);
|
||||||
|
base = "this";
|
||||||
|
type = "expression";
|
||||||
|
break;
|
||||||
|
case "Object.defineProperty(exports)":
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.exports);
|
||||||
|
base = module.exportsArgument;
|
||||||
|
type = "Object.defineProperty";
|
||||||
|
break;
|
||||||
|
case "Object.defineProperty(module.exports)":
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.module);
|
||||||
|
base = `${module.moduleArgument}.exports`;
|
||||||
|
type = "Object.defineProperty";
|
||||||
|
break;
|
||||||
|
case "Object.defineProperty(this)":
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.thisAsExports);
|
||||||
|
base = "this";
|
||||||
|
type = "Object.defineProperty";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported base ${dep.base}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "expression":
|
||||||
|
if (!used) {
|
||||||
|
initFragments.push(
|
||||||
|
new InitFragment(
|
||||||
|
"var __webpack_unused_export__;\n",
|
||||||
|
InitFragment.STAGE_CONSTANTS,
|
||||||
|
0,
|
||||||
|
"__webpack_unused_export__"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
source.replace(
|
||||||
|
dep.range[0],
|
||||||
|
dep.range[1] - 1,
|
||||||
|
"__webpack_unused_export__"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
source.replace(
|
||||||
|
dep.range[0],
|
||||||
|
dep.range[1] - 1,
|
||||||
|
`${base}${propertyAccess(used)}`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
case "Object.defineProperty":
|
||||||
|
if (!used) {
|
||||||
|
initFragments.push(
|
||||||
|
new InitFragment(
|
||||||
|
"var __webpack_unused_export__;\n",
|
||||||
|
InitFragment.STAGE_CONSTANTS,
|
||||||
|
0,
|
||||||
|
"__webpack_unused_export__"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
source.replace(
|
||||||
|
dep.range[0],
|
||||||
|
dep.range[1] - 1,
|
||||||
|
"__webpack_unused_export__ = ("
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
source.replace(
|
||||||
|
dep.range[0],
|
||||||
|
dep.range[1] - 1,
|
||||||
|
`Object.defineProperty(${base}${propertyAccess(
|
||||||
|
used.slice(0, -1)
|
||||||
|
)}, ${JSON.stringify(used[used.length - 1])}, `
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = CommonJsExportsDependency;
|
|
@ -0,0 +1,231 @@
|
||||||
|
/*
|
||||||
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||||
|
Author Tobias Koppers @sokra
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||||
|
const { evaluateToString } = require("../javascript/JavascriptParserHelpers");
|
||||||
|
const CommonJsExportsDependency = require("./CommonJsExportsDependency");
|
||||||
|
const CommonJsSelfReferenceDependency = require("./CommonJsSelfReferenceDependency");
|
||||||
|
const DynamicExports = require("./DynamicExports");
|
||||||
|
const HarmonyExports = require("./HarmonyExports");
|
||||||
|
const ModuleDecoratorDependency = require("./ModuleDecoratorDependency");
|
||||||
|
|
||||||
|
/** @typedef {import("../NormalModule")} NormalModule */
|
||||||
|
/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
|
||||||
|
|
||||||
|
/** @type {WeakMap<NormalModule, boolean>} */
|
||||||
|
const moduleExportsState = new WeakMap();
|
||||||
|
|
||||||
|
const getValueOfPropertyDescription = expr => {
|
||||||
|
if (expr.type !== "ObjectExpression") return;
|
||||||
|
for (const property of expr.properties) {
|
||||||
|
if (property.computed) continue;
|
||||||
|
const key = property.key;
|
||||||
|
if (key.type !== "Identifier" || key.name !== "value") continue;
|
||||||
|
return property.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const isTruthyLiteral = expr => {
|
||||||
|
switch (expr.type) {
|
||||||
|
case "Literal":
|
||||||
|
return !!expr.value;
|
||||||
|
case "UnaryExpression":
|
||||||
|
if (expr.operator === "!") return isFalsyLiteral(expr.argument);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isFalsyLiteral = expr => {
|
||||||
|
switch (expr.type) {
|
||||||
|
case "Literal":
|
||||||
|
return !expr.value;
|
||||||
|
case "UnaryExpression":
|
||||||
|
if (expr.operator === "!") return isTruthyLiteral(expr.argument);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CommonJsExportsParserPlugin {
|
||||||
|
static bailout(module) {
|
||||||
|
const value = moduleExportsState.get(module);
|
||||||
|
moduleExportsState.set(module, false);
|
||||||
|
if (value === true) {
|
||||||
|
module.buildMeta.exportsType = undefined;
|
||||||
|
module.buildMeta.defaultObject = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {JavascriptParser} parser the parser
|
||||||
|
*/
|
||||||
|
apply(parser) {
|
||||||
|
const enableStructuredExports = () => {
|
||||||
|
DynamicExports.enable(parser.state);
|
||||||
|
};
|
||||||
|
const checkNamespace = (members, valueExpr) => {
|
||||||
|
if (!DynamicExports.isEnabled(parser.state)) return;
|
||||||
|
if (members.length > 0 && members[0] === "__esModule") {
|
||||||
|
if (isTruthyLiteral(valueExpr)) {
|
||||||
|
DynamicExports.setFlagged(parser.state);
|
||||||
|
} else {
|
||||||
|
DynamicExports.bailout(parser.state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const bailout = () => {
|
||||||
|
DynamicExports.bailout(parser.state);
|
||||||
|
};
|
||||||
|
|
||||||
|
// metadata //
|
||||||
|
parser.hooks.evaluateTypeof
|
||||||
|
.for("module")
|
||||||
|
.tap("CommonJsExportsParserPlugin", evaluateToString("object"));
|
||||||
|
parser.hooks.evaluateTypeof
|
||||||
|
.for("exports")
|
||||||
|
.tap("CommonJsPlugin", evaluateToString("object"));
|
||||||
|
|
||||||
|
// exporting //
|
||||||
|
parser.hooks.assignMemberChain
|
||||||
|
.for("exports")
|
||||||
|
.tap("CommonJsExportsParserPlugin", (expr, members) => {
|
||||||
|
if (HarmonyExports.isEnabled(parser.state)) return;
|
||||||
|
enableStructuredExports();
|
||||||
|
checkNamespace(members, expr.right);
|
||||||
|
const dep = new CommonJsExportsDependency(
|
||||||
|
expr.left.range,
|
||||||
|
"exports",
|
||||||
|
members
|
||||||
|
);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
parser.hooks.assignMemberChain
|
||||||
|
.for("this")
|
||||||
|
.tap("CommonJsExportsParserPlugin", (expr, members) => {
|
||||||
|
if (HarmonyExports.isEnabled(parser.state)) return;
|
||||||
|
if (!parser.scope.topLevelScope) return;
|
||||||
|
enableStructuredExports();
|
||||||
|
checkNamespace(members, expr.right);
|
||||||
|
const dep = new CommonJsExportsDependency(
|
||||||
|
expr.left.range,
|
||||||
|
"this",
|
||||||
|
members
|
||||||
|
);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
parser.hooks.assignMemberChain
|
||||||
|
.for("module")
|
||||||
|
.tap("CommonJsExportsParserPlugin", (expr, members) => {
|
||||||
|
if (HarmonyExports.isEnabled(parser.state)) return;
|
||||||
|
if (members[0] !== "exports" || members.length <= 1) return;
|
||||||
|
enableStructuredExports();
|
||||||
|
checkNamespace(members, expr.right);
|
||||||
|
const dep = new CommonJsExportsDependency(
|
||||||
|
expr.left.range,
|
||||||
|
"module.exports",
|
||||||
|
members.slice(1)
|
||||||
|
);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
parser.hooks.call
|
||||||
|
.for("Object.defineProperty")
|
||||||
|
.tap("CommonJsExportsParserPlugin", expression => {
|
||||||
|
const expr = /** @type {import("estree").CallExpression} */ (expression);
|
||||||
|
if (expr.arguments.length !== 3) return;
|
||||||
|
if (expr.arguments[0].type === "SpreadElement") return;
|
||||||
|
if (expr.arguments[1].type === "SpreadElement") return;
|
||||||
|
if (expr.arguments[2].type === "SpreadElement") return;
|
||||||
|
const exportsArg = parser.evaluateExpression(expr.arguments[0]);
|
||||||
|
if (!exportsArg || !exportsArg.isIdentifier()) return;
|
||||||
|
if (
|
||||||
|
exportsArg.identifier !== "exports" &&
|
||||||
|
exportsArg.identifier !== "module.exports" &&
|
||||||
|
exportsArg.identifier !== "this"
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const propertyArg = parser.evaluateExpression(expr.arguments[1]);
|
||||||
|
if (!propertyArg) return;
|
||||||
|
const property = propertyArg.asString();
|
||||||
|
if (typeof property !== "string") return;
|
||||||
|
enableStructuredExports();
|
||||||
|
const descArg = expr.arguments[2];
|
||||||
|
checkNamespace([property], getValueOfPropertyDescription(descArg));
|
||||||
|
const dep = new CommonJsExportsDependency(
|
||||||
|
[expr.callee.range[0], expr.arguments[2].range[0]],
|
||||||
|
`Object.defineProperty(${exportsArg.identifier})`,
|
||||||
|
[property]
|
||||||
|
);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addDependency(dep);
|
||||||
|
|
||||||
|
parser.walkExpression(expr.arguments[2]);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Self reference //
|
||||||
|
parser.hooks.expression
|
||||||
|
.for("exports")
|
||||||
|
.tap("CommonJsExportsParserPlugin", expr => {
|
||||||
|
if (HarmonyExports.isEnabled(parser.state)) return;
|
||||||
|
bailout();
|
||||||
|
const dep = new CommonJsSelfReferenceDependency(
|
||||||
|
expr.range,
|
||||||
|
"exports",
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
parser.hooks.expression
|
||||||
|
.for("module.exports")
|
||||||
|
.tap("CommonJsExportsParserPlugin", expr => {
|
||||||
|
if (HarmonyExports.isEnabled(parser.state)) return;
|
||||||
|
bailout();
|
||||||
|
const dep = new CommonJsSelfReferenceDependency(
|
||||||
|
expr.range,
|
||||||
|
"module.exports",
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
parser.hooks.expression
|
||||||
|
.for("this")
|
||||||
|
.tap("CommonJsExportsParserPlugin", expr => {
|
||||||
|
if (HarmonyExports.isEnabled(parser.state)) return;
|
||||||
|
if (!parser.scope.topLevelScope) return;
|
||||||
|
bailout();
|
||||||
|
const dep = new CommonJsSelfReferenceDependency(expr.range, "this", []);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Bailouts //
|
||||||
|
parser.hooks.expression.for("module").tap("CommonJsPlugin", expr => {
|
||||||
|
bailout();
|
||||||
|
const isHarmony = HarmonyExports.isEnabled(parser.state);
|
||||||
|
const dep = new ModuleDecoratorDependency(
|
||||||
|
isHarmony
|
||||||
|
? RuntimeGlobals.harmonyModuleDecorator
|
||||||
|
: RuntimeGlobals.nodeModuleDecorator
|
||||||
|
);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
module.exports = CommonJsExportsParserPlugin;
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||||
|
Author Tobias Koppers @sokra
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const makeSerializable = require("../util/makeSerializable");
|
||||||
|
const ModuleDependency = require("./ModuleDependency");
|
||||||
|
|
||||||
|
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
|
||||||
|
/** @typedef {import("../Dependency")} Dependency */
|
||||||
|
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
|
||||||
|
/** @typedef {import("../ModuleGraph")} ModuleGraph */
|
||||||
|
|
||||||
|
class CommonJsFullRequireDependency extends ModuleDependency {
|
||||||
|
/**
|
||||||
|
* @param {string} request the request string
|
||||||
|
* @param {[number, number]} range location in source code
|
||||||
|
* @param {string[]} names accessed properties on module
|
||||||
|
*/
|
||||||
|
constructor(request, range, names) {
|
||||||
|
super(request);
|
||||||
|
this.range = range;
|
||||||
|
this.names = names;
|
||||||
|
this.call = false;
|
||||||
|
this.asiSafe = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of exports referenced by this dependency
|
||||||
|
* @param {ModuleGraph} moduleGraph module graph
|
||||||
|
* @returns {string[][]} referenced exports
|
||||||
|
*/
|
||||||
|
getReferencedExports(moduleGraph) {
|
||||||
|
if (this.call) {
|
||||||
|
const importedModule = moduleGraph.getModule(this);
|
||||||
|
if (
|
||||||
|
!importedModule ||
|
||||||
|
importedModule.getExportsType(false) !== "namespace"
|
||||||
|
) {
|
||||||
|
return [this.names.slice(0, -1)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [this.names];
|
||||||
|
}
|
||||||
|
|
||||||
|
serialize(context) {
|
||||||
|
const { write } = context;
|
||||||
|
write(this.names);
|
||||||
|
write(this.call);
|
||||||
|
write(this.asiSafe);
|
||||||
|
super.serialize(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
deserialize(context) {
|
||||||
|
const { read } = context;
|
||||||
|
this.names = read();
|
||||||
|
this.call = read();
|
||||||
|
this.asiSafe = read();
|
||||||
|
super.deserialize(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
get type() {
|
||||||
|
return "cjs full require";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonJsFullRequireDependency.Template = class CommonJsFullRequireDependencyTemplate extends ModuleDependency.Template {
|
||||||
|
/**
|
||||||
|
* @param {Dependency} dependency the dependency for which the template should be applied
|
||||||
|
* @param {ReplaceSource} source the current replace source which can be modified
|
||||||
|
* @param {DependencyTemplateContext} templateContext the context object
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
apply(
|
||||||
|
dependency,
|
||||||
|
source,
|
||||||
|
{
|
||||||
|
module,
|
||||||
|
runtimeTemplate,
|
||||||
|
moduleGraph,
|
||||||
|
chunkGraph,
|
||||||
|
runtimeRequirements,
|
||||||
|
initFragments
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
const dep = /** @type {CommonJsFullRequireDependency} */ (dependency);
|
||||||
|
if (!dep.range) return;
|
||||||
|
const importedModule = moduleGraph.getModule(dep);
|
||||||
|
const exports = runtimeTemplate.moduleExports({
|
||||||
|
module: importedModule,
|
||||||
|
chunkGraph,
|
||||||
|
request: dep.request,
|
||||||
|
weak: dep.weak,
|
||||||
|
runtimeRequirements
|
||||||
|
});
|
||||||
|
const exportExpr = runtimeTemplate.exportFromImport({
|
||||||
|
moduleGraph,
|
||||||
|
module: importedModule,
|
||||||
|
request: dep.request,
|
||||||
|
exportName: dep.names,
|
||||||
|
originModule: module,
|
||||||
|
asiSafe: dep.asiSafe,
|
||||||
|
isCall: dep.call,
|
||||||
|
callContext: undefined,
|
||||||
|
defaultInterop: false,
|
||||||
|
importVar: exports,
|
||||||
|
initFragments,
|
||||||
|
runtimeRequirements
|
||||||
|
});
|
||||||
|
source.replace(dep.range[0], dep.range[1] - 1, exportExpr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
makeSerializable(
|
||||||
|
CommonJsFullRequireDependency,
|
||||||
|
"webpack/lib/dependencies/CommonJsFullRequireDependency"
|
||||||
|
);
|
||||||
|
|
||||||
|
module.exports = CommonJsFullRequireDependency;
|
|
@ -0,0 +1,340 @@
|
||||||
|
/*
|
||||||
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||||
|
Author Tobias Koppers @sokra
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||||
|
const {
|
||||||
|
evaluateToIdentifier,
|
||||||
|
evaluateToString,
|
||||||
|
expressionIsUnsupported,
|
||||||
|
toConstantDependency
|
||||||
|
} = require("../javascript/JavascriptParserHelpers");
|
||||||
|
const CommonJsFullRequireDependency = require("./CommonJsFullRequireDependency");
|
||||||
|
const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
|
||||||
|
const CommonJsRequireDependency = require("./CommonJsRequireDependency");
|
||||||
|
const ConstDependency = require("./ConstDependency");
|
||||||
|
const ContextDependencyHelpers = require("./ContextDependencyHelpers");
|
||||||
|
const LocalModuleDependency = require("./LocalModuleDependency");
|
||||||
|
const { getLocalModule } = require("./LocalModulesHelpers");
|
||||||
|
const RequireHeaderDependency = require("./RequireHeaderDependency");
|
||||||
|
const RequireResolveContextDependency = require("./RequireResolveContextDependency");
|
||||||
|
const RequireResolveDependency = require("./RequireResolveDependency");
|
||||||
|
const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency");
|
||||||
|
|
||||||
|
class CommonJsImportsParserPlugin {
|
||||||
|
constructor(options) {
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(parser) {
|
||||||
|
const options = this.options;
|
||||||
|
|
||||||
|
// metadata //
|
||||||
|
const tapRequireExpression = (expression, getMembers) => {
|
||||||
|
parser.hooks.typeof
|
||||||
|
.for(expression)
|
||||||
|
.tap(
|
||||||
|
"CommonJsPlugin",
|
||||||
|
toConstantDependency(parser, JSON.stringify("function"))
|
||||||
|
);
|
||||||
|
parser.hooks.evaluateTypeof
|
||||||
|
.for(expression)
|
||||||
|
.tap("CommonJsPlugin", evaluateToString("function"));
|
||||||
|
parser.hooks.evaluateIdentifier
|
||||||
|
.for(expression)
|
||||||
|
.tap(
|
||||||
|
"CommonJsPlugin",
|
||||||
|
evaluateToIdentifier(expression, "require", getMembers, true)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
tapRequireExpression("require", () => []);
|
||||||
|
tapRequireExpression("require.resolve", () => ["resolve"]);
|
||||||
|
tapRequireExpression("require.resolveWeak", () => ["resolveWeak"]);
|
||||||
|
|
||||||
|
// Weird stuff //
|
||||||
|
parser.hooks.assign.for("require").tap("CommonJsPlugin", expr => {
|
||||||
|
// to not leak to global "require", we need to define a local require here.
|
||||||
|
const dep = new ConstDependency("var require;", 0);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addPresentationalDependency(dep);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Unsupported //
|
||||||
|
parser.hooks.expression
|
||||||
|
.for("require.main.require")
|
||||||
|
.tap(
|
||||||
|
"CommonJsPlugin",
|
||||||
|
expressionIsUnsupported(
|
||||||
|
parser,
|
||||||
|
"require.main.require is not supported by webpack."
|
||||||
|
)
|
||||||
|
);
|
||||||
|
parser.hooks.call
|
||||||
|
.for("require.main.require")
|
||||||
|
.tap(
|
||||||
|
"CommonJsPlugin",
|
||||||
|
expressionIsUnsupported(
|
||||||
|
parser,
|
||||||
|
"require.main.require is not supported by webpack."
|
||||||
|
)
|
||||||
|
);
|
||||||
|
parser.hooks.expression
|
||||||
|
.for("module.parent.require")
|
||||||
|
.tap(
|
||||||
|
"CommonJsPlugin",
|
||||||
|
expressionIsUnsupported(
|
||||||
|
parser,
|
||||||
|
"module.parent.require is not supported by webpack."
|
||||||
|
)
|
||||||
|
);
|
||||||
|
parser.hooks.call
|
||||||
|
.for("module.parent.require")
|
||||||
|
.tap(
|
||||||
|
"CommonJsPlugin",
|
||||||
|
expressionIsUnsupported(
|
||||||
|
parser,
|
||||||
|
"module.parent.require is not supported by webpack."
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// renaming //
|
||||||
|
parser.hooks.canRename.for("require").tap("CommonJsPlugin", () => true);
|
||||||
|
parser.hooks.rename.for("require").tap("CommonJsPlugin", expr => {
|
||||||
|
// To avoid "not defined" error, replace the value with undefined
|
||||||
|
const dep = new ConstDependency("undefined", expr.range);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addPresentationalDependency(dep);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// inspection //
|
||||||
|
parser.hooks.expression
|
||||||
|
.for("require.cache")
|
||||||
|
.tap(
|
||||||
|
"CommonJsImportsParserPlugin",
|
||||||
|
toConstantDependency(parser, RuntimeGlobals.moduleCache, [
|
||||||
|
RuntimeGlobals.moduleCache,
|
||||||
|
RuntimeGlobals.moduleId,
|
||||||
|
RuntimeGlobals.moduleLoaded
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
// require as expression //
|
||||||
|
parser.hooks.expression
|
||||||
|
.for("require")
|
||||||
|
.tap("CommonJsImportsParserPlugin", expr => {
|
||||||
|
const dep = new CommonJsRequireContextDependency(
|
||||||
|
{
|
||||||
|
request: options.unknownContextRequest,
|
||||||
|
recursive: options.unknownContextRecursive,
|
||||||
|
regExp: options.unknownContextRegExp,
|
||||||
|
mode: "sync"
|
||||||
|
},
|
||||||
|
expr.range
|
||||||
|
);
|
||||||
|
dep.critical =
|
||||||
|
options.unknownContextCritical &&
|
||||||
|
"require function is used in a way in which dependencies cannot be statically extracted";
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
dep.optional = !!parser.scope.inTry;
|
||||||
|
parser.state.current.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// require //
|
||||||
|
const processRequireItem = (expr, param) => {
|
||||||
|
if (param.isString()) {
|
||||||
|
const dep = new CommonJsRequireDependency(param.string, param.range);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
dep.optional = !!parser.scope.inTry;
|
||||||
|
parser.state.current.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const processRequireContext = (expr, param) => {
|
||||||
|
const dep = ContextDependencyHelpers.create(
|
||||||
|
CommonJsRequireContextDependency,
|
||||||
|
expr.range,
|
||||||
|
param,
|
||||||
|
expr,
|
||||||
|
options,
|
||||||
|
{},
|
||||||
|
parser
|
||||||
|
);
|
||||||
|
if (!dep) return;
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
dep.optional = !!parser.scope.inTry;
|
||||||
|
parser.state.current.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createRequireHandler = callNew => expr => {
|
||||||
|
if (expr.arguments.length !== 1) return;
|
||||||
|
let localModule;
|
||||||
|
const param = parser.evaluateExpression(expr.arguments[0]);
|
||||||
|
if (param.isConditional()) {
|
||||||
|
let isExpression = false;
|
||||||
|
for (const p of param.options) {
|
||||||
|
const result = processRequireItem(expr, p);
|
||||||
|
if (result === undefined) {
|
||||||
|
isExpression = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isExpression) {
|
||||||
|
const dep = new RequireHeaderDependency(expr.callee.range);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addPresentationalDependency(dep);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
param.isString() &&
|
||||||
|
(localModule = getLocalModule(parser.state, param.string))
|
||||||
|
) {
|
||||||
|
localModule.flagUsed();
|
||||||
|
const dep = new LocalModuleDependency(localModule, expr.range, callNew);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addPresentationalDependency(dep);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
const result = processRequireItem(expr, param);
|
||||||
|
if (result === undefined) {
|
||||||
|
processRequireContext(expr, param);
|
||||||
|
} else {
|
||||||
|
const dep = new RequireHeaderDependency(expr.callee.range);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addPresentationalDependency(dep);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
parser.hooks.call
|
||||||
|
.for("require")
|
||||||
|
.tap("CommonJsImportsParserPlugin", createRequireHandler(false));
|
||||||
|
parser.hooks.new
|
||||||
|
.for("require")
|
||||||
|
.tap("CommonJsImportsParserPlugin", createRequireHandler(true));
|
||||||
|
parser.hooks.call
|
||||||
|
.for("module.require")
|
||||||
|
.tap("CommonJsImportsParserPlugin", createRequireHandler(false));
|
||||||
|
parser.hooks.new
|
||||||
|
.for("module.require")
|
||||||
|
.tap("CommonJsImportsParserPlugin", createRequireHandler(true));
|
||||||
|
|
||||||
|
// require with property access //
|
||||||
|
const chainHandler = (expr, calleeMembers, callExpr, members) => {
|
||||||
|
if (callExpr.arguments.length !== 1) return;
|
||||||
|
const param = parser.evaluateExpression(callExpr.arguments[0]);
|
||||||
|
if (param.isString() && !getLocalModule(parser.state, param.string)) {
|
||||||
|
const dep = new CommonJsFullRequireDependency(
|
||||||
|
param.string,
|
||||||
|
expr.range,
|
||||||
|
members
|
||||||
|
);
|
||||||
|
dep.asiSafe = !parser.isAsiPosition(expr.range[0]);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const callChainHandler = (expr, calleeMembers, callExpr, members) => {
|
||||||
|
if (callExpr.arguments.length !== 1) return;
|
||||||
|
const param = parser.evaluateExpression(callExpr.arguments[0]);
|
||||||
|
if (param.isString() && !getLocalModule(parser.state, param.string)) {
|
||||||
|
const dep = new CommonJsFullRequireDependency(
|
||||||
|
param.string,
|
||||||
|
expr.callee.range,
|
||||||
|
members
|
||||||
|
);
|
||||||
|
dep.call = true;
|
||||||
|
dep.asiSafe = !parser.isAsiPosition(expr.range[0]);
|
||||||
|
dep.loc = expr.callee.loc;
|
||||||
|
parser.state.module.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
parser.hooks.memberChainOfCallMemberChain
|
||||||
|
.for("require")
|
||||||
|
.tap("CommonJsImportsParserPlugin", chainHandler);
|
||||||
|
parser.hooks.memberChainOfCallMemberChain
|
||||||
|
.for("module.require")
|
||||||
|
.tap("CommonJsImportsParserPlugin", chainHandler);
|
||||||
|
parser.hooks.callMemberChainOfCallMemberChain
|
||||||
|
.for("require")
|
||||||
|
.tap("CommonJsImportsParserPlugin", callChainHandler);
|
||||||
|
parser.hooks.callMemberChainOfCallMemberChain
|
||||||
|
.for("module.require")
|
||||||
|
.tap("CommonJsImportsParserPlugin", callChainHandler);
|
||||||
|
|
||||||
|
// require.resolve //
|
||||||
|
const processResolve = (expr, weak) => {
|
||||||
|
if (expr.arguments.length !== 1) return;
|
||||||
|
const param = parser.evaluateExpression(expr.arguments[0]);
|
||||||
|
if (param.isConditional()) {
|
||||||
|
for (const option of param.options) {
|
||||||
|
const result = processResolveItem(expr, option, weak);
|
||||||
|
if (result === undefined) {
|
||||||
|
processResolveContext(expr, option, weak);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const dep = new RequireResolveHeaderDependency(expr.callee.range);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addPresentationalDependency(dep);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
const result = processResolveItem(expr, param, weak);
|
||||||
|
if (result === undefined) {
|
||||||
|
processResolveContext(expr, param, weak);
|
||||||
|
}
|
||||||
|
const dep = new RequireResolveHeaderDependency(expr.callee.range);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addPresentationalDependency(dep);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const processResolveItem = (expr, param, weak) => {
|
||||||
|
if (param.isString()) {
|
||||||
|
const dep = new RequireResolveDependency(param.string, param.range);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
dep.optional = !!parser.scope.inTry;
|
||||||
|
dep.weak = weak;
|
||||||
|
parser.state.current.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const processResolveContext = (expr, param, weak) => {
|
||||||
|
const dep = ContextDependencyHelpers.create(
|
||||||
|
RequireResolveContextDependency,
|
||||||
|
param.range,
|
||||||
|
param,
|
||||||
|
expr,
|
||||||
|
options,
|
||||||
|
{
|
||||||
|
mode: weak ? "weak" : "sync"
|
||||||
|
},
|
||||||
|
parser
|
||||||
|
);
|
||||||
|
if (!dep) return;
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
dep.optional = !!parser.scope.inTry;
|
||||||
|
parser.state.current.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
parser.hooks.call
|
||||||
|
.for("require.resolve")
|
||||||
|
.tap("RequireResolveDependencyParserPlugin", expr => {
|
||||||
|
return processResolve(expr, false);
|
||||||
|
});
|
||||||
|
parser.hooks.call
|
||||||
|
.for("require.resolveWeak")
|
||||||
|
.tap("RequireResolveDependencyParserPlugin", expr => {
|
||||||
|
return processResolve(expr, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
module.exports = CommonJsImportsParserPlugin;
|
|
@ -5,22 +5,27 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||||
|
const RuntimeModule = require("../RuntimeModule");
|
||||||
|
const SelfModuleFactory = require("../SelfModuleFactory");
|
||||||
|
const Template = require("../Template");
|
||||||
|
const CommonJsExportsDependency = require("./CommonJsExportsDependency");
|
||||||
|
const CommonJsFullRequireDependency = require("./CommonJsFullRequireDependency");
|
||||||
const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
|
const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
|
||||||
const CommonJsRequireDependency = require("./CommonJsRequireDependency");
|
const CommonJsRequireDependency = require("./CommonJsRequireDependency");
|
||||||
const ConstDependency = require("./ConstDependency");
|
const CommonJsSelfReferenceDependency = require("./CommonJsSelfReferenceDependency");
|
||||||
|
const ModuleDecoratorDependency = require("./ModuleDecoratorDependency");
|
||||||
const RequireHeaderDependency = require("./RequireHeaderDependency");
|
const RequireHeaderDependency = require("./RequireHeaderDependency");
|
||||||
const RequireResolveContextDependency = require("./RequireResolveContextDependency");
|
const RequireResolveContextDependency = require("./RequireResolveContextDependency");
|
||||||
const RequireResolveDependency = require("./RequireResolveDependency");
|
const RequireResolveDependency = require("./RequireResolveDependency");
|
||||||
const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency");
|
const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency");
|
||||||
|
const RuntimeRequirementsDependency = require("./RuntimeRequirementsDependency");
|
||||||
|
|
||||||
const CommonJsRequireDependencyParserPlugin = require("./CommonJsRequireDependencyParserPlugin");
|
const CommonJsExportsParserPlugin = require("./CommonJsExportsParserPlugin");
|
||||||
const RequireResolveDependencyParserPlugin = require("./RequireResolveDependencyParserPlugin");
|
const CommonJsImportsParserPlugin = require("./CommonJsImportsParserPlugin");
|
||||||
|
|
||||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
evaluateToIdentifier,
|
evaluateToIdentifier,
|
||||||
evaluateToString,
|
|
||||||
toConstantDependency
|
toConstantDependency
|
||||||
} = require("../javascript/JavascriptParserHelpers");
|
} = require("../javascript/JavascriptParserHelpers");
|
||||||
|
|
||||||
|
@ -43,6 +48,15 @@ class CommonJsPlugin {
|
||||||
new CommonJsRequireDependency.Template()
|
new CommonJsRequireDependency.Template()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
compilation.dependencyFactories.set(
|
||||||
|
CommonJsFullRequireDependency,
|
||||||
|
normalModuleFactory
|
||||||
|
);
|
||||||
|
compilation.dependencyTemplates.set(
|
||||||
|
CommonJsFullRequireDependency,
|
||||||
|
new CommonJsFullRequireDependency.Template()
|
||||||
|
);
|
||||||
|
|
||||||
compilation.dependencyFactories.set(
|
compilation.dependencyFactories.set(
|
||||||
CommonJsRequireContextDependency,
|
CommonJsRequireContextDependency,
|
||||||
contextModuleFactory
|
contextModuleFactory
|
||||||
|
@ -80,72 +94,116 @@ class CommonJsPlugin {
|
||||||
new RequireHeaderDependency.Template()
|
new RequireHeaderDependency.Template()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
compilation.dependencyTemplates.set(
|
||||||
|
CommonJsExportsDependency,
|
||||||
|
new CommonJsExportsDependency.Template()
|
||||||
|
);
|
||||||
|
|
||||||
|
const selfFactory = new SelfModuleFactory(compilation.moduleGraph);
|
||||||
|
|
||||||
|
compilation.dependencyFactories.set(
|
||||||
|
CommonJsSelfReferenceDependency,
|
||||||
|
selfFactory
|
||||||
|
);
|
||||||
|
compilation.dependencyTemplates.set(
|
||||||
|
CommonJsSelfReferenceDependency,
|
||||||
|
new CommonJsSelfReferenceDependency.Template()
|
||||||
|
);
|
||||||
|
|
||||||
|
compilation.dependencyFactories.set(
|
||||||
|
ModuleDecoratorDependency,
|
||||||
|
selfFactory
|
||||||
|
);
|
||||||
|
compilation.dependencyTemplates.set(
|
||||||
|
ModuleDecoratorDependency,
|
||||||
|
new ModuleDecoratorDependency.Template()
|
||||||
|
);
|
||||||
|
|
||||||
|
compilation.hooks.runtimeRequirementInModule
|
||||||
|
.for(RuntimeGlobals.harmonyModuleDecorator)
|
||||||
|
.tap("CommonJsPlugin", (module, set) => {
|
||||||
|
set.add(RuntimeGlobals.module);
|
||||||
|
set.add(RuntimeGlobals.requireScope);
|
||||||
|
});
|
||||||
|
|
||||||
|
compilation.hooks.runtimeRequirementInModule
|
||||||
|
.for(RuntimeGlobals.nodeModuleDecorator)
|
||||||
|
.tap("CommonJsPlugin", (module, set) => {
|
||||||
|
set.add(RuntimeGlobals.module);
|
||||||
|
set.add(RuntimeGlobals.requireScope);
|
||||||
|
});
|
||||||
|
|
||||||
|
compilation.hooks.runtimeRequirementInTree
|
||||||
|
.for(RuntimeGlobals.harmonyModuleDecorator)
|
||||||
|
.tap("CommonJsPlugin", (chunk, set) => {
|
||||||
|
compilation.addRuntimeModule(
|
||||||
|
chunk,
|
||||||
|
new HarmonyModuleDecoratorRuntimeModule()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
compilation.hooks.runtimeRequirementInTree
|
||||||
|
.for(RuntimeGlobals.nodeModuleDecorator)
|
||||||
|
.tap("CommonJsPlugin", (chunk, set) => {
|
||||||
|
compilation.addRuntimeModule(
|
||||||
|
chunk,
|
||||||
|
new NodeModuleDecoratorRuntimeModule()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const handler = (parser, parserOptions) => {
|
const handler = (parser, parserOptions) => {
|
||||||
if (parserOptions.commonjs !== undefined && !parserOptions.commonjs)
|
if (parserOptions.commonjs !== undefined && !parserOptions.commonjs)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const tapRequireExpression = (expression, getMembers) => {
|
|
||||||
parser.hooks.typeof
|
|
||||||
.for(expression)
|
|
||||||
.tap(
|
|
||||||
"CommonJsPlugin",
|
|
||||||
toConstantDependency(parser, JSON.stringify("function"))
|
|
||||||
);
|
|
||||||
parser.hooks.evaluateTypeof
|
|
||||||
.for(expression)
|
|
||||||
.tap("CommonJsPlugin", evaluateToString("function"));
|
|
||||||
parser.hooks.evaluateIdentifier
|
|
||||||
.for(expression)
|
|
||||||
.tap(
|
|
||||||
"CommonJsPlugin",
|
|
||||||
evaluateToIdentifier(expression, "require", getMembers, true)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
tapRequireExpression("require", () => []);
|
|
||||||
tapRequireExpression("require.resolve", () => ["resolve"]);
|
|
||||||
tapRequireExpression("require.resolveWeak", () => ["resolveWeak"]);
|
|
||||||
|
|
||||||
parser.hooks.evaluateTypeof
|
|
||||||
.for("module")
|
|
||||||
.tap("CommonJsPlugin", evaluateToString("object"));
|
|
||||||
parser.hooks.expression.for("exports").tap("CommonJsPlugin", expr => {
|
|
||||||
const module = parser.state.module;
|
|
||||||
const isHarmony = module.buildMeta && module.buildMeta.exportsType;
|
|
||||||
if (!isHarmony) {
|
|
||||||
return toConstantDependency(parser, module.exportsArgument, [
|
|
||||||
RuntimeGlobals.exports
|
|
||||||
])(expr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
parser.hooks.assign.for("require").tap("CommonJsPlugin", expr => {
|
|
||||||
// to not leak to global "require", we need to define a local require here.
|
|
||||||
const dep = new ConstDependency("var require;", 0);
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
parser.state.module.addPresentationalDependency(dep);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
parser.hooks.canRename
|
|
||||||
.for("require")
|
|
||||||
.tap("CommonJsPlugin", () => true);
|
|
||||||
parser.hooks.rename.for("require").tap("CommonJsPlugin", expr => {
|
|
||||||
// To avoid "not defined" error, replace the value with undefined
|
|
||||||
const dep = new ConstDependency("undefined", expr.range);
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
parser.state.module.addPresentationalDependency(dep);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
parser.hooks.typeof
|
parser.hooks.typeof
|
||||||
.for("module")
|
.for("module")
|
||||||
.tap(
|
.tap(
|
||||||
"CommonJsPlugin",
|
"CommonJsPlugin",
|
||||||
toConstantDependency(parser, JSON.stringify("object"))
|
toConstantDependency(parser, JSON.stringify("object"))
|
||||||
);
|
);
|
||||||
parser.hooks.evaluateTypeof
|
|
||||||
.for("exports")
|
|
||||||
.tap("CommonJsPlugin", evaluateToString("object"));
|
|
||||||
|
|
||||||
new CommonJsRequireDependencyParserPlugin(options).apply(parser);
|
parser.hooks.expression
|
||||||
new RequireResolveDependencyParserPlugin(options).apply(parser);
|
.for("require.main")
|
||||||
|
.tap(
|
||||||
|
"CommonJsPlugin",
|
||||||
|
toConstantDependency(
|
||||||
|
parser,
|
||||||
|
`${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}]`,
|
||||||
|
[RuntimeGlobals.moduleCache, RuntimeGlobals.entryModuleId]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
parser.hooks.expression
|
||||||
|
.for("module.loaded")
|
||||||
|
.tap("CommonJsPlugin", expr => {
|
||||||
|
parser.state.module.buildMeta.moduleConcatenationBailout =
|
||||||
|
"module.loaded";
|
||||||
|
const dep = new RuntimeRequirementsDependency([
|
||||||
|
RuntimeGlobals.moduleLoaded
|
||||||
|
]);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addPresentationalDependency(dep);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
parser.hooks.expression
|
||||||
|
.for("module.id")
|
||||||
|
.tap("CommonJsPlugin", expr => {
|
||||||
|
parser.state.module.buildMeta.moduleConcatenationBailout =
|
||||||
|
"module.id";
|
||||||
|
const dep = new RuntimeRequirementsDependency([
|
||||||
|
RuntimeGlobals.moduleId
|
||||||
|
]);
|
||||||
|
dep.loc = expr.loc;
|
||||||
|
parser.state.module.addPresentationalDependency(dep);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
parser.hooks.evaluateIdentifier.for("module.hot").tap(
|
||||||
|
"CommonJsPlugin",
|
||||||
|
evaluateToIdentifier("module.hot", "module", () => ["hot"], false)
|
||||||
|
);
|
||||||
|
|
||||||
|
new CommonJsImportsParserPlugin(options).apply(parser);
|
||||||
|
new CommonJsExportsParserPlugin().apply(parser);
|
||||||
};
|
};
|
||||||
|
|
||||||
normalModuleFactory.hooks.parser
|
normalModuleFactory.hooks.parser
|
||||||
|
@ -158,4 +216,57 @@ class CommonJsPlugin {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class HarmonyModuleDecoratorRuntimeModule extends RuntimeModule {
|
||||||
|
constructor() {
|
||||||
|
super("harmony module decorator");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {string} runtime code
|
||||||
|
*/
|
||||||
|
generate() {
|
||||||
|
const { runtimeTemplate } = this.compilation;
|
||||||
|
return Template.asString([
|
||||||
|
`${
|
||||||
|
RuntimeGlobals.harmonyModuleDecorator
|
||||||
|
} = ${runtimeTemplate.basicFunction("module", [
|
||||||
|
"module = Object.create(module);",
|
||||||
|
"if (!module.children) module.children = [];",
|
||||||
|
"Object.defineProperty(module, 'exports', {",
|
||||||
|
Template.indent([
|
||||||
|
"enumerable: true,",
|
||||||
|
`set: ${runtimeTemplate.basicFunction("", [
|
||||||
|
"throw new Error('ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: ' + module.id);"
|
||||||
|
])}`
|
||||||
|
]),
|
||||||
|
"});",
|
||||||
|
"return module;"
|
||||||
|
])};`
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NodeModuleDecoratorRuntimeModule extends RuntimeModule {
|
||||||
|
constructor() {
|
||||||
|
super("node module decorator");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {string} runtime code
|
||||||
|
*/
|
||||||
|
generate() {
|
||||||
|
const { runtimeTemplate } = this.compilation;
|
||||||
|
return Template.asString([
|
||||||
|
`${
|
||||||
|
RuntimeGlobals.nodeModuleDecorator
|
||||||
|
} = ${runtimeTemplate.basicFunction("module", [
|
||||||
|
"module.paths = [];",
|
||||||
|
"if (!module.children) module.children = [];",
|
||||||
|
"return module;"
|
||||||
|
])};`
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = CommonJsPlugin;
|
module.exports = CommonJsPlugin;
|
||||||
|
|
|
@ -1,136 +0,0 @@
|
||||||
/*
|
|
||||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
|
||||||
Author Tobias Koppers @sokra
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
|
||||||
const {
|
|
||||||
toConstantDependency
|
|
||||||
} = require("../javascript/JavascriptParserHelpers");
|
|
||||||
const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
|
|
||||||
const CommonJsRequireDependency = require("./CommonJsRequireDependency");
|
|
||||||
const ContextDependencyHelpers = require("./ContextDependencyHelpers");
|
|
||||||
const LocalModuleDependency = require("./LocalModuleDependency");
|
|
||||||
const { getLocalModule } = require("./LocalModulesHelpers");
|
|
||||||
const RequireHeaderDependency = require("./RequireHeaderDependency");
|
|
||||||
|
|
||||||
class CommonJsRequireDependencyParserPlugin {
|
|
||||||
constructor(options) {
|
|
||||||
this.options = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
apply(parser) {
|
|
||||||
const options = this.options;
|
|
||||||
|
|
||||||
const processItem = (expr, param) => {
|
|
||||||
if (param.isString()) {
|
|
||||||
const dep = new CommonJsRequireDependency(param.string, param.range);
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
dep.optional = !!parser.scope.inTry;
|
|
||||||
parser.state.current.addDependency(dep);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const processContext = (expr, param) => {
|
|
||||||
const dep = ContextDependencyHelpers.create(
|
|
||||||
CommonJsRequireContextDependency,
|
|
||||||
expr.range,
|
|
||||||
param,
|
|
||||||
expr,
|
|
||||||
options,
|
|
||||||
{},
|
|
||||||
parser
|
|
||||||
);
|
|
||||||
if (!dep) return;
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
dep.optional = !!parser.scope.inTry;
|
|
||||||
parser.state.current.addDependency(dep);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.hooks.expression
|
|
||||||
.for("require.cache")
|
|
||||||
.tap(
|
|
||||||
"CommonJsRequireDependencyParserPlugin",
|
|
||||||
toConstantDependency(parser, RuntimeGlobals.moduleCache, [
|
|
||||||
RuntimeGlobals.moduleCache
|
|
||||||
])
|
|
||||||
);
|
|
||||||
parser.hooks.expression
|
|
||||||
.for("require")
|
|
||||||
.tap("CommonJsRequireDependencyParserPlugin", expr => {
|
|
||||||
const dep = new CommonJsRequireContextDependency(
|
|
||||||
{
|
|
||||||
request: options.unknownContextRequest,
|
|
||||||
recursive: options.unknownContextRecursive,
|
|
||||||
regExp: options.unknownContextRegExp,
|
|
||||||
mode: "sync"
|
|
||||||
},
|
|
||||||
expr.range
|
|
||||||
);
|
|
||||||
dep.critical =
|
|
||||||
options.unknownContextCritical &&
|
|
||||||
"require function is used in a way in which dependencies cannot be statically extracted";
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
dep.optional = !!parser.scope.inTry;
|
|
||||||
parser.state.current.addDependency(dep);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
const createHandler = callNew => expr => {
|
|
||||||
if (expr.arguments.length !== 1) return;
|
|
||||||
let localModule;
|
|
||||||
const param = parser.evaluateExpression(expr.arguments[0]);
|
|
||||||
if (param.isConditional()) {
|
|
||||||
let isExpression = false;
|
|
||||||
for (const p of param.options) {
|
|
||||||
const result = processItem(expr, p);
|
|
||||||
if (result === undefined) {
|
|
||||||
isExpression = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isExpression) {
|
|
||||||
const dep = new RequireHeaderDependency(expr.callee.range);
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
parser.state.module.addPresentationalDependency(dep);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
param.isString() &&
|
|
||||||
(localModule = getLocalModule(parser.state, param.string))
|
|
||||||
) {
|
|
||||||
localModule.flagUsed();
|
|
||||||
const dep = new LocalModuleDependency(localModule, expr.range, callNew);
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
parser.state.module.addPresentationalDependency(dep);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
const result = processItem(expr, param);
|
|
||||||
if (result === undefined) {
|
|
||||||
processContext(expr, param);
|
|
||||||
} else {
|
|
||||||
const dep = new RequireHeaderDependency(expr.callee.range);
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
parser.state.module.addPresentationalDependency(dep);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
parser.hooks.call
|
|
||||||
.for("require")
|
|
||||||
.tap("CommonJsRequireDependencyParserPlugin", createHandler(false));
|
|
||||||
parser.hooks.new
|
|
||||||
.for("require")
|
|
||||||
.tap("CommonJsRequireDependencyParserPlugin", createHandler(true));
|
|
||||||
parser.hooks.call
|
|
||||||
.for("module.require")
|
|
||||||
.tap("CommonJsRequireDependencyParserPlugin", createHandler(false));
|
|
||||||
parser.hooks.new
|
|
||||||
.for("module.require")
|
|
||||||
.tap("CommonJsRequireDependencyParserPlugin", createHandler(true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.exports = CommonJsRequireDependencyParserPlugin;
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||||
|
Author Tobias Koppers @sokra
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const { UsageState } = require("../ModuleGraph");
|
||||||
|
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||||
|
const makeSerializable = require("../util/makeSerializable");
|
||||||
|
const propertyAccess = require("../util/propertyAccess");
|
||||||
|
const NullDependency = require("./NullDependency");
|
||||||
|
|
||||||
|
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
|
||||||
|
/** @typedef {import("../Dependency")} Dependency */
|
||||||
|
/** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
|
||||||
|
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
|
||||||
|
/** @typedef {import("../ModuleGraph")} ModuleGraph */
|
||||||
|
|
||||||
|
class CommonJsSelfReferenceDependency extends NullDependency {
|
||||||
|
constructor(range, base, names) {
|
||||||
|
super();
|
||||||
|
this.range = range;
|
||||||
|
this.base = base;
|
||||||
|
this.names = names;
|
||||||
|
}
|
||||||
|
|
||||||
|
get type() {
|
||||||
|
return "cjs self exports reference";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {string | null} an identifier to merge equal requests
|
||||||
|
*/
|
||||||
|
getResourceIdentifier() {
|
||||||
|
return `self`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of exports referenced by this dependency
|
||||||
|
* @param {ModuleGraph} moduleGraph module graph
|
||||||
|
* @returns {string[][]} referenced exports
|
||||||
|
*/
|
||||||
|
getReferencedExports(moduleGraph) {
|
||||||
|
return [this.names];
|
||||||
|
}
|
||||||
|
|
||||||
|
serialize(context) {
|
||||||
|
const { write } = context;
|
||||||
|
write(this.range);
|
||||||
|
write(this.base);
|
||||||
|
write(this.names);
|
||||||
|
super.serialize(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
deserialize(context) {
|
||||||
|
const { read } = context;
|
||||||
|
this.range = read();
|
||||||
|
this.base = read();
|
||||||
|
this.names = read();
|
||||||
|
super.deserialize(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
makeSerializable(
|
||||||
|
CommonJsSelfReferenceDependency,
|
||||||
|
"webpack/lib/dependencies/CommonJsSelfReferenceDependency"
|
||||||
|
);
|
||||||
|
|
||||||
|
CommonJsSelfReferenceDependency.Template = class CommonJsSelfReferenceDependencyTemplate extends NullDependency.Template {
|
||||||
|
/**
|
||||||
|
* @param {Dependency} dependency the dependency for which the template should be applied
|
||||||
|
* @param {ReplaceSource} source the current replace source which can be modified
|
||||||
|
* @param {DependencyTemplateContext} templateContext the context object
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
apply(
|
||||||
|
dependency,
|
||||||
|
source,
|
||||||
|
{ module, moduleGraph, initFragments, runtimeRequirements }
|
||||||
|
) {
|
||||||
|
const dep = /** @type {CommonJsSelfReferenceDependency} */ (dependency);
|
||||||
|
let used;
|
||||||
|
if (dep.names.length === 0) {
|
||||||
|
used = dep.names;
|
||||||
|
} else if (module.buildMeta && module.buildMeta.exportsType === "default") {
|
||||||
|
const defaultInfo = moduleGraph.getExportInfo(module, "default");
|
||||||
|
if (defaultInfo.used === UsageState.Used) {
|
||||||
|
used = dep.names;
|
||||||
|
} else {
|
||||||
|
used = defaultInfo.exportsInfo.getUsedName(dep.names);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
used = moduleGraph.getExportsInfo(module).getUsedName(dep.names);
|
||||||
|
}
|
||||||
|
if (!used) {
|
||||||
|
throw new Error(
|
||||||
|
"Self-reference dependency has unused export name: This should not happen"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let base = undefined;
|
||||||
|
switch (dep.base) {
|
||||||
|
case "exports":
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.exports);
|
||||||
|
base = module.exportsArgument;
|
||||||
|
break;
|
||||||
|
case "module.exports":
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.module);
|
||||||
|
base = `${module.moduleArgument}.exports`;
|
||||||
|
break;
|
||||||
|
case "this":
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.thisAsExports);
|
||||||
|
base = "this";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported base ${dep.base}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (base === dep.base && used.join() === dep.names.join()) {
|
||||||
|
// Nothing has to be changed
|
||||||
|
// We don't use a replacement for compat reasons
|
||||||
|
// for plugins that update `module._source` which they
|
||||||
|
// shouldn't do!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
source.replace(
|
||||||
|
dep.range[0],
|
||||||
|
dep.range[1] - 1,
|
||||||
|
`/* self exports access */ ${base}${propertyAccess(used)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = CommonJsSelfReferenceDependency;
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||||
|
Author Tobias Koppers @sokra
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/** @typedef {import("../Parser").ParserState} ParserState */
|
||||||
|
|
||||||
|
/** @type {WeakMap<ParserState, boolean>} */
|
||||||
|
const parserStateExportsState = new WeakMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ParserState} parserState parser state
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
exports.bailout = parserState => {
|
||||||
|
const value = parserStateExportsState.get(parserState);
|
||||||
|
parserStateExportsState.set(parserState, false);
|
||||||
|
if (value === true) {
|
||||||
|
parserState.module.buildMeta.exportsType = undefined;
|
||||||
|
parserState.module.buildMeta.defaultObject = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ParserState} parserState parser state
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
exports.enable = parserState => {
|
||||||
|
const value = parserStateExportsState.get(parserState);
|
||||||
|
if (value === false) return;
|
||||||
|
parserStateExportsState.set(parserState, true);
|
||||||
|
if (value !== true) {
|
||||||
|
parserState.module.buildMeta.exportsType = "default";
|
||||||
|
parserState.module.buildMeta.defaultObject = "redirect";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ParserState} parserState parser state
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
exports.setFlagged = parserState => {
|
||||||
|
const value = parserStateExportsState.get(parserState);
|
||||||
|
if (value !== true) return;
|
||||||
|
parserState.module.buildMeta.exportsType = "flagged";
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ParserState} parserState parser state
|
||||||
|
* @returns {boolean} true, when enabled
|
||||||
|
*/
|
||||||
|
exports.isEnabled = parserState => {
|
||||||
|
const value = parserStateExportsState.get(parserState);
|
||||||
|
return value === true;
|
||||||
|
};
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const DynamicExports = require("./DynamicExports");
|
||||||
const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency");
|
const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency");
|
||||||
|
const HarmonyExports = require("./HarmonyExports");
|
||||||
|
|
||||||
module.exports = class HarmonyDetectionParserPlugin {
|
module.exports = class HarmonyDetectionParserPlugin {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
|
@ -48,16 +50,10 @@ module.exports = class HarmonyDetectionParserPlugin {
|
||||||
index: -3
|
index: -3
|
||||||
};
|
};
|
||||||
module.addPresentationalDependency(compatDep);
|
module.addPresentationalDependency(compatDep);
|
||||||
parser.state.harmonyModule = true;
|
DynamicExports.bailout(parser.state);
|
||||||
|
HarmonyExports.enable(parser.state, isStrictHarmony);
|
||||||
parser.scope.isStrict = true;
|
parser.scope.isStrict = true;
|
||||||
module.buildMeta.exportsType = "namespace";
|
|
||||||
module.buildMeta.async = isAsync;
|
module.buildMeta.async = isAsync;
|
||||||
module.buildInfo.strict = true;
|
|
||||||
module.buildInfo.exportsArgument = "__webpack_exports__";
|
|
||||||
if (isStrictHarmony) {
|
|
||||||
module.buildMeta.strictHarmonyModule = true;
|
|
||||||
module.buildInfo.moduleArgument = "__webpack_module__";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -68,7 +64,7 @@ module.exports = class HarmonyDetectionParserPlugin {
|
||||||
"The top-level-await experiment is not enabled (set experiments.topLevelAwait: true to enabled it)"
|
"The top-level-await experiment is not enabled (set experiments.topLevelAwait: true to enabled it)"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!parser.state.harmonyModule) {
|
if (!HarmonyExports.isEnabled(parser.state)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Top-level-await is only supported in EcmaScript Modules"
|
"Top-level-await is only supported in EcmaScript Modules"
|
||||||
);
|
);
|
||||||
|
@ -77,15 +73,13 @@ module.exports = class HarmonyDetectionParserPlugin {
|
||||||
});
|
});
|
||||||
|
|
||||||
const skipInHarmony = () => {
|
const skipInHarmony = () => {
|
||||||
const module = parser.state.module;
|
if (HarmonyExports.isEnabled(parser.state)) {
|
||||||
if (module && module.buildMeta && module.buildMeta.exportsType) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const nullInHarmony = () => {
|
const nullInHarmony = () => {
|
||||||
const module = parser.state.module;
|
if (HarmonyExports.isEnabled(parser.state)) {
|
||||||
if (module && module.buildMeta && module.buildMeta.exportsType) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,7 +29,7 @@ const HarmonyImportDependency = require("./HarmonyImportDependency");
|
||||||
/** @typedef {import("../WebpackError")} WebpackError */
|
/** @typedef {import("../WebpackError")} WebpackError */
|
||||||
/** @typedef {import("../util/Hash")} Hash */
|
/** @typedef {import("../util/Hash")} Hash */
|
||||||
|
|
||||||
/** @typedef {"missing"|"unused"|"empty-star"|"reexport-non-harmony-default"|"reexport-named-default"|"reexport-namespace-object"|"reexport-fake-named-namespace-object"|"reexport-fake-namespace-object"|"reexport-non-harmony-undefined"|"normal-reexport"|"dynamic-reexport"} ExportModeType */
|
/** @typedef {"missing"|"unused"|"empty-star"|"reexport-dynamic-default"|"reexport-dynamic-default-default"|"reexport-named-default"|"reexport-namespace-object"|"reexport-fake-namespace-object"|"reexport-undefined"|"normal-reexport"|"dynamic-reexport"} ExportModeType */
|
||||||
|
|
||||||
const idsSymbol = Symbol("HarmonyExportImportedSpecifierDependency.ids");
|
const idsSymbol = Symbol("HarmonyExportImportedSpecifierDependency.ids");
|
||||||
|
|
||||||
|
@ -190,30 +190,35 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const strictHarmonyModule = parentModule.buildMeta.strictHarmonyModule;
|
const importedExportsType = importedModule.getExportsType(
|
||||||
|
parentModule.buildMeta.strictHarmonyModule
|
||||||
|
);
|
||||||
|
|
||||||
const isNotAHarmonyModule =
|
const isDynamic = importedExportsType === "dynamic";
|
||||||
importedModule.buildMeta && !importedModule.buildMeta.exportsType;
|
const isDynamicDefault = importedExportsType === "dynamic-default";
|
||||||
const isNamedModule =
|
const isDefaultOnly = importedExportsType === "default-only";
|
||||||
importedModule.buildMeta &&
|
const isDefaultWithNamed = importedExportsType === "default-with-named";
|
||||||
importedModule.buildMeta.exportsType === "default";
|
|
||||||
|
|
||||||
// Special handling for reexporting the default export
|
// Special handling for reexporting the default export
|
||||||
// from non-harmony modules
|
// from non-namespace modules
|
||||||
if (name && ids.length > 0 && ids[0] === "default") {
|
if (name && ids.length > 0 && ids[0] === "default") {
|
||||||
if (isNotAHarmonyModule) {
|
if (isDynamic) {
|
||||||
const mode = new ExportMode("reexport-non-harmony-default");
|
const mode = new ExportMode("reexport-dynamic-default");
|
||||||
|
|
||||||
mode.name = name;
|
mode.name = name;
|
||||||
|
|
||||||
return mode;
|
return mode;
|
||||||
} else if (isNamedModule) {
|
} else if (isDefaultOnly || isDefaultWithNamed) {
|
||||||
const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
|
const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
|
||||||
const mode = new ExportMode("reexport-named-default");
|
const mode = new ExportMode("reexport-named-default");
|
||||||
|
|
||||||
mode.name = name;
|
mode.name = name;
|
||||||
mode.partialNamespaceExportInfo = exportInfo;
|
mode.partialNamespaceExportInfo = exportInfo;
|
||||||
|
|
||||||
|
return mode;
|
||||||
|
} else if (isDynamicDefault) {
|
||||||
|
const mode = new ExportMode("reexport-dynamic-default-default");
|
||||||
|
mode.name = name;
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,8 +230,8 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
||||||
|
|
||||||
if (ids.length > 0) {
|
if (ids.length > 0) {
|
||||||
// export { name as name }
|
// export { name as name }
|
||||||
if ((isNotAHarmonyModule || isNamedModule) && strictHarmonyModule) {
|
if (isDefaultOnly || isDynamicDefault) {
|
||||||
mode = new ExportMode("reexport-non-harmony-undefined");
|
mode = new ExportMode("reexport-undefined");
|
||||||
mode.name = name;
|
mode.name = name;
|
||||||
} else {
|
} else {
|
||||||
mode = new ExportMode("normal-reexport");
|
mode = new ExportMode("normal-reexport");
|
||||||
|
@ -235,14 +240,16 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// export { * as name }
|
// export { * as name }
|
||||||
if (isNotAHarmonyModule && strictHarmonyModule) {
|
if (isDefaultOnly || isDynamicDefault) {
|
||||||
mode = new ExportMode("reexport-fake-namespace-object");
|
mode = new ExportMode("reexport-fake-namespace-object");
|
||||||
mode.name = name;
|
mode.name = name;
|
||||||
} else if (isNamedModule) {
|
mode.partialNamespaceExportInfo = exportInfo;
|
||||||
mode = new ExportMode("reexport-fake-named-namespace-object");
|
mode.fakeType = 0;
|
||||||
|
} else if (isDefaultWithNamed) {
|
||||||
|
mode = new ExportMode("reexport-fake-namespace-object");
|
||||||
mode.name = name;
|
mode.name = name;
|
||||||
mode.partialNamespaceExportInfo = exportInfo;
|
mode.partialNamespaceExportInfo = exportInfo;
|
||||||
mode.fakeType = strictHarmonyModule ? 0 : 2;
|
mode.fakeType = 2;
|
||||||
} else {
|
} else {
|
||||||
mode = new ExportMode("reexport-namespace-object");
|
mode = new ExportMode("reexport-namespace-object");
|
||||||
mode.name = name;
|
mode.name = name;
|
||||||
|
@ -363,10 +370,10 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
||||||
case "missing":
|
case "missing":
|
||||||
case "unused":
|
case "unused":
|
||||||
case "empty-star":
|
case "empty-star":
|
||||||
case "reexport-non-harmony-undefined":
|
case "reexport-undefined":
|
||||||
return Dependency.NO_EXPORTS_REFERENCED;
|
return Dependency.NO_EXPORTS_REFERENCED;
|
||||||
|
|
||||||
case "reexport-non-harmony-default":
|
case "reexport-dynamic-default":
|
||||||
return Dependency.DEFAULT_EXPORT_REFERENCED;
|
return Dependency.DEFAULT_EXPORT_REFERENCED;
|
||||||
|
|
||||||
case "reexport-named-default": {
|
case "reexport-named-default": {
|
||||||
|
@ -383,7 +390,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
||||||
}
|
}
|
||||||
|
|
||||||
case "reexport-namespace-object":
|
case "reexport-namespace-object":
|
||||||
case "reexport-fake-named-namespace-object": {
|
case "reexport-fake-namespace-object": {
|
||||||
if (!mode.partialNamespaceExportInfo)
|
if (!mode.partialNamespaceExportInfo)
|
||||||
return Dependency.NS_OBJECT_REFERENCED;
|
return Dependency.NS_OBJECT_REFERENCED;
|
||||||
/** @type {string[][]} */
|
/** @type {string[][]} */
|
||||||
|
@ -396,8 +403,8 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
||||||
return referencedExports;
|
return referencedExports;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "reexport-fake-namespace-object":
|
|
||||||
case "dynamic-reexport":
|
case "dynamic-reexport":
|
||||||
|
case "reexport-dynamic-default-default":
|
||||||
return Dependency.NS_OBJECT_REFERENCED;
|
return Dependency.NS_OBJECT_REFERENCED;
|
||||||
|
|
||||||
case "normal-reexport":
|
case "normal-reexport":
|
||||||
|
@ -468,14 +475,14 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
||||||
})),
|
})),
|
||||||
dependencies: [moduleGraph.getModule(this)]
|
dependencies: [moduleGraph.getModule(this)]
|
||||||
};
|
};
|
||||||
case "reexport-fake-namespace-object":
|
case "reexport-dynamic-default":
|
||||||
case "reexport-non-harmony-default":
|
case "reexport-dynamic-default-default":
|
||||||
case "reexport-non-harmony-undefined":
|
case "reexport-undefined":
|
||||||
return {
|
return {
|
||||||
exports: [mode.name],
|
exports: [mode.name],
|
||||||
dependencies: [moduleGraph.getModule(this)]
|
dependencies: [moduleGraph.getModule(this)]
|
||||||
};
|
};
|
||||||
case "reexport-fake-named-namespace-object":
|
case "reexport-fake-namespace-object":
|
||||||
case "reexport-namespace-object":
|
case "reexport-namespace-object":
|
||||||
return {
|
return {
|
||||||
exports: [
|
exports: [
|
||||||
|
@ -678,23 +685,33 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "reexport-non-harmony-default":
|
case "reexport-dynamic-default":
|
||||||
initFragments.push(
|
initFragments.push(
|
||||||
this.getReexportFragment(
|
this.getReexportFragment(
|
||||||
module,
|
module,
|
||||||
"reexport default from non-harmony",
|
"reexport default from dynamic",
|
||||||
module.getUsedName(moduleGraph, mode.name),
|
module.getUsedName(moduleGraph, mode.name),
|
||||||
importVar,
|
importVar,
|
||||||
module.buildMeta && module.buildMeta.strictHarmonyModule
|
null,
|
||||||
? ""
|
runtimeRequirements
|
||||||
: null,
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "reexport-dynamic-default-default":
|
||||||
|
initFragments.push(
|
||||||
|
this.getReexportFragment(
|
||||||
|
module,
|
||||||
|
"reexport dynamic as default",
|
||||||
|
module.getUsedName(moduleGraph, mode.name),
|
||||||
|
importVar,
|
||||||
|
"",
|
||||||
runtimeRequirements
|
runtimeRequirements
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "reexport-fake-namespace-object":
|
case "reexport-fake-namespace-object":
|
||||||
case "reexport-fake-named-namespace-object":
|
|
||||||
initFragments.push(
|
initFragments.push(
|
||||||
...this.getReexportFakeNamespaceObjectFragments(
|
...this.getReexportFakeNamespaceObjectFragments(
|
||||||
module,
|
module,
|
||||||
|
@ -706,7 +723,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "reexport-non-harmony-undefined":
|
case "reexport-undefined":
|
||||||
initFragments.push(
|
initFragments.push(
|
||||||
this.getReexportFragment(
|
this.getReexportFragment(
|
||||||
module,
|
module,
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||||
|
Author Tobias Koppers @sokra
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/** @typedef {import("../Parser").ParserState} ParserState */
|
||||||
|
|
||||||
|
/** @type {WeakMap<ParserState, boolean>} */
|
||||||
|
const parserStateExportsState = new WeakMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ParserState} parserState parser state
|
||||||
|
* @param {boolean} isStrictHarmony strict harmony mode should be enabled
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
exports.enable = (parserState, isStrictHarmony) => {
|
||||||
|
const value = parserStateExportsState.get(parserState);
|
||||||
|
if (value === false) return;
|
||||||
|
parserStateExportsState.set(parserState, true);
|
||||||
|
if (value !== true) {
|
||||||
|
parserState.module.buildMeta.exportsType = "namespace";
|
||||||
|
parserState.module.buildInfo.strict = true;
|
||||||
|
parserState.module.buildInfo.exportsArgument = "__webpack_exports__";
|
||||||
|
if (isStrictHarmony) {
|
||||||
|
parserState.module.buildMeta.strictHarmonyModule = true;
|
||||||
|
parserState.module.buildInfo.moduleArgument = "__webpack_module__";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ParserState} parserState parser state
|
||||||
|
* @returns {boolean} true, when enabled
|
||||||
|
*/
|
||||||
|
exports.isEnabled = parserState => {
|
||||||
|
const value = parserStateExportsState.get(parserState);
|
||||||
|
return value === true;
|
||||||
|
};
|
|
@ -94,62 +94,68 @@ class HarmonyImportDependency extends ModuleDependency {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const exportsType =
|
const parentModule = moduleGraph.getParentModule(this);
|
||||||
importedModule.buildMeta && importedModule.buildMeta.exportsType;
|
const exportsType = importedModule.getExportsType(
|
||||||
if (!exportsType) {
|
parentModule.buildMeta.strictHarmonyModule
|
||||||
// It's not an harmony module
|
);
|
||||||
if (
|
switch (exportsType) {
|
||||||
moduleGraph.getParentModule(this).buildMeta.strictHarmonyModule &&
|
case "default-only":
|
||||||
ids.length > 0 &&
|
case "dynamic-default":
|
||||||
ids[0] !== "default"
|
// It's has only a default export
|
||||||
) {
|
if (ids.length > 0 && ids[0] !== "default") {
|
||||||
// In strict harmony modules we only support the default export
|
// In strict harmony modules we only support the default export
|
||||||
|
return [
|
||||||
|
new HarmonyLinkingError(
|
||||||
|
`Can't import the named export ${ids
|
||||||
|
.map(id => `'${id}'`)
|
||||||
|
.join(
|
||||||
|
"."
|
||||||
|
)} ${additionalMessage} from default-exporting module (only default export is available)`
|
||||||
|
)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case "default-with-named":
|
||||||
|
// It has a default export and named properties redirect
|
||||||
|
// In some cases we still want to warn here
|
||||||
|
if (
|
||||||
|
ids.length > 0 &&
|
||||||
|
ids[0] !== "default" &&
|
||||||
|
importedModule.buildMeta.defaultObject === "redirect-warn"
|
||||||
|
) {
|
||||||
|
// For these modules only the default export is supported
|
||||||
|
return [
|
||||||
|
new HarmonyLinkingError(
|
||||||
|
`Should not import the named export ${ids
|
||||||
|
.map(id => `'${id}'`)
|
||||||
|
.join(
|
||||||
|
"."
|
||||||
|
)} ${additionalMessage} from default-exporting module (only default export is available soon)`
|
||||||
|
)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case "namespace":
|
||||||
|
if (ids.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moduleGraph.isExportProvided(importedModule, ids) !== false) {
|
||||||
|
// It's provided or we are not sure
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are sure that it's not provided
|
||||||
return [
|
return [
|
||||||
new HarmonyLinkingError(
|
new HarmonyLinkingError(
|
||||||
`Can't import the named export ${ids
|
`export ${ids
|
||||||
.map(id => `'${id}'`)
|
.map(id => `'${id}'`)
|
||||||
.join(
|
.join(".")} ${additionalMessage} was not found in '${
|
||||||
"."
|
this.userRequest
|
||||||
)} ${additionalMessage} from non EcmaScript module (only default export is available)`
|
}'`
|
||||||
)
|
)
|
||||||
];
|
];
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else if (exportsType === "default") {
|
|
||||||
if (ids.length > 0 && ids[0] !== "default") {
|
|
||||||
// For these modules only the default export is supported
|
|
||||||
return [
|
|
||||||
new HarmonyLinkingError(
|
|
||||||
`Can't import the named export ${ids
|
|
||||||
.map(id => `'${id}'`)
|
|
||||||
.join(
|
|
||||||
"."
|
|
||||||
)} ${additionalMessage} from JSON module (only default export is available)`
|
|
||||||
)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ids.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (moduleGraph.isExportProvided(importedModule, ids) !== false) {
|
|
||||||
// It's provided or we are not sure
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We are sure that it's not provided
|
|
||||||
return [
|
|
||||||
new HarmonyLinkingError(
|
|
||||||
`export ${ids
|
|
||||||
.map(id => `'${id}'`)
|
|
||||||
.join(".")} ${additionalMessage} was not found in '${
|
|
||||||
this.userRequest
|
|
||||||
}'`
|
|
||||||
)
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -161,12 +167,15 @@ class HarmonyImportDependency extends ModuleDependency {
|
||||||
updateHash(hash, chunkGraph) {
|
updateHash(hash, chunkGraph) {
|
||||||
super.updateHash(hash, chunkGraph);
|
super.updateHash(hash, chunkGraph);
|
||||||
const importedModule = chunkGraph.moduleGraph.getModule(this);
|
const importedModule = chunkGraph.moduleGraph.getModule(this);
|
||||||
hash.update(
|
if (importedModule) {
|
||||||
(importedModule &&
|
const parentModule = chunkGraph.moduleGraph.getParentModule(this);
|
||||||
(!importedModule.buildMeta || importedModule.buildMeta.exportsType)) +
|
hash.update(
|
||||||
""
|
importedModule.getExportsType(
|
||||||
);
|
parentModule.buildMeta && parentModule.buildMeta.strictHarmonyModule
|
||||||
if (chunkGraph.moduleGraph.isAsync(importedModule)) hash.update("async");
|
)
|
||||||
|
);
|
||||||
|
if (chunkGraph.moduleGraph.isAsync(importedModule)) hash.update("async");
|
||||||
|
}
|
||||||
hash.update(`${this.sourceOrder}`);
|
hash.update(`${this.sourceOrder}`);
|
||||||
if (this.await) hash.update("await");
|
if (this.await) hash.update("await");
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ const HotModuleReplacementPlugin = require("../HotModuleReplacementPlugin");
|
||||||
const ConstDependency = require("./ConstDependency");
|
const ConstDependency = require("./ConstDependency");
|
||||||
const HarmonyAcceptDependency = require("./HarmonyAcceptDependency");
|
const HarmonyAcceptDependency = require("./HarmonyAcceptDependency");
|
||||||
const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency");
|
const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency");
|
||||||
|
const HarmonyExports = require("./HarmonyExports");
|
||||||
const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
|
const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
|
||||||
const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
|
const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
|
||||||
|
|
||||||
|
@ -168,7 +169,7 @@ module.exports = class HarmonyImportDependencyParserPlugin {
|
||||||
hotAcceptCallback.tap(
|
hotAcceptCallback.tap(
|
||||||
"HarmonyImportDependencyParserPlugin",
|
"HarmonyImportDependencyParserPlugin",
|
||||||
(expr, requests) => {
|
(expr, requests) => {
|
||||||
if (!parser.state.harmonyModule) {
|
if (!HarmonyExports.isEnabled(parser.state)) {
|
||||||
// This is not a harmony module, skip it
|
// This is not a harmony module, skip it
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -192,7 +193,7 @@ module.exports = class HarmonyImportDependencyParserPlugin {
|
||||||
hotAcceptWithoutCallback.tap(
|
hotAcceptWithoutCallback.tap(
|
||||||
"HarmonyImportDependencyParserPlugin",
|
"HarmonyImportDependencyParserPlugin",
|
||||||
(expr, requests) => {
|
(expr, requests) => {
|
||||||
if (!parser.state.harmonyModule) {
|
if (!HarmonyExports.isEnabled(parser.state)) {
|
||||||
// This is not a harmony module, skip it
|
// This is not a harmony module, skip it
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,9 +171,6 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
|
||||||
if (importedModule) {
|
if (importedModule) {
|
||||||
const exportsInfo = moduleGraph.getExportsInfo(importedModule);
|
const exportsInfo = moduleGraph.getExportsInfo(importedModule);
|
||||||
hash.update(`${exportsInfo.getUsedName(ids)}`);
|
hash.update(`${exportsInfo.getUsedName(ids)}`);
|
||||||
hash.update(
|
|
||||||
(!importedModule.buildMeta || importedModule.buildMeta.exportsType) + ""
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,6 +243,7 @@ HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependen
|
||||||
asiSafe: dep.asiSafe || dep.shorthand,
|
asiSafe: dep.asiSafe || dep.shorthand,
|
||||||
isCall: dep.call,
|
isCall: dep.call,
|
||||||
callContext: !dep.directImport,
|
callContext: !dep.directImport,
|
||||||
|
defaultInterop: true,
|
||||||
importVar: dep.getImportVar(moduleGraph),
|
importVar: dep.getImportVar(moduleGraph),
|
||||||
initFragments,
|
initFragments,
|
||||||
runtimeRequirements
|
runtimeRequirements
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const ConstDependency = require("./ConstDependency");
|
const ConstDependency = require("./ConstDependency");
|
||||||
|
const HarmonyExports = require("./HarmonyExports");
|
||||||
|
|
||||||
class HarmonyTopLevelThisParserPlugin {
|
class HarmonyTopLevelThisParserPlugin {
|
||||||
apply(parser) {
|
apply(parser) {
|
||||||
|
@ -13,12 +14,11 @@ class HarmonyTopLevelThisParserPlugin {
|
||||||
.for("this")
|
.for("this")
|
||||||
.tap("HarmonyTopLevelThisParserPlugin", node => {
|
.tap("HarmonyTopLevelThisParserPlugin", node => {
|
||||||
if (!parser.scope.topLevelScope) return;
|
if (!parser.scope.topLevelScope) return;
|
||||||
const module = parser.state.module;
|
if (HarmonyExports.isEnabled(parser.state)) {
|
||||||
const isHarmony = !!(module.buildMeta && module.buildMeta.exportsType);
|
|
||||||
if (isHarmony) {
|
|
||||||
const dep = new ConstDependency("undefined", node.range, null);
|
const dep = new ConstDependency("undefined", node.range, null);
|
||||||
dep.loc = node.loc;
|
dep.loc = node.loc;
|
||||||
parser.state.module.addPresentationalDependency(dep);
|
parser.state.module.addPresentationalDependency(dep);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,22 @@ class ModuleDecoratorDependency extends NullDependency {
|
||||||
return "module decorator";
|
return "module decorator";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {string | null} an identifier to merge equal requests
|
||||||
|
*/
|
||||||
|
getResourceIdentifier() {
|
||||||
|
return `self`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of exports referenced by this dependency
|
||||||
|
* @param {ModuleGraph} moduleGraph module graph
|
||||||
|
* @returns {string[][]} referenced exports
|
||||||
|
*/
|
||||||
|
getReferencedExports(moduleGraph) {
|
||||||
|
return [[]];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the hash
|
* Update the hash
|
||||||
* @param {Hash} hash hash to be updated
|
* @param {Hash} hash hash to be updated
|
||||||
|
@ -76,6 +92,8 @@ ModuleDecoratorDependency.Template = class ModuleDecoratorDependencyTemplate ext
|
||||||
{ module, chunkGraph, initFragments, runtimeRequirements }
|
{ module, chunkGraph, initFragments, runtimeRequirements }
|
||||||
) {
|
) {
|
||||||
const dep = /** @type {ModuleDecoratorDependency} */ (dependency);
|
const dep = /** @type {ModuleDecoratorDependency} */ (dependency);
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.moduleLoaded);
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.moduleId);
|
||||||
runtimeRequirements.add(RuntimeGlobals.module);
|
runtimeRequirements.add(RuntimeGlobals.module);
|
||||||
runtimeRequirements.add(dep.decorator);
|
runtimeRequirements.add(dep.decorator);
|
||||||
initFragments.push(
|
initFragments.push(
|
||||||
|
|
|
@ -5,10 +5,13 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const Dependency = require("../Dependency");
|
||||||
const makeSerializable = require("../util/makeSerializable");
|
const makeSerializable = require("../util/makeSerializable");
|
||||||
const ModuleDependency = require("./ModuleDependency");
|
const ModuleDependency = require("./ModuleDependency");
|
||||||
const ModuleDependencyAsId = require("./ModuleDependencyTemplateAsId");
|
const ModuleDependencyAsId = require("./ModuleDependencyTemplateAsId");
|
||||||
|
|
||||||
|
/** @typedef {import("../ModuleGraph")} ModuleGraph */
|
||||||
|
|
||||||
class RequireResolveDependency extends ModuleDependency {
|
class RequireResolveDependency extends ModuleDependency {
|
||||||
constructor(request, range) {
|
constructor(request, range) {
|
||||||
super(request);
|
super(request);
|
||||||
|
@ -20,6 +23,16 @@ class RequireResolveDependency extends ModuleDependency {
|
||||||
return "require.resolve";
|
return "require.resolve";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of exports referenced by this dependency
|
||||||
|
* @param {ModuleGraph} moduleGraph module graph
|
||||||
|
* @returns {string[][]} referenced exports
|
||||||
|
*/
|
||||||
|
getReferencedExports(moduleGraph) {
|
||||||
|
// This doesn't use any export
|
||||||
|
return Dependency.NO_EXPORTS_REFERENCED;
|
||||||
|
}
|
||||||
|
|
||||||
serialize(context) {
|
serialize(context) {
|
||||||
const { write } = context;
|
const { write } = context;
|
||||||
|
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
/*
|
|
||||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
|
||||||
Author Tobias Koppers @sokra
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const ContextDependencyHelpers = require("./ContextDependencyHelpers");
|
|
||||||
const RequireResolveContextDependency = require("./RequireResolveContextDependency");
|
|
||||||
const RequireResolveDependency = require("./RequireResolveDependency");
|
|
||||||
const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency");
|
|
||||||
|
|
||||||
class RequireResolveDependencyParserPlugin {
|
|
||||||
constructor(options) {
|
|
||||||
this.options = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
apply(parser) {
|
|
||||||
const options = this.options;
|
|
||||||
|
|
||||||
const process = (expr, weak) => {
|
|
||||||
if (expr.arguments.length !== 1) return;
|
|
||||||
const param = parser.evaluateExpression(expr.arguments[0]);
|
|
||||||
if (param.isConditional()) {
|
|
||||||
for (const option of param.options) {
|
|
||||||
const result = processItem(expr, option, weak);
|
|
||||||
if (result === undefined) {
|
|
||||||
processContext(expr, option, weak);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const dep = new RequireResolveHeaderDependency(expr.callee.range);
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
parser.state.module.addPresentationalDependency(dep);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
const result = processItem(expr, param, weak);
|
|
||||||
if (result === undefined) {
|
|
||||||
processContext(expr, param, weak);
|
|
||||||
}
|
|
||||||
const dep = new RequireResolveHeaderDependency(expr.callee.range);
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
parser.state.module.addPresentationalDependency(dep);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const processItem = (expr, param, weak) => {
|
|
||||||
if (param.isString()) {
|
|
||||||
const dep = new RequireResolveDependency(param.string, param.range);
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
dep.optional = !!parser.scope.inTry;
|
|
||||||
dep.weak = weak;
|
|
||||||
parser.state.current.addDependency(dep);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const processContext = (expr, param, weak) => {
|
|
||||||
const dep = ContextDependencyHelpers.create(
|
|
||||||
RequireResolveContextDependency,
|
|
||||||
param.range,
|
|
||||||
param,
|
|
||||||
expr,
|
|
||||||
options,
|
|
||||||
{
|
|
||||||
mode: weak ? "weak" : "sync"
|
|
||||||
},
|
|
||||||
parser
|
|
||||||
);
|
|
||||||
if (!dep) return;
|
|
||||||
dep.loc = expr.loc;
|
|
||||||
dep.optional = !!parser.scope.inTry;
|
|
||||||
parser.state.current.addDependency(dep);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.hooks.call
|
|
||||||
.for("require.resolve")
|
|
||||||
.tap("RequireResolveDependencyParserPlugin", expr => {
|
|
||||||
return process(expr, false);
|
|
||||||
});
|
|
||||||
parser.hooks.call
|
|
||||||
.for("require.resolveWeak")
|
|
||||||
.tap("RequireResolveDependencyParserPlugin", expr => {
|
|
||||||
return process(expr, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.exports = RequireResolveDependencyParserPlugin;
|
|
|
@ -867,6 +867,10 @@ class JavascriptModulesPlugin {
|
||||||
: Template.asString([
|
: Template.asString([
|
||||||
"__webpack_modules__[moduleId](module, module.exports, __webpack_require__);"
|
"__webpack_modules__[moduleId](module, module.exports, __webpack_require__);"
|
||||||
]);
|
]);
|
||||||
|
const needModuleId = runtimeRequirements.has(RuntimeGlobals.moduleId);
|
||||||
|
const needModuleLoaded = runtimeRequirements.has(
|
||||||
|
RuntimeGlobals.moduleLoaded
|
||||||
|
);
|
||||||
const content = Template.asString([
|
const content = Template.asString([
|
||||||
"// Check if module is in cache",
|
"// Check if module is in cache",
|
||||||
"if(__webpack_module_cache__[moduleId]) {",
|
"if(__webpack_module_cache__[moduleId]) {",
|
||||||
|
@ -874,7 +878,11 @@ class JavascriptModulesPlugin {
|
||||||
"}",
|
"}",
|
||||||
"// Create a new module (and put it into the cache)",
|
"// Create a new module (and put it into the cache)",
|
||||||
"var module = __webpack_module_cache__[moduleId] = {",
|
"var module = __webpack_module_cache__[moduleId] = {",
|
||||||
Template.indent(["i: moduleId,", "l: false,", "exports: {}"]),
|
Template.indent([
|
||||||
|
needModuleId ? "id: moduleId," : "// no module.id needed",
|
||||||
|
needModuleLoaded ? "loaded: false," : "// no module.loaded needed",
|
||||||
|
"exports: {}"
|
||||||
|
]),
|
||||||
"};",
|
"};",
|
||||||
"",
|
"",
|
||||||
outputOptions.strictModuleExceptionHandling
|
outputOptions.strictModuleExceptionHandling
|
||||||
|
@ -893,10 +901,14 @@ class JavascriptModulesPlugin {
|
||||||
"// Execute the module function",
|
"// Execute the module function",
|
||||||
moduleExecution
|
moduleExecution
|
||||||
]),
|
]),
|
||||||
"",
|
needModuleLoaded
|
||||||
"// Flag the module as loaded",
|
? Template.asString([
|
||||||
"module.l = true;",
|
"",
|
||||||
"",
|
"// Flag the module as loaded",
|
||||||
|
"module.loaded = true;",
|
||||||
|
""
|
||||||
|
])
|
||||||
|
: "",
|
||||||
"// Return the exports of the module",
|
"// Return the exports of the module",
|
||||||
"return module.exports;"
|
"return module.exports;"
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -10,6 +10,7 @@ const { SyncBailHook, HookMap } = require("tapable");
|
||||||
const vm = require("vm");
|
const vm = require("vm");
|
||||||
const Parser = require("../Parser");
|
const Parser = require("../Parser");
|
||||||
const StackedMap = require("../util/StackedMap");
|
const StackedMap = require("../util/StackedMap");
|
||||||
|
const memorize = require("../util/memorize");
|
||||||
const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
|
const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
|
||||||
|
|
||||||
/** @typedef {import("acorn").Options} AcornOptions */
|
/** @typedef {import("acorn").Options} AcornOptions */
|
||||||
|
@ -41,6 +42,8 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
|
||||||
/** @typedef {import("../Parser").ParserState} ParserState */
|
/** @typedef {import("../Parser").ParserState} ParserState */
|
||||||
/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
|
/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
|
||||||
|
|
||||||
|
const EMPTY_ARRAY = [];
|
||||||
|
|
||||||
// Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
|
// Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
|
||||||
|
|
||||||
const parser = AcornParser.extend(require("../parsing/importAwaitAcornPlugin"));
|
const parser = AcornParser.extend(require("../parsing/importAwaitAcornPlugin"));
|
||||||
|
@ -84,6 +87,25 @@ const joinRanges = (startRange, endRange) => {
|
||||||
return [startRange[0], endRange[1]];
|
return [startRange[0], endRange[1]];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const objectAndMembersToName = (object, membersReversed) => {
|
||||||
|
let name = object;
|
||||||
|
for (let i = membersReversed.length - 1; i >= 0; i--) {
|
||||||
|
name = name + "." + membersReversed[i];
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRootName = expression => {
|
||||||
|
switch (expression.type) {
|
||||||
|
case "Identifier":
|
||||||
|
return expression.name;
|
||||||
|
case "ThisExpression":
|
||||||
|
return "this";
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** @type {AcornOptions} */
|
/** @type {AcornOptions} */
|
||||||
const defaultParserOptions = {
|
const defaultParserOptions = {
|
||||||
ranges: true,
|
ranges: true,
|
||||||
|
@ -186,6 +208,10 @@ class JavascriptParser extends Parser {
|
||||||
rename: new HookMap(() => new SyncBailHook(["initExpression"])),
|
rename: new HookMap(() => new SyncBailHook(["initExpression"])),
|
||||||
/** @type {HookMap<SyncBailHook<[import("estree").AssignmentExpression], boolean | void>>} */
|
/** @type {HookMap<SyncBailHook<[import("estree").AssignmentExpression], boolean | void>>} */
|
||||||
assign: new HookMap(() => new SyncBailHook(["expression"])),
|
assign: new HookMap(() => new SyncBailHook(["expression"])),
|
||||||
|
/** @type {HookMap<SyncBailHook<[import("estree").AssignmentExpression, string[]], boolean | void>>} */
|
||||||
|
assignMemberChain: new HookMap(
|
||||||
|
() => new SyncBailHook(["expression", "members"])
|
||||||
|
),
|
||||||
/** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
|
/** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
|
||||||
typeof: new HookMap(() => new SyncBailHook(["expression"])),
|
typeof: new HookMap(() => new SyncBailHook(["expression"])),
|
||||||
/** @type {SyncBailHook<[ExpressionNode], boolean | void>} */
|
/** @type {SyncBailHook<[ExpressionNode], boolean | void>} */
|
||||||
|
@ -194,15 +220,38 @@ class JavascriptParser extends Parser {
|
||||||
topLevelAwait: new SyncBailHook(["expression"]),
|
topLevelAwait: new SyncBailHook(["expression"]),
|
||||||
/** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
|
/** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
|
||||||
call: new HookMap(() => new SyncBailHook(["expression"])),
|
call: new HookMap(() => new SyncBailHook(["expression"])),
|
||||||
/** @type {HookMap<SyncBailHook<[ExpressionNode, any[]], boolean | void>>} */
|
/** Something like "a.b()" */
|
||||||
|
/** @type {HookMap<SyncBailHook<[ExpressionNode, string[]], boolean | void>>} */
|
||||||
callMemberChain: new HookMap(
|
callMemberChain: new HookMap(
|
||||||
() => new SyncBailHook(["expression", "members"])
|
() => new SyncBailHook(["expression", "members"])
|
||||||
),
|
),
|
||||||
|
/** Something like "a.b().c.d" */
|
||||||
|
/** @type {HookMap<SyncBailHook<[ExpressionNode, string[], CallExpressionNode, string[]], boolean | void>>} */
|
||||||
|
memberChainOfCallMemberChain: new HookMap(
|
||||||
|
() =>
|
||||||
|
new SyncBailHook([
|
||||||
|
"expression",
|
||||||
|
"calleeMembers",
|
||||||
|
"callExpression",
|
||||||
|
"members"
|
||||||
|
])
|
||||||
|
),
|
||||||
|
/** Something like "a.b().c.d()"" */
|
||||||
|
/** @type {HookMap<SyncBailHook<[ExpressionNode, string[], CallExpressionNode, string[]], boolean | void>>} */
|
||||||
|
callMemberChainOfCallMemberChain: new HookMap(
|
||||||
|
() =>
|
||||||
|
new SyncBailHook([
|
||||||
|
"expression",
|
||||||
|
"calleeMembers",
|
||||||
|
"innerCallExpression",
|
||||||
|
"members"
|
||||||
|
])
|
||||||
|
),
|
||||||
/** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
|
/** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
|
||||||
new: new HookMap(() => new SyncBailHook(["expression"])),
|
new: new HookMap(() => new SyncBailHook(["expression"])),
|
||||||
/** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
|
/** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
|
||||||
expression: new HookMap(() => new SyncBailHook(["expression"])),
|
expression: new HookMap(() => new SyncBailHook(["expression"])),
|
||||||
/** @type {HookMap<SyncBailHook<[ExpressionNode, any[]], boolean | void>>} */
|
/** @type {HookMap<SyncBailHook<[ExpressionNode, string[]], boolean | void>>} */
|
||||||
expressionMemberChain: new HookMap(
|
expressionMemberChain: new HookMap(
|
||||||
() => new SyncBailHook(["expression", "members"])
|
() => new SyncBailHook(["expression", "members"])
|
||||||
),
|
),
|
||||||
|
@ -219,6 +268,7 @@ class JavascriptParser extends Parser {
|
||||||
this.sourceType = sourceType;
|
this.sourceType = sourceType;
|
||||||
/** @type {ScopeInfo} */
|
/** @type {ScopeInfo} */
|
||||||
this.scope = undefined;
|
this.scope = undefined;
|
||||||
|
/** @type {ParserState} */
|
||||||
this.state = undefined;
|
this.state = undefined;
|
||||||
this.comments = undefined;
|
this.comments = undefined;
|
||||||
this.semicolons = undefined;
|
this.semicolons = undefined;
|
||||||
|
@ -1996,6 +2046,23 @@ class JavascriptParser extends Parser {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.walkPattern(expression.left);
|
this.walkPattern(expression.left);
|
||||||
|
} else if (expression.left.type === "MemberExpression") {
|
||||||
|
const exprName = this.getMemberExpressionInfo(expression.left, [
|
||||||
|
"expression"
|
||||||
|
]);
|
||||||
|
if (exprName) {
|
||||||
|
if (
|
||||||
|
this.callHooksForInfo(
|
||||||
|
this.hooks.assignMemberChain,
|
||||||
|
exprName.rootInfo,
|
||||||
|
expression,
|
||||||
|
exprName.getMembers()
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.walkExpression(expression.left);
|
||||||
} else {
|
} else {
|
||||||
this.walkExpression(expression.left);
|
this.walkExpression(expression.left);
|
||||||
}
|
}
|
||||||
|
@ -2140,6 +2207,22 @@ class JavascriptParser extends Parser {
|
||||||
// (function(…) { }(…))
|
// (function(…) { }(…))
|
||||||
this._walkIIFE(expression.callee, expression.arguments, null);
|
this._walkIIFE(expression.callee, expression.arguments, null);
|
||||||
} else {
|
} else {
|
||||||
|
if (expression.callee.type === "MemberExpression") {
|
||||||
|
const exprInfo = this.getMemberExpressionInfo(expression.callee, [
|
||||||
|
"call"
|
||||||
|
]);
|
||||||
|
if (exprInfo && exprInfo.type === "call") {
|
||||||
|
const result = this.callHooksForInfo(
|
||||||
|
this.hooks.callMemberChainOfCallMemberChain,
|
||||||
|
exprInfo.rootInfo,
|
||||||
|
expression,
|
||||||
|
exprInfo.getCalleeMembers(),
|
||||||
|
exprInfo.call,
|
||||||
|
exprInfo.getMembers()
|
||||||
|
);
|
||||||
|
if (result === true) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
const callee = this.evaluateExpression(expression.callee);
|
const callee = this.evaluateExpression(expression.callee);
|
||||||
if (callee.isIdentifier()) {
|
if (callee.isIdentifier()) {
|
||||||
const result1 = this.callHooksForInfo(
|
const result1 = this.callHooksForInfo(
|
||||||
|
@ -2157,40 +2240,72 @@ class JavascriptParser extends Parser {
|
||||||
if (result2 === true) return;
|
if (result2 === true) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expression.callee) this.walkExpression(expression.callee);
|
if (expression.callee) {
|
||||||
|
if (expression.callee.type === "MemberExpression") {
|
||||||
|
// because of call context we need to walk the call context as expression
|
||||||
|
this.walkExpression(expression.callee.object);
|
||||||
|
if (expression.callee.computed === true)
|
||||||
|
this.walkExpression(expression.callee.property);
|
||||||
|
} else {
|
||||||
|
this.walkExpression(expression.callee);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (expression.arguments) this.walkExpressions(expression.arguments);
|
if (expression.arguments) this.walkExpressions(expression.arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
walkMemberExpression(expression) {
|
walkMemberExpression(expression) {
|
||||||
const exprName = this.getNameForExpression(expression);
|
const exprInfo = this.getMemberExpressionInfo(expression, [
|
||||||
if (exprName) {
|
"call",
|
||||||
this.walkMemberExpressionWithExpressionName(
|
"expression"
|
||||||
expression,
|
]);
|
||||||
exprName.name,
|
if (exprInfo) {
|
||||||
exprName.rootInfo,
|
switch (exprInfo.type) {
|
||||||
exprName.getMembers()
|
case "expression": {
|
||||||
);
|
const members = exprInfo.getMembers();
|
||||||
return;
|
const result = this.callHooksForInfo(
|
||||||
|
this.hooks.expressionMemberChain,
|
||||||
|
exprInfo.rootInfo,
|
||||||
|
expression,
|
||||||
|
members
|
||||||
|
);
|
||||||
|
if (result === true) return;
|
||||||
|
this.walkMemberExpressionWithExpressionName(
|
||||||
|
expression,
|
||||||
|
exprInfo.name,
|
||||||
|
exprInfo.rootInfo,
|
||||||
|
members
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case "call": {
|
||||||
|
const result = this.callHooksForInfo(
|
||||||
|
this.hooks.memberChainOfCallMemberChain,
|
||||||
|
exprInfo.rootInfo,
|
||||||
|
expression,
|
||||||
|
exprInfo.getCalleeMembers(),
|
||||||
|
exprInfo.call,
|
||||||
|
exprInfo.getMembers()
|
||||||
|
);
|
||||||
|
if (result === true) return;
|
||||||
|
// Fast skip over the member chain as we already called memberChainOfCallMemberChain
|
||||||
|
// and call computed property are literals anyway
|
||||||
|
this.walkExpression(exprInfo.call);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.walkExpression(expression.object);
|
this.walkExpression(expression.object);
|
||||||
if (expression.computed === true) this.walkExpression(expression.property);
|
if (expression.computed === true) this.walkExpression(expression.property);
|
||||||
}
|
}
|
||||||
|
|
||||||
walkMemberExpressionWithExpressionName(expression, name, rootInfo, members) {
|
walkMemberExpressionWithExpressionName(expression, name, rootInfo, members) {
|
||||||
const result1 = this.callHooksForInfo(
|
const result = this.callHooksForInfo(
|
||||||
this.hooks.expressionMemberChain,
|
|
||||||
rootInfo,
|
|
||||||
expression,
|
|
||||||
members
|
|
||||||
);
|
|
||||||
if (result1 === true) return;
|
|
||||||
const result2 = this.callHooksForInfo(
|
|
||||||
this.hooks.expression,
|
this.hooks.expression,
|
||||||
name,
|
name,
|
||||||
expression
|
expression
|
||||||
);
|
);
|
||||||
if (result2 === true) return;
|
if (result === true) return;
|
||||||
if (expression.object.type === "MemberExpression") {
|
if (expression.object.type === "MemberExpression") {
|
||||||
// optimize case where expression.object is a MemberExpression too.
|
// optimize case where expression.object is a MemberExpression too.
|
||||||
// we can keep info here when calling walkMemberExpression directly
|
// we can keep info here when calling walkMemberExpression directly
|
||||||
|
@ -2219,7 +2334,7 @@ class JavascriptParser extends Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
callHooksForExpression(hookMap, expr, ...args) {
|
callHooksForExpression(hookMap, expr, ...args) {
|
||||||
const exprName = this.getNameForExpression(expr);
|
const exprName = this.getMemberExpressionInfo(expr, ["expression"]);
|
||||||
if (exprName !== undefined) {
|
if (exprName !== undefined) {
|
||||||
return this.callHooksForInfoWithFallback(
|
return this.callHooksForInfoWithFallback(
|
||||||
hookMap,
|
hookMap,
|
||||||
|
@ -2235,7 +2350,7 @@ class JavascriptParser extends Parser {
|
||||||
* @template T
|
* @template T
|
||||||
* @template R
|
* @template R
|
||||||
* @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
|
* @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
|
||||||
* @param {ExpressionNode} expr expression info
|
* @param {MemberExpressionNode} expr expression info
|
||||||
* @param {function(string, string | ScopeInfo | VariableInfo, function(): string[]): any} fallback callback when variable in not handled by hooks
|
* @param {function(string, string | ScopeInfo | VariableInfo, function(): string[]): any} fallback callback when variable in not handled by hooks
|
||||||
* @param {function(string): any} defined callback when variable is defined
|
* @param {function(string): any} defined callback when variable is defined
|
||||||
* @param {AsArray<T>} args args for the hook
|
* @param {AsArray<T>} args args for the hook
|
||||||
|
@ -2248,7 +2363,7 @@ class JavascriptParser extends Parser {
|
||||||
defined,
|
defined,
|
||||||
...args
|
...args
|
||||||
) {
|
) {
|
||||||
const exprName = this.getNameForExpression(expr);
|
const exprName = this.getMemberExpressionInfo(expr, ["expression"]);
|
||||||
if (exprName !== undefined) {
|
if (exprName !== undefined) {
|
||||||
return this.callHooksForInfoWithFallback(
|
return this.callHooksForInfoWithFallback(
|
||||||
hookMap,
|
hookMap,
|
||||||
|
@ -2677,6 +2792,7 @@ class JavascriptParser extends Parser {
|
||||||
isStrict: false,
|
isStrict: false,
|
||||||
definitions: new StackedMap()
|
definitions: new StackedMap()
|
||||||
};
|
};
|
||||||
|
/** @type {ParserState} */
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.comments = comments;
|
this.comments = comments;
|
||||||
this.semicolons = semicolons;
|
this.semicolons = semicolons;
|
||||||
|
@ -2691,6 +2807,7 @@ class JavascriptParser extends Parser {
|
||||||
}
|
}
|
||||||
this.hooks.finish.call(ast, comments);
|
this.hooks.finish.call(ast, comments);
|
||||||
this.scope = oldScope;
|
this.scope = oldScope;
|
||||||
|
/** @type {ParserState} */
|
||||||
this.state = oldState;
|
this.state = oldState;
|
||||||
this.comments = oldComments;
|
this.comments = oldComments;
|
||||||
this.semicolons = oldSemicolons;
|
this.semicolons = oldSemicolons;
|
||||||
|
@ -2843,60 +2960,112 @@ class JavascriptParser extends Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ExpressionNode} expression an expression
|
* @param {MemberExpressionNode} expression an member expression
|
||||||
* @returns {{ name: string, rootInfo: ExportedVariableInfo, getMembers: () => string[]}} name info
|
* @returns {{ members: string[], object: ExpressionNode | SuperNode }} member names (reverse order) and remaining object
|
||||||
*/
|
*/
|
||||||
getNameForExpression(expression) {
|
extractMemberExpressionChain(expression) {
|
||||||
|
/** @type {AnyNode} */
|
||||||
let expr = expression;
|
let expr = expression;
|
||||||
const exprName = [];
|
const members = [];
|
||||||
while (expr.type === "MemberExpression") {
|
while (expr.type === "MemberExpression") {
|
||||||
if (expr.object.type === "Super") return undefined;
|
|
||||||
if (expr.computed) {
|
if (expr.computed) {
|
||||||
if (expr.property.type !== "Literal") break;
|
if (expr.property.type !== "Literal") break;
|
||||||
exprName.push(`${expr.property.value}`);
|
members.push(`${expr.property.value}`);
|
||||||
} else {
|
} else {
|
||||||
if (expr.property.type !== "Identifier") break;
|
if (expr.property.type !== "Identifier") break;
|
||||||
exprName.push(expr.property.name);
|
members.push(expr.property.name);
|
||||||
}
|
}
|
||||||
expr = expr.object;
|
expr = expr.object;
|
||||||
}
|
}
|
||||||
let rootName;
|
|
||||||
if (expr.type === "Identifier") {
|
|
||||||
rootName = expr.name;
|
|
||||||
} else if (expr.type === "ThisExpression") {
|
|
||||||
rootName = "this";
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
const rootInfo = this.getVariableInfo(rootName);
|
|
||||||
/** @type {string | ScopeInfo | true} */
|
|
||||||
let resolvedRoot;
|
|
||||||
if (rootInfo instanceof VariableInfo) {
|
|
||||||
resolvedRoot = rootInfo.freeName;
|
|
||||||
} else {
|
|
||||||
resolvedRoot = rootInfo;
|
|
||||||
}
|
|
||||||
if (typeof resolvedRoot !== "string") {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
let name = resolvedRoot;
|
|
||||||
for (let i = exprName.length - 1; i >= 0; i--) {
|
|
||||||
name = name + "." + exprName[i];
|
|
||||||
}
|
|
||||||
let reversed = false;
|
|
||||||
return {
|
return {
|
||||||
name,
|
members,
|
||||||
rootInfo,
|
object: expr
|
||||||
getMembers: () => {
|
|
||||||
if (!reversed) {
|
|
||||||
exprName.reverse();
|
|
||||||
reversed = true;
|
|
||||||
}
|
|
||||||
return exprName;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} varName variable name
|
||||||
|
* @returns {{name: string, info: VariableInfo | string}} name of the free variable and variable info for that
|
||||||
|
*/
|
||||||
|
getFreeInfoFromVariable(varName) {
|
||||||
|
const info = this.getVariableInfo(varName);
|
||||||
|
let name;
|
||||||
|
if (info instanceof VariableInfo) {
|
||||||
|
name = info.freeName;
|
||||||
|
if (typeof name !== "string") return undefined;
|
||||||
|
} else if (typeof info !== "string") {
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
name = info;
|
||||||
|
}
|
||||||
|
return { info, name };
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @typedef {{ type: "call", call: CallExpressionNode, calleeName: string, rootInfo: string | VariableInfo, getCalleeMembers: () => string[], name: string, getMembers: () => string[]}} CallExpressionInfo */
|
||||||
|
/** @typedef {{ type: "expression", rootInfo: string | VariableInfo, name: string, getMembers: () => string[]}} ExpressionExpressionInfo */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MemberExpressionNode} expression an member expression
|
||||||
|
* @param {("call"|"expression")[]} allowedTypes which types should be returned
|
||||||
|
* @returns {CallExpressionInfo | ExpressionExpressionInfo | undefined} expression info
|
||||||
|
*/
|
||||||
|
getMemberExpressionInfo(expression, allowedTypes) {
|
||||||
|
const possibleTypes = new Set(allowedTypes);
|
||||||
|
const { object, members } = this.extractMemberExpressionChain(expression);
|
||||||
|
switch (object.type) {
|
||||||
|
case "CallExpression": {
|
||||||
|
if (!possibleTypes.has("call")) return undefined;
|
||||||
|
let callee = object.callee;
|
||||||
|
let rootMembers = EMPTY_ARRAY;
|
||||||
|
if (callee.type === "MemberExpression") {
|
||||||
|
({
|
||||||
|
object: callee,
|
||||||
|
members: rootMembers
|
||||||
|
} = this.extractMemberExpressionChain(callee));
|
||||||
|
}
|
||||||
|
const rootName = getRootName(callee);
|
||||||
|
if (!rootName) return undefined;
|
||||||
|
const result = this.getFreeInfoFromVariable(rootName);
|
||||||
|
if (!result) return undefined;
|
||||||
|
const { info: rootInfo, name: resolvedRoot } = result;
|
||||||
|
const calleeName = objectAndMembersToName(resolvedRoot, rootMembers);
|
||||||
|
return {
|
||||||
|
type: "call",
|
||||||
|
call: object,
|
||||||
|
calleeName,
|
||||||
|
rootInfo,
|
||||||
|
getCalleeMembers: memorize(() => rootMembers.reverse()),
|
||||||
|
name: objectAndMembersToName(`${calleeName}()`, members),
|
||||||
|
getMembers: memorize(() => members.reverse())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case "Identifier":
|
||||||
|
case "ThisExpression": {
|
||||||
|
if (!possibleTypes.has("expression")) return undefined;
|
||||||
|
const rootName = getRootName(object);
|
||||||
|
if (!rootName) return undefined;
|
||||||
|
|
||||||
|
const result = this.getFreeInfoFromVariable(rootName);
|
||||||
|
if (!result) return undefined;
|
||||||
|
const { info: rootInfo, name: resolvedRoot } = result;
|
||||||
|
return {
|
||||||
|
type: "expression",
|
||||||
|
name: objectAndMembersToName(resolvedRoot, members),
|
||||||
|
rootInfo,
|
||||||
|
getMembers: memorize(() => members.reverse())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MemberExpressionNode} expression an expression
|
||||||
|
* @returns {{ name: string, rootInfo: ExportedVariableInfo, getMembers: () => string[]}} name info
|
||||||
|
*/
|
||||||
|
getNameForExpression(expression) {
|
||||||
|
return this.getMemberExpressionInfo(expression, ["expression"]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} code source code
|
* @param {string} code source code
|
||||||
* @param {ParseOptions} options parsing options
|
* @param {ParseOptions} options parsing options
|
||||||
|
|
|
@ -44,6 +44,8 @@ class JsonParser extends Parser {
|
||||||
state.module.buildInfo.jsonData = data;
|
state.module.buildInfo.jsonData = data;
|
||||||
state.module.buildInfo.strict = true;
|
state.module.buildInfo.strict = true;
|
||||||
state.module.buildMeta.exportsType = "default";
|
state.module.buildMeta.exportsType = "default";
|
||||||
|
state.module.buildMeta.defaultObject =
|
||||||
|
typeof data === "object" ? "redirect-warn" : false;
|
||||||
state.module.addDependency(
|
state.module.addDependency(
|
||||||
new JsonExportsDependency(JsonExportsDependency.getExportsFromData(data))
|
new JsonExportsDependency(JsonExportsDependency.getExportsFromData(data))
|
||||||
);
|
);
|
||||||
|
|
|
@ -232,48 +232,50 @@ const getExternalImport = (
|
||||||
? ""
|
? ""
|
||||||
: Template.toNormalComment(`${exportName.join(".")}`);
|
: Template.toNormalComment(`${exportName.join(".")}`);
|
||||||
let exprStart;
|
let exprStart;
|
||||||
|
const exportsType = importedModule.getExportsType(strictHarmonyModule);
|
||||||
if (exportName.length === 0) {
|
if (exportName.length === 0) {
|
||||||
switch (importedModule.buildMeta.exportsType) {
|
switch (exportsType) {
|
||||||
case "default":
|
case "dynamic-default":
|
||||||
|
case "default-only":
|
||||||
|
case "default-with-named":
|
||||||
info.interopNamespaceObjectUsed = true;
|
info.interopNamespaceObjectUsed = true;
|
||||||
exprStart = info.interopNamespaceObjectName;
|
exprStart = info.interopNamespaceObjectName;
|
||||||
break;
|
break;
|
||||||
case "namespace":
|
case "namespace":
|
||||||
exprStart = info.name;
|
exprStart = info.name;
|
||||||
break;
|
break;
|
||||||
|
case "dynamic":
|
||||||
|
exprStart = info.name;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (strictHarmonyModule) {
|
throw new Error(`Unexpected exportsType ${exportsType}`);
|
||||||
info.interopNamespaceObjectUsed = true;
|
|
||||||
exprStart = info.interopNamespaceObjectName;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
exprStart = info.name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (importedModule.buildMeta.exportsType) {
|
switch (exportsType) {
|
||||||
case "default":
|
case "default-with-named":
|
||||||
case "namespace":
|
case "namespace":
|
||||||
break;
|
break;
|
||||||
default:
|
case "default-only":
|
||||||
if (strictHarmonyModule) {
|
case "dynamic-default":
|
||||||
if (exportName[0] === "default") {
|
if (exportName[0] === "default") {
|
||||||
exprStart = info.name;
|
exprStart = info.name;
|
||||||
} else {
|
|
||||||
exprStart = "/* non-default import from non-esm module */undefined";
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (exportName[0] === "default") {
|
exprStart =
|
||||||
info.interopDefaultAccessUsed = true;
|
"/* non-default import from default-exporting module */undefined";
|
||||||
exprStart = asCall
|
|
||||||
? `${info.interopDefaultAccessName}()`
|
|
||||||
: asiSafe
|
|
||||||
? `(${info.interopDefaultAccessName}())`
|
|
||||||
: `${info.interopDefaultAccessName}.a`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "dynamic":
|
||||||
|
if (exportName[0] === "default") {
|
||||||
|
info.interopDefaultAccessUsed = true;
|
||||||
|
exprStart = asCall
|
||||||
|
? `${info.interopDefaultAccessName}()`
|
||||||
|
: asiSafe
|
||||||
|
? `(${info.interopDefaultAccessName}())`
|
||||||
|
: `${info.interopDefaultAccessName}.a`;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unexpected exportsType ${exportsType}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (exprStart) {
|
if (exprStart) {
|
||||||
|
@ -978,6 +980,7 @@ class ConcatenatedModule extends Module {
|
||||||
info.name = externalName;
|
info.name = externalName;
|
||||||
if (
|
if (
|
||||||
info.module.buildMeta.exportsType === "default" ||
|
info.module.buildMeta.exportsType === "default" ||
|
||||||
|
info.module.buildMeta.exportsType === "flagged" ||
|
||||||
!info.module.buildMeta.exportsType
|
!info.module.buildMeta.exportsType
|
||||||
) {
|
) {
|
||||||
const externalNameInterop = this.findNewName(
|
const externalNameInterop = this.findNewName(
|
||||||
|
@ -1090,7 +1093,10 @@ class ConcatenatedModule extends Module {
|
||||||
result.add(
|
result.add(
|
||||||
`var ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${info.name}, 2);\n`
|
`var ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${info.name}, 2);\n`
|
||||||
);
|
);
|
||||||
} else if (!info.module.buildMeta.exportsType) {
|
} else if (
|
||||||
|
info.module.buildMeta.exportsType === "flagged" ||
|
||||||
|
!info.module.buildMeta.exportsType
|
||||||
|
) {
|
||||||
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
||||||
result.add(
|
result.add(
|
||||||
`var ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${info.name});\n`
|
`var ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${info.name});\n`
|
||||||
|
|
|
@ -6,7 +6,11 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { UsageState } = require("../ModuleGraph");
|
const { UsageState } = require("../ModuleGraph");
|
||||||
const { numberToIdentifier } = require("../Template");
|
const {
|
||||||
|
numberToIdentifier,
|
||||||
|
NUMBER_OF_IDENTIFIER_START_CHARS,
|
||||||
|
NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS
|
||||||
|
} = require("../Template");
|
||||||
const { assignDeterministicIds } = require("../ids/IdHelpers");
|
const { assignDeterministicIds } = require("../ids/IdHelpers");
|
||||||
const {
|
const {
|
||||||
concatComparators,
|
concatComparators,
|
||||||
|
@ -62,7 +66,7 @@ const mangleExportsInfo = (exportsInfo, canBeArray) => {
|
||||||
// Don't rename 1-2 char exports or exports that can't be mangled
|
// Don't rename 1-2 char exports or exports that can't be mangled
|
||||||
for (const exportInfo of exportsInfo.ownedExports) {
|
for (const exportInfo of exportsInfo.ownedExports) {
|
||||||
const name = exportInfo.name;
|
const name = exportInfo.name;
|
||||||
if (typeof exportInfo.usedName !== "string") {
|
if (exportInfo.usedName === null) {
|
||||||
if (
|
if (
|
||||||
exportInfo.canMangle !== true ||
|
exportInfo.canMangle !== true ||
|
||||||
(name.length === 1 && /^[a-zA-Z0-9_$]/.test(name)) ||
|
(name.length === 1 && /^[a-zA-Z0-9_$]/.test(name)) ||
|
||||||
|
@ -76,7 +80,8 @@ const mangleExportsInfo = (exportsInfo, canBeArray) => {
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
exportInfo.exportsInfoOwned &&
|
exportInfo.exportsInfoOwned &&
|
||||||
exportInfo.used === UsageState.OnlyPropertiesUsed
|
(exportInfo.used === UsageState.OnlyPropertiesUsed ||
|
||||||
|
exportInfo.used === UsageState.Unused)
|
||||||
) {
|
) {
|
||||||
mangleExportsInfo(exportInfo.exportsInfo, true);
|
mangleExportsInfo(exportInfo.exportsInfo, true);
|
||||||
}
|
}
|
||||||
|
@ -93,8 +98,11 @@ const mangleExportsInfo = (exportsInfo, canBeArray) => {
|
||||||
e.usedName = name;
|
e.usedName = name;
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
[26, 52],
|
[
|
||||||
52,
|
NUMBER_OF_IDENTIFIER_START_CHARS,
|
||||||
|
NUMBER_OF_IDENTIFIER_START_CHARS * NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS
|
||||||
|
],
|
||||||
|
NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS,
|
||||||
usedNames.size
|
usedNames.size
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,8 +32,14 @@ module.exports = {
|
||||||
require("../dependencies/CachedConstDependency"),
|
require("../dependencies/CachedConstDependency"),
|
||||||
"dependencies/CommonJsRequireContextDependency": () =>
|
"dependencies/CommonJsRequireContextDependency": () =>
|
||||||
require("../dependencies/CommonJsRequireContextDependency"),
|
require("../dependencies/CommonJsRequireContextDependency"),
|
||||||
|
"dependencies/CommonJsExportsDependency": () =>
|
||||||
|
require("../dependencies/CommonJsExportsDependency"),
|
||||||
|
"dependencies/CommonJsFullRequireDependency": () =>
|
||||||
|
require("../dependencies/CommonJsFullRequireDependency"),
|
||||||
"dependencies/CommonJsRequireDependency": () =>
|
"dependencies/CommonJsRequireDependency": () =>
|
||||||
require("../dependencies/CommonJsRequireDependency"),
|
require("../dependencies/CommonJsRequireDependency"),
|
||||||
|
"dependencies/CommonJsSelfReferenceDependency": () =>
|
||||||
|
require("../dependencies/CommonJsSelfReferenceDependency"),
|
||||||
"dependencies/ConstDependency": () =>
|
"dependencies/ConstDependency": () =>
|
||||||
require("../dependencies/ConstDependency"),
|
require("../dependencies/ConstDependency"),
|
||||||
"dependencies/ContextDependency": () =>
|
"dependencies/ContextDependency": () =>
|
||||||
|
|
|
@ -57,6 +57,7 @@ class AsyncWebAssemblyJavascriptGenerator extends Generator {
|
||||||
runtimeRequirements
|
runtimeRequirements
|
||||||
} = generateContext;
|
} = generateContext;
|
||||||
runtimeRequirements.add(RuntimeGlobals.module);
|
runtimeRequirements.add(RuntimeGlobals.module);
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.moduleId);
|
||||||
runtimeRequirements.add(RuntimeGlobals.exports);
|
runtimeRequirements.add(RuntimeGlobals.exports);
|
||||||
runtimeRequirements.add(RuntimeGlobals.instantiateWasm);
|
runtimeRequirements.add(RuntimeGlobals.instantiateWasm);
|
||||||
/** @type {InitFragment[]} */
|
/** @type {InitFragment[]} */
|
||||||
|
@ -120,6 +121,7 @@ class AsyncWebAssemblyJavascriptGenerator extends Generator {
|
||||||
asiSafe: true,
|
asiSafe: true,
|
||||||
isCall: false,
|
isCall: false,
|
||||||
callContext: false,
|
callContext: false,
|
||||||
|
defaultInterop: true,
|
||||||
importVar,
|
importVar,
|
||||||
initFragments,
|
initFragments,
|
||||||
runtimeRequirements
|
runtimeRequirements
|
||||||
|
@ -143,7 +145,7 @@ class AsyncWebAssemblyJavascriptGenerator extends Generator {
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const instantiateCall =
|
const instantiateCall =
|
||||||
`${RuntimeGlobals.instantiateWasm}(${module.exportsArgument}, ${module.moduleArgument}.i` +
|
`${RuntimeGlobals.instantiateWasm}(${module.exportsArgument}, ${module.moduleArgument}.id` +
|
||||||
(importsObj ? `, ${importsObj})` : `)`);
|
(importsObj ? `, ${importsObj})` : `)`);
|
||||||
|
|
||||||
const source = new RawSource(
|
const source = new RawSource(
|
||||||
|
|
|
@ -100,6 +100,7 @@ class WebAssemblyJavascriptGenerator extends Generator {
|
||||||
asiSafe: true,
|
asiSafe: true,
|
||||||
isCall: false,
|
isCall: false,
|
||||||
callContext: null,
|
callContext: null,
|
||||||
|
defaultInterop: true,
|
||||||
initFragments,
|
initFragments,
|
||||||
runtimeRequirements
|
runtimeRequirements
|
||||||
})
|
})
|
||||||
|
@ -127,6 +128,7 @@ class WebAssemblyJavascriptGenerator extends Generator {
|
||||||
asiSafe: true,
|
asiSafe: true,
|
||||||
isCall: false,
|
isCall: false,
|
||||||
callContext: null,
|
callContext: null,
|
||||||
|
defaultInterop: true,
|
||||||
initFragments,
|
initFragments,
|
||||||
runtimeRequirements
|
runtimeRequirements
|
||||||
})};`,
|
})};`,
|
||||||
|
@ -164,6 +166,7 @@ class WebAssemblyJavascriptGenerator extends Generator {
|
||||||
|
|
||||||
// need these globals
|
// need these globals
|
||||||
runtimeRequirements.add(RuntimeGlobals.module);
|
runtimeRequirements.add(RuntimeGlobals.module);
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.moduleId);
|
||||||
runtimeRequirements.add(RuntimeGlobals.wasmInstances);
|
runtimeRequirements.add(RuntimeGlobals.wasmInstances);
|
||||||
if (exportsInfo.otherExportsInfo.used !== UsageState.Unused) {
|
if (exportsInfo.otherExportsInfo.used !== UsageState.Unused) {
|
||||||
runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject);
|
runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject);
|
||||||
|
@ -178,7 +181,7 @@ class WebAssemblyJavascriptGenerator extends Generator {
|
||||||
[
|
[
|
||||||
'"use strict";',
|
'"use strict";',
|
||||||
"// Instantiate WebAssembly module",
|
"// Instantiate WebAssembly module",
|
||||||
`var wasmExports = ${RuntimeGlobals.wasmInstances}[${module.moduleArgument}.i];`,
|
`var wasmExports = ${RuntimeGlobals.wasmInstances}[${module.moduleArgument}.id];`,
|
||||||
|
|
||||||
exportsInfo.otherExportsInfo.used !== UsageState.Unused
|
exportsInfo.otherExportsInfo.used !== UsageState.Unused
|
||||||
? `${RuntimeGlobals.makeNamespaceObject}(${module.exportsArgument});`
|
? `${RuntimeGlobals.makeNamespaceObject}(${module.exportsArgument});`
|
||||||
|
|
|
@ -188,7 +188,7 @@ it("should emit warning for require.main.require", async () => {
|
||||||
"errors": Array [],
|
"errors": Array [],
|
||||||
"warnings": Array [
|
"warnings": Array [
|
||||||
Object {
|
Object {
|
||||||
"loc": "1:0-20",
|
"loc": "1:0-30",
|
||||||
"message": "require.main.require is not supported by webpack.",
|
"message": "require.main.require is not supported by webpack.",
|
||||||
"moduleId": 0,
|
"moduleId": 0,
|
||||||
"moduleIdentifier": "<cwd>/test/fixtures/errors/require.main.require.js",
|
"moduleIdentifier": "<cwd>/test/fixtures/errors/require.main.require.js",
|
||||||
|
@ -207,7 +207,7 @@ it("should emit warning for module.parent.require", async () => {
|
||||||
"errors": Array [],
|
"errors": Array [],
|
||||||
"warnings": Array [
|
"warnings": Array [
|
||||||
Object {
|
Object {
|
||||||
"loc": "1:0-21",
|
"loc": "1:0-31",
|
||||||
"message": "module.parent.require is not supported by webpack.",
|
"message": "module.parent.require is not supported by webpack.",
|
||||||
"moduleId": 0,
|
"moduleId": 0,
|
||||||
"moduleIdentifier": "<cwd>/test/fixtures/errors/module.parent.require.js",
|
"moduleIdentifier": "<cwd>/test/fixtures/errors/module.parent.require.js",
|
||||||
|
|
|
@ -202,10 +202,10 @@ describe("Stats", () => {
|
||||||
"comparedForEmit": false,
|
"comparedForEmit": false,
|
||||||
"emitted": true,
|
"emitted": true,
|
||||||
"info": Object {
|
"info": Object {
|
||||||
"size": 198,
|
"size": 182,
|
||||||
},
|
},
|
||||||
"name": "entryA.js",
|
"name": "entryA.js",
|
||||||
"size": 198,
|
"size": 182,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"auxiliaryChunkIdHints": Array [],
|
"auxiliaryChunkIdHints": Array [],
|
||||||
|
@ -217,10 +217,10 @@ describe("Stats", () => {
|
||||||
"comparedForEmit": false,
|
"comparedForEmit": false,
|
||||||
"emitted": true,
|
"emitted": true,
|
||||||
"info": Object {
|
"info": Object {
|
||||||
"size": 1881,
|
"size": 1865,
|
||||||
},
|
},
|
||||||
"name": "entryB.js",
|
"name": "entryB.js",
|
||||||
"size": 1881,
|
"size": 1865,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"assetsByChunkName": Object {
|
"assetsByChunkName": Object {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports.func = function f() {
|
||||||
|
"use strict";
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
module.exports.abc = "abc";
|
|
@ -0,0 +1,7 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
|
||||||
|
function f(m) {
|
||||||
|
m.exports = { abc: "abc", def: "def" };
|
||||||
|
}
|
||||||
|
|
||||||
|
f(module);
|
|
@ -0,0 +1,6 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
|
||||||
|
var newObj = {};
|
||||||
|
exports = newObj;
|
||||||
|
|
||||||
|
exports.def = "def";
|
|
@ -0,0 +1,6 @@
|
||||||
|
Object.defineProperty(exports, "abc", { value: "abc" });
|
||||||
|
|
||||||
|
var newObj = {};
|
||||||
|
exports = newObj;
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "def", { value: "def" });
|
|
@ -0,0 +1,10 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
|
||||||
|
Object.defineProperties(module, {
|
||||||
|
exports: {
|
||||||
|
value: {
|
||||||
|
abc: "abc",
|
||||||
|
def: "def"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,8 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
|
||||||
|
Object.defineProperty(module, "exports", {
|
||||||
|
value: {
|
||||||
|
abc: "abc",
|
||||||
|
def: "def"
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,56 @@
|
||||||
|
it("should bailout when reading whole exports object from this", () => {
|
||||||
|
var test = require("./reading-this").test;
|
||||||
|
expect(test().abc).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should bailout when reading whole exports object from exports", () => {
|
||||||
|
var test = require("./reading-exports").test;
|
||||||
|
expect(test().abc).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should bailout when reading whole exports object from module.exports", () => {
|
||||||
|
var test = require("./reading-module-exports").test;
|
||||||
|
expect(test().abc).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should reassigning exports (assign values)", () => {
|
||||||
|
expect(require("./assign-exports-assign?1").abc).toBe("abc");
|
||||||
|
expect(require("./assign-exports-assign?2").def).toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should reassigning exports (define values)", () => {
|
||||||
|
expect(require("./assign-exports-define").abc).toBe("abc");
|
||||||
|
expect(require("./assign-exports-define").def).toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not mangle or remove nested properties", () => {
|
||||||
|
expect(require("./nested-property").abc).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be able to access the exports via call context", () => {
|
||||||
|
expect(require("./accessing-call-context?1").func().abc).toBe("abc");
|
||||||
|
var cc = require("./accessing-call-context?2");
|
||||||
|
expect(cc.func().abc).toBe("abc");
|
||||||
|
var func = require("./accessing-call-context?3").func;
|
||||||
|
expect(func()).toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be able to define an exports property on module (property)", () => {
|
||||||
|
expect(require("./define-module-property?2").abc).toBe("abc");
|
||||||
|
expect(require("./define-module-property?1").def).toBe("def");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be able to define an exports property on module (properties)", () => {
|
||||||
|
expect(require("./define-module-properties?2").abc).toBe("abc");
|
||||||
|
expect(require("./define-module-properties?1").def).toBe("def");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be able to do stuff with the module object", () => {
|
||||||
|
expect(require("./accessing-module?2").abc).toBe("abc");
|
||||||
|
expect(require("./accessing-module?1").def).toBe("def");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be able to use AMD to define exports", () => {
|
||||||
|
expect(require("./using-amd?2").abc).toBe("abc");
|
||||||
|
expect(require("./using-amd?1").def).toBe("def");
|
||||||
|
});
|
|
@ -0,0 +1,8 @@
|
||||||
|
var abc = {};
|
||||||
|
|
||||||
|
module.exports = abc;
|
||||||
|
|
||||||
|
module.exports.abc = "abc";
|
||||||
|
module.exports.def = "def";
|
||||||
|
|
||||||
|
expect(abc).toEqual({ abc: "abc", def: "def" });
|
|
@ -0,0 +1,5 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
|
||||||
|
exports.test = function() {
|
||||||
|
return exports;
|
||||||
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
|
||||||
|
exports.test = function() {
|
||||||
|
return module.exports;
|
||||||
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
|
||||||
|
exports.test = () => {
|
||||||
|
return this;
|
||||||
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
exports.abc = "not-abc";
|
||||||
|
define({
|
||||||
|
abc: "abc",
|
||||||
|
def: "def"
|
||||||
|
});
|
|
@ -0,0 +1,10 @@
|
||||||
|
it("should allow to require esm", () => {
|
||||||
|
expect(require("./module?1").abc).toBe("abc");
|
||||||
|
expect(typeof require("./module?2").func).toBe("function");
|
||||||
|
// check if a function called with a namespace object as context
|
||||||
|
// still yield the same optimization, compared to only accessing
|
||||||
|
// the export
|
||||||
|
expect(Object.keys(require("./module?3").func())).toEqual(
|
||||||
|
Object.keys(require.cache[require.resolve("./module?2")].exports)
|
||||||
|
);
|
||||||
|
});
|
|
@ -0,0 +1,6 @@
|
||||||
|
export const abc = "abc";
|
||||||
|
export const def = "def";
|
||||||
|
export const func = function() {
|
||||||
|
"use strict";
|
||||||
|
return this;
|
||||||
|
};
|
|
@ -0,0 +1,9 @@
|
||||||
|
import m1 from "./module?1";
|
||||||
|
import m2 from "./module?2";
|
||||||
|
import { abc } from "./module?3";
|
||||||
|
|
||||||
|
it("should allow to import cjs with esm", () => {
|
||||||
|
expect(m1.abc).toBe("abc");
|
||||||
|
expect(m2).toEqual({ abc: "abc", def: "def" });
|
||||||
|
expect(abc).toBe("abc");
|
||||||
|
});
|
|
@ -0,0 +1,2 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
exports.def = "def";
|
|
@ -0,0 +1,2 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
exports.def = "def";
|
|
@ -0,0 +1,2 @@
|
||||||
|
module.exports.abc = "abc";
|
||||||
|
module.exports.def = "def";
|
|
@ -0,0 +1,2 @@
|
||||||
|
this.abc = "abc";
|
||||||
|
this.def = "def";
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = () => "abc";
|
||||||
|
|
||||||
|
module.exports.def = "def";
|
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = function() {
|
||||||
|
return "abc";
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.def = "def";
|
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = {
|
||||||
|
abc: "abc"
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.def = "def";
|
|
@ -0,0 +1,2 @@
|
||||||
|
Object.defineProperty(exports, "abc", { enumerable: true, value: "abc" });
|
||||||
|
Object.defineProperty(exports, "def", { enumerable: true, value: "def" });
|
|
@ -0,0 +1,8 @@
|
||||||
|
Object.defineProperty(module.exports, "abc", {
|
||||||
|
enumerable: true,
|
||||||
|
value: "abc"
|
||||||
|
});
|
||||||
|
Object.defineProperty(module.exports, "def", {
|
||||||
|
enumerable: true,
|
||||||
|
value: "def"
|
||||||
|
});
|
|
@ -0,0 +1,2 @@
|
||||||
|
Object.defineProperty(this, "abc", { enumerable: true, value: "abc" });
|
||||||
|
Object.defineProperty(this, "def", { enumerable: true, value: "def" });
|
|
@ -0,0 +1,83 @@
|
||||||
|
it("should allow to export via exports", () => {
|
||||||
|
expect(require("./assign-exports-property?1").abc).toBe("abc");
|
||||||
|
expect(require("./assign-exports-property?2")).toEqual({
|
||||||
|
abc: "abc",
|
||||||
|
def: "def"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to export via module.exports", () => {
|
||||||
|
expect(require("./assign-module-exports-property?1").abc).toBe("abc");
|
||||||
|
expect(require("./assign-module-exports-property?2")).toEqual({
|
||||||
|
abc: "abc",
|
||||||
|
def: "def"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to export via this", () => {
|
||||||
|
expect(require("./assign-this-property?1").abc).toBe("abc");
|
||||||
|
expect(require("./assign-this-property?2")).toEqual({
|
||||||
|
abc: "abc",
|
||||||
|
def: "def"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to export via define property on exports", () => {
|
||||||
|
expect(require("./define-exports-property?1").abc).toBe("abc");
|
||||||
|
expect(require("./define-exports-property?2")).toEqual({
|
||||||
|
abc: "abc",
|
||||||
|
def: "def"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to export via define property on module.exports", () => {
|
||||||
|
expect(require("./define-module-exports-property?1").abc).toBe("abc");
|
||||||
|
expect(require("./define-module-exports-property?2")).toEqual({
|
||||||
|
abc: "abc",
|
||||||
|
def: "def"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to export via define property on this", () => {
|
||||||
|
expect(require("./define-this-property?1").abc).toBe("abc");
|
||||||
|
expect(require("./define-this-property?2")).toEqual({
|
||||||
|
abc: "abc",
|
||||||
|
def: "def"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to read own exports via exports", () => {
|
||||||
|
var test = require("./reading-self-from-exports").test;
|
||||||
|
expect(test()).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to read own exports via module.exports", () => {
|
||||||
|
var test = require("./reading-self-from-module-exports").test;
|
||||||
|
expect(test()).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to read own exports via this", () => {
|
||||||
|
var test = require("./reading-self-from-this").test;
|
||||||
|
expect(test()).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to attach exports to object", () => {
|
||||||
|
expect(require("./attach-to-object?1").abc).toBe("abc");
|
||||||
|
expect(require("./attach-to-object?2").def).toBe("def");
|
||||||
|
expect(require("./attach-to-object?3").abc).toBe("abc");
|
||||||
|
expect(require("./attach-to-object?3").def).toBe("def");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to attach exports to function", () => {
|
||||||
|
expect(require("./attach-to-function?1")()).toBe("abc");
|
||||||
|
expect(require("./attach-to-function?2").def).toBe("def");
|
||||||
|
expect(require("./attach-to-function?3")()).toBe("abc");
|
||||||
|
expect(require("./attach-to-function?3").def).toBe("def");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to attach exports to arrow function", () => {
|
||||||
|
expect(require("./attach-to-arrow-function?1")()).toBe("abc");
|
||||||
|
expect(require("./attach-to-arrow-function?2").def).toBe("def");
|
||||||
|
expect(require("./attach-to-arrow-function?3")()).toBe("abc");
|
||||||
|
expect(require("./attach-to-arrow-function?3").def).toBe("def");
|
||||||
|
});
|
|
@ -0,0 +1,5 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
|
||||||
|
exports.test = function() {
|
||||||
|
return exports.abc;
|
||||||
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
|
||||||
|
exports.test = function() {
|
||||||
|
return module.exports.abc;
|
||||||
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
|
||||||
|
exports.test = () => {
|
||||||
|
return this.abc;
|
||||||
|
};
|
|
@ -0,0 +1,15 @@
|
||||||
|
it("should be able to import a module via require and property", () => {
|
||||||
|
expect(require("./module").abc).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be able to import a module via require and destruct", () => {
|
||||||
|
var { abc } = require("./module");
|
||||||
|
expect(abc).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be able to import a module via require and exports object", () => {
|
||||||
|
var module1 = require("./module?1");
|
||||||
|
expect(module1.abc).toBe("abc");
|
||||||
|
var module2 = require("./module?2");
|
||||||
|
expect(module2).toEqual({ abc: "abc", def: "def" });
|
||||||
|
});
|
|
@ -0,0 +1,2 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
exports.def = "def";
|
|
@ -0,0 +1,33 @@
|
||||||
|
import module1 from "./module?1";
|
||||||
|
import module2, { a } from "./module?2";
|
||||||
|
|
||||||
|
it("should allow mutating imported modules (changing existing exports)", () => {
|
||||||
|
expect(module1.abc).toBe("abc");
|
||||||
|
expect(module1.def).toBe("def");
|
||||||
|
module1.abc = "new-abc";
|
||||||
|
expect(module1.abc).toBe("new-abc");
|
||||||
|
expect(module1.def).toBe("def");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow mutating imported modules (adding new properties)", () => {
|
||||||
|
expect(module2.abc).toBe("abc");
|
||||||
|
expect(module2.def).toBe("def");
|
||||||
|
expect(module2.ghi).toBe(undefined);
|
||||||
|
expect(module2.Oi).toBe(undefined);
|
||||||
|
expect(module2.a).toBe(undefined);
|
||||||
|
expect(a).toBe(undefined);
|
||||||
|
expect(module2[""]).toBe(undefined);
|
||||||
|
module2.ghi = "ghi";
|
||||||
|
module2.Oi = "Oi";
|
||||||
|
module2.a = "a";
|
||||||
|
module2[""] = {};
|
||||||
|
module2[""].abc = "abc";
|
||||||
|
expect(module2.abc).toBe("abc");
|
||||||
|
expect(module2.def).toBe("def");
|
||||||
|
expect(module2.ghi).toBe("ghi");
|
||||||
|
expect(module2.Oi).toBe("Oi");
|
||||||
|
expect(module2.a).toBe("a");
|
||||||
|
expect(a).toBe("a");
|
||||||
|
expect(module2[""]).toEqual({ abc: "abc" });
|
||||||
|
expect(module2[""].abc).toBe("abc");
|
||||||
|
});
|
|
@ -0,0 +1,2 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
exports.def = "def";
|
|
@ -0,0 +1,25 @@
|
||||||
|
it("should allow to create namespace exports via __esModule on exports", async () => {
|
||||||
|
expect(await import("./namespace-via-exports")).toBe(
|
||||||
|
require("./namespace-via-exports")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should allow to create namespace exports via __esModule on literal", async () => {
|
||||||
|
expect(await import("./namespace-via-literal")).toBe(
|
||||||
|
require("./namespace-via-literal")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should allow to create namespace exports via __esModule with Object.defineProperty", async () => {
|
||||||
|
expect(await import("./namespace-via-define-property")).toBe(
|
||||||
|
require("./namespace-via-define-property")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should allow to create namespace exports via __esModule with Object.defineProperty minimized true", async () => {
|
||||||
|
expect(await import("./namespace-via-define-property-minimized")).toBe(
|
||||||
|
require("./namespace-via-define-property-minimized")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should allow to create namespace exports via __esModule with Object.defineProperties", async () => {
|
||||||
|
expect(await import("./namespace-via-define-properties")).toBe(
|
||||||
|
require("./namespace-via-define-properties")
|
||||||
|
);
|
||||||
|
});
|
|
@ -0,0 +1,5 @@
|
||||||
|
Object.defineProperties(exports, {
|
||||||
|
__esModule: { value: true },
|
||||||
|
abc: { enumerable: true, value: "abc" },
|
||||||
|
default: { enumerable: true, value: "default" }
|
||||||
|
});
|
|
@ -0,0 +1,3 @@
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: !0 });
|
||||||
|
exports.abc = "abc";
|
||||||
|
exports.default = "default";
|
|
@ -0,0 +1,3 @@
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.abc = "abc";
|
||||||
|
exports.default = "default";
|
|
@ -0,0 +1,3 @@
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.abc = "abc";
|
||||||
|
exports.default = "default";
|
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = {
|
||||||
|
__esModule: true,
|
||||||
|
abc: "abc",
|
||||||
|
default: "default"
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = {
|
||||||
|
abc: "abc",
|
||||||
|
def: "def"
|
||||||
|
};
|
|
@ -0,0 +1,9 @@
|
||||||
|
it("should be able to export an object literal", () => {
|
||||||
|
expect(require("./direct-object?1").abc).toBe("abc");
|
||||||
|
expect(require("./direct-object?2")).toEqual({ abc: "abc", def: "def" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be able to export an object literal indirect", () => {
|
||||||
|
expect(require("./indirect-object?1").abc).toBe("abc");
|
||||||
|
expect(require("./indirect-object?2")).toEqual({ abc: "abc", def: "def" });
|
||||||
|
});
|
|
@ -0,0 +1,6 @@
|
||||||
|
var value = {
|
||||||
|
abc: "abc",
|
||||||
|
def: "def"
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = value;
|
|
@ -0,0 +1,41 @@
|
||||||
|
it("should allow to reexport a exports object (this, exports)", () => {
|
||||||
|
expect(require("./reexport-whole-exports?1").m1.abc).toBe("abc");
|
||||||
|
expect(require("./reexport-whole-exports?2").m2.abc).toBe("abc");
|
||||||
|
expect(require("./reexport-whole-exports?3").m3.abc).toBe("abc");
|
||||||
|
expect(require("./reexport-whole-exports?4").m4.abc).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to reexport a exports object (module.exports, object literal)", () => {
|
||||||
|
expect(require("./reexport-whole-module-exports?1").m1.abc).toBe("abc");
|
||||||
|
expect(require("./reexport-whole-module-exports?2").m2.abc).toBe("abc");
|
||||||
|
expect(require("./reexport-whole-module-exports?3").m3.abc).toBe("abc");
|
||||||
|
expect(require("./reexport-whole-module-exports?4").m4.abc).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to reexport a imported property (this, exports)", () => {
|
||||||
|
expect(require("./reexport-property-exports?1").p1).toBe("abc");
|
||||||
|
expect(require("./reexport-property-exports?2").p2).toBe("abc");
|
||||||
|
expect(require("./reexport-property-exports?3").p3).toBe("abc");
|
||||||
|
expect(require("./reexport-property-exports?4").p4).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to reexport a imported property (module.exports, object literal)", () => {
|
||||||
|
expect(require("./reexport-property-module-exports?1").p1).toBe("abc");
|
||||||
|
expect(require("./reexport-property-module-exports?2").p2).toBe("abc");
|
||||||
|
expect(require("./reexport-property-module-exports?3").p3).toBe("abc");
|
||||||
|
expect(require("./reexport-property-module-exports?4").p4).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to reexport a reexported exports object (this, exports)", () => {
|
||||||
|
expect(require("./reexport-reexport-exports?1").x1.abc).toBe("abc");
|
||||||
|
expect(require("./reexport-reexport-exports?2").x2.abc).toBe("abc");
|
||||||
|
expect(require("./reexport-reexport-exports?3").x3.abc).toBe("abc");
|
||||||
|
expect(require("./reexport-reexport-exports?4").x4.abc).toBe("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow to reexport a reexported exports object (module.exports, object literal)", () => {
|
||||||
|
expect(require("./reexport-reexport-module-exports?1").x1.abc).toBe("abc");
|
||||||
|
expect(require("./reexport-reexport-module-exports?2").x2.abc).toBe("abc");
|
||||||
|
expect(require("./reexport-reexport-module-exports?3").x3.abc).toBe("abc");
|
||||||
|
expect(require("./reexport-reexport-module-exports?4").x4.abc).toBe("abc");
|
||||||
|
});
|
|
@ -0,0 +1,2 @@
|
||||||
|
exports.abc = "abc";
|
||||||
|
exports.def = "def";
|
|
@ -0,0 +1,6 @@
|
||||||
|
exports.p1 = require("./module?pe1").abc;
|
||||||
|
var m2 = require("./module?pe2");
|
||||||
|
exports.p2 = m2.abc;
|
||||||
|
this.p3 = require("./module?pe3").abc;
|
||||||
|
var m4 = require("./module?pe4");
|
||||||
|
this.p4 = m4.abc;
|
|
@ -0,0 +1,8 @@
|
||||||
|
var m2 = require("./module?pme2");
|
||||||
|
module.exports = {
|
||||||
|
p1: require("./module?pme1").abc,
|
||||||
|
p2: m2.abc
|
||||||
|
};
|
||||||
|
module.exports.p3 = require("./module?pme3").abc;
|
||||||
|
var m4 = require("./module?pme4");
|
||||||
|
module.exports.p4 = m4.abc;
|
|
@ -0,0 +1,6 @@
|
||||||
|
exports.x1 = require("./reexport-whole-exports?x1").m1;
|
||||||
|
var m2 = require("./reexport-whole-exports?x2");
|
||||||
|
exports.x2 = m2.m2;
|
||||||
|
this.x3 = require("./reexport-whole-exports?x3").m3;
|
||||||
|
var m4 = require("./reexport-whole-exports?x4");
|
||||||
|
this.x4 = m4.m4;
|
|
@ -0,0 +1,8 @@
|
||||||
|
var m2 = require("./reexport-whole-module-exports?x2");
|
||||||
|
module.exports = {
|
||||||
|
x1: require("./reexport-whole-module-exports?x1").m1,
|
||||||
|
x2: m2.m2
|
||||||
|
};
|
||||||
|
module.exports.x3 = require("./reexport-whole-module-exports?x3").m3;
|
||||||
|
var m4 = require("./reexport-whole-module-exports?x4");
|
||||||
|
module.exports.x4 = m4.m4;
|
|
@ -0,0 +1,6 @@
|
||||||
|
exports.m1 = require("./module?we1");
|
||||||
|
var m2 = require("./module?we2");
|
||||||
|
exports.m2 = m2;
|
||||||
|
this.m3 = require("./module?we3");
|
||||||
|
var m4 = require("./module?we4");
|
||||||
|
this.m4 = m4;
|
|
@ -0,0 +1,8 @@
|
||||||
|
var m2 = require("./module?wme2");
|
||||||
|
module.exports = {
|
||||||
|
m1: require("./module?wme1"),
|
||||||
|
m2
|
||||||
|
};
|
||||||
|
module.exports.m3 = require("./module?wme3");
|
||||||
|
var m4 = require("./module?wme4");
|
||||||
|
module.exports.m4 = m4;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue