lukastaegert / eslint-plugin-tree-shaking Goto Github PK
View Code? Open in Web Editor NEWMarks side-effects in module initialization that would interfere with tree-shaking
License: MIT License
Marks side-effects in module initialization that would interfere with tree-shaking
License: MIT License
When using React.forwardRef
i get eslint error: Cannot determine side-effects of mutating function return value
adding it to noSideEffectsWhenCalled
doesn't help filter return value errors.
for example:
const ErrorPage = React.forwardRef((props, ref) => (
<div ref={ref} {...props} />
));
with lint rule:
"noSideEffectsWhenCalled": [
{
"module": "react",
"functions": ["forwardRef"]
}
]
or
"noSideEffectsWhenCalled": [
{
"module": "react",
"functions": "*"
}
]
could you please advise how this issue could be resolved?
Currently get this stack trace when calling a function with a conditional chain operator upon initialization:
[Error - 10:22:26 PM] TypeError: Cannot read property 'hasValue' of undefined
Occurred while linting /Users/maclockard/workspace/hex-inc/hex/packages/client/components/markdown/MarkdownSanitizeSchema.ts:2
at Object.|| (/Users/maclockard/workspace/hex-inc/hex/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:152:22)
at Object.getValueAndReportEffects (/Users/maclockard/workspace/hex-inc/hex/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:663:48)
at reportSideEffects (/Users/maclockard/workspace/hex-inc/hex/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:907:24)
at /Users/maclockard/workspace/hex-inc/hex/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:256:43
at Array.forEach (<anonymous>)
at Object.reportEffects (/Users/maclockard/workspace/hex-inc/hex/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:256:24)
at reportSideEffects (/Users/maclockard/workspace/hex-inc/hex/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:905:24)
at /Users/maclockard/workspace/hex-inc/hex/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:734:11
at Array.forEach (<anonymous>)
at Object.reportEffects (/Users/maclockard/workspace/hex-inc/hex/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:732:25)
For further maintenance
This plugin is pretty much exactly what I'm looking for to prevent side effects! Thanks for all the work that went into it. There is, however, one thing though preventing me from using this for my projects, and that's how many things you have to manually mark using magic comments. It makes perfect sense as to why, but it makes this plugin infeasible to use for medium to larger projects with lots of modules that import from both each other and 3rd party libraries.
I think the thing that would help most here would be the ability to mark functions as side effect free in the plugin config. This would really bring down the number of places you need to explicitly mark no-side-effects-when-called
in code, making this plugin much more approachable for medium to larger projects!
Here's what it could possibly look like in config:
{
"rules": {
"tree-shaking/no-side-effects-in-initialization": ["error", {
"noSideEffectsWhenCalled": [
{"module": "react", "functions": ["memo", "createComponent"]},
{"module": "styled-components", "functions": "*"},
{"builtin": "Object.values"},
{"module": "#local", "functions": ["myFunc1", "myFunc2"]}
]
}]
}
}
I hope this example is mostly self explanatory, but to call out some extra stuff I added for convenience:
"*"
instead of passing an array of function names"#local"
. What I mean by a local module is one that is imported via a relative path.This would also help address #43 by allowing folks to explicitly whitelist things themselves. Specifically since someone may be using a bundler besides rollup that already correctly handles a given builtin.
Object.freeze({})
or Object.values({})
assigned to a module global triggers "Cannot determine side-effects of calling member function", while the rule should know, that these methods themselves don't have any side effects for literals (or Object.values for any argument, since it does not modify it).
Interestingly Array.from
doesn't seem to trigger the rule, at least not in the case of Array.from(Object.values({}))
.
Code:
const loading = <Loading />
ESLint version: 8.57.0
ESLint plugins:
"eslint-config-prettier": "~9.0.0",
"eslint-formatter-azure-devops": "^1.2.0",
"eslint-plugin-import": "~2.26.0",
"eslint-plugin-jest": "~27.4.3",
"eslint-plugin-jsdoc": "~46.2.6",
"eslint-plugin-prettier": "~5.0.0",
"eslint-plugin-tree-shaking": "^1.12.2",
"eslint-plugin-tsdoc": "~0.2.14",
Given a class with a static block, eslint-plugin-tree-shaking
produces the following error:
error Unknown node type StaticBlock.
If you are using the latest version of this plugin, please consider filing an issue noting this message, the offending statement, your ESLint version, and any active ESLint presets and plugins tree-shaking/no-side-effects-in-initialization
For example:
class Foo {
static {
console.log("FOO");
}
}
Currently, eslint-plugin-tree-shaking features a test suite of > 350 code snippets which are also automatically run against rollup. These tests check that if code is not tree-shaken, then there needs to be an ESLint error. That is, you can be fairly certain that if there are no ESLint errors, you do not have any hidden side-effects in rollup. Unfortunately, the same cannot be said for Webpack. This is particularly bad since Webpack is the final bundler for most Webapps and those would benefit most from tree-shaking.
What I am looking for is a way to run a code snippet through Webpack and reliably determine if tree-shaking would remove this snippet. Main problems:
I got this issue with 1.8.0
Unknown node type SpreadElement.
If you are using the latest version of this plugin, please consider filing an issue noting this message, the offending statement, your ESLint version, and any active ESLint presets and pluginseslint(tree-shaking/no-side-effects-in-initialization)
Hi,
If I have some TypeScript like:
export class Secret {
#secret: string
constructor() {
this.#secret = 'secret'
}
getSecret(): string {
return this.#secret
}
}
I get an error:
Unknown node type PrivateIdentifier.
If you are using the latest version of this plugin, please consider filing an issue noting this message, the offending statement, your ESLint version, and any active ESLint presets and plugins eslint(tree-shaking/no-side-effects-in-initialization)
at the line #secret: string
.
eslint: 8.22.0
eslint-plugin-tree-shaking: 1.10.0
eslint-config-prettier: 8.5.0
eslint-plugin-import: 2.26.0
eslint-plugin-prettier: 4.2.1,
typescript: 4.7.4
@typescript-eslint/eslint-plugin: 5.34.0
@typescript-eslint/parser: 5.34.0
Is this likely an issue with the plugin or my tsconfig or ....?
Thanks,
Tim
When using the preset in some of my projects I see such an error:
Cannot read property 'type' of undefined
TypeError: Cannot read property 'type' of undefined
at verifyNodeTypeIsKnown (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:1013:21)
at reportSideEffects (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:1021:10)
at node.properties.forEach.subNode (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:814:11)
at Array.forEach (<anonymous>)
at Object.reportEffects (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:813:25)
at reportSideEffects (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:1025:24)
at Object.reportEffects (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:991:22)
at reportSideEffects (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:1025:24)
at node.declarations.node.declarations.forEach.declarator (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js:976:13)
at Array.forEach (<anonymous>)
I hope you don't get overwhelmed by my eslintrc: https://pastebin.com/mtrYnfTV
When using the @typescript-eslint plugin in tandem with this package, there are UnknownNodeType
errors
Unknown node type TSInterfaceDeclaration.
If you are using the latest version of this plugin, please consider filing an issue noting this message, the offending statement, your ESLint version, and any active ESLint presets and plugins tree-shaking/no-side-effects-in-initialization
The issue appears to be here where you are checking the AST for known node types.
It looks like you should either add typescript specific AST nodes to the known node types, or maybe check for a TS
prefix, or skip this check altogether and ignore unknown node types.
I got this very non-informative error:
null
Error: x
at verifyNodeTypeIsKnown ([...]\no-side-effects-in-initialization.js:1015:13)
I've checked when it blew up and it was this line of code (written in TS):
class ActionMenu extends React.Component<ActionMenuProps, ActionMenuState> {
// ...
private boxRef?: HTMLDivElement; // HERE
// ...
}
Currently, the errors produced by eslint-plugin-tree-shaking may be accurate but also somewhat technical, i.e. "Could not determine side-effects ofβ¦".
Under this issue I want to collect ideas on how to improve this and give better feedback to the user.
I noticed a big problem is Eslint only scanning a single file at a time. If you changed to become a TS server plugin instead then maybe you would have access to the whole project in order to determine if what yyou are importing is pure or not.
Great work, I am excited to see this plugin have a "low noise" configuration in the future.
15.12.3
to 15.12.4
.π¨ View failing branch.
This version is covered by your current version range and after updating it in your project the build failed.
semantic-release is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
branch
parameter from push
function (ffe1062)The new version differs by 1 commits.
ffe1062
fix: remove unnecessary branch
parameter from push
function
See the full diff
There is a collection of frequently asked questions. If those donβt help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot π΄
using React.forwardRef
shouldn't be a sideEffect
and eslint rule should pass on component using React.forwardRef
.
when using React.forwardRef
with types in typescript files eslint rule fail on: Cannot determine side-effects of mutating function return value - eslint(tree-shaking/no-side-effects-in-initialization)
for example:
ErrorPage.js
: (rule pass)
const ErrorPage = React.forwardRef((props, ref) => (
<div {...props} ref={ref} />
));
ErrorPage.tsx
: (rule fails)
const ErrorPage = React.forwardRef<HTMLDivElement, ErrorPageProps>(
(props, ref) => <div {...props} ref={ref} />
);
5.0.8
to 5.0.9
.π¨ View failing branch.
This version is covered by your current version range and after updating it in your project the build failed.
travis-deploy-once is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
require.resolve
to load babel preset (16292d3)The new version differs by 2 commits.
16292d3
fix: use require.resolve
to load babel preset
858d475
test: add babel-register.js
to test coverage
See the full diff
There is a collection of frequently asked questions. If those donβt help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot π΄
Msg: [eslint] Cannot determine side-effects of executing Literal as a statement (tree-shaking/no-side-effects-in-initialization)
Code:
(function (window) {
'use strict'
?? is a new operator not supported by this plugin yet.
patch-package patch to fix this:
eslint-plugin-tree-shaking+1.8.0.patch
diff --git a/
node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js b/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js
index 16c42ca..10e4728 100644
--- a/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js
+++ b/node_modules/eslint-plugin-tree-shaking/lib/rules/no-side-effects-in-initialization.js
@@ -150,6 +150,17 @@ const reportSideEffectsInProgram = (context, programNode) => {
return leftValue
}
return getAndReportRight()
+ },
+ '??': (getAndReportLeft, getAndReportRight) => {
+ const leftValue = getAndReportLeft()
+ if (!leftValue.hasValue) {
+ getAndReportRight()
+ return leftValue
+ }
+ if (leftValue.value) {
+ return leftValue
+ }
+ return getAndReportRight()
}
}
Right now this plugin seems a little too aggressive for my needs.
Let's look at this small example.
I am using RxJS that from my understanding is pretty good about tree shaking, and even if they aren't there isn't much I can do from my project to fix their problems and I would rather not have to add a bunch of eslint-disable everywhere.
So I am looking for options that will assume that other modules do not have any side effects.
I just want to make sure that the current module doesn't create any new side effects.
I also might be ignorant of this but does this
export class DeckService {
private readonly internalDecks$ = new BehaviorSubject<Deck[]>([]);
public readonly decks$: Observable<Deck[]>;
constructor() {
this.decks$ = this.internalDecks$.asObservable();
}
}
Really differ from this?
export class DeckService {
private readonly internalDecks$ = new BehaviorSubject<Deck[]>([]);
public readonly decks$ = this.internalDecks$.asObservable();
}
Or is this just a false positive?
master
branch failed. π¨I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.
You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. Iβm sure you can resolve this πͺ.
Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.
Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master
branch. You can also manually restart the failed CI job that runs semantic-release.
If you are not sure how to resolve this, here is some links that can help you:
If those donβt help, or if this issue is reporting something you think isnβt right, you can always ask the humans behind semantic-release.
The npm token configured in the NPM_TOKEN
environment variable must be a valid token allowing to publish to the registry https://registry.npmjs.org/
.
If you are using Two-Factor Authentication, make configure the auth-only
level is supported. semantic-release cannot publish with the default auth-and-writes
level.
Please make sure to set the NPM_TOKEN
environment variable in your CI with the exact value of the npm token.
Good luck with your project β¨
Your semantic-release bot π¦π
Hi, it would be great if you could support the Terser /*@__PURE__*/
annotation since Webpack uses this as well. This would be in addition to or as a replacement for your existing support of /* tree-shaking no-side-effects-when-called */
annotations.
Even though this plugin might be useful for library developers, I see its main use as a tool to manually check why tree-shaking does not work in a particular case. That easiest way to do this would be if there was a web app where you could paste your code and get your errors highlighted as it is done in https://eslint.org/demo/.
If someone has some experience with this or would be interested in helping to set something up this would be greatly appreciated. Bonus points if it is possible to generate links to a pre-filled version of this page because then you could use it as an easy reference when discussing tree-shaking problems in Github issues of Rollup or Webpack.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.