diff --git a/polygerrit-ui/app/.eslintrc.js b/polygerrit-ui/app/.eslintrc.js index 764d5e8d14..a3da3cf96a 100644 --- a/polygerrit-ui/app/.eslintrc.js +++ b/polygerrit-ui/app/.eslintrc.js @@ -55,6 +55,7 @@ module.exports = { }], // https://eslint.org/docs/rules/eol-last 'eol-last': 'off', + 'guard-for-in': 'error', // https://eslint.org/docs/rules/indent 'indent': ['error', 2, { MemberExpression: 2, diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts index 0b1e27ec9d..2124949a40 100644 --- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts +++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts @@ -34,7 +34,6 @@ import { InheritedBooleanInfo, } from '../../../types/common'; import {InheritedBooleanInfoConfiguredValue} from '../../../constants/constants'; -import {hasOwnProperty} from '../../../utils/common-util'; import {GrAutocomplete} from '../../shared/gr-autocomplete/gr-autocomplete'; import {IronAutogrowTextareaElement} from '@polymer/iron-autogrow-textarea/iron-autogrow-textarea'; import {appContext} from '../../../services/app-context'; @@ -174,19 +173,12 @@ export class GrCreateChangeDialog extends GestureEventListeners( .then(response => { if (!response) return []; const branches = []; - let branch; - for (const key in response) { - if (!hasOwnProperty(response, key)) { - continue; + for (const branchInfo of response) { + let name: string = branchInfo.ref; + if (name.startsWith('refs/heads/')) { + name = name.substring('refs/heads/'.length); } - if (response[key].ref.startsWith('refs/heads/')) { - branch = response[key].ref.substring('refs/heads/'.length); - } else { - branch = response[key].ref; - } - branches.push({ - name: branch, - }); + branches.push({name}); } return branches; }); diff --git a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts index 1b16052a7c..c9fd241a50 100644 --- a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts +++ b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts @@ -28,7 +28,6 @@ import {encodeURL, getBaseUrl} from '../../../utils/url-util'; import {page} from '../../../utils/page-wrapper-utils'; import {customElement, observe, property} from '@polymer/decorators'; import {ProjectInput, RepoName} from '../../../types/common'; -import {hasOwnProperty} from '../../../utils/common-util'; import {AutocompleteQuery} from '../../shared/gr-autocomplete/gr-autocomplete'; import {appContext} from '../../../services/app-context'; @@ -115,14 +114,8 @@ export class GrCreateRepoDialog extends GestureEventListeners( _getRepoSuggestions(input: string) { return this.restApiService.getSuggestedProjects(input).then(response => { const repos = []; - for (const key in response) { - if (!hasOwnProperty(response, key)) { - continue; - } - repos.push({ - name: key, - value: response[key].id, - }); + for (const [name, project] of Object.entries(response ?? {})) { + repos.push({name, value: project.id}); } return repos; }); @@ -131,14 +124,8 @@ export class GrCreateRepoDialog extends GestureEventListeners( _getGroupSuggestions(input: string) { return this.restApiService.getSuggestedGroups(input).then(response => { const groups = []; - for (const key in response) { - if (!hasOwnProperty(response, key)) { - continue; - } - groups.push({ - name: key, - value: decodeURIComponent(response[key].id), - }); + for (const [name, group] of Object.entries(response ?? {})) { + groups.push({name, value: decodeURIComponent(group.id)}); } return groups; }); diff --git a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.ts b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.ts index 888647fed3..f5602a3d47 100644 --- a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.ts +++ b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.ts @@ -39,9 +39,11 @@ import { GroupInfo, GroupName, } from '../../../types/common'; -import {AutocompleteQuery} from '../../shared/gr-autocomplete/gr-autocomplete'; +import { + AutocompleteQuery, + AutocompleteSuggestion, +} from '../../shared/gr-autocomplete/gr-autocomplete'; import {PolymerDomRepeatEvent} from '../../../types/types'; -import {hasOwnProperty} from '../../../utils/common-util'; import { fireAlert, firePageError, @@ -339,23 +341,18 @@ export class GrGroupMembers extends GestureEventListeners( return this.restApiService .getSuggestedAccounts(input, SUGGESTIONS_LIMIT) .then(accounts => { + if (!accounts) return []; const accountSuggestions = []; - let nameAndEmail; - if (!accounts) { - return []; - } - for (const key in accounts) { - if (!hasOwnProperty(accounts, key)) { - continue; - } - if (accounts[key].email !== undefined) { - nameAndEmail = `${accounts[key].name} <${accounts[key].email}>`; + for (const account of accounts) { + let nameAndEmail; + if (account.email !== undefined) { + nameAndEmail = `${account.name} <${account.email}>`; } else { - nameAndEmail = accounts[key].name; + nameAndEmail = account.name; } accountSuggestions.push({ name: nameAndEmail, - value: accounts[key]._account_id?.toString(), + value: account._account_id?.toString(), }); } return accountSuggestions; @@ -364,15 +361,9 @@ export class GrGroupMembers extends GestureEventListeners( _getGroupSuggestions(input: string) { return this.restApiService.getSuggestedGroups(input).then(response => { - const groups = []; - for (const key in response) { - if (!hasOwnProperty(response, key)) { - continue; - } - groups.push({ - name: key, - value: decodeURIComponent(response[key].id), - }); + const groups: AutocompleteSuggestion[] = []; + for (const [name, group] of Object.entries(response ?? {})) { + groups.push({name, value: decodeURIComponent(group.id)}); } return groups; }); diff --git a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.js b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.js index 654d24ac04..672ac076d0 100644 --- a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.js +++ b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.js @@ -100,7 +100,7 @@ suite('gr-group-members tests', () => { }, ]); } else { - return Promise.resolve({}); + return Promise.resolve([]); } }); stubRestApi('getSuggestedGroups').callsFake(input => { diff --git a/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts b/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts index cee803ccc1..058f86be4c 100644 --- a/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts +++ b/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts @@ -33,7 +33,6 @@ import { } from '../../shared/gr-autocomplete/gr-autocomplete'; import {GroupId, GroupInfo, GroupName} from '../../../types/common'; import {ErrorCallback} from '../../../services/gr-rest-api/gr-rest-api'; -import {hasOwnProperty} from '../../../utils/common-util'; import { fireEvent, firePageError, @@ -301,14 +300,8 @@ export class GrGroup extends GestureEventListeners( _getGroupSuggestions(input: string) { return this.restApiService.getSuggestedGroups(input).then(response => { const groups: AutocompleteSuggestion[] = []; - for (const key in response) { - if (!hasOwnProperty(response, key)) { - continue; - } - groups.push({ - name: key, - value: decodeURIComponent(response[key].id), - }); + for (const [name, group] of Object.entries(response ?? {})) { + groups.push({name, value: decodeURIComponent(group.id)}); } return groups; }); diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.ts b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.ts index 65a3b00602..5702bfbe70 100644 --- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.ts +++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.ts @@ -33,7 +33,6 @@ import { PermissionArray, } from '../../../utils/access-util'; import {customElement, property, observe} from '@polymer/decorators'; -import {hasOwnProperty} from '../../../utils/common-util'; import { LabelNameToLabelTypeInfoMap, LabelTypeInfoValues, @@ -333,14 +332,8 @@ export class GrPermission extends GestureEventListeners( .getSuggestedGroups(this._groupFilter || '', MAX_AUTOCOMPLETE_RESULTS) .then(response => { const groups: GroupSuggestion[] = []; - for (const key in response) { - if (!hasOwnProperty(response, key)) { - continue; - } - groups.push({ - name: key, - value: response[key], - }); + for (const [name, value] of Object.entries(response ?? {})) { + groups.push({name, value}); } // Does not return groups in which we already have rules for. return groups diff --git a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.ts b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.ts index 9fb79d33c8..935d091654 100644 --- a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.ts +++ b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.ts @@ -37,7 +37,6 @@ import { UrlEncodedRepoName, ProjectAccessGroups, } from '../../../types/common'; -import {hasOwnProperty} from '../../../utils/common-util'; import {GrButton} from '../../shared/gr-button/gr-button'; import {GrAccessSection} from '../gr-access-section/gr-access-section'; import { @@ -370,11 +369,9 @@ export class GrRepoAccess extends GestureEventListeners( /** * Used to recursively remove any objects with a 'deleted' bit. */ - _recursivelyRemoveDeleted(obj: PropertyTreeNode) { - for (const k in obj) { - if (!hasOwnProperty(obj, k)) { - continue; - } + _recursivelyRemoveDeleted(obj?: PropertyTreeNode) { + if (!obj) return; + for (const k of Object.keys(obj)) { const node = obj[k]; if (typeof node === 'object') { if (node.deleted) { @@ -387,17 +384,15 @@ export class GrRepoAccess extends GestureEventListeners( } _recursivelyUpdateAddRemoveObj( - obj: PropertyTreeNode, + obj: PropertyTreeNode | undefined, addRemoveObj: { add: PropertyTreeNode; remove: PropertyTreeNode; }, path: string[] = [] ) { - for (const k in obj) { - if (!hasOwnProperty(obj, k)) { - continue; - } + if (!obj) return; + for (const k of Object.keys(obj)) { const node = obj[k]; if (typeof node === 'object') { const updatedId = node.updatedId; diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.ts b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.ts index 1c30e9650a..3543e3b998 100644 --- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.ts +++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.ts @@ -392,21 +392,14 @@ export class GrRepo extends GestureEventListeners( schemesObj?: SchemesInfoMap, _selectedScheme?: string ) { - if (!schemesObj || !repo || !_selectedScheme) { - return []; - } + if (!schemesObj || !repo || !_selectedScheme) return []; + if (!hasOwnProperty(schemesObj, _selectedScheme)) return []; + const commandObj = schemesObj[_selectedScheme].clone_commands; const commands = []; - let commandObj: {[title: string]: string} = {}; - if (hasOwnProperty(schemesObj, _selectedScheme)) { - commandObj = schemesObj[_selectedScheme].clone_commands; - } - for (const title in commandObj) { - if (!hasOwnProperty(commandObj, title)) { - continue; - } + for (const [title, command] of Object.entries(commandObj)) { commands.push({ title, - command: commandObj[title] + command: command .replace(/\${project}/gi, encodeURI(repo)) .replace( /\${project-base-name}/gi, diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts index 973ccc86ec..441d514aa9 100644 --- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts +++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts @@ -37,17 +37,16 @@ import { } from '../../../types/common'; import {ChangeListToggleReviewedDetail} from '../gr-change-list-item/gr-change-list-item'; import {ChangeStarToggleStarDetail} from '../../shared/gr-change-star/gr-change-star'; -import {hasOwnProperty} from '../../../utils/common-util'; import {ChangeListViewState} from '../../../types/types'; import {fireTitleChange} from '../../../utils/event-util'; import {appContext} from '../../../services/app-context'; import {GerritView} from '../../../services/router/router-model'; -const LookupQueryPatterns = { - CHANGE_ID: /^\s*i?[0-9a-f]{7,40}\s*$/i, - CHANGE_NUM: /^\s*[1-9][0-9]*\s*$/g, - COMMIT: /[0-9a-f]{40}/, -}; +const LOOKUP_QUERY_PATTERNS: RegExp[] = [ + /^\s*i?[0-9a-f]{7,40}\s*$/i, // CHANGE_ID + /^\s*[1-9][0-9]*\s*$/g, // CHANGE_NUM + /[0-9a-f]{40}/, // COMMIT +]; const USER_QUERY_PATTERN = /^owner:\s?("[^"]+"|[^ ]+)$/; @@ -159,12 +158,8 @@ export class GrChangeListView extends GestureEventListeners( .then(changes => { changes = changes || []; if (this._query && changes.length === 1) { - let query: keyof typeof LookupQueryPatterns; - for (query in LookupQueryPatterns) { - if ( - hasOwnProperty(LookupQueryPatterns, query) && - this._query.match(LookupQueryPatterns[query]) - ) { + for (const queryPattern of LOOKUP_QUERY_PATTERNS) { + if (this._query.match(queryPattern)) { // "Back"/"Forward" buttons work correctly only with // opt_redirect options GerritNav.navigateToChange( diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts index 96714e3274..903afaac1b 100644 --- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts +++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts @@ -940,14 +940,14 @@ export class GrChangeActions return null; } let result; - for (const label in this.change.labels) { + for (const [label, labelInfo] of Object.entries(this.change.labels)) { if (!(label in this.change.permitted_labels)) { continue; } if (this.change.permitted_labels[label].length === 0) { continue; } - const status = this._getLabelStatus(this.change.labels[label]); + const status = this._getLabelStatus(labelInfo); if (status === LabelStatus.NEED) { if (result) { // More than one label is missing, so it's unclear which to quick diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts index fe68cdc19f..7fd7126e2f 100644 --- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts +++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts @@ -2077,21 +2077,15 @@ export class GrChangeView extends KeyboardShortcutMixin( } _getLatestRevisionSHA(change: ChangeInfo | ParsedChangeInfo) { - if (change.current_revision) { - return change.current_revision; - } + if (change.current_revision) return change.current_revision; // current_revision may not be present in the case where the latest rev is // a draft and the user doesn’t have permission to view that rev. let latestRev = null; let latestPatchNum = -1 as PatchSetNum; - for (const rev in change.revisions) { - if (!hasOwnProperty(change.revisions, rev)) { - continue; - } - - if (change.revisions[rev]._number > latestPatchNum) { + for (const [rev, revInfo] of Object.entries(change.revisions ?? {})) { + if (revInfo._number > latestPatchNum) { latestRev = rev; - latestPatchNum = change.revisions[rev]._number; + latestPatchNum = revInfo._number; } } return latestRev; diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts index 285571635c..10cffba004 100644 --- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts +++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts @@ -37,7 +37,6 @@ import {ReportingService} from '../../../services/gr-reporting/gr-reporting'; import {customElement, property, observe} from '@polymer/decorators'; import {AutocompleteSuggestion} from '../../shared/gr-autocomplete/gr-autocomplete'; import {HttpMethod, ChangeStatus} from '../../../constants/constants'; -import {hasOwnProperty} from '../../../utils/common-util'; import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom'; const SUGGESTIONS_LIMIT = 15; @@ -399,21 +398,16 @@ export class GrConfirmCherrypickDialog extends GestureEventListeners( return this.restApiService .getRepoBranches(input, this.project, SUGGESTIONS_LIMIT) .then((response: BranchInfo[] | undefined) => { - const branches = []; if (!response) return []; - let branch; - for (const key in response) { - if (!hasOwnProperty(response, key)) { - continue; - } - if (response[key].ref.startsWith('refs/heads/')) { - branch = response[key].ref.substring('refs/heads/'.length); + const branches = []; + for (const branchInfo of response) { + let branch; + if (branchInfo.ref.startsWith('refs/heads/')) { + branch = branchInfo.ref.substring('refs/heads/'.length); } else { - branch = response[key].ref; + branch = branchInfo.ref; } - branches.push({ - name: branch, - }); + branches.push({name: branch}); } return branches; }); diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js index e4ed5335bb..536a4abedb 100644 --- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js +++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js @@ -39,7 +39,7 @@ suite('gr-confirm-cherrypick-dialog tests', () => { }, ]); } else { - return Promise.resolve({}); + return Promise.resolve([]); } }); element = basicFixture.instantiate(); @@ -77,11 +77,9 @@ suite('gr-confirm-cherrypick-dialog tests', () => { assert.equal(element.message, myNewMessage); }); - test('_getProjectBranchesSuggestions empty', done => { - element._getProjectBranchesSuggestions('nonexistent').then(branches => { - assert.equal(branches.length, 0); - done(); - }); + test('_getProjectBranchesSuggestions empty', async () => { + const branches = await element._getProjectBranchesSuggestions('asdf'); + assert.isEmpty(branches); }); suite('cherry pick topic', () => { diff --git a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts index 9e7bdb4c58..9dcd849450 100644 --- a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts +++ b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts @@ -22,7 +22,6 @@ import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mix import {PolymerElement} from '@polymer/polymer/polymer-element'; import {htmlTemplate} from './gr-confirm-rebase-dialog_html'; import {customElement, property, observe} from '@polymer/decorators'; -import {hasOwnProperty} from '../../../utils/common-util'; import {NumericChangeId, BranchName} from '../../../types/common'; import { GrAutocomplete, @@ -109,13 +108,10 @@ export class GrConfirmRebaseDialog extends GestureEventListeners( .then(response => { if (!response) return []; const changes: RebaseChange[] = []; - for (const key in response) { - if (!hasOwnProperty(response, key)) { - continue; - } + for (const change of response) { changes.push({ - name: `${response[key]._number}: ${response[key].subject}`, - value: response[key]._number, + name: `${change._number}: ${change.subject}`, + value: change._number, }); } this._recentChanges = changes; diff --git a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.ts b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.ts index 7fbe4b5a55..ab1e4e6f51 100644 --- a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.ts +++ b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.ts @@ -122,14 +122,8 @@ export class GrDownloadDialog extends GestureEventListeners( } } const commands = []; - for (const title in commandObj) { - if (!commandObj || !hasOwnProperty(commandObj, title)) { - continue; - } - commands.push({ - title, - command: commandObj[title], - }); + for (const [title, command] of Object.entries(commandObj ?? {})) { + commands.push({title, command}); } return commands; } diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts index d41a662150..efa4c7db13 100644 --- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts +++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts @@ -67,7 +67,6 @@ import { import {DiffPreferencesInfo} from '../../../types/diff'; import {GrDiffHost} from '../../diff/gr-diff-host/gr-diff-host'; import {GrDiffPreferencesDialog} from '../../diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog'; -import {hasOwnProperty} from '../../../utils/common-util'; import {GrDiffCursor} from '../../diff/gr-diff-cursor/gr-diff-cursor'; import {GrCursorManager} from '../../shared/gr-cursor-manager/gr-cursor-manager'; import {PolymerSpliceChange} from '@polymer/polymer/interfaces'; @@ -1241,13 +1240,9 @@ export class GrFileList extends KeyboardShortcutMixin( const files: FileNameToReviewedFileInfoMap = {...filesByPath}; addUnmodifiedFiles(files, commentedPaths); const reviewedSet = new Set(reviewed || []); - for (const filePath in files) { - if (!hasOwnProperty(files, filePath)) { - continue; - } - files[filePath].isReviewed = reviewedSet.has(filePath); + for (const [filePath, reviewedFileInfo] of Object.entries(files)) { + reviewedFileInfo.isReviewed = reviewedSet.has(filePath); } - this._files = this._normalizeChangeFilesResponse(files); } diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js index 77855dff5a..2d38dcca85 100644 --- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js +++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js @@ -306,11 +306,8 @@ suite('gr-file-list tests', () => { '-1073741824': '-1 GiB', '0': '+/-0 B', }; - - for (const bytes in table) { - if (table.hasOwnProperty(bytes)) { - assert.equal(element._formatBytes(Number(bytes)), table[bytes]); - } + for (const [bytes, expected] of Object.entries(table)) { + assert.equal(element._formatBytes(Number(bytes)), expected); } }); @@ -590,12 +587,8 @@ suite('gr-file-list tests', () => { flush(); assert.equal(element.diffs.length, paths.length); assert.equal(element._expandedFiles.length, paths.length); - for (const index in element.diffs) { - if (!element.diffs.hasOwnProperty(index)) { continue; } - assert.isTrue( - element._expandedFiles - .some(f => f.path === element.diffs[index].path) - ); + for (const diff of element.diffs) { + assert.isTrue(element._expandedFiles.some(f => f.path === diff.path)); } MockInteractions.keyUpOn(element, 73, 'shift', 'i'); diff --git a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.ts b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.ts index b994fa53da..f8cd42cae0 100644 --- a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.ts +++ b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.ts @@ -65,11 +65,7 @@ export class GrLabelScores extends GestureEventListeners( if (this.shadowRoot === null || !this.change) { return labels; } - for (const label in this.permittedLabels) { - if (!hasOwnProperty(this.permittedLabels, label)) { - continue; - } - + for (const label of Object.keys(this.permittedLabels ?? {})) { const selectorEl = this.shadowRoot.querySelector( `gr-label-score-row[name="${label}"]` ) as null | GrLabelScoreRow; @@ -104,9 +100,10 @@ export class GrLabelScores extends GestureEventListeners( labelName: string, numberValue?: number ) { - for (const k in (labels[labelName] as DetailedLabelInfo).values) { - if (Number(k) === numberValue) { - return k; + const detailedInfo = labels[labelName] as DetailedLabelInfo; + for (const labelValue of Object.keys(detailedInfo.values)) { + if (Number(labelValue) === numberValue) { + return labelValue; } } return numberValue; diff --git a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.js b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.js index 5135e43989..ef123c98c1 100644 --- a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.js +++ b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.js @@ -85,12 +85,10 @@ suite('gr-label-scores tests', () => { }); test('get and set label scores', () => { - for (const label in element.permittedLabels) { - if (element.permittedLabels.hasOwnProperty(label)) { - const row = element.shadowRoot - .querySelector('gr-label-score-row[name="' + label + '"]'); - row.setSelectedValue(-1); - } + for (const label of Object.keys(element.permittedLabels)) { + const row = element.shadowRoot + .querySelector('gr-label-score-row[name="' + label + '"]'); + row.setSelectedValue(-1); } assert.deepEqual(element.getLabelValues(), { 'Code-Review': -1, diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.js b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.js index 2b92ca6474..6682bfbc5d 100644 --- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.js +++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.js @@ -1001,8 +1001,8 @@ suite('gr-reply-dialog tests', () => { }; }; const checkObjEmpty = function(obj) { - for (const prop in obj) { - if (obj.hasOwnProperty(prop) && obj[prop].length) { return false; } + for (const prop of Object.keys(obj)) { + if (obj[prop].length) { return false; } } return true; }; diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.ts b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.ts index 254eccac75..30931c311f 100644 --- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.ts +++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.ts @@ -231,7 +231,7 @@ export class GrReviewerList extends GestureEventListeners( } let result: AccountInfo[] = []; const reviewers = changeRecord.base; - for (const key in reviewers) { + for (const key of Object.keys(reviewers)) { if (this.reviewersOnly && key !== 'REVIEWER') { continue; } diff --git a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.ts b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.ts index 1085fbcf8a..468c8ca4f5 100644 --- a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.ts +++ b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.ts @@ -32,7 +32,6 @@ import { FileInfo, ParentPatchSetNum, } from '../../../types/common'; -import {hasOwnProperty} from '../../../utils/common-util'; import { Comment, CommentMap, @@ -149,15 +148,11 @@ export class ChangeComments { ]; const commentMap: CommentMap = {}; for (const response of responses) { - for (const path in response) { + for (const [path, comments] of Object.entries(response)) { if ( - hasOwnProperty(response, path) && - response[path].some(c => { + comments.some(c => { // If don't care about patch range, we know that the path exists. - if (!patchRange) { - return true; - } - return isInPatchRange(c, patchRange); + return !patchRange || isInPatchRange(c, patchRange); }) ) { commentMap[path] = true; diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts index 1e9b1cc18b..62b34e9c05 100644 --- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts +++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts @@ -85,7 +85,6 @@ import {FilesWebLinks} from '../gr-patch-range-select/gr-patch-range-select'; import {PolymerDeepPropertyChange} from '@polymer/polymer/interfaces'; import {GrDiffCursor} from '../gr-diff-cursor/gr-diff-cursor'; import {CommentSide, DiffViewMode, Side} from '../../../constants/constants'; -import {hasOwnProperty} from '../../../utils/common-util'; import {GrApplyFixDialog} from '../gr-apply-fix-dialog/gr-apply-fix-dialog'; import {LineOfInterest} from '../gr-diff/gr-diff'; import {RevisionInfo as RevisionInfoObj} from '../../shared/revision-info/revision-info'; @@ -896,9 +895,8 @@ export class GrDiffView extends KeyboardShortcutMixin( let baseCommit: CommitId | undefined; if (!this._change) return; if (!this._patchRange || !this._patchRange.patchNum) return; - for (const commitSha in this._change.revisions) { - if (!hasOwnProperty(this._change.revisions, commitSha)) continue; - const revision = this._change.revisions[commitSha]; + const revisions = this._change.revisions ?? {}; + for (const [commitSha, revision] of Object.entries(revisions)) { const patchNum = revision._number; if (patchNum === this._patchRange.patchNum) { commit = commitSha as CommitId; diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js index 8fe06f8f5d..34e74b6bac 100644 --- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js +++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js @@ -812,10 +812,7 @@ suite('gr-diff-view tests', () => { } test('edit visible only when logged and status NEW', async () => { - for (const changeStatus in ChangeStatus) { - if (!ChangeStatus.hasOwnProperty(changeStatus)) { - continue; - } + for (const changeStatus of Object.keys(ChangeStatus)) { assert.isFalse(await isEditVisibile({loggedIn: false, changeStatus}), `loggedIn: false, changeStatus: ${changeStatus}`); diff --git a/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.js b/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.js index c41b551019..1c606cde8f 100644 --- a/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.js +++ b/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.js @@ -172,12 +172,10 @@ suite('gr-styles-api tests', () => { } function assertDisplayPropertyValues(elements, expectedDisplayValues) { - for (const key in elements) { - if (elements.hasOwnProperty(key)) { - assert.equal( - getComputedStyle(elements[key]).getPropertyValue('display'), - expectedDisplayValues[key]); - } + for (let i = 0; i < elements.length; i++) { + assert.equal( + getComputedStyle(elements[i]).getPropertyValue('display'), + expectedDisplayValues[i]); } } }); diff --git a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.js b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.js index ce9c106219..1088585318 100644 --- a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.js +++ b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.js @@ -61,10 +61,8 @@ suite('gr-registration-dialog tests', () => { }); teardown(() => { - for (const eventType in _listeners) { - if (_listeners.hasOwnProperty(eventType)) { - element.removeEventListener(eventType, _listeners[eventType]); - } + for (const [eventType, listeners] of Object.entries(_listeners)) { + element.removeEventListener(eventType, listeners); } }); diff --git a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.ts b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.ts index 36444a32cf..a45e160507 100644 --- a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.ts +++ b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.ts @@ -121,14 +121,8 @@ export class GrWatchedProjectsEditor extends GestureEventListeners( _getProjectSuggestions(input: string) { return this.restApiService.getSuggestedProjects(input).then(response => { const projects: AutocompleteSuggestion[] = []; - for (const key in response) { - if (!hasOwnProperty(response, key)) { - continue; - } - projects.push({ - name: key, - value: response[key].id, - }); + for (const [name, project] of Object.entries(response ?? {})) { + projects.push({name, value: project.id}); } return projects; }); diff --git a/polygerrit-ui/app/elements/shared/gr-linked-text/link-text-parser.ts b/polygerrit-ui/app/elements/shared/gr-linked-text/link-text-parser.ts index 9066911238..36f518b5a6 100644 --- a/polygerrit-ui/app/elements/shared/gr-linked-text/link-text-parser.ts +++ b/polygerrit-ui/app/elements/shared/gr-linked-text/link-text-parser.ts @@ -350,27 +350,27 @@ export class GrLinkTextParser { // The outputArray is used to store all of the matches found for all // patterns. const outputArray: CommentLinkItem[] = []; - for (const p in config) { + for (const [configName, linkInfo] of Object.entries(config)) { // TODO(TS): it seems, the following line can be rewritten as: // if(enabled === false || enabled === 0 || enabled === '') // Should be double-checked before update // eslint-disable-next-line eqeqeq - if (config[p].enabled != null && config[p].enabled == false) { + if (linkInfo.enabled != null && linkInfo.enabled == false) { continue; } // PolyGerrit doesn't use hash-based navigation like the GWT UI. // Account for this. - const html = config[p].html; - const link = config[p].link; + const html = linkInfo.html; + const link = linkInfo.link; if (html) { - config[p].html = html.replace(/ = []; - for (const p in fetchParams) { - if (!hasOwnProperty(fetchParams, p)) { - continue; - } - const paramValue = fetchParams[p]; + for (const [p, paramValue] of Object.entries(fetchParams)) { // TODO(TS): Replace == null with === and check for null and undefined // eslint-disable-next-line eqeqeq if (paramValue == null) { @@ -482,11 +477,8 @@ s */ if (!options.headers) { options.headers = new Headers(); } - for (const header in req.headers) { - if (!hasOwnProperty(req.headers, header)) { - continue; - } - options.headers.set(header, req.headers[header]); + for (const [name, value] of Object.entries(req.headers)) { + options.headers.set(name, value); } } const url = req.url.startsWith('http') ? req.url : getBaseUrl() + req.url; diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser.ts b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser.ts index 809b78b48c..1a1062c984 100644 --- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser.ts +++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser.ts @@ -25,7 +25,6 @@ import { ReviewerUpdateInfo, Timestamp, } from '../../../types/common'; -import {hasOwnProperty} from '../../../utils/common-util'; import {accountKey} from '../../../utils/account-util'; import { FormattedReviewerUpdateInfo, @@ -122,12 +121,10 @@ export class GrReviewerUpdatesParser { */ private _completeBatch(batch: ParserBatch) { const items = []; - for (const accountId in this._updateItems) { - if (!hasOwnProperty(this._updateItems, accountId)) continue; - const updateItem = this._updateItems[accountId]; - if (this._lastState[accountId] !== updateItem.state) { - this._lastState[accountId] = updateItem.state; - items.push(updateItem); + for (const [accountId, item] of Object.entries(this._updateItems ?? {})) { + if (this._lastState[accountId] !== item.state) { + this._lastState[accountId] = item.state; + items.push(item); } } if (items.length) { @@ -233,15 +230,10 @@ export class GrReviewerUpdatesParser { const reviewerUpdates = (this.result .reviewer_updates as unknown) as ParserBatchWithNonEmptyUpdates[]; for (const update of reviewerUpdates) { - const grouppedReviewers = this._groupUpdatesByMessage(update.updates); + const groupedReviewers = this._groupUpdatesByMessage(update.updates); const newUpdates: {message: string; reviewers: AccountInfo[]}[] = []; - for (const message in grouppedReviewers) { - if (hasOwnProperty(grouppedReviewers, message)) { - newUpdates.push({ - message, - reviewers: grouppedReviewers[message], - }); - } + for (const [message, reviewers] of Object.entries(groupedReviewers)) { + newUpdates.push({message, reviewers}); } ((update as unknown) as FormattedReviewerUpdateInfo).updates = newUpdates; } diff --git a/polygerrit-ui/app/test/common-test-setup.ts b/polygerrit-ui/app/test/common-test-setup.ts index beba88e9ce..6109653d5e 100644 --- a/polygerrit-ui/app/test/common-test-setup.ts +++ b/polygerrit-ui/app/test/common-test-setup.ts @@ -43,7 +43,6 @@ import { _testOnly_defaultResinReportHandler, installPolymerResin, } from '../scripts/polymer-resin-install'; -import {hasOwnProperty} from '../utils/common-util'; declare global { interface Window { @@ -132,12 +131,9 @@ function stubImpl( // This method is inspired by web-component-tester method const proto = document.createElement(tagName).constructor .prototype as HTMLElementTagNameMap[T]; - let key: keyof HTMLElementTagNameMap[T]; const stubs: SinonSpy[] = []; - for (key in implementation) { - if (hasOwnProperty(implementation, key)) { - stubs.push(sinon.stub(proto, key).callsFake(implementation[key])); - } + for (const [key, value] of Object.entries(implementation)) { + stubs.push(sinon.stub(proto, key).callsFake(value)); } registerTestCleanup(() => { stubs.forEach(stub => {