-
Notifications
You must be signed in to change notification settings - Fork 38
Description
Given the following classic class pattern:
EmberObject.extend({
foo: 'some value',
bar: function () {},
baz: () => {},
bat() {}
});
The codemod should create the following output when run in addons:
class MyClass extends EmberObject {
bat() {}
}
MyClass.prototype.foo = 'some value';
MyClass.prototype.bar = function () {};
MyClass.prototype.baz = () => {};
instead of what it creates today:
class MyClass extends EmberObject {
foo = 'some value';
bar = function () {};
baz = () => {};
bat() {}
}
This must be done to ensure the codemod is making safe migration in case of classes being extended by consumers. That is, if we had the following class in a consuming app:
MyClass.extend({
foo: 'other value',
bar() { // some other function },
baz: () => { // some other function },
bat() { // some other function }
});
Then the values of foo, bar, and baz in this extending class would be clobbering by their underlying definition within MyClass, where the codemod has made them class fields applied to the instance.
Similarly, if we have a native class like this:
class MyExtendingClass extends MyClass {
foo = 'some value';
bar() {};
baz() {};
bat() {}
}
Then in this case, both bar and baz would get clobbered, likely causing unexpected bugs as the consumer believed they were overriding the default values in the base MyClass.
Of course, the proposed syntax is rather undesired, and in the long run you would want to find a way to convert these back to class fields after evaluating the risk and communicating with consumers (such as through a breaking release). Since this is far more likely to occur in an addon (which could have many consumers, any of which may be extending classes in ways the author can't predict) than in an app, my proposal is that we have the codemod only make changes in this manner when migrating an addon, and to keep the current behavior in apps.
To maintain the existing behavior, a second codemod could be added to this package that migrates prototype fields to class fields automatically, along with an appropriate warning of the inherent risk. This would allow people to have a much safer migration in the first step, and then optionally choose an aggressive migration to class fields as a separate change that would be easier to reason about and judge the risk level of those changes.