Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5318930

Browse files
committed
feat: warn when modules are automatically converted to strict mode
- Add WarnStrictModeModulesPlugin to detect modules converted to strict mode- Track modules with explicit 'use strict' to avoid false warnings- Plugin is opt-in to avoid breaking existing builds
1 parent21b28a8 commit5318930

File tree

8 files changed

+229
-0
lines changed

8 files changed

+229
-0
lines changed

‎lib/ModuleStrictModeWarning.js‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
MIT License http://www.opensource.org/licenses/mit-license.php
3+
Author Tobias Koppers @sokra
4+
*/
5+
6+
"use strict";
7+
8+
constWebpackError=require("./WebpackError");
9+
10+
/**@typedef {import("./Module")} Module */
11+
/**@typedef {import("./RequestShortener")} RequestShortener */
12+
13+
/**
14+
* Warning for modules that webpack automatically converts to strict mode.
15+
* This typically happens when processing ES modules (import/export syntax).
16+
*/
17+
classModuleStrictModeWarningextendsWebpackError{
18+
/**
19+
*@param {Module} module module that was converted to strict mode
20+
*@param {RequestShortener} requestShortener request shortener
21+
*/
22+
constructor(module,requestShortener){
23+
constmessage=`Module '${module.readableIdentifier(
24+
requestShortener
25+
)}' was automatically converted to strict mode, which may break the module if it uses non-strict mode features`;
26+
super(message);
27+
28+
this.name="ModuleStrictModeWarning";
29+
this.module=module;
30+
}
31+
}
32+
33+
module.exports=ModuleStrictModeWarning;

‎lib/WarnStrictModeModulesPlugin.js‎

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
MIT License http://www.opensource.org/licenses/mit-license.php
3+
Author Tobias Koppers @sokra
4+
*/
5+
6+
"use strict";
7+
8+
constModuleStrictModeWarning=require("./ModuleStrictModeWarning");
9+
const{
10+
JAVASCRIPT_MODULE_TYPE_AUTO,
11+
JAVASCRIPT_MODULE_TYPE_DYNAMIC,
12+
JAVASCRIPT_MODULE_TYPE_ESM
13+
}=require("./ModuleTypeConstants");
14+
15+
/**@typedef {import("./Compiler")} Compiler */
16+
/**@typedef {import("./Module")} Module */
17+
/**@typedef {import("./NormalModule")} NormalModule */
18+
/**@typedef {import("./javascript/JavascriptParser")} JavascriptParser */
19+
20+
constPLUGIN_NAME="WarnStrictModeModulesPlugin";
21+
22+
/**
23+
* This plugin warns when webpack automatically converts modules to strict mode.
24+
* When webpack processes ES modules (import/export), it automatically enables strict mode
25+
* which can break code that relies on non-strict mode features.
26+
*/
27+
classWarnStrictModeModulesPlugin{
28+
/**
29+
* Apply the plugin
30+
*@param {Compiler} compiler the compiler instance
31+
*@returns {void}
32+
*/
33+
apply(compiler){
34+
compiler.hooks.compilation.tap(
35+
PLUGIN_NAME,
36+
(compilation,{ normalModuleFactory})=>{
37+
// Track modules that originally had "use strict" to avoid false warnings
38+
constmodulesWithOriginalUseStrict=newWeakSet();
39+
/**
40+
* Checks if a module is a JavaScript module that we should warn about
41+
*@param {Module} module the module to check
42+
*@returns {boolean} true if this is a JS module we should check
43+
*/
44+
constisJavaScriptModule=module=>
45+
Boolean(
46+
module.type&&
47+
(module.type===JAVASCRIPT_MODULE_TYPE_AUTO||
48+
module.type===JAVASCRIPT_MODULE_TYPE_DYNAMIC||
49+
module.type===JAVASCRIPT_MODULE_TYPE_ESM)
50+
);
51+
52+
/**
53+
* Parser handler to track modules with original "use strict"
54+
*@param {JavascriptParser} parser the parser
55+
*/
56+
consthandler=parser=>{
57+
parser.hooks.program.tap(PLUGIN_NAME,ast=>{
58+
constfirstNode=ast.body[0];
59+
if(
60+
firstNode&&
61+
firstNode.type==="ExpressionStatement"&&
62+
firstNode.expression.type==="Literal"&&
63+
firstNode.expression.value==="use strict"
64+
){
65+
// Module originally had "use strict" directive
66+
modulesWithOriginalUseStrict.add(parser.state.module);
67+
}
68+
});
69+
};
70+
71+
// Register handlers for all JavaScript module types
72+
normalModuleFactory.hooks.parser
73+
.for(JAVASCRIPT_MODULE_TYPE_AUTO)
74+
.tap(PLUGIN_NAME,handler);
75+
normalModuleFactory.hooks.parser
76+
.for(JAVASCRIPT_MODULE_TYPE_DYNAMIC)
77+
.tap(PLUGIN_NAME,handler);
78+
normalModuleFactory.hooks.parser
79+
.for(JAVASCRIPT_MODULE_TYPE_ESM)
80+
.tap(PLUGIN_NAME,handler);
81+
82+
// Generate warnings during seal phase
83+
// We check during seal to handle cached modules that weren't parsed in this compilation
84+
compilation.hooks.seal.tap(PLUGIN_NAME,()=>{
85+
for(constmoduleofcompilation.modules){
86+
if(
87+
module.buildInfo&&
88+
module.buildInfo.strict&&
89+
isJavaScriptModule(module)&&
90+
!modulesWithOriginalUseStrict.has(module)&&// For cached modules, check source for "use strict" directive
91+
module.originalSource
92+
){
93+
constoriginalSource=module.originalSource();
94+
if(originalSource){
95+
constsource=originalSource.source();
96+
if(typeofsource==="string"){
97+
// Check for "use strict" at the beginning of the file or after initial comments
98+
// This regex matches "use strict" that appears as a directive, not in comments
99+
consthasUseStrictDirective=
100+
/^(?:\/\*[\s\S]*?\*\/\s*|\/\/.*\n\s*)*["']usestrict["']/.test(
101+
source
102+
);
103+
104+
if(!hasUseStrictDirective){
105+
compilation.warnings.push(
106+
newModuleStrictModeWarning(
107+
module,
108+
compilation.requestShortener
109+
)
110+
);
111+
}
112+
}
113+
}
114+
}
115+
}
116+
});
117+
}
118+
);
119+
}
120+
}
121+
122+
module.exports=WarnStrictModeModulesPlugin;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// ESM module without "use strict"
2+
// This should trigger a warning
3+
4+
exportconstesmValue=42;
5+
6+
exportfunctiontest(){
7+
// This would fail in strict mode if we used arguments.callee
8+
return"esm module";
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"use strict";
2+
// ESM module already with "use strict"
3+
// This should NOT trigger a warning
4+
5+
exportconstesmStrictValue=42;
6+
7+
exportfunctiontest(){
8+
return"esm with strict";
9+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Test that warnings are generated for modules converted to strict mode
2+
import{esmValue}from"./esm-module";
3+
import{esmStrictValue}from"./esm-with-strict";
4+
5+
it("should import ESM modules",()=>{
6+
expect(esmValue).toBe(42);
7+
expect(esmStrictValue).toBe(42);
8+
});
9+
10+
it("should generate warning in stats",()=>{
11+
conststats=__STATS__;
12+
expect(stats.warnings).toBeDefined();
13+
expect(stats.warnings.length).toBeGreaterThan(0);
14+
15+
// Check that warning was generated for esm-module.js
16+
constwarnings=stats.warnings;
17+
conststrictModeWarning=warnings.find(w=>
18+
w.message&&w.message.includes("was automatically converted to strict mode")&&
19+
w.message.includes("esm-module.js")
20+
);
21+
22+
expect(strictModeWarning).toBeDefined();
23+
expect(strictModeWarning.message).toContain("esm-module.js");
24+
expect(strictModeWarning.message).toContain("was automatically converted to strict mode");
25+
26+
// Check that NO warning was generated for esm-with-strict.js
27+
conststrictModuleWarning=warnings.find(w=>
28+
w.message&&w.message.includes("was automatically converted to strict mode")&&
29+
w.message.includes("esm-with-strict.js")
30+
);
31+
32+
expect(strictModuleWarning).toBeUndefined();
33+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports={
2+
findBundle(i){
3+
return["./bundle0.js"];
4+
}
5+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module.exports=[
2+
// Warning for esm-module.js (no "use strict")
3+
{
4+
message:
5+
/Module'\.\/esm-module\.js'wasautomaticallyconvertedtostrictmode/
6+
},
7+
// Warning for index.js (uses ES modules)
8+
{
9+
message:/Module'\.\/index\.js'wasautomaticallyconvertedtostrictmode/
10+
}
11+
];
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
constWarnStrictModeModulesPlugin=require("../../../../lib/WarnStrictModeModulesPlugin");
2+
3+
/**@type {import("../../../../types").Configuration} */
4+
module.exports={
5+
mode:"production",
6+
plugins:[newWarnStrictModeModulesPlugin()]
7+
};

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp