Skip to content

deps: update yargs to latest #11794

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

Merged
merged 5 commits into from
Dec 14, 2020
Merged

deps: update yargs to latest #11794

merged 5 commits into from
Dec 14, 2020

Conversation

brendankenny
Copy link
Contributor

fixes #11720

Two major parts of the update:

  • API updates. The biggest thing is that .boolean() no longer defaults to false, it defaults to undefined, while we've always relied on the default false. Also a bunch of other small improvements, like .number() and --version taking care of itself, etc
  • Type updates. @types/yargs has gotten super sophisticated, accumulating type info in each step of the cli flag declarations

The combo of the two started forcing more options (e.g. .boolean('flag').default('flag', false) or .option('flag', {type: 'boolean', default: false}), then arrays+strings and choices and descriptions...I eventually just opted to switch everything over to the options({flag1: opts, flag2: opts, ...}) format, which seems like a popular pattern looking at other projects.

DefinitelyTyped is limited to TypeScript 3.2 currently (and to < 4.0 until mid 2022), so types there can't do any manipulation with type names, like representing how yargs turns --some-flag into property someFlag...but we aren't limited by that :D This also adds a type transformation to model yarg's behavior. Originally I was going to augment the @types/yargs type to do that but the way yargs is set up it sends the compiler into an infinite loop before it cuts itself off. As a result, it's just a cast for now.

It's fancy, but it's really just a checked version of the unchecked cast we were doing from argv to LH.CliFlags before. It's all in typescript land, no effect on what's happening at runtime. I can revert to a plain cast if folks don't like it, though.

@brendankenny brendankenny requested a review from a team as a code owner December 9, 2020 04:42
@brendankenny brendankenny requested review from adamraine and removed request for a team December 9, 2020 04:42
@google-cla google-cla bot added the cla: yes label Dec 9, 2020
@@ -102,21 +102,6 @@ async function begin() {
' Please use "--emulated-form-factor=none" instead.');
}

if (typeof cliFlags.extraHeaders === 'string') {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

the coerce() functions from yargs gave a perfect place to do this loading/parsing and avoid the awkward type dance. Just moved into cli-flags


/**
* @param {string=} manualArgv
* @return {LH.CliFlags}
*/
function getFlags(manualArgv) {
// @ts-expect-error yargs() is incorrectly typed as not accepting a single string.
// @ts-expect-error - undocumented, but yargs() supports parsing a single `string`.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

still undocumented


// List of options
// Logging
Copy link
Contributor Author

Choose a reason for hiding this comment

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

the slightly weird order of options in here is due to our currently weird order of options. This cli-flags produces exactly the same --help order except --version and --help are switched, and there are more annotated [default: false] at the end of lines.

Happy to reorder.

},
'enable-error-reporting': {
type: 'boolean',
default: undefined, // Explicitly `undefined` so prompted by default.
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 is the case anyways now, but doesn't hurt to be explicit

// so for now cast to add yarg's camelCase properties to type.
const argv = /** @type {typeof rawArgv & CamelCasify<typeof rawArgv>} */ (rawArgv);

const jobs = Number.isFinite(argv.jobs) ? argv.jobs : undefined;
Copy link
Contributor Author

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 yargs.number() is less helpful than I'd hoped. --jobs texttext gives argv = { _: [], jobs: NaN} instead of throwing an error to the user like I hoped it would...

@@ -27,7 +27,7 @@ const {ProgressLogger} = require('./lantern/collect/common.js');
const LH_ROOT = `${__dirname}/../..`;
const ROOT_OUTPUT_DIR = `${LH_ROOT}/timings-data`;

const argv = yargs
const rawArgv = yargs
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@connorjclark I tried to minimize the changes needed in here. I don't think I changed any semantics

@@ -170,7 +198,7 @@ declare global {
chromeIgnoreDefaultFlags: boolean;
chromeFlags: string | string[];
/** Output path for the generated results. */
outputPath: string;
outputPath?: string;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

as far as I can tell, this has always been optional from cli-flags, and we rely on at least the falsy behavior of outputPath for report file naming, so seems ok to document the real type coming out of yargs

@paulirish
Copy link
Member

@brendankenny for documentation purposes, what are the breaking changes in here?

@brendankenny
Copy link
Contributor Author

@brendankenny for documentation purposes, what are the breaking changes in here?

Actually none that I know of, but my understanding from the eng meeting last week was that it's such a large jump in yargs versions that we should consider it breaking just in case.

'disable-storage-reset':
'Disable clearing the browser cache and other storage APIs before a run',
'emulated-form-factor': 'Controls the emulated device form factor (mobile vs. desktop) if not disabled',
'throttling-method': 'Controls throttling method',
'throttling.rttMs': 'Controls simulated network RTT (TCP layer)',
Copy link
Member

Choose a reason for hiding this comment

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

Why does this need to stay in a describe block?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why does this need to stay in a describe block?

because object support in yargs is half baked and I was putting off figuring out what to do with these and then I forgot to go back and do something with them :) I'll fix.

// TODO: this function does not actually verify the object type.
if (value === undefined) return value;
if (typeof value === 'object') return /** @type {LH.SharedFlagsSettings['extraHeaders']} */ (value);
if (typeof value !== 'string') throw new Error('asdfasf');
Copy link
Member

Choose a reason for hiding this comment

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

Descriptive error message?

@adamraine
Copy link
Member

Vscode is throwing some errors because of the backticks, are you seeing them as well?

Screen Shot 2020-12-09 at 6 31 57 PM

@connorjclark
Copy link
Collaborator

Make sure Code is using the TS version of the current workspace (also maybe try a yarn after you switch branches)

cmd shift p - typescript

image

@@ -120,12 +126,15 @@ function round(value) {
* @param {number} total
* @return {string}
*/
function getProgressBar(i, total = argv.n * argv.urls.length) {
function getProgressBar(i, total = argv.n * (argv.urls || []).length) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

no way to do required arrays?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no way to do required arrays?

But I think we only want a required array of urls if doing --collect? yargs.implies() can do that, I believe, but it's a little too indirect for the typescript type to infer off of. It might benefit the CLI experience, but a JS check or a default will still have to go somewhere.

I was trying to leave everything mostly untouched so it would all be recognizable when you were next back in here, but happy to commit any suggestions

Copy link
Collaborator

@connorjclark connorjclark left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Member

@adamraine adamraine left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Member

@paulirish paulirish left a comment

Choose a reason for hiding this comment

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

can you also update the --help output in the readme? I think it's a little stale already.


// We only have the single string positional argument, the url.
.option('_', {
array: true,
Copy link
Member

Choose a reason for hiding this comment

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

just curious why is this configured as an array?

Copy link
Contributor Author

@brendankenny brendankenny Dec 14, 2020

Choose a reason for hiding this comment

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

just curious why is this configured as an array?

Really just for types. _ is always an array, but setting the yargs option type to string erases the array part, this puts it back. I added a comment to make that clear.

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.

Update yargs to >4.0.0 to remediate y18n Prototype Pollution high severity vulnerability
6 participants