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

Manage circular references in objects #104

Merged
merged 16 commits into from
Dec 14, 2023

Conversation

remyguillaume
Copy link
Contributor

Hello,

I analyzed the problem described in the issue #103 more in details, and I think this Pull-Request shoulb solve the problem.

The solution is to look first if the object already has a path within the same object, and if yes, not to generate a new path.

So actually if we are looking for the parth group.children[0].children[0].parent the object behind this path actually already exists with the path group.children[0], and it's exactly the same object within the same tree structure. Therefore, the shortest path to the object should be used.

It's still possible to have the same object under many different path, this change in the code is only managing circular references within the same object.

The issue and the new code contain more comments and explanations.
Fixes #103

Could you please have a look at it and tell me if this change is ok for you?
Thanks !

And I forget the most important : Many thanks for your job, this library is really useful for us :)

@sindresorhus
Copy link
Owner

Thanks for working on this. This needs a test.

@remyguillaume
Copy link
Contributor Author

Ok I'll work on that, thanks.

I also just saw that there is an error with the linting, but I don't really understand why.
Could you please give me some explanations on what is wrong here?

@sindresorhus
Copy link
Owner

Could you please give me some explanations on what is wrong here?

Fixed in main. Just rebase.

@remyguillaume
Copy link
Contributor Author

I've added a test to reproduce the error and to validate the new code.

(Your changes on main are all visible in my pull-request now, I don't really understand why, but I read it seems to be a normal behavior in github.)

tests/on-change.test.js Outdated Show resolved Hide resolved
tests/on-change.test.js Outdated Show resolved Hide resolved
proxy.layers[1].group.layers[0].group.layers[1].group.layers[1].group.layers[2].val = 33;
t.is(resultPath, 'layers.2.val');
});

Copy link
Owner

Choose a reason for hiding this comment

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

This test does not test the mentioned infinite loop. It would be good with a test that would have caused infinite loop before this pull request.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, actually "infinite loop" was not the right term here.
The more we were modifying the object property, the more the path was getting longer.
This mean that after the first call of callback we got proxy.layers[1].group.layers[0].val.
After the second call we got proxy.layers[1].group.layers[0].group.layers[2].group.layers[0].val.
After the third call we got proxy.layers[2].group.layers[2].group.layers[1].group.layers[0].group.layers[2].group.layers[0].val.
... and so on.

Example fo logs:
image

And after 1 minute of usage of our app:
image

And actually we reached a memory limit because we were getting path that has Megabytes of data.

So, we cannot say this is a infinite loop.
But this tests actually exactly covers our problem.

Copy link
Owner

Choose a reason for hiding this comment

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

Ok. I would reword the comment then.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I've rewrited the comment.

index.js Outdated Show resolved Hide resolved
index.js Outdated
// and the path can get longer and longer until we reach a memory limit.
const childPath = path.concat(basePath, property);
const existingPath = cache.getPath(value);
if (existingPath && !isArray(childPath) && !isSymbol(childPath) && childPath.toString().startsWith(existingPath.toString())) {
Copy link
Owner

Choose a reason for hiding this comment

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

Using startsWith is a bit fragile. It could potentially match the wrong thing. For example, existingPath is foo while childPath is foo2.bar.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, you're totaly right, I didn't thought about this. I've rewriten the code to do a better comparison.
Actually I didn't manage the arrays of paths correctly in my first pull-request. I changed the code to manage arrays as well. And I've added another unittest for that too.

@sindresorhus
Copy link
Owner

sindresorhus commented Dec 11, 2023

(Your changes on main are all visible in my pull-request now, I don't really understand why, but I read it seems to be a normal behavior in github.)

That's a sign of incorrect rebasing.

Your commit repeats: https://github.com/sindresorhus/on-change/pull/104/commits

remyguillaume and others added 5 commits December 11, 2023 17:04
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
@remyguillaume
Copy link
Contributor Author

That's a sign of incorrect rebasing.

Your commit repeats: https://github.com/sindresorhus/on-change/pull/104/commits

Should I do something here ?
(Sorry, but I'm used to GitLab, which seems to manage Merge-Requests in a different way than GitHub does.)

@sindresorhus sindresorhus merged commit 3448c55 into sindresorhus:main Dec 14, 2023
2 checks passed
@remyguillaume
Copy link
Contributor Author

Hi @sindresorhus

Thanks for merging, and have a merry Christmas ! 😊

@sindresorhus
Copy link
Owner

Merry Christmas :)

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 this pull request may close these issues.

Problem with Parent-Leaf-Parent Relation in a watched object
3 participants