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(runner): make LH.Audit.Context immutable #10555

Merged
merged 3 commits into from
Apr 9, 2020
Merged

Conversation

brendankenny
Copy link
Member

@brendankenny brendankenny commented Apr 7, 2020

breaking change (see below for details)
fixes #9897

tl;dr: making this change now allows us to

  • trust audits a little less (handy for any model of plugins)
  • make audit contexts postMessageable, handy for an off-main-thread/extension plugin model if we choose to go in that direction
  • pursue the above without having to wait for the 7.0 release, whenever that will be

The change is very small since we only have two lines of code currently modifying an audit context outside of runner.js :)

The only real breaking change is that rather than audits pushing to the context to get a top-level LHR warning, they return the warning in their audit Product. It's very possible that existing extensions use this functionality. In core, there's only one audit doing so.

Note that readonly is still type-checking/advisory level enforcement, so if an audit wants to mess with things it currently can, but that's always been the case and it's useful to leave things open without a reason to do otherwise.

breaking changes:

  • audits that previously pushed a string to context.LighthouseRunWarnings to get a top-level warning in the LHR will instead need to return a runWarnings property on the Product return value, set to an array with that string in it. (example change from core)
  • previously audits could push warnings to context.LighthouseRunWarnings even if they ended up throwing an error, but that is no longer possible since the run warnings are now part of the normal return value.

@brendankenny brendankenny requested a review from a team as a code owner April 7, 2020 22:15
@brendankenny brendankenny requested review from patrickhulce and removed request for a team April 7, 2020 22:15
@@ -51,7 +51,7 @@ class ResourceSummary {
'third-party': {count: 0, size: 0},
};
const budget = Budget.getMatchingBudget(context.settings.budgets, mainResourceURL);
let firstPartyHosts = /** @type {Array<string>} */ ([]);
let firstPartyHosts = /** @type {Immutable<Array<string>>} */ ([]);
Copy link
Member Author

Choose a reason for hiding this comment

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

this will be able to be just ReadonlyArray<string> after we upgrade to tsc 3.7+

@@ -670,31 +670,6 @@ describe('Runner', () => {
});
});

it('includes any LighthouseRunWarnings from errored audits in LHR', () => {
Copy link
Member Author

Choose a reason for hiding this comment

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

this is the sole loss of functionality (being able to push top-level warnings before the audit completely errors out), but I don't think this has ever been behavior anyone cares about or needed

Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe call out the loss of this as a breaking change in PR description so we remember to include that too in final notes?

Copy link
Member Author

Choose a reason for hiding this comment

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

maybe call out the loss of this as a breaking change in PR description so we remember to include that too in final notes?

done

@@ -509,7 +509,7 @@ declare global {
export interface MetricComputationDataInput {
devtoolsLog: DevtoolsLog;
trace: Trace;
settings: Config.Settings;
settings: Immutable<Config.Settings>;
Copy link
Member Author

Choose a reason for hiding this comment

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

this is complicated because this settings is just as often not LH.Config.Settings as it is, but that's something to sort out on a different day :)

// Intermediate immutable interfaces. Prefer e.g. Immutable<Set<T>> over direct use.
// TODO: switch to recursive type references when using tsc ≥ 3.7
// see https://github.com/microsoft/TypeScript/issues/13923#issuecomment-557509399
interface ImmutableArray<T> extends ReadonlyArray<Immutable<T>> {}
Copy link
Member Author

Choose a reason for hiding this comment

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

when we upgrade tsc, this can become
type ImmutableArray<T> = ReadonlyArray<Immutable<T>>;, which means things like the built-in ReadonlyArray<string> will be transparently switchable with Immutable<Array<string>>, giving a lot better ergonomics and functionality

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.

I'm not sure I trust audits any more than I did before, but OK :)

LGTM

@@ -25,6 +25,8 @@ function makeComputedArtifact(computableArtifact) {
* @return {ReturnType<C['compute_']>}
*/
const request = (artifacts, context) => {
/** @type {Map<string, ArbitraryEqualityMap>} */
// @ts-ignore - break immutability solely for this caching-controller function.
Copy link
Collaborator

Choose a reason for hiding this comment

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

is there a Mutable<T> type we could put Context['computedCache'] through? It'd be nice to not lose that type safety just for the mutability part

Copy link
Member Author

Choose a reason for hiding this comment

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

is there a Mutable<T> type we could put Context['computedCache'] through? It'd be nice to not lose that type safety just for the mutability part

Map is a little special (as are Array and Set) because typescript has a special readonly type for it that removes all the mutating functions from instances, so Maps are ReadonlyMaps, but ReadonlyMaps aren't Maps.

Mutable<T> could do an unsafe cast for that, but we could just as easily do that here too. There's little enough going on in this line of code that ignoring seemed fine, but maybe the cast would be better?

Copy link
Collaborator

Choose a reason for hiding this comment

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

not a big deal but even the unsafe cast of ReadonlyMap to Map would be a huge upgrade IMO so we can catch the compatibility of T :)

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 we can catch the compatibility of T

very good point, sold :)

I'll wait for #10461 to be landable so I can use tsc 3.7 stuff

@@ -670,31 +670,6 @@ describe('Runner', () => {
});
});

it('includes any LighthouseRunWarnings from errored audits in LHR', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe call out the loss of this as a breaking change in PR description so we remember to include that too in final notes?

@brendankenny
Copy link
Member Author

I'm not sure I trust audits any more than I did before, but OK :)

Maybe it would have been more correct to say it gives them better guidance on how to act :)

@brendankenny
Copy link
Member Author

@connorjclark what should I do about this travis failure?

legacy-javascript/run.js ran because this PR touched legacy-javascript/examine-latest-run.js, but it was only a mock change, so presumably the diff happened in a different commit/due to dependency changes.

0.04s$ git diff --exit-code
diff --git a/lighthouse-core/scripts/legacy-javascript/summary-sizes.txt b/lighthouse-core/scripts/legacy-javascript/summary-sizes.txt
index 2f33adb..9f1e83b 100644
--- a/lighthouse-core/scripts/legacy-javascript/summary-sizes.txt
+++ b/lighthouse-core/scripts/legacy-javascript/summary-sizes.txt
@@ -113,8 +113,8 @@ variants/core-js-2-only-polyfill
    3410 variants/core-js-2-only-polyfill/es6-function-name/main.bundle.min.js
 
 variants/core-js-2-preset-env-esmodules
-3567 total
-2259 variants/core-js-2-preset-env-esmodules/false/main.bundle.min.js
+4121 total
+2813 variants/core-js-2-preset-env-esmodules/false/main.bundle.min.js
 1308 variants/core-js-2-preset-env-esmodules/true/main.bundle.min.js
 
 variants/core-js-3-only-polyfill
@@ -232,13 +232,13 @@ variants/core-js-3-only-polyfill
    3410 variants/core-js-3-only-polyfill/es6-function-name/main.bundle.min.js
 
 variants/core-js-3-preset-env-esmodules
-3567 total
-2259 variants/core-js-3-preset-env-esmodules/false/main.bundle.min.js
+4121 total
+2813 variants/core-js-3-preset-env-esmodules/false/main.bundle.min.js
 1308 variants/core-js-3-preset-env-esmodules/true/main.bundle.min.js
 
 variants/only-plugin
-2793 total
-1152 variants/only-plugin/-babel-plugin-transform-spread/main.bundle.min.js
+3347 total
+1706 variants/only-plugin/-babel-plugin-transform-spread/main.bundle.min.js
  827 variants/only-plugin/-babel-plugin-transform-regenerator/main.bundle.min.js
  814 variants/only-plugin/-babel-plugin-transform-classes/main.bundle.min.js
 
The command "git diff --exit-code" exited with 1.

@brendankenny
Copy link
Member Author

my local changes from yarn test-legacy-javascript are also different than what the travis diff shows, so I'm just going to commit the travis diff and hope the cache hasn't changed in the meantime :)

I'll gate on your approval, though @connorjclark

@brendankenny brendankenny merged commit 3e5c664 into master Apr 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make settings/context immutable
5 participants