Skip to content

Disable System.import parser plugin by default #6321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 18, 2018

Conversation

ooflorent
Copy link
Member

@ooflorent ooflorent commented Jan 15, 2018

What kind of change does this PR introduce?

refactor

Did you add tests for your changes?

yes

If relevant, link to documentation update:

TODO since the parser options are updated.

Summary

System.import is deprecated since version 2.1.0-beta.28. This PR disables System.import by default. Previously its support was opt-in. In order to enable it, the parser option system must be enabled:

This PR introduce a new warning if System.import() is used. The plugin can be toggled using a parser option:

module: {
  rules: [
    {
      test: /\.js$/,
      parser: {
        system: true // no warning
      }
    }
  ],
}

Possible system values:

  • default: Consider System.import() as import(). Emit a warning if System.import() is used.
  • true: Consider System.import() as import(). No warning.
  • false: System.import() is not intercepted. Using it most like triggers a TypeError

Does this PR introduce a breaking change?

yes (new warning)

Other information

cc @TheLarkInn @hansl @filipesilva

@@ -39,6 +39,11 @@ class SystemPlugin {
parser.state.module.context, require.resolve("../../buildin/system.js"));
return ParserHelpers.addParsedVariableToModule(parser, "System", systemPolyfillRequire);
});

parser.hooks.call.for("System.import").tap("SystemPlugin", expr => {
parser.hooks.importCall.call(expr);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This trick removes System.import handling from ImportPlugin by simulating an import() call.

@@ -15,7 +15,7 @@ class SystemPlugin {
normalModuleFactory
}) => {
const handler = (parser, parserOptions) => {
if(typeof parserOptions.system !== "undefined" && !parserOptions.system)
if(typeof parserOptions.system === "undefined" || !parserOptions.system)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlike other parser options, this one is disabled by default.

@TheLarkInn
Copy link
Member

Will users be warned they are using something that doesn't work anymore? My one concern: people use it thinking there is code splitting and it does nothing. Will this throw now?

@sokra
Copy link
Member

sokra commented Jan 16, 2018

Will users be warned they are using something that doesn't work anymore? My one concern: people use it thinking there is code splitting and it does nothing. Will this throw now?

Good point.

Maybe we should do this for webpack 4 until webpack 5.

system: true -> support System.import like import()
system: undefined -> support System.import like import() but prints errors
system: false -> ignores System.import

@ooflorent
Copy link
Member Author

@sokra working on it 👍

@ooflorent
Copy link
Member Author

I've also updated the PR message to describe the new behavior.


parser.hooks.call.for("System.import").tap("SystemPlugin", expr => {
if(shouldWarn) {
shouldWarn = false;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Emit the warning once. Only if System.import() is used somewhere.

@filipesilva
Copy link
Contributor

The behaviour described by @sokra works for Angular CLI 👍

@ooflorent
Copy link
Member Author

@filipesilva I've implemented it in this PR. The warning will be visible only if System.import is found.

this.name = "SystemImportDeprecationWarning";
this.message = "System.import() is deprecated and will be removed soon.\n" +
"Use import() or require.ensure() instead.\n" +
"For more info visit https://webpack.js.org/guides/code-splitting/";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should print a list of all modules using System.import.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about adding this to the warning and allow multiple emit?

this.origin = this.module = module;
this.originLoc = loc;

The above modification emits the following warnings:

System.import() is deprecated and will be removed soon. Use import() instead.
For more info visit https://webpack.js.org/guides/code-splitting/
 @ ./index.js 43:2-33

It may be better to debug these messages rather than a module list. What do you think?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I remove will be removed soon? I feel like it's a bit to much.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, that's better.

Add the warning to parser.scope.module.warnings instead of to the Compilation directly. This should ensure that it's correctly cached.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stats does not extract originLoc of Module#warnings; only Compilation#warnings. I'm unable to match the location into warnings.js when using parser.scope.module instead of compilation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought Module#warnings are added to Compilation#warnings after parsing...

@@ -36,7 +36,7 @@ module.exports = class NodeMainTemplatePlugin {
`${mainTemplate.requireFn}.oe = function(err) {`,
Template.indent([
"process.nextTick(function() {",
Template.indent("throw err; // catch this error by using System.import().catch()"),
Template.indent("throw err;"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// catch this error by using import().catch()

}, {
test: /\.js$/,
parser: {
system: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove all System.import calls in the hot test cases.

@@ -159,6 +159,11 @@ describe("TestCases", () => {
},
module: {
rules: [{
test: /\.js$/,
parser: {
system: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove all System.import calls in the test cases.

@@ -0,0 +1,3 @@
module.exports = [
[/System\.import\(\) is deprecated/]
];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add additional config testcases for system: true,system: undefined and system: false

compilation.warnings.push(new SystemImportDeprecationWarning());
}

parser.hooks.importCall.call(expr);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return the result of this line


this.name = "SystemImportDeprecationWarning";
this.message = "System.import() is deprecated and will be removed soon.\n" +
"Use import() or require.ensure() instead.\n" +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove require.ensure(), only recommend import()

@@ -29,13 +29,6 @@ it("should answer typeof require.ensure correctly", function() {
it("should answer typeof require.resolve correctly", function() {
(typeof require.resolve).should.be.eql("function");
});
it("should answer typeof System correctly", function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two tests should be moved into configCases/parsing/system.import

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

try {
System.import("./module").then(mod => {
mod.should.be.eql({ default: "ok" });
done();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should error here when __SYSTEM === false


parser.hooks.call.for("System.import").tap("SystemPlugin", expr => {
if(shouldWarn) {
compilation.warnings.push(new SystemImportDeprecationWarning(parser.state.module, expr.loc));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still not happy with this. To make the warning cache correctly, it has to be in module.warnings, but I will try changing it myself.

- `system: undefined`: Warns if `System.import()` is used
- `system: true`: Disable warning
- `system: false`: Skip `System.import()` instrumentation
@ooflorent ooflorent force-pushed the disable_system_import branch from b4529b2 to 3fb63f9 Compare January 18, 2018 10:34
@sokra sokra closed this Jan 18, 2018
@sokra sokra reopened this Jan 18, 2018
@webpack-bot
Copy link
Contributor

Thank you for your pull request! The most important CI builds succeeded, we’ll review the pull request soon.

@sokra sokra merged commit 41edb20 into webpack:next Jan 18, 2018
@sokra
Copy link
Member

sokra commented Jan 18, 2018

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants