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
chore(TS): Add declare and remove useless methods from Object. #8574
Conversation
Messed up a bunch of things with cacheProperties i need to fix yet. |
This is going to be another painful PR on top of certifying that class were a mistake and are less powerful and useful than functions. now i m sure. |
Build Stats
|
@ShaMan123 this thing is becoming more complicated than planned. Using public properties or defaults in the constructor is triggering the set calls. set calls executes side effects in different order depending on the order of the keys of the options and results changes. I already tried to assign defaults outside of set ( as we were doing before because they were on the prototype ) but that can't be done because they can't be assigned on We could stop executing side effects on the constructor entirely but that would mean we would need to find what breaks and fix it manually. |
Reducing the scope of the pr to unlock exports |
I have to say this PR seems a step back rather than forward. |
take a look at this POC for circle and ellipse. |
I prefer a chat if you are willing |
Some premise, adding items to the prototype isn't declare is needed because otherwise those are public properties, so if you don't assign a value, you need to declare them. Babel transpiler either errors because there is a declare or they are actual undefined properties, but existing. Looks like the above code is valid, so when the code gets transpiled and the type definition removed, those are undefined props, without declare ( and a removal from the transpiler ) the code is not correct because those undefined will remove values you add in constructor. Putting the defaults in the contructor as i did in the previous commits doesn't work for many classes that have Circle and ellipses works for me too, group and active selection do not. The reason why i m not handling it in this PR anymore is because every class will need ad hoc changes to work with setting defaults in the constructor, test changes too, so we will need more PRs. So i m descoping this PR to adding declare only, and limiting the diff to that as much as possible, so at least we can try again to enable exports from the main index. 19aa171 this is the commit where i moved all defaults in constructors and then i strated roll back. |
I thought class properties do not belong to the prototype, only to the instance. Methods belong to the prototype. |
I also separated cache properties and state properties from default values because those will either need to be in some config or stay in the prototype. Their usage is unfit for static, static does not inherit with the subclasses apparently. |
static field do inherit class A {
static method() {
return 1;
}
static arr = [1,2,3]
static type = 'A'
}
class B extends A {
static {
this.arr.push(4)
this.type = 'B'
}
static method() {
return super.method() + 2;
}
}
console.log(B.method(), B.arr, B.type) Output"use strict";
var _a;
class A {
static method() {
return 1;
}
}
A.arr = [1, 2, 3];
A.type = 'A';
class B extends A {
static method() {
return super.method() + 2;
}
}
_a = B;
(() => {
_a.arr.push(4);
_a.type = 'B';
})();
console.log(B.method(), B.arr, B.type); Compiler Options{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"strictBindCallApply": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"alwaysStrict": true,
"esModuleInterop": true,
"declaration": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"target": "ES2017",
"jsx": "react",
"module": "ESNext",
"moduleResolution": "node"
}
} Playground Link: Provided |
Sure for pure state properties that sounds a thumb rule to which you can everyone agree with. |
I need an example. |
BTW in the example the static |
They inerhit just on static things. |
Thanks for elaborating. class A {
static method() {
return 1;
}
set(key, value) {
// TS stop complaining
if (this.constructor.arr.includes(key)) {
console.log('ack', key, value);
}
}
static arr = [1,2,3]
static type = 'A'
}
class B extends A {
static {
this.arr.push(4)
this.type = 'B'
}
static arr = [...A.arr, 'key', 'key2'];
static method() {
return super.method() + 2;
}
}
class C extends B {
}
console.log('a', A.method(), A.arr, A.type);
console.log('b', B.method(), B.arr, B.type);
console.log('c', C.method(), C.arr, C.type);
const c = new C();
const b = new B();
C.method = () => {
console.log('modified static method');
return 5;
}
c.set('key', 4);
console.log(b.constructor.type)
C.arr = [...C.arr, 'foo'];
c.set('foo', 'bar')
console.log(c.constructor.method()) Output"use strict";
var _a;
class A {
static method() {
return 1;
}
set(key, value) {
// TS stop complaining
if (this.constructor.arr.includes(key)) {
console.log('ack', key, value);
}
}
}
A.arr = [1, 2, 3];
A.type = 'A';
class B extends A {
static method() {
return super.method() + 2;
}
}
_a = B;
(() => {
_a.arr.push(4);
_a.type = 'B';
})();
B.arr = [...A.arr, 'key', 'key2'];
class C extends B {
}
console.log('a', A.method(), A.arr, A.type);
console.log('b', B.method(), B.arr, B.type);
console.log('c', C.method(), C.arr, C.type);
const c = new C();
const b = new B();
C.method = () => {
console.log('modified static method');
return 5;
};
c.set('key', 4);
console.log(b.constructor.type);
C.arr = [...C.arr, 'foo'];
c.set('foo', 'bar');
console.log(c.constructor.method()); Compiler Options{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"strictBindCallApply": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"alwaysStrict": true,
"esModuleInterop": true,
"declaration": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"target": "ES2017",
"jsx": "react",
"module": "ESNext",
"moduleResolution": "node"
}
} Playground Link: Provided |
I m not sure declare are doing anything to the code rather than claryfing for tools that those are types and not actual code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks fine
a few small comments
if ( | ||
this === (target as InteractiveFabricObject) && | ||
action.slice && | ||
action.slice(0, 5) === 'scale' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
startsWith?
action.startsWith('scale')
_updateCacheCanvas() { | ||
const targetCanvas = this.canvas; | ||
if (this.noScaleCache && targetCanvas && targetCanvas._currentTransform) { | ||
const target = targetCanvas._currentTransform.target, | ||
action = targetCanvas._currentTransform.action; | ||
if ( | ||
this === (target as InteractiveFabricObject) && | ||
action.slice && | ||
action.slice(0, 5) === 'scale' | ||
) { | ||
return false; | ||
} | ||
} | ||
return super._updateCacheCanvas(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love this!
It is well scoped.
protected setOptions(options: Record<string, any> = {}) { | ||
this._setOptions(options); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we really need this alias?
It is called only once in fabric from this contrusctor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and _setOptions
is an alias for set
so that can go away as well.
too many methods that do the same shit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not this should go because no strange stuf in the constructor. It will go when we move the defaults
// static canvas and canvas have both an array of InteractiveObjects | ||
// @ts-ignore this needs to be fixed somehow, or ignored globally |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think static canvas should have the non interactive object as a type while canvas should have the interactive object
Wondering how complicated and dumb that might turn out
this.set('rx', (options && options.rx) || 0); | ||
this.set('ry', (options && options.ry) || 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am surprised this doesn't break width and height values
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because constructor({...}) is doing that up in the chain with setOptions.
The issue could be if you pass with after rx,ry. But those are exactly the kind of things that needs to addressed when we setup the defaults.
I would also not bother, i prefer to say you have to set both of them, and zero is not a good value if not for both. I wouldn't try autofixing for the developer that have to understand this once.
Same issue with polygon bounding box, line points, radius and witdh/height. there are so many things we try to take care of we probably shouldn't.
If it wasn't late now i woudl say that width and height should be internal prop for geometry and the one we set for rect and text should be some sort of public width/height that nothing have to do with the geometry calculcations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it wasn't late now i woudl say that width and height should be internal prop for geometry and the one we set for rect and text should be some sort of public width/height that nothing have to do with the geometry calculcations.
Sounds good
Same issue with polygon bounding box, line points, radius and witdh/height. there are so many things we try to take care of we probably shouldn't.
we should draft topics for a team meeting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes this whole how to use set/ set and _set, side effects, will be a recurring theme
if (isFiller(this.stroke)) { | ||
ctx.strokeStyle = this.stroke.toLive(ctx); | ||
} else { | ||
ctx.strokeStyle = this.stroke ?? ctx.fillStyle; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this code looks like a util
I think it is duplicated a few times
src/shapes/polygon.class.ts
Outdated
@@ -1,3 +1,4 @@ | |||
import { IPoint } from '../point.class'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably a leftover of a previous thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right, when it comes to assigning defaults this will have a constructor too. So it will need the IType definititon
src/shapes/textbox.class.ts
Outdated
// with the new controls this noScaleCache here shouldn't be needed anymore | ||
lockScalingFlip: true, | ||
// with the new controls this noScaleCache here shouldn't be needed anymore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
care to elaborate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think i was thinking at the width behaviour and that scaling does not affect textbox because we usually change the width. but i think i forgot of both axis scaling
src/util/transform_matrix_removal.ts
Outdated
export const _assignTransformMatrixProps = ( | ||
object: FabricObjectWithTransformMatrix | ||
) => { | ||
if (object.transformMatrix) { | ||
const { scaleX, scaleY, angle, skewX } = qrDecompose( | ||
object.transformMatrix | ||
); | ||
object.flipX = false; | ||
object.flipY = false; | ||
object.set('scaleX', scaleX); | ||
object.set('scaleY', scaleY); | ||
object.angle = angle; | ||
object.skewX = skewX; | ||
object.skewY = 0; | ||
} | ||
}; | ||
|
||
/** | ||
* This function is an helper for svg import. it removes the transform matrix | ||
* and set to object properties that fabricjs can handle | ||
* @private | ||
* @param {Object} preserveAspectRatioOptions | ||
*/ | ||
export const _removeTransformMatrix = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
naming?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't know pick one. I think exportin only one is good enough
Co-authored-by: Shachar <34343793+ShaMan123@users.noreply.github.com>
… into default-values-object
@asturur don't have an option in VSCODE that it formats on save running prettier? |
Works sporadically for me, both here and at work prettier does not kick in for me. |
I have mixed the code with the dependency update branch with export and type declaration and i have a local branch with only 101 failing test from 174 i started after merging. |
ok down to 9 failures but i have to stop now |
ok so those additional declare changes ( no test changes, no code changed ) should give us support for export and types emitting, using babel OR the other rollup plugin ( That does not support browserlist ) |
let's give priority to this today if possible, i want to move asap to discussing browerlist file and what we support and transpile on which tool. |
how can i help? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect TS to expose a flag in the config controlling this instead of this shitty declare business
@@ -31,7 +31,7 @@ export class Textbox extends IText { | |||
* Cached array of text wrapping. | |||
* @type Array | |||
*/ | |||
declare __cachedLines: Array<any> | null = null; | |||
declare __cachedLines: Array<any> | null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a dead prop
Usually just approve if the PR is ok, or block if there is something you really don't like |
Just saw this shit Is this what was creating this shit storm?? |
Yes i didn't read all the links deeply, but exactly the part of initializing as undefined. We will have to assign our own values with define properties too since we are doing it manually if we want to do that on spec. |
So a babel plugin will save us from declare? |
Motivation
Finishing up basic object migration.
Description
declare
so that any transpiler understand those should be removed.added the default values in the constructor, while still making possible to change them globally before initialization of objectsfailed / scope blown upcacheProperties and stateProperties needs to stay on prototype, having them as static is not really possible since it would require duplicating them for each class and would add another constrain when subclassing. Apparently static properties aren't usable with inheritancefailed / scope blown upChanges
Gist
In Action