-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Does not shake unused class with static property #175
Comments
It does shake, if the property is defined inside the class AND export class Test {
static id = 'A';
test() {
console.log('test');
}
}
export function foo() {
console.log('foo');
} |
Thanks for calling out this limitation. This is because esbuild's tree shaking is conservative for correctness and doesn't make the unsafe assumption that I could see making the second case work (using the |
Shouldn't it be possible to know if there is a setter defined? Or could there be an option for "aggressive" tree shaking. |
Not sure if it makes any difference, but terser did decide to shake these: terser/terser#724 |
Rollup has known tree shaking bugs where code is incorrectly removed that actually does have side effects. See rollup/rollup#2219 for some cases where this happens. Since JavaScript is a dynamic language, it's impossible even with static analysis to determine whether a statement like that has externally-visible side effects or not. As an example, the code in the original post will have side effects if this code is evaluated before it runs: Object.defineProperty(Object.prototype, 'id', {
set() {
console.log('important side effects');
}
}); class Test {
test() {
console.log("test");
}
}
Test.id = "A"; Running these two code snippets should print I could see potentially adding an opt-in "unsafe mode" that may cause otherwise-valid code to break if it makes use of setters like this. That way by default you can be sure that tree shaking is not going to break your code. This mode would be something to opt-in to only if you have very comprehensive test coverage or you have audited all code in your bundle to make sure it's not going to break any of the assumptions made by the unsafe mode (whatever those end up being). |
@evanw I’m not sure if maybe you’re referencing TypeScript semantics here, which may differ, but as the relevant proposals stand right now, a static (or instance) property is initialized with CreateDataPropertyOrThrow, meaning that the setter in the example above would not be invoked — it’s a define-own-property op, not a set op ( See step 34.a. of ClassDefinitionEvaluation as modified by the static class features proposal and step 9 of DefineField as introduced by the class fields proposal. As the name class Foo {
static bar = (Object.freeze(Foo), true);
}
// “desugaring” to:
class Foo {}
Object.freeze(Foo);
Object.defineProperty(Foo, 'bar', { writable: true, enumerable: true, configurable: true, value: true });
// (where the last line throws a TypeError) |
If aiming for correctness, it should not shake anything, right? export class Test {
test() {
console.log('test');
}
}
eval("Test.id = 'A'");
export function foo() {
console.log('foo');
} import {foo} from './model';
foo(); results to // model.js
eval("Test.id = 'A'");
function foo() {
console.log("foo");
}
// index.js
foo(); |
@evanw I'm with you, in principle, regarding avoiding every possible side effect. However, it's often safe to assume some things. For example, Terser now assumes that And if you're setting a property on a fresh object or class, it's also pretty safe to assume that's not going to have a side effect even though that's technically possible. |
I'm fixing the bug with direct |
@evanw It seems that direct |
Thanks @evanw for adressing this! 🙏 Does this work for the Currently it's the only thing preventing three.js from being tree-shaken by esbuild, it would be great if this was looked into. |
No that’s something completely different. This change doesn’t do that. Doing that is very different, and also complicated. It requires object shape tracking which is a partial evaluation technique that esbuild doesn’t do. |
@evanw Static property shaking is still not working in typescript,is there any plan to support it ? |
model.js
index.js
expected:
actual:
The text was updated successfully, but these errors were encountered: