diff --git a/lighthouse-core/gather/connections/connection.js b/lighthouse-core/gather/connections/connection.js index cb447e83a3c6..3a687f352c93 100644 --- a/lighthouse-core/gather/connections/connection.js +++ b/lighthouse-core/gather/connections/connection.js @@ -11,14 +11,14 @@ const LHError = require('../../lib/errors'); /** * @typedef {LH.StrictEventEmitter<{'protocolevent': LH.Protocol.RawEventMessage}>} CrdpEventMessageEmitter - * @typedef {LH.CrdpCommands[keyof LH.CrdpCommands]['paramsType']} CommandParamsTypes - * @typedef {LH.CrdpCommands[keyof LH.CrdpCommands]['returnType']} CommandReturnTypes + * @typedef {LH.CrdpCommands[keyof LH.CrdpCommands]} CommandInfo + * @typedef {{resolve: function(Promise): void, method: keyof LH.CrdpCommands, options: {silent?: boolean}}} CommandCallback */ class Connection { constructor() { this._lastCommandId = 0; - /** @type {Map), method: keyof LH.CrdpCommands, options: {silent?: boolean}}>} */ + /** @type {Map} */ this._callbacks = new Map(); /** @type {?CrdpEventMessageEmitter} */ @@ -46,6 +46,22 @@ class Connection { return Promise.reject(new Error('Not implemented')); } + /** + * Bind listeners for connection events. + * @param {'protocolevent'} eventName + * @param {function(LH.Protocol.RawEventMessage): void} cb + */ + on(eventName, cb) { + if (eventName !== 'protocolevent') { + throw new Error('Only supports "protocolevent" events'); + } + + if (!this._eventEmitter) { + throw new Error('Attempted to add event listener after connection disposed.'); + } + this._eventEmitter.on(eventName, cb); + } + /* eslint-disable no-unused-vars */ /** @@ -68,11 +84,9 @@ class Connection { // Responses to commands carry "id" property, while events do not. if (!('id' in object)) { - // tsc doesn't currently narrow type in !in branch, so manually cast. - const eventMessage = /** @type {LH.Protocol.RawEventMessage} */(object); log.formatProtocol('<= event', - {method: eventMessage.method, params: eventMessage.params}, 'verbose'); - this.emitProtocolEvent(eventMessage); + {method: object.method, params: object.params}, 'verbose'); + this.emitProtocolEvent(object); return; } @@ -124,29 +138,18 @@ class Connection { } } -// Declared outside class body because function expressions can be typed via more expressive @type -/** - * Bind listeners for connection events - * @type {CrdpEventMessageEmitter['on']} - */ -Connection.prototype.on = function on(eventName, cb) { - if (eventName !== 'protocolevent') { - throw new Error('Only supports "protocolevent" events'); - } - - if (!this._eventEmitter) { - throw new Error('Attempted to add event listener after connection disposed.'); - } - this._eventEmitter.on(eventName, cb); -}; - +// Declared outside class body because function expressions can be typed via coercive @type /** * Looser-typed internal implementation of `Connection.sendCommand` which is * strictly typed externally on exposed Connection interface. See * `Driver.sendCommand` for explanation. - * @type {(this: Connection, method: keyof LH.CrdpCommands, params?: CommandParamsTypes, cmdOpts?: {silent?: boolean}) => Promise} + * @this {Connection} + * @param {keyof LH.CrdpCommands} method + * @param {CommandInfo['paramsType']=} params, + * @param {{silent?: boolean}=} cmdOpts + * @return {Promise} */ -function _sendCommand(method, params = {}, cmdOpts = {}) { +function _sendCommand(method, params, cmdOpts = {}) { /* eslint-disable no-invalid-this */ log.formatProtocol('method => browser', {method, params}, 'verbose'); const id = ++this._lastCommandId; diff --git a/lighthouse-core/gather/connections/extension.js b/lighthouse-core/gather/connections/extension.js index 3f90e2e6005c..71ab954f88d0 100644 --- a/lighthouse-core/gather/connections/extension.js +++ b/lighthouse-core/gather/connections/extension.js @@ -173,17 +173,19 @@ class ExtensionConnection extends Connection { } /** - * @typedef {LH.CrdpCommands[keyof LH.CrdpCommands]['paramsType']} CommandParamsTypes - * @typedef {LH.CrdpCommands[keyof LH.CrdpCommands]['returnType']} CommandReturnTypes + * @typedef {LH.CrdpCommands[keyof LH.CrdpCommands]} CommandInfo */ -// Declared outside class body because function expressions can be typed via more expressive @type +// Declared outside class body because function expressions can be typed via coercive @type /** * Looser-typed internal implementation of `ExtensionConnection.sendCommand` * which is strictly typed externally on exposed ExtensionConnection interface. * See `Driver.sendCommand` for explanation. - * @type {(this: ExtensionConnection, method: keyof LH.CrdpCommands, params?: CommandParamsTypes) => Promise} + * @this {ExtensionConnection} + * @param {keyof LH.CrdpCommands} method + * @param {CommandInfo['paramsType']=} params, + * @return {Promise} */ -function _sendCommand(method, params = {}) { +function _sendCommand(method, params) { return new Promise((resolve, reject) => { log.formatProtocol('method => browser', {method, params}, 'verbose'); if (!this._tabId) { // eslint-disable-line no-invalid-this @@ -192,7 +194,7 @@ function _sendCommand(method, params = {}) { } // eslint-disable-next-line no-invalid-this - chrome.debugger.sendCommand({tabId: this._tabId}, method, params, result => { + chrome.debugger.sendCommand({tabId: this._tabId}, method, params || {}, result => { if (chrome.runtime.lastError) { // The error from the extension has a `message` property that is the // stringified version of the actual protocol error object. diff --git a/lighthouse-core/gather/driver.js b/lighthouse-core/gather/driver.js index 0502fa0fbc81..ec0518994779 100644 --- a/lighthouse-core/gather/driver.js +++ b/lighthouse-core/gather/driver.js @@ -1167,9 +1167,13 @@ Driver.prototype.off = function off(eventName, cb) { * Necessitated by `params` only being optional for some values of `method`. * See https://github.com/Microsoft/TypeScript/issues/5453 for needed variadic * primitive. - * @type {(this: Driver, method: any, params?: any, cmdOpts?: {silent?: boolean}) => Promise} + * @this {Driver} + * @param {any} method + * @param {any=} params, + * @param {{silent?: boolean}=} cmdOpts + * @return {Promise} */ -function _sendCommand(method, params = {}, cmdOpts = {}) { +function _sendCommand(method, params, cmdOpts = {}) { const domainCommand = /^(\w+)\.(enable|disable)$/.exec(method); if (domainCommand) { const enable = domainCommand[2] === 'enable'; diff --git a/lighthouse-core/lib/errors.js b/lighthouse-core/lib/errors.js index a7631b0cb0b5..301cfc7cbe25 100644 --- a/lighthouse-core/lib/errors.js +++ b/lighthouse-core/lib/errors.js @@ -97,7 +97,7 @@ const ERRORS = { Object.keys(ERRORS).forEach(code => ERRORS[code].code = code); -/** @type {Object} */ +/** @type {Record} */ LighthouseError.errors = ERRORS; module.exports = LighthouseError; diff --git a/lighthouse-core/lib/locales/index.js b/lighthouse-core/lib/locales/index.js index fbd64b043cbc..aa4baed52d88 100644 --- a/lighthouse-core/lib/locales/index.js +++ b/lighthouse-core/lib/locales/index.js @@ -11,6 +11,7 @@ /** @type {Record} */ const locales = { 'en-US': require('./en-US.json'), // The 'source' strings, with descriptions + // @ts-ignore - tsc bug, something about en/en-US pointing to same file 'en': require('./en-US.json'), // According to CLDR/ICU, 'en' == 'en-US' dates/numbers (Why?!) // TODO: en-GB has just ~10 messages that are different from en-US. We should only ship those. diff --git a/lighthouse-extension/app/src/lighthouse-ext-background.js b/lighthouse-extension/app/src/lighthouse-ext-background.js index 9b8586998f5d..68969d6ac9a8 100644 --- a/lighthouse-extension/app/src/lighthouse-ext-background.js +++ b/lighthouse-extension/app/src/lighthouse-ext-background.js @@ -65,7 +65,9 @@ async function runLighthouseInExtension(flags, categoryIDs) { throw new Error('no runnerResult generated by Lighthouse'); } - const blobURL = createReportPageAsBlob(runnerResult); + // Report is always a singular string since {output: 'html'}, above. + const reportHtml = /** @type {string} */ (runnerResult.report); + const blobURL = createReportPageAsBlob(reportHtml); await new Promise(resolve => chrome.windows.create({url: blobURL}, resolve)); } @@ -91,15 +93,13 @@ async function runLighthouseAsInCLI(connection, url, flags, categoryIDs, {logAss return results.report; } - /** - * @param {LH.RunnerResult} runnerResult Lighthouse results object + * @param {string} reportHtml * @return {string} Blob URL of the report (or error page) HTML */ -function createReportPageAsBlob(runnerResult) { +function createReportPageAsBlob(reportHtml) { performance.mark('report-start'); - const html = runnerResult.report; - const blob = new Blob([html], {type: 'text/html'}); + const blob = new Blob([reportHtml], {type: 'text/html'}); const blobURL = URL.createObjectURL(blob); performance.mark('report-end'); diff --git a/lighthouse-viewer/app/src/lighthouse-report-viewer.js b/lighthouse-viewer/app/src/lighthouse-report-viewer.js index 6d84ed068a5a..e4f863521993 100644 --- a/lighthouse-viewer/app/src/lighthouse-report-viewer.js +++ b/lighthouse-viewer/app/src/lighthouse-report-viewer.js @@ -226,7 +226,13 @@ class LighthouseReportViewer { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = function(e) { - resolve(e.target && e.target.result); + const readerTarget = /** @type {?FileReader} */ (e.target); + const result = /** @type {?string} */ (readerTarget && readerTarget.result); + if (!result) { + reject('Could not read file'); + return; + } + resolve(result); }; reader.onerror = reject; reader.readAsText(file); diff --git a/package.json b/package.json index f90a2d459a82..e91eb284930b 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "pretty-json-stringify": "^0.0.2", "puppeteer": "1.4.0", "sinon": "^2.3.5", - "typescript": "2.9.1-insiders.20180516", + "typescript": "3.0.1", "vscode-chrome-debug-core": "^3.23.8", "zone.js": "^0.7.3" }, diff --git a/tsconfig.json b/tsconfig.json index b1fa08f28c90..f5352e291fab 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,10 +17,6 @@ "diagnostics": true }, "include": [ - // TODO(bckenny): unnecessary workaround until https://github.com/Microsoft/TypeScript/issues/24062 - "node_modules/@types/node/index.d.ts", - "third-party/devtools/*.js", - "lighthouse-cli/**/*.js", "lighthouse-core/**/*.js", "lighthouse-extension/app/src/*.js", diff --git a/yarn.lock b/yarn.lock index 5ecdd73d010a..56fb7980575f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6199,9 +6199,9 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript@2.9.1-insiders.20180516: - version "2.9.1-insiders.20180516" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.1-insiders.20180516.tgz#aab5261edb2c162c2d0c1754bb3092d4ff6efed0" +typescript@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.0.1.tgz#43738f29585d3a87575520a4b93ab6026ef11fdb" uglify-js@^2.6: version "2.7.3"