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

feat: add mutation logging to DevTools profiler #4544

Merged
merged 36 commits into from
Sep 12, 2024

Conversation

nolanlawson
Copy link
Collaborator

@nolanlawson nolanlawson commented Sep 10, 2024

Details

Fixes #4542

Adds mutation tracking to the existing DevTools extensions (#4535, #4541), so component authors can figure out why a component was re-rendered.

Screenshot 2024-09-10 at 4 15 50 PM

For all lwc-rehydrate events, there is a list of which components were mutated, and which properties on those components were mutated.

Does this pull request introduce a breaking change?

  • 😮‍💨 No, it does not introduce a breaking change.

Does this pull request introduce an observable change?

  • 🔬 Yes, it does include an observable change.

Only in dev mode, and only if you're looking at perf timings.

The overhead of these new APIs should also be minimal – I counted the following times when running our full Karma test suite:

  • getMutationProperties - 12.5ms
  • trackTargetForMutationLogging – 0.3ms
  • flushMutationLogsForVM – 0.9ms

Base automatically changed from nolan/tooltips to master September 10, 2024 18:08
@nolanlawson nolanlawson marked this pull request as ready for review September 10, 2024 23:22
@nolanlawson nolanlawson requested a review from a team as a code owner September 10, 2024 23:22
if (isUndefined(vm)) {
// VM should only be undefined in vitest tests, where a reactive observer is not always associated with a VM
// because the unit tests just create Reactive Observers on-the-fly.
if (process.env.NODE_ENV === 'test-karma-lwc') {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if (process.env.NODE_ENV === 'test-karma-lwc') {
if (process.env.NODE_ENV !== 'test') {

If we want to assert we're not in vitest, shouldn't we check for that, rather than checking we are in Karma?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Nope, because I don't want this throwing Errors in our downstream consumer's Jest/Vitest code. :) Whereas with test-karma-lwc we know it's only ever going to throw in our own tests.

I can add a comment!

packages/@lwc/engine-core/src/framework/mutation-logger.ts Outdated Show resolved Hide resolved
trackTargetForMutationLogging(`${toString(key)}[${i}]`, target[i]);
}
} else {
for (const prop of keys(target)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we care about tracking non-enumerable props?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't believe these are tracked by @track but I'll confirm.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Dang you're right, LWC supports mutation on non-enumerable props. Looks like we might have to dig deep here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Interestingly, LWC doesn't seem to support Symbols as shallow reactive props, but it does work for deep reactivity. And non-enumerable props work in that case too. (Non-emuerable props don't seem to work shallowly either – they throw an error of Cannot assign to read only property when you try to write to them, even if they're writable.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In any case this is fixed now!

throw new Error('The VM should always be defined except possibly in unit tests');
}
} else {
// Human-readable prop like `items[0].name` on a deep object/array
Copy link
Contributor

Choose a reason for hiding this comment

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

Not gonna handle {"annoying edge case": true}? 😛

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Actually we don't need to handle this, because (today at least) there's no way to reference object["prop with spaces"] in a template, so it won't be reactive.

We could revisit this after CTE though so that you don't see things like object.prop with spaces in DevTools.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah wait, I'm wrong, you can do this with getters. I'll fix it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

ngl i assumed from the code comment that it's just a label and doesn't actually matter if it's valid JS property access...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's true! But we may as well make the label pretty. 🤓

packages/@lwc/engine-core/src/framework/mutation-logger.ts Outdated Show resolved Hide resolved
packages/@lwc/engine-core/src/framework/profiler.ts Outdated Show resolved Hide resolved
packages/@lwc/engine-core/src/framework/profiler.ts Outdated Show resolved Hide resolved
packages/@lwc/engine-core/src/framework/profiler.ts Outdated Show resolved Hide resolved
@@ -39,6 +40,9 @@ export function valueMutated(target: object, key: PropertyKey) {
if (!isUndefined(reactiveObservers)) {
for (let i = 0, len = reactiveObservers.length; i < len; i += 1) {
const ro = reactiveObservers[i];
if (process.env.NODE_ENV !== 'production') {
logMutation(ro, target, key);
Copy link
Contributor

Choose a reason for hiding this comment

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

ro just makes me think of a dog barking...

@@ -0,0 +1,20 @@
<template>
<div><strong>First name:</strong> {firstName}</div>
Copy link
Contributor

Choose a reason for hiding this comment

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

<div><strong>

That would've been a great parody bracelet, back in the day.

nolanlawson and others added 6 commits September 11, 2024 08:57
Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com>
Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com>
Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com>
Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com>
Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com>
Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com>
@nolanlawson
Copy link
Collaborator Author

TODO: need to add handling for experimental Signals.

@nolanlawson
Copy link
Collaborator Author

Tweaked the colors a bit:

Screenshot 2024-09-11 at 5 22 15 PM

@nolanlawson nolanlawson merged commit 240034a into master Sep 12, 2024
11 checks passed
@nolanlawson nolanlawson deleted the nolan/mutation-logging branch September 12, 2024 17:37
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.

Add mutation triggers to DevTools performance timings
2 participants