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

core(fr): convert trace-elements gatherer #12442

Merged
merged 9 commits into from May 6, 2021
Merged

Conversation

adamraine
Copy link
Member

Adds support for TraceElements gatherer in FR.

Ref #11313

@adamraine adamraine requested a review from a team as a code owner May 4, 2021 22:55
@adamraine adamraine requested review from connorjclark and removed request for a team May 4, 2021 22:55
@google-cla google-cla bot added the cla: yes label May 4, 2021
@@ -308,10 +314,28 @@ class TraceElements extends Gatherer {
}
}

await driver.sendCommand('Animation.disable');
session.sendCommand('Animation.disable');
Copy link
Collaborator

Choose a reason for hiding this comment

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

should these be in stopInstrumentation? does it matter?

Copy link
Collaborator

Choose a reason for hiding this comment

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

this is tricky, I'm assuming that Animation domain needs to remain enabled for Animation.resolveAnimation to work?

if not, then yeah definitely move to stopInstrumentation

Copy link
Collaborator

Choose a reason for hiding this comment

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

why was the await removed though? I seem to recall bad things happening in LR if there are unhandled promise rejections

Copy link
Collaborator

Choose a reason for hiding this comment

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

alternate option: collect animation id -> name mapping by listening for Animation.animationCreated and fetching at the end of stopInstrumentation

Copy link
Member Author

Choose a reason for hiding this comment

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

I tried this and yeah, Animation domain needs to be enabled. When I moved it back I forgot the await though haha.

Copy link
Collaborator

Choose a reason for hiding this comment

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

what do you think about the alternate option @adamraine? it's more code and possible more animation resolution at the benefit of more idiomatic "instrumentation" followed by the artifact computation.

I could see us going either way, just interested in your thoughts.

Copy link
Member Author

Choose a reason for hiding this comment

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

We're still going to have some "instrumentation" in getArtifact when we call Runtime.callFunctionOn. Some less destructive options I came up with:

  • Remove the call to Animation.disable entirely
  • Call Animation.disable in stopInstrumentation, then reenable it for getArtifact.

I'll give your suggestion a shot though to see how destructive it is.

Copy link
Member Author

Choose a reason for hiding this comment

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

So I went a little deep down this rabbit hole. I had trouble resolving the animation name from animationCreated events, however I found that we can just get the animation name directly from animationStarted events. Kinda wish I had thought of this when I first added animated elements to TraceElements 😆

@@ -159,7 +159,7 @@ describe('Fraggle Rock API', () => {
const {lhr} = result;
const {auditResults, failedAudits, erroredAudits} = getAuditsBreakdown(lhr);
// TODO(FR-COMPAT): This assertion can be removed when full compatibility is reached.
expect(auditResults.length).toMatchInlineSnapshot(`103`);
expect(auditResults.length).toMatchInlineSnapshot(`105`);
Copy link
Collaborator

Choose a reason for hiding this comment

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

hm, didn't bump the timespan one? oh right trace isn't supported in timespan yet 👍

@GoogleChrome GoogleChrome deleted a comment from mspaansen May 5, 2021
Copy link
Collaborator

@patrickhulce patrickhulce left a comment

Choose a reason for hiding this comment

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

nice! I like this a lot 👍 feels exactly as it would be if we wrote it with FR in mind from the first place :)

lighthouse-core/gather/gatherers/trace-elements.js Outdated Show resolved Hide resolved
* @param {LH.Gatherer.FRTransitionalContext} context
*/
async stopInstrumentation(context) {
if (this.onAnimationCreated) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

could avoid this if by moving onAnimationCreated to class property next to the map, but understand if you'd rather keep the impl inside startInstrumentation :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

why not a private function?

Copy link
Member Author

Choose a reason for hiding this comment

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

Needed access to this, I wound up defining it in a new constructor.

Copy link
Collaborator

Choose a reason for hiding this comment

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

See JSUsage gatherer constructor for how to use this in class callback functions.

lighthouse-core/gather/gatherers/trace-elements.js Outdated Show resolved Hide resolved
* @param {LH.Gatherer.FRTransitionalContext} context
*/
async stopInstrumentation(context) {
if (this.onAnimationCreated) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

why not a private function?

Comment on lines +51 to +59
constructor() {
super();
this._onAnimationStarted = this._onAnimationStarted.bind(this);
}

/** @param {LH.Crdp.Animation.AnimationStartedEvent} args */
_onAnimationStarted({animation: {id, name}}) {
if (name) this.animationIdToName.set(id, name);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
constructor() {
super();
this._onAnimationStarted = this._onAnimationStarted.bind(this);
}
/** @param {LH.Crdp.Animation.AnimationStartedEvent} args */
_onAnimationStarted({animation: {id, name}}) {
if (name) this.animationIdToName.set(id, name);
}
/** @param {LH.Crdp.Animation.AnimationStartedEvent} args */
_onAnimationStarted = ({animation: {id, name}}) => {
if (name) this.animationIdToName.set(id, name);
}

FWIW, this was my suggestion if you're going to separate already :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Can't do it, need access to this

Copy link
Collaborator

Choose a reason for hiding this comment

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

that shouldn't be a problem

$ cat > foo.js <<EOF
class Foo {
  x = 1
  foo = () => this.x
}

console.log(new Foo().foo())
const detached = new Foo().foo
console.log(detached()) // this works too :)
EOF
$ node foo.js
1
1

Copy link
Member Author

@adamraine adamraine May 5, 2021

Choose a reason for hiding this comment

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

Unfortunately eslint disagrees. I guess it technically works though.

Copy link
Collaborator

Choose a reason for hiding this comment

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

That's because they don't support class fields eslint/eslint#14343

@adamraine adamraine merged commit 0b00b5c into master May 6, 2021
@adamraine adamraine deleted the fr-trace-elements branch May 6, 2021 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants