Skip to content
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

Properties of Easing object can reassignment #610

Closed
MasatoMakino opened this issue May 3, 2021 · 5 comments · Fixed by #617
Closed

Properties of Easing object can reassignment #610

MasatoMakino opened this issue May 3, 2021 · 5 comments · Fixed by #617

Comments

@MasatoMakino
Copy link
Contributor

Description

All properties of the TWEEN.Easing object allow reassignment.

Expected Behavior

Easing functions and groups in TWEEN.Easing do not allow reassignment.

Actual Behavior

Easing functions and groups in TWEEN.Easing allow reassignment.

Steps to Reproduce

Open code pen

This is a problem section.

TWEEN.Easing.Quadratic = TWEEN.Easing.Linear;
TWEEN.Easing.Cubic.In = TWEEN.Easing.Bounce.Out;

This code can be run without causing any errors.

Impact

In any scope, Easing can be reassignment. If someone accidentally reassignment easing functions, it will be difficult to identify the problem.

Proposal

Ideally, if we try to reassign to TWEEN.Easing, we will get an error.
Even if no error is thrown, this issue will be resolved if the reassignment is ignored.

  • Remove Easing global object
  • Remove default export in Easing.ts
  • Change each EasingFunctionGroup (e.g. Quadratic, Cubic) to Class.
  • Change each EasingFunction to static functions
  • Change Easing import in index.ts to import * as Easing from ". /Easing.ts"

With this change, I think it will possible to ignore reassignments without losing compatibility.

Environment

macOS 10.15.7
Google Chrome 90.0.4430.93
tween.js 18.6.4

@trusktr
Copy link
Member

trusktr commented May 3, 2021

What if we apply Object.freeze?

@MasatoMakino
Copy link
Contributor Author

MasatoMakino commented May 5, 2021

What if we apply Object.freeze?

With this in view, I did some research on how to implement it.

  • Object.freeze makes properties, including functions, unchangeable.
  • Object.freeze does not support nested objects. Reference
  • Static functions are reassignable. class and static functions do not solve this issue.

There was also a review of whether to include the type definition of EasingFunctionGroup in Easing.ts.
#608 (comment)
I could not find a way to expose EasingFunctionGroup interface to outside while exporting Easing global object as default. If you have that information, please let me know.

Proposal

Based on these results, I modify the proposal.

  • Remove Easing global object
  • Remove default export in Easing.ts
  • Change each EasingFunctionGroup (e.g. Quadratic, Cubic) to frozen object.
  • Change Easing import in index.ts to import * as Easing from ". /Easing.ts"

This is a sample of Easing.ts

export type EasingFunction = (amount: number) => number

export type EasingFunctionGroup {
	In: EasingFunction
	Out: EasingFunction
	InOut: EasingFunction
}

export const Linear = Object.freeze({
	None: (amount: number): number => {
		return amount
	},
})

export const Quadratic = Object.freeze(<EasingFunctionGroup>{
	In: (amount: number): number => {
		return amount * amount
	},
	Out: (amount: number): number => {
		return amount * (2 - amount)
	},
	InOut: (amount: number): number => {
		if ((amount *= 2) < 1) {
			return 0.5 * amount * amount
		}

		return -0.5 * (--amount * (amount - 2) - 1)
	},
})

Test

I tested this sample in these environments

  • TypeScript + tween.esm.js + tween.d.ts : tsc error
  • Chrome + tween.umd.js : Uncaught TypeError: Cannot assign to read only property 'Quadratic' of object
  • node.js + tween.cjs.js : No error, but ignored.
  • nodeunit + tween.cjs.js + rollup.js + @ts-ignore : I can reassign EasingFunctionGroup, but I cannot be reassigned Easing function

If I did not ignore tsc errors intentionally, I got the best results.

If you find any problems with this proposal, please let me know.
Thanks.

MasatoMakino added a commit to MasatoMakino/tween.js that referenced this issue May 27, 2021
MasatoMakino added a commit to MasatoMakino/tween.js that referenced this issue May 27, 2021
MasatoMakino added a commit to MasatoMakino/tween.js that referenced this issue May 27, 2021
@trusktr trusktr linked a pull request Aug 2, 2021 that will close this issue
trusktr added a commit to MasatoMakino/tween.js that referenced this issue Aug 2, 2021
trusktr added a commit to MasatoMakino/tween.js that referenced this issue Apr 2, 2023
@trusktr
Copy link
Member

trusktr commented Apr 2, 2023

@MasatoMakino Hello again. sorry for taking so long. Let's apply Object.freeze() to the objects, but without changing the export format (because that is a breaking change). f.e.

const Easing = Object.freeze({
	Linear: Object.freeze({
		None: function (amount: number): number {
			return amount
		},
	},
	// ... etc ...
})

export default Easing; // same export, no breaking change

@trusktr
Copy link
Member

trusktr commented Apr 2, 2023

Another idea is using as const for type checking only, for example:

Screenshot 2023-04-02 at 2 41 02 PM

TS playground

@trusktr
Copy link
Member

trusktr commented Apr 2, 2023

By the way also @MasatoMakino, are you interested to join the org to help maintain and expand Tween.js? I sent you an invite.

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

Successfully merging a pull request may close this issue.

2 participants