From b93a71ff5fb4cf9a6a9b6e6e02c2bd683b674bb7 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Sat, 14 May 2016 15:56:40 -0400 Subject: [PATCH] Fix many more style issues. --- .eslintrc.js | 86 +++++++++++++++++++---------- src/actions/index.js | 3 +- src/async-storage.js | 24 ++++----- src/components/Histogram.js | 11 ++-- src/components/ProfileTreeView.js | 5 +- src/components/ProfileViewer.js | 3 +- src/components/TreeView.js | 3 +- src/components/VirtualList.js | 5 +- src/containers/App.js | 6 +-- src/function-info.js | 64 ++++++++++++---------- src/preprocess-profile.js | 8 +-- src/profile-data.js | 18 ++++--- src/promise-worker.js | 11 ++-- src/reducers/index.js | 8 +-- src/symbol-store-db.js | 44 +++++++-------- src/symbol-store.js | 6 +-- src/symbolication.js | 90 +++++++++++++++---------------- 17 files changed, 220 insertions(+), 175 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index c14ba10160..aa75ade709 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,35 +21,63 @@ module.exports = { 2, { "SwitchCase": 1 } ], - "linebreak-style": [ - "error", - "unix" - ], - "quotes": [ - "error", - "single" - ], - "semi": [ - "error", - "always" - ], - "no-extra-semi": [ - "error" - ], - "comma-dangle": [ - "error", - "always-multiline" - ], - "no-console": [ - "error", - { allow: ["log", "warn", "error"] } - ], - "eqeqeq": [ - "error" - ], - "valid-jsdoc": [ - "error" - ] + "linebreak-style": [ "error", "unix" ], + "quotes": [ "error", "single" ], + "semi": [ "error", "always" ], + "no-extra-semi": "error", + "comma-dangle": [ "error", "always-multiline" ], + "no-console": [ "error", { allow: ["log", "warn", "error"] } ], + "eqeqeq": "error", + "valid-jsdoc": "error", + "consistent-return": "error", + "curly": ["error", "all" ], + "dot-location": ["error", "property"], + "dot-notation": "error", + "no-alert": "error", + "no-caller": "error", + "no-else-return": "error", + "no-eval": "error", + "no-implied-eval": "error", + "no-extend-native": "error", + "no-native-reassign": "error", + "no-extra-bind": "error", + "no-labels": "error", + "no-implicit-globals": "error", + "no-invalid-this": "error", + "no-iterator": "error", + "no-lone-blocks": "error", + "no-loop-func": "error", + "no-multi-spaces": "error", + "no-param-reassign": "error", + "no-proto": "error", + "no-return-assign": "error", + "no-script-url": "error", + "no-self-compare": "error", + "no-throw-literal": "error", + "no-unmodified-loop-condition": "error", + "no-unused-expressions": "error", + "no-useless-concat": "error", + "no-useless-escape": "error", + "no-void": "error", + "no-with": "error", + "radix": "error", + "yoda": ["error", "never", { "exceptRange": true }], + "brace-style": ["error", "1tbs", { "allowSingleLine": true }], + "camelcase": "error", + "comma-spacing": "error", + "comma-style": "error", + "jsx-quotes": ["error", "prefer-single"], + "key-spacing": "error", + "keyword-spacing": "error", + "no-new-object": "error", + "no-spaced-func": "error", + "semi-spacing": "error", + "space-in-parens": ["error", "never"], + "spaced-comment": "error", + "generator-star-spacing": "error", + "no-duplicate-imports": "error", + "no-var": "error", + "prefer-const": "error" }, "settings": { "react": { diff --git a/src/actions/index.js b/src/actions/index.js index 867614b602..f2d6e0bfd0 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -72,7 +72,8 @@ class ColascedFunctionsUpdateDispatcher { }; } else { const oldMap = this._updates[threadIndex].oldFuncToNewFuncMap; - this._updates[threadIndex].oldFuncToNewFuncMap = new Map(function*() { yield* oldMap; yield* oldFuncToNewFuncMap;}()); + this._updates[threadIndex].oldFuncToNewFuncMap = + new Map(function *() { yield* oldMap; yield* oldFuncToNewFuncMap;}()); } } diff --git a/src/async-storage.js b/src/async-storage.js index 16cae66f84..d2315c8ba7 100644 --- a/src/async-storage.js +++ b/src/async-storage.js @@ -41,17 +41,17 @@ */ export function getStore(dbName) { - let DBVERSION = 1; - let STORENAME = 'keyvaluestore'; + const DBVERSION = 1; + const STORENAME = 'keyvaluestore'; let db = null; function withStore(type, onsuccess, onerror) { if (db) { - let transaction = db.transaction(STORENAME, type); - let store = transaction.objectStore(STORENAME); + const transaction = db.transaction(STORENAME, type); + const store = transaction.objectStore(STORENAME); onsuccess(store); } else { - let openreq = indexedDB.open(dbName, DBVERSION); + const openreq = indexedDB.open(dbName, DBVERSION); openreq.onerror = function withStoreOnError() { onerror(); }; @@ -61,8 +61,8 @@ export function getStore(dbName) { }; openreq.onsuccess = function withStoreOnSuccess() { db = openreq.result; - let transaction = db.transaction(STORENAME, type); - let store = transaction.objectStore(STORENAME); + const transaction = db.transaction(STORENAME, type); + const store = transaction.objectStore(STORENAME); onsuccess(store); }; } @@ -91,7 +91,7 @@ export function getStore(dbName) { return new Promise((resolve, reject) => { withStore('readwrite', (store) => { store.transaction.oncomplete = resolve; - let req = store.put(value, key); + const req = store.put(value, key); req.onerror = function setItemOnError() { reject('Error in asyncStorage.setItem(): ', req.error.name); }; @@ -103,7 +103,7 @@ export function getStore(dbName) { return new Promise((resolve, reject) => { withStore('readwrite', (store) => { store.transaction.oncomplete = resolve; - let req = store.delete(key); + const req = store.delete(key); req.onerror = function removeItemOnError() { reject('Error in asyncStorage.removeItem(): ', req.error.name); }; @@ -115,7 +115,7 @@ export function getStore(dbName) { return new Promise((resolve, reject) => { withStore('readwrite', (store) => { store.transaction.oncomplete = resolve; - let req = store.clear(); + const req = store.clear(); req.onerror = function clearOnError() { reject('Error in asyncStorage.clear(): ', req.error.name); }; @@ -148,13 +148,13 @@ export function getStore(dbName) { let req; withStore('readonly', (store) => { store.transaction.oncomplete = function onComplete() { - let cursor = req.result; + const cursor = req.result; resolve(cursor ? cursor.key : null); }; let advanced = false; req = store.openCursor(); req.onsuccess = function keyOnSuccess() { - let cursor = req.result; + const cursor = req.result; if (!cursor) { // this means there weren"t enough keys return; diff --git a/src/components/Histogram.js b/src/components/Histogram.js index 167afd9600..4abc22b13d 100644 --- a/src/components/Histogram.js +++ b/src/components/Histogram.js @@ -63,18 +63,19 @@ class Histogram extends Component { if (selectedFuncStack !== -1 && selectedFuncStack !== null) { selectedFuncStackDepth = funcStackTable.depth[selectedFuncStack]; } - function hasSelectedFuncStackPrefix(funcStack) { - let depth = funcStackTable.depth[funcStack]; - while (depth > selectedFuncStackDepth) { + function hasSelectedFuncStackPrefix(funcStackPrefix) { + let funcStack = funcStackPrefix; + for (let depth = funcStackTable.depth[funcStack]; + depth > selectedFuncStackDepth; depth--) { funcStack = funcStackTable.prefix[funcStack]; - depth--; } return funcStack === selectedFuncStack; } for (let i = 0; i < sampleFuncStacks.length; i++) { const sampleTime = thread.samples.time[i]; - if (sampleTime + intervalMs < range[0] || sampleTime > range[1]) + if (sampleTime + intervalMs < range[0] || sampleTime > range[1]) { continue; + } const funcStack = sampleFuncStacks[i]; const isHighlighted = hasSelectedFuncStackPrefix(funcStack); const sampleHeight = funcStackTable.depth[funcStack] * yPixelsPerDepth; diff --git a/src/components/ProfileTreeView.js b/src/components/ProfileTreeView.js index 00f96f701c..29c1eb1630 100644 --- a/src/components/ProfileTreeView.js +++ b/src/components/ProfileTreeView.js @@ -10,7 +10,7 @@ class ProfileTreeView extends Component{ { propName: 'totalTimePercent', title: '' }, { propName: 'selfTime', title: 'Self' }, ]; - this._mainColumn = { propName:'name', title: '' }; + this._mainColumn = { propName: 'name', title: '' }; } componentWillMount() { @@ -38,8 +38,9 @@ class ProfileTreeView extends Component{ newExpandedFuncStacks.push(currentFuncStack); for (let i = 0; i < maxInterestingDepth; i++) { const children = this._tree.getChildren(currentFuncStack); - if (children.length === 0) + if (children.length === 0) { break; + } currentFuncStack = children[0]; newExpandedFuncStacks.push(currentFuncStack); } diff --git a/src/components/ProfileViewer.js b/src/components/ProfileViewer.js index 91fd8bf512..87dac7aa52 100644 --- a/src/components/ProfileViewer.js +++ b/src/components/ProfileViewer.js @@ -1,8 +1,7 @@ import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; import shallowequal from 'shallowequal'; -import { getTimeRangeIncludingAllThreads } from '../profile-data'; -import { getFuncStackInfo, filterThreadToJSOnly, getFuncStackFromFuncArray, getStackAsFuncArray, invertCallstack } from '../profile-data'; +import { getFuncStackInfo, getTimeRangeIncludingAllThreads, filterThreadToJSOnly, getFuncStackFromFuncArray, getStackAsFuncArray, invertCallstack } from '../profile-data'; import ProfileTreeView from '../components/ProfileTreeView'; import ProfileThreadHeaderBar from '../components/ProfileThreadHeaderBar'; import ProfileViewSidebar from '../components/ProfileViewSidebar'; diff --git a/src/components/TreeView.js b/src/components/TreeView.js index 7a7f65064d..4213f487af 100644 --- a/src/components/TreeView.js +++ b/src/components/TreeView.js @@ -204,8 +204,9 @@ class TreeView extends Component { } _onKeyDown(event) { - if (event.ctrlKey || event.altKey || event.metaKey) + if (event.ctrlKey || event.altKey || event.metaKey) { return; + } if (event.keyCode < 37 || event.keyCode > 40) { if (event.keyCode !== 0 || diff --git a/src/components/VirtualList.js b/src/components/VirtualList.js index c5901da8c9..019765a7ea 100644 --- a/src/components/VirtualList.js +++ b/src/components/VirtualList.js @@ -96,8 +96,9 @@ class VirtualList extends Component { style={{height: Math.max(0, visibleRangeStart) * itemHeight + 'px'}} /> { items.map((item, i) => { - if (i < visibleRangeStart || i >= visibleRangeEnd) - return; + if (i < visibleRangeStart || i >= visibleRangeEnd) { + return null; + } return ; }) } diff --git a/src/containers/App.js b/src/containers/App.js index bee4390581..aab9058bc8 100644 --- a/src/containers/App.js +++ b/src/containers/App.js @@ -17,13 +17,13 @@ class App extends Component { dispatch(Actions.waitingForProfileFromAddon()); window.geckoProfilerPromise.then((geckoProfiler) => { - geckoProfiler.getProfile().then(profile => { - profile = preprocessProfile(profile); + geckoProfiler.getProfile().then(rawProfile => { + const profile = preprocessProfile(rawProfile); dispatch(Actions.receiveProfileFromAddon(profile)); const symbolStore = new SymbolStore('cleopatra-async-storage', { requestSymbolTable: (pdbName, breakpadId) => { - let requestedLib = { pdbName, breakpadId }; + const requestedLib = { pdbName, breakpadId }; dispatch(Actions.requestingSymbolTable(requestedLib)); return geckoProfiler.getSymbolTable(pdbName, breakpadId).then(symbolTable => { dispatch(Actions.receivedSymbolTableReply(requestedLib)); diff --git a/src/function-info.js b/src/function-info.js index 1de1d5d74f..a57582e88b 100644 --- a/src/function-info.js +++ b/src/function-info.js @@ -1,13 +1,14 @@ // Imported from cleopatra, needs to be double-checked. -let resources = {}; -let meta = { addons: [] }; +const resources = {}; +const meta = { addons: [] }; // If the function name starts with "non-virtual thunk to ", remove that part. function cleanFunctionName(functionName) { - var ignoredPrefix = 'non-virtual thunk to '; - if (functionName.startsWith(ignoredPrefix)) + const ignoredPrefix = 'non-virtual thunk to '; + if (functionName.startsWith(ignoredPrefix)) { return functionName.substr(ignoredPrefix.length); + } return functionName; } @@ -38,33 +39,37 @@ function resourceNameFromLibrary(library) { } function getAddonForScriptURI(url, host) { - if (!meta || !meta.addons) + if (!meta || !meta.addons) { return null; + } if (url.startsWith('resource:') && host.endsWith('-at-jetpack')) { // Assume this is a jetpack url - var jetpackID = host.substring(0, host.length - 11) + '@jetpack'; + const jetpackID = host.substring(0, host.length - 11) + '@jetpack'; return addonWithID(jetpackID); } if (url.startsWith('file:///') && url.indexOf('/extensions/') !== -1) { - var unpackedAddonNameMatch = /\/extensions\/(.*?)\//.exec(url); - if (unpackedAddonNameMatch) + const unpackedAddonNameMatch = /\/extensions\/(.*?)\//.exec(url); + if (unpackedAddonNameMatch) { return addonWithID(decodeURIComponent(unpackedAddonNameMatch[1])); + } return null; } if (url.startsWith('jar:file:///') && url.indexOf('/extensions/') !== -1) { - var packedAddonNameMatch = /\/extensions\/(.*?).xpi/.exec(url); - if (packedAddonNameMatch) + const packedAddonNameMatch = /\/extensions\/(.*?).xpi/.exec(url); + if (packedAddonNameMatch) { return addonWithID(decodeURIComponent(packedAddonNameMatch[1])); + } return null; } if (url.startsWith('chrome://')) { - var chromeURIMatch = /chrome\:\/\/(.*?)\//.exec(url); - if (chromeURIMatch) + const chromeURIMatch = /chrome:\/\/(.*?)\//.exec(url); + if (chromeURIMatch) { return findAddonForChromeURIHost(chromeURIMatch[1]); + } return null; } @@ -72,21 +77,20 @@ function getAddonForScriptURI(url, host) { } function resourceNameFromURI(url) { - if (!url) + if (!url) { return ensureResource('unknown', {type: 'unknown', name: ''}); + } - var match = /^(.*):\/\/(.*?)\//.exec(url); + const match = /^(.*):\/\/(.*?)\//.exec(url); if (!match) { // Can this happen? If so, we should change the regular expression above. return ensureResource('url_' + url, {type: 'url', name: url}); } - var urlRoot = match[0]; - var protocol = match[1]; - var host = match[2]; + const [urlRoot, protocol, host] = match; - var addon = getAddonForScriptURI(url, host); + const addon = getAddonForScriptURI(url, host); if (addon) { return ensureResource('addon_' + addon.id, { type: 'addon', @@ -115,7 +119,7 @@ function resourceNameFromURI(url) { // foo/ -> foo/ // foo -> foo function getFilename(url) { - var lastSlashPos = url.lastIndexOf('/', url.length - 2); + const lastSlashPos = url.lastIndexOf('/', url.length - 2); return url.substr(lastSlashPos + 1); } @@ -123,7 +127,7 @@ function getFilename(url) { // with " -> ". We only want the last URI in this list. function getRealScriptURI(url) { if (url) { - var urls = url.split(' -> '); + const urls = url.split(' -> '); return urls[urls.length - 1]; } return url; @@ -145,13 +149,14 @@ function getRealScriptURI(url) { export function getFunctionInfo(fullName) { function getCPPFunctionInfo(fullName) { - var match = + const match = /^(.*) \(in ([^\)]*)\) (\+ [0-9]+)$/.exec(fullName) || /^(.*) \(in ([^\)]*)\) (\(.*:.*\))$/.exec(fullName) || /^(.*) \(in ([^\)]*)\)$/.exec(fullName); - if (!match) + if (!match) { return null; + } return { functionName: cleanFunctionName(match[1]), @@ -163,18 +168,19 @@ export function getFunctionInfo(fullName) { } function getJSFunctionInfo(fullName) { - var jsMatch = + const jsMatch = /^(.*) \((.*):([0-9]+)\)$/.exec(fullName) || /^()(.*):([0-9]+)$/.exec(fullName); - if (!jsMatch) + if (!jsMatch) { return null; + } - var functionName = jsMatch[1] || ''; - var scriptURI = getRealScriptURI(jsMatch[2]); - var lineNumber = jsMatch[3]; - var scriptFile = getFilename(scriptURI); - var resourceName = resourceNameFromURI(scriptURI); + const functionName = jsMatch[1] || ''; + const scriptURI = getRealScriptURI(jsMatch[2]); + const lineNumber = jsMatch[3]; + const scriptFile = getFilename(scriptURI); + const resourceName = resourceNameFromURI(scriptURI); return { functionName: functionName + '() @ ' + scriptFile + ':' + lineNumber, diff --git a/src/preprocess-profile.js b/src/preprocess-profile.js index cd0a4365a0..a71d607907 100644 --- a/src/preprocess-profile.js +++ b/src/preprocess-profile.js @@ -19,7 +19,7 @@ import { provideHostSide } from './promise-worker'; */ function toStructOfArrays(rawTable) { const result = { length: rawTable.data.length }; - for (let fieldName in rawTable.schema) { + for (const fieldName in rawTable.schema) { const fieldIndex = rawTable.schema[fieldName]; result[fieldName] = rawTable.data.map(entry => (fieldIndex in entry) ? entry[fieldIndex] : null); } @@ -30,7 +30,7 @@ function toStructOfArrays(rawTable) { // with " -> ". We only want the last URI in this list. function getRealScriptURI(url) { if (url) { - var urls = url.split(' -> '); + const urls = url.split(' -> '); return urls[urls.length - 1]; } return url; @@ -183,12 +183,12 @@ function adjustTimestamps(samplesOrMarkers, delta) { export function preprocessProfile(profile) { const libs = preprocessSharedLibraries(profile.libs); const threads = []; - for (let threadOrSubprocess of profile.threads) { + for (const threadOrSubprocess of profile.threads) { if (typeof threadOrSubprocess === 'string') { const subprocessProfile = JSON.parse(threadOrSubprocess); const subprocessLibs = preprocessSharedLibraries(subprocessProfile.libs); const adjustTimestampsBy = subprocessProfile.meta.startTime - profile.meta.startTime; - for (let thread of subprocessProfile.threads) { + for (const thread of subprocessProfile.threads) { const newThread = preprocessThread(thread, subprocessLibs); newThread.samples = adjustTimestamps(newThread.samples, adjustTimestampsBy); newThread.markers = adjustTimestamps(newThread.markers, adjustTimestampsBy); diff --git a/src/profile-data.js b/src/profile-data.js index bf2bc4de28..b3223981ff 100644 --- a/src/profile-data.js +++ b/src/profile-data.js @@ -16,14 +16,18 @@ export const resourceTypes = { /** * Takes the stack table and the frame table, creates a func stack table and * fixes up the funcStack field in the samples data. - * @return object The funcStackTable and the new samples object. + * @param {object} stackTable The thread's stackTable. + * @param {object} frameTable The thread's frameTable. + * @param {object} funcTable The thread's funcTable. + * @param {object} samples The thread's samples. + * @return {object} The funcStackTable and the new samples object. */ export function getFuncStackInfo(stackTable, frameTable, funcTable, samples) { return timeCode('getFuncStackInfo', () => { - let stackIndexToFuncStackIndex = new Map(); + const stackIndexToFuncStackIndex = new Map(); const funcCount = funcTable.length; - let prefixFuncStackAndFuncToFuncStackMap = new Map(); // prefixFuncStack * funcCount + func => funcStack - let funcStackTable = { length: 0, prefix: [], func: [], depth: [] }; + const prefixFuncStackAndFuncToFuncStackMap = new Map(); // prefixFuncStack * funcCount + func => funcStack + const funcStackTable = { length: 0, prefix: [], func: [], depth: [] }; function addFuncStack(prefix, func) { const index = funcStackTable.length++; funcStackTable.prefix[index] = prefix; @@ -76,7 +80,7 @@ export function getTimeRangeIncludingAllThreads(profile) { export function defaultThreadOrder(threads) { // Put the compositor thread last. - let threadOrder = threads.map((thread, i) => i); + const threadOrder = threads.map((thread, i) => i); threadOrder.sort((a, b) => { const nameA = threads[a].name; const nameB = threads[b].name; @@ -122,7 +126,7 @@ export function filterThreadToJSOnly(thread) { const oldStackToNewStack = new Map(); const funcCount = funcTable.length; - let prefixStackAndFuncToStack = new Map(); // prefixNewStack * funcCount + func => newStackIndex + const prefixStackAndFuncToStack = new Map(); // prefixNewStack * funcCount + func => newStackIndex function convertStack(stackIndex) { if (stackIndex === null) { @@ -208,7 +212,7 @@ export function invertCallstack(thread) { prefix: [], }; const frameCount = frameTable.length; - let prefixAndFrameToStack = new Map(); // prefix * frameCount + frame => stackIndex + const prefixAndFrameToStack = new Map(); // prefix * frameCount + frame => stackIndex function stackFor(prefix, frame) { const prefixAndFrameIndex = (prefix === null ? -1 : prefix) * frameCount + frame; let stackIndex = prefixAndFrameToStack.get(prefixAndFrameIndex); diff --git a/src/promise-worker.js b/src/promise-worker.js index 7a24d3cd4c..309cc14f17 100644 --- a/src/promise-worker.js +++ b/src/promise-worker.js @@ -17,15 +17,18 @@ export function provideHostSide(workerFilename, methods) { } }; - for (let method of methods) { - this[method] = (function () { - const paramArray = Array.from(arguments); + function makeMethod(method) { + return function (...paramArray) { const msgID = nextMessageID++; worker.postMessage({ msgID, type: 'method', method, paramArray }); return new Promise((resolve, reject) => { callbacks.set(msgID, { resolve, reject }); }); - }).bind(this); + }; + } + + for (const method of methods) { + this[method] = makeMethod(method); } worker.postMessage({ type: 'constructor', constructorArguments }); diff --git a/src/reducers/index.js b/src/reducers/index.js index 6828ea4363..2f6981f993 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -147,12 +147,12 @@ function profile(state = {}, action) { case 'COALESCED_FUNCTIONS_UPDATE': { const { functionsUpdatePerThread } = action; const threads = state.threads.map((thread, threadIndex) => { - if (!functionsUpdatePerThread[threadIndex]) + if (!functionsUpdatePerThread[threadIndex]) { return thread; + } const { oldFuncToNewFuncMap, funcIndices, funcNames } = functionsUpdatePerThread[threadIndex]; - thread = applyFunctionMerging(thread, oldFuncToNewFuncMap); - thread = setFuncNames(thread, funcIndices, funcNames); - return thread; + return setFuncNames(applyFunctionMerging(thread, oldFuncToNewFuncMap), + funcIndices, funcNames); }); return Object.assign({}, state, { threads }); } diff --git a/src/symbol-store-db.js b/src/symbol-store-db.js index b5dfaf1583..fbfc6c8e90 100644 --- a/src/symbol-store-db.js +++ b/src/symbol-store-db.js @@ -7,7 +7,7 @@ import { provideHostSide } from './promise-worker'; */ export class SymbolStoreDB { /** - * @param string dbName The name of the indexedDB database that's used + * @param {string} dbName The name of the indexedDB database that's used * to store the symbol tables. */ constructor(dbName) { @@ -17,13 +17,13 @@ export class SymbolStoreDB { _setupDB(dbName) { return new Promise((resolve, reject) => { - let openreq = indexedDB.open(dbName, 1); + const openreq = indexedDB.open(dbName, 1); openreq.onerror = reject; openreq.onupgradeneeded = () => { - let db = openreq.result; + const db = openreq.result; db.onerror = reject; - let tableStore = db.createObjectStore('symbol-tables', { autoIncrement: true }); - tableStore.createIndex('libKey', ['pdbName', 'breakpadId'], { unique: true }); + const tableStore = db.createObjectStore('symbol-tables', { autoIncrement: true }); + tableStore.createIndex('libKey', ['pdbName', 'breakpadId'], { unique: true }); }; openreq.onsuccess = () => { this._db = openreq.result; @@ -38,13 +38,13 @@ export class SymbolStoreDB { } return new Promise((resolve, reject) => { - let transaction = this._db.transaction('symbol-tables', 'readonly'); - let store = transaction.objectStore('symbol-tables'); - let index = store.index('libKey'); - let req = index.openKeyCursor(IDBKeyRange.only([pdbName, breakpadId])); + const transaction = this._db.transaction('symbol-tables', 'readonly'); + const store = transaction.objectStore('symbol-tables'); + const index = store.index('libKey'); + const req = index.openKeyCursor(IDBKeyRange.only([pdbName, breakpadId])); req.onerror = reject; req.onsuccess = () => { - let cursor = req.result; + const cursor = req.result; if (cursor) { resolve(cursor.primaryKey); } else { @@ -60,10 +60,10 @@ export class SymbolStoreDB { } return new Promise((resolve, reject) => { - let transaction = this._db.transaction('symbol-tables', 'readwrite'); + const transaction = this._db.transaction('symbol-tables', 'readwrite'); transaction.onerror = reject; - let tableStore = transaction.objectStore('symbol-tables'); - let putReq = tableStore.put({ pdbName, breakpadId, addrs, index, buffer }); + const tableStore = transaction.objectStore('symbol-tables'); + const putReq = tableStore.put({ pdbName, breakpadId, addrs, index, buffer }); putReq.onsuccess = () => { resolve(putReq.result); }; @@ -76,9 +76,9 @@ export class SymbolStoreDB { } return new Promise((resolve, reject) => { - let transaction = this._db.transaction('symbol-tables', 'readonly'); - let store = transaction.objectStore('symbol-tables'); - let req = store.get(libKey); + const transaction = this._db.transaction('symbol-tables', 'readonly'); + const store = transaction.objectStore('symbol-tables'); + const req = store.get(libKey); req.onerror = reject; req.onsuccess = () => { if (req.result) { @@ -94,9 +94,9 @@ export class SymbolStoreDB { /** * Returns a promise of an array with symbol names, matching the order of * the requested addresses. - * @param {array of integers} requestedAddresses The addresses to look up symbols for, *sorted from lowest to highest*. - * @param {integer} libKey The primary key for the library, as returned by getLibKey - * @return {array of strings} The symbols, one for each address in requestedAddresses. + * @param {Array} requestedAddressesIndices The indices of each symbol that should be looked up. + * @param {Number} libKey The primary key for the library, as returned by getLibKey + * @return {Array} The symbols, one for each address in requestedAddresses. */ getSymbolsForAddressesInLib(requestedAddressesIndices, libKey) { if (!this._db) { @@ -104,9 +104,9 @@ export class SymbolStoreDB { } return new Promise((resolve, reject) => { - let transaction = this._db.transaction('symbol-tables', 'readonly'); - let store = transaction.objectStore('symbol-tables'); - let req = store.get(libKey); + const transaction = this._db.transaction('symbol-tables', 'readonly'); + const store = transaction.objectStore('symbol-tables'); + const req = store.get(libKey); req.onerror = reject; req.onsuccess = () => { if (!req.result) { diff --git a/src/symbol-store.js b/src/symbol-store.js index 0485de6a21..af0023c7c4 100644 --- a/src/symbol-store.js +++ b/src/symbol-store.js @@ -30,7 +30,7 @@ export class SymbolStore { _ensureLibraryIsInDB(lib) { const { pdbName, breakpadId } = lib; - let libid = `${pdbName}/${breakpadId}`; + const libid = `${pdbName}/${breakpadId}`; if (this._failedRequests.has(libid)) { return Promise.reject(new Error('We\'ve tried to request a symbol table for this library before and failed, so we\'re not trying again.')); } @@ -43,8 +43,8 @@ export class SymbolStore { } // Request the symbol table from the symbol provider. - let symbolTablePromise = this._symbolProvider.requestSymbolTable(lib.pdbName, lib.breakpadId); - let importPromise = symbolTablePromise.then(symbolTable => { + const symbolTablePromise = this._symbolProvider.requestSymbolTable(lib.pdbName, lib.breakpadId); + const importPromise = symbolTablePromise.then(symbolTable => { this._importingLibs.delete(libid); return this._db.importLibrary(pdbName, breakpadId, symbolTable); }, error => { diff --git a/src/symbolication.js b/src/symbolication.js index a7ab3fd30b..d0ba333b85 100644 --- a/src/symbolication.js +++ b/src/symbolication.js @@ -3,9 +3,9 @@ import { resourceTypes } from './profile-data'; /** * Return the library object that contains address. - * @param array of {start,end,...} libs The array of librarys - * @param address The address to find - * @return {start,end,...} lib object The lib object that contains address, rv.start <= address < rv.end, or null if no such lib object exists. + * @param {Array} libs The array of libraries, each with a start and end property. + * @param {Number} address The address to find + * @return {Object} lib object The lib object that contains address, rv.start <= address < rv.end, or null if no such lib object exists. */ export function getContainingLibrary(libs, address) { if (isNaN(address)) { @@ -15,26 +15,27 @@ export function getContainingLibrary(libs, address) { let left = 0; let right = libs.length - 1; while (left <= right) { - let mid = ((left + right) / 2)|0; - if (address >= libs[mid].end) + const mid = ((left + right) / 2)|0; + if (address >= libs[mid].end) { left = mid + 1; - else if (address < libs[mid].start) + } else if (address < libs[mid].start) { right = mid - 1; - else + } else { return libs[mid]; + } } return null; } /** * Find the functions in this thread's funcTable that we need symbols for. - * @param object thread The thread, in "preprocessed profile" format. - * @return Map A map containing the funcIndices of the functions that - * need to be symbolicated. Each entry's key is a lib - * object from the thread's libs array, and the value is - * an array of funcIndex. - * Example: - * map.get(lib): [0, 1, 2, 8, 34] + * @param {Object} thread The thread, in "preprocessed profile" format. + * @return {Map} A map containing the funcIndices of the functions that + * need to be symbolicated. Each entry's key is a lib + * object from the thread's libs array, and the value is + * an array of funcIndex. + * Example: + * map.get(lib): [0, 1, 2, 8, 34] */ function gatherFuncsInThread(thread) { const { libs, funcTable, stringTable, resourceTable } = thread; @@ -84,16 +85,16 @@ function gatherFuncsInThread(thread) { * return value - the return value is a map whose keys are the true func * addresses that we need symbols for. The value of each map entry is the * funcIndex for the func that has become the "one true func" for this function. - * @param array funcAddressTable An array containing the address of every function of a library, in ascending order. - * @param array funcsToSymbolicate An array containing funcIndex elements for the funcs in this library. - * @param object funcTable The funcTable that the funcIndices in addressToSymbolicate refer to. - * @param Map oldFuncToNewFuncMap An out parameter that specifies how funcs should be merged. - * @return object A map that maps a func address index to a funcIndex, one entry for each func that needs to be symbolicated. + * @param {Array} funcAddressTable An array containing the address of every function of a library, in ascending order. + * @param {Array} funcsToSymbolicate An array containing funcIndex elements for the funcs in this library. + * @param {Object} funcTable The funcTable that the funcIndices in addressToSymbolicate refer to. + * @param {Map} oldFuncToNewFuncMap An out parameter that specifies how funcs should be merged. + * @return {Object} A map that maps a func address index to a funcIndex, one entry for each func that needs to be symbolicated. */ function findFunctionsToMergeAndSymbolicationAddresses(funcAddressTable, funcsToSymbolicate, funcTable) { const oldFuncToNewFuncMap = new Map(); - let funcAddrIndices = []; - let funcIndices = []; + const funcAddrIndices = []; + const funcIndices = []; // Sort funcsToSymbolicate by address. funcsToSymbolicate.sort((i1, i2) => { @@ -109,7 +110,7 @@ function findFunctionsToMergeAndSymbolicationAddresses(funcAddressTable, funcsTo let lastFuncIndex = -1; let nextFuncAddress = 0; let nextFuncAddressIndex = 0; - for (let funcIndex of funcsToSymbolicate) { + for (const funcIndex of funcsToSymbolicate) { const funcAddress = funcTable.address[funcIndex]; if (funcAddress < nextFuncAddress) { // The address of the func at funcIndex is still inside the @@ -122,7 +123,7 @@ function findFunctionsToMergeAndSymbolicationAddresses(funcAddressTable, funcsTo // Now funcAddress >= nextFuncAddress. // Find the index in funcAddressTable of the function that funcAddress is // inside of. - let funcAddressIndex = bisection.right(funcAddressTable, funcAddress, nextFuncAddressIndex) - 1; + const funcAddressIndex = bisection.right(funcAddressTable, funcAddress, nextFuncAddressIndex) - 1; if (funcAddressIndex >= 0) { // TODO: Take realFuncAddress and put it into the func table. // const realFuncAddress = funcAddressTable[funcAddressIndex]; @@ -140,11 +141,11 @@ function findFunctionsToMergeAndSymbolicationAddresses(funcAddressTable, funcsTo * Modify the symbolicated funcs to point to the new func name strings. * This function adds the func names to the thread's string table and * adjusts the funcTable to point to those strings. - * @param thread The thread whose funcTable needs adjusting. - * @param funcAddrs An array of addresses of the functions that we got symbols for. - * @param funcNames An array of strings containing the corresponding symbols. - * @param addrToFuncIndexMap A Map that maps a func address to the funcIndex. - * @return The new thread object. + * @param {Object} thread The thread whose funcTable needs adjusting. + * @param {Object} funcIndices An array of indices of the functions that we got symbols for. + * @param {Object} funcNames An array of strings containing the corresponding symbols. + * @param {Map} addrToFuncIndexMap A Map that maps a func address to the funcIndex. + * @return {Object} The new thread object. */ export function setFuncNames(thread, funcIndices, funcNames) { const funcTable = Object.assign({}, thread.funcTable); @@ -167,9 +168,9 @@ export function setFuncNames(thread, funcIndices, funcNames) { * known, by creating one function per frame address. Once the function table * is known, different addresses that are inside the same function need to be * merged into that same function. - * @param object thread The thread that needs to be augmented. Treated as immutable. - * @param object oldFuncToNewFuncMap A map that defines which function should be collapsed into which other function. - * @return object The new thread object. + * @param {Object} thread The thread that needs to be augmented. Treated as immutable. + * @param {Map} oldFuncToNewFuncMap A map that defines which function should be collapsed into which other function. + * @return {Object} The new thread object. */ export function applyFunctionMerging(thread, oldFuncToNewFuncMap) { const frameTable = Object.assign({}, thread.frameTable, { @@ -182,17 +183,17 @@ export function applyFunctionMerging(thread, oldFuncToNewFuncMap) { } /** - * Symbolicate the given thread. Calls cbo.onUpdateThread after each bit of + * Symbolicate the given thread. Calls cbo.onMergeFunctions and cb.onGotFuncNames after each bit of * symbolication, and resolves the returned promise once completely done. - * @param object thread The thread to symbolicate, in the "preprocessed profile" format. - * @param object symbolStore A SymbolStore object that can be used for getting the required symbol tables. - * @param object cbo An object containing a callback function 'onUpdateThread' which is called with - * a new updated thread every time we've done a bit of symbolication. - * @return Promise A promise that resolves (with nothing) once symbolication of the thread has completed. + * @param {Object} thread The thread to symbolicate, in the "preprocessed profile" format. + * @param {Number} threadIndex The index of the thread. This is needed because it gets supplied in the callbacks. + * @param {Object} symbolStore A SymbolStore object that can be used for getting the required symbol tables. + * @param {Object} cbo An object containing callback functions 'onMergeFunctions' and 'onGotFuncNames'. + * @return {Promise} A promise that resolves (with nothing) once symbolication of the thread has completed. */ function symbolicateThread(thread, threadIndex, symbolStore, cbo) { - let foundFuncs = gatherFuncsInThread(thread); - return Promise.all(Array.from(foundFuncs).map(function ([lib, funcsToSymbolicate]) { + const foundFuncMap = gatherFuncsInThread(thread); + return Promise.all(Array.from(foundFuncMap).map(function ([lib, funcsToSymbolicate]) { // lib is a lib object from thread.libs. // funcsToSymbolicate is an array of funcIndex. return symbolStore.getFuncAddressTableForLib(lib).then(funcAddressTable => { @@ -200,7 +201,7 @@ function symbolicateThread(thread, threadIndex, symbolStore, cbo) { // that are actually the same function. // We don't have any symbols yet. We'll request those after we've merged // the functions. - const { funcAddrIndices, funcIndices, oldFuncToNewFuncMap } = + const { funcAddrIndices, funcIndices, oldFuncToNewFuncMap } = findFunctionsToMergeAndSymbolicationAddresses(funcAddressTable, funcsToSymbolicate, thread.funcTable); cbo.onMergeFunctions(threadIndex, oldFuncToNewFuncMap); @@ -218,11 +219,10 @@ function symbolicateThread(thread, threadIndex, symbolStore, cbo) { /** * Symbolicate a profile. - * @param object profile The profile to symbolicate, in preprocessed format. - * @param object symbolStore A SymbolStore object with a getFuncAddressTableForLib and getSymbolsForAddressesInLib methods. - * @param object cbo An object containing a callback function 'onUpdateProfile', which is called - * with a new updated profile whenever we've done a bit of symbolication. - * @return Promise A promise that resolves (with nothing) once symbolication has completed. + * @param {Object} profile The profile to symbolicate, in preprocessed format. + * @param {Object} symbolStore A SymbolStore object with a getFuncAddressTableForLib and getSymbolsForAddressesInLib methods. + * @param {Object} cbo An object containing callback functions 'onMergeFunctions' and 'onGotFuncNames'. + * @return {Promise} A promise that resolves (with nothing) once symbolication has completed. */ export function symbolicateProfile(profile, symbolStore, cbo) { return Promise.all(profile.threads.map((thread, threadIndex) => {