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

Update dependencies and lint #2391

Merged
merged 5 commits into from Aug 30, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
694 changes: 446 additions & 248 deletions package-lock.json

Large diffs are not rendered by default.

44 changes: 24 additions & 20 deletions package.json
Expand Up @@ -40,7 +40,7 @@
"shorten-repo-url": "^1.5.2",
"tiny-version-compare": "^1.0.0",
"webext-additional-permissions": "^0.1.0",
"webext-detect-page": "^1.0.2",
"webext-detect-page": "^1.0.3",
"webext-domain-permission-toggle": "^1.0.0",
"webext-dynamic-content-scripts": "^6.0.3",
"webext-options-sync": "^1.0.0-8",
Expand All @@ -51,41 +51,41 @@
},
"devDependencies": {
"@sindresorhus/tsconfig": "^0.4.0",
"@types/chrome": "0.0.86",
"@types/chrome": "0.0.88",
"@types/codemirror": "0.0.76",
"@types/copy-webpack-plugin": "^5.0.0",
"@types/firefox-webext-browser": "^67.0.2",
"@types/jsdom": "^12.2.4",
"@types/mini-css-extract-plugin": "^0.2.1",
"@types/react": "^16.8.23",
"@types/mini-css-extract-plugin": "^0.8.0",
"@types/react": "^16.9.2",
"@types/terser-webpack-plugin": "^1.2.1",
"@typescript-eslint/eslint-plugin": "^1.11.0",
"@typescript-eslint/parser": "^1.11.0",
"ava": "^2.2.0",
"@typescript-eslint/eslint-plugin": "^1.13.0",
"@typescript-eslint/parser": "^1.13.0",
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'm temporarily avoiding v2 because of a bug I don't know how to work around: typescript-eslint/typescript-eslint#890

webpack.config.ts:undefined:undefined
✖ 0:0 Parsing error: If "parserOptions.project" has been set for @typescript-eslint/parser, ./webpack.config.ts must be included in at least one of the projects provided.

test/page-detect.ts:undefined:undefined
✖ 0:0 Parsing error: If "parserOptions.project" has been set for @typescript-eslint/parser, ./test/page-detect.ts must be included in at least one of the projects provided.

test/utils.ts:undefined:undefined
✖ 0:0 Parsing error: If "parserOptions.project" has been set for @typescript-eslint/parser, ./test/utils.ts must be included in at least one of the projects provided.

test/fixtures/globals.ts:undefined:undefined
✖ 0:0 Parsing error: If "parserOptions.project" has been set for @typescript-eslint/parser, ./test/fixtures/globals.ts must be included in at least one of the projects provided.

They should go away by adding test in tsconfig's includes, but that file appears to be ignored.

Also reported in xojs/eslint-config-xo-typescript#15

"ava": "^2.3.0",
"chrome-webstore-upload-cli": "^1.2.0",
"copy-webpack-plugin": "^5.0.3",
"css-loader": "^3.0.0",
"copy-webpack-plugin": "^5.0.4",
"css-loader": "^3.2.0",
"daily-version": "^0.12.0",
"dot-json": "^1.0.4",
"eslint": "^6.0.1",
"eslint-config-xo-typescript": "^0.15.0",
"fork-ts-checker-webpack-plugin": "^1.3.7",
"eslint": "^6.2.2",
"eslint-config-xo-typescript": "^0.16.0",
"fork-ts-checker-webpack-plugin": "^1.5.0",
"jsdom": "^15.1.1",
"mini-css-extract-plugin": "^0.7.0",
"mini-css-extract-plugin": "^0.8.0",
"npm-run-all": "^4.1.3",
"size-plugin": "^1.2.0",
"size-plugin": "^2.0.0",
"string-replace-loader": "^2.2.0",
"stylelint": "^10.1.0",
"stylelint-config-xo": "^0.15.0",
"terser-webpack-plugin": "^1.3.0",
"terser-webpack-plugin": "^1.4.1",
"ts-loader": "^6.0.4",
"ts-node": "^8.3.0",
"type-fest": "^0.6.0",
"typescript": "^3.5.3",
"type-fest": "^0.7.1",
"typescript": "^3.6.2",
"web-ext": "^3.1.1",
"web-ext-submit": "^3.1.1",
"webpack": "^4.35.3",
"webpack-cli": "^3.3.5",
"webpack": "^4.39.3",
"webpack-cli": "^3.3.7",
"xo": "^0.24.0"
},
"xo": {
Expand All @@ -105,13 +105,17 @@
"rules": {
"no-alert": "off",
"import/no-unassigned-import": "off",
"import/no-unresolved": "warn"
"import/no-unresolved": "warn",
"import/named": "warn"
Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

That rule has other problems too. Disabled: xojs/xo@ee145cb

},
"overrides": [
{
"files": "**/*.+(ts|tsx)",
"extends": "xo-typescript",
"rules": {
"@typescript-eslint/no-misused-promises": "off",
Copy link
Member Author

Choose a reason for hiding this comment

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

Annoying: It doesn't let us use async functions as event handlers.

Copy link
Member

Choose a reason for hiding this comment

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

While it's convenient, my reasoning is that using async there makes it hard to see that the event handler function will cause an uncaught rejection if the await rejects. For example, using async in a new Promise can cause hard to track down issues.

And when people see:

[1, 2, 3].forEach(async value => {
  await doSomething(value);
});

they might be fooled into thinking that it awaits for each iteration, which it does not.

I'm happy to discuss this though. Maybe there some additional config that could be added to the rule?

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 understand the value in that case, but I don't have a solution for our use-case: our handlers are async just because Promise handling is great, not because anyone expects addEventListener to await them.

If we enable this rule, we have to write listeners as:

function handler() {
	(async () => {
		document.body.append(await fetchDom(...));
	})();
}

Copy link
Member Author

Choose a reason for hiding this comment

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

A more useful related rule would be the opposite: always await async functions. Does this exist already?

async function set(){...}
async function get(){...}
set(1); // Forgot `await`
await get();

Copy link
Member

Choose a reason for hiding this comment

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

A more useful related rule would be the opposite: always await async functions. Does this exist already?

This? https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-floating-promises.md

Copy link
Member Author

Choose a reason for hiding this comment

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

Almost, returnsPromise() is not awaited even though it returns a promise. It seems that it requires await only on variables

"@typescript-eslint/promise-function-async": "off",
"@typescript-eslint/no-explicit-any": "off",
Copy link
Member Author

@fregante fregante Aug 29, 2019

Choose a reason for hiding this comment

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

Good in theory, but makes us have to type one-off things just for the heck of it:

  • Code examples:

     (window as any).select = select;
     const editor: CodeMirrorInstance = document.querySelector<any>('.CodeMirror').CodeMirror;
     (global as any).navigator = window.navigator;
     (global as any).document = window.document;
     (global as any).location = new URL('https://github.com');
    
     // Which becomes:
     (global as unknown as typeof window).navigator = window.navigator;
     (global as unknown as typeof window).document = window.document;
     (global as unknown as typeof window).location = new URL('https://github.com');
  • It'd force us to type API calls

  • Also kills AnyObject which is pretty much required for the API handler

Copy link
Member

Choose a reason for hiding this comment

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

The idea was that you explicitly disable the rule where you want any to make it inconvenient enough to use that it's not misused, but I encountered some annoyance with it too, so I'll disable it for now: xojs/eslint-config-xo-typescript@bbbf889

Copy link
Member Author

Choose a reason for hiding this comment

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

The idea was that you explicitly disable the rule where you want any to make it inconvenient enough to use that it's not misused

Maybe that is worth it, I missed this one just recently: https://github.com/sindresorhus/refined-github/pull/2393/files#diff-f8fed5d366f31fce028a9c8ceca38c3eR6

The lines in my examples would just have to use eslint-disable-next-line or be wrapped by disabled/enable

Copy link
Member

Choose a reason for hiding this comment

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

I think it will be easier to enable in a year or so when TS has matured more and we need less any in general.

Copy link
Member Author

@fregante fregante Sep 9, 2019

Choose a reason for hiding this comment

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

What other problems have you had?

Do you think there will ever be a solution to my examples? They basically are:

  • setting a global (without having to create a property on the Global/Window types)
  • setting/getting one-off properties. It could probably already be fixed with:
     type CodeMirrorElement = Element & {CodeMirror: CodeMirrorInstance}
     const editor = document.querySelector<CodeMirrorElement>('.CodeMirror').CodeMirror;
  • we just want to avoid typing of certain parts like APIs because it's extra work that has to be updated when the query changes, otherwise the API response won't actually match the types (in essence, manually typing the API is as bad as an assertion). Also the API response ALWAYS has to start from AnyObject, there's no workaround for that.

Copy link
Member

Choose a reason for hiding this comment

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

I had problems with some bad types from Electron and React. Basically out of my control. I also had to use any for some things like this: https://github.com/sindresorhus/caprine/blob/7965b36c11ae1f7ccb2185bebdc85e9fc3d01078/source/menu.ts#L92

In the future, there will be less globals, and the types of large projects will be better, TS will be better.

"@typescript-eslint/no-unused-vars": [
"error",
{
Expand Down
Empty file added size-plugin.json
Empty file.
2 changes: 1 addition & 1 deletion source/background.ts
Expand Up @@ -2,7 +2,7 @@ import 'webext-dynamic-content-scripts';
import addDomainPermissionToggle from 'webext-domain-permission-toggle';
import './options-storage';

browser.runtime.onMessage.addListener(async (message, {tab}) => {
browser.runtime.onMessage.addListener((message, {tab}) => {
if (message && Array.isArray(message.openUrls)) {
for (const [i, url] of (message.openUrls as string[]).entries()) {
browser.tabs.create({
Expand Down
4 changes: 2 additions & 2 deletions source/features/follow-file-renames.tsx
Expand Up @@ -17,10 +17,10 @@ async function findRename(
): Promise<File[]> {
// API v4 doesn't support it: https://github.community/t5/GitHub-API-Development-and/What-is-the-corresponding-object-in-GraphQL-API-v4-for-patch/m-p/14502?collapse_discussion=true&filter=location&location=board:api&q=files%20changed%20commit&search_type=thread
const {files} = await api.v3(`repos/${user}/${repo}/commits/${lastCommitOnPage}`);
return files as Promise<File[]>;
return files as File[];
}

async function init(): Promise<false | void> {
function init(): false | void {
const disabledPagination = select.all('.paginate-container [disabled], .paginate-container .disabled');

if (disabledPagination.length === 0) {
Expand Down
2 changes: 1 addition & 1 deletion source/features/forked-to.tsx
Expand Up @@ -17,7 +17,7 @@ async function save(forks: string[]): Promise<void> {
return cache.set(getCacheKey(), forks, 10);
}

async function saveAllForks(): Promise<void> {
function saveAllForks(): void {
const forks = select
.all('details-dialog[src*="/fork"] .octicon-repo-forked')
.map(({nextSibling}) => nextSibling!.textContent!.trim());
Expand Down
2 changes: 1 addition & 1 deletion source/features/hide-useless-comments.tsx
Expand Up @@ -17,7 +17,7 @@ function init(): void {
}

// Ensure that they're not by VIPs (owner, collaborators, etc)
const comment = commentText.closest('.js-timeline-item') as HTMLElement;
const comment = commentText.closest<HTMLElement>('.js-timeline-item')!;
if (select.exists('.timeline-comment-label', comment)) {
continue;
}
Expand Down
3 changes: 1 addition & 2 deletions source/features/link-to-file-in-file-history.tsx
Expand Up @@ -25,8 +25,7 @@ function init(): void | false {
</a>
);

// TODO: drop `as` after https://github.com/Microsoft/TSJS-lib-generator/pull/697
(rootLink.closest('.commit-links-cell') as HTMLElement).style.width = 'auto';
rootLink.closest<HTMLElement>('.commit-links-cell')!.style.width = 'auto';

groupSiblings(rootLink);
}
Expand Down
2 changes: 1 addition & 1 deletion source/features/linkify-urls-in-code.tsx
Expand Up @@ -12,7 +12,7 @@ export function linkifyIssuesInDom(element: Element): void {
}

// Enable native issue title fetch
for (const link of (linkified.children as HTMLCollectionOf<HTMLAnchorElement>)) {
for (const link of linkified.children as HTMLCollectionOf<HTMLAnchorElement>) {
const issue = link.href.split('/').pop();
link.setAttribute('class', 'issue-link js-issue-link tooltipped tooltipped-ne');
link.setAttribute('data-error-text', 'Failed to load issue title');
Expand Down
2 changes: 1 addition & 1 deletion source/features/minimize-upload-bar.tsx
Expand Up @@ -5,7 +5,7 @@ import delegate, {DelegateEvent} from 'delegate-it';
import features from '../libs/features';
import * as icons from '../libs/icons';

async function addButton(): Promise<void> {
function addButton(): void {
for (const toolbarButton of select.all('md-ref')) {
toolbarButton.after(
<button type="button" className="toolbar-item tooltipped tooltipped-n rgh-upload-btn" aria-label="Attach files">
Expand Down
2 changes: 1 addition & 1 deletion source/features/pr-branch-auto-delete.tsx
Expand Up @@ -4,7 +4,7 @@ import features from '../libs/features';
import observeEl from '../libs/simplified-element-observer';

function init(): void {
const [subscription] = delegate('#discussion_bucket', '.js-merge-commit-button', 'click', async () => {
const [subscription] = delegate('#discussion_bucket', '.js-merge-commit-button', 'click', () => {
subscription.destroy();

observeEl('.discussion-timeline-actions', (_, observer) => {
Expand Down
11 changes: 5 additions & 6 deletions source/features/revert-file.tsx
Expand Up @@ -30,7 +30,7 @@ const getBaseRef = onetime(async (): Promise<string> => {
});

async function getFile(menuItem: Element): Promise<{isTruncated: boolean; text: string}> {
const filePath = (menuItem.closest('[data-path]') as HTMLElement).dataset.path!;
const filePath = menuItem.closest<HTMLElement>('[data-path]')!.dataset.path!;
const {repository} = await api.v4(`
repository(${getRepoGQL()}) {
file: object(expression: "${await getBaseRef()}:${filePath}") {
Expand All @@ -45,8 +45,6 @@ async function getFile(menuItem: Element): Promise<{isTruncated: boolean; text:
}

async function deleteFile(menuItem: Element): Promise<void> {
// The `a` selector skips the broken Delete link on some pages. GitHub's bug.
// TODO: where? What happens when it's not found?
menuItem.textContent = 'Deleting…';

const deleteFileLink = select<HTMLAnchorElement>('a[aria-label^="Delete this"]', menuItem.parentElement!)!;
Expand Down Expand Up @@ -77,7 +75,8 @@ async function commitFileContent(menuItem: Element, content: string): Promise<vo
async function handleRevertFileClick(event: React.MouseEvent<HTMLButtonElement>): Promise<void> {
const menuItem = event.currentTarget;
// Allow only one click
menuItem.removeEventListener('click', handleRevertFileClick as any); // TODO: change JSX event types to be plain browser events
// TODO: change JSX event types to be plain browser events
menuItem.removeEventListener('click', handleRevertFileClick as any);
menuItem.textContent = 'Reverting…';
event.preventDefault();
event.stopPropagation();
Expand All @@ -88,7 +87,7 @@ async function handleRevertFileClick(event: React.MouseEvent<HTMLButtonElement>)
if (!file) {
// The file was created by this PR. Revert === Delete.
// If there was a way to tell if a file was created by the PR, we could skip `getFile`
// TODO: find this info on the page
// TODO: find this info on the page ("was this file created by this PR?")
await deleteFile(menuItem);
return;
}
Expand All @@ -108,7 +107,7 @@ async function handleRevertFileClick(event: React.MouseEvent<HTMLButtonElement>)
}
}

async function handleMenuOpening(event: DelegateEvent): Promise<void> {
function handleMenuOpening(event: DelegateEvent): void {
const dropdown = event.delegateTarget.nextElementSibling!;

const editFile = select<HTMLAnchorElement>('[aria-label^="Change this"]', dropdown);
Expand Down
2 changes: 1 addition & 1 deletion source/features/show-names.tsx
Expand Up @@ -72,7 +72,7 @@ features.add({
features.isDashboard
],
load: features.onDomReady,
init: async () => onNewsfeedLoad(init)
init: () => onNewsfeedLoad(init)
});

features.add({
Expand Down
2 changes: 1 addition & 1 deletion source/features/sticky-discussion-sidebar.tsx
Expand Up @@ -4,7 +4,7 @@ import debounce from 'debounce-fn';
import features from '../libs/features';

function updateStickiness(): void {
const sidebar = select<HTMLElement>('#partial-discussion-sidebar')!;
const sidebar = select('#partial-discussion-sidebar')!;
const sidebarHeight = sidebar.offsetHeight + 60; // 60 matches sticky header's height
sidebar.classList.toggle('rgh-sticky-sidebar', sidebarHeight < window.innerHeight);
}
Expand Down
2 changes: 1 addition & 1 deletion source/features/submit-review-as-single-comment.tsx
Expand Up @@ -64,7 +64,7 @@ async function handleSubmitSingle(event: DelegateEvent): Promise<void> {
// Use nearby comment box
const comment = await getNewCommentField(commentContainer, lineBeingCommentedOn);
const submitButton = select<HTMLButtonElement>('[name="single_comment"]', comment.form!)!;
const commentForm = comment.closest('.inline-comment-form-container') as HTMLElement;
const commentForm = comment.closest<HTMLElement>('.inline-comment-form-container')!;

// Copy comment to new comment box
insertText(comment.form!.elements['comment[body]'] as HTMLTextAreaElement, commentText);
Expand Down
2 changes: 1 addition & 1 deletion source/features/tags-dropdown.tsx
Expand Up @@ -5,7 +5,7 @@ import features from '../libs/features';
import {getRepoURL} from '../libs/utils';
import {octoface} from '../libs/icons';

async function init(): Promise<false | void> {
function init(): false | void {
if (select.exists('.blankslate')) {
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions source/features/view-markdown-source.tsx
Expand Up @@ -39,7 +39,7 @@ async function showSource(): Promise<void> {
sourceButton.disabled = true;

const source = btnBodyMap.get(sourceButton) || fetchSource();
const rendered = btnBodyMap.get(renderedButton) as Element || select('.blob.instapaper_body')!;
const rendered = await btnBodyMap.get(renderedButton) || select('.blob.instapaper_body')!;

btnBodyMap.set(sourceButton, source);
btnBodyMap.set(renderedButton, rendered);
Expand All @@ -61,7 +61,7 @@ async function showRendered(): Promise<void> {

renderedButton.disabled = true;

(await btnBodyMap.get(sourceButton))!.replaceWith(btnBodyMap.get(renderedButton) as Element);
(await btnBodyMap.get(sourceButton))!.replaceWith(await btnBodyMap.get(renderedButton)!);

renderedButton.disabled = false;

Expand Down
19 changes: 7 additions & 12 deletions source/globals.d.ts
@@ -1,3 +1,5 @@
// TODO: Drop some definitions when their related bugs are resolved
Copy link
Member Author

@fregante fregante Aug 29, 2019

Choose a reason for hiding this comment

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

I merged all of these TODOs into one. They're just noise since we can only wait for the underlying bugs to be fixed.


type AnyObject = Record<string, any>;
type AsyncVoidFunction = () => Promise<void>;

Expand All @@ -17,16 +19,15 @@ interface Window {
content: GlobalFetch;
}

// TODO: Drop after https://github.com/sindresorhus/p-memoize/issues/9
// Drop after https://github.com/sindresorhus/p-memoize/issues/9
declare module 'mem' {
function mem<T = VoidFunction>(fn: T, options?: AnyObject): T;
export = mem;
}

declare module 'size-plugin';

// TODO: Drop linkify-* types when Firefox adds RegEx lookbehind support
// https://github.com/sindresorhus/refined-github/pull/1936#discussion_r276515991
// Drop when Firefox adds RegEx lookbehind support https://github.com/sindresorhus/refined-github/pull/1936#discussion_r276515991
declare module 'linkify-urls' {
type Options = {
user: string;
Expand All @@ -44,6 +45,7 @@ declare module 'linkify-urls' {
export = linkifyUrls;
}

// Drop when Firefox adds RegEx lookbehind support https://github.com/sindresorhus/refined-github/pull/1936#discussion_r276515991
declare module 'linkify-issues' {
type Options = {
user: string;
Expand All @@ -64,7 +66,6 @@ declare module 'linkify-issues' {
// Custom UI events specific to RGH
interface GlobalEventHandlersEventMap {
'details:toggled': CustomEvent;
'focusin': UIEvent; // Drop when it reaches W3C Recommendation https://github.com/Microsoft/TSJS-lib-generator/pull/369
'rgh:view-markdown-source': CustomEvent;
'rgh:view-markdown-rendered': CustomEvent;
'filterable:change': CustomEvent;
Expand All @@ -84,18 +85,12 @@ declare namespace JSX {
}
}

// TODO: Drop when this bug is fixed
// https://github.com/Microsoft/TypeScript/issues/30928
// Drop after https://github.com/Microsoft/TypeScript/issues/30928
interface NamedNodeMap {
[key: string]: Attr;
}

// https://github.com/Microsoft/TypeScript/issues/30928
// Drop after https://github.com/Microsoft/TypeScript/issues/30928
interface HTMLFormControlsCollection {
[key: string]: HTMLInputElement | HTMLTextAreaElement | HTMLButtonElement;
}

// TODO: Drop when this appears on npm https://github.com/microsoft/TypeScript/blob/340f81035ff1d753e6a1f0fedc2323d169c86cc6/src/lib/dom.generated.d.ts#L9686
interface KeyboardEvent {
readonly isComposing: boolean;
}
4 changes: 2 additions & 2 deletions source/libs/features.tsx
Expand Up @@ -170,12 +170,12 @@ const add = async (definition: FeatureDetails): Promise<void> => {
return result;
};

onAjaxedPages(async () => run(details));
onAjaxedPages(() => run(details));
} else if (load instanceof Promise) {
await load;
run(details);
} else {
load(async () => run(details));
load(() => run(details));
}
};

Expand Down
6 changes: 2 additions & 4 deletions source/libs/get-default-branch.ts
Expand Up @@ -26,11 +26,9 @@ function parseBranchFromDom(): string | undefined {
return matches ? matches[1] : undefined;
}

async function fetchFromApi(): Promise<any> {
async function fetchFromApi(): Promise<string> {
const response = await api.v3(`repos/${getRepoURL()}`);
if (response.default_branch) {
return response.default_branch;
}
return response.default_branch as string;
}

export default async function (): Promise<string> {
Expand Down
2 changes: 1 addition & 1 deletion source/libs/get-text-nodes.ts
@@ -1,4 +1,4 @@
export default (el: Node) => {
export default (el: Node): Text[] => {
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const nodes: Text[] = [];
let node: Text;
Expand Down
1 change: 1 addition & 0 deletions source/libs/on-new-comments.ts
Expand Up @@ -7,6 +7,7 @@ const observed = new WeakSet();

const run = debounce(() => {
// Safely run all callbacks
// eslint-disable-next-line @typescript-eslint/require-await
handlers.forEach(async cb => cb());
}, {wait: 200});

Expand Down
2 changes: 1 addition & 1 deletion source/libs/post-form.ts
Expand Up @@ -6,7 +6,7 @@ export default async function postForm(form: HTMLFormElement): Promise<Response>
const contentFetch = typeof window.content === 'object' ? window.content.fetch : window.fetch;

const response = await contentFetch(form.action, {
// `as` required until https://github.com/microsoft/TSJS-lib-generator/issues/741
// TODO: drop `as` after https://github.com/microsoft/TSJS-lib-generator/issues/741
body: new URLSearchParams(new FormData(form) as URLSearchParams),
method: 'POST',
headers: {
Expand Down
4 changes: 2 additions & 2 deletions source/options-storage.ts
@@ -1,4 +1,4 @@
import OptionsSync from 'webext-options-sync';
import OptionsSync, {Migration} from 'webext-options-sync';
import {isBackgroundPage} from 'webext-detect-page';
import {getAdditionalPermissions} from 'webext-additional-permissions';

Expand All @@ -10,7 +10,7 @@ export interface RGHOptions {
[featureName: string]: string | boolean;
}

function featureWasRenamed(from: string, to: string): any { // TODO: any should probably be `Migration` after `webext-options-sync`'s types are fixed
function featureWasRenamed(from: string, to: string): Migration<RGHOptions> {
return (options: RGHOptions) => {
if (typeof options[`feature:${from}`] === 'boolean') {
options[`feature:${to}`] = options[`feature:${from}`];
Expand Down