-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
refactor: add @__NO_SIDE_EFFECTS__
annotations to all pure functions
#4907
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
base: main
Are you sure you want to change the base?
Conversation
#__NO_SIDE_EFFECTS__
to all pure functions#__NO_SIDE_EFFECTS__
annotations to all pure functions
@@ -25,6 +25,7 @@ export interface UseActiveElementOptions extends ConfigurableWindow, Configurabl | |||
* @see https://vueuse.org/useActiveElement | |||
* @param options | |||
*/ | |||
/* #__NO_SIDE_EFFECTS__ */ |
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 prefer use @__NO_SIDE_EFFECTS__
and it should be part of the JSdocs above to avoid breaking JSDocs.
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.
Sounds good, this also allows __NO_SIDE_EFFECTS__
to appear in JSdocs and in the "Type Declarations" sections of the web documentation.
However, I found that when using TypeScript function overloads, if I place the annotation inside the JSdocs block, it won’t be preserved by the bundler.
Take usePermission
as an example:
/**
* Reactive Permissions API.
*
* @see https://vueuse.org/usePermission
*
+ * @__NO_SIDE_EFFECTS__
*/
export function usePermission(
permissionDesc: GeneralPermissionDescriptor | GeneralPermissionDescriptor['name'],
options?: UsePermissionOptions<false>
): UsePermissionReturn
export function usePermission(
permissionDesc: GeneralPermissionDescriptor | GeneralPermissionDescriptor['name'],
options: UsePermissionOptions<true>,
): UsePermissionReturnWithControls
export function usePermission(
permissionDesc: GeneralPermissionDescriptor | GeneralPermissionDescriptor['name'],
options: UsePermissionOptions<boolean> = {},
): UsePermissionReturn | UsePermissionReturnWithControls {
- ❌
__NO_SIDE_EFFECTS__
gets stripped inindex.mjs
by the bundler
If I instead move the entire JSdoc block to the last overload implementation:
export function usePermission(
permissionDesc: GeneralPermissionDescriptor | GeneralPermissionDescriptor['name'],
options?: UsePermissionOptions<false>
): UsePermissionReturn
export function usePermission(
permissionDesc: GeneralPermissionDescriptor | GeneralPermissionDescriptor['name'],
options: UsePermissionOptions<true>,
): UsePermissionReturnWithControls
+ /**
+ * Reactive Permissions API.
+ *
+ * @see https://vueuse.org/usePermission
+ *
+ * @__NO_SIDE_EFFECTS__
+ */
export function usePermission(
permissionDesc: GeneralPermissionDescriptor | GeneralPermissionDescriptor['name'],
options: UsePermissionOptions<boolean> = {},
): UsePermissionReturn | UsePermissionReturnWithControls {
- ✅
__NO_SIDE_EFFECTS__
is correctly preserved inindex.mjs
- ❌ But the JSdoc is missing from
index.d.mts
Therefore, in the case of function overloads, to ensure both the JSdocs and the annotation are retained properly, I’m considering placing __NO_SIDE_EFFECTS__
in both the JSdoc and on the final overload implementation.
+ /**
+ * Reactive Permissions API.
+ *
+ * @see https://vueuse.org/usePermission
+ *
+ * @__NO_SIDE_EFFECTS__ <- 🧑💻 for human read
+ */
export function usePermission(
permissionDesc: GeneralPermissionDescriptor | GeneralPermissionDescriptor['name'],
options?: UsePermissionOptions<false>
): UsePermissionReturn
export function usePermission(
permissionDesc: GeneralPermissionDescriptor | GeneralPermissionDescriptor['name'],
options: UsePermissionOptions<true>,
): UsePermissionReturnWithControls
+ /* @__NO_SIDE_EFFECTS__ */ <- 🤖 for bundler read
export function usePermission(
permissionDesc: GeneralPermissionDescriptor | GeneralPermissionDescriptor['name'],
options: UsePermissionOptions<boolean> = {},
): UsePermissionReturn | UsePermissionReturnWithControls {
Is there anything else I might have overlooked?
@Electron`, `@Firebase` category
#__NO_SIDE_EFFECTS__
annotations to all pure functions@__NO_SIDE_EFFECTS__
annotations to all pure functions
Before submitting the PR, please make sure you do the following
fixes #123
).Description
Resolve #4906
Side Effects Notes
I will add annotations to all functions that has "No side effects 🟢" only.
For other cases, I’d like to gather feedback from the community first.
resolve getter (🤔🟢)
The function resolves getter from parameter immediately. This may contains side effects inside the getter closure.
object param (🟢)
The param contains object. This may contains side effects inside the object getter.
useRefHistory
source
(bywatch
)source
(by_createHistoryRecord
)source
(bywatchIgnorable
)useRefHistory
options
)target
(bywatch
)target
(bywatch
)element
(byuseIntersectionObserver watch
)target
(byuseResizeObserver
)closure param (
options.eventFilter
)element
(bywatch
)options
)options.onScroll
)options
)requestDevice
options
)BroadcastChannel
useStorage
useStorage
options
)options.input
(byunrefElement
)options.dataType
(bywatch
)target
(byunrefElement
)navigator.getGamepads()
Image
query
(bywatchEffect
)object
(bywatch
)options
)options
)options
)options
)options
)options
)options
)options
)--vueuse-safe-area-*
CSS varonLoaded
)options
)options.onResize
)options
)options.stringify
)options
)options
)options.eventFilter
)options
)options
)requestPermissions
immediatelyenabled
(bywatch
)multiple
(bytoValue
)el
(byuseEventListener
)target
(byuseEventListener
)target
(byuseEventListener
)options
)options.eventFilter
)options
)onEventFired
)target
(byuseEventListener
)onPressed
)options
)options
)options
)options
)target
(byuseMouseInElement
)target
(byuseEventListener
)options
)onSwipe
)behavior
element
(bywatch
)lang
(bywatch
)text
(bywatch > utterance
)onSwipe
)options
)enabled
(bywatch
)EventSource
onReady
)options
)getter
)options
)options
)elRef
(bytoValue
)rootComponent
(byunrefElement
)list
(byuseWatchForSizes
)options
)options
)r: WatchSource
(bywatch
)onError
)fn
(bywatchEffect
)source
(bywatch
)ref
byObject.defineProperty
options
)fn
(byreactive
)predicate
)predicate
)toValue
)value
(bywatch
)value
(bywatch
)objectRef
by (unref
)r
(byvueToRef
)r
(by_toRefs
)dirty
mode modify sourceonComplete
)options
)options
)obj
(byunref
)obj
(byunref
)obj
)target
(bywatch
)refValue
(bywatch
)source
(bywatch
)revealed
initialValue
(byunref
)list
(bywatch
)options
)onPageChange
)value
(bywatch
)fn
)@Electron
@Firebase
auth
)maybeDocRef
(bywatch
)docRef
(byonValue
)@Integrations
validate
target
(bywatch
)target
(bywatch
)options
(bywatch
)onError
)onError
)text
(bywatch
)@Math
options.transform
)options.transform
)source
(bywatch
)onError
)onError
)