Merge pull request #2542 from tridactyl/bikeshed_types

Switch to DefinitelyTyped types
This commit is contained in:
Oliver Blanthorn 2020-07-01 17:51:01 +01:00 committed by GitHub
commit 545c9d3b04
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 170 additions and 121 deletions

View file

@ -17,6 +17,7 @@
"typedoc-default-themes": "^0.10.2" "typedoc-default-themes": "^0.10.2"
}, },
"devDependencies": { "devDependencies": {
"@types/firefox-webext-browser": "^78.0.0",
"@types/jest": "^26.0.3", "@types/jest": "^26.0.3",
"@types/node": "^14.0.14", "@types/node": "^14.0.14",
"@types/selenium-webdriver": "^4.0.9", "@types/selenium-webdriver": "^4.0.9",

View file

@ -89,7 +89,7 @@ browser.webNavigation.onDOMContentLoaded.addListener(() => {
// Prevent Tridactyl from being updated while it is running in the hope of fixing #290 // Prevent Tridactyl from being updated while it is running in the hope of fixing #290
browser.runtime.onUpdateAvailable.addListener(_ => undefined) browser.runtime.onUpdateAvailable.addListener(_ => undefined)
browser.runtime.onStartup.addListener(_ => { browser.runtime.onStartup.addListener(() => {
config.getAsync("autocmds", "TriStart").then(aucmds => { config.getAsync("autocmds", "TriStart").then(aucmds => {
const hosts = Object.keys(aucmds) const hosts = Object.keys(aucmds)
// If there's only one rule and it's "all", no need to check the hostname // If there's only one rule and it's "all", no need to check the hostname

View file

@ -17,14 +17,12 @@ class HistoryCompletionOption extends Completions.CompletionOptionHTML
// Create HTMLElement // Create HTMLElement
this.html = html`<tr class="HistoryCompletionOption option"> this.html = html`<tr class="HistoryCompletionOption option">
<td class="prefix">${"".padEnd(2)}</td> <td class="prefix">${"".padEnd(2)}</td>
<td class="title">${page.title}</td> <td class="title">${page.title}</td>
<td class="content"> <td class="content">
<a class="url" target="_blank" href=${page.url} <a class="url" target="_blank" href=${page.url}>${page.url}</a>
>${page.url}</a </td>
> </tr>`
</td>
</tr>`
} }
} }
@ -78,8 +76,13 @@ export class HistoryCompletionSource extends Completions.CompletionSourceFuse {
options += options ? " " : "" options += options ? " " : ""
// Options are pre-trimmed to the right length. // Options are pre-trimmed to the right length.
this.options = (await this.scoreOptions(query, config.get("historyresults"))).map( // Typescript throws an error here - further investigation is probably warranted
page => new HistoryCompletionOption(options + page.url, page as any), this.options = ((await this.scoreOptions(
query,
config.get("historyresults"),
)) as any).map(
page =>
new HistoryCompletionOption(options + page.url, page),
) )
// Deselect any selected, but remember what they were. // Deselect any selected, but remember what they were.
@ -88,9 +91,13 @@ export class HistoryCompletionSource extends Completions.CompletionSourceFuse {
// Set initial state to normal, unless the option was selected a moment // Set initial state to normal, unless the option was selected a moment
// ago, then reselect it so that users don't lose their selections. // ago, then reselect it so that users don't lose their selections.
this.options.forEach(option => option.state = "normal") this.options.forEach(option => (option.state = "normal"))
for (const option of this.options) { for (const option of this.options) {
if (lastFocused !== undefined && lastFocused.value === option.value && prevStr.length <= exstr.length) { if (
lastFocused !== undefined &&
lastFocused.value === option.value &&
prevStr.length <= exstr.length
) {
this.select(option) this.select(option)
break break
} }
@ -103,7 +110,6 @@ export class HistoryCompletionSource extends Completions.CompletionSourceFuse {
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
updateChain() {} updateChain() {}
private async scoreOptions(query: string, n: number) { private async scoreOptions(query: string, n: number) {
if (!query || config.get("historyresults") === 0) { if (!query || config.get("historyresults") === 0) {
return (await providers.getTopSites()).slice(0, n) return (await providers.getTopSites()).slice(0, n)

View file

@ -5,7 +5,7 @@ class WindowCompletionOption extends Completions.CompletionOptionHTML
implements Completions.CompletionOptionFuse { implements Completions.CompletionOptionFuse {
public fuseKeys = [] public fuseKeys = []
constructor(win) { constructor(win: browser.windows.Window) {
super() super()
this.value = win.id this.value = win.id
this.fuseKeys.push(`${win.title}`) this.fuseKeys.push(`${win.title}`)

View file

@ -35,32 +35,26 @@ interface ICancelledRequest {
} }
interface IAutoContain { interface IAutoContain {
autoContain(details: browser.webRequest.IDetails): any autoContain(details): any
cancelEarly( cancelEarly(tab: browser.tabs.Tab, details): boolean
tab: browser.tabs.Tab, cancelRequest(tab: browser.tabs.Tab, details): void
details: browser.webRequest.IDetails,
): boolean
cancelRequest(
tab: browser.tabs.Tab,
details: browser.webRequest.IDetails,
): void
clearCancelledRequests(tabId: number): void clearCancelledRequests(tabId: number): void
getCancelledRequest(tabId: number): ICancelledRequest getCancelledRequest(tabId: number): ICancelledRequest
completedRequestListener(details: browser.webRequest.IDetails): void completedRequestListener(details): void
autocontainConfigured(): boolean autocontainConfigured(): boolean
getAuconForUrl(url: string): Promise<string> getAuconForUrl(url: string): Promise<string>
getAuconForDetails(details: browser.webRequest.IDetails): Promise<string> getAuconForDetails(details): Promise<string>
} }
export class AutoContain implements IAutoContain { export class AutoContain implements IAutoContain {
private cancelledRequests: ICancelledRequest[] = [] private cancelledRequests: ICancelledRequest[] = []
private lastCreatedTab = null private lastCreatedTab = null
tabCreatedListener = (tab) => { tabCreatedListener = tab => {
this.lastCreatedTab = tab this.lastCreatedTab = tab
} }
completedRequestListener = (details: browser.webRequest.IDetails) => { completedRequestListener = details => {
if (this.getCancelledRequest(details.tabId)) { if (this.getCancelledRequest(details.tabId)) {
this.clearCancelledRequests(details.tabId) this.clearCancelledRequests(details.tabId)
} }
@ -73,12 +67,13 @@ export class AutoContain implements IAutoContain {
} }
autoContain = async ( autoContain = async (
details: browser.webRequest.IDetails, details,
): Promise<browser.webRequest.BlockingResponse> => { ): Promise<browser.webRequest.BlockingResponse> => {
if (!this.autocontainConfigured()) return { cancel: false } if (!this.autocontainConfigured()) return { cancel: false }
// Only handle in strict mode. // Only handle in strict mode.
if (Config.get("autocontainmode") === "relaxed") return { cancel: false } if (Config.get("autocontainmode") === "relaxed")
return { cancel: false }
// Only handle http requests. // Only handle http requests.
if (details.url.search("^https?://") < 0) return { cancel: false } if (details.url.search("^https?://") < 0) return { cancel: false }
@ -87,13 +82,15 @@ export class AutoContain implements IAutoContain {
if (details.tabId === -1) return { cancel: false } if (details.tabId === -1) return { cancel: false }
// Do all of our async lookups in parallel. // Do all of our async lookups in parallel.
const [tab, otherExtensionHasPriority, cookieStoreId] = await Promise.all( const [
[ tab,
browser.tabs.get(details.tabId), otherExtensionHasPriority,
this.checkOtherExtensionsHavePriority(details), cookieStoreId,
this.getAuconForDetails(details), ] = await Promise.all([
], browser.tabs.get(details.tabId),
) this.checkOtherExtensionsHavePriority(details),
this.getAuconForDetails(details),
])
// If any other extensions claim this request, we'll ignore it and let them handle it. // If any other extensions claim this request, we'll ignore it and let them handle it.
if (otherExtensionHasPriority) return { cancel: false } if (otherExtensionHasPriority) return { cancel: false }
@ -108,22 +105,30 @@ export class AutoContain implements IAutoContain {
// If this navigation created a tab, we cancel and then kill // If this navigation created a tab, we cancel and then kill
// the newly-created tab after opening. // the newly-created tab after opening.
const removeTab = this.lastCreatedTab && (this.lastCreatedTab.id === tab.id) const removeTab =
this.lastCreatedTab && this.lastCreatedTab.id === tab.id
// Figure out which tab should be the parent of the tab we'll // Figure out which tab should be the parent of the tab we'll
// be creating in the selected container. // be creating in the selected container.
const openerTabId = removeTab ? tab.openerTabId : tab.id const openerTabId = removeTab ? tab.openerTabId : tab.id
logger.debug("in tab %o and with details %o, reopening from container %o to container %o", logger.debug(
tab, details, tab.cookieStoreId, cookieStoreId) "in tab %o and with details %o, reopening from container %o to container %o",
browser.tabs.create({ tab,
details,
tab.cookieStoreId,
cookieStoreId,
)
browser.tabs
.create({
url: details.url, url: details.url,
cookieStoreId, cookieStoreId,
active: tab.active, active: tab.active,
windowId: tab.windowId, windowId: tab.windowId,
index: tab.index + 1, index: tab.index + 1,
openerTabId, openerTabId,
}).then(result => { })
.then(result => {
logger.debug("Autocontainer created tab %o", result) logger.debug("Autocontainer created tab %o", result)
}) })
@ -136,10 +141,7 @@ export class AutoContain implements IAutoContain {
} }
// Handles the requests after the initial checks made in this.autoContain. // Handles the requests after the initial checks made in this.autoContain.
cancelEarly = ( cancelEarly = (tab: browser.tabs.Tab, details): boolean => {
tab: browser.tabs.Tab,
details: browser.webRequest.IDetails,
): boolean => {
if (!this.cancelledRequests[tab.id]) { if (!this.cancelledRequests[tab.id]) {
this.cancelRequest(tab, details) this.cancelRequest(tab, details)
} else { } else {
@ -160,10 +162,7 @@ export class AutoContain implements IAutoContain {
return false return false
} }
cancelRequest = ( cancelRequest = (tab: browser.tabs.Tab, details): void => {
tab: browser.tabs.Tab,
details: browser.webRequest.IDetails,
): void => {
this.cancelledRequests[tab.id] = { this.cancelledRequests[tab.id] = {
requestIds: { requestIds: {
[details.requestId]: true, [details.requestId]: true,
@ -180,7 +179,8 @@ export class AutoContain implements IAutoContain {
}, 2000) }, 2000)
} }
getCancelledRequest = (tabId: number): ICancelledRequest => this.cancelledRequests[tabId] getCancelledRequest = (tabId: number): ICancelledRequest =>
this.cancelledRequests[tabId]
// Clear the cancelled requests. // Clear the cancelled requests.
clearCancelledRequests = (tabId: number): void => { clearCancelledRequests = (tabId: number): void => {
@ -191,9 +191,7 @@ export class AutoContain implements IAutoContain {
// Checks to see if there are any other container-related extensions and avoids getting into // Checks to see if there are any other container-related extensions and avoids getting into
// fights with them. // fights with them.
checkOtherExtensionsHavePriority = async ( checkOtherExtensionsHavePriority = async (details): Promise<boolean> => {
details: browser.webRequest.IDetails,
): Promise<boolean> => {
// The checks for each extension can be done in parallel. // The checks for each extension can be done in parallel.
const priorities = await Promise.all([ const priorities = await Promise.all([
this.checkMACPriority(details), this.checkMACPriority(details),
@ -202,18 +200,14 @@ export class AutoContain implements IAutoContain {
return priorities.some(t => t) return priorities.some(t => t)
} }
checkMACPriority = async ( checkMACPriority = async (details): Promise<boolean> => {
details: browser.webRequest.IDetails,
): Promise<boolean> => {
if ( if (
!ExtensionInfo.getExtensionEnabled( !ExtensionInfo.getExtensionEnabled(
ExtensionInfo.KNOWN_EXTENSIONS.multi_account_containers, ExtensionInfo.KNOWN_EXTENSIONS.multi_account_containers,
) )
) { ) {
// It can't take priority if it's not enabled. // It can't take priority if it's not enabled.
logger.debug( logger.debug("multi-account containers extension does not exist")
"multi-account containers extension does not exist",
)
return false return false
} }
@ -229,8 +223,10 @@ export class AutoContain implements IAutoContain {
}, },
) )
.catch(error => { .catch(error => {
logger.warning("failed to communicate with multi-account containers extension: %o", logger.warning(
error) "failed to communicate with multi-account containers extension: %o",
error,
)
return false return false
}) })
@ -247,18 +243,14 @@ export class AutoContain implements IAutoContain {
} }
} }
checkTempContainersPriority = async ( checkTempContainersPriority = async (details): Promise<boolean> => {
details: browser.webRequest.IDetails,
): Promise<boolean> => {
if ( if (
!ExtensionInfo.getExtensionEnabled( !ExtensionInfo.getExtensionEnabled(
ExtensionInfo.KNOWN_EXTENSIONS.temp_containers, ExtensionInfo.KNOWN_EXTENSIONS.temp_containers,
) )
) { ) {
// It can't take priority if it's not enabled. // It can't take priority if it's not enabled.
logger.debug( logger.debug("temporary containers extension does not exist")
"temporary containers extension does not exist",
)
return false return false
} }
@ -281,9 +273,7 @@ export class AutoContain implements IAutoContain {
getAuconForUrl = async (url: string): Promise<string> => { getAuconForUrl = async (url: string): Promise<string> => {
const aucons = Config.get("autocontain") const aucons = Config.get("autocontain")
const ausites = Object.keys(aucons) const ausites = Object.keys(aucons)
const aukeyarr = ausites.filter( const aukeyarr = ausites.filter(e => url.search(e) >= 0)
e => url.search(e) >= 0,
)
if (aukeyarr.length > 1) { if (aukeyarr.length > 1) {
logger.error( logger.error(
"Too many autocontain directives match this url. Not containing.", "Too many autocontain directives match this url. Not containing.",
@ -307,7 +297,6 @@ export class AutoContain implements IAutoContain {
} }
// Parses autocontain directives and returns valid cookieStoreIds or errors. // Parses autocontain directives and returns valid cookieStoreIds or errors.
getAuconForDetails = async ( getAuconForDetails = async (details): Promise<string> =>
details: browser.webRequest.IDetails, this.getAuconForUrl(details.url)
): Promise<string> => this.getAuconForUrl(details.url)
} }

View file

@ -84,8 +84,8 @@ export function update(
containerId: string, containerId: string,
updateObj: { updateObj: {
name: string name: string
color: browser.contextualIdentities.IdentityColor color: string
icon: browser.contextualIdentities.IdentityIcon icon: string
}, },
) { ) {
const { name, color, icon } = updateObj const { name, color, icon } = updateObj
@ -147,8 +147,8 @@ export async function exists(cname: string): Promise<boolean> {
export function fromString(name: string, color: string, icon: string, id = "") { export function fromString(name: string, color: string, icon: string, id = "") {
return { return {
name, name,
color: color as browser.contextualIdentities.IdentityColor, color,
icon: icon as browser.contextualIdentities.IdentityIcon, icon,
cookieStoreId: id, cookieStoreId: id,
} as browser.contextualIdentities.ContextualIdentity // rules are made to be broken } as browser.contextualIdentities.ContextualIdentity // rules are made to be broken
} }

View file

@ -69,7 +69,11 @@ export function attributeCaller(obj) {
return handler return handler
} }
interface TypedMessage<Root, Type extends keyof Root, Command extends keyof Root[Type]> { interface TypedMessage<
Root,
Type extends keyof Root,
Command extends keyof Root[Type]
> {
type: Type type: Type
command: Command command: Command
args: Parameters<Root[Type][Command]> args: Parameters<Root[Type][Command]>
@ -79,23 +83,80 @@ function backgroundHandler<
Root, Root,
Type extends keyof Root, Type extends keyof Root,
Command extends keyof Root[Type] Command extends keyof Root[Type]
>(root: Root, >(
message: TypedMessage<Root, Type, Command>, root: Root,
sender: browser.runtime.MessageSender, message: TypedMessage<Root, Type, Command>,
): ReturnType<Root[Type][Command]> { sender: browser.runtime.MessageSender,
): ReturnType<Root[Type][Command]> {
return root[message.type][message.command](...message.args) return root[message.type][message.command](...message.args)
} }
export function setupListener<Root>(root: Root) { export function setupListener<Root>(root: Root) {
browser.runtime.onMessage.addListener((message: any, sender: browser.runtime.MessageSender) => { // What part of
if (message.type in root) { //
if (!(message.command in root[message.type])) // ```
throw new Error(`missing handler in protocol ${message.type} ${message.command}`) // ERROR in /home/olie/projects/tridactyl/src/lib/messaging.ts
if (!Array.isArray(message.args)) // ./src/lib/messaging.ts
throw new Error(`wrong arguments in protocol ${message.type} ${message.command}`) // [tsl] ERROR in /home/olie/projects/tridactyl/src/lib/messaging.ts(90,43)
return backgroundHandler(root, message, sender) // TS2345: Argument of type '(message: any, sender: browser.runtime.MessageSender) => ReturnType<Root[keyof Root][keyof Root[keyof Root]]>' is not assignable to parameter of type '(message: any, sender: MessageSender, sendResponse: (response?: any) => void) => boolean | void | Promise<any>'.
} // Type 'ReturnType<Root[keyof Root][keyof Root[keyof Root]]>' is not assignable to type 'boolean | void | Promise<any>'.
}); // Type 'unknown' is not assignable to type 'boolean | void | Promise<any>'.
// Type 'unknown' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[keyof Root][string | number | symbol]>' is not assignable to type 'boolean | void | Promise<any>'.
// Type 'unknown' is not assignable to type 'boolean | void | Promise<any>'.
// Type 'unknown' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[keyof Root][string]> | ReturnType<Root[keyof Root][number]> | ReturnType<Root[keyof Root][symbol]>' is not assignable to type 'boolean | void | Promise<any>'.
// Type 'ReturnType<Root[keyof Root][string]>' is not assignable to type 'boolean | void | Promise<any>'.
// Type 'unknown' is not assignable to type 'boolean | void | Promise<any>'.
// Type 'unknown' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[string | number | symbol][string]>' is not assignable to type 'boolean | void | Promise<any>'.
// Type 'unknown' is not assignable to type 'boolean | void | Promise<any>'.
// Type 'unknown' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[string][string]> | ReturnType<Root[number][string]> | ReturnType<Root[symbol][string]>' is not assignable to type 'boolean | void | Promise<any>'.
// Type 'ReturnType<Root[string][string]>' is not assignable to type 'boolean | void | Promise<any>'.
// Type 'unknown' is not assignable to type 'boolean | void | Promise<any>'.
// Type 'unknown' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[string][string]>' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[string | number | symbol][string]>' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[keyof Root][string]>' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[keyof Root][string | number | symbol]>' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[keyof Root][keyof Root[keyof Root]]>' is not assignable to type 'Promise<any>'.
// Type 'unknown' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[keyof Root][string | number | symbol]>' is not assignable to type 'Promise<any>'.
// Type 'unknown' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[keyof Root][string]> | ReturnType<Root[keyof Root][number]> | ReturnType<Root[keyof Root][symbol]>' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[keyof Root][string]>' is not assignable to type 'Promise<any>'.
// Type 'unknown' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[string | number | symbol][string]>' is not assignable to type 'Promise<any>'.
// Type 'unknown' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[string][string]> | ReturnType<Root[number][string]> | ReturnType<Root[symbol][string]>' is not assignable to type 'Promise<any>'.
// Type 'ReturnType<Root[string][string]>' is not assignable to type 'Promise<any>'.
// Type '{}' is missing the following properties from type 'Promise<any>': then, catch, [Symbol.toStringTag], finally
//
// ERROR in /home/olie/projects/tridactyl/src/lib/messaging.ts
// ./src/lib/messaging.ts
// [tsl] ERROR in /home/olie/projects/tridactyl/src/lib/messaging.ts(115,40)
// TS2558: Expected 0 type arguments, but got 2.
// ```
//
// don't you understand?
//
// (This is why there is an `: any => `)
browser.runtime.onMessage.addListener(
(message: any, sender: browser.runtime.MessageSender): any => {
if (message.type in root) {
if (!(message.command in root[message.type]))
throw new Error(
`missing handler in protocol ${message.type} ${message.command}`,
)
if (!Array.isArray(message.args))
throw new Error(
`wrong arguments in protocol ${message.type} ${message.command}`,
)
return backgroundHandler(root, message, sender)
}
},
)
} }
type StripPromise<T> = T extends Promise<infer U> ? U : T type StripPromise<T> = T extends Promise<infer U> ? U : T
@ -105,14 +166,16 @@ export async function message<
Type extends keyof Messages.Background, Type extends keyof Messages.Background,
Command extends keyof Messages.Background[Type], Command extends keyof Messages.Background[Type],
F extends((...args: any) => any) & Messages.Background[Type][Command] F extends((...args: any) => any) & Messages.Background[Type][Command]
>(type: Type, command: Command, ...args: Parameters<F>) { >(type: Type, command: Command, ...args: Parameters<F>) {
const message: TypedMessage<Messages.Background, Type, Command> = { const message: TypedMessage<Messages.Background, Type, Command> = {
type, type,
command, command,
args args,
} }
return browser.runtime.sendMessage<typeof message, StripPromise<ReturnType<F>>>(message) // Typescript didn't like this
// return browser.runtime.sendMessage<typeof message, StripPromise<ReturnType<F>>>(message)
return browser.runtime.sendMessage(message)
} }
/** Message the active tab of the currentWindow */ /** Message the active tab of the currentWindow */
@ -124,7 +187,12 @@ export async function messageActiveTab(
return messageTab(await activeTabId(), type, command, args) return messageTab(await activeTabId(), type, command, args)
} }
export async function messageTab(tabId, type: TabMessageType, command, args?): Promise<any> { export async function messageTab(
tabId,
type: TabMessageType,
command,
args?,
): Promise<any> {
const message: Message = { const message: Message = {
type, type,
command, command,
@ -154,7 +222,10 @@ export async function messageAllTabs(
responses.push(await messageTab(tab.id, type, command, args)) responses.push(await messageTab(tab.id, type, command, args))
} catch (e) { } catch (e) {
// Skip errors caused by tabs we aren't running on // Skip errors caused by tabs we aren't running on
if (e.message != "Could not establish connection. Receiving end does not exist.") { if (
e.message !=
"Could not establish connection. Receiving end does not exist."
) {
logger.error(e) logger.error(e)
} }
} }

23
src/tridactyl.d.ts vendored
View file

@ -186,29 +186,6 @@ declare namespace browser.management {
const onUninstalled: WebExtEvent<(info: IExtensionInfo) => void> const onUninstalled: WebExtEvent<(info: IExtensionInfo) => void>
} }
/** An interface for the additional object that's supplied in the BlockingResponse callback.
Details here:
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/webRequest/onBeforeRequest#details
*/
declare namespace browser.webRequest {
interface IDetails {
// frameAncestors: any[]
frameId: number
method: string
originUrl: string
parentFrameId: number
proxyInfo?: any
requestBody?: any
requestId: string
tabId: number
timeStamp: number
type: ResourceType
url: string
}
}
// html-tagged-template.js // html-tagged-template.js
declare function html( declare function html(
strings: TemplateStringsArray, strings: TemplateStringsArray,

View file

@ -7,13 +7,13 @@
"sourceMap": true, "sourceMap": true,
"target": "es2017", "target": "es2017",
"lib": ["es2017","es2019.array", "es2018.promise", "dom", "dom.iterable"], "lib": ["es2017","es2019.array", "es2018.promise", "dom", "dom.iterable"],
"types": ["web-ext-types"],
"experimentalDecorators": true, "experimentalDecorators": true,
"alwaysStrict": true, "alwaysStrict": true,
"strictBindCallApply": true, "strictBindCallApply": true,
"noImplicitThis": true, "noImplicitThis": true,
"strictFunctionTypes": true, "strictFunctionTypes": true,
"baseUrl": "src/", "baseUrl": "src/",
"types": ["@types/firefox-webext-browser", "web-ext-types"],
"paths": { "paths": {
"@src/*": ["*"] "@src/*": ["*"]
} }

View file

@ -672,6 +672,11 @@
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==
"@types/firefox-webext-browser@^78.0.0":
version "78.0.0"
resolved "https://registry.yarnpkg.com/@types/firefox-webext-browser/-/firefox-webext-browser-78.0.0.tgz#9f175355beb3824dce8d5811e59585fba84dca6b"
integrity sha512-ExCtjncdA1ITEjEitvtjGcXslGPA/ZMxOxzMGfpLHZ6ZJAAx6itQi+ZEctgPFN6uPW4lSJalSsEC+lAz0Wkz9A==
"@types/graceful-fs@^4.1.2": "@types/graceful-fs@^4.1.2":
version "4.1.3" version "4.1.3"
resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.3.tgz#039af35fe26bec35003e8d86d2ee9c586354348f" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.3.tgz#039af35fe26bec35003e8d86d2ee9c586354348f"