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

[1.x] Fix reactivity conflict caused by Object.prototype.hasOwnProperty #35

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ All notable changes to **dot-diver** will be documented here. Inspired by [keep

## Unreleased

- Fixed reactivity issues caused by hasOwnProperty check

## [1.0.6](https://github.com/clickbar/dot-diver/tree/1.0.6) (2024-03-25)

- Fixed breaking change introduced in the type of SearchableObject
Expand Down
11 changes: 4 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,6 @@ type PathValueEntry<T, P extends PathEntry<T, Depth>, Depth extends number = 10>
type SafeObject = Record<string, unknown>
type SearchableObject = object

// eslint-disable-next-line @typescript-eslint/unbound-method
const hasOwnProperty = Object.prototype.hasOwnProperty

/**
* Retrieves a value from an object by dot notation. The value is received by optional chaining,
* therefore this function returns undefined if an intermediate property is undefined.
Expand All @@ -238,8 +235,8 @@ function getByPath<T extends SearchableObject, P extends PathEntry<T> & string>(
return pathArray.reduce((current: unknown, pathPart) => {
if (
typeof current !== 'object' ||
current === null ||
!hasOwnProperty.call(current, pathPart)
// eslint-disable-next-line no-prototype-builtins
!current?.hasOwnProperty(pathPart) // We use the builtin to avoid reactivity issues with Proxy
Comment on lines +238 to +239
Copy link
Member

@djfhe djfhe Aug 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// eslint-disable-next-line no-prototype-builtins
!current?.hasOwnProperty(pathPart) // We use the builtin to avoid reactivity issues with Proxy
current === null ||
current[pathPart] === undefined || // Trigger dependency tracking for libraries (e.g. vue)
!hasOwnProperty.call(current, pathPart)

I would suggest this. We still use the global hasOwnProperty function but signal vue, that we access the property so its depedency tracking works.

) {
return undefined
}
Expand Down Expand Up @@ -283,8 +280,8 @@ function setByPath<
const parentObject = pathArray.reduce<unknown>((current, pathPart) => {
if (
typeof current !== 'object' ||
current === null ||
!hasOwnProperty.call(current, pathPart)
// eslint-disable-next-line no-prototype-builtins
!current?.hasOwnProperty(pathPart)
Comment on lines +283 to +284
Copy link
Member

@djfhe djfhe Aug 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// eslint-disable-next-line no-prototype-builtins
!current?.hasOwnProperty(pathPart)
current === null ||
current[pathPart] === undefined || // Trigger dependency tracking for libraries (e.g. vue)
!hasOwnProperty.call(current, pathPart)

The same here. Adding this undefined check should not change behavior, since the check in line 292 would have catched the undefined parentObject otherwise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a good alternative, I see that you already released it, so I will close this

) {
throwAssignmentError(current, pathPart)
}
Expand Down
Loading